Linux wireless drivers development
 help / color / mirror / Atom feed
* [RFC 10/12] net: add wireless TX status socket option
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

The 802.1X EAPOL handshake hostapd does requires
knowing whether the frame was ack'ed by the peer.
Currently, we fudge this pretty badly by not even
transmitting the frame as a normal data frame but
injecting it with radiotap and getting the status
out of radiotap monitor as well. This is rather
complex, confuses users (mon.wlan0 presence) and
doesn't work with all hardware.

To get rid of that hack, introduce a real wifi TX
status option for data frame transmissions.

This works similar to the existing TX timestamping
in that it reflects the SKB back to the socket's
error queue with a SCM_WIFI_STATUS cmsg that has
an int indicating ACK status (0/1).

Since it is possible that at some point we will
want to have TX timestamping and wifi status in a
single errqueue SKB (there's little point in not
doing that), redefine SO_EE_ORIGIN_TIMESTAMPING
to SO_EE_ORIGIN_TXSTATUS which can collect more
than just the timestamp; keep the old constant
as an alias of course. Currently the internal APIs
don't make that possible, but it wouldn't be hard
to split them up in a way that makes it possible.

Thanks to Neil Horman for helping me figure out
the functions that add the control messages.

TODO:
 * sock_tx_timestamp() function should be renamed,
   maybe to sock_tx_status()?
 * sock_recv_timestamp() should also be renamed,
   I had a hard time figuring out the difference
   between that and sock_recv_ts_and_drops(). The
   former is generic, while the latter adds RX
   information only, maybe that should be reflected
   in new names?

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/alpha/include/asm/socket.h   |    3 +++
 arch/arm/include/asm/socket.h     |    3 +++
 arch/avr32/include/asm/socket.h   |    3 +++
 arch/cris/include/asm/socket.h    |    3 +++
 arch/frv/include/asm/socket.h     |    3 +++
 arch/h8300/include/asm/socket.h   |    3 +++
 arch/ia64/include/asm/socket.h    |    3 +++
 arch/m32r/include/asm/socket.h    |    3 +++
 arch/m68k/include/asm/socket.h    |    3 +++
 arch/mips/include/asm/socket.h    |    3 +++
 arch/mn10300/include/asm/socket.h |    3 +++
 arch/parisc/include/asm/socket.h  |    3 +++
 arch/powerpc/include/asm/socket.h |    3 +++
 arch/s390/include/asm/socket.h    |    3 +++
 arch/sparc/include/asm/socket.h   |    3 +++
 arch/xtensa/include/asm/socket.h  |    3 +++
 include/asm-generic/socket.h      |    3 +++
 include/linux/errqueue.h          |    3 ++-
 include/linux/skbuff.h            |   19 +++++++++++++++++--
 include/net/sock.h                |    7 +++++++
 net/core/skbuff.c                 |   20 ++++++++++++++++++++
 net/core/sock.c                   |    9 +++++++++
 net/socket.c                      |   19 +++++++++++++++++++
 23 files changed, 125 insertions(+), 3 deletions(-)

--- a/include/asm-generic/socket.h	2011-10-12 19:24:34.000000000 +0200
+++ b/include/asm-generic/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -64,4 +64,7 @@
 #define SO_DOMAIN		39
 
 #define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS	SO_WIFI_STATUS
 #endif /* __ASM_GENERIC_SOCKET_H */
--- a/net/core/sock.c	2011-10-12 19:24:40.000000000 +0200
+++ b/net/core/sock.c	2011-10-13 13:45:19.000000000 +0200
@@ -743,6 +743,11 @@ set_rcvbuf:
 		else
 			sock_reset_flag(sk, SOCK_RXQ_OVFL);
 		break;
+
+	case SO_WIFI_STATUS:
+		sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -964,6 +969,10 @@ int sock_getsockopt(struct socket *sock,
 		v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
 		break;
 
+	case SO_WIFI_STATUS:
+		v.val = !!sock_flag(sk, SOCK_WIFI_STATUS);
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
--- a/include/net/sock.h	2011-10-12 19:24:34.000000000 +0200
+++ b/include/net/sock.h	2011-10-13 13:45:19.000000000 +0200
@@ -564,6 +564,7 @@ enum sock_flags {
 	SOCK_FASYNC, /* fasync() active */
 	SOCK_RXQ_OVFL,
 	SOCK_ZEROCOPY, /* buffers from userspace */
+	SOCK_WIFI_STATUS, /* push wifi status to userspace */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -1705,7 +1706,10 @@ static inline int sock_intr_errno(long t
 
 extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 	struct sk_buff *skb);
+extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb);
 
+/* XXX: rename this function now? */
 static __inline__ void
 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
 {
@@ -1732,6 +1736,9 @@ sock_recv_timestamp(struct msghdr *msg,
 		__sock_recv_timestamp(msg, sk, skb);
 	else
 		sk->sk_stamp = kt;
+
+	if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
+		__sock_recv_wifi_status(msg, sk, skb);
 }
 
 extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
--- a/arch/alpha/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/alpha/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -69,6 +69,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/arm/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/arm/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/avr32/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/avr32/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* __ASM_AVR32_SOCKET_H */
--- a/arch/cris/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/cris/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -64,6 +64,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
 
--- a/arch/frv/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/frv/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,5 +62,8 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
--- a/arch/h8300/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/h8300/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/ia64/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/ia64/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -71,4 +71,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_IA64_SOCKET_H */
--- a/arch/m32r/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/m32r/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_M32R_SOCKET_H */
--- a/arch/m68k/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/m68k/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/mips/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/mips/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -82,6 +82,9 @@ To add: #define SO_REUSEPORT 0x0200	/* A
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
--- a/arch/mn10300/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/mn10300/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/parisc/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/parisc/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -61,6 +61,9 @@
 
 #define SO_RXQ_OVFL             0x4021
 
+#define SO_WIFI_STATUS		0x4022
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/powerpc/include/asm/socket.h	2011-10-12 19:24:33.000000000 +0200
+++ b/arch/powerpc/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -69,4 +69,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
--- a/arch/s390/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/s390/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -70,4 +70,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/sparc/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/sparc/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -58,6 +58,9 @@
 
 #define SO_RXQ_OVFL             0x0024
 
+#define SO_WIFI_STATUS		0x0025
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
--- a/arch/xtensa/include/asm/socket.h	2011-10-12 19:24:32.000000000 +0200
+++ b/arch/xtensa/include/asm/socket.h	2011-10-13 13:45:19.000000000 +0200
@@ -73,4 +73,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _XTENSA_SOCKET_H */
--- a/include/linux/errqueue.h	2011-10-12 19:24:33.000000000 +0200
+++ b/include/linux/errqueue.h	2011-10-13 13:45:19.000000000 +0200
@@ -17,7 +17,8 @@ struct sock_extended_err {
 #define SO_EE_ORIGIN_LOCAL	1
 #define SO_EE_ORIGIN_ICMP	2
 #define SO_EE_ORIGIN_ICMP6	3
-#define SO_EE_ORIGIN_TIMESTAMPING 4
+#define SO_EE_ORIGIN_TXSTATUS	4
+#define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
 
 #define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
 
--- a/include/linux/skbuff.h	2011-10-12 19:24:33.000000000 +0200
+++ b/include/linux/skbuff.h	2011-10-13 13:45:19.000000000 +0200
@@ -190,6 +190,9 @@ enum {
 
 	/* device driver supports TX zero-copy buffers */
 	SKBTX_DEV_ZEROCOPY = 1 << 4,
+
+	/* generate wifi status information (where possible) */
+	SKBTX_WIFI_STATUS = 1 << 5,
 };
 
 /*
@@ -322,6 +325,8 @@ typedef unsigned char *sk_buff_data_t;
  *	@queue_mapping: Queue mapping for multiqueue devices
  *	@ndisc_nodetype: router type (from link layer)
  *	@ooo_okay: allow the mapping of a socket to a queue to be changed
+ *	@wifi_acked_valid: wifi_acked was set
+ *	@wifi_acked: whether frame was acked on wifi or not
  *	@dma_cookie: a cookie to one of several possible DMA operations
  *		done by skb DMA functions
  *	@secmark: security marking
@@ -414,10 +419,11 @@ struct sk_buff {
 	__u8			ndisc_nodetype:2;
 #endif
 	__u8			ooo_okay:1;
+	__u8			wifi_acked_valid:1;
+	__u8			wifi_acked:1;
+	/* 11/13 bit hole (depending on nodetype presence) */
 	kmemcheck_bitfield_end(flags2);
 
-	/* 0/13 bit hole */
-
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
@@ -2062,6 +2068,15 @@ static inline void skb_tx_timestamp(stru
 	sw_tx_timestamp(skb);
 }
 
+/**
+ * skb_complete_wifi_ack - deliver skb with wifi status
+ *
+ * @skb: the original outgoing packet
+ * @acked: ack status
+ *
+ */
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked);
+
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
--- a/net/core/skbuff.c	2011-10-12 19:24:34.000000000 +0200
+++ b/net/core/skbuff.c	2011-10-13 13:45:19.000000000 +0200
@@ -3150,6 +3150,26 @@ void skb_tstamp_tx(struct sk_buff *orig_
 }
 EXPORT_SYMBOL_GPL(skb_tstamp_tx);
 
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
+{
+	struct sock *sk = skb->sk;
+	struct sock_exterr_skb *serr;
+	int err;
+
+	skb->wifi_acked_valid = 1;
+	skb->wifi_acked = acked;
+
+	serr = SKB_EXT_ERR(skb);
+	memset(serr, 0, sizeof(*serr));
+	serr->ee.ee_errno = ENOMSG;
+	serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
+
+	err = sock_queue_err_skb(sk, skb);
+	if (err)
+		kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
+
 
 /**
  * skb_partial_csum_set - set up and verify partial csum values for packet
--- a/net/socket.c	2011-10-12 19:24:34.000000000 +0200
+++ b/net/socket.c	2011-10-13 13:45:19.000000000 +0200
@@ -531,6 +531,7 @@ void sock_release(struct socket *sock)
 }
 EXPORT_SYMBOL(sock_release);
 
+/* XXX: rename this function now */
 int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 {
 	*tx_flags = 0;
@@ -538,6 +539,8 @@ int sock_tx_timestamp(struct sock *sk, _
 		*tx_flags |= SKBTX_HW_TSTAMP;
 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
 		*tx_flags |= SKBTX_SW_TSTAMP;
+	if (sock_flag(sk, SOCK_WIFI_STATUS))
+		*tx_flags |= SKBTX_WIFI_STATUS;
 	return 0;
 }
 EXPORT_SYMBOL(sock_tx_timestamp);
@@ -674,6 +677,22 @@ void __sock_recv_timestamp(struct msghdr
 }
 EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
 
+void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb)
+{
+	int ack;
+
+	if (!sock_flag(sk, SOCK_WIFI_STATUS))
+		return;
+	if (!skb->wifi_acked_valid)
+		return;
+
+	ack = skb->wifi_acked;
+
+	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
+}
+EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
+
 static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
 				   struct sk_buff *skb)
 {



^ permalink raw reply

* [RFC 09/12] mac80211: support client probe
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Support probing clients with null data frames
in AP mode.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c    |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/status.c |   45 +++++++++++++++++++--------------
 2 files changed, 95 insertions(+), 18 deletions(-)

--- a/net/mac80211/cfg.c	2011-10-13 13:45:15.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-13 21:52:32.000000000 +0200
@@ -2484,6 +2484,73 @@ static int ieee80211_tdls_oper(struct wi
 	return 0;
 }
 
+static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
+				  const u8 *peer, u64 *cookie)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_qos_hdr *nullfunc;
+	struct sk_buff *skb;
+	int size = sizeof(*nullfunc);
+	__le16 fc;
+	bool qos;
+	struct ieee80211_tx_info *info;
+	struct sta_info *sta;
+
+	rcu_read_lock();
+	sta = sta_info_get(sdata, peer);
+	if (sta)
+		qos = test_sta_flag(sta, WLAN_STA_WME);
+	rcu_read_unlock();
+
+	if (!sta)
+		return -ENOLINK;
+
+	if (qos) {
+		fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+				 IEEE80211_STYPE_QOS_NULLFUNC |
+				 IEEE80211_FCTL_FROMDS);
+	} else {
+		size -= 2;
+		fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+				 IEEE80211_STYPE_NULLFUNC |
+				 IEEE80211_FCTL_FROMDS);
+	}
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
+	if (!skb)
+		return -ENOMEM;
+
+	skb->dev = dev;
+
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	nullfunc = (void *) skb_put(skb, size);
+	nullfunc->frame_control = fc;
+	nullfunc->duration_id = 0;
+	memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
+	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+	memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+	nullfunc->seq_ctrl = 0;
+
+	info = IEEE80211_SKB_CB(skb);
+
+	info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
+		       IEEE80211_TX_INTFL_NL80211_FRAME_TX;
+
+	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+	skb->priority = 7;
+	if (qos)
+		nullfunc->qos_ctrl = cpu_to_le16(7);
+
+	local_bh_disable();
+	ieee80211_xmit(sdata, skb);
+	local_bh_enable();
+
+	*cookie = (unsigned long) skb;
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2549,4 +2616,5 @@ struct cfg80211_ops mac80211_config_ops
 	.set_rekey_data = ieee80211_set_rekey_data,
 	.tdls_oper = ieee80211_tdls_oper,
 	.tdls_mgmt = ieee80211_tdls_mgmt,
