linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/3] ath5k: led, cleanup and prepare macros
       [not found] <1242850139-25438-1-git-send-email-jirislaby@gmail.com>
@ 2009-05-20 20:08 ` Jiri Slaby
  2009-05-20 20:16 ` [PATCH 1/3] ath5k: add support for radio LED Tobias Doerffel
  1 sibling, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2009-05-20 20:08 UTC (permalink / raw)
  To: linville
  Cc: mickflemm, lrodriguez, me, linux-wireless, ath5k-devel,
	linux-kernel, Jiri Slaby

From: Jiri Slaby <jirislaby@gmail.com>

We need to use driver_data for more than pin and polaroty data.
Remove driver_data designator from ATH_LED definition and write
it explicitly.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/net/wireless/ath/ath5k/led.c |   33 +++++++++++++++++++++------------
 1 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 762e40d..0374b1f 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -47,30 +47,39 @@
 	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
 	.subvendor = (subv), .subdevice = (subd)
 
-#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
-#define ATH_PIN(data) ((data) >> 8)
-#define ATH_POLARITY(data) ((data) & 0xff)
+#define ATH_LED(pin, polarity)	(((pin) << 8) | (polarity))
+#define ATH_PIN(data)		(((data) >> 8) & 0xffff)
+#define ATH_POLARITY(data)	((data) & 0xff)
 
 /* Devices we match on for LED config info (typically laptops) */
 static const struct pci_device_id ath5k_led_devices[] = {
 	/* AR5211 */
-	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
+	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211),
+			.driver_data = ATH_LED(0, 0) },
 	/* HP Compaq nc6xx, nc4000, nx6000 */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID),
+			.driver_data = ATH_LED(1, 1) },
 	/* Acer Aspire One A150 (maximlevitsky@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008),
+			.driver_data = ATH_LED(3, 0) },
 	/* Acer Ferrari 5000 (russ.dill@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422),
+			.driver_data = ATH_LED(1, 1) },
 	/* E-machines E510 (tuliom@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428),
+			.driver_data = ATH_LED(3, 0) },
 	/* Acer Extensa 5620z (nekoreeve@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105),
+			.driver_data = ATH_LED(3, 0) },
 	/* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026),
+			.driver_data = ATH_LED(3, 0) },
 	/* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a),
+			.driver_data = ATH_LED(1, 0) },
 	/* IBM-specific AR5212 (all others) */
-	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
+	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM),
+			.driver_data = ATH_LED(0, 0) },
 	{ }
 };
 
-- 
1.6.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ath5k: add support for radio LED
       [not found] <1242850139-25438-1-git-send-email-jirislaby@gmail.com>
  2009-05-20 20:08 ` [PATCH 2/3] ath5k: led, cleanup and prepare macros Jiri Slaby
@ 2009-05-20 20:16 ` Tobias Doerffel
  2009-05-20 20:28   ` Jiri Slaby
  2009-05-20 20:29   ` Bob Copeland
  1 sibling, 2 replies; 9+ messages in thread
From: Tobias Doerffel @ 2009-05-20 20:16 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: linville, mickflemm, lrodriguez, me, linux-wireless, ath5k-devel,
	linux-kernel

