* Re: [PATCH V2] cfg80211: allow cfg80211_connect_result with bssid == NULL
From: Johannes Berg @ 2009-08-19 8:12 UTC (permalink / raw)
To: Zhu Yi; +Cc: linville, linux-wireless
In-Reply-To: <1250669302-11362-1-git-send-email-yi.zhu@intel.com>
[-- Attachment #1: Type: text/plain, Size: 1848 bytes --]
On Wed, 2009-08-19 at 16:08 +0800, Zhu Yi wrote:
> In case of connection failure, the bssid info is not a must have.
>
> Cc: Johannes Berg <johannes@sipsolutions.net>
> Signed-off-by: Zhu Yi <yi.zhu@intel.com>
> ---
> V2: change a __cfg80211_connect_result() caller to used NULL instead of zero addr
Thanks.
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> net/wireless/core.c | 4 +++-
> net/wireless/sme.c | 3 ++-
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/wireless/core.c b/net/wireless/core.c
> index e630648..8eddf98 100644
> --- a/net/wireless/core.c
> +++ b/net/wireless/core.c
> @@ -12,6 +12,7 @@
> #include <linux/debugfs.h>
> #include <linux/notifier.h>
> #include <linux/device.h>
> +#include <linux/etherdevice.h>
> #include <linux/rtnetlink.h>
> #include <net/genetlink.h>
> #include <net/cfg80211.h>
> @@ -309,7 +310,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev)
> switch (ev->type) {
> case EVENT_CONNECT_RESULT:
> __cfg80211_connect_result(
> - wdev->netdev, ev->cr.bssid,
> + wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ?
> + NULL : ev->cr.bssid,
> ev->cr.req_ie, ev->cr.req_ie_len,
> ev->cr.resp_ie, ev->cr.resp_ie_len,
> ev->cr.status,
> diff --git a/net/wireless/sme.c b/net/wireless/sme.c
> index 8e2ef54..dbd8211 100644
> --- a/net/wireless/sme.c
> +++ b/net/wireless/sme.c
> @@ -458,7 +458,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
> return;
>
> ev->type = EVENT_CONNECT_RESULT;
> - memcpy(ev->cr.bssid, bssid, ETH_ALEN);
> + if (bssid)
> + memcpy(ev->cr.bssid, bssid, ETH_ALEN);
> ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
> ev->cr.req_ie_len = req_ie_len;
> memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH V2] cfg80211: allow cfg80211_connect_result with bssid == NULL
From: Zhu Yi @ 2009-08-19 8:08 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Zhu Yi, Johannes Berg
In case of connection failure, the bssid info is not a must have.
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
V2: change a __cfg80211_connect_result() caller to used NULL instead of zero addr
net/wireless/core.c | 4 +++-
net/wireless/sme.c | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e630648..8eddf98 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -12,6 +12,7 @@
#include <linux/debugfs.h>
#include <linux/notifier.h>
#include <linux/device.h>
+#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <net/genetlink.h>
#include <net/cfg80211.h>
@@ -309,7 +310,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev)
switch (ev->type) {
case EVENT_CONNECT_RESULT:
__cfg80211_connect_result(
- wdev->netdev, ev->cr.bssid,
+ wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ?
+ NULL : ev->cr.bssid,
ev->cr.req_ie, ev->cr.req_ie_len,
ev->cr.resp_ie, ev->cr.resp_ie_len,
ev->cr.status,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8e2ef54..dbd8211 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -458,7 +458,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return;
ev->type = EVENT_CONNECT_RESULT;
- memcpy(ev->cr.bssid, bssid, ETH_ALEN);
+ if (bssid)
+ memcpy(ev->cr.bssid, bssid, ETH_ALEN);
ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
ev->cr.req_ie_len = req_ie_len;
memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH] cfg80211: fix leaks of wdev->conn->ie
From: Johannes Berg @ 2009-08-19 7:52 UTC (permalink / raw)
To: David Kilroy; +Cc: linux-wireless
In-Reply-To: <1250639011-18258-1-git-send-email-kilroyd@googlemail.com>
[-- Attachment #1: Type: text/plain, Size: 1859 bytes --]
On Wed, 2009-08-19 at 00:43 +0100, David Kilroy wrote:
> This only occurs in the following error situations:
> - driver calls connect_result with failure
> - error scheduling authentication on connect
> - error initiating scan (to get BSSID and channel) on
> connect
> - userspace calls disconnect while in the SCANNING or
> SCAN_AGAIN states
>
> Signed-off-by: David Kilroy <kilroyd@googlemail.com>
> Cc: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> I came across this while looking at my orinoco scanning issue. It's
> possible I'm wrong...
Yes, looks like I forgot these, thanks!
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> net/wireless/sme.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/net/wireless/sme.c b/net/wireless/sme.c
> index 6fb6a70..9ddc00e 100644
> --- a/net/wireless/sme.c
> +++ b/net/wireless/sme.c
> @@ -395,6 +395,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
>
> if (status != WLAN_STATUS_SUCCESS) {
> wdev->sme_state = CFG80211_SME_IDLE;
> + if (wdev->conn)
> + kfree(wdev->conn->ie);
> kfree(wdev->conn);
> wdev->conn = NULL;
> kfree(wdev->connect_keys);
> @@ -779,6 +781,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
> }
> }
> if (err) {
> + kfree(wdev->conn->ie);
> kfree(wdev->conn);
> wdev->conn = NULL;
> wdev->sme_state = CFG80211_SME_IDLE;
> @@ -848,6 +851,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
> (wdev->conn->state == CFG80211_CONN_SCANNING ||
> wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
> wdev->sme_state = CFG80211_SME_IDLE;
> + kfree(wdev->conn->ie);
> kfree(wdev->conn);
> wdev->conn = NULL;
> wdev->ssid_len = 0;
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [RFC 5/5] cfg80211: scan before connect if we don't have the bss
From: Johannes Berg @ 2009-08-19 7:48 UTC (permalink / raw)
To: David Kilroy; +Cc: linux-wireless
In-Reply-To: <1250640253-18434-6-git-send-email-kilroyd@googlemail.com>
[-- Attachment #1: Type: text/plain, Size: 1584 bytes --]
On Wed, 2009-08-19 at 01:04 +0100, David Kilroy wrote:
> @@ -791,18 +824,55 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
>
> return err;
> } else {
> + struct cfg80211_bss *bss;
> +
> wdev->sme_state = CFG80211_SME_CONNECTING;
> wdev->connect_keys = connkeys;
> +
> + bss = cfg80211_get_bss(wdev->wiphy, NULL, connect->bssid,
> + connect->ssid, connect->ssid_len,
> + WLAN_CAPABILITY_ESS,
> + WLAN_CAPABILITY_ESS);
Hmm. What if the bssid isn't set? Then the card might select a different
BSS than the one we have on the scan list.
> + /* Failed to clone (or scan), so we can't
> + * delay the connect. Free everything up and
> + * go ahead with the connect */
> + if (wdev->conn)
> + kfree(wdev->conn->ie);
> + kfree(wdev->conn);
> + wdev->conn = NULL;
and that would then run into the warning and the problem anyway? Better
to just reject with -ENOMEM I think? Also, I really don't think you
should use wdev->conn anywhere in this code path, because some code
looks at that to figure out whether or not the cfg80211 SME is used.
> + } else {
> + cfg80211_put_bss(bss);
> err = rdev->ops->connect(&rdev->wiphy, dev, connect);
And it's all racy too -- by the time the driver calls connect_result(),
the BSS might have expired after it was found here now.
I don't think this is really feasible to implement in cfg80211. Couldn't
the driver do a probe to the BSS that the device selected, and report
that before the connect result?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] cfg80211: allow cfg80211_connect_result with bssid == NULL
From: Johannes Berg @ 2009-08-19 7:30 UTC (permalink / raw)
To: Zhu Yi; +Cc: linville, linux-wireless
In-Reply-To: <1250663378-9113-1-git-send-email-yi.zhu@intel.com>
[-- Attachment #1: Type: text/plain, Size: 331 bytes --]
On Wed, 2009-08-19 at 14:29 +0800, Zhu Yi wrote:
> In case of connection failure, the bssid info is not a must have.
Good point, thanks. In fact, the original __cfg80211_connect_result()
did handle a NULL bssid, but the event stuff lost it. I think you should
also pass NULL in core.c when is_zero_ether_addr()?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH] cfg80211: allow cfg80211_connect_result with bssid == NULL
From: Zhu Yi @ 2009-08-19 6:29 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Zhu Yi, Johannes Berg
In case of connection failure, the bssid info is not a must have.
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/wireless/sme.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index b78a111..bc9584a 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -435,7 +435,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return;
ev->type = EVENT_CONNECT_RESULT;
- memcpy(ev->cr.bssid, bssid, ETH_ALEN);
+ if (bssid)
+ memcpy(ev->cr.bssid, bssid, ETH_ALEN);
ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
ev->cr.req_ie_len = req_ie_len;
memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
--
1.6.0.4
^ permalink raw reply related
* [RFC 5/5] cfg80211: scan before connect if we don't have the bss
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1250640253-18434-1-git-send-email-kilroyd@googlemail.com>
The connect_result callback relies on cfg80211 having the bss
information (via beacons/probes). For a fullmac driver, this information
is only likely to be present after a scan. Userspace is not guaranteed
to scan before connecting (e.g. wpa_supplicant ap_scan=2 in wext mode),
so before calling ->connect do an explicit ->scan if we don't have the
bss in our list.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
net/wireless/sme.c | 150 ++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 110 insertions(+), 40 deletions(-)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 9ddc00e..6dc7981 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -26,11 +26,13 @@ struct cfg80211_conn {
CFG80211_CONN_AUTHENTICATING,
CFG80211_CONN_ASSOCIATE_NEXT,
CFG80211_CONN_ASSOCIATING,
+ CFG80211_CONN_DELAYED_CONNECT,
} state;
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
u8 *ie;
size_t ie_len;
bool auto_auth, prev_bssid_valid;
+ bool connect_after_scan;
};
@@ -148,6 +150,19 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
NULL, 0,
WLAN_REASON_DEAUTH_LEAVING);
return err;
+ case CFG80211_CONN_DELAYED_CONNECT:
+ BUG_ON(!rdev->ops->connect);
+ err = rdev->ops->connect(&rdev->wiphy, wdev->netdev,
+ &wdev->conn->params);
+ kfree(wdev->conn->ie);
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ if (err) {
+ wdev->connect_keys = NULL;
+ wdev->sme_state = CFG80211_SME_IDLE;
+ wdev->ssid_len = 0;
+ }
+ return err;
default:
return 0;
}
@@ -234,6 +249,12 @@ static void __cfg80211_sme_scan_done(struct net_device *dev)
wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
return;
+ if (wdev->conn->connect_after_scan) {
+ wdev->conn->state = CFG80211_CONN_DELAYED_CONNECT;
+ schedule_work(&rdev->conn_work);
+ return;
+ }
+
if (!cfg80211_get_conn_bss(wdev)) {
/* not found */
if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
@@ -655,6 +676,52 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
}
EXPORT_SYMBOL(cfg80211_disconnected);
+static int cfg80211_conn_clone(struct wireless_dev *wdev,
+ struct cfg80211_connect_params *connect)
+{
+ if (WARN_ON(wdev->conn))
+ return -EINPROGRESS;
+
+ wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
+ if (!wdev->conn)
+ return -ENOMEM;
+
+ memcpy(&wdev->conn->params, connect, sizeof(*connect));
+ if (connect->bssid) {
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
+ }
+
+ if (connect->ie) {
+ wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
+ GFP_KERNEL);
+ wdev->conn->params.ie = wdev->conn->ie;
+ if (!wdev->conn->ie) {
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
+ wdev->conn->auto_auth = true;
+ /* start with open system ... should mostly work */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ } else {
+ wdev->conn->auto_auth = false;
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+ wdev->conn->params.ssid = wdev->ssid;
+ wdev->conn->params.ssid_len = connect->ssid_len;
+
+ wdev->conn->connect_after_scan = false;
+
+ return 0;
+}
+
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_connect_params *connect,
@@ -710,46 +777,12 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
if (!rdev->ops->auth || !rdev->ops->assoc)
return -EOPNOTSUPP;
- if (WARN_ON(wdev->conn))
- return -EINPROGRESS;
-
- wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
- if (!wdev->conn)
- return -ENOMEM;
-
/*
* Copy all parameters, and treat explicitly IEs, BSSID, SSID.
*/
- memcpy(&wdev->conn->params, connect, sizeof(*connect));
- if (connect->bssid) {
- wdev->conn->params.bssid = wdev->conn->bssid;
- memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
- }
-
- if (connect->ie) {
- wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
- GFP_KERNEL);
- wdev->conn->params.ie = wdev->conn->ie;
- if (!wdev->conn->ie) {
- kfree(wdev->conn);
- wdev->conn = NULL;
- return -ENOMEM;
- }
- }
-
- if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
- wdev->conn->auto_auth = true;
- /* start with open system ... should mostly work */
- wdev->conn->params.auth_type =
- NL80211_AUTHTYPE_OPEN_SYSTEM;
- } else {
- wdev->conn->auto_auth = false;
- }
-
- memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
- wdev->ssid_len = connect->ssid_len;
- wdev->conn->params.ssid = wdev->ssid;
- wdev->conn->params.ssid_len = connect->ssid_len;
+ err = cfg80211_conn_clone(wdev, connect);
+ if (err)
+ return err;
/* don't care about result -- but fill bssid & channel */
if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
@@ -791,18 +824,55 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
return err;
} else {
+ struct cfg80211_bss *bss;
+
wdev->sme_state = CFG80211_SME_CONNECTING;
wdev->connect_keys = connkeys;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, connect->bssid,
+ connect->ssid, connect->ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+ if (!bss) {
+ /* We don't have a matching BSS.
+ *
+ * This means __connect_result will fail,
+ * unless the driver provides scan results
+ * between now and then. So do an explicit
+ * scan, and try connect later.
+ */
+ err = cfg80211_conn_clone(wdev, connect);
+ if (!err) {
+ wdev->conn->connect_after_scan = true;
+ err = cfg80211_conn_scan(wdev);
+
+ if (!err)
+ return 0;
+ }
+
+ /* Failed to clone (or scan), so we can't
+ * delay the connect. Free everything up and
+ * go ahead with the connect */
+ if (wdev->conn)
+ kfree(wdev->conn->ie);
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+
+ } else {
+ cfg80211_put_bss(bss);
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+ }
+
err = rdev->ops->connect(&rdev->wiphy, dev, connect);
if (err) {
wdev->connect_keys = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
+ wdev->ssid_len = 0;
return err;
}
- memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
- wdev->ssid_len = connect->ssid_len;
-
return 0;
}
}
--
1.6.3.3
^ permalink raw reply related
* [RFC 4/5] orinoco: do WE via cfg80211
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1250640253-18434-1-git-send-email-kilroyd@googlemail.com>
Now that the driver supports both station and ad-hoc modes in cfg80211,
we can point the WE handlers at the cfg80211 versions.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
drivers/net/wireless/orinoco/wext.c | 726 +----------------------------------
1 files changed, 11 insertions(+), 715 deletions(-)
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 7698fdd..264c76f 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -22,67 +22,6 @@
#define MAX_RID_LEN 1024
-/* Helper routine to record keys
- * Do not call from interrupt context */
-static int orinoco_set_key(struct orinoco_private *priv, int index,
- enum orinoco_alg alg, const u8 *key, int key_len,
- const u8 *seq, int seq_len)
-{
- kzfree(priv->keys[index].key);
- kzfree(priv->keys[index].seq);
-
- if (key_len) {
- priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
- if (!priv->keys[index].key)
- goto nomem;
- } else
- priv->keys[index].key = NULL;
-
- if (seq_len) {
- priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
- if (!priv->keys[index].seq)
- goto free_key;
- } else
- priv->keys[index].seq = NULL;
-
- priv->keys[index].key_len = key_len;
- priv->keys[index].seq_len = seq_len;
-
- if (key_len)
- memcpy(priv->keys[index].key, key, key_len);
- if (seq_len)
- memcpy(priv->keys[index].seq, seq, seq_len);
-
- switch (alg) {
- case ORINOCO_ALG_TKIP:
- priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
- break;
-
- case ORINOCO_ALG_WEP:
- priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
- WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
- break;
-
- case ORINOCO_ALG_NONE:
- default:
- priv->keys[index].cipher = 0;
- break;
- }
-
- return 0;
-
-free_key:
- kfree(priv->keys[index].key);
- priv->keys[index].key = NULL;
-
-nomem:
- priv->keys[index].key_len = 0;
- priv->keys[index].seq_len = 0;
- priv->keys[index].cipher = 0;
-
- return -ENOMEM;
-}
-
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
@@ -149,274 +88,6 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* Wireless extensions */
/********************************************************************/
-static int orinoco_ioctl_setwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr,
- char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
- unsigned long flags;
- static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Enable automatic roaming - no sanity checks are needed */
- if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
- memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
- priv->bssid_fixed = 0;
- memset(priv->desired_bssid, 0, ETH_ALEN);
-
- /* "off" means keep existing connection */
- if (ap_addr->sa_data[0] == 0) {
- __orinoco_hw_set_wap(priv);
- err = 0;
- }
- goto out;
- }
-
- if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
- printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
- "support manual roaming\n",
- dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (priv->iw_mode != NL80211_IFTYPE_STATION) {
- printk(KERN_WARNING "%s: Manual roaming supported only in "
- "managed mode\n", dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* Intersil firmware hangs without Desired ESSID */
- if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
- strlen(priv->desired_essid) == 0) {
- printk(KERN_WARNING "%s: Desired ESSID must be set for "
- "manual roaming\n", dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* Finally, enable manual roaming */
- priv->bssid_fixed = 1;
- memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
-
- out:
- orinoco_unlock(priv, &flags);
- return err;
-}
-
-static int orinoco_ioctl_getwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr,
- char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
-
- int err = 0;
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- ap_addr->sa_family = ARPHRD_ETHER;
- err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
-
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_setiwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *keybuf)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- int index = (erq->flags & IW_ENCODE_INDEX) - 1;
- int setindex = priv->tx_key;
- enum orinoco_alg encode_alg = priv->encode_alg;
- int restricted = priv->wep_restrict;
- int err = -EINPROGRESS; /* Call commit handler */
- unsigned long flags;
-
- if (!priv->has_wep)
- return -EOPNOTSUPP;
-
- if (erq->pointer) {
- /* We actually have a key to set - check its length */
- if (erq->length > LARGE_KEY_SIZE)
- return -E2BIG;
-
- if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
- return -E2BIG;
- }
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Clear any TKIP key we have */
- if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
- (void) orinoco_clear_tkip_key(priv, setindex);
-
- if (erq->length > 0) {
- if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
- index = priv->tx_key;
-
- /* Switch on WEP if off */
- if (encode_alg != ORINOCO_ALG_WEP) {
- setindex = index;
- encode_alg = ORINOCO_ALG_WEP;
- }
- } else {
- /* Important note : if the user do "iwconfig eth0 enc off",
- * we will arrive there with an index of -1. This is valid
- * but need to be taken care off... Jean II */
- if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
- if ((index != -1) || (erq->flags == 0)) {
- err = -EINVAL;
- goto out;
- }
- } else {
- /* Set the index : Check that the key is valid */
- if (priv->keys[index].key_len == 0) {
- err = -EINVAL;
- goto out;
- }
- setindex = index;
- }
- }
-
- if (erq->flags & IW_ENCODE_DISABLED)
- encode_alg = ORINOCO_ALG_NONE;
- if (erq->flags & IW_ENCODE_OPEN)
- restricted = 0;
- if (erq->flags & IW_ENCODE_RESTRICTED)
- restricted = 1;
-
- if (erq->pointer && erq->length > 0) {
- err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
- erq->length, NULL, 0);
- }
- priv->tx_key = setindex;
-
- /* Try fast key change if connected and only keys are changed */
- if ((priv->encode_alg == encode_alg) &&
- (priv->wep_restrict == restricted) &&
- netif_carrier_ok(dev)) {
- err = __orinoco_hw_setup_wepkeys(priv);
- /* No need to commit if successful */
- goto out;
- }
-
- priv->encode_alg = encode_alg;
- priv->wep_restrict = restricted;
-
- out:
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_getiwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *keybuf)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- int index = (erq->flags & IW_ENCODE_INDEX) - 1;
- unsigned long flags;
-
- if (!priv->has_wep)
- return -EOPNOTSUPP;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
- index = priv->tx_key;
-
- erq->flags = 0;
- if (!priv->encode_alg)
- erq->flags |= IW_ENCODE_DISABLED;
- erq->flags |= index + 1;
-
- if (priv->wep_restrict)
- erq->flags |= IW_ENCODE_RESTRICTED;
- else
- erq->flags |= IW_ENCODE_OPEN;
-
- erq->length = priv->keys[index].key_len;
-
- memcpy(keybuf, priv->keys[index].key, erq->length);
-
- orinoco_unlock(priv, &flags);
- return 0;
-}
-
-static int orinoco_ioctl_setessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *essidbuf)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- unsigned long flags;
-
- /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
- * anyway... - Jean II */
-
- /* Hum... Should not use Wireless Extension constant (may change),
- * should use our own... - Jean II */
- if (erq->length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
- memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
-
- /* If not ANY, get the new ESSID */
- if (erq->flags)
- memcpy(priv->desired_essid, essidbuf, erq->length);
-
- orinoco_unlock(priv, &flags);
-
- return -EINPROGRESS; /* Call commit handler */
-}
-
-static int orinoco_ioctl_getessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *essidbuf)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- int active;
- int err = 0;
- unsigned long flags;
-
- if (netif_running(dev)) {
- err = orinoco_hw_get_essid(priv, &active, essidbuf);
- if (err < 0)
- return err;
- erq->length = err;
- } else {
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
- memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
- erq->length = strlen(priv->desired_essid);
- orinoco_unlock(priv, &flags);
- }
-
- erq->flags = 1;
-
- return 0;
-}
-
static int orinoco_ioctl_setfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *frq,
@@ -827,379 +498,6 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_set_encodeext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- struct iw_point *encoding = &wrqu->encoding;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int idx, alg = ext->alg, set_key = 1;
- unsigned long flags;
- int err = -EINVAL;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Determine and validate the key index */
- idx = encoding->flags & IW_ENCODE_INDEX;
- if (idx) {
- if ((idx < 1) || (idx > 4))
- goto out;
- idx--;
- } else
- idx = priv->tx_key;
-
- if (encoding->flags & IW_ENCODE_DISABLED)
- alg = IW_ENCODE_ALG_NONE;
-
- if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
- /* Clear any TKIP TX key we had */
- (void) orinoco_clear_tkip_key(priv, priv->tx_key);
- }
-
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
- priv->tx_key = idx;
- set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
- (ext->key_len > 0)) ? 1 : 0;
- }
-
- if (set_key) {
- /* Set the requested key first */
- switch (alg) {
- case IW_ENCODE_ALG_NONE:
- priv->encode_alg = ORINOCO_ALG_NONE;
- err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
- NULL, 0, NULL, 0);
- break;
-
- case IW_ENCODE_ALG_WEP:
- if (ext->key_len <= 0)
- goto out;
-
- priv->encode_alg = ORINOCO_ALG_WEP;
- err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
- ext->key, ext->key_len, NULL, 0);
- break;
-
- case IW_ENCODE_ALG_TKIP:
- {
- u8 *tkip_iv = NULL;
-
- if (!priv->has_wpa ||
- (ext->key_len > sizeof(struct orinoco_tkip_key)))
- goto out;
-
- priv->encode_alg = ORINOCO_ALG_TKIP;
-
- if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- tkip_iv = &ext->rx_seq[0];
-
- err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
- ext->key, ext->key_len, tkip_iv,
- ORINOCO_SEQ_LEN);
-
- err = __orinoco_hw_set_tkip_key(priv, idx,
- ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- priv->keys[idx].key,
- tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
- if (err)
- printk(KERN_ERR "%s: Error %d setting TKIP key"
- "\n", dev->name, err);
-
- goto out;
- }
- default:
- goto out;
- }
- }
- err = -EINPROGRESS;
- out:
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_get_encodeext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- struct iw_point *encoding = &wrqu->encoding;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int idx, max_key_len;
- unsigned long flags;
- int err;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- err = -EINVAL;
- max_key_len = encoding->length - sizeof(*ext);
- if (max_key_len < 0)
- goto out;
-
- idx = encoding->flags & IW_ENCODE_INDEX;
- if (idx) {
- if ((idx < 1) || (idx > 4))
- goto out;
- idx--;
- } else
- idx = priv->tx_key;
-
- encoding->flags = idx + 1;
- memset(ext, 0, sizeof(*ext));
-
- switch (priv->encode_alg) {
- case ORINOCO_ALG_NONE:
- ext->alg = IW_ENCODE_ALG_NONE;
- ext->key_len = 0;
- encoding->flags |= IW_ENCODE_DISABLED;
- break;
- case ORINOCO_ALG_WEP:
- ext->alg = IW_ENCODE_ALG_WEP;
- ext->key_len = min(priv->keys[idx].key_len, max_key_len);
- memcpy(ext->key, priv->keys[idx].key, ext->key_len);
- encoding->flags |= IW_ENCODE_ENABLED;
- break;
- case ORINOCO_ALG_TKIP:
- ext->alg = IW_ENCODE_ALG_TKIP;
- ext->key_len = min(priv->keys[idx].key_len, max_key_len);
- memcpy(ext->key, priv->keys[idx].key, ext->key_len);
- encoding->flags |= IW_ENCODE_ENABLED;
- break;
- }
-
- err = 0;
- out:
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
- struct iw_param *param = &wrqu->param;
- unsigned long flags;
- int ret = -EINPROGRESS;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- switch (param->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_PAIRWISE:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- case IW_AUTH_PRIVACY_INVOKED:
- case IW_AUTH_DROP_UNENCRYPTED:
- /*
- * orinoco does not use these parameters
- */
- break;
-
- case IW_AUTH_KEY_MGMT:
- /* wl_lkm implies value 2 == PSK for Hermes I
- * which ties in with WEXT
- * no other hints tho :(
- */
- priv->key_mgmt = param->value;
- break;
-
- case IW_AUTH_TKIP_COUNTERMEASURES:
- /* When countermeasures are enabled, shut down the
- * card; when disabled, re-enable the card. This must
- * take effect immediately.
- *
- * TODO: Make sure that the EAPOL message is getting
- * out before card disabled
- */
- if (param->value) {
- priv->tkip_cm_active = 1;
- ret = hermes_enable_port(hw, 0);
- } else {
- priv->tkip_cm_active = 0;
- ret = hermes_disable_port(hw, 0);
- }
- break;
-
- case IW_AUTH_80211_AUTH_ALG:
- if (param->value & IW_AUTH_ALG_SHARED_KEY)
- priv->wep_restrict = 1;
- else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
- priv->wep_restrict = 0;
- else
- ret = -EINVAL;
- break;
-
- case IW_AUTH_WPA_ENABLED:
- if (priv->has_wpa) {
- priv->wpa_enabled = param->value ? 1 : 0;
- } else {
- if (param->value)
- ret = -EOPNOTSUPP;
- /* else silently accept disable of WPA */
- priv->wpa_enabled = 0;
- }
- break;
-
- default:
- ret = -EOPNOTSUPP;
- }
-
- orinoco_unlock(priv, &flags);
- return ret;
-}
-
-static int orinoco_ioctl_get_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- struct iw_param *param = &wrqu->param;
- unsigned long flags;
- int ret = 0;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- switch (param->flags & IW_AUTH_INDEX) {
- case IW_AUTH_KEY_MGMT:
- param->value = priv->key_mgmt;
- break;
-
- case IW_AUTH_TKIP_COUNTERMEASURES:
- param->value = priv->tkip_cm_active;
- break;
-
- case IW_AUTH_80211_AUTH_ALG:
- if (priv->wep_restrict)
- param->value = IW_AUTH_ALG_SHARED_KEY;
- else
- param->value = IW_AUTH_ALG_OPEN_SYSTEM;
- break;
-
- case IW_AUTH_WPA_ENABLED:
- param->value = priv->wpa_enabled;
- break;
-
- default:
- ret = -EOPNOTSUPP;
- }
-
- orinoco_unlock(priv, &flags);
- return ret;
-}
-
-static int orinoco_ioctl_set_genie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- u8 *buf;
- unsigned long flags;
-
- /* cut off at IEEE80211_MAX_DATA_LEN */
- if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
- (wrqu->data.length && (extra == NULL)))
- return -EINVAL;
-
- if (wrqu->data.length) {
- buf = kmalloc(wrqu->data.length, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- memcpy(buf, extra, wrqu->data.length);
- } else
- buf = NULL;
-
- if (orinoco_lock(priv, &flags) != 0) {
- kfree(buf);
- return -EBUSY;
- }
-
- kfree(priv->wpa_ie);
- priv->wpa_ie = buf;
- priv->wpa_ie_len = wrqu->data.length;
-
- if (priv->wpa_ie) {
- /* Looks like wl_lkm wants to check the auth alg, and
- * somehow pass it to the firmware.
- * Instead it just calls the key mgmt rid
- * - we do this in set auth.
- */
- }
-
- orinoco_unlock(priv, &flags);
- return 0;
-}
-
-static int orinoco_ioctl_get_genie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- unsigned long flags;
- int err = 0;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
- wrqu->data.length = 0;
- goto out;
- }
-
- if (wrqu->data.length < priv->wpa_ie_len) {
- err = -E2BIG;
- goto out;
- }
-
- wrqu->data.length = priv->wpa_ie_len;
- memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
-
-out:
- orinoco_unlock(priv, &flags);
- return err;
-}
-
-static int orinoco_ioctl_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct orinoco_private *priv = ndev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *)extra;
- unsigned long flags;
- int ret = 0;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- /* silently ignore */
- break;
-
- case IW_MLME_DISASSOC:
-
- ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
- mlme->reason_code);
- break;
-
- default:
- ret = -EOPNOTSUPP;
- }
-
- orinoco_unlock(priv, &flags);
- return ret;
-}
-
static int orinoco_ioctl_getretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rrq,
@@ -1521,12 +819,12 @@ static const iw_handler orinoco_handler[] = {
STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
- STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
- STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
+ STD_IW_HANDLER(SIOCSIWAP, cfg80211_wext_siwap),
+ STD_IW_HANDLER(SIOCGIWAP, cfg80211_wext_giwap),
STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
- STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
- STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
+ STD_IW_HANDLER(SIOCSIWESSID, cfg80211_wext_siwessid),
+ STD_IW_HANDLER(SIOCGIWESSID, cfg80211_wext_giwessid),
STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts),
@@ -1534,17 +832,15 @@ static const iw_handler orinoco_handler[] = {
STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag),
STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag),
STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry),
- STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
- STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
+ STD_IW_HANDLER(SIOCSIWENCODE, cfg80211_wext_siwencode),
+ STD_IW_HANDLER(SIOCGIWENCODE, cfg80211_wext_giwencode),
STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
- STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
- STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
- STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
- STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
- STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
- STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
- STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
+ STD_IW_HANDLER(SIOCSIWGENIE, cfg80211_wext_siwgenie),
+ STD_IW_HANDLER(SIOCSIWMLME, cfg80211_wext_siwmlme),
+ STD_IW_HANDLER(SIOCSIWAUTH, cfg80211_wext_siwauth),
+ STD_IW_HANDLER(SIOCGIWAUTH, cfg80211_wext_giwauth),
+ STD_IW_HANDLER(SIOCSIWENCODEEXT, cfg80211_wext_siwencodeext),
};
--
1.6.3.3
^ permalink raw reply related
* [RFC 3/5] orinoco: implement cfg80211 key manipulation functions
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1250640253-18434-1-git-send-email-kilroyd@googlemail.com>
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
drivers/net/wireless/orinoco/cfg.c | 196 ++++++++++++++++++++++++++++++++++++
1 files changed, 196 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 253cb4e..07775b6 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -493,6 +493,198 @@ static int orinoco_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
return err;
}
+static int orinoco_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, const u8 *mac_addr,
+ struct key_params *params)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long lock;
+ enum orinoco_alg alg = ORINOCO_ALG_NONE;
+ int key_len;
+
+ if (key_index >= ORINOCO_MAX_KEYS)
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ alg = ORINOCO_ALG_WEP;
+
+ if (!priv->has_wep)
+ err = -EOPNOTSUPP;
+
+ if (params->key_len > ORINOCO_MAX_KEY_SIZE)
+ err = -E2BIG;
+ else if (params->key_len > SMALL_KEY_SIZE)
+ key_len = LARGE_KEY_SIZE;
+ else if (params->key_len > 0)
+ key_len = SMALL_KEY_SIZE;
+ else
+ err = -EINVAL;
+
+ break;
+
+ case WLAN_CIPHER_SUITE_TKIP:
+ alg = ORINOCO_ALG_TKIP;
+
+ if (!priv->has_wpa)
+ err = -EOPNOTSUPP;
+ else if (params->key_len < WLAN_KEY_LEN_TKIP)
+ err = -EINVAL;
+
+ key_len = WLAN_KEY_LEN_TKIP;
+ break;
+
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ default:
+ err = -EOPNOTSUPP;
+ }
+
+ if (err)
+ goto out;
+
+ /* Ensure existing keys are of the same cipher suite */
+ orinoco_set_encoding(priv, alg);
+
+ err = orinoco_set_key(priv, key_index, alg,
+ params->key, params->key_len,
+ params->seq, params->seq_len);
+ if (err)
+ goto out;
+
+ if (alg == ORINOCO_ALG_TKIP) {
+ /* If this is a pairwise key, assume it is the transmit key */
+ int set_tx = 0;
+ if (mac_addr) {
+ priv->tx_key = key_index;
+ set_tx = 1;
+ }
+ err = __orinoco_hw_set_tkip_key(priv, key_index, set_tx,
+ priv->keys[key_index].key,
+ priv->keys[key_index].seq,
+ priv->keys[key_index].seq_len,
+ NULL, 0);
+ }
+
+ err = __orinoco_hw_setup_enc(priv);
+
+ out:
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie, struct key_params*))
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ struct key_params params;
+ u8 key[WLAN_KEY_LEN_TKIP];
+ u8 tsc[ORINOCO_SEQ_LEN];
+ unsigned long lock;
+ int err = 0;
+
+ if (key_index >= ORINOCO_MAX_KEYS)
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ /* Take a copy of the key info */
+ memcpy(&key, priv->keys[key_index].key, priv->keys[key_index].key_len);
+
+ params.cipher = priv->keys[key_index].cipher;
+ params.key = &key[0];
+ params.key_len = priv->keys[key_index].key_len;
+
+ if (params.cipher == WLAN_CIPHER_SUITE_TKIP) {
+ /* Populate the current TSC */
+ orinoco_hw_get_tkip_iv(priv, key_index, &tsc[0]);
+ params.seq = &tsc[0];
+ params.seq_len = ORINOCO_SEQ_LEN;
+ } else {
+ params.seq = NULL;
+ params.seq_len = 0;
+ }
+
+ orinoco_unlock(priv, &lock);
+
+ callback(cookie, ¶ms);
+
+ return err;
+}
+
+static int orinoco_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, const u8 *mac_addr)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long lock;
+
+ if (key_index >= ORINOCO_MAX_KEYS)
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ kzfree(priv->keys[key_index].key);
+ kzfree(priv->keys[key_index].seq);
+ priv->keys[key_index].key = NULL;
+ priv->keys[key_index].seq = NULL;
+ priv->keys[key_index].key_len = 0;
+ priv->keys[key_index].seq_len = 0;
+ priv->keys[key_index].cipher = 0;
+
+ if (priv->has_wpa &&
+ priv->keys[key_index].cipher == WLAN_CIPHER_SUITE_TKIP)
+ err = orinoco_clear_tkip_key(priv, key_index);
+
+ err = __orinoco_hw_setup_enc(priv);
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_set_default_key(struct wiphy *wiphy,
+ struct net_device *netdev,
+ u8 key_index)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long lock;
+
+ if (key_index >= ORINOCO_MAX_KEYS)
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ priv->tx_key = key_index;
+
+ if (priv->has_wpa &&
+ priv->keys[key_index].cipher == WLAN_CIPHER_SUITE_TKIP)
+ err = __orinoco_hw_set_tkip_key(priv, key_index, 1,
+ priv->keys[key_index].key,
+ priv->keys[key_index].seq,
+ priv->keys[key_index].seq_len,
+ NULL, 0);
+ else if (priv->encode_alg == ORINOCO_ALG_WEP)
+ err = __orinoco_hw_setup_wepkeys(priv);
+ else
+ err = -EINVAL;
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel,
@@ -501,4 +693,8 @@ const struct cfg80211_ops orinoco_cfg_ops = {
.disconnect = orinoco_disconnect,
.join_ibss = orinoco_join_ibss,
.leave_ibss = orinoco_leave_ibss,
+ .add_key = orinoco_add_key,
+ .get_key = orinoco_get_key,
+ .del_key = orinoco_del_key,
+ .set_default_key = orinoco_set_default_key,
};
--
1.6.3.3
^ permalink raw reply related
* [RFC 2/5] orinoco: add cfg80211 join_ibss and leave_ibss
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1250640253-18434-1-git-send-email-kilroyd@googlemail.com>
Basic ad-hoc support.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
drivers/net/wireless/orinoco/cfg.c | 57 +++++++++++++++++++++++++++++++++++
drivers/net/wireless/orinoco/main.c | 12 +++++++
2 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 09b38e9..253cb4e 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -438,10 +438,67 @@ static int orinoco_disconnect(struct wiphy *wiphy, struct net_device *dev,
return err;
}
+static int orinoco_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ unsigned long lock;
+ int err;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ /* Setup the requested parameters in priv. If the card is not
+ * capable, then the driver will just ignore the settings that
+ * it can't do. */
+
+ err = __orinoco_connect(wiphy, params->channel, params->bssid,
+ params->ssid, params->ssid_len);
+ if (err)
+ goto out;
+
+ /* Ignore information elements and beacon interval */
+
+ /* Enable cfg80211 notification */
+ priv->connect_commanded = 1;
+
+ err = orinoco_commit(priv);
+ out:
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ unsigned long lock;
+ int err;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ /* Do we need to disassociate as well? */
+
+ memset(priv->desired_bssid, 0, ETH_ALEN);
+ memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+
+ /* Disable cfg80211 notification */
+ priv->connect_commanded = 0;
+
+ err = orinoco_commit(priv);
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel,
.scan = orinoco_scan,
.connect = orinoco_connect,
.disconnect = orinoco_disconnect,
+ .join_ibss = orinoco_join_ibss,
+ .leave_ibss = orinoco_leave_ibss,
};
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 5542173..78ef22e 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -1283,7 +1283,19 @@ static void orinoco_send_wevents(struct work_struct *work)
break;
}
break;
+
case NL80211_IFTYPE_ADHOC:
+ switch (linkstatus) {
+ case HERMES_LINKSTATUS_CONNECTED:
+ case HERMES_LINKSTATUS_AP_IN_RANGE:
+ cfg80211_ibss_joined(priv->ndev, bssid, GFP_KERNEL);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
case NL80211_IFTYPE_MONITOR:
default:
break;
--
1.6.3.3
^ permalink raw reply related
* [RFC 1/5] orinoco: add cfg80211 connect and disconnect
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1250640253-18434-1-git-send-email-kilroyd@googlemail.com>
Basic station mode support.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
drivers/net/wireless/orinoco/cfg.c | 244 ++++++++++++++++++++++++++++++++
drivers/net/wireless/orinoco/main.c | 164 ++++++++++++----------
drivers/net/wireless/orinoco/orinoco.h | 1 +
3 files changed, 333 insertions(+), 76 deletions(-)
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 27f2d33..09b38e9 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -196,8 +196,252 @@ static int orinoco_set_channel(struct wiphy *wiphy,
return err;
}
+/* Helper to ensure all keys are valid for the current encoding
+ algorithm */
+static void orinoco_set_encoding(struct orinoco_private *priv,
+ enum orinoco_alg encoding)
+{
+ if (priv->encode_alg &&
+ priv->encode_alg != encoding) {
+ int i;
+
+ for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+ kfree(priv->keys[i].key);
+ kfree(priv->keys[i].seq);
+ priv->keys[i].key = NULL;
+ priv->keys[i].seq = NULL;
+ priv->keys[i].key_len = 0;
+ priv->keys[i].seq_len = 0;
+ priv->keys[i].cipher = 0;
+ }
+
+ if (priv->encode_alg == ORINOCO_ALG_TKIP &&
+ priv->has_wpa) {
+ (void) orinoco_clear_tkip_key(priv, i);
+ (void) orinoco_clear_tkip_key(priv, i);
+ (void) orinoco_clear_tkip_key(priv, i);
+ (void) orinoco_clear_tkip_key(priv, i);
+ } else if (priv->encode_alg == ORINOCO_ALG_WEP)
+ __orinoco_hw_setup_wepkeys(priv);
+ }
+ priv->encode_alg = encoding;
+}
+
+/* Helper routine to record keys
+ * Do not call from interrupt context */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+ enum orinoco_alg alg, const u8 *key, int key_len,
+ const u8 *seq, int seq_len)
+{
+ kzfree(priv->keys[index].key);
+ kzfree(priv->keys[index].seq);
+
+ if (key_len) {
+ priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+ if (!priv->keys[index].key)
+ goto nomem;
+ } else
+ priv->keys[index].key = NULL;
+
+ if (seq_len) {
+ priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+ if (!priv->keys[index].seq)
+ goto free_key;
+ } else
+ priv->keys[index].seq = NULL;
+
+ priv->keys[index].key_len = key_len;
+ priv->keys[index].seq_len = seq_len;
+
+ if (key_len)
+ memcpy(priv->keys[index].key, key, key_len);
+ if (seq_len)
+ memcpy(priv->keys[index].seq, seq, seq_len);
+
+
+ switch (alg) {
+ case ORINOCO_ALG_TKIP:
+ priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+
+ case ORINOCO_ALG_WEP:
+ priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+ WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+ break;
+
+ case ORINOCO_ALG_NONE:
+ default:
+ priv->keys[index].cipher = 0;
+ break;
+ }
+
+ return 0;
+
+free_key:
+ kfree(priv->keys[index].key);
+ priv->keys[index].key = NULL;
+
+nomem:
+ priv->keys[index].key_len = 0;
+ priv->keys[index].seq_len = 0;
+ priv->keys[index].cipher = 0;
+
+ return -ENOMEM;
+}
+
+/* Setup channel, SSID and BSSID */
+static int __orinoco_connect(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid, const u8 *ssid,
+ u8 ssid_len)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+
+ if (channel) {
+ int chan;
+
+ chan = ieee80211_freq_to_dsss_chan(channel->center_freq);
+
+ if ((chan > 0) && (chan < NUM_CHANNELS) &&
+ (priv->channel_mask & (1 << chan)))
+ priv->channel = chan;
+ }
+
+ memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+ if (ssid)
+ memcpy(priv->desired_essid, ssid, ssid_len);
+
+ if (bssid) {
+ /* Intersil firmware hangs if you try to roam manually
+ * without an SSID set. We should always get one in
+ * this call, but just check.
+ */
+ BUG_ON(ssid_len == 0);
+
+ memcpy(priv->desired_bssid, bssid, ETH_ALEN);
+ priv->bssid_fixed = 1;
+ } else {
+ memset(priv->desired_bssid, 0, ETH_ALEN);
+ priv->bssid_fixed = 0;
+ }
+
+ return 0;
+}
+
+static int orinoco_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ enum orinoco_alg encode_alg;
+ unsigned long lock;
+ int err;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ /* Setup the requested parameters in priv. If the card is not
+ * capable, then the driver will just ignore the settings that
+ * it can't do. */
+ err = __orinoco_connect(wiphy, sme->channel, sme->bssid,
+ sme->ssid, sme->ssid_len);
+ if (err)
+ goto out;
+
+ switch (sme->auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ priv->wep_restrict = 0;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ priv->wep_restrict = 1;
+ break;
+ default:
+ /* Can't handle anything else */
+ err = -EINVAL;
+ goto out;
+ }
+
+ switch (sme->crypto.cipher_group) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ encode_alg = ORINOCO_ALG_TKIP;
+ priv->wpa_enabled = 1;
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ encode_alg = ORINOCO_ALG_WEP;
+ priv->wpa_enabled = 0;
+ break;
+
+ default:
+ encode_alg = ORINOCO_ALG_NONE;
+ priv->wpa_enabled = 0;
+ }
+
+ orinoco_set_encoding(priv, encode_alg);
+
+ /* What are we supposed to do with multiple AKM suites? */
+ if (sme->crypto.n_akm_suites > 0)
+ priv->key_mgmt = sme->crypto.akm_suites[0] & 7;
+
+ /* Finally, set WEP key */
+ if (encode_alg == ORINOCO_ALG_WEP) {
+ err = orinoco_set_key(priv, sme->key_idx, encode_alg,
+ &sme->key[0], sme->key_len, NULL, 0);
+ if (err)
+ goto out;
+
+ priv->tx_key = sme->key_idx;
+ }
+
+ /* Enable cfg80211 notification */
+ priv->connect_commanded = 1;
+
+ err = orinoco_commit(priv);
+
+out:
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ unsigned long lock;
+ u8 addr[ETH_ALEN];
+ int err;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ memset(priv->desired_bssid, 0, ETH_ALEN);
+ memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+
+ err = orinoco_hw_get_current_bssid(priv, &addr[0]);
+
+ if (!err) {
+ err = orinoco_hw_disassociate(priv, &addr[0],
+ reason_code);
+ }
+
+ priv->wpa_enabled = 0;
+
+ /* Disable cfg80211 notification */
+ priv->connect_commanded = 0;
+
+ if (err)
+ err = orinoco_commit(priv);
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel,
.scan = orinoco_scan,
+ .connect = orinoco_connect,
+ .disconnect = orinoco_disconnect,
};
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 2c7dc65..5542173 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -1188,98 +1188,109 @@ static void orinoco_join_ap(struct work_struct *work)
kfree(buf);
}
-/* Send new BSSID to userspace */
-static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
-{
- struct net_device *dev = priv->ndev;
- struct hermes *hw = &priv->hw;
- union iwreq_data wrqu;
- int err;
-
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
- ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
- if (err != 0)
- return;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- /* Send event to user space */
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
+static void orinoco_send_wevents(struct work_struct *work)
{
- struct net_device *dev = priv->ndev;
- struct hermes *hw = &priv->hw;
- union iwreq_data wrqu;
+ struct orinoco_private *priv =
+ container_of(work, struct orinoco_private, wevent_work);
+ hermes_t *hw = &priv->hw;
+ unsigned long flags;
+ u8 req_buf[88];
+ u8 resp_buf[88];
+ u8 bssid[ETH_ALEN];
+ size_t req_len = 0;
+ size_t resp_len = 0;
+ u8 *req_ie = NULL;
+ u8 *resp_ie = NULL;
+ enum nl80211_iftype iw_mode;
+ u16 linkstatus;
int err;
- u8 buf[88];
- u8 *ie;
- if (!priv->has_wpa)
+ if (orinoco_lock(priv, &flags) != 0)
return;
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
- sizeof(buf), NULL, &buf);
- if (err != 0)
- return;
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+ ETH_ALEN, NULL, &bssid[0]);
+ if (err)
+ goto out;
- ie = orinoco_get_wpa_ie(buf, sizeof(buf));
- if (ie) {
- int rem = sizeof(buf) - (ie - &buf[0]);
- wrqu.data.length = ie[1] + 2;
- if (wrqu.data.length > rem)
- wrqu.data.length = rem;
+ if (priv->has_wpa) {
+ err = hermes_read_ltv(hw, USER_BAP,
+ HERMES_RID_CURRENT_ASSOC_REQ_INFO,
+ sizeof(req_buf), NULL, &req_buf);
+ if (!err) {
+ req_ie = orinoco_get_wpa_ie(req_buf,
+ sizeof(req_buf));
+ if (req_ie) {
+ int rem = sizeof(req_buf) -
+ (req_ie - &req_buf[0]);
+ req_len = req_ie[1] + 2;
+ if (req_len > rem)
+ req_len = rem;
+ }
+ }
- if (wrqu.data.length)
- /* Send event to user space */
- wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
+ err = hermes_read_ltv(hw, USER_BAP,
+ HERMES_RID_CURRENT_ASSOC_RESP_INFO,
+ sizeof(resp_buf), NULL, &resp_buf);
+ if (!err) {
+ resp_ie = orinoco_get_wpa_ie(resp_buf,
+ sizeof(resp_buf));
+ if (resp_ie) {
+ int rem = sizeof(resp_buf) -
+ (resp_ie - &resp_buf[0]);
+ resp_len = resp_ie[1] + 2;
+ if (resp_len > rem)
+ resp_len = rem;
+ }
+ }
}
-}
-
-static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
-{
- struct net_device *dev = priv->ndev;
- struct hermes *hw = &priv->hw;
- union iwreq_data wrqu;
- int err;
- u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
- u8 *ie;
- if (!priv->has_wpa)
- return;
+ iw_mode = priv->iw_mode;
+ linkstatus = priv->last_linkstatus;
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
- sizeof(buf), NULL, &buf);
- if (err != 0)
- return;
+ if (!priv->connect_commanded)
+ goto out;
- ie = orinoco_get_wpa_ie(buf, sizeof(buf));
- if (ie) {
- int rem = sizeof(buf) - (ie - &buf[0]);
- wrqu.data.length = ie[1] + 2;
- if (wrqu.data.length > rem)
- wrqu.data.length = rem;
+ orinoco_unlock(priv, &flags);
- if (wrqu.data.length)
- /* Send event to user space */
- wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
- }
-}
+ switch (iw_mode) {
+ case NL80211_IFTYPE_STATION:
-static void orinoco_send_wevents(struct work_struct *work)
-{
- struct orinoco_private *priv =
- container_of(work, struct orinoco_private, wevent_work);
- unsigned long flags;
+ switch (linkstatus) {
+ case HERMES_LINKSTATUS_CONNECTED:
+ case HERMES_LINKSTATUS_AP_IN_RANGE:
+ cfg80211_connect_result(priv->ndev, bssid,
+ req_ie, req_len,
+ resp_ie, resp_len,
+ WLAN_STATUS_SUCCESS,
+ GFP_KERNEL);
+ break;
- if (orinoco_lock(priv, &flags) != 0)
- return;
+ case HERMES_LINKSTATUS_DISCONNECTED:
+ case HERMES_LINKSTATUS_NOT_CONNECTED:
+ case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
+ case HERMES_LINKSTATUS_AP_CHANGE:
+ cfg80211_roamed(priv->ndev, bssid, req_ie, req_len,
+ resp_ie, resp_len, GFP_KERNEL);
+ break;
- orinoco_send_assocreqie_wevent(priv);
- orinoco_send_assocrespie_wevent(priv);
- orinoco_send_bssid_wevent(priv);
+ case HERMES_LINKSTATUS_ASSOC_FAILED:
+ cfg80211_connect_result(priv->ndev, bssid,
+ req_ie, req_len,
+ resp_ie, resp_len,
+ WLAN_STATUS_ASSOC_DENIED_UNSPEC,
+ GFP_KERNEL);
+ break;
+ }
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MONITOR:
+ default:
+ break;
+ }
+ return;
+ out:
orinoco_unlock(priv, &flags);
}
@@ -2050,6 +2061,7 @@ int orinoco_init(struct orinoco_private *priv)
set_port_type(priv);
priv->channel = 0; /* use firmware default */
+ priv->connect_commanded = 0;
priv->promiscuous = 0;
priv->encode_alg = ORINOCO_ALG_NONE;
priv->tx_key = 0;
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 9ac6f1d..57ce581 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -78,6 +78,7 @@ struct orinoco_private {
/* driver state */
int open;
+ int connect_commanded;
u16 last_linkstatus;
struct work_struct join_work;
struct work_struct wevent_work;
--
1.6.3.3
^ permalink raw reply related
* [RFC v2 0/5] orinoco: use cfg80211 for key manipulation
From: David Kilroy @ 2009-08-19 0:04 UTC (permalink / raw)
To: linux-wireless; +Cc: orinoco-devel, David Kilroy
This series basically works (at least after the last patch is applied)
with wpa_supplicant in wext mode.
I had tested with wpa_supplicant in nl80211 mode, but hadn't realised
it wasn't using connect - I'll need to pick up Zhu Yis' patch and redo
some testing.
Anyway, the nl80211 interface has a small hole which patch 5 partially
papers over. I'm not that happy with the way it hijacks the AUTH/ASSOC
state machine, but it works.
Other outstanding issues:
- It looks like I haven't quite got the connect_roamed callback right:
I've got a WARNING I need to investigate in my logs
- On disconnecting and reconnecting the card I have to restart
wpa_supplicant for things to work. I'm guessing I have to look at
driver shutdown, and ensure we send a disconnected event.
Dave.
---
David Kilroy (5):
orinoco: add cfg80211 connect and disconnect
orinoco: add cfg80211 join_ibss and leave_ibss
orinoco: implement cfg80211 key manipulation functions
orinoco: do WE via cfg80211
cfg80211: scan before connect if we don't have the bss
drivers/net/wireless/orinoco/cfg.c | 497 ++++++++++++++++++++++
drivers/net/wireless/orinoco/main.c | 172 +++++----
drivers/net/wireless/orinoco/orinoco.h | 1 +
drivers/net/wireless/orinoco/wext.c | 726 +-------------------------------
net/wireless/sme.c | 150 +++++--
5 files changed, 717 insertions(+), 829 deletions(-)
^ permalink raw reply
* [PATCH] orinoco: remove spare whitespace
From: David Kilroy @ 2009-08-18 23:44 UTC (permalink / raw)
To: linux-wireless; +Cc: David Kilroy
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
Noticed while investigating false positive sparse complaint.
Really trivial.
---
drivers/net/wireless/orinoco/wext.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 3e56f76..7698fdd 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -1291,7 +1291,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev,
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- priv->ibss_port = val ;
+ priv->ibss_port = val;
/* Actually update the mode we are using */
set_port_type(priv);
--
1.6.3.3
^ permalink raw reply related
* [PATCH] cfg80211: fix leaks of wdev->conn->ie
From: David Kilroy @ 2009-08-18 23:43 UTC (permalink / raw)
To: linux-wireless; +Cc: David Kilroy, Johannes Berg
This only occurs in the following error situations:
- driver calls connect_result with failure
- error scheduling authentication on connect
- error initiating scan (to get BSSID and channel) on
connect
- userspace calls disconnect while in the SCANNING or
SCAN_AGAIN states
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
---
I came across this while looking at my orinoco scanning issue. It's
possible I'm wrong...
---
net/wireless/sme.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6fb6a70..9ddc00e 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -395,6 +395,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
if (status != WLAN_STATUS_SUCCESS) {
wdev->sme_state = CFG80211_SME_IDLE;
+ if (wdev->conn)
+ kfree(wdev->conn->ie);
kfree(wdev->conn);
wdev->conn = NULL;
kfree(wdev->connect_keys);
@@ -779,6 +781,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
}
}
if (err) {
+ kfree(wdev->conn->ie);
kfree(wdev->conn);
wdev->conn = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
@@ -848,6 +851,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
(wdev->conn->state == CFG80211_CONN_SCANNING ||
wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
wdev->sme_state = CFG80211_SME_IDLE;
+ kfree(wdev->conn->ie);
kfree(wdev->conn);
wdev->conn = NULL;
wdev->ssid_len = 0;
--
1.6.3.3
^ permalink raw reply related
* Re: [ANN] b43 LP-PHY support (BCM4310/4312/4315) now ready for testing!
From: Luis R. Rodriguez @ 2009-08-18 23:42 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Broadcom Wireless, linux-wireless, linux-kernel
In-Reply-To: <43e72e890908181641s2455e7f1me9b4d3bc277f197e@mail.gmail.com>
2009/8/18 Luis R. Rodriguez <mcgrof@gmail.com>:
> 2009/8/18 Gábor Stefanik <netrolller.3d@gmail.com>:
>> Hello World!
>>
>> Great news for Broadcom BCM4310/4312/4315 (PCI 14e4:4315) users:
>> LP-PHY support is now at the point where it can be tested for functionality!
>
> Hey great stuff :)
>
>> There are still problems with channel switching (a few patches ago,
>> only 802.11b/g channels 7 and 8 were working - no tests have been
>> performed since then) & TX is untested, but Larry has reported that he
>> can get scan results from channels 7 and 8. He doesn't have any AP on
>> these channels, so can't test if association works, but it should be
>> working too. It's also possible that recent patches have fixed the
>> channel switching bug, as the codepaths for channel switching have
>> been touched extensively, probably fixing a major miscalculation issue
>> ("Qdiv roundup" was completely wrong).
>>
>> So, go ahead, give it a try, and let's rock!
>>
>> Note that the code in wireless-testing is enough to start testing,
>> however it's recommended that you apply the following 2 pending fixes:
>> http://marc.info/?l=linux-wireless&m=125061590101156&w=2 and
>> http://marc.info/?l=linux-wireless&m=125062611720517&w=2
>>
>> Tomorrow's compat-wireless tarball, together with the above patches,
>> should also be good for testing. Not sure about today's tarball.
>
> Except CONFIG_B43_PHY_LP was not enabled on compat-wireless. But now
> it is. I kicked the cronjob and enabled CONFIG_B43_PHY_LP on
> config.mk, please report any issues.
>
> http://wireless.kernel.org/en/users/Download/
Oh and I forgot the release info:
Origin remote URL:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
git-describe for wireless-testing.git says: v2.6.31-rc6-31586-g80289f0
This is a bleeding edge compat-wireless release based on: master-2009-08-18
This is compat-release: master-2009-08-18
Luis
^ permalink raw reply
* Re: [ANN] b43 LP-PHY support (BCM4310/4312/4315) now ready for testing!
From: Luis R. Rodriguez @ 2009-08-18 23:41 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Broadcom Wireless, linux-wireless, linux-kernel
In-Reply-To: <69e28c910908181329r4b6b7cc8w3c9c0d79dda3730c@mail.gmail.com>
2009/8/18 Gábor Stefanik <netrolller.3d@gmail.com>:
> Hello World!
>
> Great news for Broadcom BCM4310/4312/4315 (PCI 14e4:4315) users:
> LP-PHY support is now at the point where it can be tested for functionality!
Hey great stuff :)
> There are still problems with channel switching (a few patches ago,
> only 802.11b/g channels 7 and 8 were working - no tests have been
> performed since then) & TX is untested, but Larry has reported that he
> can get scan results from channels 7 and 8. He doesn't have any AP on
> these channels, so can't test if association works, but it should be
> working too. It's also possible that recent patches have fixed the
> channel switching bug, as the codepaths for channel switching have
> been touched extensively, probably fixing a major miscalculation issue
> ("Qdiv roundup" was completely wrong).
>
> So, go ahead, give it a try, and let's rock!
>
> Note that the code in wireless-testing is enough to start testing,
> however it's recommended that you apply the following 2 pending fixes:
> http://marc.info/?l=linux-wireless&m=125061590101156&w=2 and
> http://marc.info/?l=linux-wireless&m=125062611720517&w=2
>
> Tomorrow's compat-wireless tarball, together with the above patches,
> should also be good for testing. Not sure about today's tarball.
Except CONFIG_B43_PHY_LP was not enabled on compat-wireless. But now
it is. I kicked the cronjob and enabled CONFIG_B43_PHY_LP on
config.mk, please report any issues.
http://wireless.kernel.org/en/users/Download/
BTW I think it would be nice for those users looking only for b43 for
us to update scripts/driver-select to have b43 as just one driver
option. Should be easy to add but I don't have time right now. Patch
is greatly welcomed though.
Luis
^ permalink raw reply
* Re: [PATCH] Don't build PCMCIA modules when PCMCIA isn't present
From: Luis R. Rodriguez @ 2009-08-18 23:34 UTC (permalink / raw)
To: Philip A. Prindeville; +Cc: John Linville, wireless, Pavel Roskin
In-Reply-To: <4A864BB1.8020307@redfish-solutions.com>
On Fri, Aug 14, 2009 at 10:46 PM, Philip A.
Prindeville<philipp@redfish-solutions.com> wrote:
> From: Philip A Prindeville <philipp@redfish-solutions.com>
>
> If you're building for a platform that has (for example) no PCMCIA/
> Cardbus, then having a single knob to turn to disable this is a
> major win. Especially if more devices get add later that are
> PCMCIA-based.
Applied, thanks Phillip.
Luis
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-08-18
From: David Miller @ 2009-08-18 23:29 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090818151436.GA2768@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Tue, 18 Aug 2009 11:14:37 -0400
> Dave,
>
> Two more for 2.6.31...
>
> The one from Johannes is actually already in net-next-2.6, but it has
> since been reported to cause a possible irq lock inversion dependency in
> 2.6.31-rc6, as described here:
>
> http://marc.info/?l=linux-wireless&m=125052198303537&w=2
>
> The one from me fixes a minor bounds checking problem in orinoco, as
> reported by Dan Carpenter. It is simple and obvious.
Pulled, thanks John.
^ permalink raw reply
* [PATCH] ar9170: refactor configure_filter
From: Christian Lamparter @ 2009-08-18 23:26 UTC (permalink / raw)
To: linux-wireless; +Cc: John Linville
Thanks to "mac80211: allow configure_filter callback to sleep",
we no longer have to defer the work to the workqueue.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
---
please test!
---
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index e6c3ee3..9c4d43c 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -184,10 +184,8 @@ struct ar9170 {
bool disable_offload;
/* filter settings */
- struct work_struct filter_config_work;
- u64 cur_mc_hash, want_mc_hash;
- u32 cur_filter, want_filter;
- unsigned long filter_changed;
+ u64 cur_mc_hash;
+ u32 cur_filter;
unsigned int filter_state;
bool sniffer_enabled;
@@ -261,10 +259,6 @@ struct ar9170_tx_info {
#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED)
#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE)
-#define AR9170_FILTER_CHANGED_MODE BIT(0)
-#define AR9170_FILTER_CHANGED_MULTICAST BIT(1)
-#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2)
-
/* exported interface */
void *ar9170_alloc(size_t priv_size);
int ar9170_register(struct ar9170 *ar, struct device *pdev);
@@ -278,8 +272,8 @@ int ar9170_nag_limiter(struct ar9170 *ar);
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
int ar9170_init_mac(struct ar9170 *ar);
int ar9170_set_qos(struct ar9170 *ar);
-int ar9170_update_multicast(struct ar9170 *ar);
-int ar9170_update_frame_filter(struct ar9170 *ar);
+int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
+int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter);
int ar9170_set_operating_mode(struct ar9170 *ar);
int ar9170_set_beacon_timers(struct ar9170 *ar);
int ar9170_set_dyn_sifs_ack(struct ar9170 *ar);
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c
index d9f1f46..6004936 100644
--- a/drivers/net/wireless/ath/ar9170/mac.c
+++ b/drivers/net/wireless/ath/ar9170/mac.c
@@ -238,39 +238,31 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
return ar9170_regwrite_result();
}
-int ar9170_update_multicast(struct ar9170 *ar)
+int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
{
int err;
ar9170_regwrite_begin(ar);
- ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H,
- ar->want_mc_hash >> 32);
- ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
- ar->want_mc_hash);
-
+ ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
+ ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
ar9170_regwrite_finish();
err = ar9170_regwrite_result();
-
if (err)
return err;
- ar->cur_mc_hash = ar->want_mc_hash;
-
+ ar->cur_mc_hash = mc_hash;
return 0;
}
-int ar9170_update_frame_filter(struct ar9170 *ar)
+int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter)
{
int err;
- err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER,
- ar->want_filter);
-
+ err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter);
if (err)
return err;
- ar->cur_filter = ar->want_filter;
-
+ ar->cur_filter = filter;
return 0;
}
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 6a9462e..0d91f43 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1232,8 +1232,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
mutex_lock(&ar->mutex);
- ar->filter_changed = 0;
-
/* reinitialize queues statistics */
memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
for (i = 0; i < __AR9170_NUM_TXQ; i++)
@@ -1296,7 +1294,6 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
#ifdef CONFIG_AR9170_LEDS
cancel_delayed_work_sync(&ar->led_work);
#endif
- cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work);
mutex_lock(&ar->mutex);
@@ -1973,8 +1970,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
}
ar->cur_filter = 0;
- ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS;
- err = ar9170_update_frame_filter(ar);
+ err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS);
if (err)
goto unlock;
@@ -1992,8 +1988,7 @@ static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->mutex);
ar->vif = NULL;
- ar->want_filter = 0;
- ar9170_update_frame_filter(ar);
+ ar9170_update_frame_filter(ar, 0);
ar9170_set_beacon_timers(ar);
dev_kfree_skb(ar->beacon);
ar->beacon = NULL;
@@ -2065,41 +2060,6 @@ out:
return err;
}
-static void ar9170_set_filters(struct work_struct *work)
-{
- struct ar9170 *ar = container_of(work, struct ar9170,
- filter_config_work);
- int err;
-
- if (unlikely(!IS_STARTED(ar)))
- return ;
-
- mutex_lock(&ar->mutex);
- if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE,
- &ar->filter_changed)) {
- err = ar9170_set_operating_mode(ar);
- if (err)
- goto unlock;
- }
-
- if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST,
- &ar->filter_changed)) {
- err = ar9170_update_multicast(ar);
- if (err)
- goto unlock;
- }
-
- if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
- &ar->filter_changed)) {
- err = ar9170_update_frame_filter(ar);
- if (err)
- goto unlock;
- }
-
-unlock:
- mutex_unlock(&ar->mutex);
-}
-
static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
struct dev_addr_list *mclist)
{
@@ -2126,6 +2086,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
{
struct ar9170 *ar = hw->priv;
+ if (unlikely(!IS_STARTED(ar)))
+ return ;
+
+ mutex_lock(&ar->mutex);
+
/* mask supported flags */
*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
@@ -2136,12 +2101,10 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
*/
if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
- multicast = ~0ULL;
+ multicast = ~0ULL;
- if (multicast != ar->want_mc_hash) {
- ar->want_mc_hash = multicast;
- set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed);
- }
+ if (multicast != ar->cur_mc_hash)
+ ar9170_update_multicast(ar, multicast);
if (changed_flags & FIF_CONTROL) {
u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
@@ -2152,24 +2115,21 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
AR9170_MAC_REG_FTF_CFE_ACK;
if (*new_flags & FIF_CONTROL)
- ar->want_filter = ar->cur_filter | filter;
+ filter |= ar->cur_filter;
else
- ar->want_filter = ar->cur_filter & ~filter;
+ filter &= (~ar->cur_filter);
- set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
- &ar->filter_changed);
+ ar9170_update_frame_filter(ar, filter);
}
if (changed_flags & FIF_PROMISC_IN_BSS) {
ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
- set_bit(AR9170_FILTER_CHANGED_MODE,
- &ar->filter_changed);
+ ar9170_set_operating_mode(ar);
}
- if (likely(IS_STARTED(ar)))
- ieee80211_queue_work(ar->hw, &ar->filter_config_work);
+ mutex_unlock(&ar->mutex);
}
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -2423,9 +2384,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
default:
break;
}
-
- if (IS_STARTED(ar) && ar->filter_changed)
- ieee80211_queue_work(ar->hw, &ar->filter_config_work);
}
static int ar9170_get_stats(struct ieee80211_hw *hw,
@@ -2596,7 +2554,6 @@ void *ar9170_alloc(size_t priv_size)
skb_queue_head_init(&ar->tx_pending[i]);
}
ar9170_rx_reset_rx_mpdu(ar);
- INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
INIT_LIST_HEAD(&ar->tx_ampdu_list);
^ permalink raw reply related
* bug? sme.c:610 __cfg80211_disconnected
From: ASIC Felix @ 2009-08-18 22:14 UTC (permalink / raw)
To: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 375 bytes --]
Hi,
found three of these in dmesg, wireless-testing kernel master-2009-08-18
wlan0: deauthenticating by local choice (reason=3)
------------[ cut here ]------------
WARNING: at net/wireless/sme.c:610 __cfg80211_disconnected+0x1bc/0x210
[cfg80211]()
Hardware name: 1875DLU
deauth failed: -67
Any ideas? Seems relatively recent, complete trace in attachment.
Cheers,
Felix
[-- Attachment #2: dmesg_sme.txt --]
[-- Type: text/plain, Size: 5064 bytes --]
th9k: RX filter 0x0 bssid 00:0b:85:6f:20:8c aid 0x0
ath9k: BSS Changed PREAMBLE 1
ath9k: BSS Changed ASSOC 1
ath9k: Bss Info ASSOC 13, bssid: 00:0b:85:6f:20:8c
ath9k: Set HW Key
ath9k: Set HW Key
ath9k: Set HW RX filter: 0x0
ath9k: Set HW RX filter: 0x0
ath9k: Set HW RX filter: 0x0
ath9k: Set HW RX filter: 0x0
ath9k: Set HW RX filter: 0x0
ath9k: Set HW RX filter: 0x0
ath9k: Set HW Key
ath9k: Set HW Key
ath9k: Set HW Key
ath9k: Set HW Key
wlan0: deauthenticated from 00:0b:85:6f:20:8c (Reason: 1)
ath9k: Configure tx [queue/halq] [0/3], aifs: 2, cw_min: 3, cw_max: 7, txop: 47
ath9k: Configure tx [queue/halq] [1/2], aifs: 2, cw_min: 7, cw_max: 15, txop: 94
ath9k: Configure tx [queue/halq] [2/1], aifs: 3, cw_min: 15, cw_max: 1023, txop: 0
ath9k: Configure tx [queue/halq] [3/0], aifs: 7, cw_min: 15, cw_max: 1023, txop: 0
ath9k: BSS Changed PREAMBLE 0
ath9k: BSS Changed CTS PROT 0
ath9k: BSS Changed ASSOC 0
ath9k: Bss Info DISASSOC
ath9k: Set HW Key
wlan0: deauthenticating by local choice (reason=3)
------------[ cut here ]------------
WARNING: at net/wireless/sme.c:610 __cfg80211_disconnected+0x1bc/0x210 [cfg80211]()
Hardware name: 1875DLU
deauth failed: -67
Modules linked in: xt_time xt_connlimit xt_realm iptable_raw xt_comment ipt_ULOG ipt_REJECT ipt_REDIRECT ipt_NETMAP ipt_MASQUERADE ipt_LOG ipt_ECN ipt_ecn ipt_ah ipt_addrtype nf_nat_tftp nf_nat_snmp_basic nf_nat_sip nf_nat_pptp nf_nat_proto_gre nf_nat_irc nf_nat_h323 nf_nat_ftp nf_nat_amanda ts_kmp nf_conntrack_amanda nf_conntrack_tftp nf_conntrack_sip nf_conntrack_pptp nf_conntrack_proto_gre nf_conntrack_netlink nf_conntrack_netbios_ns nf_conntrack_irc nf_conntrack_h323 nf_conntrack_ftp xt_tcpmss xt_recent xt_pkttype xt_physdev xt_owner xt_NFQUEUE xt_NFLOG nfnetlink_log xt_multiport xt_MARK xt_mark xt_mac xt_limit xt_length xt_iprange xt_helper xt_hashlimit xt_DSCP xt_dscp xt_dccp xt_conntrack xt_CONNMARK xt_connmark xt_CLASSIFY xt_tcpudp xt_state iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_conntrack aes_i586 aes_generic iptable_mangle nfnetlink iptable_filter ip_tables x_tables i915 drm i2c_algo_bit af_packet bridge stp llc bnep sco rfcomm l2cap bluetooth ipv6 binfmt_misc loop fuse cpufreq_ondemand cpufreq_conservative cpufreq_powersave acpi_cpufreq freq_table snd_intel8x0 arc4 snd_ac97_codec ac97_bus ecb snd_seq_dummy ath9k mac80211 snd_seq_oss snd_seq_midi_event ath cfg80211 snd_seq snd_seq_device snd_pcm_oss snd_pcm snd_timer snd_mixer_oss thinkpad_acpi tg3 processor intel_agp snd ac soundcore thermal rfkill led_class button sg joydev iTCO_wdt iTCO_vendor_support ehci_hcd video output i2c_i801 i2c_core libphy yenta_socket rsrc_nonstatic pcmcia_core snd_page_alloc battery agpgart nvram nsc_ircc irda pcspkr sr_mod evdev rtc_cmos uhci_hcd crc_ccitt usbcore ata_generic ide_pci_generic ide_gd_mod ide_core pata_acpi ata_piix ahci libata sd_mod scsi_mod crc_t10dif ext3 jbd
Pid: 1186, comm: phy0 Tainted: G M 2.6.31-rc6-wl-mnbStrip-31586-g80289f0 #65
Call Trace:
[<f82b56ac>] ? __cfg80211_disconnected+0x1bc/0x210 [cfg80211]
[<f82b56ac>] ? __cfg80211_disconnected+0x1bc/0x210 [cfg80211]
[<c013c53c>] warn_slowpath_common+0x6c/0xc0
[<f82b56ac>] ? __cfg80211_disconnected+0x1bc/0x210 [cfg80211]
[<c013c5d6>] warn_slowpath_fmt+0x26/0x30
[<f82b56ac>] __cfg80211_disconnected+0x1bc/0x210 [cfg80211]
[<f82b1bf1>] ? nl80211_send_deauth+0x21/0x30 [cfg80211]
[<f82b2dfc>] __cfg80211_send_deauth+0x21c/0x260 [cfg80211]
[<f83d02c0>] ? ieee80211_set_disassoc+0x180/0x1e0 [mac80211]
[<f82b2e9e>] cfg80211_send_deauth+0x5e/0x70 [cfg80211]
[<f83d1feb>] ieee80211_sta_work+0xa0b/0x1850 [mac80211]
[<c01412d8>] ? tasklet_action+0x58/0xc0
[<c017d988>] ? handle_IRQ_event+0x58/0x140
[<c011bf3e>] ? ack_apic_level+0x7e/0x270
[<c01300c0>] ? rq_online_rt+0x50/0x70
[<c0138745>] ? dequeue_task_fair+0x295/0x2a0
[<c0128a2e>] ? dequeue_task+0x10e/0x160
[<c010256a>] ? __switch_to+0xba/0x1a0
[<c0133296>] ? finish_task_switch+0x56/0xc0
[<c03a9af4>] ? schedule+0x4a4/0xa50
[<c015377a>] ? prepare_to_wait+0x3a/0x70
[<c014edd1>] worker_thread+0x141/0x210
[<f83d15e0>] ? ieee80211_sta_work+0x0/0x1850 [mac80211]
[<c0153530>] ? autoremove_wake_function+0x0/0x50
[<c014ec90>] ? worker_thread+0x0/0x210
[<c01531dc>] kthread+0x7c/0x90
[<c0153160>] ? kthread+0x0/0x90
[<c0104657>] kernel_thread_helper+0x7/0x10
---[ end trace fbfa3ea19c5aff5f ]---
ath9k: Set HW Key
ath9k: Set HW RX filter: 0x10
ath9k: Set channel: 2412 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2462 MHz) -> (2412 MHz), chanwidth: 0
ath9k: Set channel: 2417 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2412 MHz) -> (2417 MHz), chanwidth: 0
ath9k: Set channel: 2422 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2417 MHz) -> (2422 MHz), chanwidth: 0
ath9k: Set channel: 2427 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2422 MHz) -> (2427 MHz), chanwidth: 0
ath9k: Set channel: 2432 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2427 MHz) -> (2432 MHz), chanwidth: 0
ath9k: Set channel: 2437 MHz
ath9k: tx chmask: 1, rx chmask: 1
ath9k: (2432 MHz) -> (2437 MHz), chanwidth: 0
^ permalink raw reply
* Re: [PATCH 2/3] Add rfkill support to compal-laptop
From: Mario Limonciello @ 2009-08-18 22:00 UTC (permalink / raw)
To: Johannes Berg, Alan Jenkins
Cc: Marcel Holtmann, cezary.jackiewicz, linux-acpi, linux-kernel,
linux-wireless@vger.kernel.org
In-Reply-To: <1250631063.16393.14.camel@johannes.local>
[-- Attachment #1.1: Type: text/plain, Size: 846 bytes --]
Hi Guys:
Johannes Berg wrote:
> Hi everyone,
>
> That's a bit strange indeed, but I haven't seen the rest of the code.
>
> Does the 'soft block' bit change based on user input, like pressing a
> button?
>
> If not, you shouldn't poll that bit at all, but just set it based on
> what rfkill gives you as the return value of set_hw_state().
>
>
No it doesn't, so i've followed your advice in an updated patch, Thanks.
Alan Jenkins wrote:
> ... but you *do* need to unregister wifi_rfkill here, before you go on
> to destroy it.
>
> +err_wifi:
> + rfkill_destroy(wifi_rfkill);
> +
> + return ret;
> +}
>
> Regards
> Alan
>
I think I've addressed this properly now and only go through each of the error handlers as necessary.
--
Mario Limonciello
*Dell | Linux Engineering*
mario_limonciello@dell.com
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 02_add_rfkill_support.diff --]
[-- Type: text/x-patch; name="02_add_rfkill_support.diff", Size: 3274 bytes --]
--- compal-laptop.c.old 2009-08-18 05:23:39.668669312 -0500
+++ compal-laptop.c 2009-08-18 05:49:00.098015155 -0500
@@ -52,6 +52,7 @@
#include <linux/backlight.h>
#include <linux/platform_device.h>
#include <linux/autoconf.h>
+#include <linux/rfkill.h>
#define COMPAL_DRIVER_VERSION "0.2.6"
@@ -64,6 +65,10 @@
#define WLAN_MASK 0x01
#define BT_MASK 0x02
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bt_rfkill;
+static struct platform_device *compal_device;
+
static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -89,6 +94,84 @@
return (int) result;
}
+static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
+{
+ unsigned long radio = (unsigned long) data;
+ u8 result;
+ bool hw_blocked;
+ bool sw_blocked;
+
+ ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
+
+ hw_blocked = !(result & (KILLSWITCH_MASK | radio));
+ sw_blocked = rfkill_set_hw_state(rfkill, hw_blocked);
+
+ rfkill_set_sw_state(rfkill, sw_blocked);
+}
+
+static int compal_rfkill_set(void *data, bool blocked)
+{
+ unsigned long radio = (unsigned long) data;
+ u8 result, value;
+
+ ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
+
+ if ((result & KILLSWITCH_MASK) == 0)
+ return -EINVAL;
+
+ if (!blocked)
+ value = (u8) (result | radio);
+ else
+ value = (u8) (result & ~radio);
+ ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
+
+ return 0;
+}
+
+static const struct rfkill_ops compal_rfkill_ops = {
+ .poll = compal_rfkill_poll,
+ .set_block = compal_rfkill_set,
+};
+
+static int setup_rfkill(void)
+{
+ int ret;
+
+ wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
+ RFKILL_TYPE_WLAN, &compal_rfkill_ops,
+ (void *) WLAN_MASK);
+ if (!wifi_rfkill)
+ return -ENOMEM;
+
+ ret = rfkill_register(wifi_rfkill);
+ if (ret)
+ goto err_wifi;
+
+ bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
+ RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
+ (void *) BT_MASK);
+ if (!bt_rfkill) {
+ ret = -ENOMEM;
+ goto err_allocate_bt;
+ }
+ ret = rfkill_register(bt_rfkill);
+ if (ret)
+ goto err_register_bt;
+
+ return 0;
+
+err_register_bt:
+ rfkill_destroy(bt_rfkill);
+
+err_allocate_bt:
+ rfkill_unregister(wifi_rfkill);
+
+err_wifi:
+ rfkill_destroy(wifi_rfkill);
+
+ return ret;
+}
+
static int set_wlan_state(int state)
{
u8 result, value;
@@ -258,8 +341,6 @@
}
};
-static struct platform_device *compal_device;
-
/* Initialization */
static int dmi_check_cb(const struct dmi_system_id *id)
@@ -397,6 +478,10 @@
if (ret)
goto fail_platform_device2;
+ ret = setup_rfkill();
+ if (ret)
+ printk(KERN_WARNING "compal-laptop: Unable to setup rfkill\n");
+
printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
" successfully loaded.\n");
@@ -428,6 +513,10 @@
platform_device_unregister(compal_device);
platform_driver_unregister(&compal_driver);
backlight_device_unregister(compalbl_device);
+ rfkill_unregister(wifi_rfkill);
+ rfkill_destroy(wifi_rfkill);
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
printk(KERN_INFO "compal-laptop: driver unloaded.\n");
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] Add rfkill support to compal-laptop
From: Johannes Berg @ 2009-08-18 21:31 UTC (permalink / raw)
To: Alan Jenkins
Cc: Mario Limonciello, Marcel Holtmann, cezary.jackiewicz, linux-acpi,
linux-kernel, linux-wireless@vger.kernel.org
In-Reply-To: <9b2b86520908181408v5f7875b6sea31d8d95cc08c0b@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1194 bytes --]
Hi everyone,
> > I'm attaching the updated patch (sorry, git send-email seems to still
> > not be very graceful with line breaks when the SMTP implementation is
> > exchange from what i've seen)
>
> > +static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
> > +{
> > + unsigned long radio = (unsigned long) data;
> > + u8 result;
> > + bool hw_blocked;
> > + bool sw_blocked;
> > +
> > + ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
> > +
> > + hw_blocked = !(result & KILLSWITCH_MASK);
> > + sw_blocked = (!hw_blocked && !(result & radio));
> > +
> > + rfkill_set_states(rfkill, sw_blocked, hw_blocked);
> > +}
>
> I assume you have good reason for having sw_block depend on hw_block.
> I.e. you can't read sw_blocked while hw_blocked is set, right?
>
> If KILLSWITCH is toggled on and off, will the hardware "forget" any
> prior soft-blocks?
That's a bit strange indeed, but I haven't seen the rest of the code.
Does the 'soft block' bit change based on user input, like pressing a
button?
If not, you shouldn't poll that bit at all, but just set it based on
what rfkill gives you as the return value of set_hw_state().
hth,
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] Add rfkill support to compal-laptop
From: Alan Jenkins @ 2009-08-18 21:08 UTC (permalink / raw)
To: Mario Limonciello
Cc: johannes@sipsolutions.net, Marcel Holtmann, cezary.jackiewicz,
linux-acpi, linux-kernel, linux-wireless@vger.kernel.org
In-Reply-To: <4A8AE459.8060102@dell.com>
On 8/18/09, Mario Limonciello <mario_limonciello@dell.com> wrote:
> Hi Alan & Marcel:
>
> Alan Jenkins wrote:
>> Also, you're missing the calls to rfkill_destroy() here.
>>
>> Whew, I think that's everything. I hope you find the feedback useful,
>> despite it being a little fragmented.
>>
>>
> Thanks for all the feedback. I think i've addressed all of the concerns
> that were pointed out. I appreciate the pointer to scripts/cleanpatch,
> that does significantly help in finding whitespace problems that the
> naked eye just browses over.
>
> I'm attaching the updated patch (sorry, git send-email seems to still
> not be very graceful with line breaks when the SMTP implementation is
> exchange from what i've seen)
> +static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
> +{
> + unsigned long radio = (unsigned long) data;
> + u8 result;
> + bool hw_blocked;
> + bool sw_blocked;
> +
> + ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
> +
> + hw_blocked = !(result & KILLSWITCH_MASK);
> + sw_blocked = (!hw_blocked && !(result & radio));
> +
> + rfkill_set_states(rfkill, sw_blocked, hw_blocked);
> +}
I assume you have good reason for having sw_block depend on hw_block.
I.e. you can't read sw_blocked while hw_blocked is set, right?
If KILLSWITCH is toggled on and off, will the hardware "forget" any
prior soft-blocks?
It would also be nice to know if hardware/firmware ever changes
sw_blocked, e.g. in response to a button press.
Johannes, I think I'm confusing myself here. Can you have a look at
this code? I remember the rfkill rewrite was designed to help with
something like this, but I don't know how exactly.
Thanks
Alan
^ permalink raw reply
* [ANN] b43 LP-PHY support (BCM4310/4312/4315) now ready for testing!
From: Gábor Stefanik @ 2009-08-18 20:29 UTC (permalink / raw)
To: Broadcom Wireless, linux-wireless
Hello World!
Great news for Broadcom BCM4310/4312/4315 (PCI 14e4:4315) users:
LP-PHY support is now at the point where it can be tested for functionality!
There are still problems with channel switching (a few patches ago,
only 802.11b/g channels 7 and 8 were working - no tests have been
performed since then) & TX is untested, but Larry has reported that he
can get scan results from channels 7 and 8. He doesn't have any AP on
these channels, so can't test if association works, but it should be
working too. It's also possible that recent patches have fixed the
channel switching bug, as the codepaths for channel switching have
been touched extensively, probably fixing a major miscalculation issue
("Qdiv roundup" was completely wrong).
So, go ahead, give it a try, and let's rock!
Note that the code in wireless-testing is enough to start testing,
however it's recommended that you apply the following 2 pending fixes:
http://marc.info/?l=linux-wireless&m=125061590101156&w=2 and
http://marc.info/?l=linux-wireless&m=125062611720517&w=2
Tomorrow's compat-wireless tarball, together with the above patches,
should also be good for testing. Not sure about today's tarball.
--Gábor
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* [PATCH] b43: LP-PHY: Two small spec updates
From: Gábor Stefanik @ 2009-08-18 20:08 UTC (permalink / raw)
To: John Linville, Michael Buesch, Larry Finger
Cc: Mark Huijgen, Broadcom Wireless, linux-wireless
The specs are beginning to support rev3 LP-PHYs - implement one of
the changes needed for rev3 support.
Also, in the new MIPS driver, the "Japan TX filter" was renamed to
"analog TX filter init" - however, calling it "init" is confusing,
so name it "set analog filter", with a comment for easier future
identification.
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
drivers/net/wireless/b43/phy_lp.c | 17 ++++++++++++-----
1 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 6c69cdb..65f0010 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -609,9 +609,14 @@ static void lpphy_2063_init(struct b43_wldev *dev)
b43_radio_write(dev, B2063_PA_SP7, 0);
b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
- b43_radio_write(dev, B2063_PA_SP3, 0xa0);
- b43_radio_write(dev, B2063_PA_SP4, 0xa0);
- b43_radio_write(dev, B2063_PA_SP2, 0x18);
+ if (dev->phy.rev == 2) {
+ b43_radio_write(dev, B2063_PA_SP3, 0xa0);
+ b43_radio_write(dev, B2063_PA_SP4, 0xa0);
+ b43_radio_write(dev, B2063_PA_SP2, 0x18);
+ } else {
+ b43_radio_write(dev, B2063_PA_SP3, 0x20);
+ b43_radio_write(dev, B2063_PA_SP2, 0x20);
+ }
}
struct lpphy_stx_table_entry {
@@ -1996,7 +2001,9 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
return err;
}
-static void lpphy_japan_filter(struct b43_wldev *dev, int channel)
+
+/* This was previously called lpphy_japan_filter */
+static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
@@ -2165,7 +2172,7 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
err = lpphy_b2062_tune(dev, new_channel);
if (err)
return err;
- lpphy_japan_filter(dev, new_channel);
+ lpphy_set_analog_filter(dev, new_channel);
lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
}
--
1.6.2.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox