Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
led_control.c
Go to the documentation of this file.
1 #include "headers.h"
2 
3 #define STATUS_IMAGE_CHECKSUM_MISMATCH -199
4 #define EVENT_SIGNALED 1
5 
6 static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
7 {
8  B_UINT16 u16CheckSum = 0;
9  while (u32Size--) {
10  u16CheckSum += (B_UINT8)~(*pu8Buffer);
11  pu8Buffer++;
12  }
13  return u16CheckSum;
14 }
15 
17 {
18  INT Status;
19  Status = (Adapter->gpioBitMap & gpios) ^ gpios;
20  if (Status)
21  return FALSE;
22  else
23  return TRUE;
24 }
25 
26 static INT LED_Blink(struct bcm_mini_adapter *Adapter, UINT GPIO_Num, UCHAR uiLedIndex,
27  ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
28 {
29  int Status = STATUS_SUCCESS;
30  BOOLEAN bInfinite = FALSE;
31 
32  /* Check if num_of_time is -ve. If yes, blink led in infinite loop */
33  if (num_of_time < 0) {
34  bInfinite = TRUE;
35  num_of_time = 1;
36  }
37  while (num_of_time) {
38  if (currdriverstate == Adapter->DriverState)
39  TURN_ON_LED(GPIO_Num, uiLedIndex);
40 
41  /* Wait for timeout after setting on the LED */
43  Adapter->LEDInfo.notify_led_event,
44  currdriverstate != Adapter->DriverState ||
46  msecs_to_jiffies(timeout));
47 
48  if (kthread_should_stop()) {
51  "Led thread got signal to exit..hence exiting");
52  Adapter->LEDInfo.led_thread_running =
54  TURN_OFF_LED(GPIO_Num, uiLedIndex);
55  Status = EVENT_SIGNALED;
56  break;
57  }
58  if (Status) {
59  TURN_OFF_LED(GPIO_Num, uiLedIndex);
60  Status = EVENT_SIGNALED;
61  break;
62  }
63 
64  TURN_OFF_LED(GPIO_Num, uiLedIndex);
66  Adapter->LEDInfo.notify_led_event,
67  currdriverstate != Adapter->DriverState ||
69  msecs_to_jiffies(timeout));
70  if (bInfinite == FALSE)
71  num_of_time--;
72  }
73  return Status;
74 }
75 
76 static INT ScaleRateofTransfer(ULONG rate)
77 {
78  if (rate <= 3)
79  return rate;
80  else if ((rate > 3) && (rate <= 100))
81  return 5;
82  else if ((rate > 100) && (rate <= 200))
83  return 6;
84  else if ((rate > 200) && (rate <= 300))
85  return 7;
86  else if ((rate > 300) && (rate <= 400))
87  return 8;
88  else if ((rate > 400) && (rate <= 500))
89  return 9;
90  else if ((rate > 500) && (rate <= 600))
91  return 10;
92  else
93  return MAX_NUM_OF_BLINKS;
94 }
95 
96 
97 
98 static INT LED_Proportional_Blink(struct bcm_mini_adapter *Adapter, UCHAR GPIO_Num_tx,
99  UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex,
100  LedEventInfo_t currdriverstate)
101 {
102  /* Initial values of TX and RX packets */
103  ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
104  /* values of TX and RX packets after 1 sec */
105  ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
106  /* Rate of transfer of Tx and Rx in 1 sec */
107  ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
108  int Status = STATUS_SUCCESS;
109  INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
110  UINT remDelay = 0;
111  BOOLEAN bBlinkBothLED = TRUE;
112  /* UINT GPIO_num = DISABLE_GPIO_NUM; */
113  ulong timeout = 0;
114 
115  /* Read initial value of packets sent/received */
116  Initial_num_of_packts_tx = Adapter->dev->stats.tx_packets;
117  Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets;
118 
119  /* Scale the rate of transfer to no of blinks. */
120  num_of_time_tx = ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
121  num_of_time_rx = ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
122 
123  while ((Adapter->device_removed == FALSE)) {
124  timeout = 50;
125  /*
126  * Blink Tx and Rx LED when both Tx and Rx is
127  * in normal bandwidth
128  */
129  if (bBlinkBothLED) {
130  /*
131  * Assign minimum number of blinks of
132  * either Tx or Rx.
133  */
134  if (num_of_time_tx > num_of_time_rx)
135  num_of_time = num_of_time_rx;
136  else
137  num_of_time = num_of_time_tx;
138  if (num_of_time > 0) {
139  /* Blink both Tx and Rx LEDs */
140  if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
141  uiTxLedIndex, timeout,
142  num_of_time, currdriverstate)
143  == EVENT_SIGNALED)
144  return EVENT_SIGNALED;
145 
146  if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
147  uiRxLedIndex, timeout,
148  num_of_time, currdriverstate)
149  == EVENT_SIGNALED)
150  return EVENT_SIGNALED;
151 
152  }
153 
154  if (num_of_time == num_of_time_tx) {
155  /* Blink pending rate of Rx */
156  if (LED_Blink(Adapter, (1 << GPIO_Num_rx),
157  uiRxLedIndex, timeout,
158  num_of_time_rx-num_of_time,
159  currdriverstate)
160  == EVENT_SIGNALED)
161  return EVENT_SIGNALED;
162 
163  num_of_time = num_of_time_rx;
164  } else {
165  /* Blink pending rate of Tx */
166  if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
167  uiTxLedIndex, timeout,
168  num_of_time_tx-num_of_time,
169  currdriverstate)
170  == EVENT_SIGNALED)
171  return EVENT_SIGNALED;
172 
173  num_of_time = num_of_time_tx;
174  }
175  } else {
176  if (num_of_time == num_of_time_tx) {
177  /* Blink pending rate of Rx */
178  if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
179  uiTxLedIndex, timeout,
180  num_of_time, currdriverstate)
181  == EVENT_SIGNALED)
182  return EVENT_SIGNALED;
183  } else {
184  /* Blink pending rate of Tx */
185  if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
186  uiRxLedIndex, timeout,
187  num_of_time, currdriverstate)
188  == EVENT_SIGNALED)
189  return EVENT_SIGNALED;
190  }
191  }
192 
193  /*
194  * If Tx/Rx rate is less than maximum blinks per second,
195  * wait till delay completes to 1 second
196  */
197  remDelay = MAX_NUM_OF_BLINKS - num_of_time;
198  if (remDelay > 0) {
199  timeout = 100 * remDelay;
201  Adapter->LEDInfo.notify_led_event,
202  currdriverstate != Adapter->DriverState
203  || kthread_should_stop(),
204  msecs_to_jiffies(timeout));
205 
206  if (kthread_should_stop()) {
209  "Led thread got signal to exit..hence exiting");
210  Adapter->LEDInfo.led_thread_running =
212  return EVENT_SIGNALED;
213  }
214  if (Status)
215  return EVENT_SIGNALED;
216  }
217 
218  /* Turn off both Tx and Rx LEDs before next second */
219  TURN_OFF_LED(1 << GPIO_Num_tx, uiTxLedIndex);
220  TURN_OFF_LED(1 << GPIO_Num_rx, uiTxLedIndex);
221 
222  /*
223  * Read the Tx & Rx packets transmission after 1 second and
224  * calculate rate of transfer
225  */
226  Final_num_of_packts_tx = Adapter->dev->stats.tx_packets;
227  Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
228 
229  rate_of_transfer_tx = Final_num_of_packts_tx -
230  Initial_num_of_packts_tx;
231  rate_of_transfer_rx = Final_num_of_packts_rx -
232  Initial_num_of_packts_rx;
233 
234  /* Read initial value of packets sent/received */
235  Initial_num_of_packts_tx = Final_num_of_packts_tx;
236  Initial_num_of_packts_rx = Final_num_of_packts_rx;
237 
238  /* Scale the rate of transfer to no of blinks. */
239  num_of_time_tx =
240  ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
241  num_of_time_rx =
242  ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
243 
244  }
245  return Status;
246 }
247 
248 /*
249  * -----------------------------------------------------------------------------
250  * Procedure: ValidateDSDParamsChecksum
251  *
252  * Description: Reads DSD Params and validates checkusm.
253  *
254  * Arguments:
255  * Adapter - Pointer to Adapter structure.
256  * ulParamOffset - Start offset of the DSD parameter to be read and
257  * validated.
258  * usParamLen - Length of the DSD Parameter.
259  *
260  * Returns:
261  * <OSAL_STATUS_CODE>
262  * -----------------------------------------------------------------------------
263  */
264 static INT ValidateDSDParamsChecksum(struct bcm_mini_adapter *Adapter, ULONG ulParamOffset,
265  USHORT usParamLen)
266 {
267  INT Status = STATUS_SUCCESS;
268  PUCHAR puBuffer = NULL;
269  USHORT usChksmOrg = 0;
270  USHORT usChecksumCalculated = 0;
271 
273  "LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
274  ulParamOffset, usParamLen);
275 
276  puBuffer = kmalloc(usParamLen, GFP_KERNEL);
277  if (!puBuffer) {
279  DBG_LVL_ALL,
280  "LED Thread: ValidateDSDParamsChecksum Allocation failed");
281  return -ENOMEM;
282 
283  }
284 
285  /* Read the DSD data from the parameter offset. */
286  if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)puBuffer,
287  ulParamOffset, usParamLen)) {
289  DBG_LVL_ALL,
290  "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
292  goto exit;
293  }
294 
295  /* Calculate the checksum of the data read from the DSD parameter. */
296  usChecksumCalculated = CFG_CalculateChecksum(puBuffer, usParamLen);
298  "LED Thread: usCheckSumCalculated = 0x%x\n",
299  usChecksumCalculated);
300 
301  /*
302  * End of the DSD parameter will have a TWO bytes checksum stored in it.
303  * Read it and compare with the calculated Checksum.
304  */
305  if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)&usChksmOrg,
306  ulParamOffset+usParamLen, 2)) {
308  DBG_LVL_ALL,
309  "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
311  goto exit;
312  }
313  usChksmOrg = ntohs(usChksmOrg);
315  "LED Thread: usChksmOrg = 0x%x", usChksmOrg);
316 
317  /*
318  * Compare the checksum calculated with the checksum read
319  * from DSD section
320  */
321  if (usChecksumCalculated ^ usChksmOrg) {
323  DBG_LVL_ALL,
324  "LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
326  goto exit;
327  }
328 
329 exit:
330  kfree(puBuffer);
331  return Status;
332 }
333 
334 
335 /*
336  * -----------------------------------------------------------------------------
337  * Procedure: ValidateHWParmStructure
338  *
339  * Description: Validates HW Parameters.
340  *
341  * Arguments:
342  * Adapter - Pointer to Adapter structure.
343  * ulHwParamOffset - Start offset of the HW parameter Section to be read
344  * and validated.
345  *
346  * Returns:
347  * <OSAL_STATUS_CODE>
348  * -----------------------------------------------------------------------------
349  */
350 static INT ValidateHWParmStructure(struct bcm_mini_adapter *Adapter, ULONG ulHwParamOffset)
351 {
352 
353  INT Status = STATUS_SUCCESS;
354  USHORT HwParamLen = 0;
355  /*
356  * Add DSD start offset to the hwParamOffset to get
357  * the actual address.
358  */
359  ulHwParamOffset += DSD_START_OFFSET;
360 
361  /* Read the Length of HW_PARAM structure */
362  BeceemNVMRead(Adapter, (PUINT)&HwParamLen, ulHwParamOffset, 2);
363  HwParamLen = ntohs(HwParamLen);
364  if (0 == HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
366 
368  "LED Thread:HwParamLen = 0x%x", HwParamLen);
369  Status = ValidateDSDParamsChecksum(Adapter, ulHwParamOffset,
370  HwParamLen);
371  return Status;
372 } /* ValidateHWParmStructure() */
373 
374 static int ReadLEDInformationFromEEPROM(struct bcm_mini_adapter *Adapter,
375  UCHAR GPIO_Array[])
376 {
377  int Status = STATUS_SUCCESS;
378 
379  ULONG dwReadValue = 0;
380  USHORT usHwParamData = 0;
381  USHORT usEEPROMVersion = 0;
382  UCHAR ucIndex = 0;
383  UCHAR ucGPIOInfo[32] = {0};
384 
385  BeceemNVMRead(Adapter, (PUINT)&usEEPROMVersion,
387 
389  "usEEPROMVersion: Minor:0x%X Major:0x%x",
390  usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
391 
392 
393  if (((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) {
394  BeceemNVMRead(Adapter, (PUINT)&usHwParamData,
396  usHwParamData = ntohs(usHwParamData);
397  dwReadValue = usHwParamData;
398  } else {
399  /*
400  * Validate Compatibility section and then read HW param
401  * if compatibility section is valid.
402  */
403  Status = ValidateDSDParamsChecksum(Adapter,
406 
407  if (Status != STATUS_SUCCESS)
408  return Status;
409 
410  BeceemNVMRead(Adapter, (PUINT)&dwReadValue,
412  dwReadValue = ntohl(dwReadValue);
413  }
414 
415 
417  "LED Thread: Start address of HW_PARAM structure = 0x%lx",
418  dwReadValue);
419 
420  /*
421  * Validate if the address read out is within the DSD.
422  * Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
423  * lower limit should be above DSD_START_OFFSET and
424  * upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
425  */
426  if (dwReadValue < DSD_START_OFFSET ||
427  dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
429 
430  Status = ValidateHWParmStructure(Adapter, dwReadValue);
431  if (Status)
432  return Status;
433 
434  /*
435  * Add DSD_START_OFFSET to the offset read from the EEPROM.
436  * This will give the actual start HW Parameters start address.
437  * To read GPIO section, add GPIO offset further.
438  */
439 
440  dwReadValue +=
441  DSD_START_OFFSET; /* = start address of hw param section. */
442  dwReadValue += GPIO_SECTION_START_OFFSET;
443  /* = GPIO start offset within HW Param section. */
444 
445  /*
446  * Read the GPIO values for 32 GPIOs from EEPROM and map the function
447  * number to GPIO pin number to GPIO_Array
448  */
449  BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo, dwReadValue, 32);
450  for (ucIndex = 0; ucIndex < 32; ucIndex++) {
451 
452  switch (ucGPIOInfo[ucIndex]) {
453  case RED_LED:
454  GPIO_Array[RED_LED] = ucIndex;
455  Adapter->gpioBitMap |= (1 << ucIndex);
456  break;
457  case BLUE_LED:
458  GPIO_Array[BLUE_LED] = ucIndex;
459  Adapter->gpioBitMap |= (1 << ucIndex);
460  break;
461  case YELLOW_LED:
462  GPIO_Array[YELLOW_LED] = ucIndex;
463  Adapter->gpioBitMap |= (1 << ucIndex);
464  break;
465  case GREEN_LED:
466  GPIO_Array[GREEN_LED] = ucIndex;
467  Adapter->gpioBitMap |= (1 << ucIndex);
468  break;
469  default:
470  break;
471  }
472 
473  }
475  "GPIO's bit map correspond to LED :0x%X", Adapter->gpioBitMap);
476  return Status;
477 }
478 
479 
480 static int ReadConfigFileStructure(struct bcm_mini_adapter *Adapter,
481  BOOLEAN *bEnableThread)
482 {
483  int Status = STATUS_SUCCESS;
484  /* Array to store GPIO numbers from EEPROM */
485  UCHAR GPIO_Array[NUM_OF_LEDS+1];
486  UINT uiIndex = 0;
487  UINT uiNum_of_LED_Type = 0;
488  PUCHAR puCFGData = NULL;
489  UCHAR bData = 0;
490  memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
491 
492  if (!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) {
494  DBG_LVL_ALL, "Target Params not Avail.\n");
495  return -ENOENT;
496  }
497 
498  /* Populate GPIO_Array with GPIO numbers for LED functions */
499  /* Read the GPIO numbers from EEPROM */
500  Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
501  if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) {
502  *bEnableThread = FALSE;
503  return STATUS_SUCCESS;
504  } else if (Status) {
505  *bEnableThread = FALSE;
506  return Status;
507  }
508 
509  /*
510  * CONFIG file read successfully. Deallocate the memory of
511  * uiFileNameBufferSize
512  */
514  "LED Thread: Config file read successfully\n");
515  puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
516 
517  /*
518  * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
519  * will have the information of LED type, LED on state for different
520  * driver state and LED blink state.
521  */
522 
523  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
524  bData = *puCFGData;
525 
526  /*
527  * Check Bit 8 for polarity. If it is set,
528  * polarity is reverse polarity
529  */
530  if (bData & 0x80) {
531  Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
532  /* unset the bit 8 */
533  bData = bData & 0x7f;
534  }
535 
536  Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
537  if (bData <= NUM_OF_LEDS)
538  Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
539  GPIO_Array[bData];
540  else
541  Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
543 
544  puCFGData++;
545  bData = *puCFGData;
546  Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
547  puCFGData++;
548  bData = *puCFGData;
549  Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State = bData;
550  puCFGData++;
551  }
552 
553  /*
554  * Check if all the LED settings are disabled. If it is disabled,
555  * dont launch the LED control thread.
556  */
557  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
558  if ((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
559  (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
560  (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
561  uiNum_of_LED_Type++;
562  }
563  if (uiNum_of_LED_Type >= NUM_OF_LEDS)
564  *bEnableThread = FALSE;
565 
566  return Status;
567 }
568 
569 /*
570  * -----------------------------------------------------------------------------
571  * Procedure: LedGpioInit
572  *
573  * Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode
574  * and make the initial state to be OFF.
575  *
576  * Arguments:
577  * Adapter - Pointer to MINI_ADAPTER structure.
578  *
579  * Returns: VOID
580  *
581  * -----------------------------------------------------------------------------
582  */
583 static VOID LedGpioInit(struct bcm_mini_adapter *Adapter)
584 {
585  UINT uiResetValue = 0;
586  UINT uiIndex = 0;
587 
588  /* Set all LED GPIO Mode to output mode */
589  if (rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
590  sizeof(uiResetValue)) < 0)
592  DBG_LVL_ALL, "LED Thread: RDM Failed\n");
593  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
594  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
596  uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
597  TURN_OFF_LED(1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,
598  uiIndex);
599  }
600  if (wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
601  sizeof(uiResetValue)) < 0)
603  DBG_LVL_ALL, "LED Thread: WRM Failed\n");
604 
605  Adapter->LEDInfo.bIdle_led_off = FALSE;
606 }
607 
608 static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter, UCHAR *GPIO_num_tx,
609  UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,
610  LedEventInfo_t currdriverstate)
611 {
612  UINT uiIndex = 0;
613 
614  *GPIO_num_tx = DISABLE_GPIO_NUM;
615  *GPIO_num_rx = DISABLE_GPIO_NUM;
616 
617  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
618 
619  if ((currdriverstate == NORMAL_OPERATION) ||
620  (currdriverstate == IDLEMODE_EXIT) ||
621  (currdriverstate == FW_DOWNLOAD)) {
622  if (Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State &
623  currdriverstate) {
624  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
625  != DISABLE_GPIO_NUM) {
626  if (*GPIO_num_tx == DISABLE_GPIO_NUM) {
627  *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
628  *uiLedTxIndex = uiIndex;
629  } else {
630  *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
631  *uiLedRxIndex = uiIndex;
632  }
633  }
634  }
635  } else {
636  if (Adapter->LEDInfo.LEDState[uiIndex].LED_On_State
637  & currdriverstate) {
638  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
639  != DISABLE_GPIO_NUM) {
640  *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
641  *uiLedTxIndex = uiIndex;
642  }
643  }
644  }
645  }
646  return STATUS_SUCCESS;
647 }
648 static VOID LEDControlThread(struct bcm_mini_adapter *Adapter)
649 {
650  UINT uiIndex = 0;
651  UCHAR GPIO_num = 0;
652  UCHAR uiLedIndex = 0;
653  UINT uiResetValue = 0;
654  LedEventInfo_t currdriverstate = 0;
655  ulong timeout = 0;
656 
657  INT Status = 0;
658 
659  UCHAR dummyGPIONum = 0;
660  UCHAR dummyIndex = 0;
661 
662  /* currdriverstate = Adapter->DriverState; */
664 
665  /*
666  * Wait till event is triggered
667  *
668  * wait_event(Adapter->LEDInfo.notify_led_event,
669  * currdriverstate!= Adapter->DriverState);
670  */
671 
672  GPIO_num = DISABLE_GPIO_NUM;
673 
674  while (TRUE) {
675  /* Wait till event is triggered */
676  if ((GPIO_num == DISABLE_GPIO_NUM)
677  ||
678  ((currdriverstate != FW_DOWNLOAD) &&
679  (currdriverstate != NORMAL_OPERATION) &&
680  (currdriverstate != LOWPOWER_MODE_ENTER))
681  ||
682  (currdriverstate == LED_THREAD_INACTIVE))
683  Status = wait_event_interruptible(
684  Adapter->LEDInfo.notify_led_event,
685  currdriverstate != Adapter->DriverState
686  || kthread_should_stop());
687 
688  if (kthread_should_stop() || Adapter->device_removed) {
690  DBG_LVL_ALL,
691  "Led thread got signal to exit..hence exiting");
692  Adapter->LEDInfo.led_thread_running =
694  TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
695  return; /* STATUS_FAILURE; */
696  }
697 
698  if (GPIO_num != DISABLE_GPIO_NUM)
699  TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
700 
701  if (Adapter->LEDInfo.bLedInitDone == FALSE) {
702  LedGpioInit(Adapter);
703  Adapter->LEDInfo.bLedInitDone = TRUE;
704  }
705 
706  switch (Adapter->DriverState) {
707  case DRIVER_INIT:
708  currdriverstate = DRIVER_INIT;
709  /* Adapter->DriverState; */
710  BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
711  &uiLedIndex, &dummyIndex, currdriverstate);
712 
713  if (GPIO_num != DISABLE_GPIO_NUM)
714  TURN_ON_LED(1 << GPIO_num, uiLedIndex);
715 
716  break;
717  case FW_DOWNLOAD:
718  /*
719  * BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
720  * LED_DUMP_INFO, DBG_LVL_ALL,
721  * "LED Thread: FW_DN_DONE called\n");
722  */
723  currdriverstate = FW_DOWNLOAD;
724  BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
725  &uiLedIndex, &dummyIndex, currdriverstate);
726 
727  if (GPIO_num != DISABLE_GPIO_NUM) {
728  timeout = 50;
729  LED_Blink(Adapter, 1 << GPIO_num, uiLedIndex,
730  timeout, -1, currdriverstate);
731  }
732  break;
733  case FW_DOWNLOAD_DONE:
734  currdriverstate = FW_DOWNLOAD_DONE;
735  BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
736  &uiLedIndex, &dummyIndex, currdriverstate);
737  if (GPIO_num != DISABLE_GPIO_NUM)
738  TURN_ON_LED(1 << GPIO_num, uiLedIndex);
739  break;
740 
741  case SHUTDOWN_EXIT:
742  /*
743  * no break, continue to NO_NETWORK_ENTRY
744  * state as well.
745  */
746  case NO_NETWORK_ENTRY:
747  currdriverstate = NO_NETWORK_ENTRY;
748  BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
749  &uiLedIndex, &dummyGPIONum, currdriverstate);
750  if (GPIO_num != DISABLE_GPIO_NUM)
751  TURN_ON_LED(1 << GPIO_num, uiLedIndex);
752  break;
753  case NORMAL_OPERATION:
754  {
755  UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
756  UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
757  UCHAR uiLEDTx = 0;
758  UCHAR uiLEDRx = 0;
759  currdriverstate = NORMAL_OPERATION;
760  Adapter->LEDInfo.bIdle_led_off = FALSE;
761 
762  BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx,
763  &GPIO_num_rx, &uiLEDTx, &uiLEDRx,
764  currdriverstate);
765  if ((GPIO_num_tx == DISABLE_GPIO_NUM) &&
766  (GPIO_num_rx ==
767  DISABLE_GPIO_NUM)) {
768  GPIO_num = DISABLE_GPIO_NUM;
769  } else {
770  /*
771  * If single LED is selected, use same
772  * for both Tx and Rx
773  */
774  if (GPIO_num_tx == DISABLE_GPIO_NUM) {
775  GPIO_num_tx = GPIO_num_rx;
776  uiLEDTx = uiLEDRx;
777  } else if (GPIO_num_rx ==
779  GPIO_num_rx = GPIO_num_tx;
780  uiLEDRx = uiLEDTx;
781  }
782  /*
783  * Blink the LED in proportionate
784  * to Tx and Rx transmissions.
785  */
786  LED_Proportional_Blink(Adapter,
787  GPIO_num_tx, uiLEDTx,
788  GPIO_num_rx, uiLEDRx,
789  currdriverstate);
790  }
791  }
792  break;
793  case LOWPOWER_MODE_ENTER:
794  currdriverstate = LOWPOWER_MODE_ENTER;
796  Adapter->ulPowerSaveMode) {
797  /* Turn OFF all the LED */
798  uiResetValue = 0;
799  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
800  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
801  TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
802  }
803 
804  }
805  /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
806  Adapter->LEDInfo.bLedInitDone = FALSE;
807  Adapter->LEDInfo.bIdle_led_off = TRUE;
808  wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
809  GPIO_num = DISABLE_GPIO_NUM;
810  break;
811  case IDLEMODE_CONTINUE:
812  currdriverstate = IDLEMODE_CONTINUE;
813  GPIO_num = DISABLE_GPIO_NUM;
814  break;
815  case IDLEMODE_EXIT:
816  break;
817  case DRIVER_HALT:
818  currdriverstate = DRIVER_HALT;
819  GPIO_num = DISABLE_GPIO_NUM;
820  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
821  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
822  != DISABLE_GPIO_NUM)
823  TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
824  }
825  /* Adapter->DriverState = DRIVER_INIT; */
826  break;
827  case LED_THREAD_INACTIVE:
829  DBG_LVL_ALL, "InActivating LED thread...");
830  currdriverstate = LED_THREAD_INACTIVE;
831  Adapter->LEDInfo.led_thread_running =
833  Adapter->LEDInfo.bLedInitDone = FALSE;
834  /* disable ALL LED */
835  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
836  if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
837  != DISABLE_GPIO_NUM)
838  TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
839  }
840  break;
841  case LED_THREAD_ACTIVE:
843  DBG_LVL_ALL, "Activating LED thread again...");
844  if (Adapter->LinkUpStatus == FALSE)
845  Adapter->DriverState = NO_NETWORK_ENTRY;
846  else
847  Adapter->DriverState = NORMAL_OPERATION;
848 
849  Adapter->LEDInfo.led_thread_running =
851  break;
852  /* return; */
853  default:
854  break;
855  }
856  }
858 }
859 
860 int InitLedSettings(struct bcm_mini_adapter *Adapter)
861 {
862  int Status = STATUS_SUCCESS;
863  BOOLEAN bEnableThread = TRUE;
864  UCHAR uiIndex = 0;
865 
866  /*
867  * Initially set BitPolarity to normal polarity. The bit 8 of LED type
868  * is used to change the polarity of the LED.
869  */
870 
871  for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
872  Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
873 
874  /*
875  * Read the LED settings of CONFIG file and map it
876  * to GPIO numbers in EEPROM
877  */
878  Status = ReadConfigFileStructure(Adapter, &bEnableThread);
879  if (STATUS_SUCCESS != Status) {
881  DBG_LVL_ALL,
882  "LED Thread: FAILED in ReadConfigFileStructure\n");
883  return Status;
884  }
885 
886  if (Adapter->LEDInfo.led_thread_running) {
887  if (bEnableThread) {
888  ;
889  } else {
890  Adapter->DriverState = DRIVER_HALT;
891  wake_up(&Adapter->LEDInfo.notify_led_event);
892  Adapter->LEDInfo.led_thread_running =
894  }
895 
896  } else if (bEnableThread) {
897  /* Create secondary thread to handle the LEDs */
900  Adapter->LEDInfo.led_thread_running =
902  Adapter->LEDInfo.bIdle_led_off = FALSE;
903  Adapter->LEDInfo.led_cntrl_threadid =
904  kthread_run((int (*)(void *)) LEDControlThread,
905  Adapter, "led_control_thread");
906  if (IS_ERR(Adapter->LEDInfo.led_cntrl_threadid)) {
908  DBG_LVL_ALL,
909  "Not able to spawn Kernel Thread\n");
910  Adapter->LEDInfo.led_thread_running =
912  return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
913  }
914  }
915  return Status;
916 }