+	.probe_client = ieee80211_probe_client,
 };
--- a/net/mac80211/status.c	2011-10-13 13:45:14.000000000 +0200
+++ b/net/mac80211/status.c	2011-10-13 21:51:41.000000000 +0200
@@ -420,27 +420,36 @@ void ieee80211_tx_status(struct ieee8021
 	}
 
 	if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
-		struct ieee80211_work *wk;
 		u64 cookie = (unsigned long)skb;
 
-		rcu_read_lock();
-		list_for_each_entry_rcu(wk, &local->work_list, list) {
-			if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
-				continue;
-			if (wk->offchan_tx.frame != skb)
-				continue;
-			wk->offchan_tx.status = true;
-			break;
-		}
-		rcu_read_unlock();
-		if (local->hw_roc_skb_for_status == skb) {
-			cookie = local->hw_roc_cookie ^ 2;
-			local->hw_roc_skb_for_status = NULL;
-		}
+		if (ieee80211_is_nullfunc(hdr->frame_control) ||
+		    ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+			if (info->flags & IEEE80211_TX_STAT_ACK)
+				cfg80211_probe_acked(skb->dev, hdr->addr1,
+						     cookie, GFP_ATOMIC);
+		} else {
+			struct ieee80211_work *wk;
 
-		cfg80211_mgmt_tx_status(
-			skb->dev, cookie, skb->data, skb->len,
-			!!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
+			rcu_read_lock();
+			list_for_each_entry_rcu(wk, &local->work_list, list) {
+				if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
+					continue;
+				if (wk->offchan_tx.frame != skb)
+					continue;
+				wk->offchan_tx.status = true;
+				break;
+			}
+			rcu_read_unlock();
+			if (local->hw_roc_skb_for_status == skb) {
+				cookie = local->hw_roc_cookie ^ 2;
+				local->hw_roc_skb_for_status = NULL;
+			}
+
+			cfg80211_mgmt_tx_status(
+				skb->dev, cookie, skb->data, skb->len,
+				!!(info->flags & IEEE80211_TX_STAT_ACK),
+				GFP_ATOMIC);
+		}
 	}
 
 	/* this was a transmitted frame, but now we want to reuse it */



^ permalink raw reply

* [RFC 08/12] nl80211: add API to probe a client
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

When the AP SME in hostapd is used it wants to
probe the clients when they have been idle for
some time. Add explicit API to support this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |    9 ++++
 include/net/cfg80211.h  |   16 +++++++
 net/wireless/nl80211.c  |  102 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 127 insertions(+)

--- a/include/linux/nl80211.h	2011-10-13 11:09:24.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-13 11:30:08.000000000 +0200
@@ -520,6 +520,13 @@
  *	If used as the command, must have an interface index, and you can
  *	only unsubscribe from the event by closing the socket.
  *
+ * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+ *	by sending a null data frame to it and reporting when the frame is
+ *	acknowleged. This is used to allow timing out inactive clients. Uses
+ *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+ *	direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+ *	up the event with the request.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -651,6 +658,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_UNEXPECTED_FRAME,
 
+	NL80211_CMD_PROBE_CLIENT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- a/include/net/cfg80211.h	2011-10-13 11:10:33.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-13 12:55:26.000000000 +0200
@@ -1425,6 +1425,9 @@ struct cfg80211_gtk_rekey_data {
  *
  * @tdls_mgmt: Transmit a TDLS management frame.
  * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
+ *
+ * @probe_client: probe an associated client, must return a cookie that it
+ *	later passes to cfg80211_probe_acked().
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1614,6 +1617,9 @@ struct cfg80211_ops {
 			     u16 status_code, const u8 *buf, size_t len);
 	int	(*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
 			     u8 *peer, enum nl80211_tdls_operation oper);
+
+	int	(*probe_client)(struct wiphy *wiphy, struct net_device *dev,
+				const u8 *peer, u64 *cookie);
 };
 
 /*
@@ -3207,6 +3213,16 @@ void cfg80211_pmksa_candidate_notify(str
 bool cfg80211_rx_spurious_frame(struct net_device *dev,
 				const u8 *addr, gfp_t gfp);
 
+/**
+ * cfg80211_probe_acked - notify that probe was acked
+ * @dev: the device the probe was sent on
+ * @addr: the address of the peer
+ * @cookie: the cookie filled in @probe_client previously
+ * @gfp: allocation flags
+ */
+void cfg80211_probe_acked(struct net_device *dev, const u8 *addr,
+			  u64 cookie, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
--- a/net/wireless/nl80211.c	2011-10-13 11:11:29.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-13 13:04:08.000000000 +0200
@@ -891,6 +891,7 @@ static int nl80211_send_wiphy(struct sk_
 	}
 	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
 		CMD(sched_scan_start, START_SCHED_SCAN);
+	CMD(probe_client, PROBE_CLIENT);
 
 #undef CMD
 
@@ -5844,6 +5845,59 @@ static int nl80211_register_unexpected_f
 	return 0;
 }
 
