Linux wireless drivers development
 help / color / mirror / Atom feed
* [RFC PATCH 08/10] rndis_wlan: convert mic failure wireless event to cfg80211
From: Jussi Kivilinna @ 2009-08-28 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   32 +++++++++++++++++---------------
 1 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 6919c54..01cd341 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2720,9 +2720,10 @@ static void rndis_wlan_auth_indication(struct usbnet *usbdev,
 {
 	u8 *buf;
 	const char *type;
-	int flags, buflen;
+	int flags, buflen, key_id;
 	bool pairwise_error, group_error;
 	struct ndis_80211_auth_request *auth_req;
+	enum nl80211_key_type key_type;
 
 	/* must have at least one array entry */
 	if (len < offsetof(struct ndis_80211_status_indication, u) +
@@ -2758,23 +2759,24 @@ static void rndis_wlan_auth_indication(struct usbnet *usbdev,
 		devinfo(usbdev, "authentication indication: %s (0x%08x)", type,
 				le32_to_cpu(auth_req->flags));
 
-		if (pairwise_error || group_error) {
-			union iwreq_data wrqu;
-			struct iw_michaelmicfailure micfailure;
+		if (pairwise_error) {
+			key_type = NL80211_KEYTYPE_PAIRWISE;
+			key_id = -1;
 
-			memset(&micfailure, 0, sizeof(micfailure));
-			if (pairwise_error)
-				micfailure.flags |= IW_MICFAILURE_PAIRWISE;
-			if (group_error)
-				micfailure.flags |= IW_MICFAILURE_GROUP;
+			cfg80211_michael_mic_failure(usbdev->net,
+							auth_req->bssid,
+							key_type, key_id, NULL,
+							GFP_KERNEL);
+		}
 
-			memcpy(micfailure.src_addr.sa_data, auth_req->bssid,
-				ETH_ALEN);
+		if (group_error) {
+			key_type = NL80211_KEYTYPE_GROUP;
+			key_id = -1;
 
-			memset(&wrqu, 0, sizeof(wrqu));
-			wrqu.data.length = sizeof(micfailure);
-			wireless_send_event(usbdev->net, IWEVMICHAELMICFAILURE,
-						&wrqu, (u8 *)&micfailure);
+			cfg80211_michael_mic_failure(usbdev->net,
+							auth_req->bssid,
+							key_type, key_id, NULL,
+							GFP_KERNEL);
 		}
 
 		buflen -= le32_to_cpu(auth_req->length);


^ permalink raw reply related

* [RFC PATCH 07/10] rndis_wlan: remove unneeded SIOCSIWCOMMIT
From: Jussi Kivilinna @ 2009-08-28 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 919b268..6919c54 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2179,13 +2179,6 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
  * wireless extension handlers
  */
 
-static int rndis_iw_commit(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	/* dummy op */
-	return 0;
-}
-
 #if 0
 /* Commented code out instead of removing to have more sane patch for review.
  * Will be removed later in the set.
@@ -2558,7 +2551,6 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
 #define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
 static const iw_handler rndis_iw_handler[] =
 {
-	IW_IOCTL(SIOCSIWCOMMIT)    = rndis_iw_commit,
 	IW_IOCTL(SIOCGIWNAME)      = (iw_handler) cfg80211_wext_giwname,
 	IW_IOCTL(SIOCSIWFREQ)      = (iw_handler) cfg80211_wext_siwfreq,
 	IW_IOCTL(SIOCGIWFREQ)      = (iw_handler) cfg80211_wext_giwfreq,


^ permalink raw reply related

* [RFC PATCH 06/10] rndis_wlan: rename wireless stats worker to device poller
From: Jussi Kivilinna @ 2009-08-28 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Stats worker no longer poll stats from device anymore. It's still
needed to poll device control channel for connect/disconnect events,
so rename stats worker as device poller.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   36 +++++++++++++++++++-----------------
 1 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index ac873d0..919b268 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -440,7 +440,7 @@ struct rndis_wlan_private {
 	struct cfg80211_scan_request *scan_request;
 
 	struct workqueue_struct *workqueue;
-	struct delayed_work stats_work;
+	struct delayed_work dev_poller_work;
 	struct delayed_work scan_work;
 	struct work_struct work;
 	struct mutex command_lock;
@@ -2984,15 +2984,16 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev)
 }
 
 
-#define STATS_UPDATE_JIFFIES (HZ)
-static void rndis_update_wireless_stats(struct work_struct *work)
+#define DEVICE_POLLER_JIFFIES (HZ)
+static void rndis_device_poller(struct work_struct *work)
 {
 	struct rndis_wlan_private *priv =
-		container_of(work, struct rndis_wlan_private, stats_work.work);
+		container_of(work, struct rndis_wlan_private,
+							dev_poller_work.work);
 	struct usbnet *usbdev = priv->usbdev;
 	__le32 rssi, tmp;
 	int len, ret, j;
-	int update_jiffies = STATS_UPDATE_JIFFIES;
+	int update_jiffies = DEVICE_POLLER_JIFFIES;
 	void *buf;
 
 	/* Only check/do workaround when connected. Calling is_associated()
@@ -3007,8 +3008,8 @@ static void rndis_update_wireless_stats(struct work_struct *work)
 	if (ret == 0)
 		priv->last_qual = level_to_qual(le32_to_cpu(rssi));
 
-	devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret,
-							le32_to_cpu(rssi));
+	devdbg(usbdev, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d",
+		ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi)));
 
 	/* Workaround transfer stalls on poor quality links.
 	 * TODO: find right way to fix these stalls (as stalls do not happen
@@ -3019,8 +3020,8 @@ static void rndis_update_wireless_stats(struct work_struct *work)
 		 * Slower doesn't catch stalls fast enough.
 		 */
 		j = msecs_to_jiffies(priv->param_workaround_interval);
-		if (j > STATS_UPDATE_JIFFIES)
-			j = STATS_UPDATE_JIFFIES;
+		if (j > DEVICE_POLLER_JIFFIES)
+			j = DEVICE_POLLER_JIFFIES;
 		else if (j <= 0)
 			j = 1;
 		update_jiffies = j;
@@ -3040,8 +3041,8 @@ static void rndis_update_wireless_stats(struct work_struct *work)
 		rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
 		kfree(buf);
 	}
-end:
 
+end:
 	if (update_jiffies >= HZ)
 		update_jiffies = round_jiffies_relative(update_jiffies);
 	else {
@@ -3050,7 +3051,8 @@ end:
 			update_jiffies = j;
 	}
 
-	queue_delayed_work(priv->workqueue, &priv->stats_work, update_jiffies);
+	queue_delayed_work(priv->workqueue, &priv->dev_poller_work,
+								update_jiffies);
 }
 
 
@@ -3175,7 +3177,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 	/* because rndis_command() sleeps we need to use workqueue */
 	priv->workqueue = create_singlethread_workqueue("rndis_wlan");
 	INIT_WORK(&priv->work, rndis_wlan_worker);
-	INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
+	INIT_DELAYED_WORK(&priv->dev_poller_work, rndis_device_poller);
 	INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results);
 
 	/* try bind rndis_host */
@@ -3252,7 +3254,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 	return 0;
 
 fail:
-	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_delayed_work_sync(&priv->dev_poller_work);
 	cancel_delayed_work_sync(&priv->scan_work);
 	cancel_work_sync(&priv->work);
 	flush_workqueue(priv->workqueue);
@@ -3270,7 +3272,7 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
 	/* turn radio off */
 	disassociate(usbdev, 0);
 
-	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_delayed_work_sync(&priv->dev_poller_work);
 	cancel_delayed_work_sync(&priv->scan_work);
 	cancel_work_sync(&priv->work);
 	flush_workqueue(priv->workqueue);
@@ -3301,8 +3303,8 @@ static int rndis_wlan_reset(struct usbnet *usbdev)
 	   (set_multicast_list() also turns on current packet filter) */
 	set_multicast_list(usbdev);
 
-	queue_delayed_work(priv->workqueue, &priv->stats_work,
-		round_jiffies_relative(STATS_UPDATE_JIFFIES));
+	queue_delayed_work(priv->workqueue, &priv->dev_poller_work,
+		round_jiffies_relative(DEVICE_POLLER_JIFFIES));
 
 	return deauthenticate(usbdev);
 }
@@ -3319,7 +3321,7 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
 	retval = disassociate(usbdev, 0);
 
 	priv->work_pending = 0;
-	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_delayed_work_sync(&priv->dev_poller_work);
 	cancel_delayed_work_sync(&priv->scan_work);
 	cancel_work_sync(&priv->work);
 	flush_workqueue(priv->workqueue);


^ permalink raw reply related

* [RFC PATCH 05/10] rndis_wlan: add cfg80211 dump_station
From: Jussi Kivilinna @ 2009-08-28 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 1be0172..ac873d0 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -531,6 +531,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
 					u8 *mac, struct station_info *sinfo);
 
+static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
+			       int idx, u8 *mac, struct station_info *sinfo);
+
 static struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
@@ -546,6 +549,7 @@ static struct cfg80211_ops rndis_config_ops = {
 	.del_key = rndis_del_key,
 	.set_default_key = rndis_set_default_key,
 	.get_station = rndis_get_station,
+	.dump_station = rndis_dump_station,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -2155,6 +2159,22 @@ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
 	return 0;
 }
 
+static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
+			       int idx, u8 *mac, struct station_info *sinfo)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	memcpy(mac, priv->bssid, ETH_ALEN);
+
+	rndis_fill_station_info(usbdev, sinfo);
+
+	return 0;
+}
+
 /*
  * wireless extension handlers
  */


^ permalink raw reply related

* [RFC PATCH 04/10] rndis_wlan: add cfg80211 get_station
From: Jussi Kivilinna @ 2009-08-28 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Add cfg80211 get_station and convert SIOCGIWRATE and get_wireless_stats
to cfg80211.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |  118 ++++++++++++++++++-------------------
 1 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 93b504b..1be0172 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -444,17 +444,14 @@ struct rndis_wlan_private {
 	struct delayed_work scan_work;
 	struct work_struct work;
 	struct mutex command_lock;
-	spinlock_t stats_lock;
 	unsigned long work_pending;
+	int last_qual;
 
 	struct ieee80211_supported_band band;
 	struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
 	struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
 	u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)];
 
-	struct iw_statistics iwstats;
-	struct iw_statistics privstats;
-
 	int caps;
 	int multicast_size;
 
@@ -472,6 +469,7 @@ struct rndis_wlan_private {
 	int radio_on;
 	int infra_mode;
 	bool connected;
+	u8 bssid[ETH_ALEN];
 	struct ndis_80211_ssid essid;
 	__le32 current_command_oid;
 
@@ -530,6 +528,9 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 								u8 key_index);
 
+static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
+					u8 *mac, struct station_info *sinfo);
+
 static struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
@@ -544,6 +545,7 @@ static struct cfg80211_ops rndis_config_ops = {
 	.add_key = rndis_add_key,
 	.del_key = rndis_del_key,
 	.set_default_key = rndis_set_default_key,
+	.get_station = rndis_get_station,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -1931,6 +1933,7 @@ static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev,
 	devdbg(usbdev, "cfg80211.disconnect(%d)", reason_code);
 
 	priv->connected = false;
+	memset(priv->bssid, 0, ETH_ALEN);
 
 	return deauthenticate(usbdev);
 }
@@ -2037,6 +2040,7 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 	devdbg(usbdev, "cfg80211.leave_ibss()");
 
 	priv->connected = false;
+	memset(priv->bssid, 0, ETH_ALEN);
 
 	return deauthenticate(usbdev);
 }
@@ -2114,6 +2118,43 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 	return add_wep_key(usbdev, key.material, key.len, key_index);
 }
 
