Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCHv2] mac80211: Fix circular locking dependency in ARP filter handling
From: Johannes Berg @ 2010-06-08 13:14 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linville, linux-wireless, reinette.chatre
In-Reply-To: <1276002335-18600-1-git-send-email-juuso.oikarinen@nokia.com>

On Tue, 2010-06-08 at 16:05 +0300, Juuso Oikarinen wrote:

> +		promisc = sdata->flags & IEEE80211_SDATA_PROMISC;
> +		if (promisc)
> +			bss_conf->arp_filter_enabled = 0;
> +		else
> +			bss_conf->arp_filter_enabled = sdata->arp_filter_state;

bss_conf->arp_filter_enabled = !promisc && sdata->arp_filter_state;

?

Or if not, use false instead of 0 please.

johannes


^ permalink raw reply

* [PATCHv2] mac80211: Fix circular locking dependency in ARP filter handling
From: Juuso Oikarinen @ 2010-06-08 13:05 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, reinette.chatre

There is a circular locking dependency when configuring the
hardware ARP filters on association, occurring when flushing the mac80211
workqueue. This is what happens:

[   92.026800] =======================================================
[   92.030507] [ INFO: possible circular locking dependency detected ]
[   92.030507] 2.6.34-04781-g2b2c009 #85
[   92.030507] -------------------------------------------------------
[   92.030507] modprobe/5225 is trying to acquire lock:
[   92.030507]  ((wiphy_name(local->hw.wiphy))){+.+.+.}, at: [<ffffffff8105b5c0>] flush_workq
ueue+0x0/0xb0
[   92.030507]
[   92.030507] but task is already holding lock:
[   92.030507]  (rtnl_mutex){+.+.+.}, at: [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]
[   92.030507] which lock already depends on the new lock.
[   92.030507]
[   92.030507]
[   92.030507] the existing dependency chain (in reverse order) is:
[   92.030507]
[   92.030507] -> #2 (rtnl_mutex){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff81341754>] mutex_lock_nested+0x44/0x300
[   92.030507]        [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]        [<ffffffffa022d47c>] ieee80211_assoc_done+0x6c/0xe0 [mac80211]
[   92.030507]        [<ffffffffa022f2ad>] ieee80211_work_work+0x31d/0x1280 [mac80211]

[   92.030507] -> #1 ((&local->work_work)){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105a51a>] worker_thread+0x22a/0x370
[   92.030507]        [<ffffffff8105ecc6>] kthread+0x96/0xb0
[   92.030507]        [<ffffffff81003a94>] kernel_thread_helper+0x4/0x10
[   92.030507]
[   92.030507] -> #0 ((wiphy_name(local->hw.wiphy))){+.+.+.}:
[   92.030507]        [<ffffffff81075fdc>] __lock_acquire+0x1c0c/0x1d50
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105b60e>] flush_workqueue+0x4e/0xb0
[   92.030507]        [<ffffffffa023ff7b>] ieee80211_stop_device+0x2b/0xb0 [mac80211]
[   92.030507]        [<ffffffffa0231635>] ieee80211_stop+0x3e5/0x680 [mac80211]

The locking in this case is quite complex. Fix the problem by rewriting the
way the hardware ARP filter list is handled - i.e. make a copy of the address
list to the bss_conf struct, and provide that list to the hardware driver
when needed.

Additionally, this patch ensures that hardware ARP filtering is not enabled
when promiscuous mode is set.

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
v2: Do not enable ARP filtering if in promiscuous mode

 include/net/mac80211.h      |   34 +++++----
 net/mac80211/driver-ops.h   |   17 -----
 net/mac80211/driver-trace.h |   25 -------
 net/mac80211/ieee80211_i.h  |    2 +
 net/mac80211/main.c         |  168 +++++++++++++++++++++++++++++--------------
 net/mac80211/mlme.c         |   39 ++++++----
 6 files changed, 159 insertions(+), 126 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e3c1d47..f409d00 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -19,7 +19,6 @@
 #include <linux/wireless.h>
 #include <linux/device.h>
 #include <linux/ieee80211.h>
-#include <linux/inetdevice.h>
 #include <net/cfg80211.h>
 
 /**
@@ -147,6 +146,7 @@ struct ieee80211_low_level_stats {
  *	enabled/disabled (beaconing modes)
  * @BSS_CHANGED_CQM: Connection quality monitor config changed
  * @BSS_CHANGED_IBSS: IBSS join status changed
+ * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -161,10 +161,18 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_BEACON_ENABLED	= 1<<9,
 	BSS_CHANGED_CQM			= 1<<10,
 	BSS_CHANGED_IBSS		= 1<<11,
+	BSS_CHANGED_ARP_FILTER		= 1<<12,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
 
+/*
+ * The maximum number of IPv4 addresses listed for ARP filtering. If the number
+ * of addresses for an interface increase beyond this value, hardware ARP
+ * filtering will be disabled.
+ */
+#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
+
 /**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
@@ -200,6 +208,14 @@ enum ieee80211_bss_change {
  * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
  *	implies disabled
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
+ * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
+ *	may filter ARP queries targeted for other addresses than listed here.
+ *	The driver must allow ARP queries targeted for all address listed here
+ *	to pass through. An empty list implies no ARP queries need to pass.
+ * @arp_addr_cnt: Number of addresses currently on the list.
+ * @arp_filter_enabled: Enable ARP filtering - if enabled, the hardware may
+ *      filter ARP queries based on the @arp_addr_list, if disabled, the
+ *      hardware must not perform any ARP filtering.
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -220,6 +236,9 @@ struct ieee80211_bss_conf {
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
 	enum nl80211_channel_type channel_type;
+	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
+	u8 arp_addr_cnt;
+	bool arp_filter_enabled;
 };
 
 /**
@@ -1529,16 +1548,6 @@ enum ieee80211_ampdu_mlme_action {
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
- * @configure_arp_filter: Configuration function for hardware ARP query filter.
- *	This function is called with all the IP addresses configured to the
- *	interface as argument - all ARP queries targeted to any of these
- *	addresses must pass through. If the hardware filter does not support
- *	enought addresses, hardware filtering must be disabled. The ifa_list
- *	argument may be NULL, indicating that filtering must be disabled.
- *	This function is called upon association complete with current
- *	address(es), and while associated whenever the IP address(es) change.
- *	The callback can sleep.
- *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -1678,9 +1687,6 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
-	int (*configure_arp_filter)(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct in_ifaddr *ifa_list);
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index d1139e4..bbea3bc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -83,23 +83,6 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
 	trace_drv_bss_info_changed(local, sdata, info, changed);
 }
 
-struct in_ifaddr;
-static inline int drv_configure_arp_filter(struct ieee80211_local *local,
-					   struct ieee80211_vif *vif,
-					   struct in_ifaddr *ifa_list)
-{
-	int ret = 0;
-
-	might_sleep();
-
-	if (local->ops->configure_arp_filter)
-		ret = local->ops->configure_arp_filter(&local->hw, vif,
-						       ifa_list);
-
-	trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
-	return ret;
-}
-
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6b90630..1e293df 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -219,31 +219,6 @@ TRACE_EVENT(drv_bss_info_changed,
 	)
 );
 
-TRACE_EVENT(drv_configure_arp_filter,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct in_ifaddr *ifa_list, int ret),
-
-	TP_ARGS(local, sdata, ifa_list, ret),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__field(int, ret)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		__entry->ret = ret;
-	),
-
-	TP_printk(
-		VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
-		VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
-	)
-);
-
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4d3883e..79e366e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -517,6 +517,8 @@ struct ieee80211_sub_if_data {
 
 	u16 sequence_number;
 
+	bool arp_filter_state;
+
 	/*
 	 * AP this belongs to: self in AP mode and
 	 * corresponding AP in VLAN mode, NULL for
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5706156..8398d36 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -20,6 +20,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/bitmap.h>
 #include <linux/pm_qos_params.h>
+#include <linux/inetdevice.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
 
@@ -84,12 +85,125 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
 	local->filter_flags = new_flags & ~(1<<31);
 }
 
+#ifdef CONFIG_INET
+static void ieee80211_reconfig_arp_filter(struct ieee80211_local *local)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_managed *ifmgd;
+	struct ieee80211_bss_conf *bss_conf;
+	u32 changed;
+	bool promisc;
+	bool old_state;
+
+	/* Check ARP filtering state for each interface */
+	rtnl_lock();
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (sdata->vif.type != NL80211_IFTYPE_STATION)
+				continue;
+
+		ifmgd = &sdata->u.mgd;
+		mutex_lock(&ifmgd->mtx);
+		if (!ifmgd->associated) {
+			mutex_unlock(&ifmgd->mtx);
+			continue;
+		}
+
+		bss_conf = &sdata->vif.bss_conf;
+
+		old_state = !!(bss_conf->arp_filter_enabled);
+
+		promisc = sdata->flags & IEEE80211_SDATA_PROMISC;
+		if (promisc)
+			bss_conf->arp_filter_enabled = 0;
+		else
+			bss_conf->arp_filter_enabled = sdata->arp_filter_state;
+
+		if (old_state != bss_conf->arp_filter_enabled) {
+			changed = BSS_CHANGED_ARP_FILTER;
+			ieee80211_bss_info_change_notify(sdata, changed);
+		}
+
+		mutex_unlock(&ifmgd->mtx);
+	}
+	rtnl_unlock();
+}
+
+static int ieee80211_ifa_changed(struct notifier_block *nb,
+				 unsigned long data, void *arg)
+{
+	struct in_ifaddr *ifa = arg;
+	struct ieee80211_local *local =
+		container_of(nb, struct ieee80211_local,
+			     ifa_notifier);
+	struct net_device *ndev = ifa->ifa_dev->dev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	struct in_device *idev;
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_bss_conf *bss_conf;
+	struct ieee80211_if_managed *ifmgd;
+	int c = 0;
+
+	/* Make sure it's our interface that got changed */
+	if (!wdev)
+		return NOTIFY_DONE;
+
+	if (wdev->wiphy != local->hw.wiphy)
+		return NOTIFY_DONE;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	bss_conf = &sdata->vif.bss_conf;
+
+	/* ARP filtering is only supported in managed mode */
+	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+		return NOTIFY_DONE;
+
+	idev = sdata->dev->ip_ptr;
+	if (!idev)
+		return NOTIFY_DONE;
+
+	ifmgd = &sdata->u.mgd;
+	mutex_lock(&ifmgd->mtx);
+
+	/* Copy the addresses to the bss_conf list */
+	ifa = idev->ifa_list;
+	while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
+		bss_conf->arp_addr_list[c] = ifa->ifa_address;
+		ifa = ifa->ifa_next;
+		c++;
+	}
+
+	/* If not all addresses fit the list, disable filtering */
+	if (ifa) {
+		sdata->arp_filter_state = false;
+		c = 0;
+	} else {
+		sdata->arp_filter_state = true;
+	}
+	bss_conf->arp_addr_cnt = c;
+
+	/* Configure driver only if associated and not in promiscuous mode */
+	if (ifmgd->associated && !(sdata->flags & IEEE80211_SDATA_PROMISC)) {
+		bss_conf->arp_filter_enabled = sdata->arp_filter_state;
+		ieee80211_bss_info_change_notify(sdata,
+						 BSS_CHANGED_ARP_FILTER);
+	}
+
+	mutex_unlock(&ifmgd->mtx);
+
+	return NOTIFY_DONE;
+}
+#endif
+
 static void ieee80211_reconfig_filter(struct work_struct *work)
 {
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, reconfig_filter);
 
 	ieee80211_configure_filter(local);
