1// SPDX-License-Identifier: GPL-2.0
2/******************************************************************************
3 * rtl8712_led.c
4 *
5 * Copyright(c) 2007 - 2010  Realtek Corporation. All rights reserved.
6 * Linux device driver for RTL8192SU
7 *
8 * Modifications for inclusion into the Linux staging tree are
9 * Copyright(c) 2010 Larry Finger. All rights reserved.
10 *
11 * Contact information:
12 * WLAN FAE <wlanfae@realtek.com>
13 * Larry Finger <Larry.Finger@lwfinger.net>
14 *
15 ******************************************************************************/
16
17#include "drv_types.h"
18
19/*===========================================================================
20 *	Constant.
21 *===========================================================================
22
23 *
24 * Default LED behavior.
25 */
26#define LED_BLINK_NORMAL_INTERVAL	100
27#define LED_BLINK_SLOWLY_INTERVAL	200
28#define LED_BLINK_LONG_INTERVAL	400
29
30#define LED_BLINK_NO_LINK_INTERVAL_ALPHA	1000
31#define LED_BLINK_LINK_INTERVAL_ALPHA		500
32#define LED_BLINK_SCAN_INTERVAL_ALPHA		180
33#define LED_BLINK_FASTER_INTERVAL_ALPHA		50
34#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA	5000
35
36/*===========================================================================
37 * LED object.
38 *===========================================================================
39 */
40enum _LED_STATE_871x {
41	LED_UNKNOWN = 0,
42	LED_STATE_ON = 1,
43	LED_STATE_OFF = 2,
44	LED_BLINK_NORMAL = 3,
45	LED_BLINK_SLOWLY = 4,
46	LED_POWER_ON_BLINK = 5,
47	LED_SCAN_BLINK = 6, /* LED is blinking during scanning period,
48			     * the # of times to blink is depend on time
49			     * for scanning.
50			     */
51	LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */
52	LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer
53				    * Server case
54				    */
55	LED_BLINK_WPS = 9,	/* LED is blinkg during WPS communication */
56	LED_TXRX_BLINK = 10,
57	LED_BLINK_WPS_STOP = 11,	/*for ALPHA */
58	LED_BLINK_WPS_STOP_OVERLAP = 12,	/*for BELKIN */
59};
60
61/*===========================================================================
62 *	Prototype of protected function.
63 *===========================================================================
64 */
65static void BlinkTimerCallback(struct timer_list *t);
66
67static void BlinkWorkItemCallback(struct work_struct *work);
68/*===========================================================================
69 * LED_819xUsb routines.
70 *===========================================================================
71 *
72 *
73 *
74 *	Description:
75 *		Initialize an LED_871x object.
76 */
77static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
78			enum LED_PIN_871x	LedPin)
79{
80	pLed->padapter = padapter;
81	pLed->LedPin = LedPin;
82	pLed->CurrLedState = LED_STATE_OFF;
83	pLed->bLedOn = false;
84	pLed->bLedBlinkInProgress = false;
85	pLed->BlinkTimes = 0;
86	pLed->BlinkingLedState = LED_UNKNOWN;
87	timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
88	INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
89}
90
91/*
92 *	Description:
93 *		DeInitialize an LED_871x object.
94 */
95static void DeInitLed871x(struct LED_871x *pLed)
96{
97	del_timer_sync(&pLed->BlinkTimer);
98	/* We should reset bLedBlinkInProgress if we cancel
99	 * the LedControlTimer,
100	 */
101	pLed->bLedBlinkInProgress = false;
102}
103
104/*
105 *	Description:
106 *		Turn on LED according to LedPin specified.
107 */
108static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed)
109{
110	u8	LedCfg;
111
112	if (padapter->surprise_removed || padapter->driver_stopped)
113		return;
114	LedCfg = r8712_read8(padapter, LEDCFG);
115	switch (pLed->LedPin) {
116	case LED_PIN_GPIO0:
117		break;
118	case LED_PIN_LED0:
119		/* SW control led0 on.*/
120		r8712_write8(padapter, LEDCFG, LedCfg & 0xf0);
121		break;
122	case LED_PIN_LED1:
123		/* SW control led1 on.*/
124		r8712_write8(padapter, LEDCFG, LedCfg & 0x0f);
125		break;
126	default:
127		break;
128	}
129	pLed->bLedOn = true;
130}
131
132/*
133 *	Description:
134 *		Turn off LED according to LedPin specified.
135 */
136static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed)
137{
138	u8	LedCfg;
139
140	if (padapter->surprise_removed || padapter->driver_stopped)
141		return;
142	LedCfg = r8712_read8(padapter, LEDCFG);
143	switch (pLed->LedPin) {
144	case LED_PIN_GPIO0:
145		break;
146	case LED_PIN_LED0:
147		LedCfg &= 0xf0; /* Set to software control.*/
148		r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3)));
149		break;
150	case LED_PIN_LED1:
151		LedCfg &= 0x0f; /* Set to software control.*/
152		r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7)));
153		break;
154	default:
155		break;
156	}
157	pLed->bLedOn = false;
158}
159
160/*===========================================================================
161 * Interface to manipulate LED objects.
162 *===========================================================================
163 *
164 *	Description:
165 *		Initialize all LED_871x objects.
166 */
167void r8712_InitSwLeds(struct _adapter *padapter)
168{
169	struct led_priv	*pledpriv = &padapter->ledpriv;
170
171	pledpriv->LedControlHandler = LedControl871x;
172	InitLed871x(padapter, &pledpriv->SwLed0, LED_PIN_LED0);
173	InitLed871x(padapter, &pledpriv->SwLed1, LED_PIN_LED1);
174}
175
176/*	Description:
177 *		DeInitialize all LED_819xUsb objects.
178 */
179void r8712_DeInitSwLeds(struct _adapter *padapter)
180{
181	struct led_priv	*ledpriv = &padapter->ledpriv;
182
183	DeInitLed871x(&ledpriv->SwLed0);
184	DeInitLed871x(&ledpriv->SwLed1);
185}
186
187/*	Description:
188 *		Implementation of LED blinking behavior.
189 *		It toggle off LED and schedule corresponding timer if necessary.
190 */
191static void SwLedBlink(struct LED_871x *pLed)
192{
193	struct _adapter *padapter = pLed->padapter;
194	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
195	u8 bStopBlinking = false;
196
197	/* Change LED according to BlinkingLedState specified. */
198	if (pLed->BlinkingLedState == LED_STATE_ON)
199		SwLedOn(padapter, pLed);
200	else
201		SwLedOff(padapter, pLed);
202	/* Determine if we shall change LED state again. */
203	pLed->BlinkTimes--;
204	switch (pLed->CurrLedState) {
205	case LED_BLINK_NORMAL:
206		if (pLed->BlinkTimes == 0)
207			bStopBlinking = true;
208		break;
209	case LED_BLINK_StartToBlink:
210		if (check_fwstate(pmlmepriv, _FW_LINKED) &&
211		    (pmlmepriv->fw_state & WIFI_STATION_STATE))
212			bStopBlinking = true;
213		if (check_fwstate(pmlmepriv, _FW_LINKED) &&
214		    ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) ||
215		    (pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE)))
216			bStopBlinking = true;
217		else if (pLed->BlinkTimes == 0)
218			bStopBlinking = true;
219		break;
220	case LED_BLINK_WPS:
221		if (pLed->BlinkTimes == 0)
222			bStopBlinking = true;
223		break;
224	default:
225		bStopBlinking = true;
226		break;
227	}
228	if (bStopBlinking) {
229		if (check_fwstate(pmlmepriv, _FW_LINKED) &&
230		    !pLed->bLedOn)
231			SwLedOn(padapter, pLed);
232		else if (check_fwstate(pmlmepriv, _FW_LINKED) &&  pLed->bLedOn)
233			SwLedOff(padapter, pLed);
234		pLed->BlinkTimes = 0;
235		pLed->bLedBlinkInProgress = false;
236	} else {
237		/* Assign LED state to toggle. */
238		if (pLed->BlinkingLedState == LED_STATE_ON)
239			pLed->BlinkingLedState = LED_STATE_OFF;
240		else
241			pLed->BlinkingLedState = LED_STATE_ON;
242
243		/* Schedule a timer to toggle LED state. */
244		switch (pLed->CurrLedState) {
245		case LED_BLINK_NORMAL:
246			mod_timer(&pLed->BlinkTimer, jiffies +
247				  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
248			break;
249		case LED_BLINK_SLOWLY:
250		case LED_BLINK_StartToBlink:
251			mod_timer(&pLed->BlinkTimer, jiffies +
252				  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
253			break;
254		case LED_BLINK_WPS:
255			mod_timer(&pLed->BlinkTimer, jiffies +
256				  msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
257			break;
258		default:
259			mod_timer(&pLed->BlinkTimer, jiffies +
260				  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
261			break;
262		}
263	}
264}
265
266static void SwLedBlink1(struct LED_871x *pLed)
267{
268	struct _adapter *padapter = pLed->padapter;
269	struct led_priv *ledpriv = &padapter->ledpriv;
270	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
271	struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
272	struct LED_871x *pLed1 = &ledpriv->SwLed1;
273	u8 bStopBlinking = false;
274
275	if (peeprompriv->CustomerID == RT_CID_819x_CAMEO)
276		pLed = &ledpriv->SwLed1;
277	/* Change LED according to BlinkingLedState specified. */
278	if (pLed->BlinkingLedState == LED_STATE_ON)
279		SwLedOn(padapter, pLed);
280	else
281		SwLedOff(padapter, pLed);
282	if (peeprompriv->CustomerID == RT_CID_DEFAULT) {
283		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
284			if (!pLed1->bSWLedCtrl) {
285				SwLedOn(padapter, pLed1);
286				pLed1->bSWLedCtrl = true;
287			} else if (!pLed1->bLedOn) {
288				SwLedOn(padapter, pLed1);
289			}
290		} else {
291			if (!pLed1->bSWLedCtrl) {
292				SwLedOff(padapter, pLed1);
293				pLed1->bSWLedCtrl = true;
294			} else if (pLed1->bLedOn) {
295				SwLedOff(padapter, pLed1);
296			}
297		}
298	}
299	switch (pLed->CurrLedState) {
300	case LED_BLINK_SLOWLY:
301		if (pLed->bLedOn)
302			pLed->BlinkingLedState = LED_STATE_OFF;
303		else
304			pLed->BlinkingLedState = LED_STATE_ON;
305		mod_timer(&pLed->BlinkTimer, jiffies +
306			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
307		break;
308	case LED_BLINK_NORMAL:
309		if (pLed->bLedOn)
310			pLed->BlinkingLedState = LED_STATE_OFF;
311		else
312			pLed->BlinkingLedState = LED_STATE_ON;
313		mod_timer(&pLed->BlinkTimer, jiffies +
314			  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
315		break;
316	case LED_SCAN_BLINK:
317		pLed->BlinkTimes--;
318		if (pLed->BlinkTimes == 0)
319			bStopBlinking = true;
320		if (bStopBlinking) {
321			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
322				pLed->bLedLinkBlinkInProgress = true;
323				pLed->CurrLedState = LED_BLINK_NORMAL;
324				if (pLed->bLedOn)
325					pLed->BlinkingLedState = LED_STATE_OFF;
326				else
327					pLed->BlinkingLedState = LED_STATE_ON;
328				mod_timer(&pLed->BlinkTimer, jiffies +
329					  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
330			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
331				pLed->bLedNoLinkBlinkInProgress = true;
332				pLed->CurrLedState = LED_BLINK_SLOWLY;
333				if (pLed->bLedOn)
334					pLed->BlinkingLedState = LED_STATE_OFF;
335				else
336					pLed->BlinkingLedState = LED_STATE_ON;
337				mod_timer(&pLed->BlinkTimer, jiffies +
338					  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
339			}
340			pLed->bLedScanBlinkInProgress = false;
341		} else {
342			if (pLed->bLedOn)
343				pLed->BlinkingLedState = LED_STATE_OFF;
344			else
345				pLed->BlinkingLedState = LED_STATE_ON;
346			mod_timer(&pLed->BlinkTimer, jiffies +
347				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
348		}
349		break;
350	case LED_TXRX_BLINK:
351		pLed->BlinkTimes--;
352		if (pLed->BlinkTimes == 0)
353			bStopBlinking = true;
354		if (bStopBlinking) {
355			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
356				pLed->bLedLinkBlinkInProgress = true;
357				pLed->CurrLedState = LED_BLINK_NORMAL;
358				if (pLed->bLedOn)
359					pLed->BlinkingLedState = LED_STATE_OFF;
360				else
361					pLed->BlinkingLedState = LED_STATE_ON;
362				mod_timer(&pLed->BlinkTimer, jiffies +
363					  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
364			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
365				pLed->bLedNoLinkBlinkInProgress = true;
366				pLed->CurrLedState = LED_BLINK_SLOWLY;
367				if (pLed->bLedOn)
368					pLed->BlinkingLedState = LED_STATE_OFF;
369				else
370					pLed->BlinkingLedState = LED_STATE_ON;
371				mod_timer(&pLed->BlinkTimer, jiffies +
372					  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
373			}
374			pLed->BlinkTimes = 0;
375			pLed->bLedBlinkInProgress = false;
376		} else {
377			if (pLed->bLedOn)
378				pLed->BlinkingLedState = LED_STATE_OFF;
379			else
380				pLed->BlinkingLedState = LED_STATE_ON;
381			mod_timer(&pLed->BlinkTimer, jiffies +
382				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
383		}
384		break;
385	case LED_BLINK_WPS:
386		if (pLed->bLedOn)
387			pLed->BlinkingLedState = LED_STATE_OFF;
388		else
389			pLed->BlinkingLedState = LED_STATE_ON;
390		mod_timer(&pLed->BlinkTimer, jiffies +
391			  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
392		break;
393	case LED_BLINK_WPS_STOP:	/* WPS success */
394		if (pLed->BlinkingLedState == LED_STATE_ON) {
395			pLed->BlinkingLedState = LED_STATE_OFF;
396			mod_timer(&pLed->BlinkTimer, jiffies +
397				  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
398			bStopBlinking = false;
399		} else {
400			bStopBlinking = true;
401		}
402		if (bStopBlinking) {
403			pLed->bLedLinkBlinkInProgress = true;
404			pLed->CurrLedState = LED_BLINK_NORMAL;
405			if (pLed->bLedOn)
406				pLed->BlinkingLedState = LED_STATE_OFF;
407			else
408				pLed->BlinkingLedState = LED_STATE_ON;
409			mod_timer(&pLed->BlinkTimer, jiffies +
410				  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
411		}
412		pLed->bLedWPSBlinkInProgress = false;
413		break;
414	default:
415		break;
416	}
417}
418
419static void SwLedBlink2(struct LED_871x *pLed)
420{
421	struct _adapter *padapter = pLed->padapter;
422	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
423	u8 bStopBlinking = false;
424
425	/* Change LED according to BlinkingLedState specified. */
426	if (pLed->BlinkingLedState == LED_STATE_ON)
427		SwLedOn(padapter, pLed);
428	else
429		SwLedOff(padapter, pLed);
430	switch (pLed->CurrLedState) {
431	case LED_SCAN_BLINK:
432		pLed->BlinkTimes--;
433		if (pLed->BlinkTimes == 0)
434			bStopBlinking = true;
435		if (bStopBlinking) {
436			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
437				pLed->CurrLedState = LED_STATE_ON;
438				pLed->BlinkingLedState = LED_STATE_ON;
439				SwLedOn(padapter, pLed);
440			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
441				pLed->CurrLedState = LED_STATE_OFF;
442				pLed->BlinkingLedState = LED_STATE_OFF;
443				SwLedOff(padapter, pLed);
444			}
445			pLed->bLedScanBlinkInProgress = false;
446		} else {
447			if (pLed->bLedOn)
448				pLed->BlinkingLedState = LED_STATE_OFF;
449			else
450				pLed->BlinkingLedState = LED_STATE_ON;
451			mod_timer(&pLed->BlinkTimer, jiffies +
452				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
453		}
454		break;
455	case LED_TXRX_BLINK:
456		pLed->BlinkTimes--;
457		if (pLed->BlinkTimes == 0)
458			bStopBlinking = true;
459		if (bStopBlinking) {
460			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
461				pLed->CurrLedState = LED_STATE_ON;
462				pLed->BlinkingLedState = LED_STATE_ON;
463				SwLedOn(padapter, pLed);
464			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
465				pLed->CurrLedState = LED_STATE_OFF;
466				pLed->BlinkingLedState = LED_STATE_OFF;
467				SwLedOff(padapter, pLed);
468			}
469			pLed->bLedBlinkInProgress = false;
470		} else {
471			if (pLed->bLedOn)
472				pLed->BlinkingLedState = LED_STATE_OFF;
473			else
474				pLed->BlinkingLedState = LED_STATE_ON;
475			mod_timer(&pLed->BlinkTimer, jiffies +
476				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
477		}
478		break;
479	default:
480		break;
481	}
482}
483
484static void SwLedBlink3(struct LED_871x *pLed)
485{
486	struct _adapter *padapter = pLed->padapter;
487	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
488	u8 bStopBlinking = false;
489
490	/* Change LED according to BlinkingLedState specified. */
491	if (pLed->BlinkingLedState == LED_STATE_ON)
492		SwLedOn(padapter, pLed);
493	else
494		if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
495			SwLedOff(padapter, pLed);
496	switch (pLed->CurrLedState) {
497	case LED_SCAN_BLINK:
498		pLed->BlinkTimes--;
499		if (pLed->BlinkTimes == 0)
500			bStopBlinking = true;
501		if (bStopBlinking) {
502			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
503				pLed->CurrLedState = LED_STATE_ON;
504				pLed->BlinkingLedState = LED_STATE_ON;
505				if (!pLed->bLedOn)
506					SwLedOn(padapter, pLed);
507			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
508				pLed->CurrLedState = LED_STATE_OFF;
509				pLed->BlinkingLedState = LED_STATE_OFF;
510				if (pLed->bLedOn)
511					SwLedOff(padapter, pLed);
512			}
513			pLed->bLedScanBlinkInProgress = false;
514		} else {
515			if (pLed->bLedOn)
516				pLed->BlinkingLedState = LED_STATE_OFF;
517			else
518				pLed->BlinkingLedState = LED_STATE_ON;
519			mod_timer(&pLed->BlinkTimer, jiffies +
520				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
521		}
522		break;
523	case LED_TXRX_BLINK:
524		pLed->BlinkTimes--;
525		if (pLed->BlinkTimes == 0)
526			bStopBlinking = true;
527		if (bStopBlinking) {
528			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
529				pLed->CurrLedState = LED_STATE_ON;
530				pLed->BlinkingLedState = LED_STATE_ON;
531				if (!pLed->bLedOn)
532					SwLedOn(padapter, pLed);
533			} else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
534				pLed->CurrLedState = LED_STATE_OFF;
535				pLed->BlinkingLedState = LED_STATE_OFF;
536				if (pLed->bLedOn)
537					SwLedOff(padapter, pLed);
538			}
539			pLed->bLedBlinkInProgress = false;
540		} else {
541			if (pLed->bLedOn)
542				pLed->BlinkingLedState = LED_STATE_OFF;
543			else
544				pLed->BlinkingLedState = LED_STATE_ON;
545			mod_timer(&pLed->BlinkTimer, jiffies +
546				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
547		}
548		break;
549	case LED_BLINK_WPS:
550		if (pLed->bLedOn)
551			pLed->BlinkingLedState = LED_STATE_OFF;
552		else
553			pLed->BlinkingLedState = LED_STATE_ON;
554		mod_timer(&pLed->BlinkTimer, jiffies +
555			  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
556		break;
557	case LED_BLINK_WPS_STOP:	/*WPS success*/
558		if (pLed->BlinkingLedState == LED_STATE_ON) {
559			pLed->BlinkingLedState = LED_STATE_OFF;
560			mod_timer(&pLed->BlinkTimer, jiffies +
561				  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
562			bStopBlinking = false;
563		} else {
564			bStopBlinking = true;
565		}
566		if (bStopBlinking) {
567			pLed->CurrLedState = LED_STATE_ON;
568			pLed->BlinkingLedState = LED_STATE_ON;
569			SwLedOn(padapter, pLed);
570			pLed->bLedWPSBlinkInProgress = false;
571		}
572		break;
573	default:
574		break;
575	}
576}
577
578static void SwLedBlink4(struct LED_871x *pLed)
579{
580	struct _adapter *padapter = pLed->padapter;
581	struct led_priv	*ledpriv = &padapter->ledpriv;
582	struct LED_871x *pLed1 = &ledpriv->SwLed1;
583	u8 bStopBlinking = false;
584
585	/* Change LED according to BlinkingLedState specified. */
586	if (pLed->BlinkingLedState == LED_STATE_ON)
587		SwLedOn(padapter, pLed);
588	else
589		SwLedOff(padapter, pLed);
590	if (!pLed1->bLedWPSBlinkInProgress &&
591	    pLed1->BlinkingLedState == LED_UNKNOWN) {
592		pLed1->BlinkingLedState = LED_STATE_OFF;
593		pLed1->CurrLedState = LED_STATE_OFF;
594		SwLedOff(padapter, pLed1);
595	}
596	switch (pLed->CurrLedState) {
597	case LED_BLINK_SLOWLY:
598		if (pLed->bLedOn)
599			pLed->BlinkingLedState = LED_STATE_OFF;
600		else
601			pLed->BlinkingLedState = LED_STATE_ON;
602		mod_timer(&pLed->BlinkTimer, jiffies +
603			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
604		break;
605	case LED_BLINK_StartToBlink:
606		if (pLed->bLedOn) {
607			pLed->BlinkingLedState = LED_STATE_OFF;
608			mod_timer(&pLed->BlinkTimer, jiffies +
609				  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
610		} else {
611			pLed->BlinkingLedState = LED_STATE_ON;
612			mod_timer(&pLed->BlinkTimer, jiffies +
613				  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
614		}
615		break;
616	case LED_SCAN_BLINK:
617		pLed->BlinkTimes--;
618		if (pLed->BlinkTimes == 0)
619			bStopBlinking = true;
620		if (bStopBlinking) {
621			pLed->bLedNoLinkBlinkInProgress = true;
622			pLed->CurrLedState = LED_BLINK_SLOWLY;
623			if (pLed->bLedOn)
624				pLed->BlinkingLedState = LED_STATE_OFF;
625			else
626				pLed->BlinkingLedState = LED_STATE_ON;
627			mod_timer(&pLed->BlinkTimer, jiffies +
628				  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
629			pLed->bLedScanBlinkInProgress = false;
630		} else {
631			if (pLed->bLedOn)
632				pLed->BlinkingLedState = LED_STATE_OFF;
633			else
634				pLed->BlinkingLedState = LED_STATE_ON;
635			mod_timer(&pLed->BlinkTimer, jiffies +
636				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
637		}
638		break;
639	case LED_TXRX_BLINK:
640		pLed->BlinkTimes--;
641		if (pLed->BlinkTimes == 0)
642			bStopBlinking = true;
643		if (bStopBlinking) {
644			pLed->bLedNoLinkBlinkInProgress = true;
645			pLed->CurrLedState = LED_BLINK_SLOWLY;
646			if (pLed->bLedOn)
647				pLed->BlinkingLedState = LED_STATE_OFF;
648			else
649				pLed->BlinkingLedState = LED_STATE_ON;
650			mod_timer(&pLed->BlinkTimer, jiffies +
651				  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
652			pLed->bLedBlinkInProgress = false;
653		} else {
654			if (pLed->bLedOn)
655				pLed->BlinkingLedState = LED_STATE_OFF;
656			else
657				pLed->BlinkingLedState = LED_STATE_ON;
658			mod_timer(&pLed->BlinkTimer, jiffies +
659				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
660		}
661		break;
662	case LED_BLINK_WPS:
663		if (pLed->bLedOn) {
664			pLed->BlinkingLedState = LED_STATE_OFF;
665			mod_timer(&pLed->BlinkTimer, jiffies +
666				  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
667		} else {
668			pLed->BlinkingLedState = LED_STATE_ON;
669			mod_timer(&pLed->BlinkTimer, jiffies +
670				  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
671		}
672		break;
673	case LED_BLINK_WPS_STOP:	/*WPS authentication fail*/
674		if (pLed->bLedOn)
675			pLed->BlinkingLedState = LED_STATE_OFF;
676		else
677			pLed->BlinkingLedState = LED_STATE_ON;
678		mod_timer(&pLed->BlinkTimer, jiffies +
679			  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
680		break;
681	case LED_BLINK_WPS_STOP_OVERLAP:	/*WPS session overlap */
682		pLed->BlinkTimes--;
683		if (pLed->BlinkTimes == 0) {
684			if (pLed->bLedOn)
685				pLed->BlinkTimes = 1;
686			else
687				bStopBlinking = true;
688		}
689		if (bStopBlinking) {
690			pLed->BlinkTimes = 10;
691			pLed->BlinkingLedState = LED_STATE_ON;
692			mod_timer(&pLed->BlinkTimer, jiffies +
693				  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
694		} else {
695			if (pLed->bLedOn)
696				pLed->BlinkingLedState = LED_STATE_OFF;
697			else
698				pLed->BlinkingLedState = LED_STATE_ON;
699			mod_timer(&pLed->BlinkTimer, jiffies +
700				  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
701		}
702		break;
703	default:
704		break;
705	}
706}
707
708static void SwLedBlink5(struct LED_871x *pLed)
709{
710	struct _adapter *padapter = pLed->padapter;
711	u8 bStopBlinking = false;
712
713	/* Change LED according to BlinkingLedState specified. */
714	if (pLed->BlinkingLedState == LED_STATE_ON)
715		SwLedOn(padapter, pLed);
716	else
717		SwLedOff(padapter, pLed);
718	switch (pLed->CurrLedState) {
719	case LED_SCAN_BLINK:
720		pLed->BlinkTimes--;
721		if (pLed->BlinkTimes == 0)
722			bStopBlinking = true;
723		if (bStopBlinking) {
724			pLed->CurrLedState = LED_STATE_ON;
725			pLed->BlinkingLedState = LED_STATE_ON;
726			if (!pLed->bLedOn)
727				mod_timer(&pLed->BlinkTimer, jiffies +
728					  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
729			pLed->bLedScanBlinkInProgress = false;
730		} else {
731			if (pLed->bLedOn)
732				pLed->BlinkingLedState = LED_STATE_OFF;
733			else
734				pLed->BlinkingLedState = LED_STATE_ON;
735			mod_timer(&pLed->BlinkTimer, jiffies +
736				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
737		}
738		break;
739	case LED_TXRX_BLINK:
740		pLed->BlinkTimes--;
741		if (pLed->BlinkTimes == 0)
742			bStopBlinking = true;
743		if (bStopBlinking) {
744			pLed->CurrLedState = LED_STATE_ON;
745			pLed->BlinkingLedState = LED_STATE_ON;
746			if (!pLed->bLedOn)
747				mod_timer(&pLed->BlinkTimer, jiffies +
748					  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
749			pLed->bLedBlinkInProgress = false;
750		} else {
751			if (pLed->bLedOn)
752				pLed->BlinkingLedState = LED_STATE_OFF;
753			else
754				pLed->BlinkingLedState = LED_STATE_ON;
755			mod_timer(&pLed->BlinkTimer, jiffies +
756				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
757		}
758		break;
759	default:
760		break;
761	}
762}
763
764static void SwLedBlink6(struct LED_871x *pLed)
765{
766	struct _adapter *padapter = pLed->padapter;
767	u8 bStopBlinking = false;
768
769	/* Change LED according to BlinkingLedState specified. */
770	if (pLed->BlinkingLedState == LED_STATE_ON)
771		SwLedOn(padapter, pLed);
772	else
773		SwLedOff(padapter, pLed);
774	switch (pLed->CurrLedState) {
775	case LED_TXRX_BLINK:
776		pLed->BlinkTimes--;
777		if (pLed->BlinkTimes == 0)
778			bStopBlinking = true;
779		if (bStopBlinking) {
780			pLed->CurrLedState = LED_STATE_ON;
781			pLed->BlinkingLedState = LED_STATE_ON;
782			if (!pLed->bLedOn)
783				SwLedOn(padapter, pLed);
784			pLed->bLedBlinkInProgress = false;
785		} else {
786			if (pLed->bLedOn)
787				pLed->BlinkingLedState = LED_STATE_OFF;
788			else
789				pLed->BlinkingLedState = LED_STATE_ON;
790			mod_timer(&pLed->BlinkTimer, jiffies +
791				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
792		}
793		break;
794	case LED_BLINK_WPS:
795		if (pLed->bLedOn)
796			pLed->BlinkingLedState = LED_STATE_OFF;
797		else
798			pLed->BlinkingLedState = LED_STATE_ON;
799		mod_timer(&pLed->BlinkTimer, jiffies +
800			  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
801		break;
802
803	default:
804		break;
805	}
806}
807
808/*	Description:
809 *		Callback function of LED BlinkTimer,
810 *		it just schedules to corresponding BlinkWorkItem.
811 */
812static void BlinkTimerCallback(struct timer_list *t)
813{
814	struct LED_871x  *pLed = from_timer(pLed, t, BlinkTimer);
815
816	/* This fixed the crash problem on Fedora 12 when trying to do the
817	 * insmod;ifconfig up;rmmod commands.
818	 */
819	if (pLed->padapter->surprise_removed || pLed->padapter->driver_stopped)
820		return;
821	schedule_work(&pLed->BlinkWorkItem);
822}
823
824/*	Description:
825 *		Callback function of LED BlinkWorkItem.
826 *		We dispatch actual LED blink action according to LedStrategy.
827 */
828static void BlinkWorkItemCallback(struct work_struct *work)
829{
830	struct LED_871x *pLed = container_of(work, struct LED_871x,
831				BlinkWorkItem);
832	struct led_priv	*ledpriv = &pLed->padapter->ledpriv;
833
834	switch (ledpriv->LedStrategy) {
835	case SW_LED_MODE0:
836		SwLedBlink(pLed);
837		break;
838	case SW_LED_MODE1:
839		SwLedBlink1(pLed);
840		break;
841	case SW_LED_MODE2:
842		SwLedBlink2(pLed);
843		break;
844	case SW_LED_MODE3:
845		SwLedBlink3(pLed);
846		break;
847	case SW_LED_MODE4:
848		SwLedBlink4(pLed);
849		break;
850	case SW_LED_MODE5:
851		SwLedBlink5(pLed);
852		break;
853	case SW_LED_MODE6:
854		SwLedBlink6(pLed);
855		break;
856	default:
857		SwLedBlink(pLed);
858		break;
859	}
860}
861
862/*============================================================================
863 * Default LED behavior.
864 *============================================================================
865 *
866 *	Description:
867 *		Implement each led action for SW_LED_MODE0.
868 *		This is default strategy.
869 */
870
871static void SwLedControlMode1(struct _adapter *padapter,
872			      enum LED_CTL_MODE LedAction)
873{
874	struct led_priv *ledpriv = &padapter->ledpriv;
875	struct LED_871x *pLed = &ledpriv->SwLed0;
876	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
877	struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
878
879	if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
880		pLed = &ledpriv->SwLed1;
881	switch (LedAction) {
882	case LED_CTL_START_TO_LINK:
883	case LED_CTL_NO_LINK:
884		if (!pLed->bLedNoLinkBlinkInProgress) {
885			if (pLed->CurrLedState == LED_SCAN_BLINK ||
886			    IS_LED_WPS_BLINKING(pLed))
887				return;
888			if (pLed->bLedLinkBlinkInProgress) {
889				del_timer(&pLed->BlinkTimer);
890				pLed->bLedLinkBlinkInProgress = false;
891			}
892			if (pLed->bLedBlinkInProgress) {
893				del_timer(&pLed->BlinkTimer);
894				pLed->bLedBlinkInProgress = false;
895			}
896			pLed->bLedNoLinkBlinkInProgress = true;
897			pLed->CurrLedState = LED_BLINK_SLOWLY;
898			if (pLed->bLedOn)
899				pLed->BlinkingLedState = LED_STATE_OFF;
900			else
901				pLed->BlinkingLedState = LED_STATE_ON;
902			mod_timer(&pLed->BlinkTimer, jiffies +
903				  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
904		}
905		break;
906	case LED_CTL_LINK:
907		if (!pLed->bLedLinkBlinkInProgress) {
908			if (pLed->CurrLedState == LED_SCAN_BLINK ||
909			    IS_LED_WPS_BLINKING(pLed))
910				return;
911			if (pLed->bLedNoLinkBlinkInProgress) {
912				del_timer(&pLed->BlinkTimer);
913				pLed->bLedNoLinkBlinkInProgress = false;
914			}
915			if (pLed->bLedBlinkInProgress) {
916				del_timer(&pLed->BlinkTimer);
917				pLed->bLedBlinkInProgress = false;
918			}
919			pLed->bLedLinkBlinkInProgress = true;
920			pLed->CurrLedState = LED_BLINK_NORMAL;
921			if (pLed->bLedOn)
922				pLed->BlinkingLedState = LED_STATE_OFF;
923			else
924				pLed->BlinkingLedState = LED_STATE_ON;
925			mod_timer(&pLed->BlinkTimer, jiffies +
926				  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
927		}
928		break;
929	case LED_CTL_SITE_SURVEY:
930		if (psitesurveyctrl->traffic_busy &&
931		    check_fwstate(pmlmepriv, _FW_LINKED))
932			; /* dummy branch */
933		else if (!pLed->bLedScanBlinkInProgress) {
934			if (IS_LED_WPS_BLINKING(pLed))
935				return;
936			if (pLed->bLedNoLinkBlinkInProgress) {
937				del_timer(&pLed->BlinkTimer);
938				pLed->bLedNoLinkBlinkInProgress = false;
939			}
940			if (pLed->bLedLinkBlinkInProgress) {
941				del_timer(&pLed->BlinkTimer);
942				pLed->bLedLinkBlinkInProgress = false;
943			}
944			if (pLed->bLedBlinkInProgress) {
945				del_timer(&pLed->BlinkTimer);
946				pLed->bLedBlinkInProgress = false;
947			}
948			pLed->bLedScanBlinkInProgress = true;
949			pLed->CurrLedState = LED_SCAN_BLINK;
950			pLed->BlinkTimes = 24;
951			if (pLed->bLedOn)
952				pLed->BlinkingLedState = LED_STATE_OFF;
953			else
954				pLed->BlinkingLedState = LED_STATE_ON;
955			mod_timer(&pLed->BlinkTimer, jiffies +
956				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
957		}
958		break;
959	case LED_CTL_TX:
960	case LED_CTL_RX:
961		if (!pLed->bLedBlinkInProgress) {
962			if (pLed->CurrLedState == LED_SCAN_BLINK ||
963			    IS_LED_WPS_BLINKING(pLed))
964				return;
965			if (pLed->bLedNoLinkBlinkInProgress) {
966				del_timer(&pLed->BlinkTimer);
967				pLed->bLedNoLinkBlinkInProgress = false;
968			}
969			if (pLed->bLedLinkBlinkInProgress) {
970				del_timer(&pLed->BlinkTimer);
971				pLed->bLedLinkBlinkInProgress = false;
972			}
973			pLed->bLedBlinkInProgress = true;
974			pLed->CurrLedState = LED_TXRX_BLINK;
975			pLed->BlinkTimes = 2;
976			if (pLed->bLedOn)
977				pLed->BlinkingLedState = LED_STATE_OFF;
978			else
979				pLed->BlinkingLedState = LED_STATE_ON;
980			mod_timer(&pLed->BlinkTimer, jiffies +
981				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
982		}
983		break;
984
985	case LED_CTL_START_WPS: /*wait until xinpin finish */
986	case LED_CTL_START_WPS_BOTTON:
987		if (!pLed->bLedWPSBlinkInProgress) {
988			if (pLed->bLedNoLinkBlinkInProgress) {
989				del_timer(&pLed->BlinkTimer);
990				pLed->bLedNoLinkBlinkInProgress = false;
991			}
992			if (pLed->bLedLinkBlinkInProgress) {
993				del_timer(&pLed->BlinkTimer);
994				pLed->bLedLinkBlinkInProgress = false;
995			}
996			if (pLed->bLedBlinkInProgress) {
997				del_timer(&pLed->BlinkTimer);
998				pLed->bLedBlinkInProgress = false;
999			}
1000			if (pLed->bLedScanBlinkInProgress) {
1001				del_timer(&pLed->BlinkTimer);
1002				pLed->bLedScanBlinkInProgress = false;
1003			}
1004			pLed->bLedWPSBlinkInProgress = true;
1005			pLed->CurrLedState = LED_BLINK_WPS;
1006			if (pLed->bLedOn)
1007				pLed->BlinkingLedState = LED_STATE_OFF;
1008			else
1009				pLed->BlinkingLedState = LED_STATE_ON;
1010			mod_timer(&pLed->BlinkTimer, jiffies +
1011				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1012		}
1013		break;
1014	case LED_CTL_STOP_WPS:
1015		if (pLed->bLedNoLinkBlinkInProgress) {
1016			del_timer(&pLed->BlinkTimer);
1017			pLed->bLedNoLinkBlinkInProgress = false;
1018		}
1019		if (pLed->bLedLinkBlinkInProgress) {
1020			del_timer(&pLed->BlinkTimer);
1021			pLed->bLedLinkBlinkInProgress = false;
1022		}
1023		if (pLed->bLedBlinkInProgress) {
1024			del_timer(&pLed->BlinkTimer);
1025			pLed->bLedBlinkInProgress = false;
1026		}
1027		if (pLed->bLedScanBlinkInProgress) {
1028			del_timer(&pLed->BlinkTimer);
1029			pLed->bLedScanBlinkInProgress = false;
1030		}
1031		if (pLed->bLedWPSBlinkInProgress)
1032			del_timer(&pLed->BlinkTimer);
1033		else
1034			pLed->bLedWPSBlinkInProgress = true;
1035		pLed->CurrLedState = LED_BLINK_WPS_STOP;
1036		if (pLed->bLedOn) {
1037			pLed->BlinkingLedState = LED_STATE_OFF;
1038			mod_timer(&pLed->BlinkTimer, jiffies +
1039				  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
1040		} else {
1041			pLed->BlinkingLedState = LED_STATE_ON;
1042			mod_timer(&pLed->BlinkTimer,
1043				  jiffies + msecs_to_jiffies(0));
1044		}
1045		break;
1046	case LED_CTL_STOP_WPS_FAIL:
1047		if (pLed->bLedWPSBlinkInProgress) {
1048			del_timer(&pLed->BlinkTimer);
1049			pLed->bLedWPSBlinkInProgress = false;
1050		}
1051		pLed->bLedNoLinkBlinkInProgress = true;
1052		pLed->CurrLedState = LED_BLINK_SLOWLY;
1053		if (pLed->bLedOn)
1054			pLed->BlinkingLedState = LED_STATE_OFF;
1055		else
1056			pLed->BlinkingLedState = LED_STATE_ON;
1057		mod_timer(&pLed->BlinkTimer, jiffies +
1058			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1059		break;
1060	case LED_CTL_POWER_OFF:
1061		pLed->CurrLedState = LED_STATE_OFF;
1062		pLed->BlinkingLedState = LED_STATE_OFF;
1063		if (pLed->bLedNoLinkBlinkInProgress) {
1064			del_timer(&pLed->BlinkTimer);
1065			pLed->bLedNoLinkBlinkInProgress = false;
1066		}
1067		if (pLed->bLedLinkBlinkInProgress) {
1068			del_timer(&pLed->BlinkTimer);
1069			pLed->bLedLinkBlinkInProgress = false;
1070		}
1071		if (pLed->bLedBlinkInProgress) {
1072			del_timer(&pLed->BlinkTimer);
1073			pLed->bLedBlinkInProgress = false;
1074		}
1075		if (pLed->bLedWPSBlinkInProgress) {
1076			del_timer(&pLed->BlinkTimer);
1077			pLed->bLedWPSBlinkInProgress = false;
1078		}
1079		if (pLed->bLedScanBlinkInProgress) {
1080			del_timer(&pLed->BlinkTimer);
1081			pLed->bLedScanBlinkInProgress = false;
1082		}
1083		mod_timer(&pLed->BlinkTimer,
1084			  jiffies + msecs_to_jiffies(0));
1085		break;
1086	default:
1087		break;
1088	}
1089}
1090
1091static void SwLedControlMode2(struct _adapter *padapter,
1092			      enum LED_CTL_MODE LedAction)
1093{
1094	struct led_priv	 *ledpriv = &padapter->ledpriv;
1095	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1096	struct LED_871x *pLed = &ledpriv->SwLed0;
1097
1098	switch (LedAction) {
1099	case LED_CTL_SITE_SURVEY:
1100		if (pmlmepriv->sitesurveyctrl.traffic_busy)
1101			; /* dummy branch */
1102		else if (!pLed->bLedScanBlinkInProgress) {
1103			if (IS_LED_WPS_BLINKING(pLed))
1104				return;
1105
1106			if (pLed->bLedBlinkInProgress) {
1107				del_timer(&pLed->BlinkTimer);
1108				pLed->bLedBlinkInProgress = false;
1109			}
1110			pLed->bLedScanBlinkInProgress = true;
1111			pLed->CurrLedState = LED_SCAN_BLINK;
1112			pLed->BlinkTimes = 24;
1113			if (pLed->bLedOn)
1114				pLed->BlinkingLedState = LED_STATE_OFF;
1115			else
1116				pLed->BlinkingLedState = LED_STATE_ON;
1117			mod_timer(&pLed->BlinkTimer, jiffies +
1118				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1119		}
1120		break;
1121
1122	case LED_CTL_TX:
1123	case LED_CTL_RX:
1124		if (!pLed->bLedBlinkInProgress &&
1125		    check_fwstate(pmlmepriv, _FW_LINKED)) {
1126			if (pLed->CurrLedState == LED_SCAN_BLINK ||
1127			    IS_LED_WPS_BLINKING(pLed))
1128				return;
1129			pLed->bLedBlinkInProgress = true;
1130			pLed->CurrLedState = LED_TXRX_BLINK;
1131			pLed->BlinkTimes = 2;
1132			if (pLed->bLedOn)
1133				pLed->BlinkingLedState = LED_STATE_OFF;
1134			else
1135				pLed->BlinkingLedState = LED_STATE_ON;
1136			mod_timer(&pLed->BlinkTimer, jiffies +
1137				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1138		}
1139		break;
1140
1141	case LED_CTL_LINK:
1142		pLed->CurrLedState = LED_STATE_ON;
1143		pLed->BlinkingLedState = LED_STATE_ON;
1144		if (pLed->bLedBlinkInProgress) {
1145			del_timer(&pLed->BlinkTimer);
1146			pLed->bLedBlinkInProgress = false;
1147		}
1148		if (pLed->bLedScanBlinkInProgress) {
1149			del_timer(&pLed->BlinkTimer);
1150			pLed->bLedScanBlinkInProgress = false;
1151		}
1152
1153		mod_timer(&pLed->BlinkTimer,
1154			  jiffies + msecs_to_jiffies(0));
1155		break;
1156
1157	case LED_CTL_START_WPS: /*wait until xinpin finish*/
1158	case LED_CTL_START_WPS_BOTTON:
1159		if (!pLed->bLedWPSBlinkInProgress) {
1160			if (pLed->bLedBlinkInProgress) {
1161				del_timer(&pLed->BlinkTimer);
1162				pLed->bLedBlinkInProgress = false;
1163			}
1164			if (pLed->bLedScanBlinkInProgress) {
1165				del_timer(&pLed->BlinkTimer);
1166				pLed->bLedScanBlinkInProgress = false;
1167			}
1168			pLed->bLedWPSBlinkInProgress = true;
1169			pLed->CurrLedState = LED_STATE_ON;
1170			pLed->BlinkingLedState = LED_STATE_ON;
1171			mod_timer(&pLed->BlinkTimer,
1172				  jiffies + msecs_to_jiffies(0));
1173		}
1174		break;
1175
1176	case LED_CTL_STOP_WPS:
1177		pLed->bLedWPSBlinkInProgress = false;
1178		pLed->CurrLedState = LED_STATE_ON;
1179		pLed->BlinkingLedState = LED_STATE_ON;
1180		mod_timer(&pLed->BlinkTimer,
1181			  jiffies + msecs_to_jiffies(0));
1182		break;
1183
1184	case LED_CTL_STOP_WPS_FAIL:
1185		pLed->bLedWPSBlinkInProgress = false;
1186		pLed->CurrLedState = LED_STATE_OFF;
1187		pLed->BlinkingLedState = LED_STATE_OFF;
1188		mod_timer(&pLed->BlinkTimer,
1189			  jiffies + msecs_to_jiffies(0));
1190		break;
1191
1192	case LED_CTL_START_TO_LINK:
1193	case LED_CTL_NO_LINK:
1194		if (!IS_LED_BLINKING(pLed)) {
1195			pLed->CurrLedState = LED_STATE_OFF;
1196			pLed->BlinkingLedState = LED_STATE_OFF;
1197			mod_timer(&pLed->BlinkTimer,
1198				  jiffies + msecs_to_jiffies(0));
1199		}
1200		break;
1201	case LED_CTL_POWER_OFF:
1202		pLed->CurrLedState = LED_STATE_OFF;
1203		pLed->BlinkingLedState = LED_STATE_OFF;
1204		if (pLed->bLedBlinkInProgress) {
1205			del_timer(&pLed->BlinkTimer);
1206			pLed->bLedBlinkInProgress = false;
1207		}
1208		if (pLed->bLedScanBlinkInProgress) {
1209			del_timer(&pLed->BlinkTimer);
1210			pLed->bLedScanBlinkInProgress = false;
1211		}
1212		if (pLed->bLedWPSBlinkInProgress) {
1213			del_timer(&pLed->BlinkTimer);
1214			pLed->bLedWPSBlinkInProgress = false;
1215		}
1216		mod_timer(&pLed->BlinkTimer,
1217			  jiffies + msecs_to_jiffies(0));
1218		break;
1219	default:
1220		break;
1221	}
1222}
1223
1224static void SwLedControlMode3(struct _adapter *padapter,
1225			      enum LED_CTL_MODE LedAction)
1226{
1227	struct led_priv	*ledpriv = &padapter->ledpriv;
1228	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1229	struct LED_871x *pLed = &ledpriv->SwLed0;
1230
1231	switch (LedAction) {
1232	case LED_CTL_SITE_SURVEY:
1233		if (pmlmepriv->sitesurveyctrl.traffic_busy)
1234			; /* dummy branch */
1235		else if (!pLed->bLedScanBlinkInProgress) {
1236			if (IS_LED_WPS_BLINKING(pLed))
1237				return;
1238			if (pLed->bLedBlinkInProgress) {
1239				del_timer(&pLed->BlinkTimer);
1240				pLed->bLedBlinkInProgress = false;
1241			}
1242			pLed->bLedScanBlinkInProgress = true;
1243			pLed->CurrLedState = LED_SCAN_BLINK;
1244			pLed->BlinkTimes = 24;
1245			if (pLed->bLedOn)
1246				pLed->BlinkingLedState = LED_STATE_OFF;
1247			else
1248				pLed->BlinkingLedState = LED_STATE_ON;
1249			mod_timer(&pLed->BlinkTimer, jiffies +
1250				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1251		}
1252		break;
1253	case LED_CTL_TX:
1254	case LED_CTL_RX:
1255		if (!pLed->bLedBlinkInProgress &&
1256		    check_fwstate(pmlmepriv, _FW_LINKED)) {
1257			if (pLed->CurrLedState == LED_SCAN_BLINK ||
1258			    IS_LED_WPS_BLINKING(pLed))
1259				return;
1260			pLed->bLedBlinkInProgress = true;
1261			pLed->CurrLedState = LED_TXRX_BLINK;
1262			pLed->BlinkTimes = 2;
1263			if (pLed->bLedOn)
1264				pLed->BlinkingLedState = LED_STATE_OFF;
1265			else
1266				pLed->BlinkingLedState = LED_STATE_ON;
1267			mod_timer(&pLed->BlinkTimer, jiffies +
1268				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1269		}
1270		break;
1271	case LED_CTL_LINK:
1272		if (IS_LED_WPS_BLINKING(pLed))
1273			return;
1274		pLed->CurrLedState = LED_STATE_ON;
1275		pLed->BlinkingLedState = LED_STATE_ON;
1276		if (pLed->bLedBlinkInProgress) {
1277			del_timer(&pLed->BlinkTimer);
1278			pLed->bLedBlinkInProgress = false;
1279		}
1280		if (pLed->bLedScanBlinkInProgress) {
1281			del_timer(&pLed->BlinkTimer);
1282			pLed->bLedScanBlinkInProgress = false;
1283		}
1284		mod_timer(&pLed->BlinkTimer,
1285			  jiffies + msecs_to_jiffies(0));
1286		break;
1287	case LED_CTL_START_WPS: /* wait until xinpin finish */
1288	case LED_CTL_START_WPS_BOTTON:
1289		if (!pLed->bLedWPSBlinkInProgress) {
1290			if (pLed->bLedBlinkInProgress) {
1291				del_timer(&pLed->BlinkTimer);
1292				pLed->bLedBlinkInProgress = false;
1293			}
1294			if (pLed->bLedScanBlinkInProgress) {
1295				del_timer(&pLed->BlinkTimer);
1296				pLed->bLedScanBlinkInProgress = false;
1297			}
1298			pLed->bLedWPSBlinkInProgress = true;
1299			pLed->CurrLedState = LED_BLINK_WPS;
1300			if (pLed->bLedOn)
1301				pLed->BlinkingLedState = LED_STATE_OFF;
1302			else
1303				pLed->BlinkingLedState = LED_STATE_ON;
1304			mod_timer(&pLed->BlinkTimer, jiffies +
1305				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1306		}
1307		break;
1308	case LED_CTL_STOP_WPS:
1309		if (pLed->bLedWPSBlinkInProgress) {
1310			del_timer(&pLed->BlinkTimer);
1311			pLed->bLedWPSBlinkInProgress = false;
1312		} else {
1313			pLed->bLedWPSBlinkInProgress = true;
1314		}
1315		pLed->CurrLedState = LED_BLINK_WPS_STOP;
1316		if (pLed->bLedOn) {
1317			pLed->BlinkingLedState = LED_STATE_OFF;
1318			mod_timer(&pLed->BlinkTimer, jiffies +
1319				  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
1320		} else {
1321			pLed->BlinkingLedState = LED_STATE_ON;
1322			mod_timer(&pLed->BlinkTimer,
1323				  jiffies + msecs_to_jiffies(0));
1324		}
1325		break;
1326	case LED_CTL_STOP_WPS_FAIL:
1327		if (pLed->bLedWPSBlinkInProgress) {
1328			del_timer(&pLed->BlinkTimer);
1329			pLed->bLedWPSBlinkInProgress = false;
1330		}
1331		pLed->CurrLedState = LED_STATE_OFF;
1332		pLed->BlinkingLedState = LED_STATE_OFF;
1333		mod_timer(&pLed->BlinkTimer,
1334			  jiffies + msecs_to_jiffies(0));
1335		break;
1336	case LED_CTL_START_TO_LINK:
1337	case LED_CTL_NO_LINK:
1338		if (!IS_LED_BLINKING(pLed)) {
1339			pLed->CurrLedState = LED_STATE_OFF;
1340			pLed->BlinkingLedState = LED_STATE_OFF;
1341			mod_timer(&pLed->BlinkTimer,
1342				  jiffies + msecs_to_jiffies(0));
1343		}
1344		break;
1345	case LED_CTL_POWER_OFF:
1346		pLed->CurrLedState = LED_STATE_OFF;
1347		pLed->BlinkingLedState = LED_STATE_OFF;
1348		if (pLed->bLedBlinkInProgress) {
1349			del_timer(&pLed->BlinkTimer);
1350			pLed->bLedBlinkInProgress = false;
1351		}
1352		if (pLed->bLedScanBlinkInProgress) {
1353			del_timer(&pLed->BlinkTimer);
1354			pLed->bLedScanBlinkInProgress = false;
1355		}
1356		if (pLed->bLedWPSBlinkInProgress) {
1357			del_timer(&pLed->BlinkTimer);
1358			pLed->bLedWPSBlinkInProgress = false;
1359		}
1360		mod_timer(&pLed->BlinkTimer,
1361			  jiffies + msecs_to_jiffies(0));
1362		break;
1363	default:
1364		break;
1365	}
1366}
1367
1368static void SwLedControlMode4(struct _adapter *padapter,
1369			      enum LED_CTL_MODE LedAction)
1370{
1371	struct led_priv	*ledpriv = &padapter->ledpriv;
1372	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1373	struct LED_871x *pLed = &ledpriv->SwLed0;
1374	struct LED_871x *pLed1 = &ledpriv->SwLed1;
1375
1376	switch (LedAction) {
1377	case LED_CTL_START_TO_LINK:
1378		if (pLed1->bLedWPSBlinkInProgress) {
1379			pLed1->bLedWPSBlinkInProgress = false;
1380			del_timer(&pLed1->BlinkTimer);
1381			pLed1->BlinkingLedState = LED_STATE_OFF;
1382			pLed1->CurrLedState = LED_STATE_OFF;
1383			if (pLed1->bLedOn)
1384				mod_timer(&pLed->BlinkTimer,
1385					  jiffies + msecs_to_jiffies(0));
1386		}
1387		if (!pLed->bLedStartToLinkBlinkInProgress) {
1388			if (pLed->CurrLedState == LED_SCAN_BLINK ||
1389			    IS_LED_WPS_BLINKING(pLed))
1390				return;
1391			if (pLed->bLedBlinkInProgress) {
1392				del_timer(&pLed->BlinkTimer);
1393				pLed->bLedBlinkInProgress = false;
1394			}
1395			if (pLed->bLedNoLinkBlinkInProgress) {
1396				del_timer(&pLed->BlinkTimer);
1397				pLed->bLedNoLinkBlinkInProgress = false;
1398			}
1399			pLed->bLedStartToLinkBlinkInProgress = true;
1400			pLed->CurrLedState = LED_BLINK_StartToBlink;
1401			if (pLed->bLedOn) {
1402				pLed->BlinkingLedState = LED_STATE_OFF;
1403				mod_timer(&pLed->BlinkTimer, jiffies +
1404					  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1405			} else {
1406				pLed->BlinkingLedState = LED_STATE_ON;
1407				mod_timer(&pLed->BlinkTimer, jiffies +
1408					  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1409			}
1410		}
1411		break;
1412	case LED_CTL_LINK:
1413	case LED_CTL_NO_LINK:
1414		/*LED1 settings*/
1415		if (LedAction == LED_CTL_LINK) {
1416			if (pLed1->bLedWPSBlinkInProgress) {
1417				pLed1->bLedWPSBlinkInProgress = false;
1418				del_timer(&pLed1->BlinkTimer);
1419				pLed1->BlinkingLedState = LED_STATE_OFF;
1420				pLed1->CurrLedState = LED_STATE_OFF;
1421				if (pLed1->bLedOn)
1422					mod_timer(&pLed->BlinkTimer,
1423						  jiffies + msecs_to_jiffies(0));
1424			}
1425		}
1426		if (!pLed->bLedNoLinkBlinkInProgress) {
1427			if (pLed->CurrLedState == LED_SCAN_BLINK ||
1428			    IS_LED_WPS_BLINKING(pLed))
1429				return;
1430			if (pLed->bLedBlinkInProgress) {
1431				del_timer(&pLed->BlinkTimer);
1432				pLed->bLedBlinkInProgress = false;
1433			}
1434			pLed->bLedNoLinkBlinkInProgress = true;
1435			pLed->CurrLedState = LED_BLINK_SLOWLY;
1436			if (pLed->bLedOn)
1437				pLed->BlinkingLedState = LED_STATE_OFF;
1438			else
1439				pLed->BlinkingLedState = LED_STATE_ON;
1440			mod_timer(&pLed->BlinkTimer, jiffies +
1441				  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1442		}
1443		break;
1444	case LED_CTL_SITE_SURVEY:
1445		if (pmlmepriv->sitesurveyctrl.traffic_busy &&
1446		    check_fwstate(pmlmepriv, _FW_LINKED))
1447			;
1448		else if (!pLed->bLedScanBlinkInProgress) {
1449			if (IS_LED_WPS_BLINKING(pLed))
1450				return;
1451			if (pLed->bLedNoLinkBlinkInProgress) {
1452				del_timer(&pLed->BlinkTimer);
1453				pLed->bLedNoLinkBlinkInProgress = false;
1454			}
1455			if (pLed->bLedBlinkInProgress) {
1456				del_timer(&pLed->BlinkTimer);
1457				pLed->bLedBlinkInProgress = false;
1458			}
1459			pLed->bLedScanBlinkInProgress = true;
1460			pLed->CurrLedState = LED_SCAN_BLINK;
1461			pLed->BlinkTimes = 24;
1462			if (pLed->bLedOn)
1463				pLed->BlinkingLedState = LED_STATE_OFF;
1464			else
1465				pLed->BlinkingLedState = LED_STATE_ON;
1466			mod_timer(&pLed->BlinkTimer, jiffies +
1467				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1468		}
1469		break;
1470	case LED_CTL_TX:
1471	case LED_CTL_RX:
1472		if (!pLed->bLedBlinkInProgress) {
1473			if (pLed->CurrLedState == LED_SCAN_BLINK ||
1474			    IS_LED_WPS_BLINKING(pLed))
1475				return;
1476			if (pLed->bLedNoLinkBlinkInProgress) {
1477				del_timer(&pLed->BlinkTimer);
1478				pLed->bLedNoLinkBlinkInProgress = false;
1479			}
1480			pLed->bLedBlinkInProgress = true;
1481			pLed->CurrLedState = LED_TXRX_BLINK;
1482			pLed->BlinkTimes = 2;
1483			if (pLed->bLedOn)
1484				pLed->BlinkingLedState = LED_STATE_OFF;
1485			else
1486				pLed->BlinkingLedState = LED_STATE_ON;
1487			mod_timer(&pLed->BlinkTimer, jiffies +
1488				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1489		}
1490		break;
1491	case LED_CTL_START_WPS: /*wait until xinpin finish*/
1492	case LED_CTL_START_WPS_BOTTON:
1493		if (pLed1->bLedWPSBlinkInProgress) {
1494			pLed1->bLedWPSBlinkInProgress = false;
1495			del_timer(&pLed1->BlinkTimer);
1496			pLed1->BlinkingLedState = LED_STATE_OFF;
1497			pLed1->CurrLedState = LED_STATE_OFF;
1498			if (pLed1->bLedOn)
1499				mod_timer(&pLed->BlinkTimer,
1500					  jiffies + msecs_to_jiffies(0));
1501		}
1502		if (!pLed->bLedWPSBlinkInProgress) {
1503			if (pLed->bLedNoLinkBlinkInProgress) {
1504				del_timer(&pLed->BlinkTimer);
1505				pLed->bLedNoLinkBlinkInProgress = false;
1506			}
1507			if (pLed->bLedBlinkInProgress) {
1508				del_timer(&pLed->BlinkTimer);
1509				pLed->bLedBlinkInProgress = false;
1510			}
1511			if (pLed->bLedScanBlinkInProgress) {
1512				del_timer(&pLed->BlinkTimer);
1513				pLed->bLedScanBlinkInProgress = false;
1514			}
1515			pLed->bLedWPSBlinkInProgress = true;
1516			pLed->CurrLedState = LED_BLINK_WPS;
1517			if (pLed->bLedOn) {
1518				pLed->BlinkingLedState = LED_STATE_OFF;
1519				mod_timer(&pLed->BlinkTimer, jiffies +
1520					  msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1521			} else {
1522				pLed->BlinkingLedState = LED_STATE_ON;
1523				mod_timer(&pLed->BlinkTimer, jiffies +
1524					  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1525			}
1526		}
1527		break;
1528	case LED_CTL_STOP_WPS:	/*WPS connect success*/
1529		if (pLed->bLedWPSBlinkInProgress) {
1530			del_timer(&pLed->BlinkTimer);
1531			pLed->bLedWPSBlinkInProgress = false;
1532		}
1533		pLed->bLedNoLinkBlinkInProgress = true;
1534		pLed->CurrLedState = LED_BLINK_SLOWLY;
1535		if (pLed->bLedOn)
1536			pLed->BlinkingLedState = LED_STATE_OFF;
1537		else
1538			pLed->BlinkingLedState = LED_STATE_ON;
1539		mod_timer(&pLed->BlinkTimer, jiffies +
1540			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1541		break;
1542	case LED_CTL_STOP_WPS_FAIL:	/*WPS authentication fail*/
1543		if (pLed->bLedWPSBlinkInProgress) {
1544			del_timer(&pLed->BlinkTimer);
1545			pLed->bLedWPSBlinkInProgress = false;
1546		}
1547		pLed->bLedNoLinkBlinkInProgress = true;
1548		pLed->CurrLedState = LED_BLINK_SLOWLY;
1549		if (pLed->bLedOn)
1550			pLed->BlinkingLedState = LED_STATE_OFF;
1551		else
1552			pLed->BlinkingLedState = LED_STATE_ON;
1553		mod_timer(&pLed->BlinkTimer, jiffies +
1554			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1555		/*LED1 settings*/
1556		if (pLed1->bLedWPSBlinkInProgress)
1557			del_timer(&pLed1->BlinkTimer);
1558		else
1559			pLed1->bLedWPSBlinkInProgress = true;
1560		pLed1->CurrLedState = LED_BLINK_WPS_STOP;
1561		if (pLed1->bLedOn)
1562			pLed1->BlinkingLedState = LED_STATE_OFF;
1563		else
1564			pLed1->BlinkingLedState = LED_STATE_ON;
1565		mod_timer(&pLed->BlinkTimer, jiffies +
1566			  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1567		break;
1568	case LED_CTL_STOP_WPS_FAIL_OVERLAP:	/*WPS session overlap*/
1569		if (pLed->bLedWPSBlinkInProgress) {
1570			del_timer(&pLed->BlinkTimer);
1571			pLed->bLedWPSBlinkInProgress = false;
1572		}
1573		pLed->bLedNoLinkBlinkInProgress = true;
1574		pLed->CurrLedState = LED_BLINK_SLOWLY;
1575		if (pLed->bLedOn)
1576			pLed->BlinkingLedState = LED_STATE_OFF;
1577		else
1578			pLed->BlinkingLedState = LED_STATE_ON;
1579		mod_timer(&pLed->BlinkTimer, jiffies +
1580			  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1581		/*LED1 settings*/
1582		if (pLed1->bLedWPSBlinkInProgress)
1583			del_timer(&pLed1->BlinkTimer);
1584		else
1585			pLed1->bLedWPSBlinkInProgress = true;
1586		pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
1587		pLed1->BlinkTimes = 10;
1588		if (pLed1->bLedOn)
1589			pLed1->BlinkingLedState = LED_STATE_OFF;
1590		else
1591			pLed1->BlinkingLedState = LED_STATE_ON;
1592		mod_timer(&pLed->BlinkTimer, jiffies +
1593			  msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1594		break;
1595	case LED_CTL_POWER_OFF:
1596		pLed->CurrLedState = LED_STATE_OFF;
1597		pLed->BlinkingLedState = LED_STATE_OFF;
1598		if (pLed->bLedNoLinkBlinkInProgress) {
1599			del_timer(&pLed->BlinkTimer);
1600			pLed->bLedNoLinkBlinkInProgress = false;
1601		}
1602		if (pLed->bLedLinkBlinkInProgress) {
1603			del_timer(&pLed->BlinkTimer);
1604			pLed->bLedLinkBlinkInProgress = false;
1605		}
1606		if (pLed->bLedBlinkInProgress) {
1607			del_timer(&pLed->BlinkTimer);
1608			pLed->bLedBlinkInProgress = false;
1609		}
1610		if (pLed->bLedWPSBlinkInProgress) {
1611			del_timer(&pLed->BlinkTimer);
1612			pLed->bLedWPSBlinkInProgress = false;
1613		}
1614		if (pLed->bLedScanBlinkInProgress) {
1615			del_timer(&pLed->BlinkTimer);
1616			pLed->bLedScanBlinkInProgress = false;
1617		}
1618		if (pLed->bLedStartToLinkBlinkInProgress) {
1619			del_timer(&pLed->BlinkTimer);
1620			pLed->bLedStartToLinkBlinkInProgress = false;
1621		}
1622		if (pLed1->bLedWPSBlinkInProgress) {
1623			del_timer(&pLed1->BlinkTimer);
1624			pLed1->bLedWPSBlinkInProgress = false;
1625		}
1626		pLed1->BlinkingLedState = LED_UNKNOWN;
1627		SwLedOff(padapter, pLed);
1628		SwLedOff(padapter, pLed1);
1629		break;
1630	default:
1631		break;
1632	}
1633}
1634
1635static void SwLedControlMode5(struct _adapter *padapter,
1636			      enum LED_CTL_MODE LedAction)
1637{
1638	struct led_priv	*ledpriv = &padapter->ledpriv;
1639	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1640	struct LED_871x *pLed = &ledpriv->SwLed0;
1641
1642	if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
1643		pLed = &ledpriv->SwLed1;
1644
1645	switch (LedAction) {
1646	case LED_CTL_POWER_ON:
1647	case LED_CTL_NO_LINK:
1648	case LED_CTL_LINK:	/* solid blue */
1649		if (pLed->CurrLedState == LED_SCAN_BLINK)
1650			return;
1651		pLed->CurrLedState = LED_STATE_ON;
1652		pLed->BlinkingLedState = LED_STATE_ON;
1653		pLed->bLedBlinkInProgress = false;
1654		mod_timer(&pLed->BlinkTimer,
1655			  jiffies + msecs_to_jiffies(0));
1656		break;
1657	case LED_CTL_SITE_SURVEY:
1658		if (pmlmepriv->sitesurveyctrl.traffic_busy &&
1659		    check_fwstate(pmlmepriv, _FW_LINKED))
1660			; /* dummy branch */
1661		else if (!pLed->bLedScanBlinkInProgress) {
1662			if (pLed->bLedBlinkInProgress) {
1663				del_timer(&pLed->BlinkTimer);
1664				pLed->bLedBlinkInProgress = false;
1665			}
1666			pLed->bLedScanBlinkInProgress = true;
1667			pLed->CurrLedState = LED_SCAN_BLINK;
1668			pLed->BlinkTimes = 24;
1669			if (pLed->bLedOn)
1670				pLed->BlinkingLedState = LED_STATE_OFF;
1671			else
1672				pLed->BlinkingLedState = LED_STATE_ON;
1673			mod_timer(&pLed->BlinkTimer, jiffies +
1674				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1675		}
1676		break;
1677	case LED_CTL_TX:
1678	case LED_CTL_RX:
1679		if (!pLed->bLedBlinkInProgress) {
1680			if (pLed->CurrLedState == LED_SCAN_BLINK)
1681				return;
1682			pLed->bLedBlinkInProgress = true;
1683			pLed->CurrLedState = LED_TXRX_BLINK;
1684			pLed->BlinkTimes = 2;
1685			if (pLed->bLedOn)
1686				pLed->BlinkingLedState = LED_STATE_OFF;
1687			else
1688				pLed->BlinkingLedState = LED_STATE_ON;
1689			mod_timer(&pLed->BlinkTimer, jiffies +
1690				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1691		}
1692		break;
1693	case LED_CTL_POWER_OFF:
1694		pLed->CurrLedState = LED_STATE_OFF;
1695		pLed->BlinkingLedState = LED_STATE_OFF;
1696		if (pLed->bLedBlinkInProgress) {
1697			del_timer(&pLed->BlinkTimer);
1698			pLed->bLedBlinkInProgress = false;
1699		}
1700		SwLedOff(padapter, pLed);
1701		break;
1702	default:
1703		break;
1704	}
1705}
1706
1707static void SwLedControlMode6(struct _adapter *padapter,
1708			      enum LED_CTL_MODE LedAction)
1709{
1710	struct led_priv	*ledpriv = &padapter->ledpriv;
1711	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1712	struct LED_871x *pLed = &ledpriv->SwLed0;
1713
1714	switch (LedAction) {
1715	case LED_CTL_POWER_ON:
1716	case LED_CTL_NO_LINK:
1717	case LED_CTL_LINK:	/*solid blue*/
1718	case LED_CTL_SITE_SURVEY:
1719		if (IS_LED_WPS_BLINKING(pLed))
1720			return;
1721		pLed->CurrLedState = LED_STATE_ON;
1722		pLed->BlinkingLedState = LED_STATE_ON;
1723		pLed->bLedBlinkInProgress = false;
1724		mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0));
1725		break;
1726	case LED_CTL_TX:
1727	case LED_CTL_RX:
1728		if (!pLed->bLedBlinkInProgress &&
1729		    check_fwstate(pmlmepriv, _FW_LINKED)) {
1730			if (IS_LED_WPS_BLINKING(pLed))
1731				return;
1732			pLed->bLedBlinkInProgress = true;
1733			pLed->CurrLedState = LED_TXRX_BLINK;
1734			pLed->BlinkTimes = 2;
1735			if (pLed->bLedOn)
1736				pLed->BlinkingLedState = LED_STATE_OFF;
1737			else
1738				pLed->BlinkingLedState = LED_STATE_ON;
1739			mod_timer(&pLed->BlinkTimer, jiffies +
1740				  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1741		}
1742		break;
1743	case LED_CTL_START_WPS: /*wait until xinpin finish*/
1744	case LED_CTL_START_WPS_BOTTON:
1745		if (!pLed->bLedWPSBlinkInProgress) {
1746			if (pLed->bLedBlinkInProgress) {
1747				del_timer(&pLed->BlinkTimer);
1748				pLed->bLedBlinkInProgress = false;
1749			}
1750			pLed->bLedWPSBlinkInProgress = true;
1751			pLed->CurrLedState = LED_BLINK_WPS;
1752			if (pLed->bLedOn)
1753				pLed->BlinkingLedState = LED_STATE_OFF;
1754			else
1755				pLed->BlinkingLedState = LED_STATE_ON;
1756			mod_timer(&pLed->BlinkTimer, jiffies +
1757				  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1758		}
1759		break;
1760	case LED_CTL_STOP_WPS_FAIL:
1761	case LED_CTL_STOP_WPS:
1762		if (pLed->bLedWPSBlinkInProgress) {
1763			del_timer(&pLed->BlinkTimer);
1764			pLed->bLedWPSBlinkInProgress = false;
1765		}
1766		pLed->CurrLedState = LED_STATE_ON;
1767		pLed->BlinkingLedState = LED_STATE_ON;
1768		mod_timer(&pLed->BlinkTimer,
1769			  jiffies + msecs_to_jiffies(0));
1770		break;
1771	case LED_CTL_POWER_OFF:
1772		pLed->CurrLedState = LED_STATE_OFF;
1773		pLed->BlinkingLedState = LED_STATE_OFF;
1774		if (pLed->bLedBlinkInProgress) {
1775			del_timer(&pLed->BlinkTimer);
1776			pLed->bLedBlinkInProgress = false;
1777		}
1778		if (pLed->bLedWPSBlinkInProgress) {
1779			del_timer(&pLed->BlinkTimer);
1780			pLed->bLedWPSBlinkInProgress = false;
1781		}
1782		SwLedOff(padapter, pLed);
1783		break;
1784	default:
1785		break;
1786	}
1787}
1788
1789/*	Description:
1790 *		Dispatch LED action according to pHalData->LedStrategy.
1791 */
1792void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
1793{
1794	struct led_priv	*ledpriv = &padapter->ledpriv;
1795
1796	if (!ledpriv->bRegUseLed)
1797		return;
1798	switch (ledpriv->LedStrategy) {
1799	case SW_LED_MODE0:
1800		break;
1801	case SW_LED_MODE1:
1802		SwLedControlMode1(padapter, LedAction);
1803		break;
1804	case SW_LED_MODE2:
1805		SwLedControlMode2(padapter, LedAction);
1806		break;
1807	case SW_LED_MODE3:
1808		SwLedControlMode3(padapter, LedAction);
1809		break;
1810	case SW_LED_MODE4:
1811		SwLedControlMode4(padapter, LedAction);
1812		break;
1813	case SW_LED_MODE5:
1814		SwLedControlMode5(padapter, LedAction);
1815		break;
1816	case SW_LED_MODE6:
1817		SwLedControlMode6(padapter, LedAction);
1818		break;
1819	default:
1820		break;
1821	}
1822}
1823
1824void r8712_flush_led_works(struct _adapter *padapter)
1825{
1826	struct led_priv *pledpriv = &padapter->ledpriv;
1827
1828	flush_work(&pledpriv->SwLed0.BlinkWorkItem);
1829	flush_work(&pledpriv->SwLed1.BlinkWorkItem);
1830}
1831