+static void rndis_fill_station_info(struct usbnet *usbdev,
+						struct station_info *sinfo)
+{
+	__le32 linkspeed, rssi;
+	int ret, len;
+
+	memset(sinfo, 0, sizeof(*sinfo));
+
+	len = sizeof(linkspeed);
+	ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &linkspeed, &len);
+	if (ret == 0) {
+		sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000;
+		sinfo->filled |= STATION_INFO_TX_BITRATE;
+	}
+
+	len = sizeof(rssi);
+	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+	if (ret == 0) {
+		sinfo->signal = level_to_qual(le32_to_cpu(rssi));
+		sinfo->filled |= STATION_INFO_SIGNAL;
+	}	
+}
+
+static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
+					u8 *mac, struct station_info *sinfo)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	if (compare_ether_addr(priv->bssid, mac))
+		return -ENOENT;
+
+	rndis_fill_station_info(usbdev, sinfo);
+
+	return 0;
+}
+
 /*
  * wireless extension handlers
  */
@@ -2459,7 +2500,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 				(u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
 				flags);
 }
-#endif
 
 
 static int rndis_iw_get_rate(struct net_device *dev,
@@ -2492,6 +2532,7 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
 
 	return &priv->iwstats;
 }
+#endif
 
 
 #define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
@@ -2510,7 +2551,7 @@ static const iw_handler rndis_iw_handler[] =
 	IW_IOCTL(SIOCGIWSCAN)      = (iw_handler) cfg80211_wext_giwscan,
 	IW_IOCTL(SIOCSIWESSID)     = (iw_handler) cfg80211_wext_siwessid,
 	IW_IOCTL(SIOCGIWESSID)     = (iw_handler) cfg80211_wext_giwessid,
-	IW_IOCTL(SIOCGIWRATE)      = rndis_iw_get_rate,
+	IW_IOCTL(SIOCGIWRATE)      = (iw_handler) cfg80211_wext_giwrate,
 	IW_IOCTL(SIOCSIWRTS)       = (iw_handler) cfg80211_wext_siwrts,
 	IW_IOCTL(SIOCGIWRTS)       = (iw_handler) cfg80211_wext_giwrts,
 	IW_IOCTL(SIOCSIWFRAG)      = (iw_handler) cfg80211_wext_siwfrag,
@@ -2539,7 +2580,7 @@ static const struct iw_handler_def rndis_iw_handlers = {
 	.standard = (iw_handler *)rndis_iw_handler,
 	.private  = (iw_handler *)rndis_wlan_private_handler,
 	.private_args = (struct iw_priv_args *)rndis_wlan_private_args,
-	.get_wireless_stats = rndis_get_wireless_stats,
+	.get_wireless_stats = cfg80211_wireless_stats,
 };
 
 
@@ -2614,6 +2655,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
 		cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
 
 	priv->connected = true;
+	memcpy(priv->bssid, bssid, ETH_ALEN);
 
 	usbnet_resume_rx(usbdev);
 	netif_carrier_on(usbdev->net);
@@ -2928,64 +2970,30 @@ static void rndis_update_wireless_stats(struct work_struct *work)
 	struct rndis_wlan_private *priv =
 		container_of(work, struct rndis_wlan_private, stats_work.work);
 	struct usbnet *usbdev = priv->usbdev;
-	struct iw_statistics iwstats;
 	__le32 rssi, tmp;
 	int len, ret, j;
-	unsigned long flags;
 	int update_jiffies = STATS_UPDATE_JIFFIES;
 	void *buf;
 
-	spin_lock_irqsave(&priv->stats_lock, flags);
-	memcpy(&iwstats, &priv->privstats, sizeof(iwstats));
-	spin_unlock_irqrestore(&priv->stats_lock, flags);
-
-	/* only update stats when connected */
-	if (!is_associated(usbdev)) {
-		iwstats.qual.qual = 0;
-		iwstats.qual.level = 0;
-		iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
-				| IW_QUAL_LEVEL_UPDATED
-				| IW_QUAL_NOISE_INVALID
-				| IW_QUAL_QUAL_INVALID
-				| IW_QUAL_LEVEL_INVALID;
+	/* Only check/do workaround when connected. Calling is_associated()
+	 * also polls device with rndis_command() and catches for media link
+	 * indications.
+	 */
+	if (!is_associated(usbdev))
 		goto end;
-	}
 
 	len = sizeof(rssi);
 	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+	if (ret == 0)
+		priv->last_qual = level_to_qual(le32_to_cpu(rssi));
 
 	devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret,
 							le32_to_cpu(rssi));
-	if (ret == 0) {
-		memset(&iwstats.qual, 0, sizeof(iwstats.qual));
-		iwstats.qual.qual  = level_to_qual(le32_to_cpu(rssi));
-		iwstats.qual.level = level_to_qual(le32_to_cpu(rssi));
-		iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
-				| IW_QUAL_LEVEL_UPDATED
-				| IW_QUAL_NOISE_INVALID;
-	}
-
-	memset(&iwstats.discard, 0, sizeof(iwstats.discard));
-
-	len = sizeof(tmp);
-	ret = rndis_query_oid(usbdev, OID_GEN_XMIT_ERROR, &tmp, &len);
-	if (ret == 0)
-		iwstats.discard.misc += le32_to_cpu(tmp);
-
-	len = sizeof(tmp);
-	ret = rndis_query_oid(usbdev, OID_GEN_RCV_ERROR, &tmp, &len);
-	if (ret == 0)
-		iwstats.discard.misc += le32_to_cpu(tmp);
-
-	len = sizeof(tmp);
-	ret = rndis_query_oid(usbdev, OID_GEN_RCV_NO_BUFFER, &tmp, &len);
-	if (ret == 0)
-		iwstats.discard.misc += le32_to_cpu(tmp);
 
 	/* Workaround transfer stalls on poor quality links.
 	 * TODO: find right way to fix these stalls (as stalls do not happen
 	 * with ndiswrapper/windows driver). */
-	if (iwstats.qual.qual <= 25) {
+	if (priv->last_qual <= 25) {
 		/* Decrease stats worker interval to catch stalls.
 		 * faster. Faster than 400-500ms causes packet loss,
 		 * Slower doesn't catch stalls fast enough.
@@ -3013,9 +3021,6 @@ static void rndis_update_wireless_stats(struct work_struct *work)
 		kfree(buf);
 	}
 end:
-	spin_lock_irqsave(&priv->stats_lock, flags);
-	memcpy(&priv->privstats, &iwstats, sizeof(iwstats));
-	spin_unlock_irqrestore(&priv->stats_lock, flags);
 
 	if (update_jiffies >= HZ)
 		update_jiffies = round_jiffies_relative(update_jiffies);
@@ -3146,7 +3151,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 	priv->usbdev = usbdev;
 
 	mutex_init(&priv->command_lock);
-	spin_lock_init(&priv->stats_lock);
 
 	/* because rndis_command() sleeps we need to use workqueue */
 	priv->workqueue = create_singlethread_workqueue("rndis_wlan");
@@ -3183,14 +3187,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 	else
 		usbdev->net->flags &= ~IFF_MULTICAST;
 
-	priv->iwstats.qual.qual = 0;
-	priv->iwstats.qual.level = 0;
-	priv->iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
-					| IW_QUAL_LEVEL_UPDATED
-					| IW_QUAL_NOISE_INVALID
-					| IW_QUAL_QUAL_INVALID
-					| IW_QUAL_LEVEL_INVALID;
-
 	/* fill-out wiphy structure and register w/ cfg80211 */
 	memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN);
 	wiphy->privid = rndis_wiphy_privid;


^ permalink raw reply related

* [RFC PATCH 03/10] rndis_wlan: add cfg80211 key handling
From: Jussi Kivilinna @ 2009-08-28 10:27 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Add cfg80211 add_key/del_key/set_default_key and convert wext to use theim.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |  133 +++++++++++++++++++++++++++++--------
 1 files changed, 103 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index ffb195d..93b504b 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -424,7 +424,7 @@ static const u32 rndis_cipher_suites[] = {
 
 struct rndis_wlan_encr_key {
 	int len;
-	int cipher;
+	u32 cipher;
 	u8 material[32];
 	u8 bssid[ETH_ALEN];
 	bool pairwise;
@@ -520,6 +520,16 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
 static int rndis_set_channel(struct wiphy *wiphy,
 	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
 
+static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
+					u8 key_index, const u8 *mac_addr,
+					struct key_params *params);
+
+static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
+					u8 key_index, const u8 *mac_addr);
+
+static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
+								u8 key_index);
+
 static struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
@@ -531,6 +541,9 @@ static struct cfg80211_ops rndis_config_ops = {
 	.join_ibss = rndis_join_ibss,
 	.leave_ibss = rndis_leave_ibss,
 	.set_channel = rndis_set_channel,
+	.add_key = rndis_add_key,
+	.del_key = rndis_del_key,
+	.set_default_key = rndis_set_default_key,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -1258,7 +1271,10 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_wep_key ndis_key;
-	int cipher, ret;
+	u32 cipher;
+	int ret;
+
+	devdbg(usbdev, "add_wep_key(idx: %d, len: %d)", index, key_len);
 
 	if ((key_len != 5 && key_len != 13) || index < 0 || index > 3)
 		return -EINVAL;
@@ -1302,8 +1318,8 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
 
 
 static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
-			int index, const u8 *addr, const u8 *rx_seq, int cipher,
-			int flags)
+			int index, const u8 *addr, const u8 *rx_seq,
+			int seq_len, u32 cipher, int flags)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_key ndis_key;
@@ -1319,10 +1335,18 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
 			key_len);
 		return -EINVAL;
 	}
-	if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) {
-		devdbg(usbdev, "add_wpa_key: recv seq flag without buffer");
-		return -EINVAL;
+	if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) {
+		if (!rx_seq || seq_len <= 0) {
+			devdbg(usbdev, "add_wpa_key: recv seq flag without"
+					"buffer");
+			return -EINVAL;
+		}
+		if (rx_seq && seq_len > sizeof(ndis_key.rsc)) {
+			devdbg(usbdev, "add_wpa_key: too big recv seq buffer");
+			return -EINVAL;
+		}
 	}
+
 	is_addr_ok = addr && !is_zero_ether_addr(addr) &&
 					!is_broadcast_ether_addr(addr);
 	if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) {
@@ -1353,7 +1377,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
 		memcpy(ndis_key.material, key, key_len);
 
 	if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)
-		memcpy(ndis_key.rsc, rx_seq, 6);
+		memcpy(ndis_key.rsc, rx_seq, seq_len);
 
 	if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
 		/* pairwise key */
@@ -1392,31 +1416,17 @@ static int restore_key(struct usbnet *usbdev, int key_idx)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct rndis_wlan_encr_key key;
-	int flags;
+
+	if (is_wpa_key(priv, key_idx))
+		return 0;
 
 	key = priv->encr_keys[key_idx];
 
-	devdbg(usbdev, "restore_key: %i:%s:%i", key_idx,
-		is_wpa_key(priv, key_idx) ? "wpa" : "wep",
-		key.len);
+	devdbg(usbdev, "restore_key: %i:%i", key_idx, key.len);
 
 	if (key.len == 0)
 		return 0;
 