+
+#ifdef CONFIG_INET
+	ieee80211_reconfig_arp_filter(local);
+#endif
 }
 
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
@@ -329,60 +443,6 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
 	mutex_unlock(&local->iflist_mtx);
 }
 
-#ifdef CONFIG_INET
-int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
-{
-	struct in_device *idev;
-	int ret = 0;
-
-	BUG_ON(!sdata);
-	ASSERT_RTNL();
-
-	idev = sdata->dev->ip_ptr;
-	if (!idev)
-		return 0;
-
-	ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
-				       idev->ifa_list);
-	return ret;
-}
-
-static int ieee80211_ifa_changed(struct notifier_block *nb,
-				 unsigned long data, void *arg)
-{
-	struct in_ifaddr *ifa = arg;
-	struct ieee80211_local *local =
-		container_of(nb, struct ieee80211_local,
-			     ifa_notifier);
-	struct net_device *ndev = ifa->ifa_dev->dev;
-	struct wireless_dev *wdev = ndev->ieee80211_ptr;
-	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_if_managed *ifmgd;
-
-	/* Make sure it's our interface that got changed */
-	if (!wdev)
-		return NOTIFY_DONE;
-
-	if (wdev->wiphy != local->hw.wiphy)
-		return NOTIFY_DONE;
-
-	/* We are concerned about IP addresses only when associated */
-	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-
-	/* ARP filtering is only supported in managed mode */
-	if (sdata->vif.type != NL80211_IFTYPE_STATION)
-		return NOTIFY_DONE;
-
-	ifmgd = &sdata->u.mgd;
-	mutex_lock(&ifmgd->mtx);
-	if (ifmgd->associated)
-		ieee80211_set_arp_filter(sdata);
-	mutex_unlock(&ifmgd->mtx);
-
-	return NOTIFY_DONE;
-}
-#endif
-
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 					const struct ieee80211_ops *ops)
 {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ac68c41..d328e9a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -806,11 +806,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_bss *bss = (void *)cbss->priv;
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 
 	bss_info_changed |= BSS_CHANGED_ASSOC;
 	/* set timing information */
-	sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
-	sdata->vif.bss_conf.timestamp = cbss->tsf;
+	bss_conf->beacon_int = cbss->beacon_interval;
+	bss_conf->timestamp = cbss->tsf;
 
 	bss_info_changed |= BSS_CHANGED_BEACON_INT;
 	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
@@ -835,7 +836,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 
 	ieee80211_led_assoc(local, 1);
 
-	sdata->vif.bss_conf.assoc = 1;
+	bss_conf->assoc = 1;
 	/*
 	 * For now just always ask the driver to update the basic rateset
 	 * when we have associated, we aren't checking whether it actually
@@ -848,9 +849,18 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 
 	/* Tell the driver to monitor connection quality (if supported) */
 	if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) &&
-	    sdata->vif.bss_conf.cqm_rssi_thold)
+	    bss_conf->cqm_rssi_thold)
 		bss_info_changed |= BSS_CHANGED_CQM;
 
+#ifdef CONFIG_INET
+	/* Enable ARP filtering unless in promisc mode */
+	if (!(sdata->flags & IEEE80211_SDATA_PROMISC) &&
+	    bss_conf->arp_filter_enabled != sdata->arp_filter_state) {
+		bss_conf->arp_filter_enabled = sdata->arp_filter_state;
+		bss_info_changed |= BSS_CHANGED_ARP_FILTER;
+	}
+#endif
+
 	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
 	mutex_lock(&local->iflist_mtx);
@@ -932,6 +942,13 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	ieee80211_hw_config(local, config_changed);
 
+	/* Disable ARP filtering */
+	if (sdata->vif.bss_conf.arp_filter_enabled) {
+		sdata->vif.bss_conf.arp_filter_enabled = false;
+		changed |= BSS_CHANGED_ARP_FILTER;
+	}
+
+
 	/* The BSSID (not really interesting) and HT changed */
 	changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
 	ieee80211_bss_info_change_notify(sdata, changed);
@@ -2116,19 +2133,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 			cfg80211_send_assoc_timeout(wk->sdata->dev,
 						    wk->filter_ta);
 			return WORK_DONE_DESTROY;
-#ifdef CONFIG_INET
-		} else {
-			mutex_unlock(&wk->sdata->u.mgd.mtx);
-
-			/*
-			 * configure ARP filter IP addresses to the driver,
-			 * intentionally outside the mgd mutex.
-			 */
-			rtnl_lock();
-			ieee80211_set_arp_filter(wk->sdata);
-			rtnl_unlock();
-#endif
 		}
+
+		mutex_unlock(&wk->sdata->u.mgd.mtx);
 	}
 
 	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
-- 
1.6.3.3


^ permalink raw reply related

* Re: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network
From: Johannes Berg @ 2010-06-08 12:48 UTC (permalink / raw)
  To: Teemu Paasikivi; +Cc: linville, linux-wireless
In-Reply-To: <1276000459-1121-4-git-send-email-ext-teemu.3.paasikivi@nokia.com>

On Tue, 2010-06-08 at 15:34 +0300, Teemu Paasikivi wrote:
> When joinig a ibss network, basic rates for bss were not stored. When
> network was self created, leaving and (re)joining same network has
> caused basic rates to be left unset. With this patch stored values are
> used.

>  	bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
>  					mgmt, skb->len, 0, GFP_KERNEL);
> +
> +	ibss = (struct ieee80211_bss *)(bss->priv);

Watch out -- bss can be NULL here if memory allocation fails. It's just
that put_bss(NULL) is valid.

> +	for (i = 0; i < sband->n_bitrates; i++) {
> +		u8 basic = 0x00;
> +		if (basic_rates & BIT(i))
> +			basic = 0x80;
> +
> +		ibss->supp_rates[i] = supp_rates[i] | basic;
> +	}
> +
> +	ibss->supp_rates_len = i;
> +
>  	cfg80211_put_bss(bss);


However this kinda confuses me.

We had a long-standing TODO item on our list at
http://wireless.kernel.org/en/developers/todo-list

"when leaving an IBSS and we were the only member, remove it from
cfg80211's BSS list"

Maybe that would help here too?

However I don't understand the scenario anyway. If you create an IBSS,
you start beaconing and tell cfg80211 about it with a frame that
includes the supported and basic rates. Then you leave, but the BSS
stays around in cfg80211 for 15 seconds. If you re-join within those 15
seconds, the scan results will pick up the old IBSS that no longer
exists, and we "join" it rather than creating it.

However -- joining it will take the basic rates from it. So wouldn't you
get the old basic rates which is fine? What do you mean by "left unset"?

What happens if you join an IBSS that already exists?

johannes


^ permalink raw reply

* [RFC] iw: Configure basic rates when joining ibss network
From: Teemu Paasikivi @ 2010-06-08 12:37 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Teemu Paasikivi

This patch adds configuration option to configure basic rates when
joining ibss network.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
---
 ibss.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/ibss.c b/ibss.c
