All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFT 0/4] rfkill improvements
@ 2009-05-21 21:59 Johannes Berg
  2009-05-21 21:59 ` [RFT 1/4] net: introduce pre-up netdev notifier Johannes Berg
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-21 21:59 UTC (permalink / raw)
  To: linux-wireless

So this integrates rfkill into cfg80211 with the semantics
we discussed before. I've also ported iwlwifi for the fun
of it but due to lack of hardware can't test it. Help would
be appreciated a lot.

Note that this changes core kernel code so be prepared to
compile a lot of the kernel again.

johannes


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

* [RFT 1/4] net: introduce pre-up netdev notifier
  2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
@ 2009-05-21 21:59 ` Johannes Berg
  2009-05-21 21:59 ` [RFT 2/4] rfkill: add function to query state Johannes Berg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-21 21:59 UTC (permalink / raw)
  To: linux-wireless

NETDEV_UP is called after the device is set UP, but sometimes
it is useful to be able to veto the device UP. Introduce a
new NETDEV_PRE_UP notifier that can be used for exactly this.
The first use case will be cfg80211 denying interfaces to be
set UP if the device is known to be rfkill'ed.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
John, please take this patch via your tree, I asked Dave and
he's cool with that.

 include/linux/notifier.h |    1 +
 net/core/dev.c           |    7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

--- wireless-testing.orig/include/linux/notifier.h	2009-05-21 21:17:29.000000000 +0200
+++ wireless-testing/include/linux/notifier.h	2009-05-21 21:17:44.000000000 +0200
@@ -198,6 +198,7 @@ static inline int notifier_to_errno(int 
 #define NETDEV_CHANGENAME	0x000A
 #define NETDEV_FEAT_CHANGE	0x000B
 #define NETDEV_BONDING_FAILOVER 0x000C
+#define NETDEV_PRE_UP		0x000D
 
 #define SYS_DOWN	0x0001	/* Notify of system down */
 #define SYS_RESTART	SYS_DOWN
--- wireless-testing.orig/net/core/dev.c	2009-05-21 21:17:48.000000000 +0200
+++ wireless-testing/net/core/dev.c	2009-05-21 21:18:51.000000000 +0200
@@ -1047,7 +1047,7 @@ void dev_load(struct net *net, const cha
 int dev_open(struct net_device *dev)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
-	int ret = 0;
+	int ret;
 
 	ASSERT_RTNL();
 
@@ -1064,6 +1064,11 @@ int dev_open(struct net_device *dev)
 	if (!netif_device_present(dev))
 		return -ENODEV;
 
+	ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev);
+	ret = notifier_to_errno(ret);
+	if (ret)
+		return ret;
+
 	/*
 	 *	Call device private open method
 	 */

-- 


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

* [RFT 2/4] rfkill: add function to query state
  2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
  2009-05-21 21:59 ` [RFT 1/4] net: introduce pre-up netdev notifier Johannes Berg
@ 2009-05-21 21:59 ` Johannes Berg
  2009-05-21 21:59 ` [RFT 3/4] cfg80211: add rfkill support Johannes Berg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-21 21:59 UTC (permalink / raw)
  To: linux-wireless

Sometimes it is necessary to know how the state is,
and it is easier to query rfkill than keep track of
it somewhere else, so add a function for that. This
could later be expanded to return hard/soft block,
but so far that isn't necessary.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/linux/rfkill.h |   12 ++++++++++++
 net/rfkill/core.c      |   13 +++++++++++++
 2 files changed, 25 insertions(+)

--- wireless-testing.orig/include/linux/rfkill.h	2009-05-21 21:55:37.000000000 +0200
+++ wireless-testing/include/linux/rfkill.h	2009-05-21 21:56:00.000000000 +0200
@@ -225,6 +225,13 @@ void rfkill_set_states(struct rfkill *rf
  *	registered drivers?
  */
 void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked);
+
+/**
+ * rfkill_blocked - query rfkill block
+ *
+ * @rfkill: rfkill struct to query
+ */
+bool rfkill_blocked(struct rfkill *rfkill);
 #else /* !RFKILL */
 static inline struct rfkill * __must_check
 rfkill_alloc(const char *name,
@@ -277,6 +284,11 @@ static inline void rfkill_set_global_sw_
 					      bool blocked)
 {
 }
+
+static inline bool rfkill_blocked(struct rfkill *rfkill)
+{
+	return false;
+}
 #endif /* RFKILL || RFKILL_MODULE */
 
 
--- wireless-testing.orig/net/rfkill/core.c	2009-05-21 21:55:41.000000000 +0200
+++ wireless-testing/net/rfkill/core.c	2009-05-21 21:56:00.000000000 +0200
@@ -862,6 +862,19 @@ void rfkill_destroy(struct rfkill *rfkil
 }
 EXPORT_SYMBOL(rfkill_destroy);
 