-	if (is_wpa_key(priv, key_idx)) {
-		flags = 0;
-
-		/*if (priv->encr_tx_key_index == key_idx)
-			flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/
-
-		if (!is_zero_ether_addr(key.bssid) &&
-				!is_broadcast_ether_addr(key.bssid))
-			flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
-
-		return add_wpa_key(usbdev, key.material, key.len, key_idx,
-					key.bssid, NULL, key.cipher, flags);
-	}
-
 	return add_wep_key(usbdev, key.material, key.len, key_idx);
 }
 
@@ -1437,7 +1447,7 @@ static void clear_key(struct rndis_wlan_private *priv, int idx)
 
 
 /* remove_key is for both wep and wpa */
-static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_remove_key remove_key;
@@ -2041,6 +2051,69 @@ static int rndis_set_channel(struct wiphy *wiphy,
 			ieee80211_frequency_to_channel(chan->center_freq));
 }
 
+static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
+					u8 key_index, const u8 *mac_addr,
+					struct key_params *params)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	int flags;
+
+	devdbg(usbdev, "rndis_add_key(%i, %pM, %08x)", key_index, mac_addr,
+							params->cipher);
+
+	switch (params->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		return add_wep_key(usbdev, params->key, params->key_len,
+								key_index);
+	case WLAN_CIPHER_SUITE_TKIP:
+	case WLAN_CIPHER_SUITE_CCMP:
+		flags = 0;
+
+		if (params->seq && params->seq_len > 0)
+			flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
+		if (mac_addr)
+			flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY |
+					NDIS_80211_ADDKEY_TRANSMIT_KEY;
+
+		return add_wpa_key(usbdev, params->key, params->key_len,
+				key_index, mac_addr, params->seq,
+				params->seq_len, params->cipher, flags);
+	default:
+		devdbg(usbdev, "rndis_add_key: unsupported cipher %08x",
+							params->cipher);
+		return -ENOTSUPP;
+	}
+}
+
+static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
+					u8 key_index, const u8 *mac_addr)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	devdbg(usbdev, "rndis_del_key(%i, %pM)", key_index, mac_addr);
+
+	return remove_key(usbdev, key_index, mac_addr);
+}
+
+static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
+								u8 key_index)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	struct rndis_wlan_encr_key key;
+
+	devdbg(usbdev, "rndis_set_default_key(%i)", key_index);
+
+	priv->encr_tx_key_index = key_index;
+
+	key = priv->encr_keys[key_index];
+
+	return add_wep_key(usbdev, key.material, key.len, key_index);
+}
+
 /*
  * wireless extension handlers
  */
@@ -2268,7 +2341,6 @@ static int rndis_iw_get_auth(struct net_device *dev,
 	}
 	return 0;
 }
-#endif
 
 
 static int rndis_iw_set_encode(struct net_device *dev,
@@ -2387,6 +2459,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 				(u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
 				flags);
 }
+#endif
 
 
 static int rndis_iw_get_rate(struct net_device *dev,
@@ -2444,8 +2517,8 @@ static const iw_handler rndis_iw_handler[] =
 	IW_IOCTL(SIOCGIWFRAG)      = (iw_handler) cfg80211_wext_giwfrag,
 	IW_IOCTL(SIOCSIWTXPOW)     = (iw_handler) cfg80211_wext_siwtxpower,
 	IW_IOCTL(SIOCGIWTXPOW)     = (iw_handler) cfg80211_wext_giwtxpower,
-	IW_IOCTL(SIOCSIWENCODE)    = rndis_iw_set_encode,
-	IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext,
+	IW_IOCTL(SIOCSIWENCODE)    = (iw_handler) cfg80211_wext_siwencode,
+	IW_IOCTL(SIOCSIWENCODEEXT) = (iw_handler) cfg80211_wext_siwencodeext,
 	IW_IOCTL(SIOCSIWAUTH)      = (iw_handler) cfg80211_wext_siwauth,
 	IW_IOCTL(SIOCGIWAUTH)      = (iw_handler) cfg80211_wext_giwauth,
 	IW_IOCTL(SIOCSIWGENIE)     = (iw_handler) cfg80211_wext_siwgenie,


^ permalink raw reply related

* [RFC PATCH 02/10] rndis_wlan: add cfg80211 set_channel
From: Jussi Kivilinna @ 2009-08-28 10:27 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Add cfg80211 set_channel and convert wext to use it.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |  105 +++++--------------------------------
 1 files changed, 15 insertions(+), 90 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index c2af5be..ffb195d 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -517,6 +517,9 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
 static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
 
+static int rndis_set_channel(struct wiphy *wiphy,
+	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
+
 static struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
@@ -527,6 +530,7 @@ static struct cfg80211_ops rndis_config_ops = {
 	.disconnect = rndis_disconnect,
 	.join_ibss = rndis_join_ibss,
 	.leave_ibss = rndis_leave_ibss,
+	.set_channel = rndis_set_channel,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -924,46 +928,6 @@ static int level_to_qual(int level)
 }
 
 
-static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
-{
-	freq->e = 0;
-	freq->i = 0;
-	freq->flags = 0;
-
-	/* see comment in wireless.h above the "struct iw_freq"
-	 * definition for an explanation of this if
-	 * NOTE: 1000000 is due to the kHz
-	 */
-	if (dsconfig > 1000000) {
-		freq->m = dsconfig / 10;
-		freq->e = 1;
-	} else
-		freq->m = dsconfig;
-
-	/* convert from kHz to Hz */
-	freq->e += 3;
-}
-
-
-static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
-{
-	if (freq->m < 1000 && freq->e == 0) {
-		if (freq->m >= 1 && freq->m <= 14)
-			*dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000;
-		else
-			return -1;
-	} else {
-		int i;
-		*dsconfig = freq->m;
-		for (i = freq->e; i > 0; i--)
-			*dsconfig *= 10;
-		*dsconfig /= 1000;
-	}
-
-	return 0;
-}
-
-
 /*
  * common functions
  */
@@ -2067,6 +2031,15 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 	return deauthenticate(usbdev);
 }
 
+static int rndis_set_channel(struct wiphy *wiphy,
+	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	return set_channel(usbdev,
+			ieee80211_frequency_to_channel(chan->center_freq));
+}
 
 /*
  * wireless extension handlers
@@ -2416,54 +2389,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 }
 
 
-static int rndis_iw_set_freq(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct ndis_80211_conf config;
-	unsigned int dsconfig;
-	int len, ret;
-
-	/* this OID is valid only when not associated */
-	if (is_associated(usbdev))
-		return 0;
-
-	dsconfig = 0;
-	if (freq_to_dsconfig(&wrqu->freq, &dsconfig))
-		return -EINVAL;
-
-	len = sizeof(config);
-	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
-	if (ret != 0) {
-		devdbg(usbdev, "SIOCSIWFREQ: querying configuration failed");
-		return 0;
-	}
-
-	config.ds_config = cpu_to_le32(dsconfig);
-
-	devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
-	return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
-								sizeof(config));
-}
-
-
-static int rndis_iw_get_freq(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct ndis_80211_conf config;
-	int len, ret;
-
-	len = sizeof(config);
-	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
-	if (ret == 0)
-		dsconfig_to_freq(le32_to_cpu(config.ds_config), &wrqu->freq);
-
-	devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
-	return ret;
-}
-
-
 static int rndis_iw_get_rate(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
@@ -2501,8 +2426,8 @@ static const iw_handler rndis_iw_handler[] =
 {
 	IW_IOCTL(SIOCSIWCOMMIT)    = rndis_iw_commit,
 	IW_IOCTL(SIOCGIWNAME)      = (iw_handler) cfg80211_wext_giwname,
-	IW_IOCTL(SIOCSIWFREQ)      = rndis_iw_set_freq,
-	IW_IOCTL(SIOCGIWFREQ)      = rndis_iw_get_freq,
+	IW_IOCTL(SIOCSIWFREQ)      = (iw_handler) cfg80211_wext_siwfreq,
+	IW_IOCTL(SIOCGIWFREQ)      = (iw_handler) cfg80211_wext_giwfreq,
 	IW_IOCTL(SIOCSIWMODE)      = (iw_handler) cfg80211_wext_siwmode,
 	IW_IOCTL(SIOCGIWMODE)      = (iw_handler) cfg80211_wext_giwmode,
 	IW_IOCTL(SIOCGIWRANGE)     = (iw_handler) cfg80211_wext_giwrange,


^ permalink raw reply related

* [RFC PATCH 01/10] rndis_wlan: add cfg80211 connect, disconnect, join_ibss and leave_ibss
From: Jussi Kivilinna @ 2009-08-28 10:27 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>

Add cfg80211 connect functions for station and ad-hoc modes and
convert wext to use theim.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |  669 +++++++++++++++++++++++++------------
 1 files changed, 460 insertions(+), 209 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index c5a674d..c2af5be 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -358,13 +358,6 @@ struct ndis_80211_assoc_info {
 	__le32 offset_resp_ies;
 } __attribute__((packed));
 
-/* these have to match what is in wpa_supplicant */
-enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP };
-enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
-		  CIPHER_WEP104 };
-enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
-		    KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE };
-
 /*
  *  private data
  */
@@ -379,6 +372,15 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
 #define WORK_LINK_DOWN		(1<<1)
 #define WORK_SET_MULTICAST_LIST	(1<<2)
 
+#define RNDIS_WLAN_ALG_NONE	0
+#define RNDIS_WLAN_ALG_WEP	(1<<0)
+#define RNDIS_WLAN_ALG_TKIP	(1<<1)
+#define RNDIS_WLAN_ALG_CCMP	(1<<2)
+
+#define RNDIS_WLAN_KEY_MGMT_NONE	0
+#define RNDIS_WLAN_KEY_MGMT_802_1X	(1<<0)
+#define RNDIS_WLAN_KEY_MGMT_PSK		(1<<1)
+
 #define COMMAND_BUFFER_SIZE	(CONTROL_BUFFER_SIZE + sizeof(struct rndis_set))
 
 static const struct ieee80211_channel rndis_channels[] = {
@@ -469,15 +471,16 @@ struct rndis_wlan_private {
 	/* hardware state */
 	int radio_on;
 	int infra_mode;
+	bool connected;
 	struct ndis_80211_ssid essid;
 	__le32 current_command_oid;
 
 	/* encryption stuff */
 	int  encr_tx_key_index;
 	struct rndis_wlan_encr_key encr_keys[4];
+	enum nl80211_auth_type wpa_auth_type;
 	int  wpa_version;
 	int  wpa_keymgmt;
-	int  wpa_authalg;
 	int  wpa_ie_len;
 	u8  *wpa_ie;
 	int  wpa_cipher_pair;
@@ -503,12 +506,27 @@ static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
 				int dbm);
 static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
 
+static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
+				struct cfg80211_connect_params *sme);
+
+static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev,
+				u16 reason_code);
+
+static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+					struct cfg80211_ibss_params *params);
+
+static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
+
 static struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
 	.set_wiphy_params = rndis_set_wiphy_params,
 	.set_tx_power = rndis_set_tx_power,
 	.get_tx_power = rndis_get_tx_power,
+	.connect = rndis_connect,
+	.disconnect = rndis_disconnect,
+	.join_ibss = rndis_join_ibss,
+	.leave_ibss = rndis_leave_ibss,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -545,6 +563,34 @@ static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
 }
 
 
