iwl-led.c revision 759ef89fb096c4a6ef078d3cfd5682ac037bd789
1ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/******************************************************************************
2ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
3ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
4ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
5ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * This program is free software; you can redistribute it and/or modify it
6ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * under the terms of version 2 of the GNU General Public License as
7ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * published by the Free Software Foundation.
8ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
9ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * This program is distributed in the hope that it will be useful, but WITHOUT
10ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * more details.
13ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
14ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * You should have received a copy of the GNU General Public License along with
15ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * this program; if not, write to the Free Software Foundation, Inc.,
16ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
18ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * The full GNU General Public License is included in this distribution in the
19ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * file called LICENSE.
20ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
21ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * Contact Information:
22759ef89fb096c4a6ef078d3cfd5682ac037bd789Winkler, Tomas *  Intel Linux Wireless <ilw@linux.intel.com>
23ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *
25ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas *****************************************************************************/
26ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
27ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
28ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/kernel.h>
29ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/module.h>
30ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/init.h>
31ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/pci.h>
32ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/dma-mapping.h>
33ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/delay.h>
34ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/skbuff.h>
35ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/netdevice.h>
36ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/wireless.h>
37ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <net/mac80211.h>
38ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <linux/etherdevice.h>
39ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include <asm/unaligned.h>
40ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
413e0d4cb12f6fd97193a455b49125398b2231c87cTomas Winkler#include "iwl-dev.h"
42ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include "iwl-core.h"
43fee1247a30e5b3d48fe985b4a935eb6818f3b464Tomas Winkler#include "iwl-io.h"
44ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#include "iwl-helpers.h"
45ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
460eee612731e133604023bfa8d20047e98160845eTomas Winkler#ifdef CONFIG_IWLWIFI_DEBUG
470eee612731e133604023bfa8d20047e98160845eTomas Winklerstatic const char *led_type_str[] = {
480eee612731e133604023bfa8d20047e98160845eTomas Winkler	__stringify(IWL_LED_TRG_TX),
490eee612731e133604023bfa8d20047e98160845eTomas Winkler	__stringify(IWL_LED_TRG_RX),
500eee612731e133604023bfa8d20047e98160845eTomas Winkler	__stringify(IWL_LED_TRG_ASSOC),
510eee612731e133604023bfa8d20047e98160845eTomas Winkler	__stringify(IWL_LED_TRG_RADIO),
520eee612731e133604023bfa8d20047e98160845eTomas Winkler	NULL
530eee612731e133604023bfa8d20047e98160845eTomas Winkler};
540eee612731e133604023bfa8d20047e98160845eTomas Winkler#endif /* CONFIG_IWLWIFI_DEBUG */
550eee612731e133604023bfa8d20047e98160845eTomas Winkler
560eee612731e133604023bfa8d20047e98160845eTomas Winkler
57ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasstatic const struct {
58ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	u16 tpt;
59ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	u8 on_time;
600eee612731e133604023bfa8d20047e98160845eTomas Winkler	u8 off_time;
61ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas} blink_tbl[] =
62ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
63ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{300, 25, 25},
64ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{200, 40, 40},
65ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{100, 55, 55},
66ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{70, 65, 65},
67ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{50, 75, 75},
68ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{20, 85, 85},
69ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{15, 95, 95 },
70ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{10, 110, 110},
71ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	{5, 130, 130},
72ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	{0, 167, 167},
73ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler/* SOLID_ON */
74ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	{-1, IWL_LED_SOLID, 0}
75ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas};
76ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
77ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler#define IWL_1MB_RATE (128 * 1024)
78ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler#define IWL_LED_THRESHOLD (16)
79ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
80ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
81ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler
82ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler/*  [0-256] -> [0..8] FIXME: we need [0..10] */
83ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winklerstatic inline int iwl_brightness_to_idx(enum led_brightness brightness)
84ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
85ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	return fls(0x000000FF & (u32)brightness);
86ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
87ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
88ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Send led command */
89ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winklerstatic int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
90ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
91ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	struct iwl_host_cmd cmd = {
92ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.id = REPLY_LEDS_CMD,
93ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.len = sizeof(struct iwl_led_cmd),
94ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.data = led_cmd,
95ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.meta.flags = CMD_ASYNC,
96ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.meta.u.callback = NULL,
97ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	};
98ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	u32 reg;
99ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
1003395f6e9cf48469d7ee05703cad1502002741c16Tomas Winkler	reg = iwl_read32(priv, CSR_LED_REG);
101ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
1023395f6e9cf48469d7ee05703cad1502002741c16Tomas Winkler		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
103ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
104ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return iwl_send_cmd(priv, &cmd);
105ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
106ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
107ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler/* Set led pattern command */
1083eb2011a67b044859069359948579b942993c416Abhijeet Kolekarstatic int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
1093eb2011a67b044859069359948579b942993c416Abhijeet Kolekar			       unsigned int idx)
110ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
111ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	struct iwl_led_cmd led_cmd = {
112ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.id = led_id,
113ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.interval = IWL_DEF_LED_INTRVL
114ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	};
115ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
116ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	BUG_ON(idx > IWL_MAX_BLINK_TBL);
117ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler
118ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	led_cmd.on = blink_tbl[idx].on_time;
119ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	led_cmd.off = blink_tbl[idx].off_time;
120ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler
121ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return iwl_send_led_cmd(priv, &led_cmd);
122ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
123ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
124ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Set led register off */
125ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasstatic int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
126ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
127ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	IWL_DEBUG_LED("led on %d\n", led_id);
1283395f6e9cf48469d7ee05703cad1502002741c16Tomas Winkler	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
129ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return 0;
130ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
131ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
132ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#if 0
133ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler/* Set led on command */
134ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winklerstatic int iwl4965_led_on(struct iwl_priv *priv, int led_id)
135ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler{
136ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	struct iwl_led_cmd led_cmd = {
137ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.id = led_id,
138ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.on = IWL_LED_SOLID,
139ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.off = 0,
140ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		.interval = IWL_DEF_LED_INTRVL
141ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	};
142ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	return iwl_send_led_cmd(priv, &led_cmd);
143ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler}
144ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler
145ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Set led off command */
146ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasint iwl4965_led_off(struct iwl_priv *priv, int led_id)
147ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
148ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	struct iwl_led_cmd led_cmd = {
149ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.id = led_id,
150ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.on = 0,
151ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.off = 0,
152ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		.interval = IWL_DEF_LED_INTRVL
153ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	};
154ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	IWL_DEBUG_LED("led off %d\n", led_id);
155ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return iwl_send_led_cmd(priv, &led_cmd);
156ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
157ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas#endif
158ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
159ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
160ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Set led register off */
161ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasstatic int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
162ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
163c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	IWL_DEBUG_LED("LED Reg off\n");
1643395f6e9cf48469d7ee05703cad1502002741c16Tomas Winkler	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
165ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return 0;
166ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
167ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
168ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/*
169c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer * Set led register in case of disassociation according to rfkill state
170c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer */
171c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummerstatic int iwl_led_associate(struct iwl_priv *priv, int led_id)
172c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer{
173c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	IWL_DEBUG_LED("Associated\n");
174c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	priv->allow_blinking = 1;
175c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	return iwl4965_led_on_reg(priv, led_id);
176c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer}
177c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummerstatic int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
178c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer{
179c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	priv->allow_blinking = 0;
180c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	if (iwl_is_rfkill(priv))
181c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer		iwl4965_led_off_reg(priv, led_id);
182c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	else
183c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer		iwl4965_led_on_reg(priv, led_id);
184c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer
185c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	return 0;
186c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer}
187c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer
188c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer/*
189ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * brightness call back function for Tx/Rx LED
190ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas */
191ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winklerstatic int iwl_led_associated(struct iwl_priv *priv, int led_id)
192ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
193ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
194ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	    !test_bit(STATUS_READY, &priv->status))
195ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return 0;
196ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
197ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
198ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	/* start counting Tx/Rx bytes */
199ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (!priv->last_blink_time && priv->allow_blinking)
200ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		priv->last_blink_time = jiffies;
201ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return 0;
202ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
203ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
204ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/*
205ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * brightness call back for association and radio
206ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas */
2070eee612731e133604023bfa8d20047e98160845eTomas Winklerstatic void iwl_led_brightness_set(struct led_classdev *led_cdev,
208ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas				       enum led_brightness brightness)
209ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
2100eee612731e133604023bfa8d20047e98160845eTomas Winkler	struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev);
211ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	struct iwl_priv *priv = led->priv;
212ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
213ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
214ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
215ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
2160eee612731e133604023bfa8d20047e98160845eTomas Winkler
2170eee612731e133604023bfa8d20047e98160845eTomas Winkler	IWL_DEBUG_LED("Led type = %s brightness = %d\n",
2180eee612731e133604023bfa8d20047e98160845eTomas Winkler			led_type_str[led->type], brightness);
219ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	switch (brightness) {
220ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	case LED_FULL:
221ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		if (led->led_on)
222ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas			led->led_on(priv, IWL_LED_LINK);
223ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		break;
224ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	case LED_OFF:
225ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		if (led->led_off)
226ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas			led->led_off(priv, IWL_LED_LINK);
227ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		break;
228ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	default:
229ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		if (led->led_pattern) {
230ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler			int idx = iwl_brightness_to_idx(brightness);
231ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler			led->led_pattern(priv, IWL_LED_LINK, idx);
232ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		}
233ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		break;
234ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	}
235ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
236ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
237ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
238ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
239ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/*
240ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * Register led class with the system
241ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas */
2420eee612731e133604023bfa8d20047e98160845eTomas Winklerstatic int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
243ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas				   enum led_type type, u8 set_led,
2445cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener				   char *trigger)
245ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
246ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	struct device *device = wiphy_dev(priv->hw->wiphy);
247ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	int ret;
248ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
2495cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener	led->led_dev.name = led->name;
2500eee612731e133604023bfa8d20047e98160845eTomas Winkler	led->led_dev.brightness_set = iwl_led_brightness_set;
251ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	led->led_dev.default_trigger = trigger;
252ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
253a571ea4eb34adbf33bbaf4bdc6db6037b1a93e0fTomas Winkler	led->priv = priv;
254a571ea4eb34adbf33bbaf4bdc6db6037b1a93e0fTomas Winkler	led->type = type;
255a571ea4eb34adbf33bbaf4bdc6db6037b1a93e0fTomas Winkler
256ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	ret = led_classdev_register(device, &led->led_dev);
257ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (ret) {
258ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		IWL_ERROR("Error: failed to register led handler.\n");
259ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return ret;
260ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	}
261ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
262ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	led->registered = 1;
263ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
264ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (set_led && led->led_on)
265ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		led->led_on(priv, IWL_LED_LINK);
266a571ea4eb34adbf33bbaf4bdc6db6037b1a93e0fTomas Winkler
267ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return 0;
268ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
269ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
270ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
271ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/*
272ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * calculate blink rate according to last 2 sec Tx/Rx activities
273ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas */
274ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winklerstatic int iwl_get_blink_rate(struct iwl_priv *priv)
275ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
276ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	int i;
2770eee612731e133604023bfa8d20047e98160845eTomas Winkler	u64 current_tpt = priv->tx_stats[2].bytes;
2780eee612731e133604023bfa8d20047e98160845eTomas Winkler	/* FIXME: + priv->rx_stats[2].bytes; */
279ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	s64 tpt = current_tpt - priv->led_tpt;
280ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
281a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler	if (tpt < 0) /* wraparound */
282ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		tpt = -tpt;
283ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
284031211049b71619f7e776521963c082ca453d9fdAndrew Morton	IWL_DEBUG_LED("tpt %lld current_tpt %llu\n",
285031211049b71619f7e776521963c082ca453d9fdAndrew Morton		(long long)tpt,
286031211049b71619f7e776521963c082ca453d9fdAndrew Morton		(unsigned long long)current_tpt);
287ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led_tpt = current_tpt;
288ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
289ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	if (!priv->allow_blinking)
290ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		i = IWL_MAX_BLINK_TBL;
291ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	else
292ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
293ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas			if (tpt  > (blink_tbl[i].tpt * IWL_1MB_RATE))
294ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas				break;
295ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
296ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	IWL_DEBUG_LED("LED BLINK IDX=%d", i);
297ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	return i;
298ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
299ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
300ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/*
301ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * this function called from handler. Since setting Led command can
302ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * happen very frequent we postpone led command to be called from
303ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas * REPLY handler so we know ucode is up
304ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas */
305ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasvoid iwl_leds_background(struct iwl_priv *priv)
306ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
307ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	u8 blink_idx;
308ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
309ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
310ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		priv->last_blink_time = 0;
311ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
312ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	}
313c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	if (iwl_is_rfkill(priv)) {
314ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		priv->last_blink_time = 0;
315ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
316ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	}
317ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
318ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (!priv->allow_blinking) {
319ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		priv->last_blink_time = 0;
320ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
321ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler			priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
322ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler			iwl4965_led_pattern(priv, IWL_LED_LINK,
323ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler					    IWL_SOLID_BLINK_IDX);
324ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		}
325ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
326ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	}
327ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (!priv->last_blink_time ||
328ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	    !time_after(jiffies, priv->last_blink_time +
329ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas			msecs_to_jiffies(1000)))
330ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
331ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
332ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	blink_idx = iwl_get_blink_rate(priv);
333ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
334ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	/* call only if blink rate change */
335ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	if (blink_idx != priv->last_blink_rate)
336ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler		iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx);
337ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
3380eee612731e133604023bfa8d20047e98160845eTomas Winkler	priv->last_blink_time = jiffies;
339ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	priv->last_blink_rate = blink_idx;
340ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
341ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed AbbasEXPORT_SYMBOL(iwl_leds_background);
342ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
343ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Register all led handler */
344ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasint iwl_leds_register(struct iwl_priv *priv)
345ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
346ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	char *trigger;
347ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	int ret;
348ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
349ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->last_blink_rate = 0;
350ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led_tpt = 0;
351ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->last_blink_time = 0;
352ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->allow_blinking = 0;
353ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
354ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	trigger = ieee80211_get_radio_led_name(priv->hw);
3555cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener	snprintf(priv->led[IWL_LED_TRG_RADIO].name,
3565cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio",
357ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		 wiphy_name(priv->hw->wiphy));
358ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
359ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
360ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
361ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
362ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
3630eee612731e133604023bfa8d20047e98160845eTomas Winkler	ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO],
3645cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener				   IWL_LED_TRG_RADIO, 1, trigger);
365ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (ret)
366ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		goto exit_fail;
367ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
368ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	trigger = ieee80211_get_assoc_led_name(priv->hw);
3695cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener	snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
3705cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc",
371ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		 wiphy_name(priv->hw->wiphy));
372ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
3730eee612731e133604023bfa8d20047e98160845eTomas Winkler	ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC],
3745cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener				   IWL_LED_TRG_ASSOC, 0, trigger);
3750eee612731e133604023bfa8d20047e98160845eTomas Winkler
376ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	/* for assoc always turn led on */
377c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate;
378c785d1d5018b93878a9280b0c04df96682cc6effEsti Kummer	priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate;
379ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
380ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
381ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (ret)
382ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		goto exit_fail;
383ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
384ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	trigger = ieee80211_get_rx_led_name(priv->hw);
3855cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener	snprintf(priv->led[IWL_LED_TRG_RX].name,
3865cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX",
3875cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 wiphy_name(priv->hw->wiphy));
388ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
3890eee612731e133604023bfa8d20047e98160845eTomas Winkler	ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX],
3905cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener				   IWL_LED_TRG_RX, 0, trigger);
391ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
392ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated;
393ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated;
394ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
395ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
396ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (ret)
397ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		goto exit_fail;
398ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
399ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	trigger = ieee80211_get_tx_led_name(priv->hw);
4005cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener	snprintf(priv->led[IWL_LED_TRG_TX].name,
4015cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX",
4025cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener		 wiphy_name(priv->hw->wiphy));
4035cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener
4040eee612731e133604023bfa8d20047e98160845eTomas Winkler	ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX],
4055cbbb376d65ed181ed290cea505ba37a0425ee25Sven Wegener				   IWL_LED_TRG_TX, 0, trigger);
4060eee612731e133604023bfa8d20047e98160845eTomas Winkler
407ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated;
408ec1a746042ea4c1c93065185897d6e8d3e7de894Tomas Winkler	priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated;
409ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
410ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
411ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (ret)
412ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		goto exit_fail;
413ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
414ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return 0;
415ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
416ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasexit_fail:
417ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	iwl_leds_unregister(priv);
418ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	return ret;
419ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
420ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed AbbasEXPORT_SYMBOL(iwl_leds_register);
421ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
422ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* unregister led class */
4230eee612731e133604023bfa8d20047e98160845eTomas Winklerstatic void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led)
424ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
425ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (!led->registered)
426ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		return;
427ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
428ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	led_classdev_unregister(&led->led_dev);
429ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
430ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	if (set_led)
431ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas		led->led_dev.brightness_set(&led->led_dev, LED_OFF);
432ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	led->registered = 0;
433ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
434ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
435ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas/* Unregister all led handlers */
436ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbasvoid iwl_leds_unregister(struct iwl_priv *priv)
437ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas{
438ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
439ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
440ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
441ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
442ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas}
443ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed AbbasEXPORT_SYMBOL(iwl_leds_unregister);
444ab53d8af6772b22d4d68b1bcd74f7a5dba693983Mohamed Abbas
445