+static int nl80211_probe_client(struct sk_buff *skb,
+				struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct sk_buff *msg;
+	void *hdr;
+	const u8 *addr;
+	u64 cookie;
+	int err;
+
+	if (wdev->iftype != NL80211_IFTYPE_AP &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	if (!rdev->ops->probe_client)
+		return -EOPNOTSUPP;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+			     NL80211_CMD_PROBE_CLIENT);
+
+	if (IS_ERR(hdr)) {
+		err = PTR_ERR(hdr);
+		goto free_msg;
+	}
+
+	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+	err = rdev->ops->probe_client(&rdev->wiphy, dev, addr, &cookie);
+	if (err)
+		goto free_msg;
+
+	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	err = -ENOBUFS;
+ free_msg:
+	nlmsg_free(msg);
+	return err;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -6407,6 +6461,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_PROBE_CLIENT,
+		.doit = nl80211_probe_client,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7528,6 +7590,46 @@ nl80211_send_cqm_pktloss_notify(struct c
 	nlmsg_free(msg);
 }
 
+void cfg80211_probe_acked(struct net_device *dev, const u8 *addr,
+			  u64 cookie, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_probe_acked);
+
 static int nl80211_netlink_notify(struct notifier_block * nb,
 				  unsigned long state,
 				  void *_notify)



^ permalink raw reply

* [RFC 07/12] nl80211: advertise device AP SME
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Add the ability to advertise that the device
contains the AP SME and what features it can
support.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/ath/ath6kl/init.c |    4 +++-
 include/linux/nl80211.h                |   20 ++++++++++++++++++++
 include/net/cfg80211.h                 |    6 ++++++
 net/wireless/core.c                    |    4 ++++
 net/wireless/nl80211.c                 |    4 ++++
 5 files changed, 37 insertions(+), 1 deletion(-)

--- a/include/linux/nl80211.h	2011-10-13 11:06:25.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-13 11:09:24.000000000 +0200
@@ -1122,6 +1122,11 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ *	that have AP support to indicate that the have the AP SME integrated
+ *	with support for the features listed in this attribute, see
+ *	&enum nl80211_ap_sme_features.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1350,6 +1355,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_DEVICE_AP_MLME,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2661,4 +2668,17 @@ enum nl80211_tdls_operation {
 	NL80211_TDLS_DISABLE_LINK,
 };
 
+/**
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * @NL80211_AP_SME_WSC: The driver is capable of indicating received probe
+ *	request frames to userspace via management frame subscription events
+ *	if the payload includes the WSC IE. The driver is capable of adding
+ *	the WSC IE as configured from userspace into beacons, probe responses
+ *	and (re)association reponse frame and allows userspace to update them
+ *	during the lifetime of the BSS.
+ */
+enum nl80211_ap_sme_features {
+	NL80211_AP_SME_WSC	= 1 << 0,
+};
+
 #endif /* __LINUX_NL80211_H */
--- a/include/net/cfg80211.h	2011-10-13 11:06:25.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-13 11:10:33.000000000 +0200
@@ -1672,6 +1672,7 @@ struct cfg80211_ops {
  *	teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
  *	command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1690,6 +1691,7 @@ enum wiphy_flags {
 	WIPHY_FLAG_AP_UAPSD			= BIT(14),
 	WIPHY_FLAG_SUPPORTS_TDLS		= BIT(15),
 	WIPHY_FLAG_TDLS_EXTERNAL_SETUP		= BIT(16),
+	WIPHY_FLAG_HAVE_AP_SME			= BIT(17),
 };
 
 /**
@@ -1900,6 +1902,8 @@ struct wiphy_wowlan_support {
  *	may request, if implemented.
  *
  * @wowlan: WoWLAN support information
+ *
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1923,6 +1927,8 @@ struct wiphy {
 
 	u32 flags;
 
+	u32 ap_sme_capa;
+
 	enum cfg80211_signal_type signal_type;
 
 	int bss_priv_size;
--- a/net/wireless/core.c	2011-10-06 21:59:47.000000000 +0200
+++ b/net/wireless/core.c	2011-10-13 11:12:27.000000000 +0200
@@ -492,6 +492,10 @@ int wiphy_register(struct wiphy *wiphy)
 		    !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
 		return -EINVAL;
 
+	if (WARN_ON(wiphy->ap_sme_capa &&
+		    !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
+		return -EINVAL;
+
 	if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
 		return -EINVAL;
 
--- a/net/wireless/nl80211.c	2011-10-13 10:21:41.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-13 11:11:29.000000000 +0200
@@ -1008,6 +1008,10 @@ static int nl80211_send_wiphy(struct sk_
 	if (nl80211_put_iface_combinations(&dev->wiphy, msg))
 		goto nla_put_failure;
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME)
+		NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_MLME,
+			    dev->wiphy.ap_sme_capa);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
--- a/drivers/net/wireless/ath/ath6kl/init.c	2011-10-05 09:07:16.000000000 +0200
+++ b/drivers/net/wireless/ath/ath6kl/init.c	2011-10-13 11:14:01.000000000 +0200
@@ -1548,7 +1548,9 @@ static int ath6kl_init(struct net_device
 	ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
 			 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
 
-	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
+				  WIPHY_FLAG_HAVE_AP_SME;
+	ar->wdev->wiphy->ap_sme_capa = NL80211_AP_SME_WSC;
 
 	status = ath6kl_target_config_wlan_params(ar);
 	if (!status)



^ permalink raw reply

* [RFC 06/12] mac80211: support spurious class3 event
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Add support for the spurious class3 frame event
to mac80211 to enable AP w/o monitor mode.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rx.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/net/mac80211/rx.c	2011-10-11 15:22:31.000000000 +0200
+++ b/net/mac80211/rx.c	2011-10-11 15:22:38.000000000 +0200
@@ -854,6 +854,13 @@ ieee80211_rx_h_check(struct ieee80211_rx
 			    rx->sdata->control_port_protocol)
 				return RX_CONTINUE;
 		}
+
+		if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
+		    cfg80211_rx_spurious_frame(rx->sdata->dev,
+		    			       hdr->addr2,
+		    			       GFP_ATOMIC))
+			return RX_DROP_UNUSABLE;
+
 		return RX_DROP_MONITOR;
 	}
 



^ permalink raw reply

* [RFC 05/12] nl80211: allow subscribing to unexpected class3 frames
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

To implement AP mode without monitor interfaces we
need to be able to send a deauth to stations that
send frames without being associated. Enable this
by adding a new nl80211 event for such frames that
an application can subscribe to.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |   13 +++++++++
 include/net/cfg80211.h  |   19 +++++++++++++
 net/wireless/mlme.c     |   16 +++++++++++
 net/wireless/nl80211.c  |   66 ++++++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/nl80211.h  |    3 ++
 5 files changed, 117 insertions(+)

--- a/include/linux/nl80211.h	2011-09-29 17:25:23.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-11 14:46:17.000000000 +0200
@@ -509,6 +509,17 @@
  * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
  * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
  *
+ * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
+ *	(or GO) interface (i.e. hostapd) to ask for unexpected frames to
+ *	implement sending deauth to stations that send unexpected class 3
+ *	frames. Also used as the event sent by the kernel when such a frame
+ *	is received. When 4 address mode is supported, it may also be used
+ *	to notify the AP controller about those frames.
+ *	For the event, the %NL80211_ATTR_MAC attribute carries TA along
+ *	with more information like the interface index.
+ *	If used as the command, must have an interface index, and you can
+ *	only unsubscribe from the event by closing the socket.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -638,6 +649,8 @@ enum nl80211_commands {
 	NL80211_CMD_TDLS_OPER,
 	NL80211_CMD_TDLS_MGMT,
 
+	NL80211_CMD_UNEXPECTED_FRAME,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- a/include/net/cfg80211.h	2011-10-06 21:59:47.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-11 15:22:36.000000000 +0200
@@ -2176,6 +2176,8 @@ struct wireless_dev {
 
 	int beacon_interval;
 
+	u32 ap_unexpected_nlpid;
+
 #ifdef CONFIG_CFG80211_WEXT
 	/* wext data */
 	struct {
@@ -3182,6 +3184,23 @@ void cfg80211_gtk_rekey_notify(struct ne
 void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
 				     const u8 *bssid, bool preauth, gfp_t gfp);
 
+/**
+ * cfg80211_rx_spurious_frame - inform userspace about a spurious frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * a spurious class 3 frame was received, to be able to deauth the
+ * sender. If 4addr frames are supported in AP mode, these may also
+ * be passed here if they aren't yet allowed for the sender so that
+ * the userspace application can set up things properly.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+				const u8 *addr, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
--- a/net/wireless/mlme.c	2011-09-28 17:10:13.000000000 +0200
+++ b/net/wireless/mlme.c	2011-10-11 14:46:43.000000000 +0200
@@ -879,6 +879,9 @@ void cfg80211_mlme_unregister_socket(str
 	}
 
 	spin_unlock_bh(&wdev->mgmt_registrations_lock);
+
+	if (nlpid == wdev->ap_unexpected_nlpid)
+		wdev->ap_unexpected_nlpid = 0;
 }
 
 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
@@ -1107,3 +1110,16 @@ void cfg80211_pmksa_candidate_notify(str
 	nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 }
 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
+
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+				const u8 *addr, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO))
+		return false;
+
+	return nl80211_unexpected_frame(dev, addr, gfp);
+}
+EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
--- a/net/wireless/nl80211.c	2011-10-04 10:49:07.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-11 14:46:55.000000000 +0200
@@ -5823,6 +5823,23 @@ static int nl80211_set_rekey_data(struct
 	return err;
 }
 
+static int nl80211_register_unexpected_frame(struct sk_buff *skb,
+					     struct genl_info *info)
+{
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+	if (wdev->iftype != NL80211_IFTYPE_AP &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EINVAL;
+
+	if (wdev->ap_unexpected_nlpid)
+		return -EBUSY;
+
+	wdev->ap_unexpected_nlpid = info->snd_pid;
+	return 0;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -6378,6 +6395,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_UNEXPECTED_FRAME,
+		.doit = nl80211_register_unexpected_frame,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7198,6 +7223,47 @@ void nl80211_send_sta_del_event(struct c
 	nlmsg_free(msg);
 }
 
+bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+	u32 nlpid = ACCESS_ONCE(wdev->ap_unexpected_nlpid);
+
+	if (!nlpid)
+		return false;
+
+	msg = nlmsg_new(100, gfp);
+	if (!msg)
+		return true;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UNEXPECTED_FRAME);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return true;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return true;
+	}
+
+	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
+	return true;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+	return true;
+}
+
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		      struct net_device *netdev, u32 nlpid,
 		      int freq, const u8 *buf, size_t len, gfp_t gfp)
--- a/net/wireless/nl80211.h	2011-09-23 10:34:28.000000000 +0200
+++ b/net/wireless/nl80211.h	2011-10-11 14:47:39.000000000 +0200
@@ -117,4 +117,7 @@ void nl80211_pmksa_candidate_notify(stru
 				    struct net_device *netdev, int index,
 				    const u8 *bssid, bool preauth, gfp_t gfp);
 
+bool nl80211_unexpected_frame(struct net_device *dev,
+			      const u8 *addr, gfp_t gfp);
+
 #endif /* __NET_WIRELESS_NL80211_H */



^ permalink raw reply

* [RFC 04/12] mac80211: add support for control port protocol in AP mode
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

This will allow us to support dynamic WEP with 802.1X
properly in mac80211 by not encrypting outgoing and
accepting unencrypted incoming frames.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c   |   21 ++++++++++++++++++++-
 net/mac80211/iface.c |   13 ++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

--- a/net/mac80211/cfg.c	2011-10-13 13:16:27.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-13 21:53:56.000000000 +0200
@@ -576,6 +576,8 @@ static int ieee80211_add_beacon(struct w
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct beacon_data *old;
+	struct ieee80211_sub_if_data *vlan;
+	int ret;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -583,7 +585,24 @@ static int ieee80211_add_beacon(struct w
 	if (old)
 		return -EALREADY;
 
-	return ieee80211_config_beacon(sdata, params);
+	ret = ieee80211_config_beacon(sdata, params);
+	if (ret)
+		return ret;
+
+	/*
+	 * Apply control port protocol, this allows us to
+	 * not encrypt dynamic WEP control frames.
+	 */
+	sdata->control_port_protocol = params->crypto.control_port_ethertype;
+	sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
+	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
+		vlan->control_port_protocol =
+			params->crypto.control_port_ethertype;
+		vlan->control_port_no_encrypt =
+			params->crypto.control_port_no_encrypt;
+	}
+
+	return 0;
 }
 
 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
--- a/net/mac80211/iface.c	2011-10-13 13:16:27.000000000 +0200
+++ b/net/mac80211/iface.c	2011-10-13 13:45:15.000000000 +0200
@@ -188,11 +188,22 @@ static int ieee80211_do_open(struct net_
 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
 			return -ENOLINK;
 		break;
-	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_AP_VLAN: {
+		struct ieee80211_sub_if_data *master;
+
 		if (!sdata->bss)
 			return -ENOLINK;
+
 		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
+
+		master = container_of(sdata->bss,
+				      struct ieee80211_sub_if_data, u.ap);
+		sdata->control_port_protocol =
+			master->control_port_protocol;
+		sdata->control_port_no_encrypt =
+			master->control_port_no_encrypt;
 		break;
+		}
 	case NL80211_IFTYPE_AP:
 		sdata->bss = &sdata->u.ap;
 		break;



^ permalink raw reply

* [RFC 03/12] mac80211: add helper to free TX skb
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Drivers that need to drop a frame before it
can be transmitted will usually simply free
that frame. This is currently fine, but in
the future it'll be needed to tell mac80211
about this case, so add a new routine that
frees a TX skb.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h |   10 ++++++++++
 net/mac80211/status.c  |    6 ++++++
 2 files changed, 16 insertions(+)

--- a/include/net/mac80211.h	2011-10-11 12:08:43.000000000 +0200
+++ b/include/net/mac80211.h	2011-10-11 13:50:07.000000000 +0200
@@ -1304,6 +1304,16 @@ ieee80211_get_alt_retry_rate(const struc
 }
 
 /**
+ * ieee80211_free_txskb - free TX skb
+ * @hw: the hardware
+ * @skb: the skb
+ *
+ * Free a transmit skb. Use this funtion when some failure
+ * to transmit happened and thus status cannot be reported.
+ */
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
  * DOC: Hardware crypto acceleration
  *
  * mac80211 is capable of taking advantage of many hardware
--- a/net/mac80211/status.c	2011-10-11 12:08:43.000000000 +0200
+++ b/net/mac80211/status.c	2011-10-11 13:50:08.000000000 +0200
@@ -544,3 +544,9 @@ void ieee80211_report_low_ack(struct iee
 				    num_packets, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(ieee80211_report_low_ack);
+
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ieee80211_free_txskb);



^ permalink raw reply

* [RFC 02/12] mac80211: fix TID for null poll response
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

The queue mapping/TID for non-QoS null data
responses to is never set, making it default
to BK. Fix that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

--- a/net/mac80211/sta_info.c	2011-10-07 10:43:31.000000000 +0200
+++ b/net/mac80211/sta_info.c	2011-10-13 13:16:57.000000000 +0200
@@ -1203,11 +1203,9 @@ static void ieee80211_send_null_response
 	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
 	memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
 
+	skb->priority = tid;
+	skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]);
 	if (qos) {
-		skb->priority = tid;
-
-		skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]);
-
 		nullfunc->qos_ctrl = cpu_to_le16(tid);
 
 		if (reason == IEEE80211_FRAME_RELEASE_UAPSD)



^ permalink raw reply

* [RFC 01/12] mac80211: reformat TX unauthorised check
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20111014151119.246288840@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Reformat the check, the indentation is completely strange.
Also change the last part of the condition to make the
code shorter.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

--- a/net/mac80211/tx.c	2011-10-12 17:11:32.000000000 +0200
+++ b/net/mac80211/tx.c	2011-10-12 17:27:00.000000000 +0200
@@ -1896,11 +1896,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	 * Drop unicast frames to unauthorised stations unless they are
 	 * EAPOL frames from the local station.
 	 */
-	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-		unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized &&
-		      !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
-		       compare_ether_addr(sdata->vif.addr,
-					  skb->data + ETH_ALEN) == 0))) {
+	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
+		     !is_multicast_ether_addr(hdr.addr1) && !authorized &&
+		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
+		      compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN)))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "%s: dropped frame to %pM"