+static int rndis_cipher_to_alg(u32 cipher)
+{
+	switch (cipher) {
+	default:
+		return RNDIS_WLAN_ALG_NONE;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		return RNDIS_WLAN_ALG_WEP;
+	case WLAN_CIPHER_SUITE_TKIP:
+		return RNDIS_WLAN_ALG_TKIP;
+	case WLAN_CIPHER_SUITE_CCMP:
+		return RNDIS_WLAN_ALG_CCMP;
+	}
+}
+
+static int rndis_akm_suite_to_key_mgmt(u32 akm_suite)
+{
+	switch (akm_suite) {
+	default:
+		return RNDIS_WLAN_KEY_MGMT_NONE;
+	case WLAN_AKM_SUITE_8021X:
+		return RNDIS_WLAN_KEY_MGMT_802_1X;
+	case WLAN_AKM_SUITE_PSK:
+		return RNDIS_WLAN_KEY_MGMT_PSK;
+	}
+}
+
+
 #ifdef DEBUG
 static const char *oid_to_string(__le32 oid)
 {
@@ -925,35 +971,16 @@ static int set_infra_mode(struct usbnet *usbdev, int mode);
 static void restore_keys(struct usbnet *usbdev);
 static int rndis_check_bssid_list(struct usbnet *usbdev);
 
-static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
-{
-	int ret, len;
-
-	len = sizeof(*ssid);
-	ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
-
-	if (ret != 0)
-		ssid->length = 0;
-
-#ifdef DEBUG
-	{
-		unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
-
-		memcpy(tmp, ssid->essid, le32_to_cpu(ssid->length));
-		tmp[le32_to_cpu(ssid->length)] = 0;
-		devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
-	}
-#endif
-	return ret;
-}
-
-
 static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret;
 
 	ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid));
+	if (ret < 0) {
+		devwarn(usbdev, "setting SSID failed (%08X)", ret);
+		return ret;
+	}
 	if (ret == 0) {
 		memcpy(&priv->essid, ssid, sizeof(priv->essid));
 		priv->radio_on = 1;
@@ -963,6 +990,25 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 	return ret;
 }
 
+static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
+{
+	int ret;
+
+	ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
+	if (ret < 0) {
+		devwarn(usbdev, "setting BSSID[%pM] failed (%08X)", bssid, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int clear_bssid(struct usbnet *usbdev)
+{
+	u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+	return set_bssid(usbdev, broadcast_mac);
+}
 
 static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
 {
@@ -984,11 +1030,15 @@ static int get_association_info(struct usbnet *usbdev,
 				info, &len);
 }
 
-static int is_associated(struct usbnet *usbdev)
+static bool is_associated(struct usbnet *usbdev)
 {
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	u8 bssid[ETH_ALEN];
 	int ret;
 
+	if (!priv->radio_on)
+		return false;
+
 	ret = get_bssid(usbdev, bssid);
 
 	return (ret == 0 && !is_zero_ether_addr(bssid));
@@ -1032,34 +1082,34 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
 }
 
 
-static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
+static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
+				enum nl80211_auth_type auth_type, int keymgmt)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tmp;
 	int auth_mode, ret;
 
 	devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x "
-		"keymgmt=0x%x", wpa_version, authalg, priv->wpa_keymgmt);
+		"keymgmt=0x%x", wpa_version, auth_type, keymgmt);
 
-	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
-		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+	if (wpa_version & NL80211_WPA_VERSION_2) {
+		if (keymgmt & RNDIS_WLAN_KEY_MGMT_802_1X)
 			auth_mode = NDIS_80211_AUTH_WPA2;
 		else
 			auth_mode = NDIS_80211_AUTH_WPA2_PSK;
-	} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
-		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+	} else if (wpa_version & NL80211_WPA_VERSION_1) {
+		if (keymgmt & RNDIS_WLAN_KEY_MGMT_802_1X)
 			auth_mode = NDIS_80211_AUTH_WPA;
-		else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
+		else if (keymgmt & RNDIS_WLAN_KEY_MGMT_PSK)
 			auth_mode = NDIS_80211_AUTH_WPA_PSK;
 		else
 			auth_mode = NDIS_80211_AUTH_WPA_NONE;
-	} else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
-		if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
-			auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
-		else
-			auth_mode = NDIS_80211_AUTH_SHARED;
-	} else
+	} else if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
+		auth_mode = NDIS_80211_AUTH_SHARED;
+	else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
 		auth_mode = NDIS_80211_AUTH_OPEN;
+	else
+		return -ENOTSUPP;
 
 	tmp = cpu_to_le32(auth_mode);
 	ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
@@ -1070,7 +1120,9 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
 	}
 
 	priv->wpa_version = wpa_version;
-	priv->wpa_authalg = authalg;
+	priv->wpa_auth_type = auth_type;
+	priv->wpa_keymgmt = keymgmt;
+
 	return 0;
 }
 
@@ -1082,8 +1134,8 @@ static int set_priv_filter(struct usbnet *usbdev)
 
 	devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version);
 
-	if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
-	    priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
+	if (priv->wpa_version & NL80211_WPA_VERSION_2 ||
+	    priv->wpa_version & NL80211_WPA_VERSION_1)
 		tmp = cpu_to_le32(NDIS_80211_PRIV_8021X_WEP);
 	else
 		tmp = cpu_to_le32(NDIS_80211_PRIV_ACCEPT_ALL);
@@ -1100,19 +1152,17 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
 	int encr_mode, ret;
 
 	devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x",
-		pairwise,
-		groupwise);
+		pairwise, groupwise);
 
-	if (pairwise & IW_AUTH_CIPHER_CCMP)
+	if (pairwise & RNDIS_WLAN_ALG_CCMP)
 		encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
-	else if (pairwise & IW_AUTH_CIPHER_TKIP)
+	else if (pairwise & RNDIS_WLAN_ALG_TKIP)
 		encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
-	else if (pairwise &
-		 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+	else if (pairwise & RNDIS_WLAN_ALG_WEP)
 		encr_mode = NDIS_80211_ENCR_WEP_ENABLED;
-	else if (groupwise & IW_AUTH_CIPHER_CCMP)
+	else if (groupwise & RNDIS_WLAN_ALG_CCMP)
 		encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
-	else if (groupwise & IW_AUTH_CIPHER_TKIP)
+	else if (groupwise & RNDIS_WLAN_ALG_TKIP)
 		encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
 	else
 		encr_mode = NDIS_80211_ENCR_DISABLED;
@@ -1131,18 +1181,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
 }
 
 
-static int set_assoc_params(struct usbnet *usbdev)
-{
-	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
-
-	set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg);
-	set_priv_filter(usbdev);
-	set_encr_mode(usbdev, priv->wpa_cipher_pair, priv->wpa_cipher_group);
-
-	return 0;
-}
-
-
 static int set_infra_mode(struct usbnet *usbdev, int mode)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@@ -1201,16 +1239,11 @@ static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold)
 
 static void set_default_iw_params(struct usbnet *usbdev)
 {
-	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
-
-	priv->wpa_keymgmt = 0;
-	priv->wpa_version = 0;
-
 	set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
-	set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
-				IW_AUTH_ALG_OPEN_SYSTEM);
+	set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_OPEN_SYSTEM,
+						RNDIS_WLAN_KEY_MGMT_NONE);
 	set_priv_filter(usbdev);
-	set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
+	set_encr_mode(usbdev, RNDIS_WLAN_ALG_NONE, RNDIS_WLAN_ALG_NONE);
 }
 
 
@@ -1224,8 +1257,40 @@ static int deauthenticate(struct usbnet *usbdev)
 }
 
 
+static int set_channel(struct usbnet *usbdev, int channel)
+{
+	struct ndis_80211_conf config;
+	unsigned int dsconfig;
+	int len, ret;
+
+	devdbg(usbdev, "set_channel(%d)", channel);
+
+	/* this OID is valid only when not associated */
+	if (is_associated(usbdev))
+		return 0;
+
+	dsconfig = ieee80211_dsss_chan_to_freq(channel) * 1000;
+
+	len = sizeof(config);
+	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+	if (ret < 0) {
+		devdbg(usbdev, "set_channel: querying configuration failed");
+		return ret;
+	}
+
+	config.ds_config = cpu_to_le32(dsconfig);
+	ret = rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
+								sizeof(config));
+
+	devdbg(usbdev, "set_channel: %d -> %d", channel, ret);
+
+	return ret;
+}
+
+
 /* index must be 0 - N, as per NDIS  */
-static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
+								int index)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_wep_key ndis_key;
@@ -1248,8 +1313,8 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
 
 	if (index == priv->encr_tx_key_index) {
 		ndis_key.index |= NDIS_80211_ADDWEP_TRANSMIT_KEY;
-		ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
-						IW_AUTH_CIPHER_NONE);
+		ret = set_encr_mode(usbdev, RNDIS_WLAN_ALG_WEP,
+							RNDIS_WLAN_ALG_NONE);
 		if (ret)
 			devwarn(usbdev, "encryption couldn't be enabled (%08X)",
 									ret);
@@ -1458,7 +1523,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
 
 	/* if it is transmit key, disable encryption */
 	if (index == priv->encr_tx_key_index)
-		set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
+		set_encr_mode(usbdev, RNDIS_WLAN_ALG_NONE, RNDIS_WLAN_ALG_NONE);
 
 	return 0;
 }
@@ -1765,6 +1830,243 @@ static void rndis_get_scan_results(struct work_struct *work)
 	priv->scan_request = NULL;
 }
 
