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