index 4715ac8..edc83fd 100644
--- a/ibss.c
+++ b/ibss.c
@@ -18,6 +18,11 @@ static int join_ibss(struct nl80211_state *state,
 {
 	char *end;
 	unsigned char abssid[6];
+	unsigned char rates[NL80211_MAX_SUPP_RATES];
+	int n_rates = 0;
+	char *value = NULL, *sptr = NULL;
+	float rate;
+
 
 	if (argc < 2)
 		return 1;
@@ -41,6 +46,24 @@ static int join_ibss(struct nl80211_state *state,
 		argc--;
 	}
 
+	if (argc > 1 && strcmp(argv[0], "basic-rates") == 0) {
+		argv++;
+		argc--;
+
+		value = strtok_r(argv[0], ",", &sptr);
+
+		while (value && n_rates < NL80211_MAX_SUPP_RATES) {
+			rate = atof(value);
+			rates[n_rates++] = rate * 2;
+			value = strtok_r(NULL, ",", &sptr);
+		}
+
+		NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, n_rates, rates);
+
+		argv++;
+		argc--;
+	}
+
 	if (argc) {
 		if (mac_addr_a2n(abssid, argv[0]) == 0) {
 			NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
@@ -73,7 +96,9 @@ static int leave_ibss(struct nl80211_state *state,
 COMMAND(ibss, leave, NULL,
 	NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
 	"Leave the current IBSS cell.");
-COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
+COMMAND(ibss, join,
+	"<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] "
+	"[basic-rates <rate in Mbps,rate2,...>] [key d:0:abcde]",
 	NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
 	"Join the IBSS cell with the given SSID, if it doesn't exist create\n"
 	"it on the given frequency. When fixed frequency is requested, don't\n"
-- 
1.5.6.3


^ permalink raw reply related

* [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network
From: Teemu Paasikivi @ 2010-06-08 12:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1276000459-1121-3-git-send-email-ext-teemu.3.paasikivi@nokia.com>

When joinig a ibss network, basic rates for bss were not stored. When
network was self created, leaving and (re)joining same network has
caused basic rates to be left unset. With this patch stored values are
used.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
---
 net/mac80211/ibss.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d984ab2..72407f0 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -77,6 +77,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	struct cfg80211_bss *bss;
 	u32 bss_change;
 	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+	struct ieee80211_bss *ibss;
 
 	/* Reset own TSF to allow time synchronization work. */
 	drv_reset_tsf(local);
@@ -191,6 +192,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
 	bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
 					mgmt, skb->len, 0, GFP_KERNEL);
+
+	ibss = (struct ieee80211_bss *)(bss->priv);
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		u8 basic = 0x00;
+		if (basic_rates & BIT(i))
+			basic = 0x80;
+
+		ibss->supp_rates[i] = supp_rates[i] | basic;
+	}
+
+	ibss->supp_rates_len = i;
+
 	cfg80211_put_bss(bss);
 	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
 }
-- 
1.5.6.3


^ permalink raw reply related

* [RFC 2/3] mac80211: Set changed basic rates flag
From: Teemu Paasikivi @ 2010-06-08 12:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1276000459-1121-2-git-send-email-ext-teemu.3.paasikivi@nokia.com>

Add changed basic rates flag to bss_changed while joinig ibss network.

This patch is split from the patch containing support for setting basic
rates when creating ibss network. Original patch was posted by Johannes
Berg on the linux-wireless posting list.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
---
 net/mac80211/ibss.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8be5a96..d984ab2 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -179,6 +179,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	bss_change |= BSS_CHANGED_BEACON;
 	bss_change |= BSS_CHANGED_BEACON_ENABLED;
 	bss_change |= BSS_CHANGED_IBSS;
+	bss_change |= BSS_CHANGED_BASIC_RATES;
 	sdata->vif.bss_conf.ibss_joined = true;
 	ieee80211_bss_info_change_notify(sdata, bss_change);
 
-- 
1.5.6.3


^ permalink raw reply related

* [RFC 1/3] mac80211: Set basic rates while joining ibss network
From: Teemu Paasikivi @ 2010-06-08 12:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1276000459-1121-1-git-send-email-ext-teemu.3.paasikivi@nokia.com>

This patch adds support to nl80211 and mac80211 to set basic rates when
joining/creating ibss network.

Original patch was posted by Johannes Berg on the linux-wireless posting list.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
---
 include/net/cfg80211.h     |    2 +
 net/mac80211/ibss.c        |    4 ++-
 net/mac80211/ieee80211_i.h |    2 +
 net/wireless/nl80211.c     |   49 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0c3c214..4ff4e1f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -801,6 +801,7 @@ struct cfg80211_disassoc_request {
  * @beacon_interval: beacon interval to use
  * @privacy: this is a protected network, keys will be configured
  *	after joining
+ * @basic_rates: bitmap of basic rates to use when creating the IBSS
  */
 struct cfg80211_ibss_params {
 	u8 *ssid;
@@ -809,6 +810,7 @@ struct cfg80211_ibss_params {
 	u8 *ie;
 	u8 ssid_len, ie_len;
 	u16 beacon_interval;
+	u32 basic_rates;
 	bool channel_fixed;
 	bool privacy;
 };
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d7a96ce..8be5a96 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -172,6 +172,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	rcu_assign_pointer(ifibss->presp, skb);
 
 	sdata->vif.bss_conf.beacon_int = beacon_int;
+	sdata->vif.bss_conf.basic_rates = basic_rates;
 	bss_change = BSS_CHANGED_BEACON_INT;
 	bss_change |= ieee80211_reset_erp_info(sdata);
 	bss_change |= BSS_CHANGED_BSSID;
@@ -529,7 +530,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
 		sdata->drop_unencrypted = 0;
 
 	__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
-				  ifibss->channel, 3, /* first two are basic */
+				  ifibss->channel, ifibss->basic_rates,
 				  capability, 0);
 }
 
@@ -910,6 +911,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 		sdata->u.ibss.fixed_bssid = false;
 
 	sdata->u.ibss.privacy = params->privacy;
+	sdata->u.ibss.basic_rates = params->basic_rates;
 
 	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4d3883e..fde058b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -393,6 +393,8 @@ struct ieee80211_if_ibss {
 	unsigned long request;
 	unsigned long last_scan_completed;
 
+	u32 basic_rates;
+
 	bool timer_running;
 
 	bool fixed_bssid;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90ab3c8..324b4a5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3955,6 +3955,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
+	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
+		u8 *rates =
+			nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+		int n_rates =
+			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+		struct ieee80211_supported_band *sband =
+			wiphy->bands[ibss.channel->band];
+		int i, j;
+
+		if (n_rates == 0) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < n_rates; i++) {
+			int rate = (rates[i] & 0x7f) * 5;
+			bool found = false;
+
+			for (j = 0; j < sband->n_bitrates; j++) {
+				if (sband->bitrates[j].bitrate == rate) {
+					found = true;
+					ibss.basic_rates |= BIT(j);
+					break;
+				}
+			}
+			if (!found) {
+				err = -EINVAL;
+				goto out;
+			}
+		}
+	} else {
+		/*
+		* If no rates were explicitly configured,
+		* use the mandatory rate set for 11b or
+		* 11a for maximum compatibility.
+		*/
+		struct ieee80211_supported_band *sband =
+			wiphy->bands[ibss.channel->band];
+		int j;
+		u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
+			IEEE80211_RATE_MANDATORY_A :
+			IEEE80211_RATE_MANDATORY_B;
+
+		for (j = 0; j < sband->n_bitrates; j++) {
+			if (sband->bitrates[j].flags & flag)
+				ibss.basic_rates |= BIT(j);
+		}
+	}
+
 	err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
 
 out:
-- 
1.5.6.3


^ permalink raw reply related

* [RFC 0/3] mac80211: Add support for configuring ibss basic rates
From: Teemu Paasikivi @ 2010-06-08 12:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi

This patch set implements support for configuring basic rates for ibss network when joining/creating one. First two patches are basically patch proposed by Johannes Berg on linux-wireless posting list split in two. These implement interface to nl80211 to do actual configuration from user space. Last patch is to fix a problem when leaving and joining back to self created ibss network, without this basic rates would be left unset. That is caused by the fact that the stack holds information for the self created bss and when rejoining it looks like already existing ibss network. This causes little annoyance (bug?) by preventing changing basic rates once ibss is created as long as the stack holds the information. 

Teemu Paasikivi (3):
  mac80211: Set basic rates while joining ibss network
  mac80211: Set changed basic rates flag
  mac80211: Store basic rates for bss when joining ibss network

 include/net/cfg80211.h     |    2 +
 net/mac80211/ibss.c        |   19 ++++++++++++++++-
 net/mac80211/ieee80211_i.h |    2 +
 net/wireless/nl80211.c     |   49 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 1 deletions(-)


^ permalink raw reply

* [PATCH v2] wl1251: fix ELP_CTRL register reads
From: Grazvydas Ignotas @ 2010-06-08 11:33 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Grazvydas Ignotas

Reading the ELP_CTRL register with sdio_readb causes problems because
hardware seems to be performing a write using stuff bits in the request
(those bits contain write data in write request). This indicates that it
actually expects RAW (read after write) type of request, so perform that
when reading ELP_CTRL instead. Also cache last written value so we know
what to write when doing RAW request.

Because of the above it was not possible to wake the chip from ELP power
saving mode, PM had to be disabled to have the driver usable in SDIO
mode. After this patch PM is functional.

For backporting to 2.6.34 or earlier, this patch depends on
6c1f716e8154ee9315534782b9b1eedea0559a24, which adds the
required SDIO funcion.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
Acked-by: Kalle Valo <kvalo@adurom.com>
---
This is the same as previous version, just updated the commit message.

 drivers/net/wireless/wl12xx/wl1251_sdio.c |   40 ++++++++++++++++++++++++----
 1 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index c561332..b901b61 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -37,11 +37,17 @@
 #define SDIO_DEVICE_ID_TI_WL1251	0x9066
 #endif
 
+struct wl1251_sdio {
+	struct sdio_func *func;
+	u32 elp_val;
+};
+
 static struct wl12xx_platform_data *wl12xx_board_data;
 
 static struct sdio_func *wl_to_func(struct wl1251 *wl)
 {
-	return wl->if_priv;
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	return wl_sdio->func;
 }
 
 static void wl1251_sdio_interrupt(struct sdio_func *func)
@@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
 static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
 {
 	int ret = 0;
-	struct sdio_func *func = wl_to_func(wl);
-
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	struct sdio_func *func = wl_sdio->func;
+
+	/*
+	 * The hardware only supports RAW (read after write) access for
+	 * reading, regular sdio_readb won't work here (it interprets
+	 * the unused bits of CMD52 as write data even if we send read
+	 * request).
+	 */
 	sdio_claim_host(func);
-	*val = sdio_readb(func, addr, &ret);
+	*val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
 	sdio_release_host(func);
 
 	if (ret)
@@ -103,7 +116,8 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
 static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
 {
 	int ret = 0;
-	struct sdio_func *func = wl_to_func(wl);
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	struct sdio_func *func = wl_sdio->func;
 
 	sdio_claim_host(func);
 	sdio_writeb(func, val, addr, &ret);
@@ -111,6 +125,8 @@ static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
 
 	if (ret)
 		wl1251_error("sdio_writeb failed (%d)", ret);
+	else
+		wl_sdio->elp_val = val;
 }
 
 static void wl1251_sdio_reset(struct wl1251 *wl)
@@ -197,6 +213,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
 	int ret;
 	struct wl1251 *wl;
 	struct ieee80211_hw *hw;
+	struct wl1251_sdio *wl_sdio;
 
 	hw = wl1251_alloc_hw();
 	if (IS_ERR(hw))
@@ -204,6 +221,12 @@ static int wl1251_sdio_probe(struct sdio_func *func,
 
 	wl = hw->priv;
 
+	wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
+	if (wl_sdio == NULL) {
+		ret = -ENOMEM;
+		goto out_free_hw;
+	}
+
 	sdio_claim_host(func);
 	ret = sdio_enable_func(func);
 	if (ret)
@@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func,
 	sdio_release_host(func);
 
 	SET_IEEE80211_DEV(hw, &func->dev);
-	wl->if_priv = func;
+	wl_sdio->func = func;
+	wl->if_priv = wl_sdio;
 	wl->if_ops = &wl1251_sdio_ops;
 	wl->set_power = wl1251_sdio_set_power;
 
@@ -259,6 +283,8 @@ disable:
 	sdio_disable_func(func);
 release:
 	sdio_release_host(func);
+	kfree(wl_sdio);
+out_free_hw:
 	wl1251_free_hw(wl);
 	return ret;
 }
@@ -266,9 +292,11 @@ release:
 static void __devexit wl1251_sdio_remove(struct sdio_func *func)
 {
 	struct wl1251 *wl = sdio_get_drvdata(func);
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
 
 	if (wl->irq)
 		free_irq(wl->irq, wl);
+	kfree(wl_sdio);
 	wl1251_free_hw(wl);
 
 	sdio_claim_host(func);
-- 
1.7.0.2


^ permalink raw reply related

* [PATCH] mac80211: Fix circular locking dependency in ARP filter handling
From: Juuso Oikarinen @ 2010-06-08 10:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, reinette.chatre

There is a circular locking dependency when configuring the
hardware ARP filters on association, occurring when flushing the mac80211
workqueue. This is what happens:

[   92.026800] =======================================================
[   92.030507] [ INFO: possible circular locking dependency detected ]
[   92.030507] 2.6.34-04781-g2b2c009 #85
[   92.030507] -------------------------------------------------------
[   92.030507] modprobe/5225 is trying to acquire lock:
[   92.030507]  ((wiphy_name(local->hw.wiphy))){+.+.+.}, at: [<ffffffff8105b5c0>] flush_workq
ueue+0x0/0xb0
[   92.030507]
[   92.030507] but task is already holding lock:
[   92.030507]  (rtnl_mutex){+.+.+.}, at: [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]
[   92.030507] which lock already depends on the new lock.
[   92.030507]
[   92.030507]
[   92.030507] the existing dependency chain (in reverse order) is:
[   92.030507]
[   92.030507] -> #2 (rtnl_mutex){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff81341754>] mutex_lock_nested+0x44/0x300
[   92.030507]        [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]        [<ffffffffa022d47c>] ieee80211_assoc_done+0x6c/0xe0 [mac80211]
[   92.030507]        [<ffffffffa022f2ad>] ieee80211_work_work+0x31d/0x1280 [mac80211]

[   92.030507] -> #1 ((&local->work_work)){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105a51a>] worker_thread+0x22a/0x370
[   92.030507]        [<ffffffff8105ecc6>] kthread+0x96/0xb0
[   92.030507]        [<ffffffff81003a94>] kernel_thread_helper+0x4/0x10
[   92.030507]
[   92.030507] -> #0 ((wiphy_name(local->hw.wiphy))){+.+.+.}:
[   92.030507]        [<ffffffff81075fdc>] __lock_acquire+0x1c0c/0x1d50
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105b60e>] flush_workqueue+0x4e/0xb0
[   92.030507]        [<ffffffffa023ff7b>] ieee80211_stop_device+0x2b/0xb0 [mac80211]
[   92.030507]        [<ffffffffa0231635>] ieee80211_stop+0x3e5/0x680 [mac80211]

The locking in this case is quite complex. Fix the problem by rewriting the
way the hardware ARP filter list is handled - i.e. make a copy of the address
list to the bss_conf struct, and provide that list to the hardware driver
when needed.

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 include/net/mac80211.h      |   30 ++++++++++++++------------
 net/mac80211/driver-ops.h   |   17 ---------------
 net/mac80211/driver-trace.h |   25 ----------------------
 net/mac80211/main.c         |   47 +++++++++++++++++++++++++-----------------
 net/mac80211/mlme.c         |   16 +++-----------
 5 files changed, 48 insertions(+), 87 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e3c1d47..086f235 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -19,7 +19,6 @@
 #include <linux/wireless.h>
 #include <linux/device.h>
 #include <linux/ieee80211.h>
-#include <linux/inetdevice.h>
 #include <net/cfg80211.h>
 
 /**
@@ -147,6 +146,7 @@ struct ieee80211_low_level_stats {
  *	enabled/disabled (beaconing modes)
  * @BSS_CHANGED_CQM: Connection quality monitor config changed
  * @BSS_CHANGED_IBSS: IBSS join status changed
+ * @BSS_CHANGED_ARP_ADDR_LIST: Hardware ARP filter address list changed
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -161,10 +161,18 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_BEACON_ENABLED	= 1<<9,
 	BSS_CHANGED_CQM			= 1<<10,
 	BSS_CHANGED_IBSS		= 1<<11,
+	BSS_CHANGED_ARP_ADDR_LIST	= 1<<12,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
 
+/*
+ * The maximum number of IPv4 addresses listed for ARP filtering. If the number
+ * of addresses for an interface increase beyond this value, hardware ARP
+ * filtering will be disabled.
+ */
+#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
+
 /**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
@@ -200,6 +208,11 @@ enum ieee80211_bss_change {
  * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
  *	implies disabled
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
+ * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
+ *	may filter ARP queries targeted for other addresses than listed here.
+ *	The driver must allow ARP queries targeted for all address listed here
+ *	to pass through.
+ * @arp_addr_cnt: Number of addresses currently on the list
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -220,6 +233,8 @@ struct ieee80211_bss_conf {
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
 	enum nl80211_channel_type channel_type;
+	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
+	u8 arp_addr_cnt;
 };
 
 /**
@@ -1529,16 +1544,6 @@ enum ieee80211_ampdu_mlme_action {
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
- * @configure_arp_filter: Configuration function for hardware ARP query filter.
- *	This function is called with all the IP addresses configured to the
- *	interface as argument - all ARP queries targeted to any of these
- *	addresses must pass through. If the hardware filter does not support
- *	enought addresses, hardware filtering must be disabled. The ifa_list
- *	argument may be NULL, indicating that filtering must be disabled.
- *	This function is called upon association complete with current
- *	address(es), and while associated whenever the IP address(es) change.
- *	The callback can sleep.
- *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -1678,9 +1683,6 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
-	int (*configure_arp_filter)(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct in_ifaddr *ifa_list);
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index d1139e4..bbea3bc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -83,23 +83,6 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
 	trace_drv_bss_info_changed(local, sdata, info, changed);
 }
 
-struct in_ifaddr;
-static inline int drv_configure_arp_filter(struct ieee80211_local *local,
-					   struct ieee80211_vif *vif,
-					   struct in_ifaddr *ifa_list)
-{
-	int ret = 0;
-
-	might_sleep();
-
-	if (local->ops->configure_arp_filter)
-		ret = local->ops->configure_arp_filter(&local->hw, vif,
-						       ifa_list);
-
-	trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
-	return ret;
-}
-
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6b90630..1e293df 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -219,31 +219,6 @@ TRACE_EVENT(drv_bss_info_changed,
 	)
 );
 
-TRACE_EVENT(drv_configure_arp_filter,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct in_ifaddr *ifa_list, int ret),
-
-	TP_ARGS(local, sdata, ifa_list, ret),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__field(int, ret)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		__entry->ret = ret;
-	),
-
-	TP_printk(
-		VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
-		VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
-	)
-);
-
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5706156..0a6400b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -20,6 +20,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/bitmap.h>
 #include <linux/pm_qos_params.h>
+#include <linux/inetdevice.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
 
@@ -330,23 +331,6 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
 }
 
 #ifdef CONFIG_INET
-int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
-{
-	struct in_device *idev;
-	int ret = 0;
-
-	BUG_ON(!sdata);
-	ASSERT_RTNL();
-
-	idev = sdata->dev->ip_ptr;
-	if (!idev)
-		return 0;
-
-	ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
-				       idev->ifa_list);
-	return ret;
-}
-
 static int ieee80211_ifa_changed(struct notifier_block *nb,
 				 unsigned long data, void *arg)
 {
@@ -356,8 +340,11 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 			     ifa_notifier);
 	struct net_device *ndev = ifa->ifa_dev->dev;
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	struct in_device *idev;
 	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_bss_conf *bss_conf;
 	struct ieee80211_if_managed *ifmgd;
+	int c = 0;
 
 	/* Make sure it's our interface that got changed */
 	if (!wdev)
@@ -366,17 +353,39 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 	if (wdev->wiphy != local->hw.wiphy)
 		return NOTIFY_DONE;
 
-	/* We are concerned about IP addresses only when associated */
 	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	bss_conf = &sdata->vif.bss_conf;
 
 	/* ARP filtering is only supported in managed mode */
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return NOTIFY_DONE;
 
+	idev = sdata->dev->ip_ptr;
+	if (!idev)
+		return NOTIFY_DONE;
+
 	ifmgd = &sdata->u.mgd;
 	mutex_lock(&ifmgd->mtx);
+
+	/* Copy the addresses to the bss_conf list */
+	ifa = idev->ifa_list;
+	while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
+		bss_conf->arp_addr_list[c] = ifa->ifa_address;
+		ifa = ifa->ifa_next;
+		c++;
+	}
+
+	/* If not all addresses fit the list, disable filtering */
+	if (ifa)
+		c = 0;
+
+	bss_conf->arp_addr_cnt = c;
+
+	/* We are concerned about ARP filterting only when associated */
 	if (ifmgd->associated)
-		ieee80211_set_arp_filter(sdata);
+		ieee80211_bss_info_change_notify(sdata,
+						 BSS_CHANGED_ARP_ADDR_LIST);
+
 	mutex_unlock(&ifmgd->mtx);
 
 	return NOTIFY_DONE;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ac68c41..8a39530 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -851,6 +851,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 	    sdata->vif.bss_conf.cqm_rssi_thold)
 		bss_info_changed |= BSS_CHANGED_CQM;
 
+	bss_info_changed |= BSS_CHANGED_ARP_ADDR_LIST;
+
 	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
 	mutex_lock(&local->iflist_mtx);
@@ -2116,19 +2118,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 			cfg80211_send_assoc_timeout(wk->sdata->dev,
 						    wk->filter_ta);
 			return WORK_DONE_DESTROY;
-#ifdef CONFIG_INET
-		} else {
-			mutex_unlock(&wk->sdata->u.mgd.mtx);
-
-			/*
-			 * configure ARP filter IP addresses to the driver,
-			 * intentionally outside the mgd mutex.
-			 */
-			rtnl_lock();
-			ieee80211_set_arp_filter(wk->sdata);
-			rtnl_unlock();
-#endif
 		}