+static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
+					struct cfg80211_connect_params *sme)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	struct ieee80211_channel *channel = sme->channel;
+	struct ndis_80211_ssid ssid;
+	int pairwise = RNDIS_WLAN_ALG_NONE;
+	int groupwise = RNDIS_WLAN_ALG_NONE;
+	int keymgmt = RNDIS_WLAN_KEY_MGMT_NONE;
+	int length, i, ret, chan = -1;
+
+	if (channel)
+		chan = ieee80211_frequency_to_channel(channel->center_freq);
+
+	groupwise = rndis_cipher_to_alg(sme->crypto.cipher_group);
+	for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++)
+		pairwise |=
+			rndis_cipher_to_alg(sme->crypto.ciphers_pairwise[i]);
+
+	if (sme->crypto.n_ciphers_pairwise > 0 &&
+			pairwise == RNDIS_WLAN_ALG_NONE) {
+		deverr(usbdev, "Unsupported pairwise cipher");
+		return -ENOTSUPP;
+	}
+
+	for (i = 0; i < sme->crypto.n_akm_suites; i++)
+		keymgmt |=
+			rndis_akm_suite_to_key_mgmt(sme->crypto.akm_suites[i]);
+
+	if (sme->crypto.n_akm_suites > 0 &&
+			keymgmt == RNDIS_WLAN_KEY_MGMT_NONE) {
+		deverr(usbdev, "Invalid keymgmt");
+		return -ENOTSUPP;
+	}
+
+	devdbg(usbdev, "cfg80211.connect('%.32s':[%pM]:%d:[%d,0x%x:0x%x]:[0x%x:"
+			"0x%x]:0x%x)", sme->ssid, sme->bssid, chan,
+			sme->privacy, sme->crypto.wpa_versions, sme->auth_type,
+			groupwise, pairwise, keymgmt);
+
+	if (is_associated(usbdev))
+		disassociate(usbdev, false);
+
+	ret = set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
+	if (ret < 0) {
+		devdbg(usbdev, "connect: set_infra_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	ret = set_auth_mode(usbdev, sme->crypto.wpa_versions, sme->auth_type,
+								keymgmt);
+	if (ret < 0) {
+		devdbg(usbdev, "connect: set_auth_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	set_priv_filter(usbdev);
+
+	ret = set_encr_mode(usbdev, pairwise, groupwise);
+	if (ret < 0) {
+		devdbg(usbdev, "connect: set_encr_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	if (channel) {
+		ret = set_channel(usbdev, chan);
+		if (ret < 0) {
+			devdbg(usbdev, "connect: set_channel failed, %d", ret);
+			goto err_turn_radio_on;
+		}
+	}
+
+	if (sme->key && ((groupwise | pairwise) & RNDIS_WLAN_ALG_WEP)) {
+		priv->encr_tx_key_index = sme->key_idx;
+		ret = add_wep_key(usbdev, sme->key, sme->key_len, sme->key_idx);
+		if (ret < 0) {
+			devdbg(usbdev, "connect: add_wep_key failed, %d "
+				"(%d, %d)", ret, sme->key_len, sme->key_idx);
+			goto err_turn_radio_on;
+		}
+	}
+
+	if (sme->bssid && !is_zero_ether_addr(sme->bssid) &&
+				!is_broadcast_ether_addr(sme->bssid)) {
+		ret = set_bssid(usbdev, sme->bssid);
+		if (ret < 0) {
+			devdbg(usbdev, "connect: set_bssid failed, %d", ret);
+			goto err_turn_radio_on;
+		}
+	} else
+		clear_bssid(usbdev);
+
+	length = sme->ssid_len;
+	if (length > NDIS_802_11_LENGTH_SSID)
+		length = NDIS_802_11_LENGTH_SSID;
+
+	memset(&ssid, 0, sizeof(ssid));
+	ssid.length = cpu_to_le32(length);
+	memcpy(ssid.essid, sme->ssid, length);
+
+	/* Pause and purge rx queue, so we don't pass packets before
+	 * 'media connect'-indication.
+	 */
+	usbnet_pause_rx(usbdev);
+	usbnet_purge_paused_rxq(usbdev);
+
+	ret = set_essid(usbdev, &ssid);
+	if (ret < 0)
+		devdbg(usbdev, "connect: set_essid failed, %d", ret);
+	return ret;
+
+err_turn_radio_on:
+	disassociate(usbdev, 1);
+
+	return ret;
+}
+
+static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev,
+								u16 reason_code)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	devdbg(usbdev, "cfg80211.disconnect(%d)", reason_code);
+
+	priv->connected = false;
+
+	return deauthenticate(usbdev);
+}
+
+static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+					struct cfg80211_ibss_params *params)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	struct ieee80211_channel *channel = params->channel;
+	struct ndis_80211_ssid ssid;
+	enum nl80211_auth_type auth_type;
+	int ret, alg, length, chan = -1;
+
+	if (channel)
+		chan = ieee80211_frequency_to_channel(channel->center_freq);
+
+	/* TODO: How to handle ad-hoc encryption?
+	 * connect() has *key, join_ibss() doesn't. RNDIS requires key to be
+	 * pre-shared for encryption (open/shared/wpa), is key set before
+	 * join_ibss? Which auth_type to use (not in params)? What about WPA?
+	 */
+	if (params->privacy) {
+		auth_type = NL80211_AUTHTYPE_SHARED_KEY;
+		alg = RNDIS_WLAN_ALG_WEP;
+	} else {
+		auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+		alg = RNDIS_WLAN_ALG_NONE;
+	}
+
+	devdbg(usbdev, "cfg80211.join_ibss('%.32s':[%pM]:%d:%d)", params->ssid,
+					params->bssid, chan, params->privacy);
+
+	if (is_associated(usbdev))
+		disassociate(usbdev, false);
+
+	ret = set_infra_mode(usbdev, NDIS_80211_INFRA_ADHOC);
+	if (ret < 0) {
+		devdbg(usbdev, "join_ibss: set_infra_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	ret = set_auth_mode(usbdev, 0, auth_type, RNDIS_WLAN_KEY_MGMT_NONE);
+	if (ret < 0) {
+		devdbg(usbdev, "join_ibss: set_auth_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	set_priv_filter(usbdev);
+
+	ret = set_encr_mode(usbdev, alg, RNDIS_WLAN_ALG_NONE);
+	if (ret < 0) {
+		devdbg(usbdev, "join_ibss: set_encr_mode failed, %d", ret);
+		goto err_turn_radio_on;
+	}
+
+	if (channel) {
+		ret = set_channel(usbdev, chan);
+		if (ret < 0) {
+			devdbg(usbdev, "join_ibss: set_channel failed, %d",
+				ret);
+			goto err_turn_radio_on;
+		}
+	}
+
+	if (params->bssid && !is_zero_ether_addr(params->bssid) &&
+				!is_broadcast_ether_addr(params->bssid)) {
+		ret = set_bssid(usbdev, params->bssid);
+		if (ret < 0) {
+			devdbg(usbdev, "join_ibss: set_bssid failed, %d", ret);
+			goto err_turn_radio_on;
+		}
+	} else
+		clear_bssid(usbdev);
+
+	length = params->ssid_len;
+	if (length > NDIS_802_11_LENGTH_SSID)
+		length = NDIS_802_11_LENGTH_SSID;
+
+	memset(&ssid, 0, sizeof(ssid));
+	ssid.length = cpu_to_le32(length);
+	memcpy(ssid.essid, params->ssid, length);
+
+	/* Don't need to pause rx queue for ad-hoc. */
+	usbnet_purge_paused_rxq(usbdev);
+	usbnet_resume_rx(usbdev);
+
+	ret = set_essid(usbdev, &ssid);
+	if (ret < 0)
+		devdbg(usbdev, "join_ibss: set_essid failed, %d", ret);
+	return ret;
+
+err_turn_radio_on:
+	disassociate(usbdev, 1);
+
+	return ret;
+}
+
+static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+
+	devdbg(usbdev, "cfg80211.leave_ibss()");
+
+	priv->connected = false;
+
+	return deauthenticate(usbdev);
+}
+
 
 /*
  * wireless extension handlers
@@ -1777,7 +2079,10 @@ static int rndis_iw_commit(struct net_device *dev,
 	return 0;
 }
 
-
+#if 0
+/* Commented code out instead of removing to have more sane patch for review.
+ * Will be removed later in the set.
+ */
 static int rndis_iw_set_essid(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
 {
@@ -1990,6 +2295,7 @@ static int rndis_iw_get_auth(struct net_device *dev,
 	}
 	return 0;
 }
+#endif
 
 
 static int rndis_iw_set_encode(struct net_device *dev,
@@ -2024,11 +2330,11 @@ static int rndis_iw_set_encode(struct net_device *dev,
 
 	/* global encryption state (for all keys) */
 	if (wrqu->data.flags & IW_ENCODE_OPEN)
-		ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
-						IW_AUTH_ALG_OPEN_SYSTEM);
+		ret = set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_OPEN_SYSTEM,
+						RNDIS_WLAN_KEY_MGMT_NONE);
 	else /*if (wrqu->data.flags & IW_ENCODE_RESTRICTED)*/
-		ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
-						IW_AUTH_ALG_SHARED_KEY);
+		ret = set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_SHARED_KEY,
+						RNDIS_WLAN_KEY_MGMT_NONE);
 	if (ret != 0)
 		return ret;
 
@@ -2077,7 +2383,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 		return -EINVAL;
 	}
 
-	if (ext->alg == WPA_ALG_WEP) {
+	if (ext->alg == IW_ENCODE_ALG_WEP) {
 		if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
 			priv->encr_tx_key_index = keyidx;
 		return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
@@ -2110,63 +2416,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 }
 
 
-static int rndis_iw_set_genie(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
-	int ret = 0;
-
-#ifdef DEBUG
-	int j;
-	u8 *gie = extra;
-	for (j = 0; j < wrqu->data.length; j += 8)
-		devdbg(usbdev,
-			"SIOCSIWGENIE %04x - "
-			"%02x %02x %02x %02x %02x %02x %02x %02x", j,
-			gie[j + 0], gie[j + 1], gie[j + 2], gie[j + 3],
-			gie[j + 4], gie[j + 5], gie[j + 6], gie[j + 7]);
-#endif
-	/* clear existing IEs */
-	if (priv->wpa_ie_len) {
-		kfree(priv->wpa_ie);
-		priv->wpa_ie_len = 0;
-	}
-
-	/* set new IEs */
-	priv->wpa_ie = kmalloc(wrqu->data.length, GFP_KERNEL);
-	if (priv->wpa_ie) {
-		priv->wpa_ie_len = wrqu->data.length;
-		memcpy(priv->wpa_ie, extra, priv->wpa_ie_len);
-	} else
-		ret = -ENOMEM;
-	return ret;
-}
-
-
-static int rndis_iw_get_genie(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
-
-	devdbg(usbdev, "SIOCGIWGENIE");
-
-	if (priv->wpa_ie_len == 0 || priv->wpa_ie == NULL) {
-		wrqu->data.length = 0;
-		return 0;
-	}
-
-	if (wrqu->data.length < priv->wpa_ie_len)
-		return -E2BIG;
-
-	wrqu->data.length = priv->wpa_ie_len;
-	memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
-
-	return 0;
-}
-
-
 static int rndis_iw_set_freq(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
@@ -2233,32 +2482,6 @@ static int rndis_iw_get_rate(struct net_device *dev,
 }
 
 
-static int rndis_iw_set_mlme(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
-	struct iw_mlme *mlme = (struct iw_mlme *)extra;
-	unsigned char bssid[ETH_ALEN];
-
-	get_bssid(usbdev, bssid);
-
-	if (memcmp(bssid, mlme->addr.sa_data, ETH_ALEN))
-		return -EINVAL;
-
-	switch (mlme->cmd) {
-	case IW_MLME_DEAUTH:
-		return deauthenticate(usbdev);
-	case IW_MLME_DISASSOC:
-		return disassociate(usbdev, priv->radio_on);
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-
 static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
@@ -2283,12 +2506,12 @@ static const iw_handler rndis_iw_handler[] =
 	IW_IOCTL(SIOCSIWMODE)      = (iw_handler) cfg80211_wext_siwmode,
 	IW_IOCTL(SIOCGIWMODE)      = (iw_handler) cfg80211_wext_giwmode,
 	IW_IOCTL(SIOCGIWRANGE)     = (iw_handler) cfg80211_wext_giwrange,
-	IW_IOCTL(SIOCSIWAP)        = rndis_iw_set_bssid,
-	IW_IOCTL(SIOCGIWAP)        = rndis_iw_get_bssid,
+	IW_IOCTL(SIOCSIWAP)        = (iw_handler) cfg80211_wext_siwap,
+	IW_IOCTL(SIOCGIWAP)        = (iw_handler) cfg80211_wext_giwap,
 	IW_IOCTL(SIOCSIWSCAN)      = (iw_handler) cfg80211_wext_siwscan,
 	IW_IOCTL(SIOCGIWSCAN)      = (iw_handler) cfg80211_wext_giwscan,
-	IW_IOCTL(SIOCSIWESSID)     = rndis_iw_set_essid,
-	IW_IOCTL(SIOCGIWESSID)     = rndis_iw_get_essid,
+	IW_IOCTL(SIOCSIWESSID)     = (iw_handler) cfg80211_wext_siwessid,
+	IW_IOCTL(SIOCGIWESSID)     = (iw_handler) cfg80211_wext_giwessid,
 	IW_IOCTL(SIOCGIWRATE)      = rndis_iw_get_rate,
 	IW_IOCTL(SIOCSIWRTS)       = (iw_handler) cfg80211_wext_siwrts,
 	IW_IOCTL(SIOCGIWRTS)       = (iw_handler) cfg80211_wext_giwrts,
@@ -2298,11 +2521,10 @@ static const iw_handler rndis_iw_handler[] =
 	IW_IOCTL(SIOCGIWTXPOW)     = (iw_handler) cfg80211_wext_giwtxpower,
 	IW_IOCTL(SIOCSIWENCODE)    = rndis_iw_set_encode,
 	IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext,
-	IW_IOCTL(SIOCSIWAUTH)      = rndis_iw_set_auth,
-	IW_IOCTL(SIOCGIWAUTH)      = rndis_iw_get_auth,
-	IW_IOCTL(SIOCSIWGENIE)     = rndis_iw_set_genie,
-	IW_IOCTL(SIOCGIWGENIE)     = rndis_iw_get_genie,
-	IW_IOCTL(SIOCSIWMLME)      = rndis_iw_set_mlme,
+	IW_IOCTL(SIOCSIWAUTH)      = (iw_handler) cfg80211_wext_siwauth,
+	IW_IOCTL(SIOCGIWAUTH)      = (iw_handler) cfg80211_wext_giwauth,
+	IW_IOCTL(SIOCSIWGENIE)     = (iw_handler) cfg80211_wext_siwgenie,
+	IW_IOCTL(SIOCSIWMLME)      = (iw_handler) cfg80211_wext_siwmlme,
 };
 
 static const iw_handler rndis_wlan_private_handler[] = {
@@ -2325,49 +2547,78 @@ static const struct iw_handler_def rndis_iw_handlers = {
 
 static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
 {
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_assoc_info *info;
-	union iwreq_data evt;
 	u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32];
 	u8 bssid[ETH_ALEN];
+	int resp_ie_len, req_ie_len;
+	u8 *req_ie, *resp_ie;
 	int ret, offset;
+	bool roamed = false;
+
+	if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) {
+		/* received media connect indication while connected, either
+		 * device reassociated with same AP or roamed to new. */
+		roamed = true;
+	}
+
+	req_ie_len = 0;
+	resp_ie_len = 0;
+	req_ie = NULL;
+	resp_ie = NULL;
+
+	if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
+		memset(assoc_buf, 0, sizeof(assoc_buf));
+		info = (void *)assoc_buf;
+
+		/* Get association info IEs from device and send them back to
+		 * userspace. */
+		ret = get_association_info(usbdev, info, sizeof(assoc_buf));
+		if (!ret) {
+			req_ie_len = le32_to_cpu(info->req_ie_length);
+			if (req_ie_len > 0) {
+				offset = le32_to_cpu(info->offset_req_ies);
+				req_ie = (u8 *)info + offset;
+			}
 
-	memset(assoc_buf, 0, sizeof(assoc_buf));
-	info = (void *)assoc_buf;
+			resp_ie_len = le32_to_cpu(info->resp_ie_length);
+			if (resp_ie_len > 0) {
+				offset = le32_to_cpu(info->offset_resp_ies);
+				resp_ie = (u8 *)info + offset;
+			}
+		}
+	} else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC))
+		return;
 
-	netif_carrier_on(usbdev->net);
+	ret = get_bssid(usbdev, bssid);
+	if (ret < 0)
+		memset(bssid, 0, sizeof(bssid));
 
-	/* Get association info IEs from device and send them back to
-	 * userspace. */
-	ret = get_association_info(usbdev, info, sizeof(assoc_buf));
-	if (!ret) {
-		evt.data.length = le32_to_cpu(info->req_ie_length);
-		if (evt.data.length > 0) {
-			offset = le32_to_cpu(info->offset_req_ies);
-			wireless_send_event(usbdev->net,
-				IWEVASSOCREQIE, &evt,
-				(char *)info + offset);
-		}
+	devdbg(usbdev, "link up work: [%pM] %s", bssid, roamed ? "roamed" : "");
 
-		evt.data.length = le32_to_cpu(info->resp_ie_length);
-		if (evt.data.length > 0) {
-			offset = le32_to_cpu(info->offset_resp_ies);
-			wireless_send_event(usbdev->net,
-				IWEVASSOCRESPIE, &evt,
-				(char *)info + offset);
-		}
+	/* Internal bss list in device always contains at least the currently
+	 * connected bss and we can get it to cfg80211 with
+	 * rndis_check_bssid_list().
+	 * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS
+	 * spec.
+	 */
+	rndis_check_bssid_list(usbdev);
 
-		usbnet_resume_rx(usbdev);
-	}
+	if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
+		if (!roamed)
+			cfg80211_connect_result(usbdev->net, bssid, req_ie,
+						req_ie_len, resp_ie,
+						resp_ie_len, 0, GFP_KERNEL);
+		else
+			cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len,
+					resp_ie, resp_ie_len, GFP_KERNEL);
+	} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
+		cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
 
