From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
To: linux-wireless@vger.kernel.org
Cc: "John W. Linville" <linville@tuxdriver.com>,
Johannes Berg <johannes@sipsolutions.net>
Subject: [RFC PATCH 04/10] rndis_wlan: add cfg80211 get_station
Date: Fri, 28 Aug 2009 13:28:03 +0300 [thread overview]
Message-ID: <20090828102803.15684.91877.stgit@fate.lan> (raw)
In-Reply-To: <20090828102742.15684.10566.stgit@fate.lan>
Add cfg80211 get_station and convert SIOCGIWRATE and get_wireless_stats
to cfg80211.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/rndis_wlan.c | 118 ++++++++++++++++++-------------------
1 files changed, 57 insertions(+), 61 deletions(-)
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 93b504b..1be0172 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -444,17 +444,14 @@ struct rndis_wlan_private {
struct delayed_work scan_work;
struct work_struct work;
struct mutex command_lock;
- spinlock_t stats_lock;
unsigned long work_pending;
+ int last_qual;
struct ieee80211_supported_band band;
struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)];
- struct iw_statistics iwstats;
- struct iw_statistics privstats;
-
int caps;
int multicast_size;
@@ -472,6 +469,7 @@ struct rndis_wlan_private {
int radio_on;
int infra_mode;
bool connected;
+ u8 bssid[ETH_ALEN];
struct ndis_80211_ssid essid;
__le32 current_command_oid;
@@ -530,6 +528,9 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index);
+static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo);
+
static struct cfg80211_ops rndis_config_ops = {
.change_virtual_intf = rndis_change_virtual_intf,
.scan = rndis_scan,
@@ -544,6 +545,7 @@ static struct cfg80211_ops rndis_config_ops = {
.add_key = rndis_add_key,
.del_key = rndis_del_key,
.set_default_key = rndis_set_default_key,
+ .get_station = rndis_get_station,
};
static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -1931,6 +1933,7 @@ static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev,
devdbg(usbdev, "cfg80211.disconnect(%d)", reason_code);
priv->connected = false;
+ memset(priv->bssid, 0, ETH_ALEN);
return deauthenticate(usbdev);
}
@@ -2037,6 +2040,7 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
devdbg(usbdev, "cfg80211.leave_ibss()");
priv->connected = false;
+ memset(priv->bssid, 0, ETH_ALEN);
return deauthenticate(usbdev);
}
@@ -2114,6 +2118,43 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
return add_wep_key(usbdev, key.material, key.len, key_index);
}
+static void rndis_fill_station_info(struct usbnet *usbdev,
+ struct station_info *sinfo)
+{
+ __le32 linkspeed, rssi;
+ int ret, len;
+
+ memset(sinfo, 0, sizeof(*sinfo));
+
+ len = sizeof(linkspeed);
+ ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &linkspeed, &len);
+ if (ret == 0) {
+ sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000;
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ }
+
+ len = sizeof(rssi);
+ ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+ if (ret == 0) {
+ sinfo->signal = level_to_qual(le32_to_cpu(rssi));
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ }
+}
+
+static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+{
+ struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+ struct usbnet *usbdev = priv->usbdev;
+
+ if (compare_ether_addr(priv->bssid, mac))
+ return -ENOENT;
+
+ rndis_fill_station_info(usbdev, sinfo);
+
+ return 0;
+}
+
/*
* wireless extension handlers
*/
@@ -2459,7 +2500,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
(u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
flags);
}
-#endif
static int rndis_iw_get_rate(struct net_device *dev,
@@ -2492,6 +2532,7 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
return &priv->iwstats;
}
+#endif
#define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
@@ -2510,7 +2551,7 @@ static const iw_handler rndis_iw_handler[] =
IW_IOCTL(SIOCGIWSCAN) = (iw_handler) cfg80211_wext_giwscan,
IW_IOCTL(SIOCSIWESSID) = (iw_handler) cfg80211_wext_siwessid,
IW_IOCTL(SIOCGIWESSID) = (iw_handler) cfg80211_wext_giwessid,
- IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate,
+ IW_IOCTL(SIOCGIWRATE) = (iw_handler) cfg80211_wext_giwrate,
IW_IOCTL(SIOCSIWRTS) = (iw_handler) cfg80211_wext_siwrts,
IW_IOCTL(SIOCGIWRTS) = (iw_handler) cfg80211_wext_giwrts,
IW_IOCTL(SIOCSIWFRAG) = (iw_handler) cfg80211_wext_siwfrag,
@@ -2539,7 +2580,7 @@ static const struct iw_handler_def rndis_iw_handlers = {
.standard = (iw_handler *)rndis_iw_handler,
.private = (iw_handler *)rndis_wlan_private_handler,
.private_args = (struct iw_priv_args *)rndis_wlan_private_args,
- .get_wireless_stats = rndis_get_wireless_stats,
+ .get_wireless_stats = cfg80211_wireless_stats,
};
@@ -2614,6 +2655,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
priv->connected = true;
+ memcpy(priv->bssid, bssid, ETH_ALEN);
usbnet_resume_rx(usbdev);
netif_carrier_on(usbdev->net);
@@ -2928,64 +2970,30 @@ static void rndis_update_wireless_stats(struct work_struct *work)
struct rndis_wlan_private *priv =
container_of(work, struct rndis_wlan_private, stats_work.work);
struct usbnet *usbdev = priv->usbdev;
- struct iw_statistics iwstats;
__le32 rssi, tmp;
int len, ret, j;
- unsigned long flags;
int update_jiffies = STATS_UPDATE_JIFFIES;
void *buf;
- spin_lock_irqsave(&priv->stats_lock, flags);
- memcpy(&iwstats, &priv->privstats, sizeof(iwstats));
- spin_unlock_irqrestore(&priv->stats_lock, flags);
-
- /* only update stats when connected */
- if (!is_associated(usbdev)) {
- iwstats.qual.qual = 0;
- iwstats.qual.level = 0;
- iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
- | IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_INVALID
- | IW_QUAL_QUAL_INVALID
- | IW_QUAL_LEVEL_INVALID;
+ /* Only check/do workaround when connected. Calling is_associated()
+ * also polls device with rndis_command() and catches for media link
+ * indications.
+ */
+ if (!is_associated(usbdev))
goto end;
- }
len = sizeof(rssi);
ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+ if (ret == 0)
+ priv->last_qual = level_to_qual(le32_to_cpu(rssi));
devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret,
le32_to_cpu(rssi));
- if (ret == 0) {
- memset(&iwstats.qual, 0, sizeof(iwstats.qual));
- iwstats.qual.qual = level_to_qual(le32_to_cpu(rssi));
- iwstats.qual.level = level_to_qual(le32_to_cpu(rssi));
- iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
- | IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_INVALID;
- }
-
- memset(&iwstats.discard, 0, sizeof(iwstats.discard));
-
- len = sizeof(tmp);
- ret = rndis_query_oid(usbdev, OID_GEN_XMIT_ERROR, &tmp, &len);
- if (ret == 0)
- iwstats.discard.misc += le32_to_cpu(tmp);
-
- len = sizeof(tmp);
- ret = rndis_query_oid(usbdev, OID_GEN_RCV_ERROR, &tmp, &len);
- if (ret == 0)
- iwstats.discard.misc += le32_to_cpu(tmp);
-
- len = sizeof(tmp);
- ret = rndis_query_oid(usbdev, OID_GEN_RCV_NO_BUFFER, &tmp, &len);
- if (ret == 0)
- iwstats.discard.misc += le32_to_cpu(tmp);
/* Workaround transfer stalls on poor quality links.
* TODO: find right way to fix these stalls (as stalls do not happen
* with ndiswrapper/windows driver). */
- if (iwstats.qual.qual <= 25) {
+ if (priv->last_qual <= 25) {
/* Decrease stats worker interval to catch stalls.
* faster. Faster than 400-500ms causes packet loss,
* Slower doesn't catch stalls fast enough.
@@ -3013,9 +3021,6 @@ static void rndis_update_wireless_stats(struct work_struct *work)
kfree(buf);
}
end:
- spin_lock_irqsave(&priv->stats_lock, flags);
- memcpy(&priv->privstats, &iwstats, sizeof(iwstats));
- spin_unlock_irqrestore(&priv->stats_lock, flags);
if (update_jiffies >= HZ)
update_jiffies = round_jiffies_relative(update_jiffies);
@@ -3146,7 +3151,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
priv->usbdev = usbdev;
mutex_init(&priv->command_lock);
- spin_lock_init(&priv->stats_lock);
/* because rndis_command() sleeps we need to use workqueue */
priv->workqueue = create_singlethread_workqueue("rndis_wlan");
@@ -3183,14 +3187,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
else
usbdev->net->flags &= ~IFF_MULTICAST;
- priv->iwstats.qual.qual = 0;
- priv->iwstats.qual.level = 0;
- priv->iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
- | IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_INVALID
- | IW_QUAL_QUAL_INVALID
- | IW_QUAL_LEVEL_INVALID;
-
/* fill-out wiphy structure and register w/ cfg80211 */
memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN);
wiphy->privid = rndis_wiphy_privid;
next prev parent reply other threads:[~2009-08-28 10:28 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-28 10:27 [RFC PATCH 00/10] complete cfg80211 conversion Jussi Kivilinna
2009-08-28 10:27 ` [RFC PATCH 01/10] rndis_wlan: add cfg80211 connect, disconnect, join_ibss and leave_ibss Jussi Kivilinna
2009-08-28 10:27 ` [RFC PATCH 02/10] rndis_wlan: add cfg80211 set_channel Jussi Kivilinna
2009-08-28 10:27 ` [RFC PATCH 03/10] rndis_wlan: add cfg80211 key handling Jussi Kivilinna
2009-08-28 10:28 ` Jussi Kivilinna [this message]
2009-08-28 10:28 ` [RFC PATCH 05/10] rndis_wlan: add cfg80211 dump_station Jussi Kivilinna
2009-08-28 10:28 ` [RFC PATCH 06/10] rndis_wlan: rename wireless stats worker to device poller Jussi Kivilinna
2009-08-28 10:28 ` [RFC PATCH 07/10] rndis_wlan: remove unneeded SIOCSIWCOMMIT Jussi Kivilinna
2009-08-28 10:28 ` [RFC PATCH 08/10] rndis_wlan: convert mic failure wireless event to cfg80211 Jussi Kivilinna
2009-08-28 10:28 ` [RFC PATCH 09/10] rndis_wlan: disable IWEVPMKIDCAND wireless event Jussi Kivilinna
2009-08-28 10:28 ` [RFC PATCH 10/10] rndis_wlan: use cfg80211_wext_handler Jussi Kivilinna
2009-08-28 11:11 ` Johannes Berg
2009-08-28 13:11 ` [RFC PATCH 00/10] complete cfg80211 conversion John W. Linville
2009-08-28 14:34 ` Jussi Kivilinna
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090828102803.15684.91877.stgit@fate.lan \
--to=jussi.kivilinna@mbnet.fi \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.