^ permalink raw reply

* [RFC 00/12] no more mon.wlan0
From: Johannes Berg @ 2011-10-14 15:11 UTC (permalink / raw)
  To: linux-wireless

Add infrastructure to get rid of the "cooked"
monitor interface in AP mode.

johannes


^ permalink raw reply

* Re: [PATCH] ssb: Convert to use crc8 code in kernel library
From: Pavel Roskin @ 2011-10-14 15:11 UTC (permalink / raw)
  To: Larry Finger
  Cc: John W Linville, Michael Buesch, zajec5, b43-dev, linux-wireless
In-Reply-To: <4e90ce9a.89uGF659NNpbpyA3%Larry.Finger@lwfinger.net>

On Sat, 08 Oct 2011 17:28:42 -0500
Larry Finger <Larry.Finger@lwfinger.net> wrote:

> +static inline void htol16_buf(u16 *buf, unsigned int size)
> +{
> +	size /= 2;
> +	while (size--)
> +		*(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
>  }

I'm not not sure compilers would optimize it out on little-endian
systems.  Perhaps you want a define that uses this code on
big-endian systems and does nothing on little endian systems.

Also, it would be nice to have a compile-time check that size is even.
Or maybe size should be the number of 16-bit words, but then it would be
better to call the argument "count" or something like that.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* iwlagn: WARN_ON() in iwl_get_idle_rx_chain_count()
From: Michał Mirosław @ 2011-10-14 15:02 UTC (permalink / raw)
  To: Intel Linux Wireless; +Cc: linux-wireless, netdev

WARN_ON() in iwl_get_idle_rx_chain_count() gets triggered on system shutdown
when WiFi card is associated to an AP. This is on kernel built from
Linus' tree, commit 37cf95162af4036b4198756a590aab8126fa2ce4 (3.1.0-rc9+).
It looks HT-related, I can't reproduce this on 802.11g network.

Best Regards,
Michał Mirosław


09:00.0 Network controller: Intel Corporation Centrino Wireless-N 1030 (rev 34)
        Subsystem: Intel Corporation Centrino Wireless-N 1030 BGN
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 52
        Region 0: Memory at f7a00000 (64-bit, non-prefetchable) [size=8K]
        Capabilities: <access denied>
        Kernel driver in use: iwlagn

Oct 14 00:04:26 oko kernel: [ 2796.354030] ------------[ cut here ]------------
Oct 14 00:04:26 oko kernel: [ 2796.354996] WARNING: at /usr/src/linux-git/drivers/net/wireless/iwlwifi/iwl-agn-lib.c:1766 iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]()
Oct 14 00:04:26 oko kernel: [ 2796.355955] Hardware name: Vostro 3350
Oct 14 00:04:26 oko kernel: [ 2796.356906] invalid SMPS mode 0
Oct 14 00:04:26 oko kernel: [ 2796.356920] Modules linked in: acpi_cpufreq mperf cpufreq_conservative autofs4 rfcomm cpufreq_stats bnep cpufreq_powersave cpufreq_userspace pci_stub binfmt_misc microcode uinput nfs lockd auth_rpcgss nfs_acl sunrpc ext2 coretemp loop kvm_intel kvm aesni_intel cryptd aes_x86_64 aes_generic ecb btusb radeon bluetooth uvcvideo usb_storage videodev arc4 media uas iwlagn v4l2_compat_ioctl32 i915 crc16 snd_hda_codec_idt ttm drm_kms_helper mac80211 drm snd_hda_intel snd_hda_codec ehci_hcd snd_hwdep xhci_hcd snd_pcm snd_seq usbcore joydev sg cfg80211 snd_timer sr_mod snd_seq_device snd r8169 psmouse dell_wmi cdrom dell_laptop soundcore i2c_algo_bit pcspkr evdev sparse_keymap processor snd_page_alloc video cfbcopyarea mii dcdbas button cfbimgblt cfbfillrect wmi ac battery ext3 jbd mbcache dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod thermal thermal_sys [last unloaded: vboxdrv]
Oct 14 00:04:26 oko kernel: [ 2796.365031] Pid: 3017, comm: wpa_supplicant Not tainted 3.1.0-rc9+ #12
Oct 14 00:04:26 oko kernel: [ 2796.366263] Call Trace:
Oct 14 00:04:26 oko kernel: [ 2796.367490]  [<ffffffff8103437f>] ? warn_slowpath_common+0x78/0x8c
Oct 14 00:04:26 oko kernel: [ 2796.368673]  [<ffffffff8103442b>] ? warn_slowpath_fmt+0x45/0x4a
Oct 14 00:04:26 oko kernel: [ 2796.369836]  [<ffffffffa0310733>] ? __sta_info_destroy+0x267/0x2af [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.371046]  [<ffffffffa03a93f1>] ? iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.372274]  [<ffffffffa03b2f9e>] ? iwlagn_bss_info_changed+0x245/0x4b3 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.373753]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.374990]  [<ffffffffa031c03a>] ? __ieee80211_recalc_idle+0xef/0x194 [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.376272]  [<ffffffffa031cbee>] ? ieee80211_recalc_idle+0x1e/0x42 [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.377506]  [<ffffffffa0319690>] ? ieee80211_mgd_deauth+0x19c/0x1c0 [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.378771]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.380083]  [<ffffffffa01ca76c>] ? __cfg80211_mlme_deauth+0x107/0x116 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.381293]  [<ffffffff812e64d9>] ? schedule_hrtimeout_range_clock+0xc8/0x103
Oct 14 00:04:26 oko kernel: [ 2796.382550]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.383803]  [<ffffffffa01ca7e4>] ? cfg80211_mlme_deauth+0x69/0x82 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.385039]  [<ffffffff81023735>] ? __wake_up_common+0x40/0x77
Oct 14 00:04:26 oko kernel: [ 2796.386309]  [<ffffffffa01c15ed>] ? nl80211_deauthenticate+0xbc/0xc7 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.387607]  [<ffffffffa01c35cb>] ? nl80211_pre_doit+0x85/0xfb [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.389171]  [<ffffffff81250f71>] ? genl_rcv_msg+0x1cb/0x1f9
Oct 14 00:04:26 oko kernel: [ 2796.390753]  [<ffffffff81250da6>] ? genl_rcv+0x28/0x28
Oct 14 00:04:26 oko kernel: [ 2796.392295]  [<ffffffff81250a06>] ? netlink_rcv_skb+0x36/0x7a
Oct 14 00:04:26 oko kernel: [ 2796.393896]  [<ffffffff81250d9d>] ? genl_rcv+0x1f/0x28
Oct 14 00:04:26 oko kernel: [ 2796.395521]  [<ffffffff81250537>] ? netlink_unicast+0xe6/0x14e
Oct 14 00:04:26 oko kernel: [ 2796.397095]  [<ffffffff81250819>] ? netlink_sendmsg+0x27a/0x2b2
Oct 14 00:04:26 oko kernel: [ 2796.398741]  [<ffffffff810f45dc>] ? __pollwait+0xce/0xce
Oct 14 00:04:26 oko kernel: [ 2796.400378]  [<ffffffff8122172d>] ? sock_sendmsg+0xc1/0xde
Oct 14 00:04:26 oko kernel: [ 2796.402042]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.403645]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.405148]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.406650]  [<ffffffff812228d4>] ? move_addr_to_kernel+0x24/0x46
Oct 14 00:04:26 oko kernel: [ 2796.408098]  [<ffffffff812219c5>] ? __sys_sendmsg+0x1e8/0x288
Oct 14 00:04:26 oko kernel: [ 2796.408102]  [<ffffffff812e9798>] ? add_preempt_count+0x9a/0x9c
Oct 14 00:04:26 oko kernel: [ 2796.408107]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.408109]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.408112]  [<ffffffff812e6f14>] ? _raw_spin_unlock_irq+0x23/0x2f
Oct 14 00:04:26 oko kernel: [ 2796.408115]  [<ffffffff810022e1>] ? do_signal+0x51d/0x5f3
Oct 14 00:04:26 oko kernel: [ 2796.408119]  [<ffffffff81008f1b>] ? init_fpu+0x72/0x7f
Oct 14 00:04:26 oko kernel: [ 2796.408122]  [<ffffffff8100969f>] ? check_for_xstate+0x1c/0x6f
Oct 14 00:04:26 oko kernel: [ 2796.408124]  [<ffffffff81009966>] ? restore_i387_xstate+0x9e/0x17c
Oct 14 00:04:26 oko kernel: [ 2796.408128]  [<ffffffff81044e92>] ? do_sigaltstack+0xaa/0x13e
Oct 14 00:04:26 oko kernel: [ 2796.408131]  [<ffffffff812233c5>] ? sys_sendmsg+0x39/0x58
Oct 14 00:04:26 oko kernel: [ 2796.408134]  [<ffffffff812ec17b>] ? system_call_fastpath+0x16/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.408176] ---[ end trace 634279251cfb99d1 ]---
Oct 14 00:04:26 oko kernel: [ 2796.409026] ------------[ cut here ]------------
Oct 14 00:04:26 oko kernel: [ 2796.409046] WARNING: at /usr/src/linux-git/drivers/net/wireless/iwlwifi/iwl-agn-lib.c:1766 iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]()
Oct 14 00:04:26 oko kernel: [ 2796.409048] Hardware name: Vostro 3350
Oct 14 00:04:26 oko kernel: [ 2796.409049] invalid SMPS mode 0
Oct 14 00:04:26 oko kernel: [ 2796.409050] Modules linked in: acpi_cpufreq mperf cpufreq_conservative autofs4 rfcomm cpufreq_stats bnep cpufreq_powersave cpufreq_userspace pci_stub binfmt_misc microcode uinput nfs lockd auth_rpcgss nfs_acl sunrpc ext2 coretemp loop kvm_intel kvm aesni_intel cryptd aes_x86_64 aes_generic ecb btusb radeon bluetooth uvcvideo usb_storage videodev arc4 media uas iwlagn v4l2_compat_ioctl32 i915 crc16 snd_hda_codec_idt ttm drm_kms_helper mac80211 drm snd_hda_intel snd_hda_codec ehci_hcd snd_hwdep xhci_hcd snd_pcm snd_seq usbcore joydev sg cfg80211 snd_timer sr_mod snd_seq_device snd r8169 psmouse dell_wmi cdrom dell_laptop soundcore i2c_algo_bit pcspkr evdev sparse_keymap processor snd_page_alloc video cfbcopyarea mii dcdbas button cfbimgblt cfbfillrect wmi ac battery ext3 jbd mbcache dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod thermal thermal_sys [last unloaded: vboxdrv]
Oct 14 00:04:26 oko kernel: [ 2796.409109] Pid: 3017, comm: wpa_supplicant Tainted: G        W   3.1.0-rc9+ #12
Oct 14 00:04:26 oko kernel: [ 2796.409110] Call Trace:
Oct 14 00:04:26 oko kernel: [ 2796.409116]  [<ffffffff8103437f>] ? warn_slowpath_common+0x78/0x8c
Oct 14 00:04:26 oko kernel: [ 2796.409119]  [<ffffffff8103442b>] ? warn_slowpath_fmt+0x45/0x4a
Oct 14 00:04:26 oko kernel: [ 2796.409133]  [<ffffffffa03b78e7>] ? iwl_send_cmd+0x1a4/0x303 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409140]  [<ffffffffa03a93f1>] ? iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409145]  [<ffffffffa03a276d>] ? iwl_update_chain_flags+0x32/0x58 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409156]  [<ffffffffa03af7cd>] ? iwl_power_set_mode+0xf4/0x157 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409163]  [<ffffffffa03af9e0>] ? iwl_power_update_mode+0x1b0/0x1b9 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409170]  [<ffffffffa03b2cd8>] ? iwlagn_mac_config+0x206/0x287 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409185]  [<ffffffffa0319690>] ? ieee80211_mgd_deauth+0x19c/0x1c0 [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.409188]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.409201]  [<ffffffffa01ca76c>] ? __cfg80211_mlme_deauth+0x107/0x116 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409206]  [<ffffffff812e64d9>] ? schedule_hrtimeout_range_clock+0xc8/0x103
Oct 14 00:04:26 oko kernel: [ 2796.409208]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409216]  [<ffffffffa01ca7e4>] ? cfg80211_mlme_deauth+0x69/0x82 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409220]  [<ffffffff81023735>] ? __wake_up_common+0x40/0x77
Oct 14 00:04:26 oko kernel: [ 2796.409228]  [<ffffffffa01c15ed>] ? nl80211_deauthenticate+0xbc/0xc7 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409238]  [<ffffffffa01c35cb>] ? nl80211_pre_doit+0x85/0xfb [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409244]  [<ffffffff81250f71>] ? genl_rcv_msg+0x1cb/0x1f9
Oct 14 00:04:26 oko kernel: [ 2796.409246]  [<ffffffff81250da6>] ? genl_rcv+0x28/0x28
Oct 14 00:04:26 oko kernel: [ 2796.409249]  [<ffffffff81250a06>] ? netlink_rcv_skb+0x36/0x7a
Oct 14 00:04:26 oko kernel: [ 2796.409251]  [<ffffffff81250d9d>] ? genl_rcv+0x1f/0x28
Oct 14 00:04:26 oko kernel: [ 2796.409253]  [<ffffffff81250537>] ? netlink_unicast+0xe6/0x14e
Oct 14 00:04:26 oko kernel: [ 2796.409256]  [<ffffffff81250819>] ? netlink_sendmsg+0x27a/0x2b2
Oct 14 00:04:26 oko kernel: [ 2796.409262]  [<ffffffff810f45dc>] ? __pollwait+0xce/0xce
Oct 14 00:04:26 oko kernel: [ 2796.409266]  [<ffffffff8122172d>] ? sock_sendmsg+0xc1/0xde
Oct 14 00:04:26 oko kernel: [ 2796.409268]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.409271]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409273]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.409276]  [<ffffffff812228d4>] ? move_addr_to_kernel+0x24/0x46
Oct 14 00:04:26 oko kernel: [ 2796.409279]  [<ffffffff812219c5>] ? __sys_sendmsg+0x1e8/0x288
Oct 14 00:04:26 oko kernel: [ 2796.409282]  [<ffffffff812e9798>] ? add_preempt_count+0x9a/0x9c
Oct 14 00:04:26 oko kernel: [ 2796.409284]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409286]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.409289]  [<ffffffff812e6f14>] ? _raw_spin_unlock_irq+0x23/0x2f
Oct 14 00:04:26 oko kernel: [ 2796.409294]  [<ffffffff810022e1>] ? do_signal+0x51d/0x5f3
Oct 14 00:04:26 oko kernel: [ 2796.409297]  [<ffffffff81008f1b>] ? init_fpu+0x72/0x7f
Oct 14 00:04:26 oko kernel: [ 2796.409300]  [<ffffffff8100969f>] ? check_for_xstate+0x1c/0x6f
Oct 14 00:04:26 oko kernel: [ 2796.409303]  [<ffffffff81009966>] ? restore_i387_xstate+0x9e/0x17c
Oct 14 00:04:26 oko kernel: [ 2796.409305]  [<ffffffff81044e92>] ? do_sigaltstack+0xaa/0x13e
Oct 14 00:04:26 oko kernel: [ 2796.409308]  [<ffffffff812233c5>] ? sys_sendmsg+0x39/0x58
Oct 14 00:04:26 oko kernel: [ 2796.409312]  [<ffffffff812ec17b>] ? system_call_fastpath+0x16/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409314] ---[ end trace 634279251cfb99d2 ]---
Oct 14 00:04:26 oko kernel: [ 2796.409315] ------------[ cut here ]------------
Oct 14 00:04:26 oko kernel: [ 2796.409325] WARNING: at /usr/src/linux-git/drivers/net/wireless/iwlwifi/iwl-agn-lib.c:1766 iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]()
Oct 14 00:04:26 oko kernel: [ 2796.409327] Hardware name: Vostro 3350
Oct 14 00:04:26 oko kernel: [ 2796.409328] invalid SMPS mode 0
Oct 14 00:04:26 oko kernel: [ 2796.409329] Modules linked in: acpi_cpufreq mperf cpufreq_conservative autofs4 rfcomm cpufreq_stats bnep cpufreq_powersave cpufreq_userspace pci_stub binfmt_misc microcode uinput nfs lockd auth_rpcgss nfs_acl sunrpc ext2 coretemp loop kvm_intel kvm aesni_intel cryptd aes_x86_64 aes_generic ecb btusb radeon bluetooth uvcvideo usb_storage videodev arc4 media uas iwlagn v4l2_compat_ioctl32 i915 crc16 snd_hda_codec_idt ttm drm_kms_helper mac80211 drm snd_hda_intel snd_hda_codec ehci_hcd snd_hwdep xhci_hcd snd_pcm snd_seq usbcore joydev sg cfg80211 snd_timer sr_mod snd_seq_device snd r8169 psmouse dell_wmi cdrom dell_laptop soundcore i2c_algo_bit pcspkr evdev sparse_keymap processor snd_page_alloc video cfbcopyarea mii dcdbas button cfbimgblt cfbfillrect wmi ac battery ext3 jbd mbcache dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod thermal thermal_sys [last unloaded: vboxdrv]
Oct 14 00:04:26 oko kernel: [ 2796.409371] Pid: 3017, comm: wpa_supplicant Tainted: G        W   3.1.0-rc9+ #12
Oct 14 00:04:26 oko kernel: [ 2796.409372] Call Trace:
Oct 14 00:04:26 oko kernel: [ 2796.409381]  [<ffffffff8103437f>] ? warn_slowpath_common+0x78/0x8c
Oct 14 00:04:26 oko kernel: [ 2796.409384]  [<ffffffff8103442b>] ? warn_slowpath_fmt+0x45/0x4a
Oct 14 00:04:26 oko kernel: [ 2796.409392]  [<ffffffffa03b78e7>] ? iwl_send_cmd+0x1a4/0x303 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409399]  [<ffffffffa03a93f1>] ? iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409408]  [<ffffffffa03a276d>] ? iwl_update_chain_flags+0x32/0x58 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409415]  [<ffffffffa03af7cd>] ? iwl_power_set_mode+0xf4/0x157 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409421]  [<ffffffffa03af9e0>] ? iwl_power_update_mode+0x1b0/0x1b9 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409429]  [<ffffffffa03b2cd8>] ? iwlagn_mac_config+0x206/0x287 [iwlagn]
Oct 14 00:04:26 oko kernel: [ 2796.409439]  [<ffffffffa0319690>] ? ieee80211_mgd_deauth+0x19c/0x1c0 [mac80211]
Oct 14 00:04:26 oko kernel: [ 2796.409442]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.409457]  [<ffffffffa01ca76c>] ? __cfg80211_mlme_deauth+0x107/0x116 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409460]  [<ffffffff812e64d9>] ? schedule_hrtimeout_range_clock+0xc8/0x103
Oct 14 00:04:26 oko kernel: [ 2796.409463]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409477]  [<ffffffffa01ca7e4>] ? cfg80211_mlme_deauth+0x69/0x82 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409479]  [<ffffffff81023735>] ? __wake_up_common+0x40/0x77
Oct 14 00:04:26 oko kernel: [ 2796.409490]  [<ffffffffa01c15ed>] ? nl80211_deauthenticate+0xbc/0xc7 [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409498]  [<ffffffffa01c35cb>] ? nl80211_pre_doit+0x85/0xfb [cfg80211]
Oct 14 00:04:26 oko kernel: [ 2796.409502]  [<ffffffff81250f71>] ? genl_rcv_msg+0x1cb/0x1f9
Oct 14 00:04:26 oko kernel: [ 2796.409505]  [<ffffffff81250da6>] ? genl_rcv+0x28/0x28
Oct 14 00:04:26 oko kernel: [ 2796.409507]  [<ffffffff81250a06>] ? netlink_rcv_skb+0x36/0x7a
Oct 14 00:04:26 oko kernel: [ 2796.409509]  [<ffffffff81250d9d>] ? genl_rcv+0x1f/0x28
Oct 14 00:04:26 oko kernel: [ 2796.409511]  [<ffffffff81250537>] ? netlink_unicast+0xe6/0x14e
Oct 14 00:04:26 oko kernel: [ 2796.409514]  [<ffffffff81250819>] ? netlink_sendmsg+0x27a/0x2b2
Oct 14 00:04:26 oko kernel: [ 2796.409517]  [<ffffffff810f45dc>] ? __pollwait+0xce/0xce
Oct 14 00:04:26 oko kernel: [ 2796.409519]  [<ffffffff8122172d>] ? sock_sendmsg+0xc1/0xde
Oct 14 00:04:26 oko kernel: [ 2796.409521]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.409526]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409529]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:26 oko kernel: [ 2796.409532]  [<ffffffff812228d4>] ? move_addr_to_kernel+0x24/0x46
Oct 14 00:04:26 oko kernel: [ 2796.409534]  [<ffffffff812219c5>] ? __sys_sendmsg+0x1e8/0x288
Oct 14 00:04:26 oko kernel: [ 2796.409537]  [<ffffffff812e9798>] ? add_preempt_count+0x9a/0x9c
Oct 14 00:04:26 oko kernel: [ 2796.409539]  [<ffffffff8102c1e5>] ? get_parent_ip+0x9/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409542]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:26 oko kernel: [ 2796.409544]  [<ffffffff812e6f14>] ? _raw_spin_unlock_irq+0x23/0x2f
Oct 14 00:04:26 oko kernel: [ 2796.409548]  [<ffffffff810022e1>] ? do_signal+0x51d/0x5f3
Oct 14 00:04:26 oko kernel: [ 2796.409551]  [<ffffffff81008f1b>] ? init_fpu+0x72/0x7f
Oct 14 00:04:26 oko kernel: [ 2796.409554]  [<ffffffff8100969f>] ? check_for_xstate+0x1c/0x6f
Oct 14 00:04:26 oko kernel: [ 2796.409556]  [<ffffffff81009966>] ? restore_i387_xstate+0x9e/0x17c
Oct 14 00:04:26 oko kernel: [ 2796.409559]  [<ffffffff81044e92>] ? do_sigaltstack+0xaa/0x13e
Oct 14 00:04:26 oko kernel: [ 2796.409564]  [<ffffffff812233c5>] ? sys_sendmsg+0x39/0x58
Oct 14 00:04:26 oko kernel: [ 2796.409568]  [<ffffffff812ec17b>] ? system_call_fastpath+0x16/0x1b
Oct 14 00:04:26 oko kernel: [ 2796.409570] ---[ end trace 634279251cfb99d3 ]---
Oct 14 00:04:26 oko kernel: [ 2796.409586] cfg80211: Calling CRDA for country: PL
Oct 14 00:04:27 oko kernel: [ 2796.573759] ------------[ cut here ]------------
Oct 14 00:04:27 oko kernel: [ 2796.575276] WARNING: at /usr/src/linux-git/drivers/net/wireless/iwlwifi/iwl-agn-lib.c:1766 iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]()
Oct 14 00:04:27 oko kernel: [ 2796.576866] Hardware name: Vostro 3350
Oct 14 00:04:27 oko kernel: [ 2796.578449] invalid SMPS mode 0
Oct 14 00:04:27 oko kernel: [ 2796.578488] Modules linked in: acpi_cpufreq mperf cpufreq_conservative autofs4 rfcomm cpufreq_stats bnep cpufreq_powersave cpufreq_userspace pci_stub binfmt_misc microcode uinput nfs lockd auth_rpcgss nfs_acl sunrpc ext2 coretemp loop kvm_intel kvm aesni_intel cryptd aes_x86_64 aes_generic ecb btusb radeon bluetooth uvcvideo usb_storage videodev arc4 media uas iwlagn v4l2_compat_ioctl32 i915 crc16 snd_hda_codec_idt ttm drm_kms_helper mac80211 drm snd_hda_intel snd_hda_codec ehci_hcd snd_hwdep xhci_hcd snd_pcm snd_seq usbcore joydev sg cfg80211 snd_timer sr_mod snd_seq_device snd r8169 psmouse dell_wmi cdrom dell_laptop soundcore i2c_algo_bit pcspkr evdev sparse_keymap processor snd_page_alloc video cfbcopyarea mii dcdbas button cfbimgblt cfbfillrect wmi ac battery ext3 jbd mbcache dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod thermal thermal_sys [last unloaded: vboxdrv]
Oct 14 00:04:27 oko kernel: [ 2796.591110] Pid: 2973, comm: NetworkManager Tainted: G        W   3.1.0-rc9+ #12
Oct 14 00:04:27 oko kernel: [ 2796.592295] Call Trace:
Oct 14 00:04:27 oko kernel: [ 2796.593474]  [<ffffffff8103437f>] ? warn_slowpath_common+0x78/0x8c
Oct 14 00:04:27 oko kernel: [ 2796.594693]  [<ffffffff8103442b>] ? warn_slowpath_fmt+0x45/0x4a
Oct 14 00:04:27 oko kernel: [ 2796.595910]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:27 oko kernel: [ 2796.597087]  [<ffffffffa03a93f1>] ? iwlagn_set_rxon_chain+0x107/0x1b2 [iwlagn]
Oct 14 00:04:27 oko kernel: [ 2796.598296]  [<ffffffff812e6f14>] ? _raw_spin_unlock_irq+0x23/0x2f
Oct 14 00:04:27 oko kernel: [ 2796.599507]  [<ffffffffa03adc8c>] ? iwl_teardown_interface+0x4a/0x7e [iwlagn]
Oct 14 00:04:27 oko kernel: [ 2796.600697]  [<ffffffffa03ae569>] ? iwl_mac_remove_interface+0x4e/0x5e [iwlagn]
Oct 14 00:04:27 oko kernel: [ 2796.601914]  [<ffffffffa031c3f3>] ? ieee80211_do_stop+0x314/0x465 [mac80211]
Oct 14 00:04:27 oko kernel: [ 2796.603133]  [<ffffffff81039618>] ? _local_bh_enable_ip.isra.12+0x94/0xa2
Oct 14 00:04:27 oko kernel: [ 2796.604328]  [<ffffffffa031c557>] ? ieee80211_stop+0x13/0x17 [mac80211]
Oct 14 00:04:27 oko kernel: [ 2796.605523]  [<ffffffff8122f754>] ? __dev_close_many+0x7f/0xab
Oct 14 00:04:27 oko kernel: [ 2796.606752]  [<ffffffff8122f7b0>] ? __dev_close+0x30/0x47
Oct 14 00:04:27 oko kernel: [ 2796.607981]  [<ffffffff812e96ed>] ? sub_preempt_count+0x83/0x94
Oct 14 00:04:27 oko kernel: [ 2796.609179]  [<ffffffff81233e6a>] ? __dev_change_flags+0x9d/0x118
Oct 14 00:04:27 oko kernel: [ 2796.610406]  [<ffffffff81233f4b>] ? dev_change_flags+0x12/0x42
Oct 14 00:04:27 oko kernel: [ 2796.611639]  [<ffffffff8123da18>] ? do_setlink+0x287/0x6f8
Oct 14 00:04:27 oko kernel: [ 2796.612848]  [<ffffffff810da6a2>] ? __kmalloc_node_track_caller+0xcb/0x105
Oct 14 00:04:27 oko kernel: [ 2796.614089]  [<ffffffff812263ef>] ? sock_rmalloc+0x2b/0x4b
Oct 14 00:04:27 oko kernel: [ 2796.615338]  [<ffffffff8123e20a>] ? __rtnl_unlock+0xc/0xc
Oct 14 00:04:27 oko kernel: [ 2796.616549]  [<ffffffff8123e0d2>] ? rtnl_setlink+0xc4/0xe6
Oct 14 00:04:27 oko kernel: [ 2796.617799]  [<ffffffff81250a06>] ? netlink_rcv_skb+0x36/0x7a
Oct 14 00:04:27 oko kernel: [ 2796.619042]  [<ffffffff8123d64d>] ? rtnetlink_rcv+0x1f/0x28
Oct 14 00:04:27 oko kernel: [ 2796.620261]  [<ffffffff81250537>] ? netlink_unicast+0xe6/0x14e
Oct 14 00:04:27 oko kernel: [ 2796.621476]  [<ffffffff81250819>] ? netlink_sendmsg+0x27a/0x2b2
Oct 14 00:04:27 oko kernel: [ 2796.622718]  [<ffffffff8122172d>] ? sock_sendmsg+0xc1/0xde
Oct 14 00:04:27 oko kernel: [ 2796.623961]  [<ffffffff8122160e>] ? sock_recvmsg+0xcd/0xec
Oct 14 00:04:27 oko kernel: [ 2796.625173]  [<ffffffff8122172d>] ? sock_sendmsg+0xc1/0xde
Oct 14 00:04:27 oko kernel: [ 2796.626407]  [<ffffffff8116d88c>] ? cpumask_any_but+0x24/0x34
Oct 14 00:04:27 oko kernel: [ 2796.627641]  [<ffffffff812228d4>] ? move_addr_to_kernel+0x24/0x46
Oct 14 00:04:27 oko kernel: [ 2796.628853]  [<ffffffff812219c5>] ? __sys_sendmsg+0x1e8/0x288
Oct 14 00:04:27 oko kernel: [ 2796.630089]  [<ffffffff812df81a>] ? __bad_area_nosemaphore+0x87/0x1f0
Oct 14 00:04:27 oko kernel: [ 2796.631335]  [<ffffffff810e79c6>] ? fget_light+0x85/0x8d
Oct 14 00:04:27 oko kernel: [ 2796.632537]  [<ffffffff812230a0>] ? sys_sendto+0x108/0x137
Oct 14 00:04:27 oko kernel: [ 2796.633768]  [<ffffffff810f6c44>] ? dput+0xe6/0xf3
Oct 14 00:04:27 oko kernel: [ 2796.634992]  [<ffffffff812233c5>] ? sys_sendmsg+0x39/0x58
Oct 14 00:04:27 oko kernel: [ 2796.636194]  [<ffffffff812ec17b>] ? system_call_fastpath+0x16/0x1b
Oct 14 00:04:27 oko kernel: [ 2796.637398] ---[ end trace 634279251cfb99d4 ]---