-	ret = get_bssid(usbdev, bssid);
-	if (!ret) {
-		evt.data.flags = 0;
-		evt.data.length = 0;
-		memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
-		wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
-	}
+	priv->connected = true;
 
 	usbnet_resume_rx(usbdev);
+	netif_carrier_on(usbdev->net);
 }
 
 static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)


^ permalink raw reply related

* [RFC PATCH 00/10] complete cfg80211 conversion
From: Jussi Kivilinna @ 2009-08-28 10:27 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Johannes Berg

This patchset completes cfg80211 conversion of rndis_wlan. Tested connect with 
wext-compat: WPA/WPA2-PSK, WEP work with station mode. Adhoc work with
and without WEP. Throught nl80211 pretty much untested.

Should rndis_wlan find out key_id for cfg80211_michael_mic_failure, patch 
currently uses -1?

---

Jussi Kivilinna (10):
      rndis_wlan: use cfg80211_wext_handler
      rndis_wlan: disable IWEVPMKIDCAND wireless event
      rndis_wlan: convert mic failure wireless event to cfg80211
      rndis_wlan: remove unneeded SIOCSIWCOMMIT
      rndis_wlan: rename wireless stats worker to device poller
      rndis_wlan: add cfg80211 dump_station
      rndis_wlan: add cfg80211 get_station
      rndis_wlan: add cfg80211 key handling
      rndis_wlan: add cfg80211 set_channel
      rndis_wlan: add cfg80211 connect, disconnect, join_ibss and leave_ibss


 drivers/net/wireless/rndis_wlan.c | 1299 ++++++++++++++++---------------------
 1 files changed, 571 insertions(+), 728 deletions(-)

-- 

^ permalink raw reply

* [PATCH 8/8] rndis_wlan: enable infrastructure before setting random essid
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Random essid must be set to turn on radio when not connected. If device is
in ad-hoc mode, this results 'media connect' indications with the random
essid which should be ignored.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index d117620..c5a674d 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -921,6 +921,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
 /*
  * common functions
  */
+static int set_infra_mode(struct usbnet *usbdev, int mode);
 static void restore_keys(struct usbnet *usbdev);
 static int rndis_check_bssid_list(struct usbnet *usbdev);
 
@@ -1014,6 +1015,11 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
 	/* disassociate causes radio to be turned off; if reset_ssid
 	 * is given, set random ssid to enable radio */
 	if (reset_ssid) {
+		/* Set device to infrastructure mode so we don't get ad-hoc
+		 * 'media connect' indications with the random ssid.
+		 */
+		set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
+
 		ssid.length = cpu_to_le32(sizeof(ssid.essid));
 		get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2);
 		ssid.essid[0] = 0x1;


^ permalink raw reply related

* [PATCH 7/8] rndis_wlan: set ieee80211_ptr->iftype in rndis_change_virtual_intf
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index c28fde5..d117620 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1526,7 +1526,8 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
 					enum nl80211_iftype type, u32 *flags,
 					struct vif_params *params)
 {
-	struct usbnet *usbdev = netdev_priv(dev);
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
 	int mode;
 
 	switch (type) {
@@ -1540,6 +1541,8 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
+	priv->wdev.iftype = type;
+
 	return set_infra_mode(usbdev, mode);
 }
 


^ permalink raw reply related

* [PATCH 6/8] rndis_wlan: use is_zero_ether_addr() and is_broadcast_ether_addr()
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Use is_zero_ether_addr() and is_broadcast_ether_addr() instead of
memcmp against ffff_bssid/zero_bssid.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   17 ++++++-----------
 1 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index dc3083b..c28fde5 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -514,11 +514,6 @@ static struct cfg80211_ops rndis_config_ops = {
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
 
 
-static const unsigned char zero_bssid[ETH_ALEN] = {0,};
-static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff,
-							0xff, 0xff, 0xff };
-
-
 static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev)
 {
 	return (struct rndis_wlan_private *)dev->driver_priv;
@@ -995,7 +990,7 @@ static int is_associated(struct usbnet *usbdev)
 
 	ret = get_bssid(usbdev, bssid);
 
-	return(ret == 0 && memcmp(bssid, zero_bssid, ETH_ALEN) != 0);
+	return (ret == 0 && !is_zero_ether_addr(bssid));
 }
 
 
@@ -1293,8 +1288,8 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
 		devdbg(usbdev, "add_wpa_key: recv seq flag without buffer");
 		return -EINVAL;
 	}
-	is_addr_ok = addr && memcmp(addr, zero_bssid, ETH_ALEN) != 0 &&
-			memcmp(addr, ffff_bssid, ETH_ALEN) != 0;
+	is_addr_ok = addr && !is_zero_ether_addr(addr) &&
+					!is_broadcast_ether_addr(addr);
 	if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) {
 		devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)",
 			addr);
@@ -1379,8 +1374,8 @@ static int restore_key(struct usbnet *usbdev, int key_idx)
 		/*if (priv->encr_tx_key_index == key_idx)
 			flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/
 
-		if (memcmp(key.bssid, zero_bssid, ETH_ALEN) != 0 &&
-				memcmp(key.bssid, ffff_bssid, ETH_ALEN) != 0)
+		if (!is_zero_ether_addr(key.bssid) &&
+				!is_broadcast_ether_addr(key.bssid))
 			flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
 
 		return add_wpa_key(usbdev, key.material, key.len, key_idx,
@@ -1430,7 +1425,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
 		remove_key.index = cpu_to_le32(index);
 		if (bssid) {
 			/* pairwise key */
-			if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
+			if (!is_broadcast_ether_addr(bssid))
 				remove_key.index |=
 					NDIS_80211_ADDKEY_PAIRWISE_KEY;
 			memcpy(remove_key.bssid, bssid,


^ permalink raw reply related

* [PATCH 5/8] rndis_wlan: move link up/down work to separate functions
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Move link up/down work to separate functions and use local array
for allocating memory for info structure instead of kzmalloc.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |  101 ++++++++++++++++++++-----------------
 1 files changed, 55 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index cb362b0..dc3083b 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2319,68 +2319,77 @@ static const struct iw_handler_def rndis_iw_handlers = {
 };
 
 
-static void rndis_wlan_worker(struct work_struct *work)
+static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
 {
-	struct rndis_wlan_private *priv =
-		container_of(work, struct rndis_wlan_private, work);
-	struct usbnet *usbdev = priv->usbdev;
-	union iwreq_data evt;
-	unsigned char bssid[ETH_ALEN];
 	struct ndis_80211_assoc_info *info;
-	int assoc_size = sizeof(*info) + IW_CUSTOM_MAX + 32;
+	union iwreq_data evt;
+	u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32];
+	u8 bssid[ETH_ALEN];
 	int ret, offset;
 
-	if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending)) {
-		netif_carrier_on(usbdev->net);
-
-		info = kzalloc(assoc_size, GFP_KERNEL);
-		if (!info)
-			goto get_bssid;
-
-		/* Get association info IEs from device and send them back to
-		 * userspace. */
-		ret = get_association_info(usbdev, info, assoc_size);
-		if (!ret) {
-			evt.data.length = le32_to_cpu(info->req_ie_length);
-			if (evt.data.length > 0) {
-				offset = le32_to_cpu(info->offset_req_ies);
-				wireless_send_event(usbdev->net,
-					IWEVASSOCREQIE, &evt,
-					(char *)info + offset);
-			}
-
-			evt.data.length = le32_to_cpu(info->resp_ie_length);
-			if (evt.data.length > 0) {
-				offset = le32_to_cpu(info->offset_resp_ies);
-				wireless_send_event(usbdev->net,
-					IWEVASSOCRESPIE, &evt,
-					(char *)info + offset);
-			}
+	memset(assoc_buf, 0, sizeof(assoc_buf));
+	info = (void *)assoc_buf;
+
+	netif_carrier_on(usbdev->net);
+
+	/* Get association info IEs from device and send them back to
+	 * userspace. */
+	ret = get_association_info(usbdev, info, sizeof(assoc_buf));
+	if (!ret) {
+		evt.data.length = le32_to_cpu(info->req_ie_length);
+		if (evt.data.length > 0) {
+			offset = le32_to_cpu(info->offset_req_ies);
+			wireless_send_event(usbdev->net,
+				IWEVASSOCREQIE, &evt,
+				(char *)info + offset);
 		}
 
-		kfree(info);
-
-get_bssid:
-		ret = get_bssid(usbdev, bssid);
-		if (!ret) {
-			evt.data.flags = 0;
-			evt.data.length = 0;
-			memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
-			wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
+		evt.data.length = le32_to_cpu(info->resp_ie_length);
+		if (evt.data.length > 0) {
+			offset = le32_to_cpu(info->offset_resp_ies);
+			wireless_send_event(usbdev->net,
+				IWEVASSOCRESPIE, &evt,
+				(char *)info + offset);
 		}
 
 		usbnet_resume_rx(usbdev);
 	}
 
-	if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) {
-		netif_carrier_off(usbdev->net);
-
+	ret = get_bssid(usbdev, bssid);
+	if (!ret) {
 		evt.data.flags = 0;
 		evt.data.length = 0;
-		memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
+		memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
 		wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
 	}
 
+	usbnet_resume_rx(usbdev);
+}
+
+static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)
+{
+	union iwreq_data evt;
+
+	netif_carrier_off(usbdev->net);
+
+	evt.data.flags = 0;
+	evt.data.length = 0;
+	memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
+	wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
+}
+
+static void rndis_wlan_worker(struct work_struct *work)
+{
+	struct rndis_wlan_private *priv =
+		container_of(work, struct rndis_wlan_private, work);
+	struct usbnet *usbdev = priv->usbdev;
+
+	if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending))
+		rndis_wlan_do_link_up_work(usbdev);
+
+	if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending))
+		rndis_wlan_do_link_down_work(usbdev);
+
 	if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
 		set_multicast_list(usbdev);
 }