[-- Attachment #1: Type: Text/Plain, Size: 776 bytes --]

Hi,

Am Mittwoch, 20. Mai 2009 22:08:57 schrieb Jiri Slaby:
> From: Tobias Doerffel <tobias.doerffel@gmail.com>
>
> I found these patches on the web not being merged since Jan. Was
> there any reason why they shouldn't be accepted?
Yes - they needed further work. The approach was wrong because the GPIO does 
not control the LED rather than some internal rfkill mechanism (which itself 
controls the LED). I therefore reworked things to have general RFKILL support 
in ath5k and proposed the patches. They were reviewed by Bob Copeland and I 
addressed most of the issues so far but didn't come up with a new patch yet, 
as there're still minor things to be worked out. If there's interest, I'll 
prepare a new patch which represents the current state.

Toby

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ath5k: add support for radio LED
  2009-05-20 20:16 ` [PATCH 1/3] ath5k: add support for radio LED Tobias Doerffel
@ 2009-05-20 20:28   ` Jiri Slaby
  2009-05-20 20:29   ` Bob Copeland
  1 sibling, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2009-05-20 20:28 UTC (permalink / raw)
  To: Tobias Doerffel
  Cc: linville, mickflemm, lrodriguez, me, linux-wireless, ath5k-devel,
	linux-kernel

On 05/20/2009 10:16 PM, Tobias Doerffel wrote:
> Hi,
> 
> Am Mittwoch, 20. Mai 2009 22:08:57 schrieb Jiri Slaby:
>> From: Tobias Doerffel <tobias.doerffel@gmail.com>
>>
>> I found these patches on the web not being merged since Jan. Was
>> there any reason why they shouldn't be accepted?
> Yes - they needed further work. The approach was wrong because the GPIO does 
> not control the LED rather than some internal rfkill mechanism (which itself 
> controls the LED). I therefore reworked things to have general RFKILL support 
> in ath5k and proposed the patches. They were reviewed by Bob Copeland and I 
> addressed most of the issues so far but didn't come up with a new patch yet, 
> as there're still minor things to be worked out. If there's interest, I'll 
> prepare a new patch which represents the current state.

I think we are definitely interested. Please send an updated patch.

Thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ath5k: add support for radio LED
  2009-05-20 20:16 ` [PATCH 1/3] ath5k: add support for radio LED Tobias Doerffel
  2009-05-20 20:28   ` Jiri Slaby
@ 2009-05-20 20:29   ` Bob Copeland
  2009-05-25 23:24     ` [PATCH] ath5k: added initial RFKILL support Tobias Doerffel
  1 sibling, 1 reply; 9+ messages in thread
From: Bob Copeland @ 2009-05-20 20:29 UTC (permalink / raw)
  To: Tobias Doerffel, Jiri Slaby
  Cc: linville, mickflemm, lrodriguez, linux-wireless, ath5k-devel,
	linux-kernel

On Wed, 20 May 2009 22:16:42 +0200, Tobias Doerffel wrote
> If there's interest, I'll  prepare a new patch which represents the
> current state.

I'm definitely interested in seeing rfkill gpio support getting in,
it's overdue.  So I say repost it and we can fasttrack that.  Digging
up your last patchset was already on my todo list.

As for patch 2/3 it might be a good idea to have support for
which-led-does-what encoded into the driver data anyway; other
people have asked for that and the "solution" of adding various
echos to sysfs LED trigger files is rather sad.  OTOH it could
eventually be a lot of data to carry around.

-- 
Bob Copeland %% www.bobcopeland.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] ath5k: added initial RFKILL support
  2009-05-20 20:29   ` Bob Copeland
@ 2009-05-25 23:24     ` Tobias Doerffel
  2009-05-25 23:32       ` Johannes Berg
  0 siblings, 1 reply; 9+ messages in thread
From: Tobias Doerffel @ 2009-05-25 23:24 UTC (permalink / raw)
  To: Bob Copeland, Jiri Slaby, ath5k-devel
  Cc: mickflemm, linux-wireless, linux-kernel


[-- Attachment #1.1: Type: Text/Plain, Size: 661 bytes --]

Hi,

Am Mittwoch, 20. Mai 2009 22:29:42 schrieb Bob Copeland:
> I'm definitely interested in seeing rfkill gpio support getting in,
> it's overdue.  So I say repost it and we can fasttrack that.  Digging
> up your last patchset was already on my todo list.
Here we go. I attached a patch (against wireless-testing) which represents my 
latest work on RFKILL support for ath5k. It still lacks testing with a real 
physical rfkill switch (for I don't have one with my NC10) but everything else 
(SW rfkill) works fine after testing various scenarios. Furthermore I think I 
addressed all remarks in the last review by Bob Copeland.

Regards,

Toby

[-- Attachment #1.2: 0001-ath5k-added-initial-RFKILL-support.patch --]
[-- Type: text/x-patch, Size: 18651 bytes --]

From 0dfab8fbd3223747e2a7948296606e661899630b Mon Sep 17 00:00:00 2001
From: Tobias Doerffel <tobias.doerffel@gmail.com>
Date: Tue, 26 May 2009 00:52:20 +0200
Subject: [PATCH] ath5k: added initial RFKILL support

This patch introduces initial RFKILL support for the ath5k driver.
All RFKILL related code is separated into newly created rfkill.c.

Changes to existing code are minimal:

- added a new data structure ath5k_rfkill to the ath5k_softc structure
- new function ath5k_eeprom_read_rfkill() for retrieving RFKILL related
  parameters from EEPROM
- inserted calls to init/deinit routines for both the SW and HW part of
  RFKILL support
- ath5k_intr() has been extended to handle AR5K_INT_GPIO interrupts
---
 drivers/net/wireless/ath/ath5k/Kconfig  |    9 +
 drivers/net/wireless/ath/ath5k/Makefile |    1 +
 drivers/net/wireless/ath/ath5k/ath5k.h  |   22 +++
 drivers/net/wireless/ath/ath5k/base.c   |   20 ++-
 drivers/net/wireless/ath/ath5k/base.h   |   26 +++
 drivers/net/wireless/ath/ath5k/eeprom.c |   16 ++
 drivers/net/wireless/ath/ath5k/reset.c  |   17 --
 drivers/net/wireless/ath/ath5k/rfkill.c |  268 +++++++++++++++++++++++++++++++
 8 files changed, 358 insertions(+), 21 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath5k/rfkill.c

diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 509b6f9..618a879 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -39,3 +39,12 @@ config ATH5K_DEBUG
 
 	  modprobe ath5k debug=0x00000400
 
+config ATH5K_RFKILL
+	bool "Atheros 5xxx rfkill support"
+	select RFKILL
+	depends on ATH5K
+	default y
+	---help---
+	  Include support for enabling/disabling WiFi via rfkill switch
+	  with Atheros 5xxx cards
+
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 84a74c5..f1e281c 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -12,4 +12,5 @@ ath5k-y				+= attach.o
 ath5k-y				+= base.o
 ath5k-y				+= led.o
 ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
+ath5k-$(CONFIG_ATH5K_RFKILL)	+= rfkill.o
 obj-$(CONFIG_ATH5K)		+= ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 8137182..0dadcbb 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1162,6 +1162,10 @@ extern void ath5k_led_enable(struct ath5k_softc *sc);
 extern void ath5k_led_off(struct ath5k_softc *sc);
 extern void ath5k_unregister_leds(struct ath5k_softc *sc);
 
+/* Start/Stop Functions */
+extern int ath5k_init(struct ath5k_softc *sc);
+extern int ath5k_stop_hw(struct ath5k_softc *sc);
+
 /* Reset Functions */
 extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
 extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
@@ -1190,6 +1194,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
 extern int ath5k_eeprom_init(struct ath5k_hw *ah);
 extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
 extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern void ath5k_eeprom_read_rfkill(struct ath5k_hw *ah, u16 *gpio, u8 *polarity);
 extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
 
 /* Protocol Control Unit Functions */
@@ -1256,6 +1261,23 @@ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
 extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
 extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
 
+/* rfkill Functions */
+#ifdef CONFIG_ATH5K_RFKILL
+extern int ath5k_rfkill_init(struct ath5k_softc *sc);
+extern void ath5k_rfkill_deinit(struct ath5k_softc *sc);
+extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
+extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
+#else
+static inline int ath5k_rfkill_init(struct ath5k_softc *sc)
+{
+	return 0;
+}
+
+static inline void ath5k_rfkill_deinit(struct ath5k_softc *sc) {}
+static inline void ath5k_rfkill_hw_start(struct ath5k_hw *ah) {}
+static inline void ath5k_rfkill_hw_stop(struct ath5k_hw *ah) {}
+#endif
+
 /* Misc functions */
 int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
 extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index fb51937..aa9446e 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -363,9 +363,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 }
 
 /* Interrupt handling */
-static int 	ath5k_init(struct ath5k_softc *sc);
 static int 	ath5k_stop_locked(struct ath5k_softc *sc);
-static int 	ath5k_stop_hw(struct ath5k_softc *sc);
 static irqreturn_t ath5k_intr(int irq, void *dev_id);
 static void 	ath5k_tasklet_reset(unsigned long data);
 
@@ -822,6 +820,9 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 
 	ath5k_init_leds(sc);
 
+	/* Initialize rfkill subsystem */
+	ath5k_rfkill_init(sc);
+
 	return 0;
 err_queues:
 	ath5k_txq_release(sc);
@@ -856,6 +857,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 	ath5k_txq_release(sc);
 	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
 	ath5k_unregister_leds(sc);
+	ath5k_rfkill_deinit(sc);
 
 	/*
 	 * NB: can't reclaim these until after ieee80211_ifdetach
@@ -2321,7 +2323,7 @@ static void ath5k_tasklet_beacon(unsigned long data)
 * Interrupt handling *
 \********************/
 
-static int
+int
 ath5k_init(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
@@ -2353,6 +2355,8 @@ ath5k_init(struct ath5k_softc *sc)
 	if (ret)
 		goto done;
 
+	ath5k_rfkill_hw_start(ah);
+
 	/*
 	 * Reset the key cache since some parts do not reset the
 	 * contents on initial power up or resume from suspend.
@@ -2419,7 +2423,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
  * if another thread does a system call and the thread doing the
  * stop is preempted).
  */
-static int
+int
 ath5k_stop_hw(struct ath5k_softc *sc)
 {
 	int ret;
@@ -2461,6 +2465,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
 	tasklet_kill(&sc->restq);
 	tasklet_kill(&sc->beacontq);
 
+	ath5k_rfkill_hw_stop(sc->ah);
+
 	return ret;
 }
 
@@ -2519,6 +2525,12 @@ ath5k_intr(int irq, void *dev_id)
 				 */
 				ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
 			}
+#ifdef CONFIG_ATH5K_RFKILL
+			if (status & AR5K_INT_GPIO)
+			{
+				tasklet_schedule(&sc->rf_kill.toggleq);
+			}
+#endif
 		}
 	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
 
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 852b2c1..88c6929 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -46,6 +46,7 @@
 #include <linux/wireless.h>
 #include <linux/if_ether.h>
 #include <linux/leds.h>
+#include <linux/rfkill.h>
 
 #include "ath5k.h"
 #include "debug.h"
@@ -91,6 +92,27 @@ struct ath5k_led
 	struct led_classdev led_dev;		/* led classdev */
 };
 
+/* Rfkill */
+#define ATH5K_RFKILL_FLAG_HW_STARTED	BIT(0)
+#define ATH5K_RFKILL_FLAG_SW_BLOCKED	BIT(1)
+#define ATH5K_RFKILL_FLAG_HW_BLOCKED	BIT(2)
+
+struct ath5k_rfkill {
+	/* GPIO PIN for rfkill */
+	u16 gpio;
+	/* polarity of rfkill GPIO PIN */
+	u8 polarity;
+	/* The RFKILL subsystem data structure */
+	struct rfkill *rfkill;
+	/* The unique name of this rfkill switch */
+	char rfkill_name[32];
+	/* Flags indicating SW RFKILL status */
+	u32 flags;
+	/* RFKILL toggle tasklet */
+	struct tasklet_struct toggleq;
+	/* mutex for RFKILL related operations */
+	struct mutex lock;
+};
 
 #if CHAN_DEBUG
 #define ATH_CHAN_MAX	(26+26+26+200+200)
@@ -167,6 +189,10 @@ struct ath5k_softc {
 	struct tasklet_struct	txtq;		/* tx intr tasklet */
 	struct ath5k_led	tx_led;		/* tx led */
 
+#ifdef CONFIG_ATH5K_RFKILL
+	struct ath5k_rfkill	rf_kill;
+#endif
+
 	spinlock_t		block;		/* protects beacon */
 	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
 	struct ath5k_buf	*bbuf;		/* beacon buffer */
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index c56b494..ff00502 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1800,3 +1800,19 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
 
 	return 0;
 }
+
+
+/*
+ * Read RFKILL GPIO configuration from eeprom
+ */
+void ath5k_eeprom_read_rfkill(struct ath5k_hw *ah, u16 *gpio, u8 *polarity)
+{
+	u16 data;
+
+	ath5k_hw_eeprom_read(ah, AR5K_EEPROM_RFKILL_GPIO_SEL, &data);
+	*gpio = AR5K_REG_MS(data, AR5K_EEPROM_RFKILL_GPIO_SEL);
+
+	ath5k_hw_eeprom_read(ah, AR5K_EEPROM_RFKILL_POLARITY, &data);
+	*polarity = AR5K_REG_MS(data, AR5K_EEPROM_RFKILL_POLARITY);
+}
+
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index bd1940e..8077f0a 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1305,23 +1305,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	if (ah->ah_version != AR5K_AR5210)
 		ath5k_hw_set_imr(ah, ah->ah_imr);
 
-	/*
-	 * Setup RFKill interrupt if rfkill flag is set on eeprom.
-	 * TODO: Use gpio pin and polarity infos from eeprom
-	 * TODO: Handle this in ath5k_intr because it'll result
-	 * 	 a nasty interrupt storm.
-	 */
-#if 0
-	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
-		ath5k_hw_set_gpio_input(ah, 0);
-		ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
-		if (ah->ah_gpio[0] == 0)
-			ath5k_hw_set_gpio_intr(ah, 0, 1);
-		else
-			ath5k_hw_set_gpio_intr(ah, 0, 0);
-	}
-#endif
-
 	/* Enable 32KHz clock function for AR5212+ chips
 	 * Set clocks to 32KHz operation and use an
 	 * external 32KHz crystal when sleeping if one
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
new file mode 100644
index 0000000..2ae6961
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -0,0 +1,268 @@
+/*
+ * RFKILL support for ath5k
+ *
+ * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "base.h"
+
+
+static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+{
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
+		sc->rf_kill.gpio, sc->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+}
+
+
+static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+{
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
+		sc->rf_kill.gpio, sc->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+}
+
+static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
+{
+	struct ath5k_hw *ah = sc->ah;
+	ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
+	ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+					!!ah->ah_gpio[0] : !ah->ah_gpio[0]);
+}
+
+static void
+ath5k_radio_enable(struct ath5k_softc *sc)
+{
+	ath5k_init(sc);
+
+	ieee80211_wake_queues(sc->hw);
+}
+
+
+static void
+ath5k_radio_disable(struct ath5k_softc *sc)
+{
+	ieee80211_stop_queues(sc->hw);
+
+	/* shutdown hardware */
+	ath5k_stop_hw(sc);
+}
+
+
+static bool
+ath5k_is_rfkill_set(struct ath5k_softc *sc)
+{
+	/* configuring GPIO for input for some reason disables rfkill */
+	/*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
+	return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
+							sc->rf_kill.polarity;
+}
+
+
+static void
+ath5k_tasklet_rfkill_toggle(unsigned long data)
+{
+	struct ath5k_softc *sc = (void *)data;
+	bool radio_on;
+
+	mutex_lock(&sc->rf_kill.lock);
+
+	radio_on = !ath5k_is_rfkill_set(sc);
+
+	/*
+	 * enable/disable radio only when there is a
+	 * state change in RF switch
+	 */
+	if (radio_on == !!(sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_BLOCKED)) {
+		enum rfkill_state state;
+
+		if (sc->rf_kill.flags & ATH5K_RFKILL_FLAG_SW_BLOCKED) {
+			state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
+				: RFKILL_STATE_HARD_BLOCKED;
+		} else if (radio_on) {
+			ath5k_radio_enable(sc);
+			state = RFKILL_STATE_UNBLOCKED;
+		} else {
+			ath5k_radio_disable(sc);
+			state = RFKILL_STATE_HARD_BLOCKED;
+		}
+
+		if (state == RFKILL_STATE_HARD_BLOCKED)
+			sc->rf_kill.flags |= ATH5K_RFKILL_FLAG_HW_BLOCKED;
+		else
+			sc->rf_kill.flags &= ~ATH5K_RFKILL_FLAG_HW_BLOCKED;
+
+		rfkill_force_state(sc->rf_kill.rfkill, state);
+	}
+	mutex_unlock(&sc->rf_kill.lock);
+
+}
+
+
+/* s/w rfkill handler */
+static int
+ath5k_rfkill_soft_toggle(void *data, enum rfkill_state state)
+{
+	struct ath5k_softc *sc = data;
+	mutex_lock(&sc->rf_kill.lock);
+	/* RFKILL framework might call this toggle callback even if HW is
+	   not started (i.e. interface not up) - depending on the current
+	   SW RFKILL state this could cause calling ath5k_radio_disable()
+           leading to kernel panic due to un-initialized HW state */
+	if (!(sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_STARTED)) {
+		mutex_unlock(&sc->rf_kill.lock);
+		return -EINVAL;
+	}
+
+	switch (state) {
+	case RFKILL_STATE_SOFT_BLOCKED:
+		if (!(sc->rf_kill.flags & (ATH5K_RFKILL_FLAG_HW_BLOCKED |
+						ATH5K_RFKILL_FLAG_SW_BLOCKED)))
+			ath5k_radio_disable(sc);
+		sc->rf_kill.flags |= ATH5K_RFKILL_FLAG_SW_BLOCKED;
+		mutex_unlock(&sc->rf_kill.lock);
+		return 0;
+	case RFKILL_STATE_UNBLOCKED:
+		if ((sc->rf_kill.flags & ATH5K_RFKILL_FLAG_SW_BLOCKED)) {
+			sc->rf_kill.flags &= ~ATH5K_RFKILL_FLAG_SW_BLOCKED;
+			if (sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_BLOCKED) {
+				ATH5K_ERR(sc, "Can't turn on the"
+					"radio as it is disabled by h/w\n");
+				mutex_unlock(&sc->rf_kill.lock);
+				return -EBUSY;
+			}
+			ath5k_radio_enable(sc);
+		}
+		mutex_unlock(&sc->rf_kill.lock);
+		return 0;
+	default:
+		break;
+	}
+	mutex_unlock(&sc->rf_kill.lock);
+	return -EINVAL;
+}
+
+
+/* Init s/w rfkill */
+int
+ath5k_rfkill_init(struct ath5k_softc *sc)
+{
+	int err;
+
+	mutex_init(&sc->rf_kill.lock);
+
+	sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
+					     RFKILL_TYPE_WLAN);
+	if (!sc->rf_kill.rfkill) {
+		ATH5K_ERR(sc, "Failed to allocate rfkill\n");
+		return -ENOMEM;
+	}
+
+	snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
+		"ath5k-%s:rfkill", wiphy_name(sc->hw->wiphy));
+	sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
+	sc->rf_kill.rfkill->data = sc;
+	sc->rf_kill.rfkill->toggle_radio = ath5k_rfkill_soft_toggle;
+	sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
+
+	err = rfkill_register(sc->rf_kill.rfkill);
+	if (err) {
+		sc->rf_kill.rfkill = NULL;
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/* Deinitialize s/w rfkill */
+void
+ath5k_rfkill_deinit(struct ath5k_softc *sc)
+{
+	if (sc->rf_kill.rfkill != NULL) {
+		rfkill_unregister(sc->rf_kill.rfkill);
+		sc->rf_kill.rfkill = NULL;
+	}
+}
+
+
+void
+ath5k_rfkill_hw_start(struct ath5k_hw *ah)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+
+	if ((sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_STARTED) ||
+		(sc->rf_kill.flags & ATH5K_RFKILL_FLAG_SW_BLOCKED))
+		return;
+
+	/* read rfkill GPIO configuration from EEPROM */
+	ath5k_eeprom_read_rfkill(ah, &sc->rf_kill.gpio, &sc->rf_kill.polarity);
+
+	tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
+		(unsigned long)sc);
+
+	if (!(sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_BLOCKED))
+		ath5k_rfkill_disable(sc);
+
+	/* enable interrupt for rfkill switch */
+	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
+		ath5k_rfkill_set_intr(sc, true);
+	}
+
+	sc->rf_kill.flags |= ATH5K_RFKILL_FLAG_HW_STARTED;
+}
+
+
+void
+ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+
+	if (sc->rf_kill.flags & ATH5K_RFKILL_FLAG_HW_STARTED) {
+		/* disable interrupt for rfkill switch */
+		if (AR5K_EEPROM_HDR_RFKILL(
+				ah->ah_capabilities.cap_eeprom.ee_header)) {
+			ath5k_rfkill_set_intr(sc, false);
+		}
+
+		tasklet_kill(&sc->rf_kill.toggleq);
+
+		/* enable RFKILL when stopping HW so Wifi LED is turned off */
+		ath5k_rfkill_enable(sc);
+
+		sc->rf_kill.flags &= ~ATH5K_RFKILL_FLAG_HW_STARTED;
+	}
+}
+
-- 
1.6.3.1


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] ath5k: added initial RFKILL support
  2009-05-25 23:24     ` [PATCH] ath5k: added initial RFKILL support Tobias Doerffel
@ 2009-05-25 23:32       ` Johannes Berg
  2009-05-29 22:33         ` Tobias Doerffel
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2009-05-25 23:32 UTC (permalink / raw)
  To: Tobias Doerffel
  Cc: Bob Copeland, Jiri Slaby, ath5k-devel, mickflemm, linux-wireless,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 385 bytes --]

On Tue, 2009-05-26 at 01:24 +0200, Tobias Doerffel wrote:

> +       err = rfkill_register(sc->rf_kill.rfkill);
> +       if (err) {
> +               sc->rf_kill.rfkill = NULL;
> +               return -1;
> +       }

Missing rfkill_free, and why -EPERM? Could you try to work against v11
of my rfkill patch, or better even against the cfg80211 rfkill instead?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] ath5k: added initial RFKILL support
  2009-05-25 23:32       ` Johannes Berg