^ permalink raw reply

* Re: [PATCH] libertas: fix changing interface type when interface is down
From: Dan Williams @ 2011-10-14 15:00 UTC (permalink / raw)
  To: Daniel Drake; +Cc: linville, linux-wireless, libertas-dev
In-Reply-To: <20111014110526.74BCC9D401E@zog.reactivated.net>

On Fri, 2011-10-14 at 12:05 +0100, Daniel Drake wrote:
> The recent changes to only power the device when the interface up
> introduced a bug: changing interface type, legal when the interface
> is down, performs device I/O.
> 
> Fix this functionality by validating and recording the interface
> type when the change is requested, but only applying the change
> if/when the interface is brought up.
> 
> Signed-off-by: Daniel Drake <dsd@laptop.org>

Acked-by: Dan Williams <dcbw@redhat.com>

> ---
>  drivers/net/wireless/libertas/cfg.c  |   20 ++++++--------------
>  drivers/net/wireless/libertas/decl.h |    2 ++
>  drivers/net/wireless/libertas/main.c |   32 ++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
> index 610bfce..ff63782 100644
> --- a/drivers/net/wireless/libertas/cfg.c
> +++ b/drivers/net/wireless/libertas/cfg.c
> @@ -1666,28 +1666,20 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
>  	if (dev == priv->mesh_dev)
>  		return -EOPNOTSUPP;
>  
> -	lbs_deb_enter(LBS_DEB_CFG80211);
> -
>  	switch (type) {
>  	case NL80211_IFTYPE_MONITOR:
> -		ret = lbs_set_monitor_mode(priv, 1);
> -		break;
>  	case NL80211_IFTYPE_STATION:
> -		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
> -			ret = lbs_set_monitor_mode(priv, 0);
> -		if (!ret)
> -			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
> -		break;
>  	case NL80211_IFTYPE_ADHOC:
> -		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
> -			ret = lbs_set_monitor_mode(priv, 0);
> -		if (!ret)
> -			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
>  		break;
>  	default:
> -		ret = -ENOTSUPP;
> +		return -EOPNOTSUPP;
>  	}
>  
> +	lbs_deb_enter(LBS_DEB_CFG80211);
> +
> +	if (priv->iface_running)
> +		ret = lbs_set_iface_type(priv, type);
> +
>  	if (!ret)
>  		priv->wdev->iftype = type;
>  
> diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
> index 9304e6f..bc951ab 100644
> --- a/drivers/net/wireless/libertas/decl.h
> +++ b/drivers/net/wireless/libertas/decl.h
> @@ -9,6 +9,7 @@
>  
>  #include <linux/netdevice.h>
>  #include <linux/firmware.h>
> +#include <linux/nl80211.h>
>  
>  /* Should be terminated by a NULL entry */
>  struct lbs_fw_table {
> @@ -45,6 +46,7 @@ void lbs_host_to_card_done(struct lbs_private *priv);
>  
>  int lbs_start_iface(struct lbs_private *priv);
>  int lbs_stop_iface(struct lbs_private *priv);
> +int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type);
>  
>  int lbs_rtap_supported(struct lbs_private *priv);
>  
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 6a32623..f78afd7 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -99,6 +99,32 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
>  	return 0;
>  }
>  
> +int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type)
> +{
> +	int ret = 0;
> +
> +	switch (type) {
> +	case NL80211_IFTYPE_MONITOR:
> +		ret = lbs_set_monitor_mode(priv, 1);
> +		break;
> +	case NL80211_IFTYPE_STATION:
> +		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
> +			ret = lbs_set_monitor_mode(priv, 0);
> +		if (!ret)
> +			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
> +		break;
> +	case NL80211_IFTYPE_ADHOC:
> +		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
> +			ret = lbs_set_monitor_mode(priv, 0);
> +		if (!ret)
> +			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
> +		break;
> +	default:
> +		ret = -ENOTSUPP;
> +	}
> +	return ret;
> +}
> +
>  int lbs_start_iface(struct lbs_private *priv)
>  {
>  	struct cmd_ds_802_11_mac_address cmd;
> @@ -120,6 +146,12 @@ int lbs_start_iface(struct lbs_private *priv)
>  		goto err;
>  	}
>  
> +	ret = lbs_set_iface_type(priv, priv->wdev->iftype);
> +	if (ret) {
> +		lbs_deb_net("set iface type failed\n");
> +		goto err;
> +	}
> +
>  	lbs_update_channel(priv);
>  
>  	priv->iface_running = true;