+bool rfkill_blocked(struct rfkill *rfkill)
+{
+	unsigned long flags;
+	u32 state;
+
+	spin_lock_irqsave(&rfkill->lock, flags);
+	state = rfkill->state;
+	spin_unlock_irqrestore(&rfkill->lock, flags);
+
+	return !!(state & RFKILL_BLOCK_ANY);
+}
+EXPORT_SYMBOL(rfkill_blocked);
+
 
 static int __init rfkill_init(void)
 {

-- 


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

* [RFT 3/4] cfg80211: add rfkill support
  2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
  2009-05-21 21:59 ` [RFT 1/4] net: introduce pre-up netdev notifier Johannes Berg
  2009-05-21 21:59 ` [RFT 2/4] rfkill: add function to query state Johannes Berg
@ 2009-05-21 21:59 ` Johannes Berg
  2009-05-23  9:52   ` [RFT 3/4 v2] " Johannes Berg
  2009-05-24 13:32   ` [RFT 3/4] " Dan Williams
  2009-05-21 21:59 ` [RFT 4/4] iwlwifi: port to cfg80211 rfkill Johannes Berg
  2009-05-23  8:52 ` [RFT 5/4] iwm: port to new " Johannes Berg
  4 siblings, 2 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-21 21:59 UTC (permalink / raw)
  To: linux-wireless

To be easier on drivers and users, have cfg80211 register an
rfkill structure that drivers can access. When soft-killed,
simply take down all interfaces; when hard-killed the driver
needs to notify us and we will take down the interfaces
after the fact. While rfkilled, interfaces cannot be set UP.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/cfg80211.h     |   21 +++++++++--
 include/net/mac80211.h     |   18 ++++++++--
 net/mac80211/cfg.c         |   20 ++++-------
 net/mac80211/driver-ops.h  |    7 +++
 net/mac80211/iface.c       |    4 +-
 net/mac80211/util.c        |    2 -
 net/wireless/Kconfig       |    3 +
 net/wireless/core.c        |   81 +++++++++++++++++++++++++++++++++++++++++++--
 net/wireless/core.h        |    7 +++
 net/wireless/wext-compat.c |   11 +++---
 10 files changed, 145 insertions(+), 29 deletions(-)

--- wireless-testing.orig/net/wireless/core.c	2009-05-21 21:56:48.000000000 +0200
+++ wireless-testing/net/wireless/core.c	2009-05-21 23:45:24.000000000 +0200
@@ -12,6 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/notifier.h>
 #include <linux/device.h>
+#include <linux/rtnetlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "nl80211.h"
@@ -227,6 +228,41 @@ int cfg80211_dev_rename(struct cfg80211_
 	return 0;
 }
 
+static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
+{
+	struct cfg80211_registered_device *drv = data;
+
+	drv->ops->rfkill_poll(&drv->wiphy);
+}
+
+static int cfg80211_rfkill_set_block(void *data, bool blocked)
+{
+	struct cfg80211_registered_device *drv = data;
+	struct wireless_dev *wdev;
+
+	if (!blocked)
+		return 0;
+
+	rtnl_lock();
+	mutex_lock(&drv->devlist_mtx);
+
+	list_for_each_entry(wdev, &drv->netdev_list, list)
+		dev_close(wdev->netdev);
+
+	mutex_unlock(&drv->devlist_mtx);
+	rtnl_unlock();
+
+	return 0;
+}
+
+void cfg80211_rfkill_sync_work(struct work_struct *work)
+{
+	struct cfg80211_registered_device *drv;
+
+	drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
+	cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
@@ -274,6 +310,18 @@ struct wiphy *wiphy_new(const struct cfg
 	drv->wiphy.dev.class = &ieee80211_class;
 	drv->wiphy.dev.platform_data = drv;
 
+	drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
+	drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
+				   &drv->wiphy.dev, RFKILL_TYPE_WLAN,
+				   &drv->rfkill_ops, drv);
+
+	if (!drv->rfkill) {
+		kfree(drv);
+		return NULL;
+	}
+
+	INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
+
 	/*
 	 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
 	 * Fragmentation and RTS threshold are disabled by default with the
@@ -356,6 +404,13 @@ int wiphy_register(struct wiphy *wiphy)
 	if (res)
 		goto out_unlock;
 
+	if (wiphy->rfkill_poll && drv->ops->rfkill_poll)
+		drv->rfkill_ops.poll = cfg80211_rfkill_poll;
+
+	res = rfkill_register(drv->rfkill);
+	if (res)
+		goto out_rm_dev;
+
 	list_add(&drv->list, &cfg80211_drv_list);
 
 	/* add to debugfs */
@@ -379,7 +434,11 @@ int wiphy_register(struct wiphy *wiphy)
 	cfg80211_debugfs_drv_add(drv);
 
 	res = 0;
-out_unlock:
+	goto out_unlock;
+
+ out_rm_dev:
+	device_del(&drv->wiphy.dev);
+ out_unlock:
 	mutex_unlock(&cfg80211_mutex);
 	return res;
 }
@@ -389,6 +448,8 @@ void wiphy_unregister(struct wiphy *wiph
 {
 	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
 
+	rfkill_unregister(drv->rfkill);
+
 	/* protect the device list */
 	mutex_lock(&cfg80211_mutex);
 
@@ -425,6 +486,7 @@ EXPORT_SYMBOL(wiphy_unregister);
 void cfg80211_dev_free(struct cfg80211_registered_device *drv)
 {
 	struct cfg80211_internal_bss *scan, *tmp;
+	rfkill_destroy(drv->rfkill);
 	mutex_destroy(&drv->mtx);
 	mutex_destroy(&drv->devlist_mtx);
 	list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
@@ -438,6 +500,15 @@ void wiphy_free(struct wiphy *wiphy)
 }
 EXPORT_SYMBOL(wiphy_free);
 
+void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
+{
+	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+
+	if (rfkill_set_hw_state(drv->rfkill, blocked))
+		schedule_work(&drv->rfkill_sync);
+}
+EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
+
 static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 					 unsigned long state,
 					 void *ndev)
@@ -446,7 +517,7 @@ static int cfg80211_netdev_notifier_call
 	struct cfg80211_registered_device *rdev;
 
 	if (!dev->ieee80211_ptr)
-		return 0;
+		return NOTIFY_DONE;
 
 	rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
 
@@ -492,9 +563,13 @@ static int cfg80211_netdev_notifier_call
 		}
 		mutex_unlock(&rdev->devlist_mtx);
 		break;
+	case NETDEV_PRE_UP:
+		if (rfkill_blocked(rdev->rfkill))
+			return notifier_from_errno(-EINVAL);
+		break;
 	}
 
-	return 0;
+	return NOTIFY_DONE;
 }
 
 static struct notifier_block cfg80211_netdev_notifier = {
--- wireless-testing.orig/net/wireless/core.h	2009-05-21 21:56:48.000000000 +0200
+++ wireless-testing/net/wireless/core.h	2009-05-21 22:50:16.000000000 +0200
@@ -11,6 +11,8 @@
 #include <linux/kref.h>
 #include <linux/rbtree.h>
 #include <linux/debugfs.h>
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "reg.h"
@@ -24,6 +26,11 @@ struct cfg80211_registered_device {
 	 * any call is in progress */
 	struct mutex mtx;
 
+	/* rfkill support */
+	struct rfkill_ops rfkill_ops;
+	struct rfkill *rfkill;
+	struct work_struct rfkill_sync;
+
 	/* ISO / IEC 3166 alpha2 for which this device is receiving
 	 * country IEs on, this can help disregard country IEs from APs
 	 * on the same alpha2 quickly. The alpha2 may differ from
--- wireless-testing.orig/include/net/cfg80211.h	2009-05-21 21:56:48.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h	2009-05-21 23:43:53.000000000 +0200
@@ -757,13 +757,11 @@ enum wiphy_params_flags {
  * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
  * @TX_POWER_LIMITED: limit TX power by the dbm parameter
  * @TX_POWER_FIXED: fix TX power to the dbm parameter
- * @TX_POWER_OFF: turn off completely (will go away)
  */
 enum tx_power_setting {
 	TX_POWER_AUTOMATIC,
 	TX_POWER_LIMITED,
 	TX_POWER_FIXED,
-	TX_POWER_OFF,
 };
 
 /**
@@ -855,8 +853,10 @@ enum tx_power_setting {
  *
  * @set_tx_power: set the transmit power according to the parameters
  * @get_tx_power: store the current TX power into the dbm variable;
- *	return 0 if successful; or -ENETDOWN if successful but power
- *	is disabled (this will go away)
+ *	return 0 if successful
+ *
+ * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
+ *	functions to adjust rfkill hw state
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -952,6 +952,8 @@ struct cfg80211_ops {
 	int	(*set_tx_power)(struct wiphy *wiphy,
 				enum tx_power_setting type, int dbm);
 	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
+
+	void	(*rfkill_poll)(struct wiphy *wiphy);
 };
 
 /*
@@ -990,6 +992,8 @@ struct cfg80211_ops {
  * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
  *	-1 = fragmentation disabled, only odd values >= 256 used
  * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ *
+ * @rfkill_poll: poll rfkill via rfkill_poll method, if present
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1003,6 +1007,8 @@ struct wiphy {
 	bool custom_regulatory;
 	bool strict_regulatory;
 
+	bool rfkill_poll;
+
 	enum cfg80211_signal_type signal_type;
 
 	int bss_priv_size;
@@ -1619,4 +1625,11 @@ void cfg80211_michael_mic_failure(struct
  */
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 
+/**
+ * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
+ * @wiphy: the wiphy
+ * @blocked: block status
+ */
+void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked);
+
 #endif /* __NET_CFG80211_H */
--- wireless-testing.orig/net/wireless/Kconfig	2009-05-21 21:56:48.000000000 +0200
+++ wireless-testing/net/wireless/Kconfig	2009-05-21 22:38:31.000000000 +0200
@@ -1,5 +1,6 @@
 config CFG80211
-        tristate "Improved wireless configuration API"
+	tristate "Improved wireless configuration API"
+	depends on RFKILL || !RFKILL
 
 config CFG80211_REG_DEBUG
 	bool "cfg80211 regulatory debugging"
--- wireless-testing.orig/net/wireless/wext-compat.c	2009-05-21 22:54:28.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c	2009-05-21 23:11:18.000000000 +0200
@@ -764,6 +764,8 @@ int cfg80211_wext_siwtxpower(struct net_
 
 	/* only change when not disabling */
 	if (!data->txpower.disabled) {
+		rfkill_set_sw_state(rdev->rfkill, false);
+
 		if (data->txpower.fixed) {
 			/*
 			 * wext doesn't support negative values, see
@@ -787,7 +789,9 @@ int cfg80211_wext_siwtxpower(struct net_
 			}
 		}
 	} else {
-		type = TX_POWER_OFF;
+		rfkill_set_sw_state(rdev->rfkill, true);
+		schedule_work(&rdev->rfkill_sync);
+		return 0;
 	}
 
 	return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
@@ -811,13 +815,12 @@ int cfg80211_wext_giwtxpower(struct net_
 		return -EOPNOTSUPP;
 
 	err = rdev->ops->get_tx_power(wdev->wiphy, &val);
-	/* HACK!!! */
-	if (err && err != -ENETDOWN)
+	if (err)
 		return err;
 
 	/* well... oh well */
 	data->txpower.fixed = 1;
-	data->txpower.disabled = err == -ENETDOWN;
+	data->txpower.disabled = rfkill_blocked(rdev->rfkill);
 	data->txpower.value = val;
 	data->txpower.flags = IW_TXPOW_DBM;
 
--- wireless-testing.orig/net/mac80211/cfg.c	2009-05-21 22:57:11.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c	2009-05-21 23:49:58.000000000 +0200
@@ -1339,7 +1339,6 @@ static int ieee80211_set_tx_power(struct
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_channel *chan = local->hw.conf.channel;
 	u32 changes = 0;
-	bool radio_enabled = true;
 
 	switch (type) {
 	case TX_POWER_AUTOMATIC:
@@ -1358,14 +1357,6 @@ static int ieee80211_set_tx_power(struct
 			return -EINVAL;
 		local->user_power_level = dbm;
 		break;
-	case TX_POWER_OFF:
-		radio_enabled = false;
-		break;
-	}
-
-	if (radio_enabled != local->hw.conf.radio_enabled) {
-		changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
-		local->hw.conf.radio_enabled = radio_enabled;
 	}
 
 	ieee80211_hw_config(local, changes);
@@ -1379,12 +1370,16 @@ static int ieee80211_get_tx_power(struct
 
 	*dbm = local->hw.conf.power_level;
 
-	if (!local->hw.conf.radio_enabled)
-		return -ENETDOWN;
-
 	return 0;
 }
 
+static void ieee80211_rfkill_poll(struct wiphy *wiphy)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	drv_rfkill_poll(local);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1426,4 +1421,5 @@ struct cfg80211_ops mac80211_config_ops 
 	.set_wiphy_params = ieee80211_set_wiphy_params,
 	.set_tx_power = ieee80211_set_tx_power,
 	.get_tx_power = ieee80211_get_tx_power,
+	.rfkill_poll = ieee80211_rfkill_poll,
 };
--- wireless-testing.orig/net/mac80211/iface.c	2009-05-21 22:58:17.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2009-05-21 23:18:00.000000000 +0200
@@ -170,7 +170,7 @@ static int ieee80211_open(struct net_dev
 			goto err_del_bss;
 		/* we're brought up, everything changes */
 		hw_reconf_flags = ~0;
-		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+		ieee80211_led_radio(local, true);
 	}
 
 	/*
@@ -560,7 +560,7 @@ static int ieee80211_stop(struct net_dev
 
 		drv_stop(local);
 
-		ieee80211_led_radio(local, 0);
+		ieee80211_led_radio(local, false);
 
 		flush_workqueue(local->hw.workqueue);
 
--- wireless-testing.orig/net/mac80211/util.c	2009-05-21 22:58:36.000000000 +0200
+++ wireless-testing/net/mac80211/util.c	2009-05-21 23:17:24.000000000 +0200
@@ -1092,7 +1092,7 @@ int ieee80211_reconfig(struct ieee80211_
 	if (local->open_count) {
 		res = drv_start(local);
 
-		ieee80211_led_radio(local, hw->conf.radio_enabled);
+		ieee80211_led_radio(local, true);
 	}
 
 	/* add interfaces */
--- wireless-testing.orig/include/net/mac80211.h	2009-05-21 22:59:09.000000000 +0200
+++ wireless-testing/include/net/mac80211.h	2009-05-21 23:48:08.000000000 +0200
@@ -529,7 +529,7 @@ enum ieee80211_conf_flags {
 /**
  * enum ieee80211_conf_changed - denotes which configuration changed
  *
- * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
+ * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED
  * @_IEEE80211_CONF_CHANGE_BEACON_INTERVAL: DEPRECATED
  * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
  * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
@@ -540,7 +540,7 @@ enum ieee80211_conf_flags {
  * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
  */
 enum ieee80211_conf_changed {
-	IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
+	_IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
 	_IEEE80211_CONF_CHANGE_BEACON_INTERVAL	= BIT(1),
 	IEEE80211_CONF_CHANGE_LISTEN_INTERVAL	= BIT(2),
 	IEEE80211_CONF_CHANGE_RADIOTAP		= BIT(3),
@@ -559,6 +559,14 @@ __IEEE80211_CONF_CHANGE_BEACON_INTERVAL(
 #define IEEE80211_CONF_CHANGE_BEACON_INTERVAL \
 	__IEEE80211_CONF_CHANGE_BEACON_INTERVAL()
 
+static inline __deprecated enum ieee80211_conf_changed
+__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
+{
+	return _IEEE80211_CONF_CHANGE_RADIO_ENABLED;
+}
+#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \
+	__IEEE80211_CONF_CHANGE_RADIO_ENABLED()
+
 /**
  * struct ieee80211_conf - configuration of the device
  *
@@ -1419,6 +1427,10 @@ enum ieee80211_ampdu_mlme_action {
  * 	is the first frame we expect to perform the action on. Notice
  * 	that TX/RX_STOP can pass NULL for this parameter.
  *	Returns a negative error code on failure.
+ *
+ * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
+ *	need to set wiphy->rfkill_poll to %true before registration,
+ *	and need to call wiphy_rfkill_set_hw_state() in the callback.
  */
 struct ieee80211_ops {
 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1467,6 +1479,8 @@ struct ieee80211_ops {
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    enum ieee80211_ampdu_mlme_action action,
 			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+
+	void (*rfkill_poll)(struct ieee80211_hw *hw);
 };
 
 /**
--- wireless-testing.orig/net/mac80211/driver-ops.h	2009-05-21 23:49:10.000000000 +0200
+++ wireless-testing/net/mac80211/driver-ops.h	2009-05-21 23:49:43.000000000 +0200
@@ -181,4 +181,11 @@ static inline int drv_ampdu_action(struc
 						sta, tid, ssn);
 	return -EOPNOTSUPP;
 }
+
+
+static inline void drv_rfkill_poll(struct ieee80211_local *local)
+{
+	if (local->ops->rfkill_poll)
+		local->ops->rfkill_poll(&local->hw);
+}
 #endif /* __MAC80211_DRIVER_OPS */

-- 


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

* [RFT 4/4] iwlwifi: port to cfg80211 rfkill
  2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
                   ` (2 preceding siblings ...)
  2009-05-21 21:59 ` [RFT 3/4] cfg80211: add rfkill support Johannes Berg
@ 2009-05-21 21:59 ` Johannes Berg
  2009-05-23  8:49   ` [RFT 4/4 v2] " Johannes Berg
  2009-05-23  8:52 ` [RFT 5/4] iwm: port to new " Johannes Berg
  4 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2009-05-21 21:59 UTC (permalink / raw)
  To: linux-wireless

This ports the iwlwifi rfkill code to the new API offered by
cfg80211 and thus removes a lot of useless stuff. The soft-
rfkill is completely removed since that is now handled by
setting the interfaces down.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 drivers/net/wireless/iwlwifi/Kconfig        |    4 
 drivers/net/wireless/iwlwifi/Makefile       |    1 
 drivers/net/wireless/iwlwifi/iwl-3945.h     |    1 
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   40 ++------
 drivers/net/wireless/iwlwifi/iwl-core.c     |  138 ----------------------------
 drivers/net/wireless/iwlwifi/iwl-core.h     |   16 ---
 drivers/net/wireless/iwlwifi/iwl-debugfs.c  |    2 
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    5 -
 drivers/net/wireless/iwlwifi/iwl-rfkill.c   |  131 --------------------------
 drivers/net/wireless/iwlwifi/iwl-rfkill.h   |   48 ---------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   41 +-------
 11 files changed, 18 insertions(+), 409 deletions(-)

--- wireless-testing.orig/drivers/net/wireless/iwlwifi/Kconfig	2009-05-21 23:51:13.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/Kconfig	2009-05-21 23:52:39.000000000 +0200
@@ -10,10 +10,6 @@ config IWLWIFI_LEDS
 	bool "Enable LED support in iwlagn and iwl3945 drivers"
 	depends on IWLWIFI
 
-config IWLWIFI_RFKILL
-	def_bool y
-	depends on IWLWIFI && RFKILL
-
 config IWLWIFI_SPECTRUM_MEASUREMENT
 	bool "Enable Spectrum Measurement in iwlagn driver"
 	depends on IWLWIFI
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-3945.h	2009-05-21 23:52:07.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-3945.h	2009-05-21 23:52:39.000000000 +0200
@@ -154,7 +154,6 @@ struct iwl3945_frame {
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.c	2009-05-21 23:52:07.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.c	2009-05-21 23:56:47.000000000 +0200
@@ -755,19 +755,13 @@ static void iwl_rx_card_state_notif(stru
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	if (!(flags & RXON_CARD_DISABLED))
 		iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -1065,7 +1059,7 @@ static void iwl_irq_tasklet(struct iwl_p
 				set_bit(STATUS_RF_KILL_HW, &priv->status);
 			else
 				clear_bit(STATUS_RF_KILL_HW, &priv->status);
-			queue_work(priv->workqueue, &priv->rf_kill);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
@@ -1553,12 +1547,10 @@ static void __iwl_down(struct iwl_priv *
 		ieee80211_stop_queues(priv->hw);
 
 	/* If we have not previously called iwl_init() then
-	 * clear all bits but the RF Kill bits and return */
+	 * clear all bits but the RF Kill bit and return */
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
 			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -1567,11 +1559,9 @@ static void __iwl_down(struct iwl_priv *
 	}
 
 	/* ...otherwise clear out all the status bits but the RF Kill
-	 * bits and continue taking the NIC down. */
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
@@ -1646,9 +1636,10 @@ static int __iwl_up(struct iwl_priv *pri
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
 	if (iwl_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+
 		iwl_enable_interrupts(priv);
-		IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
-		    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
 		return 0;
 	}
 
@@ -1778,7 +1769,6 @@ static void iwl_bg_up(struct work_struct
 	mutex_lock(&priv->mutex);
 	__iwl_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl_bg_restart(struct work_struct *data)
@@ -1956,8 +1946,6 @@ static int iwl_mac_start(struct ieee8021
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		return ret;
 
@@ -2507,7 +2495,6 @@ static void iwl_setup_deferred_work(stru
 	INIT_WORK(&priv->up, iwl_bg_up);
 	INIT_WORK(&priv->restart, iwl_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
@@ -2761,12 +2748,8 @@ static int iwl_pci_probe(struct pci_dev 
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	err = iwl_rfkill_init(priv);
-	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	iwl_power_initialize(priv);
 	return 0;
@@ -2829,7 +2812,6 @@ static void __devexit iwl_pci_remove(str
 
 	iwl_synchronize_irq(priv);
 
-	iwl_rfkill_unregister(priv);
 	iwl_dealloc_ucode_pci(priv);
 
 	if (priv->rxq.bd)
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.c	2009-05-21 23:52:08.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.c	2009-05-21 23:52:39.000000000 +0200
@@ -36,7 +36,6 @@
 #include "iwl-debug.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
-#include "iwl-rfkill.h"
 #include "iwl-sta.h"
 
 
@@ -1968,126 +1967,6 @@ int iwl_send_card_state(struct iwl_priv 
 }
 EXPORT_SYMBOL(iwl_send_card_state);
 
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status))
-		return;
-
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n");
-
-	iwl_scan_cancel(priv);
-	/* FIXME: This is a workaround for AP */
-	if (priv->iw_mode != NL80211_IFTYPE_AP) {
-		spin_lock_irqsave(&priv->lock, flags);
-		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-			    CSR_UCODE_SW_BIT_RFKILL);
-		spin_unlock_irqrestore(&priv->lock, flags);
-		/* call the host command only if no hw rf-kill set */
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-		    iwl_is_ready(priv))
-			iwl_send_card_state(priv,
-				CARD_STATE_CMD_DISABLE, 0);
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-			/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-	}
-}
-EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
-
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
-		return 0;
-
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n");
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-	/* If the driver is up it will receive CARD_STATE_NOTIFICATION
-	 * notification where it will clear SW rfkill status.
-	 * Setting it here would break the handler. Only if the
-	 * interface is down we can set here since we don't
-	 * receive any further notification.
-	 */
-	if (!priv->is_open)
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* wake up ucode */
-	msleep(10);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_read32(priv, CSR_UCODE_DRV_GP1);
-	if (!iwl_grab_nic_access(priv))
-		iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-		IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-				  "disabled by HW switch\n");
-		return 0;
-	}
-
-	/* when driver is up while rfkill is on, it wont receive
-	 * any CARD_STATE_NOTIFICATION notifications so we have to
-	 * restart it in here
-	 */
-	if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-		if (!iwl_is_rfkill(priv))
-			queue_work(priv->workqueue, &priv->up);
-	}
-
-	/* If the driver is already loaded, it will receive
-	 * CARD_STATE_NOTIFICATION notifications and the handler will
-	 * call restart to reload the driver.
-	 */
-	return 1;
-}
-EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
-
-void iwl_bg_rf_kill(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
-	wake_up_interruptible(&priv->wait_command_queue);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (!iwl_is_rfkill(priv)) {
-		IWL_DEBUG_RF_KILL(priv,
-			  "HW and/or SW RF Kill no longer active, restarting "
-			  "device\n");
-		if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
-		    priv->is_open)
-			queue_work(priv->workqueue, &priv->restart);
-	} else {
-		/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-			IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-					  "disabled by SW switch\n");
-		else
-			IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
-				    "Kill switch must be turned off for "
-				    "wireless networking to work.\n");
-	}
-	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
-}
-EXPORT_SYMBOL(iwl_bg_rf_kill);
-
 void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
 			   struct iwl_rx_mem_buffer *rxb)
 {
@@ -2632,23 +2511,6 @@ int iwl_mac_config(struct ieee80211_hw *
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
 		priv->cfg->ops->hcmd->set_rxon_chain(priv);
 
-	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-		if (conf->radio_enabled &&
-			iwl_radio_kill_sw_enable_radio(priv)) {
-			IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
-						"waiting for uCode\n");
-			goto out;
-		}
-
-		if (!conf->radio_enabled)
-			iwl_radio_kill_sw_disable_radio(priv);
-	}
-
-	if (!conf->radio_enabled) {
-		IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-		goto out;
-	}
-
 	if (!iwl_is_ready(priv)) {
 		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 		goto out;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.h	2009-05-21 23:52:07.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.h	2009-05-21 23:52:39.000000000 +0200
@@ -345,14 +345,6 @@ int iwl_txq_check_empty(struct iwl_priv 
  ****************************************************/
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
 
-/*****************************************************
- * RF -Kill - here and not in iwl-rfkill.h to be available when
- * RF-kill subsystem is not compiled.
- ****************************************************/
-void iwl_bg_rf_kill(struct work_struct *work);
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
-
 /*******************************************************************************
  * Rate
  ******************************************************************************/
@@ -489,7 +481,6 @@ void iwlcore_free_geos(struct iwl_priv *
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
@@ -524,11 +515,6 @@ static inline int iwl_is_init(struct iwl
 	return test_bit(STATUS_INIT, &priv->status);
 }
 
-static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
-{
-	return test_bit(STATUS_RF_KILL_SW, &priv->status);
-}
-
 static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
 {
 	return test_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -536,7 +522,7 @@ static inline int iwl_is_rfkill_hw(struc
 
 static inline int iwl_is_rfkill(struct iwl_priv *priv)
 {
-	return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
+	return iwl_is_rfkill_hw(priv);
 }
 
 static inline int iwl_is_ready_rf(struct iwl_priv *priv)
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-05-21 23:43:11.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-05-21 23:52:39.000000000 +0200
@@ -442,8 +442,6 @@ static ssize_t iwl_dbgfs_status_read(str
 		test_bit(STATUS_INT_ENABLED, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
 		test_bit(STATUS_RF_KILL_HW, &priv->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n",
-		test_bit(STATUS_RF_KILL_SW, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
 		test_bit(STATUS_INIT, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-05-21 23:52:07.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-05-21 23:52:39.000000000 +0200
@@ -41,7 +41,6 @@
 #include "iwl-prph.h"
 #include "iwl-fh.h"
 #include "iwl-debug.h"
-#include "iwl-rfkill.h"
 #include "iwl-4965-hw.h"
 #include "iwl-3945-hw.h"
 #include "iwl-3945-led.h"
@@ -930,9 +929,6 @@ struct iwl_priv {
 	 * 4965's initialize alive response contains some calibration data. */
 	struct iwl_init_alive_resp card_alive_init;
 	struct iwl_alive_resp card_alive;
-#if defined(CONFIG_IWLWIFI_RFKILL)
-	struct rfkill *rfkill;
-#endif
 
 #ifdef CONFIG_IWLWIFI_LEDS
 	unsigned long last_blink_time;
@@ -1057,7 +1053,6 @@ struct iwl_priv {
 	struct work_struct calibrated_work;
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
-	struct work_struct rf_kill;
 	struct work_struct abort_scan;
 	struct work_struct update_link_led;
 	struct work_struct auth_work;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c	2009-05-21 23:52:07.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl3945-base.c	2009-05-21 23:52:39.000000000 +0200
@@ -1149,18 +1149,12 @@ static void iwl3945_rx_card_state_notif(
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+				test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -2761,8 +2755,6 @@ static void __iwl3945_down(struct iwl_pr
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
 				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -2771,11 +2763,9 @@ static void __iwl3945_down(struct iwl_pr
 	}
 
 	/* ...otherwise clear out all the status bits but the RF Kill
-	 * bits and continue taking the NIC down. */
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
@@ -2837,12 +2827,6 @@ static int __iwl3945_up(struct iwl_priv 
 		return -EIO;
 	}
 
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-		IWL_WARN(priv, "Radio disabled by SW RF kill (module "
-			    "parameter)\n");
-		return -ENODEV;
-	}
-
 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
 		IWL_ERR(priv, "ucode not available for device bring up\n");
 		return -EIO;
@@ -2959,15 +2943,14 @@ static void iwl3945_rfkill_poll(struct w
 {
 	struct iwl_priv *priv =
 	    container_of(data, struct iwl_priv, rfkill_poll.work);
-	unsigned long status = priv->status;
 
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
 			   round_jiffies_relative(2 * HZ));
@@ -3199,7 +3182,6 @@ static void iwl3945_bg_up(struct work_st
 	mutex_lock(&priv->mutex);
 	__iwl3945_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3362,8 +3344,6 @@ static int iwl3945_mac_start(struct ieee
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		goto out_release_irq;
 
@@ -3955,7 +3935,6 @@ static void iwl3945_setup_deferred_work(
 	INIT_WORK(&priv->up, iwl3945_bg_up);
 	INIT_WORK(&priv->restart, iwl3945_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -4317,13 +4296,6 @@ static int iwl3945_pci_probe(struct pci_
 	if (err)
 		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-	err = iwl_rfkill_init(priv);
-	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
-
 	/* Start monitoring the killswitch */
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
 			   2 * HZ);
@@ -4389,7 +4361,6 @@ static void __devexit iwl3945_pci_remove
 
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
-	iwl_rfkill_unregister(priv);
 	cancel_delayed_work_sync(&priv->rfkill_poll);
 
 	iwl3945_dealloc_ucode_pci(priv);
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-rfkill.c	2009-05-21 23:51:13.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,131 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-
-/* software rf-kill from user */
-static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
-{
-	struct iwl_priv *priv = data;
-
-	if (!priv->rfkill)
-		return -EINVAL;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return 0;
-
-	IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
-
-	mutex_lock(&priv->mutex);
-
-	if (iwl_is_rfkill_hw(priv))
-		goto out_unlock;
-
-	if (!blocked)
-		iwl_radio_kill_sw_enable_radio(priv);
-	else
-		iwl_radio_kill_sw_disable_radio(priv);
-
-out_unlock:
-	mutex_unlock(&priv->mutex);
-	return 0;
-}
-
-static const struct rfkill_ops iwl_rfkill_ops = {
-	.set_block = iwl_rfkill_soft_rf_kill,
-};
-
-int iwl_rfkill_init(struct iwl_priv *priv)
-{
-	struct device *device = wiphy_dev(priv->hw->wiphy);
-	int ret = 0;
-
-	BUG_ON(device == NULL);
-
-	IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
-	priv->rfkill = rfkill_alloc(priv->cfg->name,
-				    device,
-				    RFKILL_TYPE_WLAN,
-				    &iwl_rfkill_ops, priv);
-	if (!priv->rfkill) {
-		IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	ret = rfkill_register(priv->rfkill);
-	if (ret) {
-		IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
-		goto free_rfkill;
-	}
-
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return 0;
-
-free_rfkill:
-	rfkill_destroy(priv->rfkill);
-	priv->rfkill = NULL;
-
-error:
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return ret;
-}
-EXPORT_SYMBOL(iwl_rfkill_init);
-
-void iwl_rfkill_unregister(struct iwl_priv *priv)
-{
-
-	if (priv->rfkill) {
-		rfkill_unregister(priv->rfkill);
-		rfkill_destroy(priv->rfkill);
-	}
-
-	priv->rfkill = NULL;
-}
-EXPORT_SYMBOL(iwl_rfkill_unregister);
-
-/* set RFKILL to the right state. */
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
-{
-	if (!priv->rfkill)
-		return;
-
-	if (rfkill_set_hw_state(priv->rfkill,
-				!!iwl_is_rfkill_hw(priv)))
-		iwl_radio_kill_sw_disable_radio(priv);
-	else
-		iwl_radio_kill_sw_enable_radio(priv);
-}
-EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-rfkill.h	2009-05-21 23:43:11.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#ifndef __iwl_rf_kill_h__
-#define __iwl_rf_kill_h__
-
-struct iwl_priv;
-
-#include <linux/rfkill.h>
-
-#ifdef CONFIG_IWLWIFI_RFKILL
-
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
-void iwl_rfkill_unregister(struct iwl_priv *priv);
-int iwl_rfkill_init(struct iwl_priv *priv);
-#else
-static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
-static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
-static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
-#endif
-
-
-
-#endif  /* __iwl_rf_kill_h__ */
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/Makefile	2009-05-21 23:43:10.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/Makefile	2009-05-21 23:52:39.000000000 +0200
@@ -4,7 +4,6 @@ iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-
 iwlcore-objs 		+= iwl-scan.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
-iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
 iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
 
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o

-- 


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

* [RFT 4/4 v2] iwlwifi: port to cfg80211 rfkill
  2009-05-21 21:59 ` [RFT 4/4] iwlwifi: port to cfg80211 rfkill Johannes Berg
@ 2009-05-23  8:49   ` Johannes Berg
  0 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-23  8:49 UTC (permalink / raw)
  To: linux-wireless

This ports the iwlwifi rfkill code to the new API offered by
cfg80211 and thus removes a lot of useless stuff. The soft-
rfkill is completely removed since that is now handled by
setting the interfaces down.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 drivers/net/wireless/iwlwifi/Kconfig        |    4 
 drivers/net/wireless/iwlwifi/Makefile       |    1 
 drivers/net/wireless/iwlwifi/iwl-3945.h     |    1 
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   42 ++------
 drivers/net/wireless/iwlwifi/iwl-core.c     |  138 ----------------------------
 drivers/net/wireless/iwlwifi/iwl-core.h     |   16 ---
 drivers/net/wireless/iwlwifi/iwl-debugfs.c  |    2 
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    5 -
 drivers/net/wireless/iwlwifi/iwl-rfkill.c   |  131 --------------------------
 drivers/net/wireless/iwlwifi/iwl-rfkill.h   |   48 ---------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   41 +-------
 11 files changed, 19 insertions(+), 410 deletions(-)

--- wireless-testing.orig/drivers/net/wireless/iwlwifi/Kconfig	2009-05-23 10:34:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/Kconfig	2009-05-23 10:44:37.000000000 +0200
@@ -10,10 +10,6 @@ config IWLWIFI_LEDS
 	bool "Enable LED support in iwlagn and iwl3945 drivers"
 	depends on IWLWIFI
 
-config IWLWIFI_RFKILL
-	def_bool y
-	depends on IWLWIFI && RFKILL
-
 config IWLWIFI_SPECTRUM_MEASUREMENT
 	bool "Enable Spectrum Measurement in iwlagn driver"
 	depends on IWLWIFI
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-3945.h	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-3945.h	2009-05-23 10:44:37.000000000 +0200
@@ -154,7 +154,6 @@ struct iwl3945_frame {
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.c	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.c	2009-05-23 10:48:48.000000000 +0200
@@ -737,19 +737,13 @@ static void iwl_rx_card_state_notif(stru
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	if (!(flags & RXON_CARD_DISABLED))
 		iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -1045,7 +1039,7 @@ static void iwl_irq_tasklet_legacy(struc
 				set_bit(STATUS_RF_KILL_HW, &priv->status);
 			else
 				clear_bit(STATUS_RF_KILL_HW, &priv->status);
-			queue_work(priv->workqueue, &priv->rf_kill);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
@@ -1218,7 +1212,7 @@ static void iwl_irq_tasklet(struct iwl_p
 				set_bit(STATUS_RF_KILL_HW, &priv->status);
 			else
 				clear_bit(STATUS_RF_KILL_HW, &priv->status);
-			queue_work(priv->workqueue, &priv->rf_kill);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
@@ -1726,12 +1720,10 @@ static void __iwl_down(struct iwl_priv *
 		ieee80211_stop_queues(priv->hw);
 
 	/* If we have not previously called iwl_init() then
-	 * clear all bits but the RF Kill bits and return */
+	 * clear all bits but the RF Kill bit and return */
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
 			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -1740,11 +1732,9 @@ static void __iwl_down(struct iwl_priv *
 	}
 
 	/* ...otherwise clear out all the status bits but the RF Kill
-	 * bits and continue taking the NIC down. */
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
@@ -1866,9 +1856,10 @@ static int __iwl_up(struct iwl_priv *pri
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
 	if (iwl_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+
 		iwl_enable_interrupts(priv);
-		IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
-		    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
 		return 0;
 	}
 
@@ -2000,7 +1991,6 @@ static void iwl_bg_up(struct work_struct
 	mutex_lock(&priv->mutex);
 	__iwl_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl_bg_restart(struct work_struct *data)
@@ -2178,8 +2168,6 @@ static int iwl_mac_start(struct ieee8021
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		return ret;
 
@@ -2731,7 +2719,6 @@ static void iwl_setup_deferred_work(stru
 	INIT_WORK(&priv->up, iwl_bg_up);
 	INIT_WORK(&priv->restart, iwl_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
@@ -3001,12 +2988,8 @@ static int iwl_pci_probe(struct pci_dev 
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	err = iwl_rfkill_init(priv);
-	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	iwl_power_initialize(priv);
 	return 0;
@@ -3070,7 +3053,6 @@ static void __devexit iwl_pci_remove(str
 
 	iwl_synchronize_irq(priv);
 
-	iwl_rfkill_unregister(priv);
 	iwl_dealloc_ucode_pci(priv);
 
 	if (priv->rxq.bd)
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.c	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.c	2009-05-23 10:44:37.000000000 +0200
@@ -36,7 +36,6 @@
 #include "iwl-debug.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
-#include "iwl-rfkill.h"
 #include "iwl-sta.h"
 #include "iwl-helpers.h"
 
@@ -2216,126 +2215,6 @@ int iwl_send_card_state(struct iwl_priv 
 }
 EXPORT_SYMBOL(iwl_send_card_state);
 
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status))
-		return;
-
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n");
-
-	iwl_scan_cancel(priv);
-	/* FIXME: This is a workaround for AP */
-	if (priv->iw_mode != NL80211_IFTYPE_AP) {
-		spin_lock_irqsave(&priv->lock, flags);
-		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-			    CSR_UCODE_SW_BIT_RFKILL);
-		spin_unlock_irqrestore(&priv->lock, flags);
-		/* call the host command only if no hw rf-kill set */
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-		    iwl_is_ready(priv))
-			iwl_send_card_state(priv,
-				CARD_STATE_CMD_DISABLE, 0);
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-			/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-	}
-}
-EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
-
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
-		return 0;
-
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n");
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-	/* If the driver is up it will receive CARD_STATE_NOTIFICATION
-	 * notification where it will clear SW rfkill status.
-	 * Setting it here would break the handler. Only if the
-	 * interface is down we can set here since we don't
-	 * receive any further notification.
-	 */
-	if (!priv->is_open)
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* wake up ucode */
-	msleep(10);
-
-	iwl_read32(priv, CSR_UCODE_DRV_GP1);
-	spin_lock_irqsave(&priv->reg_lock, flags);
-	if (!iwl_grab_nic_access(priv))
-		iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, flags);
-
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-		IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-				  "disabled by HW switch\n");
-		return 0;
-	}
-
-	/* when driver is up while rfkill is on, it wont receive
-	 * any CARD_STATE_NOTIFICATION notifications so we have to
-	 * restart it in here
-	 */
-	if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-		if (!iwl_is_rfkill(priv))
-			queue_work(priv->workqueue, &priv->up);
-	}
-
-	/* If the driver is already loaded, it will receive
-	 * CARD_STATE_NOTIFICATION notifications and the handler will
-	 * call restart to reload the driver.
-	 */
-	return 1;
-}
-EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
-
-void iwl_bg_rf_kill(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
-	wake_up_interruptible(&priv->wait_command_queue);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (!iwl_is_rfkill(priv)) {
-		IWL_DEBUG_RF_KILL(priv,
-			  "HW and/or SW RF Kill no longer active, restarting "
-			  "device\n");
-		if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
-		    priv->is_open)
-			queue_work(priv->workqueue, &priv->restart);
-	} else {
-		/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-			IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-					  "disabled by SW switch\n");
-		else
-			IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
-				    "Kill switch must be turned off for "
-				    "wireless networking to work.\n");
-	}
-	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
-}
-EXPORT_SYMBOL(iwl_bg_rf_kill);
-
 void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
 			   struct iwl_rx_mem_buffer *rxb)
 {
@@ -2880,23 +2759,6 @@ int iwl_mac_config(struct ieee80211_hw *
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
 		priv->cfg->ops->hcmd->set_rxon_chain(priv);
 
-	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-		if (conf->radio_enabled &&
-			iwl_radio_kill_sw_enable_radio(priv)) {
-			IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
-						"waiting for uCode\n");
-			goto out;
-		}
-
-		if (!conf->radio_enabled)
-			iwl_radio_kill_sw_disable_radio(priv);
-	}
-
-	if (!conf->radio_enabled) {
-		IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-		goto out;
-	}
-
 	if (!iwl_is_ready(priv)) {
 		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 		goto out;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.h	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.h	2009-05-23 10:44:37.000000000 +0200
@@ -358,14 +358,6 @@ int iwl_txq_check_empty(struct iwl_priv 
  ****************************************************/
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
 
-/*****************************************************
- * RF -Kill - here and not in iwl-rfkill.h to be available when
- * RF-kill subsystem is not compiled.
- ****************************************************/
-void iwl_bg_rf_kill(struct work_struct *work);
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
-
 /*******************************************************************************
  * Rate
  ******************************************************************************/
@@ -508,7 +500,6 @@ void iwlcore_free_geos(struct iwl_priv *
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
@@ -543,11 +534,6 @@ static inline int iwl_is_init(struct iwl
 	return test_bit(STATUS_INIT, &priv->status);
 }
 
-static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
-{
-	return test_bit(STATUS_RF_KILL_SW, &priv->status);
-}
-
 static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
 {
 	return test_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -555,7 +541,7 @@ static inline int iwl_is_rfkill_hw(struc
 
 static inline int iwl_is_rfkill(struct iwl_priv *priv)
 {
-	return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
+	return iwl_is_rfkill_hw(priv);
 }
 
 static inline int iwl_is_ready_rf(struct iwl_priv *priv)
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-05-23 10:34:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-05-23 10:44:37.000000000 +0200
@@ -449,8 +449,6 @@ static ssize_t iwl_dbgfs_status_read(str
 		test_bit(STATUS_INT_ENABLED, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
 		test_bit(STATUS_RF_KILL_HW, &priv->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n",
-		test_bit(STATUS_RF_KILL_SW, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
 		test_bit(STATUS_INIT, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-05-23 10:44:37.000000000 +0200
@@ -41,7 +41,6 @@
 #include "iwl-prph.h"
 #include "iwl-fh.h"
 #include "iwl-debug.h"
-#include "iwl-rfkill.h"
 #include "iwl-4965-hw.h"
 #include "iwl-3945-hw.h"
 #include "iwl-3945-led.h"
@@ -937,9 +936,6 @@ struct iwl_priv {
 	 * 4965's initialize alive response contains some calibration data. */
 	struct iwl_init_alive_resp card_alive_init;
 	struct iwl_alive_resp card_alive;
-#if defined(CONFIG_IWLWIFI_RFKILL)
-	struct rfkill *rfkill;
-#endif
 
 #ifdef CONFIG_IWLWIFI_LEDS
 	unsigned long last_blink_time;
@@ -1074,7 +1070,6 @@ struct iwl_priv {
 	struct work_struct calibrated_work;
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
-	struct work_struct rf_kill;
 	struct work_struct abort_scan;
 	struct work_struct update_link_led;
 	struct work_struct auth_work;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c	2009-05-23 10:44:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl3945-base.c	2009-05-23 10:44:37.000000000 +0200
@@ -1149,18 +1149,12 @@ static void iwl3945_rx_card_state_notif(
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+				test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -2708,8 +2702,6 @@ static void __iwl3945_down(struct iwl_pr
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
 				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -2718,11 +2710,9 @@ static void __iwl3945_down(struct iwl_pr
 	}
 
 	/* ...otherwise clear out all the status bits but the RF Kill
-	 * bits and continue taking the NIC down. */
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
@@ -2779,12 +2769,6 @@ static int __iwl3945_up(struct iwl_priv 
 		return -EIO;
 	}
 
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-		IWL_WARN(priv, "Radio disabled by SW RF kill (module "
-			    "parameter)\n");
-		return -ENODEV;
-	}
-
 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
 		IWL_ERR(priv, "ucode not available for device bring up\n");
 		return -EIO;
@@ -2901,15 +2885,14 @@ static void iwl3945_rfkill_poll(struct w
 {
 	struct iwl_priv *priv =
 	    container_of(data, struct iwl_priv, rfkill_poll.work);
-	unsigned long status = priv->status;
 
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
 			   round_jiffies_relative(2 * HZ));
@@ -3141,7 +3124,6 @@ static void iwl3945_bg_up(struct work_st
 	mutex_lock(&priv->mutex);
 	__iwl3945_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3304,8 +3286,6 @@ static int iwl3945_mac_start(struct ieee
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		goto out_release_irq;
 
@@ -3897,7 +3877,6 @@ static void iwl3945_setup_deferred_work(
 	INIT_WORK(&priv->up, iwl3945_bg_up);
 	INIT_WORK(&priv->restart, iwl3945_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -4265,13 +4244,6 @@ static int iwl3945_pci_probe(struct pci_
 	if (err)
 		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-	err = iwl_rfkill_init(priv);
-	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
-
 	/* Start monitoring the killswitch */
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
 			   2 * HZ);
@@ -4337,7 +4309,6 @@ static void __devexit iwl3945_pci_remove
 
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
-	iwl_rfkill_unregister(priv);
 	cancel_delayed_work_sync(&priv->rfkill_poll);
 
 	iwl3945_dealloc_ucode_pci(priv);
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-rfkill.c	2009-05-23 10:34:47.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,131 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-
-/* software rf-kill from user */
-static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
-{
-	struct iwl_priv *priv = data;
-
-	if (!priv->rfkill)
-		return -EINVAL;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return 0;
-
-	IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
-
-	mutex_lock(&priv->mutex);
-
-	if (iwl_is_rfkill_hw(priv))
-		goto out_unlock;
-
-	if (!blocked)
-		iwl_radio_kill_sw_enable_radio(priv);
-	else
-		iwl_radio_kill_sw_disable_radio(priv);
-
-out_unlock:
-	mutex_unlock(&priv->mutex);
-	return 0;
-}
-
-static const struct rfkill_ops iwl_rfkill_ops = {
-	.set_block = iwl_rfkill_soft_rf_kill,
-};
-
-int iwl_rfkill_init(struct iwl_priv *priv)
-{
-	struct device *device = wiphy_dev(priv->hw->wiphy);
-	int ret = 0;
-
-	BUG_ON(device == NULL);
-
-	IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
-	priv->rfkill = rfkill_alloc(priv->cfg->name,
-				    device,
-				    RFKILL_TYPE_WLAN,
-				    &iwl_rfkill_ops, priv);
-	if (!priv->rfkill) {
-		IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	ret = rfkill_register(priv->rfkill);
-	if (ret) {
-		IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
-		goto free_rfkill;
-	}
-
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return 0;
-
-free_rfkill:
-	rfkill_destroy(priv->rfkill);
-	priv->rfkill = NULL;
-
-error:
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return ret;
-}
-EXPORT_SYMBOL(iwl_rfkill_init);
-
-void iwl_rfkill_unregister(struct iwl_priv *priv)
-{
-
-	if (priv->rfkill) {
-		rfkill_unregister(priv->rfkill);
-		rfkill_destroy(priv->rfkill);
-	}
-
-	priv->rfkill = NULL;
-}
-EXPORT_SYMBOL(iwl_rfkill_unregister);
-
-/* set RFKILL to the right state. */
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
-{
-	if (!priv->rfkill)
-		return;
-
-	if (rfkill_set_hw_state(priv->rfkill,
-				!!iwl_is_rfkill_hw(priv)))
-		iwl_radio_kill_sw_disable_radio(priv);
-	else
-		iwl_radio_kill_sw_enable_radio(priv);
-}
-EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-rfkill.h	2009-05-23 10:34:47.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#ifndef __iwl_rf_kill_h__
-#define __iwl_rf_kill_h__
-
-struct iwl_priv;
-
-#include <linux/rfkill.h>
-
-#ifdef CONFIG_IWLWIFI_RFKILL
-
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
-void iwl_rfkill_unregister(struct iwl_priv *priv);
-int iwl_rfkill_init(struct iwl_priv *priv);
-#else
-static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
-static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
-static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
-#endif
-
-
-
-#endif  /* __iwl_rf_kill_h__ */
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/Makefile	2009-05-23 10:34:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/Makefile	2009-05-23 10:44:37.000000000 +0200
@@ -4,7 +4,6 @@ iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-
 iwlcore-objs 		+= iwl-scan.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
-iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
 iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
 
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o



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

* [RFT 5/4] iwm: port to new cfg80211 rfkill
  2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
                   ` (3 preceding siblings ...)
  2009-05-21 21:59 ` [RFT 4/4] iwlwifi: port to cfg80211 rfkill Johannes Berg
@ 2009-05-23  8:52 ` Johannes Berg
  2009-05-25  1:22   ` Zhu Yi
  4 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2009-05-23  8:52 UTC (permalink / raw)
  To: linux-wireless; +Cc: Zhu, Yi, Samuel Ortiz

Which means removing all rfkill code since it only does
soft-kill which cfg80211 will now handle in exactly the
same way the driver did.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 drivers/net/wireless/iwmc3200wifi/Makefile |    2 
 drivers/net/wireless/iwmc3200wifi/iwm.h    |    4 -
 drivers/net/wireless/iwmc3200wifi/netdev.c |   10 ---
 drivers/net/wireless/iwmc3200wifi/rfkill.c |   83 -----------------------------
 4 files changed, 1 insertion(+), 98 deletions(-)

--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/Makefile	2009-05-23 10:48:02.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/Makefile	2009-05-23 10:49:23.000000000 +0200
@@ -1,5 +1,5 @@
 obj-$(CONFIG_IWM) := iwmc3200wifi.o
 iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
-iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o rfkill.o
+iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o
 
 iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/rfkill.c	2009-05-23 10:48:02.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,83 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <linux/rfkill.h>
-
-#include "iwm.h"
-
-static int iwm_rfkill_set_block(void *data, bool blocked)
-{
-	struct iwm_priv *iwm = data;
-
-	if (!blocked) {
-		if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio))
-			return -EBUSY;
-
-		if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) &&
-		    (iwm_to_ndev(iwm)->flags & IFF_UP))
-			return iwm_up(iwm);
-	} else {
-		if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
-			return iwm_down(iwm);
-	}
-
-	return 0;
-}
-
-static const struct rfkill_ops iwm_rfkill_ops = {
-	.set_block = iwm_rfkill_set_block,
-};
-
-int iwm_rfkill_init(struct iwm_priv *iwm)
-{
-	int ret;
-
-	iwm->rfkill = rfkill_alloc(KBUILD_MODNAME,
-				   iwm_to_dev(iwm),
-				   RFKILL_TYPE_WLAN,
-				   &iwm_rfkill_ops, iwm);
-	if (!iwm->rfkill) {
-		IWM_ERR(iwm, "Unable to allocate rfkill device\n");
-		return -ENOMEM;
-	}
-
-	ret = rfkill_register(iwm->rfkill);
-	if (ret) {
-		IWM_ERR(iwm, "Failed to register rfkill device\n");
-		goto fail;
-	}
-
-	return 0;
- fail:
-	rfkill_destroy(iwm->rfkill);
-	return ret;
-}
-
-void iwm_rfkill_exit(struct iwm_priv *iwm)
-{
-	if (iwm->rfkill) {
-		rfkill_unregister(iwm->rfkill);
-		rfkill_destroy(iwm->rfkill);
-	}
-	iwm->rfkill = NULL;
-}
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/iwm.h	2009-05-23 10:51:09.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/iwm.h	2009-05-23 10:51:12.000000000 +0200
@@ -343,8 +343,4 @@ int iwm_rx_handle_resp(struct iwm_priv *
 		       struct iwm_wifi_cmd *cmd);
 void iwm_rx_free(struct iwm_priv *iwm);
 
-/* RF Kill API */
-int iwm_rfkill_init(struct iwm_priv *iwm);
-void iwm_rfkill_exit(struct iwm_priv *iwm);
-
 #endif
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/netdev.c	2009-05-23 10:51:18.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/netdev.c	2009-05-23 10:51:29.000000000 +0200
@@ -136,17 +136,8 @@ void *iwm_if_alloc(int sizeof_bus, struc
 
 	wdev->netdev = ndev;
 
-	ret = iwm_rfkill_init(iwm);
-	if (ret) {
-		dev_err(dev, "Failed to init rfkill\n");
-		goto out_rfkill;
-	}
-
 	return iwm;
 
- out_rfkill:
-	unregister_netdev(ndev);
-
  out_ndev:
 	free_netdev(ndev);
 
@@ -162,7 +153,6 @@ void iwm_if_free(struct iwm_priv *iwm)
 	if (!iwm_to_ndev(iwm))
 		return;
 
-	iwm_rfkill_exit(iwm);
 	unregister_netdev(iwm_to_ndev(iwm));
 	free_netdev(iwm_to_ndev(iwm));
 	iwm_wdev_free(iwm);



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

* [RFT 3/4 v2] cfg80211: add rfkill support
  2009-05-21 21:59 ` [RFT 3/4] cfg80211: add rfkill support Johannes Berg
@ 2009-05-23  9:52   ` Johannes Berg
  2009-05-24 13:32   ` [RFT 3/4] " Dan Williams
  1 sibling, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-23  9:52 UTC (permalink / raw)
  To: linux-wireless

To be easier on drivers and users, have cfg80211 register an
rfkill structure that drivers can access. When soft-killed,
simply take down all interfaces; when hard-killed the driver
needs to notify us and we will take down the interfaces
after the fact. While rfkilled, interfaces cannot be set UP.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/cfg80211.h     |   21 +++++++++--
 include/net/mac80211.h     |   20 +++++++++--
 net/mac80211/cfg.c         |   20 ++++-------
 net/mac80211/driver-ops.h  |    7 +++
 net/mac80211/iface.c       |    4 +-
 net/mac80211/util.c        |    2 -
 net/wireless/Kconfig       |    3 +
 net/wireless/core.c        |   81 +++++++++++++++++++++++++++++++++++++++++++--
 net/wireless/core.h        |    7 +++
 net/wireless/wext-compat.c |   11 +++---
 10 files changed, 146 insertions(+), 30 deletions(-)

--- wireless-testing.orig/net/wireless/core.c	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/wireless/core.c	2009-05-23 11:18:02.000000000 +0200
@@ -12,6 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/notifier.h>
 #include <linux/device.h>
+#include <linux/rtnetlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "nl80211.h"
@@ -227,6 +228,41 @@ int cfg80211_dev_rename(struct cfg80211_
 	return 0;
 }
 
+static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
+{
+	struct cfg80211_registered_device *drv = data;
+
+	drv->ops->rfkill_poll(&drv->wiphy);
+}
+
+static int cfg80211_rfkill_set_block(void *data, bool blocked)
+{
+	struct cfg80211_registered_device *drv = data;
+	struct wireless_dev *wdev;
+
+	if (!blocked)
+		return 0;
+
+	rtnl_lock();
+	mutex_lock(&drv->devlist_mtx);
+
+	list_for_each_entry(wdev, &drv->netdev_list, list)
+		dev_close(wdev->netdev);
+
+	mutex_unlock(&drv->devlist_mtx);
+	rtnl_unlock();
+
+	return 0;
+}
+
+void cfg80211_rfkill_sync_work(struct work_struct *work)
+{
+	struct cfg80211_registered_device *drv;
+
+	drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
+	cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
@@ -274,6 +310,18 @@ struct wiphy *wiphy_new(const struct cfg
 	drv->wiphy.dev.class = &ieee80211_class;
 	drv->wiphy.dev.platform_data = drv;
 
+	drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
+	drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
+				   &drv->wiphy.dev, RFKILL_TYPE_WLAN,
+				   &drv->rfkill_ops, drv);
+
+	if (!drv->rfkill) {
+		kfree(drv);
+		return NULL;
+	}
+
+	INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
+
 	/*
 	 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
 	 * Fragmentation and RTS threshold are disabled by default with the
@@ -356,6 +404,13 @@ int wiphy_register(struct wiphy *wiphy)
 	if (res)
 		goto out_unlock;
 
+	if (wiphy->rfkill_poll && drv->ops->rfkill_poll)
+		drv->rfkill_ops.poll = cfg80211_rfkill_poll;
+
+	res = rfkill_register(drv->rfkill);
+	if (res)
+		goto out_rm_dev;
+
 	list_add(&drv->list, &cfg80211_drv_list);
 
 	/* add to debugfs */
@@ -379,7 +434,11 @@ int wiphy_register(struct wiphy *wiphy)
 	cfg80211_debugfs_drv_add(drv);
 
 	res = 0;
-out_unlock:
+	goto out_unlock;
+
+ out_rm_dev:
+	device_del(&drv->wiphy.dev);
+ out_unlock:
 	mutex_unlock(&cfg80211_mutex);
 	return res;
 }
@@ -389,6 +448,8 @@ void wiphy_unregister(struct wiphy *wiph
 {
 	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
 
+	rfkill_unregister(drv->rfkill);
+
 	/* protect the device list */
 	mutex_lock(&cfg80211_mutex);
 
@@ -425,6 +486,7 @@ EXPORT_SYMBOL(wiphy_unregister);
 void cfg80211_dev_free(struct cfg80211_registered_device *drv)
 {
 	struct cfg80211_internal_bss *scan, *tmp;
+	rfkill_destroy(drv->rfkill);
 	mutex_destroy(&drv->mtx);
 	mutex_destroy(&drv->devlist_mtx);
 	list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
@@ -438,6 +500,15 @@ void wiphy_free(struct wiphy *wiphy)
 }
 EXPORT_SYMBOL(wiphy_free);
 
+void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
+{
+	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+
+	if (rfkill_set_hw_state(drv->rfkill, blocked))
+		schedule_work(&drv->rfkill_sync);
+}
+EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
+
 static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 					 unsigned long state,
 					 void *ndev)
@@ -446,7 +517,7 @@ static int cfg80211_netdev_notifier_call
 	struct cfg80211_registered_device *rdev;
 
 	if (!dev->ieee80211_ptr)
-		return 0;
+		return NOTIFY_DONE;
 
 	rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
 
@@ -492,9 +563,13 @@ static int cfg80211_netdev_notifier_call
 		}
 		mutex_unlock(&rdev->devlist_mtx);
 		break;
+	case NETDEV_PRE_UP:
+		if (rfkill_blocked(rdev->rfkill))
+			return notifier_from_errno(-EINVAL);
+		break;
 	}
 
-	return 0;
+	return NOTIFY_DONE;
 }
 
 static struct notifier_block cfg80211_netdev_notifier = {
--- wireless-testing.orig/net/wireless/core.h	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/wireless/core.h	2009-05-23 11:18:02.000000000 +0200
@@ -11,6 +11,8 @@
 #include <linux/kref.h>
 #include <linux/rbtree.h>
 #include <linux/debugfs.h>
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "reg.h"
@@ -24,6 +26,11 @@ struct cfg80211_registered_device {
 	 * any call is in progress */
 	struct mutex mtx;
 
+	/* rfkill support */
+	struct rfkill_ops rfkill_ops;
+	struct rfkill *rfkill;
+	struct work_struct rfkill_sync;
+
 	/* ISO / IEC 3166 alpha2 for which this device is receiving
 	 * country IEs on, this can help disregard country IEs from APs
 	 * on the same alpha2 quickly. The alpha2 may differ from
--- wireless-testing.orig/include/net/cfg80211.h	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h	2009-05-23 11:18:02.000000000 +0200
@@ -757,13 +757,11 @@ enum wiphy_params_flags {
  * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
  * @TX_POWER_LIMITED: limit TX power by the dbm parameter
  * @TX_POWER_FIXED: fix TX power to the dbm parameter
- * @TX_POWER_OFF: turn off completely (will go away)
  */
 enum tx_power_setting {
 	TX_POWER_AUTOMATIC,
 	TX_POWER_LIMITED,
 	TX_POWER_FIXED,
-	TX_POWER_OFF,
 };
 
 /**
@@ -855,8 +853,10 @@ enum tx_power_setting {
  *
  * @set_tx_power: set the transmit power according to the parameters
  * @get_tx_power: store the current TX power into the dbm variable;
- *	return 0 if successful; or -ENETDOWN if successful but power
- *	is disabled (this will go away)
+ *	return 0 if successful
+ *
+ * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
+ *	functions to adjust rfkill hw state
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -952,6 +952,8 @@ struct cfg80211_ops {
 	int	(*set_tx_power)(struct wiphy *wiphy,
 				enum tx_power_setting type, int dbm);
 	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
+
+	void	(*rfkill_poll)(struct wiphy *wiphy);
 };
 
 /*
@@ -990,6 +992,8 @@ struct cfg80211_ops {
  * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
  *	-1 = fragmentation disabled, only odd values >= 256 used
  * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ *
+ * @rfkill_poll: poll rfkill via rfkill_poll method, if present
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1003,6 +1007,8 @@ struct wiphy {
 	bool custom_regulatory;
 	bool strict_regulatory;
 
+	bool rfkill_poll;
+
 	enum cfg80211_signal_type signal_type;
 
 	int bss_priv_size;
@@ -1666,4 +1672,11 @@ void cfg80211_michael_mic_failure(struct
  */
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 
+/**
+ * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
+ * @wiphy: the wiphy
+ * @blocked: block status
+ */
+void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked);
+
 #endif /* __NET_CFG80211_H */
--- wireless-testing.orig/net/wireless/Kconfig	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/wireless/Kconfig	2009-05-23 11:18:02.000000000 +0200
@@ -1,5 +1,6 @@
 config CFG80211
-        tristate "Improved wireless configuration API"
+	tristate "Improved wireless configuration API"
+	depends on RFKILL || !RFKILL
 
 config CFG80211_REG_DEBUG
 	bool "cfg80211 regulatory debugging"
--- wireless-testing.orig/net/wireless/wext-compat.c	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c	2009-05-23 11:18:02.000000000 +0200
@@ -764,6 +764,8 @@ int cfg80211_wext_siwtxpower(struct net_
 
 	/* only change when not disabling */
 	if (!data->txpower.disabled) {
+		rfkill_set_sw_state(rdev->rfkill, false);
+
 		if (data->txpower.fixed) {
 			/*
 			 * wext doesn't support negative values, see
@@ -787,7 +789,9 @@ int cfg80211_wext_siwtxpower(struct net_
 			}
 		}
 	} else {
-		type = TX_POWER_OFF;
+		rfkill_set_sw_state(rdev->rfkill, true);
+		schedule_work(&rdev->rfkill_sync);
+		return 0;
 	}
 
 	return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
@@ -811,13 +815,12 @@ int cfg80211_wext_giwtxpower(struct net_
 		return -EOPNOTSUPP;
 
 	err = rdev->ops->get_tx_power(wdev->wiphy, &val);
-	/* HACK!!! */
-	if (err && err != -ENETDOWN)
+	if (err)
 		return err;
 
 	/* well... oh well */
 	data->txpower.fixed = 1;
-	data->txpower.disabled = err == -ENETDOWN;
+	data->txpower.disabled = rfkill_blocked(rdev->rfkill);
 	data->txpower.value = val;
 	data->txpower.flags = IW_TXPOW_DBM;
 
--- wireless-testing.orig/net/mac80211/cfg.c	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c	2009-05-23 11:18:02.000000000 +0200
@@ -1339,7 +1339,6 @@ static int ieee80211_set_tx_power(struct
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_channel *chan = local->hw.conf.channel;
 	u32 changes = 0;
-	bool radio_enabled = true;
 
 	switch (type) {
 	case TX_POWER_AUTOMATIC:
@@ -1358,14 +1357,6 @@ static int ieee80211_set_tx_power(struct
 			return -EINVAL;
 		local->user_power_level = dbm;
 		break;
-	case TX_POWER_OFF:
-		radio_enabled = false;
-		break;
-	}
-
-	if (radio_enabled != local->hw.conf.radio_enabled) {
-		changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
-		local->hw.conf.radio_enabled = radio_enabled;
 	}
 
 	ieee80211_hw_config(local, changes);
@@ -1379,12 +1370,16 @@ static int ieee80211_get_tx_power(struct
 
 	*dbm = local->hw.conf.power_level;
 
-	if (!local->hw.conf.radio_enabled)
-		return -ENETDOWN;
-
 	return 0;
 }
 
+static void ieee80211_rfkill_poll(struct wiphy *wiphy)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	drv_rfkill_poll(local);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1426,4 +1421,5 @@ struct cfg80211_ops mac80211_config_ops 
 	.set_wiphy_params = ieee80211_set_wiphy_params,
 	.set_tx_power = ieee80211_set_tx_power,
 	.get_tx_power = ieee80211_get_tx_power,
+	.rfkill_poll = ieee80211_rfkill_poll,
 };
--- wireless-testing.orig/net/mac80211/iface.c	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2009-05-23 11:18:02.000000000 +0200
@@ -170,7 +170,7 @@ static int ieee80211_open(struct net_dev
 			goto err_del_bss;
 		/* we're brought up, everything changes */
 		hw_reconf_flags = ~0;
-		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+		ieee80211_led_radio(local, true);
 	}
 
 	/*
@@ -560,7 +560,7 @@ static int ieee80211_stop(struct net_dev
 
 		drv_stop(local);
 
-		ieee80211_led_radio(local, 0);
+		ieee80211_led_radio(local, false);
 
 		flush_workqueue(local->hw.workqueue);
 
--- wireless-testing.orig/net/mac80211/util.c	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/mac80211/util.c	2009-05-23 11:18:02.000000000 +0200
@@ -1019,7 +1019,7 @@ int ieee80211_reconfig(struct ieee80211_
 	if (local->open_count) {
 		res = drv_start(local);
 
-		ieee80211_led_radio(local, hw->conf.radio_enabled);
+		ieee80211_led_radio(local, true);
 	}
 
 	/* add interfaces */
--- wireless-testing.orig/include/net/mac80211.h	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/include/net/mac80211.h	2009-05-23 11:18:02.000000000 +0200
@@ -529,7 +529,7 @@ enum ieee80211_conf_flags {
 /**
  * enum ieee80211_conf_changed - denotes which configuration changed
  *
- * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
+ * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED
  * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
  * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
  * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed
@@ -539,7 +539,7 @@ enum ieee80211_conf_flags {
  * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
  */
 enum ieee80211_conf_changed {
-	IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
+	_IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
 	IEEE80211_CONF_CHANGE_LISTEN_INTERVAL	= BIT(2),
 	IEEE80211_CONF_CHANGE_RADIOTAP		= BIT(3),
 	IEEE80211_CONF_CHANGE_PS		= BIT(4),
@@ -549,6 +549,14 @@ enum ieee80211_conf_changed {
 	IEEE80211_CONF_CHANGE_IDLE		= BIT(8),
 };
 
+static inline __deprecated enum ieee80211_conf_changed
+__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
+{
+	return _IEEE80211_CONF_CHANGE_RADIO_ENABLED;
+}
+#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \
+	__IEEE80211_CONF_CHANGE_RADIO_ENABLED()
+
 /**
  * struct ieee80211_conf - configuration of the device
  *
@@ -588,7 +596,7 @@ struct ieee80211_conf {
 	int max_sleep_period;
 
 	u16 listen_interval;
-	bool radio_enabled;
+	bool __deprecated radio_enabled;
 
 	u8 long_frame_max_tx_count, short_frame_max_tx_count;
 
@@ -1399,6 +1407,10 @@ enum ieee80211_ampdu_mlme_action {
  * 	is the first frame we expect to perform the action on. Notice
  * 	that TX/RX_STOP can pass NULL for this parameter.
  *	Returns a negative error code on failure.
+ *
+ * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
+ *	need to set wiphy->rfkill_poll to %true before registration,
+ *	and need to call wiphy_rfkill_set_hw_state() in the callback.
  */
 struct ieee80211_ops {
 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1447,6 +1459,8 @@ struct ieee80211_ops {
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    enum ieee80211_ampdu_mlme_action action,
 			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+
+	void (*rfkill_poll)(struct ieee80211_hw *hw);
 };
 
 /**
--- wireless-testing.orig/net/mac80211/driver-ops.h	2009-05-23 11:18:01.000000000 +0200
+++ wireless-testing/net/mac80211/driver-ops.h	2009-05-23 11:18:02.000000000 +0200
@@ -181,4 +181,11 @@ static inline int drv_ampdu_action(struc
 						sta, tid, ssn);
 	return -EOPNOTSUPP;
 }
+
+
+static inline void drv_rfkill_poll(struct ieee80211_local *local)
+{
+	if (local->ops->rfkill_poll)
+		local->ops->rfkill_poll(&local->hw);
+}
 #endif /* __MAC80211_DRIVER_OPS */



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

* Re: [RFT 3/4] cfg80211: add rfkill support
  2009-05-21 21:59 ` [RFT 3/4] cfg80211: add rfkill support Johannes Berg
  2009-05-23  9:52   ` [RFT 3/4 v2] " Johannes Berg
@ 2009-05-24 13:32   ` Dan Williams
  2009-05-24 17:24     ` Johannes Berg
  2009-05-26 16:38     ` Marcel Holtmann
  1 sibling, 2 replies; 13+ messages in thread
From: Dan Williams @ 2009-05-24 13:32 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On Thu, 2009-05-21 at 23:59 +0200, Johannes Berg wrote:
> plain text document attachment (015-cfg80211-rfkill.patch)
> To be easier on drivers and users, have cfg80211 register an
> rfkill structure that drivers can access. When soft-killed,
> simply take down all interfaces; when hard-killed the driver
> needs to notify us and we will take down the interfaces
> after the fact. While rfkilled, interfaces cannot be set UP.

Any chance we could get something other than EINVAL returned from the
PRE_UP notifier when the device is rfkilled?  It's useful to get some
indication of *why* the device can't be brought up.  For example, if the
device requires firmware but that firmware isn't present, the driver
will usually return ENOENT because that's what request_firmware()
returns when it can't find what it needs.  Thus userspace can do
something intelligent with the error.

So maybe EL2HLT could be (ab)used here?  I guess technically it's an L1
halt since the PHY is powered down, but whatever.  The only other stuff
that seems to use this are the USB 'gadget' drivers.  Either that, or
lets make an EL1OFF or ERFKILL maybe.

Dan

> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>  include/net/cfg80211.h     |   21 +++++++++--
>  include/net/mac80211.h     |   18 ++++++++--
>  net/mac80211/cfg.c         |   20 ++++-------
>  net/mac80211/driver-ops.h  |    7 +++
>  net/mac80211/iface.c       |    4 +-
>  net/mac80211/util.c        |    2 -
>  net/wireless/Kconfig       |    3 +
>  net/wireless/core.c        |   81 +++++++++++++++++++++++++++++++++++++++++++--
>  net/wireless/core.h        |    7 +++
>  net/wireless/wext-compat.c |   11 +++---
>  10 files changed, 145 insertions(+), 29 deletions(-)
> 
> --- wireless-testing.orig/net/wireless/core.c	2009-05-21 21:56:48.000000000 +0200
> +++ wireless-testing/net/wireless/core.c	2009-05-21 23:45:24.000000000 +0200
> @@ -12,6 +12,7 @@
>  #include <linux/debugfs.h>
>  #include <linux/notifier.h>
>  #include <linux/device.h>
> +#include <linux/rtnetlink.h>
>  #include <net/genetlink.h>
>  #include <net/cfg80211.h>
>  #include "nl80211.h"
> @@ -227,6 +228,41 @@ int cfg80211_dev_rename(struct cfg80211_
>  	return 0;
>  }
>  
> +static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
> +{
> +	struct cfg80211_registered_device *drv = data;
> +
> +	drv->ops->rfkill_poll(&drv->wiphy);
> +}
> +
> +static int cfg80211_rfkill_set_block(void *data, bool blocked)
> +{
> +	struct cfg80211_registered_device *drv = data;
> +	struct wireless_dev *wdev;
> +
> +	if (!blocked)
> +		return 0;
> +
> +	rtnl_lock();
> +	mutex_lock(&drv->devlist_mtx);
> +
> +	list_for_each_entry(wdev, &drv->netdev_list, list)
> +		dev_close(wdev->netdev);
> +
> +	mutex_unlock(&drv->devlist_mtx);
> +	rtnl_unlock();
> +
> +	return 0;
> +}
> +
> +void cfg80211_rfkill_sync_work(struct work_struct *work)
> +{
> +	struct cfg80211_registered_device *drv;
> +
> +	drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
> +	cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
> +}
> +
>  /* exported functions */
>  
>  struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
> @@ -274,6 +310,18 @@ struct wiphy *wiphy_new(const struct cfg
>  	drv->wiphy.dev.class = &ieee80211_class;
>  	drv->wiphy.dev.platform_data = drv;
>  
> +	drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
> +	drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
> +				   &drv->wiphy.dev, RFKILL_TYPE_WLAN,
> +				   &drv->rfkill_ops, drv);
> +
> +	if (!drv->rfkill) {
> +		kfree(drv);
> +		return NULL;
> +	}
> +
> +	INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
> +
>  	/*
>  	 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
>  	 * Fragmentation and RTS threshold are disabled by default with the
> @@ -356,6 +404,13 @@ int wiphy_register(struct wiphy *wiphy)
>  	if (res)
>  		goto out_unlock;
>  
> +	if (wiphy->rfkill_poll && drv->ops->rfkill_poll)
> +		drv->rfkill_ops.poll = cfg80211_rfkill_poll;
> +
> +	res = rfkill_register(drv->rfkill);
> +	if (res)
> +		goto out_rm_dev;
> +
>  	list_add(&drv->list, &cfg80211_drv_list);
>  
>  	/* add to debugfs */
> @@ -379,7 +434,11 @@ int wiphy_register(struct wiphy *wiphy)
>  	cfg80211_debugfs_drv_add(drv);
>  
>  	res = 0;
> -out_unlock:
> +	goto out_unlock;
> +
> + out_rm_dev:
> +	device_del(&drv->wiphy.dev);
> + out_unlock:
>  	mutex_unlock(&cfg80211_mutex);
>  	return res;
>  }
> @@ -389,6 +448,8 @@ void wiphy_unregister(struct wiphy *wiph
>  {
>  	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
>  
> +	rfkill_unregister(drv->rfkill);
> +
>  	/* protect the device list */
>  	mutex_lock(&cfg80211_mutex);
>  
> @@ -425,6 +486,7 @@ EXPORT_SYMBOL(wiphy_unregister);
>  void cfg80211_dev_free(struct cfg80211_registered_device *drv)
>  {
>  	struct cfg80211_internal_bss *scan, *tmp;
> +	rfkill_destroy(drv->rfkill);
>  	mutex_destroy(&drv->mtx);
>  	mutex_destroy(&drv->devlist_mtx);
>  	list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
> @@ -438,6 +500,15 @@ void wiphy_free(struct wiphy *wiphy)
>  }
>  EXPORT_SYMBOL(wiphy_free);
>  
> +void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
> +{
> +	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
> +
> +	if (rfkill_set_hw_state(drv->rfkill, blocked))
> +		schedule_work(&drv->rfkill_sync);
> +}
> +EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
> +
>  static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
>  					 unsigned long state,
>  					 void *ndev)
> @@ -446,7 +517,7 @@ static int cfg80211_netdev_notifier_call
>  	struct cfg80211_registered_device *rdev;
>  
>  	if (!dev->ieee80211_ptr)
> -		return 0;
> +		return NOTIFY_DONE;
>  
>  	rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
>  
> @@ -492,9 +563,13 @@ static int cfg80211_netdev_notifier_call
>  		}
>  		mutex_unlock(&rdev->devlist_mtx);
>  		break;
> +	case NETDEV_PRE_UP:
> +		if (rfkill_blocked(rdev->rfkill))
> +			return notifier_from_errno(-EINVAL);
> +		break;
>  	}
>  
> -	return 0;
> +	return NOTIFY_DONE;
>  }
>  
>  static struct notifier_block cfg80211_netdev_notifier = {
> --- wireless-testing.orig/net/wireless/core.h	2009-05-21 21:56:48.000000000 +0200
> +++ wireless-testing/net/wireless/core.h	2009-05-21 22:50:16.000000000 +0200
> @@ -11,6 +11,8 @@
>  #include <linux/kref.h>
>  #include <linux/rbtree.h>
>  #include <linux/debugfs.h>
> +#include <linux/rfkill.h>
> +#include <linux/workqueue.h>
>  #include <net/genetlink.h>
>  #include <net/cfg80211.h>
>  #include "reg.h"
> @@ -24,6 +26,11 @@ struct cfg80211_registered_device {
>  	 * any call is in progress */
>  	struct mutex mtx;
>  
> +	/* rfkill support */
> +	struct rfkill_ops rfkill_ops;
> +	struct rfkill *rfkill;
> +	struct work_struct rfkill_sync;
> +
>  	/* ISO / IEC 3166 alpha2 for which this device is receiving
>  	 * country IEs on, this can help disregard country IEs from APs
>  	 * on the same alpha2 quickly. The alpha2 may differ from
> --- wireless-testing.orig/include/net/cfg80211.h	2009-05-21 21:56:48.000000000 +0200
> +++ wireless-testing/include/net/cfg80211.h	2009-05-21 23:43:53.000000000 +0200
> @@ -757,13 +757,11 @@ enum wiphy_params_flags {
>   * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
>   * @TX_POWER_LIMITED: limit TX power by the dbm parameter
>   * @TX_POWER_FIXED: fix TX power to the dbm parameter
> - * @TX_POWER_OFF: turn off completely (will go away)
>   */
>  enum tx_power_setting {
>  	TX_POWER_AUTOMATIC,
>  	TX_POWER_LIMITED,
>  	TX_POWER_FIXED,
> -	TX_POWER_OFF,
>  };
>  
>  /**
> @@ -855,8 +853,10 @@ enum tx_power_setting {
>   *
>   * @set_tx_power: set the transmit power according to the parameters
>   * @get_tx_power: store the current TX power into the dbm variable;
> - *	return 0 if successful; or -ENETDOWN if successful but power
> - *	is disabled (this will go away)
> + *	return 0 if successful
> + *
> + * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
> + *	functions to adjust rfkill hw state
>   */
>  struct cfg80211_ops {
>  	int	(*suspend)(struct wiphy *wiphy);
> @@ -952,6 +952,8 @@ struct cfg80211_ops {
>  	int	(*set_tx_power)(struct wiphy *wiphy,
>  				enum tx_power_setting type, int dbm);
>  	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
> +
> +	void	(*rfkill_poll)(struct wiphy *wiphy);
>  };
>  
>  /*
> @@ -990,6 +992,8 @@ struct cfg80211_ops {
>   * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
>   *	-1 = fragmentation disabled, only odd values >= 256 used
>   * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
> + *
> + * @rfkill_poll: poll rfkill via rfkill_poll method, if present
>   */
>  struct wiphy {
>  	/* assign these fields before you register the wiphy */
> @@ -1003,6 +1007,8 @@ struct wiphy {
>  	bool custom_regulatory;
>  	bool strict_regulatory;
>  
> +	bool rfkill_poll;
> +
>  	enum cfg80211_signal_type signal_type;
>  
>  	int bss_priv_size;
> @@ -1619,4 +1625,11 @@ void cfg80211_michael_mic_failure(struct
>   */
>  void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
>  
> +/**
> + * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
> + * @wiphy: the wiphy
> + * @blocked: block status
> + */
> +void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked);
> +
>  #endif /* __NET_CFG80211_H */
> --- wireless-testing.orig/net/wireless/Kconfig	2009-05-21 21:56:48.000000000 +0200
> +++ wireless-testing/net/wireless/Kconfig	2009-05-21 22:38:31.000000000 +0200
> @@ -1,5 +1,6 @@
>  config CFG80211
> -        tristate "Improved wireless configuration API"
> +	tristate "Improved wireless configuration API"
> +	depends on RFKILL || !RFKILL
>  
>  config CFG80211_REG_DEBUG
>  	bool "cfg80211 regulatory debugging"
> --- wireless-testing.orig/net/wireless/wext-compat.c	2009-05-21 22:54:28.000000000 +0200
> +++ wireless-testing/net/wireless/wext-compat.c	2009-05-21 23:11:18.000000000 +0200
> @@ -764,6 +764,8 @@ int cfg80211_wext_siwtxpower(struct net_
>  
>  	/* only change when not disabling */
>  	if (!data->txpower.disabled) {
> +		rfkill_set_sw_state(rdev->rfkill, false);
> +
>  		if (data->txpower.fixed) {
>  			/*
>  			 * wext doesn't support negative values, see
> @@ -787,7 +789,9 @@ int cfg80211_wext_siwtxpower(struct net_
>  			}
>  		}
>  	} else {
> -		type = TX_POWER_OFF;
> +		rfkill_set_sw_state(rdev->rfkill, true);
> +		schedule_work(&rdev->rfkill_sync);
> +		return 0;
>  	}
>  
>  	return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
> @@ -811,13 +815,12 @@ int cfg80211_wext_giwtxpower(struct net_
>  		return -EOPNOTSUPP;
>  
>  	err = rdev->ops->get_tx_power(wdev->wiphy, &val);
> -	/* HACK!!! */
> -	if (err && err != -ENETDOWN)
> +	if (err)
>  		return err;
>  
>  	/* well... oh well */
>  	data->txpower.fixed = 1;
> -	data->txpower.disabled = err == -ENETDOWN;
> +	data->txpower.disabled = rfkill_blocked(rdev->rfkill);
>  	data->txpower.value = val;
>  	data->txpower.flags = IW_TXPOW_DBM;
>  
> --- wireless-testing.orig/net/mac80211/cfg.c	2009-05-21 22:57:11.000000000 +0200
> +++ wireless-testing/net/mac80211/cfg.c	2009-05-21 23:49:58.000000000 +0200
> @@ -1339,7 +1339,6 @@ static int ieee80211_set_tx_power(struct
>  	struct ieee80211_local *local = wiphy_priv(wiphy);
>  	struct ieee80211_channel *chan = local->hw.conf.channel;
>  	u32 changes = 0;
> -	bool radio_enabled = true;
>  
>  	switch (type) {
>  	case TX_POWER_AUTOMATIC:
> @@ -1358,14 +1357,6 @@ static int ieee80211_set_tx_power(struct
>  			return -EINVAL;
>  		local->user_power_level = dbm;
>  		break;
> -	case TX_POWER_OFF:
> -		radio_enabled = false;
> -		break;
> -	}
> -
> -	if (radio_enabled != local->hw.conf.radio_enabled) {
> -		changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
> -		local->hw.conf.radio_enabled = radio_enabled;
>  	}
>  
>  	ieee80211_hw_config(local, changes);
> @@ -1379,12 +1370,16 @@ static int ieee80211_get_tx_power(struct
>  
>  	*dbm = local->hw.conf.power_level;
>  
> -	if (!local->hw.conf.radio_enabled)
> -		return -ENETDOWN;
> -
>  	return 0;
>  }
>  
> +static void ieee80211_rfkill_poll(struct wiphy *wiphy)
> +{
> +	struct ieee80211_local *local = wiphy_priv(wiphy);
> +
> +	drv_rfkill_poll(local);
> +}
> +
>  struct cfg80211_ops mac80211_config_ops = {
>  	.add_virtual_intf = ieee80211_add_iface,
>  	.del_virtual_intf = ieee80211_del_iface,
> @@ -1426,4 +1421,5 @@ struct cfg80211_ops mac80211_config_ops 
>  	.set_wiphy_params = ieee80211_set_wiphy_params,
>  	.set_tx_power = ieee80211_set_tx_power,
>  	.get_tx_power = ieee80211_get_tx_power,
> +	.rfkill_poll = ieee80211_rfkill_poll,
>  };
> --- wireless-testing.orig/net/mac80211/iface.c	2009-05-21 22:58:17.000000000 +0200
> +++ wireless-testing/net/mac80211/iface.c	2009-05-21 23:18:00.000000000 +0200
> @@ -170,7 +170,7 @@ static int ieee80211_open(struct net_dev
>  			goto err_del_bss;
>  		/* we're brought up, everything changes */
>  		hw_reconf_flags = ~0;
> -		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
> +		ieee80211_led_radio(local, true);
>  	}
>  
>  	/*
> @@ -560,7 +560,7 @@ static int ieee80211_stop(struct net_dev
>  
>  		drv_stop(local);
>  
> -		ieee80211_led_radio(local, 0);
> +		ieee80211_led_radio(local, false);
>  
>  		flush_workqueue(local->hw.workqueue);
>  
> --- wireless-testing.orig/net/mac80211/util.c	2009-05-21 22:58:36.000000000 +0200
> +++ wireless-testing/net/mac80211/util.c	2009-05-21 23:17:24.000000000 +0200
> @@ -1092,7 +1092,7 @@ int ieee80211_reconfig(struct ieee80211_
>  	if (local->open_count) {
>  		res = drv_start(local);
>  
> -		ieee80211_led_radio(local, hw->conf.radio_enabled);
> +		ieee80211_led_radio(local, true);
>  	}
>  
>  	/* add interfaces */
> --- wireless-testing.orig/include/net/mac80211.h	2009-05-21 22:59:09.000000000 +0200
> +++ wireless-testing/include/net/mac80211.h	2009-05-21 23:48:08.000000000 +0200
> @@ -529,7 +529,7 @@ enum ieee80211_conf_flags {
>  /**
>   * enum ieee80211_conf_changed - denotes which configuration changed
>   *
> - * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
> + * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED
>   * @_IEEE80211_CONF_CHANGE_BEACON_INTERVAL: DEPRECATED
>   * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
>   * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
> @@ -540,7 +540,7 @@ enum ieee80211_conf_flags {
>   * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
>   */
>  enum ieee80211_conf_changed {
> -	IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
> +	_IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
>  	_IEEE80211_CONF_CHANGE_BEACON_INTERVAL	= BIT(1),
>  	IEEE80211_CONF_CHANGE_LISTEN_INTERVAL	= BIT(2),
>  	IEEE80211_CONF_CHANGE_RADIOTAP		= BIT(3),
> @@ -559,6 +559,14 @@ __IEEE80211_CONF_CHANGE_BEACON_INTERVAL(
>  #define IEEE80211_CONF_CHANGE_BEACON_INTERVAL \
>  	__IEEE80211_CONF_CHANGE_BEACON_INTERVAL()
>  
> +static inline __deprecated enum ieee80211_conf_changed
> +__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
> +{
> +	return _IEEE80211_CONF_CHANGE_RADIO_ENABLED;
> +}
> +#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \
> +	__IEEE80211_CONF_CHANGE_RADIO_ENABLED()
> +
>  /**
>   * struct ieee80211_conf - configuration of the device
>   *
> @@ -1419,6 +1427,10 @@ enum ieee80211_ampdu_mlme_action {
>   * 	is the first frame we expect to perform the action on. Notice
>   * 	that TX/RX_STOP can pass NULL for this parameter.
>   *	Returns a negative error code on failure.
> + *
> + * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
> + *	need to set wiphy->rfkill_poll to %true before registration,
> + *	and need to call wiphy_rfkill_set_hw_state() in the callback.
>   */
>  struct ieee80211_ops {
>  	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
> @@ -1467,6 +1479,8 @@ struct ieee80211_ops {
>  	int (*ampdu_action)(struct ieee80211_hw *hw,
>  			    enum ieee80211_ampdu_mlme_action action,
>  			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
> +
> +	void (*rfkill_poll)(struct ieee80211_hw *hw);
>  };
>  
>  /**
> --- wireless-testing.orig/net/mac80211/driver-ops.h	2009-05-21 23:49:10.000000000 +0200
> +++ wireless-testing/net/mac80211/driver-ops.h	2009-05-21 23:49:43.000000000 +0200
> @@ -181,4 +181,11 @@ static inline int drv_ampdu_action(struc
>  						sta, tid, ssn);
>  	return -EOPNOTSUPP;
>  }
> +
> +
> +static inline void drv_rfkill_poll(struct ieee80211_local *local)
> +{
> +	if (local->ops->rfkill_poll)
> +		local->ops->rfkill_poll(&local->hw);
> +}
>  #endif /* __MAC80211_DRIVER_OPS */
> 


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

* Re: [RFT 3/4] cfg80211: add rfkill support
  2009-05-24 13:32   ` [RFT 3/4] " Dan Williams
@ 2009-05-24 17:24     ` Johannes Berg
  2009-05-26 16:38     ` Marcel Holtmann
  1 sibling, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-24 17:24 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-wireless

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

On Sun, 2009-05-24 at 09:32 -0400, Dan Williams wrote:
> On Thu, 2009-05-21 at 23:59 +0200, Johannes Berg wrote:
> > plain text document attachment (015-cfg80211-rfkill.patch)
> > To be easier on drivers and users, have cfg80211 register an
> > rfkill structure that drivers can access. When soft-killed,
> > simply take down all interfaces; when hard-killed the driver
> > needs to notify us and we will take down the interfaces
> > after the fact. While rfkilled, interfaces cannot be set UP.
> 
> Any chance we could get something other than EINVAL returned from the
> PRE_UP notifier when the device is rfkilled?  It's useful to get some
> indication of *why* the device can't be brought up.  For example, if the
> device requires firmware but that firmware isn't present, the driver
> will usually return ENOENT because that's what request_firmware()
> returns when it can't find what it needs.  Thus userspace can do
> something intelligent with the error.
> 
> So maybe EL2HLT could be (ab)used here?  I guess technically it's an L1
> halt since the PHY is powered down, but whatever.  The only other stuff
> that seems to use this are the USB 'gadget' drivers.  Either that, or
> lets make an EL1OFF or ERFKILL maybe.

Sure, we can do whatever we want, I just quickly put EINVAL in.

johannes

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

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

* Re: [RFT 5/4] iwm: port to new cfg80211 rfkill
  2009-05-23  8:52 ` [RFT 5/4] iwm: port to new " Johannes Berg
@ 2009-05-25  1:22   ` Zhu Yi
  2009-05-25  5:13     ` Johannes Berg
  0 siblings, 1 reply; 13+ messages in thread
From: Zhu Yi @ 2009-05-25  1:22 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Samuel Ortiz

On Sat, 2009-05-23 at 16:52 +0800, Johannes Berg wrote:
> Which means removing all rfkill code since it only does
> soft-kill which cfg80211 will now handle in exactly the
> same way the driver did.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

Looks good to me. I think we can remove the "select RFKILL" in Kconfig
also.

Thanks,
-yi
> ---
>  drivers/net/wireless/iwmc3200wifi/Makefile |    2 
>  drivers/net/wireless/iwmc3200wifi/iwm.h    |    4 -
>  drivers/net/wireless/iwmc3200wifi/netdev.c |   10 ---
>  drivers/net/wireless/iwmc3200wifi/rfkill.c |   83 -----------------------------
>  4 files changed, 1 insertion(+), 98 deletions(-)
> 
> --- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/Makefile	2009-05-23 10:48:02.000000000 +0200
> +++ wireless-testing/drivers/net/wireless/iwmc3200wifi/Makefile	2009-05-23 10:49:23.000000000 +0200
> @@ -1,5 +1,5 @@
>  obj-$(CONFIG_IWM) := iwmc3200wifi.o
>  iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
> -iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o rfkill.o
> +iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o
>  
>  iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
> --- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/rfkill.c	2009-05-23 10:48:02.000000000 +0200
> +++ /dev/null	1970-01-01 00:00:00.000000000 +0000
> @@ -1,83 +0,0 @@
> -/*
> - * Intel Wireless Multicomm 3200 WiFi driver
> - *
> - * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
> - * Samuel Ortiz <samuel.ortiz@intel.com>
> - * Zhu Yi <yi.zhu@intel.com>
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License version
> - * 2 as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> - * 02110-1301, USA.
> - *
> - */
> -
> -#include <linux/rfkill.h>
> -
> -#include "iwm.h"
> -
> -static int iwm_rfkill_set_block(void *data, bool blocked)
> -{
> -	struct iwm_priv *iwm = data;
> -
> -	if (!blocked) {
> -		if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio))
> -			return -EBUSY;
> -
> -		if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) &&
> -		    (iwm_to_ndev(iwm)->flags & IFF_UP))
> -			return iwm_up(iwm);
> -	} else {
> -		if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
> -			return iwm_down(iwm);
> -	}
> -
> -	return 0;
> -}
> -
> -static const struct rfkill_ops iwm_rfkill_ops = {
> -	.set_block = iwm_rfkill_set_block,
> -};
> -
> -int iwm_rfkill_init(struct iwm_priv *iwm)
> -{
> -	int ret;
> -
> -	iwm->rfkill = rfkill_alloc(KBUILD_MODNAME,
> -				   iwm_to_dev(iwm),
> -				   RFKILL_TYPE_WLAN,
> -				   &iwm_rfkill_ops, iwm);
> -	if (!iwm->rfkill) {
> -		IWM_ERR(iwm, "Unable to allocate rfkill device\n");
> -		return -ENOMEM;
> -	}
> -
> -	ret = rfkill_register(iwm->rfkill);
> -	if (ret) {
> -		IWM_ERR(iwm, "Failed to register rfkill device\n");
> -		goto fail;
> -	}
> -
> -	return 0;
> - fail:
> -	rfkill_destroy(iwm->rfkill);
> -	return ret;
> -}
> -
> -void iwm_rfkill_exit(struct iwm_priv *iwm)
> -{
> -	if (iwm->rfkill) {
> -		rfkill_unregister(iwm->rfkill);
> -		rfkill_destroy(iwm->rfkill);
> -	}
> -	iwm->rfkill = NULL;
> -}
> --- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/iwm.h	2009-05-23 10:51:09.000000000 +0200
> +++ wireless-testing/drivers/net/wireless/iwmc3200wifi/iwm.h	2009-05-23 10:51:12.000000000 +0200
> @@ -343,8 +343,4 @@ int iwm_rx_handle_resp(struct iwm_priv *
>  		       struct iwm_wifi_cmd *cmd);
>  void iwm_rx_free(struct iwm_priv *iwm);
>  
> -/* RF Kill API */
> -int iwm_rfkill_init(struct iwm_priv *iwm);
> -void iwm_rfkill_exit(struct iwm_priv *iwm);
> -
>  #endif
> --- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/netdev.c	2009-05-23 10:51:18.000000000 +0200
> +++ wireless-testing/drivers/net/wireless/iwmc3200wifi/netdev.c	2009-05-23 10:51:29.000000000 +0200
> @@ -136,17 +136,8 @@ void *iwm_if_alloc(int sizeof_bus, struc
>  
>  	wdev->netdev = ndev;
>  
> -	ret = iwm_rfkill_init(iwm);
> -	if (ret) {
> -		dev_err(dev, "Failed to init rfkill\n");
> -		goto out_rfkill;
> -	}
> -
>  	return iwm;
>  
> - out_rfkill:
> -	unregister_netdev(ndev);
> -
>   out_ndev:
>  	free_netdev(ndev);
>  
> @@ -162,7 +153,6 @@ void iwm_if_free(struct iwm_priv *iwm)
>  	if (!iwm_to_ndev(iwm))
>  		return;
>  
> -	iwm_rfkill_exit(iwm);
>  	unregister_netdev(iwm_to_ndev(iwm));
>  	free_netdev(iwm_to_ndev(iwm));
>  	iwm_wdev_free(iwm);
> 
> 


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

* Re: [RFT 5/4] iwm: port to new cfg80211 rfkill
  2009-05-25  1:22   ` Zhu Yi
@ 2009-05-25  5:13     ` Johannes Berg
  0 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2009-05-25  5:13 UTC (permalink / raw)
  To: Zhu Yi; +Cc: linux-wireless, Samuel Ortiz

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

On Mon, 2009-05-25 at 09:22 +0800, Zhu Yi wrote:
> On Sat, 2009-05-23 at 16:52 +0800, Johannes Berg wrote:
> > Which means removing all rfkill code since it only does
> > soft-kill which cfg80211 will now handle in exactly the
> > same way the driver did.
> > 
> > Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> 
> Looks good to me. I think we can remove the "select RFKILL" in Kconfig
> also.

Indeed, thanks.

johannes

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

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

* Re: [RFT 3/4] cfg80211: add rfkill support
  2009-05-24 13:32   ` [RFT 3/4] " Dan Williams
  2009-05-24 17:24     ` Johannes Berg
@ 2009-05-26 16:38     ` Marcel Holtmann
  1 sibling, 0 replies; 13+ messages in thread
From: Marcel Holtmann @ 2009-05-26 16:38 UTC (permalink / raw)
  To: Dan Williams; +Cc: Johannes Berg, linux-wireless

Hi Dan,

> > plain text document attachment (015-cfg80211-rfkill.patch)
> > To be easier on drivers and users, have cfg80211 register an
> > rfkill structure that drivers can access. When soft-killed,
> > simply take down all interfaces; when hard-killed the driver
> > needs to notify us and we will take down the interfaces
> > after the fact. While rfkilled, interfaces cannot be set UP.
> 
> Any chance we could get something other than EINVAL returned from the
> PRE_UP notifier when the device is rfkilled?  It's useful to get some
> indication of *why* the device can't be brought up.  For example, if the
> device requires firmware but that firmware isn't present, the driver
> will usually return ENOENT because that's what request_firmware()
> returns when it can't find what it needs.  Thus userspace can do
> something intelligent with the error.
> 
> So maybe EL2HLT could be (ab)used here?  I guess technically it's an L1
> halt since the PHY is powered down, but whatever.  The only other stuff
> that seems to use this are the USB 'gadget' drivers.  Either that, or
> lets make an EL1OFF or ERFKILL maybe.

I think that creating ERFKILL is a really good idea. We should do that.

Regards

Marcel



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

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

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-21 21:59 [RFT 0/4] rfkill improvements Johannes Berg
2009-05-21 21:59 ` [RFT 1/4] net: introduce pre-up netdev notifier Johannes Berg
2009-05-21 21:59 ` [RFT 2/4] rfkill: add function to query state Johannes Berg
2009-05-21 21:59 ` [RFT 3/4] cfg80211: add rfkill support Johannes Berg
2009-05-23  9:52   ` [RFT 3/4 v2] " Johannes Berg
2009-05-24 13:32   ` [RFT 3/4] " Dan Williams
2009-05-24 17:24     ` Johannes Berg
2009-05-26 16:38     ` Marcel Holtmann
2009-05-21 21:59 ` [RFT 4/4] iwlwifi: port to cfg80211 rfkill Johannes Berg
2009-05-23  8:49   ` [RFT 4/4 v2] " Johannes Berg
2009-05-23  8:52 ` [RFT 5/4] iwm: port to new " Johannes Berg
2009-05-25  1:22   ` Zhu Yi
2009-05-25  5:13     ` Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.