• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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