^ permalink raw reply related

* [PATCH 4/8] rndis_wlan: increase scan timer delay
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Increase scan delay from 1 sec to 6 sec. Spec says that scan by
OID_802_11_BSSID_LIST_SCAN completes in 6 seconds.
Before rfkill patch too short delay was not problem as device was
always active (radio on) and performing background scanning.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2309ad2..cb362b0 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1607,7 +1607,7 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
 }
 
 
-#define SCAN_DELAY_JIFFIES (HZ)
+#define SCAN_DELAY_JIFFIES (6 * HZ)
 static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
 			struct cfg80211_scan_request *request)
 {


^ permalink raw reply related

* [PATCH 3/8] rndis_wlan: resize bssid list if too small
From: Jussi Kivilinna @ 2009-08-28  9:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

Buffer used for bssid list might be too small. Change rndis_query_oid()
to return required buffer length to caller and make rndis_check_bssid_list()
resize buffer when needed.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   17 +++++++++++++++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 3779621..2309ad2 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -676,7 +676,8 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 
 	if (ret == 0) {
 		ret = le32_to_cpu(u.get_c->len);
-		*len = (*len > ret) ? ret : *len;
+		if (ret > *len)
+			*len = ret;
 		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
 		ret = rndis_error_status(u.get_c->status);
 
@@ -1656,6 +1657,9 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
 	int ie_len, bssid_len;
 	u8 *ie;
 
+	devdbg(usbdev, " found bssid: '%.32s' [%pM]", bssid->ssid.essid,
+							bssid->mac);
+
 	/* parse bssid structure */
 	bssid_len = le32_to_cpu(bssid->length);
 
@@ -1695,10 +1699,12 @@ static int rndis_check_bssid_list(struct usbnet *usbdev)
 	struct ndis_80211_bssid_list_ex *bssid_list;
 	struct ndis_80211_bssid_ex *bssid;
 	int ret = -EINVAL, len, count, bssid_len;
+	bool resized = false;
 
 	devdbg(usbdev, "check_bssid_list");
 
 	len = CONTROL_BUFFER_SIZE;
+resize_buf:
 	buf = kmalloc(len, GFP_KERNEL);
 	if (!buf) {
 		ret = -ENOMEM;
@@ -1709,11 +1715,18 @@ static int rndis_check_bssid_list(struct usbnet *usbdev)
 	if (ret != 0)
 		goto out;
 
+	if (!resized && len > CONTROL_BUFFER_SIZE) {
+		resized = true;
+		kfree(buf);
+		goto resize_buf;
+	}
+
 	bssid_list = buf;
 	bssid = bssid_list->bssid;
 	bssid_len = le32_to_cpu(bssid->length);
 	count = le32_to_cpu(bssid_list->num_items);
-	devdbg(usbdev, "check_bssid_list: %d BSSIDs found", count);
+	devdbg(usbdev, "check_bssid_list: %d BSSIDs found (buflen: %d)", count,
+									len);
 
 	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
 		rndis_bss_info_update(usbdev, bssid);


^ permalink raw reply related

* [PATCH 2/8] rndis_wlan: get bssid scan list before new scan
From: Jussi Kivilinna @ 2009-08-28  9:58 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville
In-Reply-To: <20090828095849.10554.58857.stgit@fate.lan>

OID_802_11_BSSID_LIST_SCAN clears device's bssid list, so retrieve
current bssid list from device before issuing new scan.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 612c2c7..3779621 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -926,6 +926,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
  * common functions
  */
 static void restore_keys(struct usbnet *usbdev);
+static int rndis_check_bssid_list(struct usbnet *usbdev);
 
 static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 {
@@ -1616,6 +1617,11 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
 
 	devdbg(usbdev, "cfg80211.scan");
 
+	/* Get current bssid list from device before new scan, as new scan
+	 * clears internal bssid list.
+	 */
+	rndis_check_bssid_list(usbdev);
+
 	if (!request)
 		return -EINVAL;
 


^ permalink raw reply related

* [PATCH 1/8] rndis_wlan: ignore OID_802_11_ADD_KEY triggered media connect indications
From: Jussi Kivilinna @ 2009-08-28  9:58 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville

Setting WPA keys with OID_802_11_ADD_KEY sometimes trigger
instant media connect indication. These indications are extranous and
should be ignored, as otherwise driver would send reassociation event to
userspace which in this case is not needed.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index f181b00..612c2c7 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -470,6 +470,7 @@ struct rndis_wlan_private {
 	int radio_on;
 	int infra_mode;
 	struct ndis_80211_ssid essid;
+	__le32 current_command_oid;
 
 	/* encryption stuff */
 	int  encr_tx_key_index;
@@ -665,7 +666,9 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 	u.get->msg_len = cpu_to_le32(sizeof *u.get);
 	u.get->oid = oid;
 
+	priv->current_command_oid = oid;
 	ret = rndis_command(dev, u.header, buflen);
+	priv->current_command_oid = 0;
 	if (ret < 0)
 		devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d "
 			"(%08x)", oid_to_string(oid), ret,
@@ -725,7 +728,9 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
 	u.set->handle = cpu_to_le32(0);
 	memcpy(u.buf + sizeof(*u.set), data, len);
 
+	priv->current_command_oid = oid;
 	ret = rndis_command(dev, u.header, buflen);
+	priv->current_command_oid = 0;
 	if (ret < 0)
 		devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d "
 			"(%08x)", oid_to_string(oid), ret,
@@ -760,6 +765,7 @@ static int rndis_reset(struct usbnet *usbdev)
 	memset(reset, 0, sizeof(*reset));
 	reset->msg_type = RNDIS_MSG_RESET;
 	reset->msg_len = cpu_to_le32(sizeof(*reset));
+	priv->current_command_oid = 0;
 	ret = rndis_command(usbdev, (void *)reset, CONTROL_BUFFER_SIZE);
 
 	mutex_unlock(&priv->command_lock);
@@ -2558,6 +2564,17 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
 
 	switch (msg->status) {
 	case RNDIS_STATUS_MEDIA_CONNECT:
+		if (priv->current_command_oid == OID_802_11_ADD_KEY) {
+			/* OID_802_11_ADD_KEY causes sometimes extra
+			 * "media connect" indications which confuses driver
+			 * and userspace to think that device is
+			 * roaming/reassociating when it isn't.
+			 */
+			devdbg(usbdev, "ignored OID_802_11_ADD_KEY triggered "
+					"'media connect'");
+			return;
+		}
+
 		usbnet_pause_rx(usbdev);
 
 		devinfo(usbdev, "media connect");


^ permalink raw reply related

* Re: [PATCH 13/13] wl1271: added Juuso Oikarinen as module author
From: Luciano Coelho @ 2009-08-28  9:27 UTC (permalink / raw)
  To: ext Johannes Berg
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	Oikarinen Juuso (Nokia-D-MSW/Tampere),
	Valo Kalle (Nokia-D/Tampere)
In-Reply-To: <1251450604.3456.1.camel@johannes.local>

ext Johannes Berg wrote:
> On Fri, 2009-08-28 at 12:01 +0300, Luciano Coelho wrote:
>
>   
>> Is that the right way to do it? At least in include/linux/module.h it 
>> says this:
>>
>> /* Author, ideally of form NAME[, NAME]*[ and NAME] */
>> #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
>>     
>
> Interesting, but I suspect that should just be changed.
>
> If you use multiple MODULE_AUTHOR, they will be shown as such:
>
> $ /sbin/modinfo ar9170usb | grep author
> author:         Christian Lamparter <chunkeey@web.de>
> author:         Johannes Berg <johannes@sipsolutions.net>
>
>
> If you use just one, it would be one long author: line with all of them.
> I think the multiple line case is much nicer.
>   

Yes, I totally agree with you.  I'll use multiple MODULE_AUTHOR()s.  ;)

-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH 13/13] wl1271: added Juuso Oikarinen as module author
From: Johannes Berg @ 2009-08-28  9:10 UTC (permalink / raw)
  To: Luciano Coelho
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	Oikarinen Juuso (Nokia-D-MSW/Tampere),
	Valo Kalle (Nokia-D/Tampere)
In-Reply-To: <4A979D06.2000205@nokia.com>

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

On Fri, 2009-08-28 at 12:01 +0300, Luciano Coelho wrote:

> Is that the right way to do it? At least in include/linux/module.h it 
> says this:
> 
> /* Author, ideally of form NAME[, NAME]*[ and NAME] */
> #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)

Interesting, but I suspect that should just be changed.

If you use multiple MODULE_AUTHOR, they will be shown as such:

$ /sbin/modinfo ar9170usb | grep author
author:         Christian Lamparter <chunkeey@web.de>
author:         Johannes Berg <johannes@sipsolutions.net>


If you use just one, it would be one long author: line with all of them.
I think the multiple line case is much nicer.

johannes

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

^ permalink raw reply

* Re: [PATCH 13/13] wl1271: added Juuso Oikarinen as module author
From: Luciano Coelho @ 2009-08-28  9:01 UTC (permalink / raw)
  To: ext Johannes Berg
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	Oikarinen Juuso (Nokia-D-MSW/Tampere),
	Valo Kalle (Nokia-D/Tampere)
In-Reply-To: <1251408741.22482.14.camel@johannes.local>

ext Johannes Berg wrote:
> On Fri, 2009-08-28 at 00:00 +0300, Luciano Coelho wrote:
>   
>> Add Juuso as one of the module authors, since he's working heavily on this
>> module as well.
>>
>> Cc: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
>> ---
>>  drivers/net/wireless/wl12xx/wl1271_main.c |    3 ++-
>>  1 files changed, 2 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
>> index a97d434..4163eac 100644
>> --- a/drivers/net/wireless/wl12xx/wl1271_main.c
>> +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
>> @@ -1449,4 +1449,5 @@ module_init(wl1271_init);
>>  module_exit(wl1271_exit);
>>  
>>  MODULE_LICENSE("GPL");
>> -MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
>> +MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>, "
>> +	      "Juuso Oikarinen <juuso.oikarinen@nokia.com>");
>>     
>
> Use multiple MODULE_AUTHORs instead.
>   

Is that the right way to do it? At least in include/linux/module.h it 
says this:

/* Author, ideally of form NAME[, NAME]*[ and NAME] */
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)

As I interpret it, it means that there should be one MODULE_AUTHOR with 
a string that contains all the names.  So actually the right way to do 
it would be this:

MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com> and "
	      "Juuso Oikarinen <juuso.oikarinen@nokia.com>");


Or am I missing/misinterpreting something?

-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH 1/2] cfg80211: initialize rate control after station inserted
From: Johannes Berg @ 2009-08-28  7:45 UTC (permalink / raw)
  To: Reinette Chatre; +Cc: linville, linux-wireless
In-Reply-To: <1251416094-10420-1-git-send-email-reinette.chatre@intel.com>

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

Hi,

Thanks. I'll comment on both patches together. Can you please also tell
us what the problem is this is solving? I'm a bit lost.

I think both of these patches should just rolled into one since this is
also a mac80211 patch -- even if it's for the bit that interacts with
cfg80211.

However, I don't think I actually understand the changes.

>  	sta_apply_parameters(local, sta, params);
>  
> -	rate_control_rate_init(sta);
> -
>  	layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
>  		sdata->vif.type == NL80211_IFTYPE_AP;
>  
> @@ -742,13 +740,17 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
>  		if (err == -EEXIST && layer2_update) {
>  			/* Need to update layer 2 devices on reassociation */
>  			sta = sta_info_get(local, mac);
> -			if (sta)
> +			if (sta) {
> +				rate_control_rate_init(sta);
>  				ieee80211_send_layer2_update(sta);
> +			}
>  		}

Why is this necessary? It should already have been called for this
station earlier?

>  		rcu_read_unlock();
>  		return err;
>  	}
>  
> +	rate_control_rate_init(sta);
> +