^ permalink raw reply

* Re: How to create library module with callbacks?
From: Arend van Spriel @ 2011-10-14 14:43 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <CACna6ryphLSrh5vtOEDXek7s9DGxWKSSgQB-KJVLyzfmBCP3KA@mail.gmail.com>

On 10/14/2011 03:21 PM, Rafał Miłecki wrote:
> I want to create module library, which will handle PHY operations on
> Broadcom card. For most of the time, I'm going to call library
> functions from b43.
> 
> However, there are places where I need to call some (b43) driver
> function from library module.
> 
> How can I handle that? Should I pass some functions pointers to the
> library? Is that going to work? Or is there a better approach?
> 
> P.S.
> I'm asking at linux-wireless, it's not wireless related however. I
> think question is quite simple for C hackers and there is no need to
> hit LKML.
> 

Hi Rafał,

It should be no different as normal drivers do. In your case I would say
b43 registers itself with phylib module and provides phylib_ops. It
could also provide the bcma_device for the 80211 core so the phylib can
use bcma directly. Whether or not phylib is still a library module when
doing so can be argued. As it does not provide a system function by
itself I tend to say it is.

I would suggest to look into mac80211 to see how it deals with the
callbacks it does into the device drivers.

Gr. AvS


^ permalink raw reply

* Re: How to create library module with callbacks?
From: Pavel Roskin @ 2011-10-14 14:42 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linux-wireless
In-Reply-To: <CACna6ryphLSrh5vtOEDXek7s9DGxWKSSgQB-KJVLyzfmBCP3KA@mail.gmail.com>

