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