Also, I don't see anything between the old place that it was called and
the new place you're moving it to that could possibly change the station
parameters?

Same in ibss.c (not quoting it here) where you're only moving it to
after sta_info_insert() -- all that seems to do is add race conditions,
allowing other code to find not-yet-initialised stations.

So the only place I could see a change being necessary would be mlme.c,
but then only moving rate_control_rate_init() to after the flags
settings, not to after the insert.

Am I missing something?

johannes

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

^ permalink raw reply

* Re: ar9271 mailing list and driver project page
From: Holger Schurig @ 2009-08-28  7:34 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: devel, linux-wireless, linux-kernel, Greg KH
In-Reply-To: <43e72e890908271943s6dca1257g1f1e56d0347cc21d@mail.gmail.com>

> ar9271 and ar9170 seem to share a few things, one of which is
> firmware upload. ar9271's firmware upload routine was modified
> to make it match ar9170's as much as possible to share it on
> ath.ko

Is it true that most devices which will use ath.ko won't ever use 
firmware uploading?  It's only a few Ath-USB devices, so maybe 
you could do an ath_fw.ko for this.

(Somebody who's always working with embedded devices and likes to 
keeps small :-)

-- 
http://www.holgerschurig.de

^ permalink raw reply

* Re: [ath5k-devel] [PATCH 1/2] ath5k: fix uninitialized value use in ath5k_eeprom_read_turbo_modes()
From: Luis R. Rodriguez @ 2009-08-28  5:21 UTC (permalink / raw)
  To: Nick Kossifidis
  Cc: Bob Copeland, Pavel Roskin, ath5k-devel, linux-wireless,
	John W. Linville
In-Reply-To: <40f31dec0908272117s27b3a59ep5f18c85aa179793d@mail.gmail.com>

On Thu, Aug 27, 2009 at 9:17 PM, Nick Kossifidis<mickflemm@gmail.com> wrote:

> Many people use turbo mode and it's not an ugly proprietary extension, static
> turbo mode is close to just having 40MHz channels,

Its not following any spec and I suspect it will create pretty noise
on existing wireless networks. 11n has at least some precautions to
try to be friendly, such as trying using primary and extension
channels to match nearby APs. I don't believe Atheros Turbo has such
things.

> we can use the same way to
> switch to it as with 5 and 10MHz channels.

5 and 10 MHz seem to be defined and used as per 802.11 and those seem
reasonable to support.

> Most code is there, we are ready to support 5/10/40MHz channels on the
> driver part

Great.

> as soon as we are done with cfg80211/mac80211 compatibility so why drop it ?

We can drop Turbo, but it seems reasonable to keep 5 MHz and 10 MHz support.

> Having multiple drivers won't help users, i thought that MadWiFi was "dead"
> and we were working on a complete alternative.

MadWifi is dead.

  Luis

^ permalink raw reply

* Re: [ath5k-devel] [PATCH 1/2] ath5k: fix uninitialized value use in ath5k_eeprom_read_turbo_modes()
From: Nick Kossifidis @ 2009-08-28  4:17 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Bob Copeland, Pavel Roskin, ath5k-devel, linux-wireless,
	John W. Linville
In-Reply-To: <43e72e890908272057s28ee11c6x624e8a08c6bd17e9@mail.gmail.com>

2009/8/28 Luis R. Rodriguez <mcgrof@gmail.com>:
> On Thu, Aug 27, 2009 at 8:01 PM, Nick Kossifidis<mickflemm@gmail.com> wrote:
>> 2009/8/27 Luis R. Rodriguez <mcgrof@gmail.com>:
>>> On Thu, Aug 27, 2009 at 11:17 AM, Bob Copeland<bcopeland@gmail.com> wrote:
>>>> On Thu, Aug 27, 2009 at 8:58 AM, Nick Kossifidis<mickflemm@gmail.com> wrote:
>>>>> 2009/8/27 Pavel Roskin <proski@gnu.org>:
>>>>
>>>>> Current code works fine (i 've checked it against various cards),
>>>>> there is nothing wrong
>>>>> with having another function for reading turbo modes, i find it's
>>>>> cleaner that way.
>>>>
>>>> Well, we also don't use the turbo modes at all and that's where the
>>>> error is (IIRC) so it shouldn't have any impact. :)
>>>
>>> Again, why don't we just remove all that fucking turbo cruft?
>>>
>>>  Luis
>>>
>>
>> Why should we remove it, we are discussing on implementing channel
>> width setting for 5 and 10 MHz channels already so where is the
>> problem supporting turbo mode (40MHz) ?
>
> Supporting 5 MHz and 10 MHz channels is very different than supporting
> Turbo (40 MHz). 5 MHz and 10 MHz channels seems to be something you
> can use as per 802.11, 40 MHz "Turbo" stuff is just a vendor extension
> and at least by my part I don't want to move a finger to either
> support it nor do I think its a good idea to support it. Other people
> have objected to vendor extensions before on mac80211 so I don't think
> you'll find much support for this from a lot of people.
>

Many people use turbo mode and it's not an ugly proprietary extension, static
turbo mode is close to just having 40MHz channels, we can use the same way to
switch to it as with 5 and 10MHz channels. The difficult part is
having dynamic turbo
(supporting 20MHz and 40MHz stations at the same time) but we don't deal with it
anyway (and it's only useful on ap mode).

Most code is there, we are ready to support 5/10/40MHz channels on the
driver part
as soon as we are done with cfg80211/mac80211 compatibility so why drop it ?

> The way I see is if you want vendor extensions like Atheros Turbo or
> XR use MadWifi.
>

XR is not supported on MadWiFi, i remember only some parts were supported +
we don't have much to work with anyway (XR code is missing from Legacy and
Sam's HAL) + not many people use it anyway so i agree we can drop it but it's
nothing like turbo mode, as i said many people use that.

>> Also EEPROM code should read the eeprom and fill the structs, since
>> these infos are there we should read them, i don't see any reason to
>> skip them
>
> I didn't see Bob's patch remove that stuff. Its pointless to use it though.
>

It can be confusing (offsets missing etc) + we might want to put eeprom infos
on debugfs (i had an ugly patch just for that) for debuging.

>> i thought our goal was to support this hw as much as
>> possible,
>
> We should support users as best as possible, whether or not you
> support vendor extensions is an entirely different story.
>
>> if we want to get rid of MadWiFi we 'll have to at least
>> support 5, 10 and 40MHz (turbo) channels.
>
> I don't want to get rid of MadWifi, what we have now is a proper
> upstream replacement. MadWifi is still a hack put together, and people
> who want hacks can use that.
>

Having multiple drivers won't help users, i thought that MadWiFi was "dead"
and we were working on a complete alternative.



-- 
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

^ permalink raw reply

* Re: [ath5k-devel] [PATCH 1/2] ath5k: fix uninitialized value use in ath5k_eeprom_read_turbo_modes()
From: Luis R. Rodriguez @ 2009-08-28  3:57 UTC (permalink / raw)
  To: Nick Kossifidis
  Cc: Bob Copeland, Pavel Roskin, ath5k-devel, linux-wireless,
	John W. Linville
In-Reply-To: <40f31dec0908272001u1a67cbf3ycc5d9588dd48915d@mail.gmail.com>

On Thu, Aug 27, 2009 at 8:01 PM, Nick Kossifidis<mickflemm@gmail.com> wrote:
> 2009/8/27 Luis R. Rodriguez <mcgrof@gmail.com>:
>> On Thu, Aug 27, 2009 at 11:17 AM, Bob Copeland<bcopeland@gmail.com> wrote:
>>> On Thu, Aug 27, 2009 at 8:58 AM, Nick Kossifidis<mickflemm@gmail.com> wrote:
>>>> 2009/8/27 Pavel Roskin <proski@gnu.org>:
>>>
>>>> Current code works fine (i 've checked it against various cards),
>>>> there is nothing wrong
>>>> with having another function for reading turbo modes, i find it's
>>>> cleaner that way.
>>>
>>> Well, we also don't use the turbo modes at all and that's where the
>>> error is (IIRC) so it shouldn't have any impact. :)
>>
>> Again, why don't we just remove all that fucking turbo cruft?
>>
>>  Luis
>>
>
> Why should we remove it, we are discussing on implementing channel
> width setting for 5 and 10 MHz channels already so where is the
> problem supporting turbo mode (40MHz) ?

Supporting 5 MHz and 10 MHz channels is very different than supporting
Turbo (40 MHz). 5 MHz and 10 MHz channels seems to be something you
can use as per 802.11, 40 MHz "Turbo" stuff is just a vendor extension
and at least by my part I don't want to move a finger to either
support it nor do I think its a good idea to support it. Other people
have objected to vendor extensions before on mac80211 so I don't think
you'll find much support for this from a lot of people.

The way I see is if you want vendor extensions like Atheros Turbo or
XR use MadWifi.

> Also EEPROM code should read the eeprom and fill the structs, since
> these infos are there we should read them, i don't see any reason to
> skip them

I didn't see Bob's patch remove that stuff. Its pointless to use it though.

> i thought our goal was to support this hw as much as
> possible,

We should support users as best as possible, whether or not you
support vendor extensions is an entirely different story.

> if we want to get rid of MadWiFi we 'll have to at least
> support 5, 10 and 40MHz (turbo) channels.

I don't want to get rid of MadWifi, what we have now is a proper
upstream replacement. MadWifi is still a hack put together, and people
who want hacks can use that.

> I understand that there is
> no support yet on mac80211/cfg80211 but i don't think removing all
> this stuff and bring it back is the right thing to do.

I don't expect it will come back.

  Luis

^ 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