@ 2009-05-29 22:33         ` Tobias Doerffel
  2009-05-29 23:14           ` Johannes Berg
  0 siblings, 1 reply; 9+ messages in thread
From: Tobias Doerffel @ 2009-05-29 22:33 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Bob Copeland, Jiri Slaby, ath5k-devel, mickflemm, linux-wireless,
	linux-kernel

[-- Attachment #1: Type: Text/Plain, Size: 873 bytes --]

Hi,

Am Dienstag, 26. Mai 2009 01:32:46 schrieb Johannes Berg:
> On Tue, 2009-05-26 at 01:24 +0200, Tobias Doerffel wrote:
> > +       err = rfkill_register(sc->rf_kill.rfkill);
> > +       if (err) {
> > +               sc->rf_kill.rfkill = NULL;
> > +               return -1;
> > +       }
>
> Missing rfkill_free, and why -EPERM?
Thanks for this remark. I fixed the code and will post an updated patch soon.

Any other comments on the patch? If not, any chance to get it merged into 
wireless-testing branch?

> Could you try to work against v11
> of my rfkill patch, or better even against the cfg80211 rfkill instead?
I didn't look at both of them yet. However I think we first should try to get 
current rfkill support into mainline as fast as possible. Improvements and 
adaptations to reworked rfkill framework can follow.

Regards,

Toby

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] ath5k: added initial RFKILL support
  2009-05-29 22:33         ` Tobias Doerffel
@ 2009-05-29 23:14           ` Johannes Berg
  2009-05-30 15:26             ` [ath5k-devel] " Alan Jenkins
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2009-05-29 23:14 UTC (permalink / raw)
  To: Tobias Doerffel
  Cc: Bob Copeland, Jiri Slaby, ath5k-devel, mickflemm, linux-wireless,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 821 bytes --]

On Sat, 2009-05-30 at 00:33 +0200, Tobias Doerffel wrote:

> > Could you try to work against v11
> > of my rfkill patch, or better even against the cfg80211 rfkill instead?
> I didn't look at both of them yet. However I think we first should try to get 
> current rfkill support into mainline as fast as possible. Improvements and 
> adaptations to reworked rfkill framework can follow.

No other comments from me -- but since the v11 of the rfkill rewrite
will certainly hit the tree before your patch (it's almost in) you
_will_ have to work against it. I'll also try to make the cfg80211
rfkill hit the tree very soon for reasons I'll explain elsewhere -- you
would be better off working against that because then your rfkill code
is very very very simple and doesn't need to do much at all.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ath5k-devel] [PATCH] ath5k: added initial RFKILL support
  2009-05-29 23:14           ` Johannes Berg