+
+		mutex_unlock(&wk->sdata->u.mgd.mtx);
 	}
 
 	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH v3 1/3] cfg80211: Add nl80211 antenna configuration
From: Johannes Berg @ 2010-06-08  9:05 UTC (permalink / raw)
  To: Bruno Randolf; +Cc: linville, linux-wireless
In-Reply-To: <201006081010.13314.br1@einfach.org>

On Tue, 2010-06-08 at 10:10 +0900, Bruno Randolf wrote:

> i don't particularly care about where the antenna information is printed 
> exactly, so anything will be fine with me.
> 
> but when i look at the wiphy info, it shows mostly capability information, 
> like the list of supported frequencies, list of bitrates, supported interface 
> modes, supported commands. the only exception is coverage class, which is the 
> only runtime configuration as far as i can see. therefore i thought it doesnt 
> fit there well.
> 
> maybe another command for getting runtime configuration like channel(s), fixed 
> bitrates, essid, bssid, RTS/CTS, fraqmentation, txpower, power management, 
> antenna settings, etc... would make sense? allthough in this list antenna is 
> probably the only one which is per phy and not per interface...

Right so there isn't much runtime stuff in the list now. I don't see
anything inherently bad in adding more though, since userspace can
selectively look at the attributes, and it's not like it's a huge amount
of data?