On Fri, 14 Oct 2011 15:21:16 +0200
Rafał Miłecki <zajec5@gmail.com> wrote:

> I want to create module library, which will handle PHY operations on
> Broadcom card. For most of the time, I'm going to call library
> functions from b43.
> 
> However, there are places where I need to call some (b43) driver
> function from library module.
> 
> How can I handle that? Should I pass some functions pointers to the
> library? Is that going to work? Or is there a better approach?

Yes, that should work.  All modules and the kernel live in the same
address space.  But you should make sure that those pointers won't be
used if the calling module is unloaded.

In fact, b43 does it already with mac80211, ssb and bcma.  See
b43_hw_ops, b43_ssb_driver and b43_bcma_driver in the code.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* How to create library module with callbacks?
From: Rafał Miłecki @ 2011-10-14 13:21 UTC (permalink / raw)
  To: linux-wireless

I want to create module library, which will handle PHY operations on
Broadcom card. For most of the time, I'm going to call library
functions from b43.

However, there are places where I need to call some (b43) driver
function from library module.

How can I handle that? Should I pass some functions pointers to the
library? Is that going to work? Or is there a better approach?

P.S.
I'm asking at linux-wireless, it's not wireless related however. I
think question is quite simple for C hackers and there is no need to
hit LKML.

-- 
Rafał

^ permalink raw reply

* [PATCH 3/5] ath6kl: Add SDIO polling method into menu
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee
In-Reply-To: <1318596646-19495-1-git-send-email-sangwook.lee@linaro.org>

At the initial developement stage, sometimes we need SDIO polling
method due to SDIO Interrupt problems. This patch adds selection
option into kernel menu

Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
---
 drivers/net/wireless/ath/ath6kl/Kconfig |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index 3d5f8be..7e530b8 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -13,3 +13,11 @@ config ATH6KL_DEBUG
 	depends on ATH6KL
 	---help---
 	  Enables debug support
+
+config ATH6KL_SDIO_POLL
+        bool "Atheros ath6kl debugging with SDIO polling"
+        depends on ATH6KL
+        ---help---
+          Enables SDIO polling for debugging when SDIO's probem
+          happens. This is tested only with HW2.0. By default
+          polling time interval is 10ms
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 4/5] ath6kl: Add SDIO polling file into Makefile
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee
In-Reply-To: <1318596646-19495-1-git-send-email-sangwook.lee@linaro.org>

Add new file into Makefile

Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
---
 drivers/net/wireless/ath/ath6kl/Makefile |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8f7a0d1..a8f4a55 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -32,6 +32,7 @@ ath6kl-y += main.o
 ath6kl-y += txrx.o
 ath6kl-y += wmi.o
 ath6kl-y += sdio.o
+ath6kl-$(CONFIG_ATH6KL_SDIO_POLL) += sdio_poll.o
 ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
 
 ccflags-y += -D__CHECK_ENDIAN__
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 1/5] ath6kl: Add SDIO polling function definitions
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee
In-Reply-To: <1318596646-19495-1-git-send-email-sangwook.lee@linaro.org>

Add SDIO polling function definition into debug.h

Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
---
 drivers/net/wireless/ath/ath6kl/debug.h |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 9288a3c..bbe4a39 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -133,6 +133,31 @@ static inline int ath6kl_debug_init(struct ath6kl *ar)
 static inline void ath6kl_debug_cleanup(struct ath6kl *ar)
 {
 }
+#endif
+
+#ifdef CONFIG_ATH6KL_SDIO_POLL
+void ath6kl_wd_init(struct ath6kl *ar);
+
+void ath6kl_wd_cleanup(struct ath6kl *ar);
+
+static inline int ath6kl_wd_poll_is_ture(void)
+{
+	return true;
+}
+
+#else
+static inline void ath6kl_wd_init(struct ath6kl *ar)
+{
+}
+
+static inline void ath6kl_wd_cleanup(struct ath6kl *ar)
+{
+}
+
+static inline int ath6kl_wd_poll_is_ture(void)
+{
+	return false;
+}
 
 #endif
 #endif
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 5/5] ath6kl: Add SDIO polling function
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee
In-Reply-To: <1318596646-19495-1-git-send-email-sangwook.lee@linaro.org>

SDIO polling fuctions exsits on the separate file. This can be
deseleted in Makefile according to menu configuration

Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
---
 drivers/net/wireless/ath/ath6kl/sdio_poll.c |  216 +++++++++++++++++++++++++++
 1 files changed, 216 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath6kl/sdio_poll.c

