1#include "headers.h" 2 3#define STATUS_IMAGE_CHECKSUM_MISMATCH -199 4#define EVENT_SIGNALED 1 5 6static 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 17bool 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 28static 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 82static 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 102static 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 149static 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 */ 263static 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 329exit: 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 */ 350static 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 375static 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 483static 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 */ 589static 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 617static 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 656static 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 824static 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 896int 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