johannes


^ permalink raw reply

* Re: [RFC PATCHv2] mac80211: Fix circular locking dependency in ARP filter handling
From: Juuso Oikarinen @ 2010-06-08  8:46 UTC (permalink / raw)
  To: ext Johannes Berg
  Cc: linux-wireless@vger.kernel.org, reinette.chatre@intel.com
In-Reply-To: <1275984236.3706.45.camel@jlt3.sipsolutions.net>

On Tue, 2010-06-08 at 10:03 +0200, ext Johannes Berg wrote:
> On Tue, 2010-06-08 at 09:24 +0300, Juuso Oikarinen wrote:
> 
> > @@ -161,10 +161,20 @@ enum ieee80211_bss_change {
> >  	BSS_CHANGED_BEACON_ENABLED	= 1<<9,
> >  	BSS_CHANGED_CQM			= 1<<10,
> >  	BSS_CHANGED_IBSS		= 1<<11,
> > +#ifdef CONFIG_INET
> > +	BSS_CHANGED_ARP_ADDR_LIST	= 1<<12,
> > +#endif
> 
> Ick, don't do that, all drivers would end up littered with ifdefs.
>  
> > @@ -220,6 +235,10 @@ struct ieee80211_bss_conf {
> >  	s32 cqm_rssi_thold;
> >  	u32 cqm_rssi_hyst;
> >  	enum nl80211_channel_type channel_type;
> > +#ifdef CONFIG_INET
> > +	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
> > +	u8 arp_addr_cnt;
> > +#endifs
> 
> same here.
> 
> > @@ -851,6 +851,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
> >  	    sdata->vif.bss_conf.cqm_rssi_thold)
> >  		bss_info_changed |= BSS_CHANGED_CQM;
> >  
> > +#ifdef CONFIG_INET
> > +	bss_info_changed |= BSS_CHANGED_ARP_ADDR_LIST;
> > +#endif
> > +
> 
> I don't see why you can't set that unconditionally here either, it'll
> just be an empty list always.

I was about to send the patch without the ifdefs, but was unsure about
the policy here so I decided to add at the at the last minute.

Our testing guy found a bug too - the condition for the max number of
IP's is wrong, it will take at most 3 addresses currently.

> Otherwise looks pretty good.

As you say it looks OK, I'll remove the above #ifdef's, fix that one bug
(and others if/when our tester dude finds more) and resubmit. 

-Juuso

> johannes
> 



^ permalink raw reply

* Re: [RFC PATCHv2] mac80211: Fix circular locking dependency in ARP filter handling
From: Johannes Berg @ 2010-06-08  8:03 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linux-wireless, reinette.chatre
In-Reply-To: <1275978299-18237-1-git-send-email-juuso.oikarinen@nokia.com>

On Tue, 2010-06-08 at 09:24 +0300, Juuso Oikarinen wrote:

> @@ -161,10 +161,20 @@ enum ieee80211_bss_change {
>  	BSS_CHANGED_BEACON_ENABLED	= 1<<9,
>  	BSS_CHANGED_CQM			= 1<<10,
>  	BSS_CHANGED_IBSS		= 1<<11,
> +#ifdef CONFIG_INET
> +	BSS_CHANGED_ARP_ADDR_LIST	= 1<<12,
> +#endif

Ick, don't do that, all drivers would end up littered with ifdefs.
 
> @@ -220,6 +235,10 @@ struct ieee80211_bss_conf {
>  	s32 cqm_rssi_thold;
>  	u32 cqm_rssi_hyst;
>  	enum nl80211_channel_type channel_type;
> +#ifdef CONFIG_INET
> +	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
> +	u8 arp_addr_cnt;
> +#endifs

same here.

> @@ -851,6 +851,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
>  	    sdata->vif.bss_conf.cqm_rssi_thold)
>  		bss_info_changed |= BSS_CHANGED_CQM;
>  
> +#ifdef CONFIG_INET
> +	bss_info_changed |= BSS_CHANGED_ARP_ADDR_LIST;
> +#endif
> +

I don't see why you can't set that unconditionally here either, it'll
just be an empty list always.

Otherwise looks pretty good.

johannes


^ permalink raw reply

* Re: [PATCH v3 1/3] cfg80211: Add nl80211 antenna configuration
From: Johannes Berg @ 2010-06-08  7:27 UTC (permalink / raw)
  To: Bruno Randolf; +Cc: linux-wireless
In-Reply-To: <201006081019.10217.br1@einfach.org>

On Tue, 2010-06-08 at 10:19 +0900, Bruno Randolf wrote:

> > > +	res = rdev->ops->get_antenna(&rdev->wiphy, &tx_ant, &rx_ant);
> > > +	if (res)
> > > +		goto free_msg;
> > 
> > and complain about the driver if they still are after this.
> 
> would that be a WARN_ON?

Yeah I suppose so.

johannes


^ permalink raw reply

* Re: [PATCH] iwlwifi: add missing rcu_read_lock
From: Johannes Berg @ 2010-06-08  7:25 UTC (permalink / raw)
  To: Miles Lane; +Cc: John Linville, Reinette Chatre, Wey-Yi W Guy, linux-wireless
In-Reply-To: <AANLkTin91YUTC8ogoflpFN4V3f21ItLlV_EoFU-uvrzo@mail.gmail.com>

On Mon, 2010-06-07 at 17:31 -0400, Miles Lane wrote:

> > --- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn-tx.c     2010-06-07 21:17:56.000000000 +0200
> > +++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn-tx.c  2010-06-07 21:18:04.000000000 +0200
> > @@ -1146,6 +1146,7 @@ static void iwlagn_tx_status(struct iwl_
> >        struct ieee80211_sta *sta;
> >        struct iwl_station_priv *sta_priv;
> >
> > +       rcu_read_lock();
> >        sta = ieee80211_find_sta(priv->vif, hdr->addr1);
> >        if (sta) {
> >                sta_priv = (void *)sta->drv_priv;
> > @@ -1154,6 +1155,7 @@ static void iwlagn_tx_status(struct iwl_
> >                    atomic_dec_return(&sta_priv->pending_frames) == 0)
> >                        ieee80211_sta_block_awake(priv->hw, sta, false);
> >        }
> > +       rcu_read_unlock();
> >
> >        ieee80211_tx_status_irqsafe(priv->hw, skb);
> >  }
> >
> >
> >
> 
> Unclean patch application - is this to be expected?
> 
> patching file drivers/net/wireless/iwlwifi/iwl-agn-tx.c
> Hunk #1 succeeded at 1125 (offset -21 lines).
> Hunk #2 succeeded at 1134 (offset -21 lines).

Didn't pay much attention what tree I generated it against since I knew
this code hasn't changed in a while ... so the offset looks perfectly
fine. Fuzz I'd have been surprised about :)

johannes


^ permalink raw reply

* [RFC PATCHv2] mac80211: Fix circular locking dependency in ARP filter handling
From: Juuso Oikarinen @ 2010-06-08  6:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: reinette.chatre

There is a circular locking dependency when configuring the
hardware ARP filters on association, occurring when flushing the mac80211
workqueue. This is what happens:

[   92.026800] =======================================================
[   92.030507] [ INFO: possible circular locking dependency detected ]
[   92.030507] 2.6.34-04781-g2b2c009 #85
[   92.030507] -------------------------------------------------------
[   92.030507] modprobe/5225 is trying to acquire lock:
[   92.030507]  ((wiphy_name(local->hw.wiphy))){+.+.+.}, at: [<ffffffff8105b5c0>] flush_workq
ueue+0x0/0xb0
[   92.030507]
[   92.030507] but task is already holding lock:
[   92.030507]  (rtnl_mutex){+.+.+.}, at: [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]
[   92.030507] which lock already depends on the new lock.
[   92.030507]
[   92.030507]
[   92.030507] the existing dependency chain (in reverse order) is:
[   92.030507]
[   92.030507] -> #2 (rtnl_mutex){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff81341754>] mutex_lock_nested+0x44/0x300
[   92.030507]        [<ffffffff812b9ce2>] rtnl_lock+0x12/0x20
[   92.030507]        [<ffffffffa022d47c>] ieee80211_assoc_done+0x6c/0xe0 [mac80211]
[   92.030507]        [<ffffffffa022f2ad>] ieee80211_work_work+0x31d/0x1280 [mac80211]

[   92.030507] -> #1 ((&local->work_work)){+.+.+.}:
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105a51a>] worker_thread+0x22a/0x370
[   92.030507]        [<ffffffff8105ecc6>] kthread+0x96/0xb0
[   92.030507]        [<ffffffff81003a94>] kernel_thread_helper+0x4/0x10
[   92.030507]
[   92.030507] -> #0 ((wiphy_name(local->hw.wiphy))){+.+.+.}:
[   92.030507]        [<ffffffff81075fdc>] __lock_acquire+0x1c0c/0x1d50
[   92.030507]        [<ffffffff810761fb>] lock_acquire+0xdb/0x110
[   92.030507]        [<ffffffff8105b60e>] flush_workqueue+0x4e/0xb0
[   92.030507]        [<ffffffffa023ff7b>] ieee80211_stop_device+0x2b/0xb0 [mac80211]
[   92.030507]        [<ffffffffa0231635>] ieee80211_stop+0x3e5/0x680 [mac80211]

The locking in this case is quite complex. Fix the problem by rewriting the
way the hardware ARP filter list is handled - i.e. make a copy of the address
list to the bss_conf struct, and provide that list to the hardware driver
when needed.

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 include/net/mac80211.h      |   34 ++++++++++++++++++-------------
 net/mac80211/driver-ops.h   |   17 ---------------
 net/mac80211/driver-trace.h |   25 -----------------------
 net/mac80211/main.c         |   46 +++++++++++++++++++++++++-----------------
 net/mac80211/mlme.c         |   18 +++++-----------
 5 files changed, 53 insertions(+), 87 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e3c1d47..af2f3cc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -19,7 +19,6 @@
 #include <linux/wireless.h>
 #include <linux/device.h>
 #include <linux/ieee80211.h>
-#include <linux/inetdevice.h>
 #include <net/cfg80211.h>
 
 /**
@@ -147,6 +146,7 @@ struct ieee80211_low_level_stats {
  *	enabled/disabled (beaconing modes)
  * @BSS_CHANGED_CQM: Connection quality monitor config changed
  * @BSS_CHANGED_IBSS: IBSS join status changed
+ * @BSS_CHANGED_ARP_ADDR_LIST: Hardware ARP filter address list changed
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -161,10 +161,20 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_BEACON_ENABLED	= 1<<9,
 	BSS_CHANGED_CQM			= 1<<10,
 	BSS_CHANGED_IBSS		= 1<<11,
+#ifdef CONFIG_INET
+	BSS_CHANGED_ARP_ADDR_LIST	= 1<<12,
+#endif
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
 
+/*
+ * The maximum number of IPv4 addresses listed for ARP filtering. If the number
+ * of addresses for an interface increase beyond this value, hardware ARP
+ * filtering will be disabled.
+ */
+#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
+
 /**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
@@ -200,6 +210,11 @@ enum ieee80211_bss_change {
  * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
  *	implies disabled
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
+ * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
+ *	may filter ARP queries targeted for other addresses than listed here.
+ *	The driver must allow ARP queries targeted for all address listed here
+ *	to pass through.
+ * @arp_addr_cnt: Number of addresses currently on the list
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -220,6 +235,10 @@ struct ieee80211_bss_conf {
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
 	enum nl80211_channel_type channel_type;
+#ifdef CONFIG_INET
+	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
+	u8 arp_addr_cnt;
+#endifs
 };
 
 /**
@@ -1529,16 +1548,6 @@ enum ieee80211_ampdu_mlme_action {
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
- * @configure_arp_filter: Configuration function for hardware ARP query filter.
- *	This function is called with all the IP addresses configured to the
- *	interface as argument - all ARP queries targeted to any of these
- *	addresses must pass through. If the hardware filter does not support
- *	enought addresses, hardware filtering must be disabled. The ifa_list
- *	argument may be NULL, indicating that filtering must be disabled.
- *	This function is called upon association complete with current
- *	address(es), and while associated whenever the IP address(es) change.
- *	The callback can sleep.
- *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -1678,9 +1687,6 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
-	int (*configure_arp_filter)(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct in_ifaddr *ifa_list);
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index d1139e4..bbea3bc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -83,23 +83,6 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
 	trace_drv_bss_info_changed(local, sdata, info, changed);
 }
 
-struct in_ifaddr;
-static inline int drv_configure_arp_filter(struct ieee80211_local *local,
-					   struct ieee80211_vif *vif,
-					   struct in_ifaddr *ifa_list)
-{
-	int ret = 0;
-
-	might_sleep();
-
-	if (local->ops->configure_arp_filter)
-		ret = local->ops->configure_arp_filter(&local->hw, vif,
-						       ifa_list);
-
-	trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
-	return ret;
-}
-
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6b90630..1e293df 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -219,31 +219,6 @@ TRACE_EVENT(drv_bss_info_changed,
 	)
 );
 
-TRACE_EVENT(drv_configure_arp_filter,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct in_ifaddr *ifa_list, int ret),
-
-	TP_ARGS(local, sdata, ifa_list, ret),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__field(int, ret)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		__entry->ret = ret;
-	),
-
-	TP_printk(
-		VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
-		VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
-	)
-);
-
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 88b671a..89dc7c1 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -20,6 +20,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/bitmap.h>
 #include <linux/pm_qos_params.h>
+#include <linux/inetdevice.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
 
@@ -330,23 +331,6 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
 }
 
 #ifdef CONFIG_INET
-int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
-{
-	struct in_device *idev;
-	int ret = 0;
-
-	BUG_ON(!sdata);
-	ASSERT_RTNL();
-
-	idev = sdata->dev->ip_ptr;
-	if (!idev)
-		return 0;
-
-	ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
-				       idev->ifa_list);
-	return ret;
-}
-
 static int ieee80211_ifa_changed(struct notifier_block *nb,
 				 unsigned long data, void *arg)
 {
@@ -356,8 +340,11 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 			     ifa_notifier);
 	struct net_device *ndev = ifa->ifa_dev->dev;
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	struct in_device *idev;
 	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_bss_conf *bss_conf;
 	struct ieee80211_if_managed *ifmgd;
+	int c = 0;
 
 	if (!netif_running(ndev))
 		return NOTIFY_DONE;
@@ -369,17 +356,38 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 	if (wdev->wiphy != local->hw.wiphy)
 		return NOTIFY_DONE;
 
-	/* We are concerned about IP addresses only when associated */
 	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	bss_conf = &sdata->vif.bss_conf;
 
 	/* ARP filtering is only supported in managed mode */
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return NOTIFY_DONE;
 
+	idev = sdata->dev->ip_ptr;
+	if (!idev)
+		return NOTIFY_DONE;
+
 	ifmgd = &sdata->u.mgd;
 	mutex_lock(&ifmgd->mtx);
+
+	/* Copy the addresses to the bss_conf list */
+	ifa = idev->ifa_list;
+	while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
+		bss_conf->arp_addr_list[c] = ifa->ifa_address;
+		ifa = ifa->ifa_next;
+		c++;
+	}
+
+	if (c == IEEE80211_BSS_ARP_ADDR_LIST_LEN)
+		c = 0;
+
+	bss_conf->arp_addr_cnt = c;
+
+	/* We are concerned about ARP filterting only when associated */
 	if (ifmgd->associated)