diff --git a/drivers/net/wireless/ath/ath6kl/sdio_poll.c b/drivers/net/wireless/ath/ath6kl/sdio_poll.c
new file mode 100644
index 0000000..ce2f127
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/sdio_poll.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2011 Linaro
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/kthread.h>
+#include "core.h"
+#include "cfg80211.h"
+#include "target.h"
+#include "debug.h"
+#include "hif-ops.h"
+
+/* This structure is duplicated used in sdio.c */
+struct ath6kl_sdio {
+
+	struct sdio_func *func;
+
+	spinlock_t lock;
+
+	/* free list */
+	struct list_head bus_req_freeq;
+
+	/* available bus requests */
+	struct bus_request bus_req[BUS_REQUEST_MAX_NUM];
+
+	struct ath6kl *ar;
+	u8 *dma_buffer;
+
+	/* scatter request list head */
+	struct list_head scat_req;
+
+	spinlock_t scat_lock;
+	bool is_disabled;
+	atomic_t irq_handling;
+	const struct sdio_device_id *id;
+	struct work_struct wr_async_work;
+	struct list_head wr_asyncq;
+	spinlock_t wr_async_lock;
+};
+
+/* Use polling method of SDIO interrupt */
+struct ath6kl_poll {
+	/* Watchdog task struct */
+	struct task_struct *wd_ts;
+	/* watchdog sempahore */
+	struct semaphore wd_sem;
+	struct completion wd_exited;
+	/* Wathdog wake up timer */
+	struct timer_list wd_timer;
+	bool wd_timer_valid;
+	/* polling time ms */
+	int wd_ms;
+};
+
+/*Later, this can become a member of struct ath6kl */
+static struct ath6kl_poll *ap_g;
+
+static void ath6kl_wd_poll_handler(struct ath6kl *ar)
+{
+	int status;
+	struct ath6kl_sdio *ar_sdio;
+
+	/* Wait for htc_target to be created
+	 * because wd_init is called
+	 * beforeath6kl_core_init
+	 */
+	if (!ar->htc_target)
+		return;
+
+	ar_sdio = (struct ath6kl_sdio *)ar->hif_priv;
+	ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
+	atomic_set(&ar_sdio->irq_handling, 1);
+	status = ath6kldev_intr_bh_handler(ar);
+	atomic_set(&ar_sdio->irq_handling, 0);
+	WARN_ON(status && status != -ECANCELED);
+}
+
+/* Update watchdog time */
+static inline void ath6kl_wd_update_time(struct ath6kl_poll *ap)
+{
+	if (ap->wd_timer_valid)
+		mod_timer(&ap->wd_timer, jiffies + msecs_to_jiffies(ap->wd_ms));
+}
+
+static void ath6kl_wd_func(ulong data)
+{
+	struct ath6kl_poll *ap = (struct ath6kl_poll *)data;
+
+	if (!ap->wd_timer_valid) {
+		del_timer_sync(&ap->wd_timer);
+		return;
+	}
+	/* Wake up sleeping watchdog thread */
+	if (ap->wd_timer_valid)
+		up(&ap->wd_sem);
+
+	/* Reschedule the watchdog */
+	ath6kl_wd_update_time(ap);
+}
+
+static int ath6kl_wd_thread(void *data)
+{
+	struct ath6kl *ar = (struct ath6kl *)data;
+	struct ath6kl_poll *ap = ap_g;
+	struct sched_param param = {.sched_priority = 1 };
+
+	sched_setscheduler(current, SCHED_FIFO, &param);
+	allow_signal(SIGKILL);
+	allow_signal(SIGTERM);
+
+	/* Run until signal received */
+	do {
+		if (down_interruptible(&ap->wd_sem) == 0) {
+			/* Call the bus module watchdog */
+			ath6kl_wd_poll_handler(ar);
+			/* Reschedule the watchdog */
+			ath6kl_wd_update_time(ap);
+		} else {
+			break;
+		}
+	} while (!kthread_should_stop());
+
+	complete_and_exit(&ap->wd_exited, 0);
+
+	return 0;
+}
+
+/**
+ * ath6kl_wd_init -init watchdog poll for ath6kl
+ *
+ * must be called after ath6kl_htc_create because SDIO host
+ * irq must be disabled
+ */
+void ath6kl_wd_init(struct ath6kl *ar)
+{
+	struct ath6kl_poll *ap;
+	struct timer_list *timer;
+
+	ap = kzalloc(sizeof(struct ath6kl_poll), GFP_KERNEL);
+
+	/* For ath6kl_wd_cleanup */
+	ap_g = ap;
+
+	if (!ap) {
+		ath6kl_err("failed to alloc memory\n");
+		return;
+	}
+
+	/* Congfigure polling time */
+	ap->wd_timer_valid = true;
+	/* Please change this polling time : 10 ms by default */
+	ap->wd_ms = 10;
+
+	sema_init(&ap->wd_sem, 1);
+	init_completion(&ap->wd_exited);
+
+	ap->wd_ts = kthread_run(ath6kl_wd_thread, (void *)ar, "ath6kl_wd");
+	if (IS_ERR(ap->wd_ts)) {
+		ap->wd_timer_valid = false;
+		del_timer_sync(&ap->wd_timer);
+		ath6kl_err("failed to make ath6k_wd\n");
+		kfree(ap);
+		ap_g = NULL;
+		return;
+	}
+
+	/* Set up the watchdog timer */
+	timer = &ap->wd_timer;
+	init_timer(timer);
+	timer->function = ath6kl_wd_func;
+	timer->data = (ulong) ap;
+	/* Run timer now at first */
+	timer->expires = jiffies + msecs_to_jiffies(1);
+	add_timer(timer);
+
+}
+
+void ath6kl_wd_cleanup(struct ath6kl *ar)
+{
+	struct ath6kl_poll *ap = ap_g;
+
+	/* Check validity */
+	if (!ap || !ap->wd_timer_valid)
+		return;
+
+	ap->wd_ms = 0;
+	del_timer_sync(&ap->wd_timer);
+	ap->wd_timer_valid = false;
+
+	/* Wake up thread sleeping on wd_sem */
+	send_sig(SIGTERM, ap->wd_ts, 1);
+
+	wait_for_completion(&ap->wd_exited);
+
+	/* Kill watchdog thread */
+	kthread_stop(ap->wd_ts);
+
+	kfree(ap);
+}
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 2/5] ath6kl: Add SDIO polling function hook into SDIO init time
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee
In-Reply-To: <1318596646-19495-1-git-send-email-sangwook.lee@linaro.org>

Add SDIO polling function into SDIO related file

Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
---
 drivers/net/wireless/ath/ath6kl/sdio.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index f48af45..f3520d9 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -447,6 +447,9 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
 	int status;
 	struct ath6kl_sdio *ar_sdio;
 
+	if (ath6kl_wd_poll_is_ture())
+		return;
+
 	ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
 
 	ar_sdio = sdio_get_drvdata(func);
@@ -858,6 +861,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
 
 	sdio_release_host(func);
 
+	ath6kl_wd_init(ar);
+
 	ret = ath6kl_core_init(ar);
 	if (ret) {
 		ath6kl_err("Failed to init ath6kl core\n");
@@ -891,6 +896,8 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
 	ath6kl_stop_txrx(ar_sdio->ar);
 	cancel_work_sync(&ar_sdio->wr_async_work);
 
+	ath6kl_wd_cleanup(ar_sdio->ar);
+
 	ath6kl_unavail_ev(ar_sdio->ar);
 
 	ath6kl_sdio_power_off(ar_sdio);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 0/5] ath6kl: Add SDIO polling method for debugging
From: Sangwook Lee @ 2011-10-14 12:50 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, patches, Sangwook Lee

Add SDIO polling method based user defined intevals
At initial development stage, when SDIO irqs problem happen,
We can use this funtionality for debugging.
This is only tested with AR6003 HW2.0

Sangwook Lee (5):
  ath6kl: Add SDIO polling function definitions
  ath6kl: Add SDIO polling function hook into SDIO init time
  ath6kl: Add SDIO polling method into menu
  ath6kl: Add SDIO polling file into Makefile
  ath6kl: Add SDIO polling function

 drivers/net/wireless/ath/ath6kl/Kconfig     |    8 +
 drivers/net/wireless/ath/ath6kl/Makefile    |    1 +
 drivers/net/wireless/ath/ath6kl/debug.h     |   25 +++
 drivers/net/wireless/ath/ath6kl/sdio.c      |    7 +
 drivers/net/wireless/ath/ath6kl/sdio_poll.c |  216 +++++++++++++++++++++++++++
 5 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath6kl/sdio_poll.c

-- 
1.7.4.1


^ permalink raw reply

* [PATCH] libertas: fix changing interface type when interface is down
From: Daniel Drake @ 2011-10-14 11:05 UTC (permalink / raw)
  To: linville, dcbw; +Cc: linux-wireless, libertas-dev

The recent changes to only power the device when the interface up
introduced a bug: changing interface type, legal when the interface
is down, performs device I/O.

Fix this functionality by validating and recording the interface
type when the change is requested, but only applying the change
if/when the interface is brought up.

Signed-off-by: Daniel Drake <dsd@laptop.org>
---
 drivers/net/wireless/libertas/cfg.c  |   20 ++++++--------------
 drivers/net/wireless/libertas/decl.h |    2 ++
 drivers/net/wireless/libertas/main.c |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 610bfce..ff63782 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1666,28 +1666,20 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
 	if (dev == priv->mesh_dev)
 		return -EOPNOTSUPP;
 
-	lbs_deb_enter(LBS_DEB_CFG80211);
-
 	switch (type) {
 	case NL80211_IFTYPE_MONITOR:
-		ret = lbs_set_monitor_mode(priv, 1);
-		break;
 	case NL80211_IFTYPE_STATION:
-		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
-			ret = lbs_set_monitor_mode(priv, 0);
-		if (!ret)
-			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
-		break;
 	case NL80211_IFTYPE_ADHOC:
-		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
-			ret = lbs_set_monitor_mode(priv, 0);
-		if (!ret)
-			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
 		break;
 	default:
-		ret = -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
+	lbs_deb_enter(LBS_DEB_CFG80211);
+
+	if (priv->iface_running)
+		ret = lbs_set_iface_type(priv, type);
+
 	if (!ret)
 		priv->wdev->iftype = type;
 
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 9304e6f..bc951ab 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -9,6 +9,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/firmware.h>
+#include <linux/nl80211.h>
 
 /* Should be terminated by a NULL entry */
 struct lbs_fw_table {
@@ -45,6 +46,7 @@ void lbs_host_to_card_done(struct lbs_private *priv);
 
 int lbs_start_iface(struct lbs_private *priv);
 int lbs_stop_iface(struct lbs_private *priv);
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type);
 
 int lbs_rtap_supported(struct lbs_private *priv);
 
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 6a32623..f78afd7 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -99,6 +99,32 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
 	return 0;
 }
 
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type)
+{
+	int ret = 0;
+
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+		ret = lbs_set_monitor_mode(priv, 1);
+		break;
+	case NL80211_IFTYPE_STATION:
+		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+			ret = lbs_set_monitor_mode(priv, 0);
+		if (!ret)
+			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+			ret = lbs_set_monitor_mode(priv, 0);
+		if (!ret)
+			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
+		break;
+	default:
+		ret = -ENOTSUPP;
+	}
+	return ret;
+}
+
 int lbs_start_iface(struct lbs_private *priv)
 {
 	struct cmd_ds_802_11_mac_address cmd;
@@ -120,6 +146,12 @@ int lbs_start_iface(struct lbs_private *priv)
 		goto err;
 	}
 
+	ret = lbs_set_iface_type(priv, priv->wdev->iftype);
+	if (ret) {
+		lbs_deb_net("set iface type failed\n");
+		goto err;
+	}
+
 	lbs_update_channel(priv);
 
 	priv->iface_running = true;
-- 
1.7.6.4


^ permalink raw reply related

* Re: [PATCH v2] mac80211: pass vif param to conf_tx() callback
From: Eliad Peller @ 2011-10-14  9:54 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1318433496.3933.44.camel@jlt3.sipsolutions.net>

On Wed, Oct 12, 2011 at 5:31 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Sun, 2011-10-02 at 10:15 +0200, Eliad Peller wrote:
>> tx params should be configured per interface.
>> add ieee80211_vif param to the conf_tx callback,
>> and change all the drivers that use this callback.
>
> For the record, I said this to you on IRC but you weren't around I
> guess. This patch (with the other ones) is now passing a bogus sdata/vif
> pointer to drivers -- e.g. for monitor mode interfaces from
> ieee80211_do_open -> ieee80211_set_wmm_default -> drv_conf_tx.
>
> I suspect the way to fix this would be to move the call to
> ieee80211_set_wmm_default into the last switch statement in do_open,
> could you please look into it?
>
thanks for the info.
i'll look into it.

Eliad.

^ 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