Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / drivers / staging / bcm / led_control.c
blobc7f48862972219802a28c16f984f214f16e9a345
1 #include "headers.h"
3 #define STATUS_IMAGE_CHECKSUM_MISMATCH -199
4 #define EVENT_SIGNALED 1
6 static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
8 B_UINT16 u16CheckSum = 0;
9 while (u32Size--) {
10 u16CheckSum += (B_UINT8)~(*pu8Buffer);
11 pu8Buffer++;
13 return u16CheckSum;
16 BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios)
18 INT Status;
19 Status = (Adapter->gpioBitMap & gpios) ^ gpios;
20 if (Status)
21 return FALSE;
22 else
23 return TRUE;
26 static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex,
27 ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
29 int Status = STATUS_SUCCESS;
30 BOOLEAN bInfinite = FALSE;
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;
37 while (num_of_time) {
38 if (currdriverstate == Adapter->DriverState)
39 TURN_ON_LED(GPIO_Num, uiLedIndex);
41 /* Wait for timeout after setting on the LED */
42 Status = wait_event_interruptible_timeout(
43 Adapter->LEDInfo.notify_led_event,
44 currdriverstate != Adapter->DriverState ||
45 kthread_should_stop(),
46 msecs_to_jiffies(timeout));
48 if (kthread_should_stop()) {
49 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
50 DBG_LVL_ALL,
51 "Led thread got signal to exit..hence exiting");
52 Adapter->LEDInfo.led_thread_running =
53 BCM_LED_THREAD_DISABLED;
54 TURN_OFF_LED(GPIO_Num, uiLedIndex);
55 Status = EVENT_SIGNALED;
56 break;
58 if (Status) {
59 TURN_OFF_LED(GPIO_Num, uiLedIndex);
60 Status = EVENT_SIGNALED;
61 break;
64 TURN_OFF_LED(GPIO_Num, uiLedIndex);
65 Status = wait_event_interruptible_timeout(
66 Adapter->LEDInfo.notify_led_event,
67 currdriverstate != Adapter->DriverState ||
68 kthread_should_stop(),
69 msecs_to_jiffies(timeout));
70 if (bInfinite == FALSE)
71 num_of_time--;
73 return Status;
76 static INT ScaleRateofTransfer(ULONG rate)
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;
98 static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx,
99 UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex,
100 LedEventInfo_t currdriverstate)
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;
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;
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);
123 while ((Adapter->device_removed == FALSE)) {
124 timeout = 50;
126 * Blink Tx and Rx LED when both Tx and Rx is
127 * in normal bandwidth
129 if (bBlinkBothLED) {
131 * Assign minimum number of blinks of
132 * either Tx or Rx.
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;
146 if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
147 uiRxLedIndex, timeout,
148 num_of_time, currdriverstate)
149 == EVENT_SIGNALED)
150 return EVENT_SIGNALED;
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;
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;
173 num_of_time = num_of_time_tx;
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;
194 * If Tx/Rx rate is less than maximum blinks per second,
195 * wait till delay completes to 1 second
197 remDelay = MAX_NUM_OF_BLINKS - num_of_time;
198 if (remDelay > 0) {
199 timeout = 100 * remDelay;
200 Status = wait_event_interruptible_timeout(
201 Adapter->LEDInfo.notify_led_event,
202 currdriverstate != Adapter->DriverState
203 || kthread_should_stop(),
204 msecs_to_jiffies(timeout));
206 if (kthread_should_stop()) {
207 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
208 LED_DUMP_INFO, DBG_LVL_ALL,
209 "Led thread got signal to exit..hence exiting");
210 Adapter->LEDInfo.led_thread_running =
211 BCM_LED_THREAD_DISABLED;
212 return EVENT_SIGNALED;
214 if (Status)
215 return EVENT_SIGNALED;
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);
223 * Read the Tx & Rx packets transmission after 1 second and
224 * calculate rate of transfer
226 Final_num_of_packts_tx = Adapter->dev->stats.tx_packets;
227 Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
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;
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;
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);
245 return Status;
249 * -----------------------------------------------------------------------------
250 * Procedure: ValidateDSDParamsChecksum
252 * Description: Reads DSD Params and validates checkusm.
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.
260 * Returns:
261 * <OSAL_STATUS_CODE>
262 * -----------------------------------------------------------------------------
264 static INT ValidateDSDParamsChecksum(PMINI_ADAPTER Adapter, ULONG ulParamOffset,
265 USHORT usParamLen)
267 INT Status = STATUS_SUCCESS;
268 PUCHAR puBuffer = NULL;
269 USHORT usChksmOrg = 0;
270 USHORT usChecksumCalculated = 0;
272 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
273 "LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
274 ulParamOffset, usParamLen);
276 puBuffer = kmalloc(usParamLen, GFP_KERNEL);
277 if (!puBuffer) {
278 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
279 DBG_LVL_ALL,
280 "LED Thread: ValidateDSDParamsChecksum Allocation failed");
281 return -ENOMEM;
285 /* Read the DSD data from the parameter offset. */
286 if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)puBuffer,
287 ulParamOffset, usParamLen)) {
288 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
289 DBG_LVL_ALL,
290 "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
291 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
292 goto exit;
295 /* Calculate the checksum of the data read from the DSD parameter. */
296 usChecksumCalculated = CFG_CalculateChecksum(puBuffer, usParamLen);
297 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
298 "LED Thread: usCheckSumCalculated = 0x%x\n",
299 usChecksumCalculated);
302 * End of the DSD parameter will have a TWO bytes checksum stored in it.
303 * Read it and compare with the calculated Checksum.
305 if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)&usChksmOrg,
306 ulParamOffset+usParamLen, 2)) {
307 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
308 DBG_LVL_ALL,
309 "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
310 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
311 goto exit;
313 usChksmOrg = ntohs(usChksmOrg);
314 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
315 "LED Thread: usChksmOrg = 0x%x", usChksmOrg);
318 * Compare the checksum calculated with the checksum read
319 * from DSD section
321 if (usChecksumCalculated ^ usChksmOrg) {
322 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
323 DBG_LVL_ALL,
324 "LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
325 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
326 goto exit;
329 exit:
330 kfree(puBuffer);
331 return Status;
336 * -----------------------------------------------------------------------------
337 * Procedure: ValidateHWParmStructure
339 * Description: Validates HW Parameters.
341 * Arguments:
342 * Adapter - Pointer to Adapter structure.
343 * ulHwParamOffset - Start offset of the HW parameter Section to be read
344 * and validated.
346 * Returns:
347 * <OSAL_STATUS_CODE>
348 * -----------------------------------------------------------------------------
350 static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset)
353 INT Status = STATUS_SUCCESS;
354 USHORT HwParamLen = 0;
356 * Add DSD start offset to the hwParamOffset to get
357 * the actual address.
359 ulHwParamOffset += DSD_START_OFFSET;
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)
365 return STATUS_IMAGE_CHECKSUM_MISMATCH;
367 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
368 "LED Thread:HwParamLen = 0x%x", HwParamLen);
369 Status = ValidateDSDParamsChecksum(Adapter, ulHwParamOffset,
370 HwParamLen);
371 return Status;
372 } /* ValidateHWParmStructure() */
374 static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter,
375 UCHAR GPIO_Array[])
377 int Status = STATUS_SUCCESS;
379 ULONG dwReadValue = 0;
380 USHORT usHwParamData = 0;
381 USHORT usEEPROMVersion = 0;
382 UCHAR ucIndex = 0;
383 UCHAR ucGPIOInfo[32] = {0};
385 BeceemNVMRead(Adapter, (PUINT)&usEEPROMVersion,
386 EEPROM_VERSION_OFFSET, 2);
388 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
389 "usEEPROMVersion: Minor:0x%X Major:0x%x",
390 usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
393 if (((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) {
394 BeceemNVMRead(Adapter, (PUINT)&usHwParamData,
395 EEPROM_HW_PARAM_POINTER_ADDRESS, 2);
396 usHwParamData = ntohs(usHwParamData);
397 dwReadValue = usHwParamData;
398 } else {
400 * Validate Compatibility section and then read HW param
401 * if compatibility section is valid.
403 Status = ValidateDSDParamsChecksum(Adapter,
404 DSD_START_OFFSET,
405 COMPATIBILITY_SECTION_LENGTH_MAP5);
407 if (Status != STATUS_SUCCESS)
408 return Status;
410 BeceemNVMRead(Adapter, (PUINT)&dwReadValue,
411 EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5, 4);
412 dwReadValue = ntohl(dwReadValue);
416 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
417 "LED Thread: Start address of HW_PARAM structure = 0x%lx",
418 dwReadValue);
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)
426 if (dwReadValue < DSD_START_OFFSET ||
427 dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
428 return STATUS_IMAGE_CHECKSUM_MISMATCH;
430 Status = ValidateHWParmStructure(Adapter, dwReadValue);
431 if (Status)
432 return Status;
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.
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. */
446 * Read the GPIO values for 32 GPIOs from EEPROM and map the function
447 * number to GPIO pin number to GPIO_Array
449 BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo, dwReadValue, 32);
450 for (ucIndex = 0; ucIndex < 32; ucIndex++) {
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;
474 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
475 "GPIO's bit map correspond to LED :0x%X", Adapter->gpioBitMap);
476 return Status;
480 static int ReadConfigFileStructure(PMINI_ADAPTER Adapter,
481 BOOLEAN *bEnableThread)
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);
492 if (!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) {
493 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
494 DBG_LVL_ALL, "Target Params not Avail.\n");
495 return -ENOENT;
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;
510 * CONFIG file read successfully. Deallocate the memory of
511 * uiFileNameBufferSize
513 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
514 "LED Thread: Config file read successfully\n");
515 puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
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.
523 for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
524 bData = *puCFGData;
527 * Check Bit 8 for polarity. If it is set,
528 * polarity is reverse polarity
530 if (bData & 0x80) {
531 Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
532 /* unset the bit 8 */
533 bData = bData & 0x7f;
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 =
542 DISABLE_GPIO_NUM;
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++;
554 * Check if all the LED settings are disabled. If it is disabled,
555 * dont launch the LED control thread.
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++;
563 if (uiNum_of_LED_Type >= NUM_OF_LEDS)
564 *bEnableThread = FALSE;
566 return Status;
570 * -----------------------------------------------------------------------------
571 * Procedure: LedGpioInit
573 * Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode
574 * and make the initial state to be OFF.
576 * Arguments:
577 * Adapter - Pointer to MINI_ADAPTER structure.
579 * Returns: VOID
581 * -----------------------------------------------------------------------------
583 static VOID LedGpioInit(PMINI_ADAPTER Adapter)
585 UINT uiResetValue = 0;
586 UINT uiIndex = 0;
588 /* Set all LED GPIO Mode to output mode */
589 if (rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
590 sizeof(uiResetValue)) < 0)
591 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
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 !=
595 DISABLE_GPIO_NUM)
596 uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
597 TURN_OFF_LED(1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,
598 uiIndex);
600 if (wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
601 sizeof(uiResetValue)) < 0)
602 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
603 DBG_LVL_ALL, "LED Thread: WRM Failed\n");
605 Adapter->LEDInfo.bIdle_led_off = FALSE;
608 static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx,
609 UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,
610 LedEventInfo_t currdriverstate)
612 UINT uiIndex = 0;
614 *GPIO_num_tx = DISABLE_GPIO_NUM;
615 *GPIO_num_rx = DISABLE_GPIO_NUM;
617 for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
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;
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;
646 return STATUS_SUCCESS;
648 static VOID LEDControlThread(PMINI_ADAPTER Adapter)
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;
657 INT Status = 0;
659 UCHAR dummyGPIONum = 0;
660 UCHAR dummyIndex = 0;
662 /* currdriverstate = Adapter->DriverState; */
663 Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
666 * Wait till event is triggered
668 * wait_event(Adapter->LEDInfo.notify_led_event,
669 * currdriverstate!= Adapter->DriverState);
672 GPIO_num = DISABLE_GPIO_NUM;
674 while (TRUE) {
675 /* Wait till event is triggered */
676 if ((GPIO_num == DISABLE_GPIO_NUM)
678 ((currdriverstate != FW_DOWNLOAD) &&
679 (currdriverstate != NORMAL_OPERATION) &&
680 (currdriverstate != LOWPOWER_MODE_ENTER))
682 (currdriverstate == LED_THREAD_INACTIVE))
683 Status = wait_event_interruptible(
684 Adapter->LEDInfo.notify_led_event,
685 currdriverstate != Adapter->DriverState
686 || kthread_should_stop());
688 if (kthread_should_stop() || Adapter->device_removed) {
689 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
690 DBG_LVL_ALL,
691 "Led thread got signal to exit..hence exiting");
692 Adapter->LEDInfo.led_thread_running =
693 BCM_LED_THREAD_DISABLED;
694 TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
695 return; /* STATUS_FAILURE; */
698 if (GPIO_num != DISABLE_GPIO_NUM)
699 TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
701 if (Adapter->LEDInfo.bLedInitDone == FALSE) {
702 LedGpioInit(Adapter);
703 Adapter->LEDInfo.bLedInitDone = TRUE;
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);
713 if (GPIO_num != DISABLE_GPIO_NUM)
714 TURN_ON_LED(1 << GPIO_num, uiLedIndex);
716 break;
717 case FW_DOWNLOAD:
719 * BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
720 * LED_DUMP_INFO, DBG_LVL_ALL,
721 * "LED Thread: FW_DN_DONE called\n");
723 currdriverstate = FW_DOWNLOAD;
724 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
725 &uiLedIndex, &dummyIndex, currdriverstate);
727 if (GPIO_num != DISABLE_GPIO_NUM) {
728 timeout = 50;
729 LED_Blink(Adapter, 1 << GPIO_num, uiLedIndex,
730 timeout, -1, currdriverstate);
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;
741 case SHUTDOWN_EXIT:
743 * no break, continue to NO_NETWORK_ENTRY
744 * state as well.
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:
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;
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 {
771 * If single LED is selected, use same
772 * for both Tx and Rx
774 if (GPIO_num_tx == DISABLE_GPIO_NUM) {
775 GPIO_num_tx = GPIO_num_rx;
776 uiLEDTx = uiLEDRx;
777 } else if (GPIO_num_rx ==
778 DISABLE_GPIO_NUM) {
779 GPIO_num_rx = GPIO_num_tx;
780 uiLEDRx = uiLEDTx;
783 * Blink the LED in proportionate
784 * to Tx and Rx transmissions.
786 LED_Proportional_Blink(Adapter,
787 GPIO_num_tx, uiLEDTx,
788 GPIO_num_rx, uiLEDRx,
789 currdriverstate);
792 break;
793 case LOWPOWER_MODE_ENTER:
794 currdriverstate = LOWPOWER_MODE_ENTER;
795 if (DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING ==
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);
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);
825 /* Adapter->DriverState = DRIVER_INIT; */
826 break;
827 case LED_THREAD_INACTIVE:
828 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
829 DBG_LVL_ALL, "InActivating LED thread...");
830 currdriverstate = LED_THREAD_INACTIVE;
831 Adapter->LEDInfo.led_thread_running =
832 BCM_LED_THREAD_RUNNING_INACTIVELY;
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);
840 break;
841 case LED_THREAD_ACTIVE:
842 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
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;
849 Adapter->LEDInfo.led_thread_running =
850 BCM_LED_THREAD_RUNNING_ACTIVELY;
851 break;
852 /* return; */
853 default:
854 break;
857 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
860 int InitLedSettings(PMINI_ADAPTER Adapter)
862 int Status = STATUS_SUCCESS;
863 BOOLEAN bEnableThread = TRUE;
864 UCHAR uiIndex = 0;
867 * Initially set BitPolarity to normal polarity. The bit 8 of LED type
868 * is used to change the polarity of the LED.
871 for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
872 Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
875 * Read the LED settings of CONFIG file and map it
876 * to GPIO numbers in EEPROM
878 Status = ReadConfigFileStructure(Adapter, &bEnableThread);
879 if (STATUS_SUCCESS != Status) {
880 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
881 DBG_LVL_ALL,
882 "LED Thread: FAILED in ReadConfigFileStructure\n");
883 return Status;
886 if (Adapter->LEDInfo.led_thread_running) {
887 if (bEnableThread) {
889 } else {
890 Adapter->DriverState = DRIVER_HALT;
891 wake_up(&Adapter->LEDInfo.notify_led_event);
892 Adapter->LEDInfo.led_thread_running =
893 BCM_LED_THREAD_DISABLED;
896 } else if (bEnableThread) {
897 /* Create secondary thread to handle the LEDs */
898 init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
899 init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
900 Adapter->LEDInfo.led_thread_running =
901 BCM_LED_THREAD_RUNNING_ACTIVELY;
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)) {
907 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
908 DBG_LVL_ALL,
909 "Not able to spawn Kernel Thread\n");
910 Adapter->LEDInfo.led_thread_running =
911 BCM_LED_THREAD_DISABLED;
912 return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
915 return Status;