-		ieee80211_set_arp_filter(sdata);
+		ieee80211_bss_info_change_notify(sdata,
+						 BSS_CHANGED_ARP_ADDR_LIST);
+
 	mutex_unlock(&ifmgd->mtx);
 
 	return NOTIFY_DONE;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ac68c41..25ceea3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -851,6 +851,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 	    sdata->vif.bss_conf.cqm_rssi_thold)
 		bss_info_changed |= BSS_CHANGED_CQM;
 
+#ifdef CONFIG_INET
+	bss_info_changed |= BSS_CHANGED_ARP_ADDR_LIST;
+#endif
+
 	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
 	mutex_lock(&local->iflist_mtx);
@@ -2116,19 +2120,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 			cfg80211_send_assoc_timeout(wk->sdata->dev,
 						    wk->filter_ta);
 			return WORK_DONE_DESTROY;
-#ifdef CONFIG_INET
-		} else {
-			mutex_unlock(&wk->sdata->u.mgd.mtx);
-
-			/*
-			 * configure ARP filter IP addresses to the driver,
-			 * intentionally outside the mgd mutex.
-			 */
-			rtnl_lock();
-			ieee80211_set_arp_filter(wk->sdata);
-			rtnl_unlock();
-#endif
 		}
+
+		mutex_unlock(&wk->sdata->u.mgd.mtx);
 	}
 
 	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
-- 
1.6.3.3


^ permalink raw reply related

* iwlagn fails to assoc with nexus one in ad-hoc mode
From: David Miller @ 2010-06-08  4:46 UTC (permalink / raw)
  To: linux-wireless


When I try to associate the wireless activity light blinks like
crazy and I get kernel log dumps like the one at the end of
this email.

The nexus one uses a Broadcom BCM4328 for wireless.

Windows 7 users report the same problem with Intel wireless, and that
upgrading to the Intel wireless windows driver, version 13.1.1.1,
fixes the problem.

For example, see here:

http://code.google.com/p/android-wifi-tether/issues/detail?id=244

Can we make sure whatever got fixed in the windows driver propagates
into our Linux drivers too? :-)

Thanks!