@ 2009-05-30 15:26             ` Alan Jenkins
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Jenkins @ 2009-05-30 15:26 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Tobias Doerffel, Jiri Slaby, ath5k-devel, linux-wireless, linux-kernel

On 5/30/09, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Sat, 2009-05-30 at 00:33 +0200, Tobias Doerffel wrote:
>
>> > Could you try to work against v11
>> > of my rfkill patch, or better even against the cfg80211 rfkill instead?
>> I didn't look at both of them yet. However I think we first should try to
>> get
>> current rfkill support into mainline as fast as possible. Improvements and
>>
>> adaptations to reworked rfkill framework can follow.
>
> No other comments from me -- but since the v11 of the rfkill rewrite
> will certainly hit the tree before your patch (it's almost in) you
> _will_ have to work against it. I'll also try to make the cfg80211
> rfkill hit the tree very soon for reasons I'll explain elsewhere -- you
> would be better off working against that because then your rfkill code
> is very very very simple and doesn't need to do much at all.
>
> johannes

Btw, I believe the new rfkill core behaviour should avoid the concern
I raised about the EeePC.

Reminder: the eeepc-laptop implements platform rfkill on the original
model(s) by hotplugging the entire ath5k device.  If you boot with it
in the blocked state, the old rfkill core would "lock in" that state
as the default.  If you then hotplug the ath5k device _and it comes up
with an rfkill device of it's own_, my concern is that the new rfkill
device would be initialized to a blocked state.  It would be
impossible to enable the wireless.

The new core removes this idea of a separate "default" state, so it
can't have this problem.

Regards
Alan

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-05-30 15:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1242850139-25438-1-git-send-email-jirislaby@gmail.com>
2009-05-20 20:08 ` [PATCH 2/3] ath5k: led, cleanup and prepare macros Jiri Slaby
2009-05-20 20:16 ` [PATCH 1/3] ath5k: add support for radio LED Tobias Doerffel
2009-05-20 20:28   ` Jiri Slaby
2009-05-20 20:29   ` Bob Copeland
2009-05-25 23:24     ` [PATCH] ath5k: added initial RFKILL support Tobias Doerffel
2009-05-25 23:32       ` Johannes Berg
2009-05-29 22:33         ` Tobias Doerffel
2009-05-29 23:14           ` Johannes Berg
2009-05-30 15:26             ` [ath5k-devel] " Alan Jenkins

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).