--------------------
iwlagn 0000:03:00.0: Microcode SW error detected.  Restarting 0x2000000.
iwlagn 0000:03:00.0: Start IWL Error Log Dump:
iwlagn 0000:03:00.0: Status: 0x000212E4, count: 5
iwlagn 0000:03:00.0: Desc                               Time       data1      data2      line
iwlagn 0000:03:00.0: SYSASSERT                    (#05) 0010614736 0x00000080 0x00000010 854
iwlagn 0000:03:00.0: blink1  blink2  ilink1  ilink2
iwlagn 0000:03:00.0: 0x03870 0x03870 0x008B2 0x00000
iwlagn 0000:03:00.0: CSR values:
iwlagn 0000:03:00.0: (2nd byte of CSR_INT_COALESCING is CSR_INT_PERIODIC_REG)
iwlagn 0000:03:00.0:        CSR_HW_IF_CONFIG_REG: 0X00480302
iwlagn 0000:03:00.0:          CSR_INT_COALESCING: 0X00000040
iwlagn 0000:03:00.0:                     CSR_INT: 0X00000000
iwlagn 0000:03:00.0:                CSR_INT_MASK: 0X00000000
iwlagn 0000:03:00.0:           CSR_FH_INT_STATUS: 0X00000000
iwlagn 0000:03:00.0:                 CSR_GPIO_IN: 0X00000000
iwlagn 0000:03:00.0:                   CSR_RESET: 0X00000000
iwlagn 0000:03:00.0:                CSR_GP_CNTRL: 0X080403c5
iwlagn 0000:03:00.0:                  CSR_HW_REV: 0X00000024
iwlagn 0000:03:00.0:              CSR_EEPROM_REG: 0X00000000
iwlagn 0000:03:00.0:               CSR_EEPROM_GP: 0X90000004
iwlagn 0000:03:00.0:              CSR_OTP_GP_REG: 0X00060000
iwlagn 0000:03:00.0:                 CSR_GIO_REG: 0X00080046
iwlagn 0000:03:00.0:            CSR_GP_UCODE_REG: 0X00000029
iwlagn 0000:03:00.0:           CSR_GP_DRIVER_REG: 0X00000000
iwlagn 0000:03:00.0:           CSR_UCODE_DRV_GP1: 0X00000000
iwlagn 0000:03:00.0:           CSR_UCODE_DRV_GP2: 0X00000000
iwlagn 0000:03:00.0:                 CSR_LED_REG: 0X00000078
iwlagn 0000:03:00.0:        CSR_DRAM_INT_TBL_REG: 0X88034db0
iwlagn 0000:03:00.0:        CSR_GIO_CHICKEN_BITS: 0X27800200
iwlagn 0000:03:00.0:             CSR_ANA_PLL_CFG: 0X00880300
iwlagn 0000:03:00.0:           CSR_HW_REV_WA_REG: 0X0001001a
iwlagn 0000:03:00.0:        CSR_DBG_HPET_MEM_REG: 0Xffff0000
iwlagn 0000:03:00.0: FH register values:
iwlagn 0000:03:00.0:         FH_RSCSR_CHNL0_STTS_WPTR_REG: 0X034c7900
iwlagn 0000:03:00.0:        FH_RSCSR_CHNL0_RBDCB_BASE_REG: 0X0034ccc0
iwlagn 0000:03:00.0:                  FH_RSCSR_CHNL0_WPTR: 0X00000040
iwlagn 0000:03:00.0:         FH_MEM_RCSR_CHNL0_CONFIG_REG: 0X80819104
iwlagn 0000:03:00.0:          FH_MEM_RSSR_SHARED_CTRL_REG: 0X000000fc
iwlagn 0000:03:00.0:            FH_MEM_RSSR_RX_STATUS_REG: 0X07030000
iwlagn 0000:03:00.0:    FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV: 0X00000000
iwlagn 0000:03:00.0:                FH_TSSR_TX_STATUS_REG: 0X07ff0001
iwlagn 0000:03:00.0:                 FH_TSSR_TX_ERROR_REG: 0X00000000
iwlagn 0000:03:00.0: Start IWL Event Log Dump: display last 20 entries
iwlagn 0000:03:00.0: EVT_LOGT:0000054936:0x00000001:0353
iwlagn 0000:03:00.0: EVT_LOGT:0000054953:0x0000010f:0106
iwlagn 0000:03:00.0: EVT_LOGT:0000054955:0x00000000:0301
iwlagn 0000:03:00.0: EVT_LOGT:0000055026:0x0000000d:0353
iwlagn 0000:03:00.0: EVT_LOGT:0000055037:0x00000000:0302
iwlagn 0000:03:00.0: EVT_LOGT:0000055057:0x00000c1d:0352
iwlagn 0000:03:00.0: EVT_LOGT:0000055058:0x00000002:0353
iwlagn 0000:03:00.0: EVT_LOGT:0000055070:0x00000000:0302
iwlagn 0000:03:00.0: EVT_LOGT:0000055094:0x00000d48:0352
iwlagn 0000:03:00.0: EVT_LOGT:0000055095:0x00000003:0353
iwlagn 0000:03:00.0: EVT_LOGT:0000055157:0x0000010f:0106
iwlagn 0000:03:00.0: EVT_LOGT:0000055159:0x00000000:0302
iwlagn 0000:03:00.0: EVT_LOGT:0000055171:0x00002000:0350
iwlagn 0000:03:00.0: EVT_LOGT:0000079297:0x0000010f:0106
iwlagn 0000:03:00.0: EVT_LOGT:0000079299:0x00000000:0301
iwlagn 0000:03:00.0: EVT_LOGT:0000079679:0x00000080:0313
iwlagn 0000:03:00.0: EVT_LOGT:0000079681:0x000005b4:0501
iwlagn 0000:03:00.0: EVT_LOGT:0000081109:0x00000000:0356
iwlagn 0000:03:00.0: EVT_LOGT:0000081141:0x000002ef:0501
iwlagn 0000:03:00.0: EVT_LOGT:0000081150:0x00000000:0125
iwlagn 0000:03:00.0: Unable to find TIM Element in beacon
iwlagn 0000:03:00.0: Unable to find TIM Element in beacon
iwlagn 0000:03:00.0: index 0 already used in uCode key table.

^ permalink raw reply

* Re: [RFC PATCH] mac80211: Fix circular locking dependency in ARP filter handling
From: Juuso Oikarinen @ 2010-06-08  4:32 UTC (permalink / raw)
  To: ext Johannes Berg
  Cc: linux-wireless@vger.kernel.org, reinette.chatre@intel.com
In-Reply-To: <1275923383.29978.19.camel@jlt3.sipsolutions.net>

On Mon, 2010-06-07 at 17:09 +0200, ext Johannes Berg wrote:
> On Mon, 2010-06-07 at 16:42 +0300, Juuso Oikarinen wrote:
> 
> > > > +#ifdef CONFIG_INET
> > > > +		cancel_work_sync(&sdata->u.mgd.arp_config_work);
> > > > +#endif
> > > 
> > > No can do, this is under RTNL and thus can't block waiting for a work
> > > that acquires the RTNL ... the work might already be running, waiting
> > > for the RTNL, by the time you get here. This will also get you a lockdep
> > > complaint.
> > 
> > The work-func escapes based on ieee80211_sdata_running before acquiring
> > the rtnl - hence here it should never get to the lock. I saw the same
> > being used in those other work funcs too. I was beginning work to try to
> > validate that, so it's not enough?
> 
> No, it's not enough. Like I said: "the work might already be running,
> waiting for the RTNL" -- and once it obtains the RTNL, sdata has already
> been freed!
> 
> > > This is why 
> > > 
> > > > @@ -379,7 +379,8 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
> > > >  	ifmgd = &sdata->u.mgd;
> > > >  	mutex_lock(&ifmgd->mtx);
> > > >  	if (ifmgd->associated)
> > > > -		ieee80211_set_arp_filter(sdata);
> > > > +		ieee80211_queue_work(&sdata->local->hw,
> > > > +				     &sdata->u.mgd.arp_config_work);
> > > >  	mutex_unlock(&ifmgd->mtx);
> > > 
> > > No need to do change it here since the rtnl is held outside.
> > 
> > Yes, I know rtnl is held outside. I changed this for two reasons. First,
> > I think it maybe better if the driver function is always called in the
> > same scope. Secondly, this gets rid of inetdevs intermediate
> > configurations (if you change IP address, it will first remove the
> > previous one, and immediately after add a new one, resulting in two
> > calls to the driver config function.)
> 
> Interesting. But that only works if it does that both together under
> rtnl. I don't think the context really matters -- it should be the same
> at least from a locking POV you have both rtnl and mgd->mtx acquired.
> 
> > > Also, and this applies to the change in mlme.c too, you must never put
> > > work that acquires the rtnl onto the mac80211 workqueue ... that's what
> > > you were trying to fix to start with!
> > 
> > > But because the interface might go away before your work runs, you're in
> > > a stupid situation where you can't really use a per-interface work
> > > either ... I think you probably need to have the work in ieee80211_local
> > > and iterate the interface list.
> > 
> > I thought about iterating the interface list. I assume you imply calling
> > the configure function for every interface.
> 
> Only if it's associated, I guess.
> 
> > Going still back to the current patch: assuming that you overlooked the
> > sdata_running() call in the arp_config_work() function, and we can after
> > all cancel_work_sync in _stop(), would using the kernel's default
> > workqueue solve the rtnl problem, or are the rtnl dependencies there
> > too?
> 
> Using the default wq would solve the rtnl from workqueue problem,
> obviously, but wouldn't fix the cancel_work_sync problem.
> 

Yeah, I actually did realize this during the night. No, I wasn't
sleepless - my brain still has a tendency to generate realizations for
the joy of the morning.

I'll try to think about alternative solutions. The driver provided list
idea is neat, but I think will scale badly for multiple vif's.

-Juuso

> johannes
> 



^ permalink raw reply

* Re: [PATCH v3 1/3] cfg80211: Add nl80211 antenna configuration
From: Bruno Randolf @ 2010-06-08  1:19 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1275901408.3639.2.camel@jlt3.sipsolutions.net>

On Monday 07 June 2010 18:03:28 you wrote:
> On Mon, 2010-06-07 at 15:58 +0900, Bruno Randolf wrote:
> > +static int nl80211_get_antenna(struct sk_buff *skb, struct genl_info
> > *info) +{
> > +	struct cfg80211_registered_device *rdev;
> > +	struct sk_buff *msg;
> > +	void *hdr;
> > +	int res;
> > +	u8 tx_ant, rx_ant;
> 
> You should probably set them both to 0 here,

ok.
 
> > +	res = rdev->ops->get_antenna(&rdev->wiphy, &tx_ant, &rx_ant);
> > +	if (res)
> > +		goto free_msg;
> 
> and complain about the driver if they still are after this.

would that be a WARN_ON?

thanks,
bruno

^ permalink raw reply

* Re: [PATCH v3 1/3] cfg80211: Add nl80211 antenna configuration
From: Bruno Randolf @ 2010-06-08  1:10 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <1275901514.3639.4.camel@jlt3.sipsolutions.net>

On Monday 07 June 2010 18:05:14 you wrote:
> On Mon, 2010-06-07 at 15:58 +0900, Bruno Randolf wrote:
> > + * @NL80211_CMD_GET_ANTENNA: Get antenna configuration from driver.
> 
> Since we already have runtime configuration and capability information
> as part of the wiphy information printout, remind me again what was
> wrong with adding antenna information there as well rather than having a
> separate command to retrieve it?
>
> As far as differentiating that information is concerned, you can easily
> implement an iw "get antenna" command by just partially printing the
> wiphy information, for example, no?

i don't particularly care about where the antenna information is printed 
exactly, so anything will be fine with me.

but when i look at the wiphy info, it shows mostly capability information, 
like the list of supported frequencies, list of bitrates, supported interface 
modes, supported commands. the only exception is coverage class, which is the 
only runtime configuration as far as i can see. therefore i thought it doesnt 
fit there well.

maybe another command for getting runtime configuration like channel(s), fixed 
bitrates, essid, bssid, RTS/CTS, fraqmentation, txpower, power management, 
antenna settings, etc... would make sense? allthough in this list antenna is 
probably the only one which is per phy and not per interface...

i can leave the 'antenna get' command out until this is clarified.

bruno

^ permalink raw reply

* Re: [PATCH] mac80211: fix deauth before assoc
From: Miles Lane @ 2010-06-07 22:29 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1275940207.29978.24.camel@jlt3.sipsolutions.net>

Tested.  Looks good.

On Mon, Jun 7, 2010 at 3:50 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> When we receive a deauthentication frame before
> having successfully associated, we neither print
> a message nor abort assocation. The former makes
> it hard to debug, while the latter later causes
> a warning in cfg80211 when, as will typically be
> the case, association timed out.
>
> This warning was reported by many, e.g. in
> https://bugzilla.kernel.org/show_bug.cgi?id=15981,
> but I couldn't initially pinpoint it. I verified
> the fix by hacking hostapd to send a deauth frame
> instead of an association response.
>
> Cc: stable@kernel.org
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  net/mac80211/mlme.c |   39 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 38 insertions(+), 1 deletion(-)
>
> --- wireless-testing.orig/net/mac80211/mlme.c   2010-06-07 21:35:41.000000000 +0200
> +++ wireless-testing/net/mac80211/mlme.c        2010-06-07 21:46:00.000000000 +0200
> @@ -1695,8 +1695,45 @@ void ieee80211_sta_rx_queued_mgmt(struct
>        mutex_unlock(&ifmgd->mtx);
>
>        if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
> -           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
> +           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
> +               struct ieee80211_local *local = sdata->local;
> +               struct ieee80211_work *wk;
> +
> +               mutex_lock(&local->work_mtx);
> +               list_for_each_entry(wk, &local->work_list, list) {
> +                       if (wk->sdata != sdata)
> +                               continue;
> +
> +                       if (wk->type != IEEE80211_WORK_ASSOC)
> +                               continue;
> +
> +                       if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
> +                               continue;
> +                       if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
> +                               continue;
> +
> +                       /*
> +                        * Printing the message only here means we can't
> +                        * spuriously print it, but it also means that it
> +                        * won't be printed when the frame comes in before
> +                        * we even tried to associate or in similar cases.
> +                        *
> +                        * Ultimately, I suspect cfg80211 should print the
> +                        * messages instead.
> +                        */
> +                       printk(KERN_DEBUG
> +                              "%s: deauthenticated from %pM (Reason: %u)\n",
> +                              sdata->name, mgmt->bssid,
> +                              le16_to_cpu(mgmt->u.deauth.reason_code));
> +
> +                       list_del_rcu(&wk->list);
> +                       free_work(wk);
> +                       break;
> +               }
> +               mutex_unlock(&local->work_mtx);
> +
>                cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
> +       }
>  }
>
>  static void ieee80211_sta_timer(unsigned long data)
>
>
>

^ permalink raw reply

* Re: [PATCH] iwlwifi: add missing rcu_read_lock
From: Miles Lane @ 2010-06-07 22:28 UTC (permalink / raw)
  To: reinette chatre
  Cc: Johannes Berg, John Linville, Guy, Wey-Yi W, linux-wireless
In-Reply-To: <1275946462.1835.9324.camel@rchatre-DESK>

Tested.  Looks good.

On Mon, Jun 7, 2010 at 5:34 PM, reinette chatre
<reinette.chatre@intel.com> wrote:
> On Mon, 2010-06-07 at 12:20 -0700, Johannes Berg wrote:
>> From: Johannes Berg <johannes.berg@intel.com>
>>
>> Using ieee80211_find_sta() needs to be under
>> RCU read lock, which iwlwifi currently misses,
>> so fix it.
>>
>> Cc: stable@kernel.org
>> Reported-by: Miles Lane <miles.lane@gmail.com>
>> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
>
> Acked-by: Reinette Chatre <reinette.chatre@intel.com>
>
> Reinette
>
>
>

^ permalink raw reply

* Re: [PATCH] iwlwifi: add missing rcu_read_lock
From: reinette chatre @ 2010-06-07 21:34 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, Guy, Wey-Yi W, Miles Lane, linux-wireless
In-Reply-To: <1275938438.29978.23.camel@jlt3.sipsolutions.net>

On Mon, 2010-06-07 at 12:20 -0700, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> Using ieee80211_find_sta() needs to be under
> RCU read lock, which iwlwifi currently misses,
> so fix it.
> 
> Cc: stable@kernel.org
> Reported-by: Miles Lane <miles.lane@gmail.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>

Acked-by: Reinette Chatre <reinette.chatre@intel.com>

Reinette



^ permalink raw reply

* Re: [PATCH] iwlwifi: add missing rcu_read_lock
From: Miles Lane @ 2010-06-07 21:31 UTC (permalink / raw)
  To: Johannes Berg
  Cc: John Linville, Reinette Chatre, Wey-Yi W Guy, linux-wireless
In-Reply-To: <1275938438.29978.23.camel@jlt3.sipsolutions.net>

On Mon, Jun 7, 2010 at 3:20 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Using ieee80211_find_sta() needs to be under
> RCU read lock, which iwlwifi currently misses,
> so fix it.
>
> Cc: stable@kernel.org
> Reported-by: Miles Lane <miles.lane@gmail.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  drivers/net/wireless/iwlwifi/iwl-agn-tx.c |    2 ++
>  1 file changed, 2 insertions(+)
>
> --- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn-tx.c     2010-06-07 21:17:56.000000000 +0200
> +++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn-tx.c  2010-06-07 21:18:04.000000000 +0200
> @@ -1146,6 +1146,7 @@ static void iwlagn_tx_status(struct iwl_
>        struct ieee80211_sta *sta;
>        struct iwl_station_priv *sta_priv;
>
> +       rcu_read_lock();
>        sta = ieee80211_find_sta(priv->vif, hdr->addr1);
>        if (sta) {
>                sta_priv = (void *)sta->drv_priv;
> @@ -1154,6 +1155,7 @@ static void iwlagn_tx_status(struct iwl_
>                    atomic_dec_return(&sta_priv->pending_frames) == 0)
>                        ieee80211_sta_block_awake(priv->hw, sta, false);
>        }
> +       rcu_read_unlock();
>
>        ieee80211_tx_status_irqsafe(priv->hw, skb);
>  }
>
>
>

Unclean patch application - is this to be expected?

patching file drivers/net/wireless/iwlwifi/iwl-agn-tx.c
Hunk #1 succeeded at 1125 (offset -21 lines).
Hunk #2 succeeded at 1134 (offset -21 lines).

^ permalink raw reply

* Re: [PATCH] iwlwifi: fix-up botched revert
From: Randy Dunlap @ 2010-06-07 20:38 UTC (permalink / raw)
  To: John W. Linville
  Cc: linux-wireless, Stephen Rothwell, linux-next, linux-kernel
In-Reply-To: <1275936576-15590-1-git-send-email-linville@tuxdriver.com>

On 06/07/10 11:49, John W. Linville wrote:
> In the revert of "iwlwifi: move _agn statistics related structure", I
> need to use CONFIG_IWLWIFI_DEBUGFS instead of CONFIG_IWLWIFI_DEBUG in
> the private structure definition.  Without this patch, it is possible
> to get this:
> 
> drivers/net/wireless/iwlwifi/iwl-rx.c: In function 'iwl_accumulative_statistics':
> drivers/net/wireless/iwlwifi/iwl-rx.c:304: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:305: error: 'struct iwl_priv' has no member named 'delta_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:306: error: 'struct iwl_priv' has no member named 'max_delta'
> drivers/net/wireless/iwlwifi/iwl-rx.c:321: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:323: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:325: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:327: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:329: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:331: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c: In function 'iwl_reply_statistics':
> drivers/net/wireless/iwlwifi/iwl-rx.c:484: error: 'struct iwl_priv' has no member named 'accum_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:486: error: 'struct iwl_priv' has no member named 'delta_statistics'
> drivers/net/wireless/iwlwifi/iwl-rx.c:488: error: 'struct iwl_priv' has no member named 'max_delta'
> 
> Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
> Signed-off-by: John W. Linville <linville@tuxdriver.com>

Acked-by: Randy Dunlap <randy.dunlap@oracle.com>

Thanks.

> ---
>  drivers/net/wireless/iwlwifi/iwl-dev.h |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
> index f359d9f..a00248c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-dev.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
> @@ -1208,7 +1208,7 @@ struct iwl_priv {
>  	struct iwl_tt_mgmt thermal_throttle;
>  
>  	struct iwl_notif_statistics statistics;
> -#ifdef CONFIG_IWLWIFI_DEBUG
> +#ifdef CONFIG_IWLWIFI_DEBUGFS
>  	struct iwl_notif_statistics accum_statistics;
>  	struct iwl_notif_statistics delta_statistics;
>  	struct iwl_notif_statistics max_delta;


-- 
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox