Commit 343c686c authored by Pavel Roskin's avatar Pavel Roskin Committed by Jeff Garzik

[PATCH] orinoco: WE-18 support

Author: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: default avatarPavel Roskin <proski@gnu.org>

Use new Wireless Extension API for wireless stats.
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent b81e8e1f
...@@ -137,7 +137,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); ...@@ -137,7 +137,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/* We do this this way to avoid ifdefs in the actual code */ /* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY #ifdef WIRELESS_SPY
#define SPY_NUMBER(priv) (priv->spy_number) #define SPY_NUMBER(priv) (priv->spy_data.spy_number)
#else #else
#define SPY_NUMBER(priv) 0 #define SPY_NUMBER(priv) 0
#endif /* WIRELESS_SPY */ #endif /* WIRELESS_SPY */
...@@ -396,10 +396,10 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) ...@@ -396,10 +396,10 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* If a spy address is defined, we report stats of the /* If a spy address is defined, we report stats of the
* first spy address - Jean II */ * first spy address - Jean II */
if (SPY_NUMBER(priv)) { if (SPY_NUMBER(priv)) {
wstats->qual.qual = priv->spy_stat[0].qual; wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
wstats->qual.level = priv->spy_stat[0].level; wstats->qual.level = priv->spy_data.spy_stat[0].level;
wstats->qual.noise = priv->spy_stat[0].noise; wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
wstats->qual.updated = priv->spy_stat[0].updated; wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
} }
} else { } else {
struct { struct {
...@@ -718,18 +718,13 @@ static inline int is_ethersnap(void *_hdr) ...@@ -718,18 +718,13 @@ static inline int is_ethersnap(void *_hdr)
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
int level, int noise) int level, int noise)
{ {
struct orinoco_private *priv = netdev_priv(dev); struct iw_quality wstats;
int i; wstats.level = level - 0x95;
wstats.noise = noise - 0x95;
/* Gather wireless spy statistics: for each packet, compare the wstats.qual = (level > noise) ? (level - noise) : 0;
* source address with out list, and if match, get the stats... */ wstats.updated = 7;
for (i = 0; i < priv->spy_number; i++) /* Update spy records */
if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { wireless_spy_update(dev, mac, &wstats);
priv->spy_stat[i].level = level - 0x95;
priv->spy_stat[i].noise = noise - 0x95;
priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
priv->spy_stat[i].updated = 7;
}
} }
static void orinoco_stat_gather(struct net_device *dev, static void orinoco_stat_gather(struct net_device *dev,
...@@ -2458,8 +2453,11 @@ struct net_device *alloc_orinocodev(int sizeof_card, ...@@ -2458,8 +2453,11 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->watchdog_timeo = HZ; /* 1 second timeout */
dev->get_stats = orinoco_get_stats; dev->get_stats = orinoco_get_stats;
dev->ethtool_ops = &orinoco_ethtool_ops; dev->ethtool_ops = &orinoco_ethtool_ops;
dev->get_wireless_stats = orinoco_get_wireless_stats;
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
#ifdef WIRELESS_SPY
priv->wireless_data.spy_data = &priv->spy_data;
dev->wireless_data = &priv->wireless_data;
#endif
dev->change_mtu = orinoco_change_mtu; dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list; dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */ /* we use the default eth_mac_addr for setting the MAC addr */
...@@ -2831,7 +2829,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, ...@@ -2831,7 +2829,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
} }
} }
if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
/* Quality stats meaningless in ad-hoc mode */ /* Quality stats meaningless in ad-hoc mode */
} else { } else {
range->max_qual.qual = 0x8b - 0x2f; range->max_qual.qual = 0x8b - 0x2f;
...@@ -2878,6 +2876,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, ...@@ -2878,6 +2876,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
range->min_r_time = 0; range->min_r_time = 0;
range->max_r_time = 65535 * 1000; /* ??? */ range->max_r_time = 65535 * 1000; /* ??? */
/* Event capability (kernel) */
IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
/* Event capability (driver) */
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
TRACE_EXIT(dev->name); TRACE_EXIT(dev->name);
return 0; return 0;
...@@ -3837,92 +3843,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev, ...@@ -3837,92 +3843,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err; return err;
} }
/* Spy is used for link quality/strength measurements in Ad-Hoc mode
* Jean II */
static int orinoco_ioctl_setspy(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *srq,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);
struct sockaddr *address = (struct sockaddr *) extra;
int number = srq->length;
int i;
unsigned long flags;
/* Make sure nobody mess with the structure while we do */
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
/* orinoco_lock() doesn't disable interrupts, so make sure the
* interrupt rx path don't get confused while we copy */
priv->spy_number = 0;
if (number > 0) {
/* Extract the addresses */
for (i = 0; i < number; i++)
memcpy(priv->spy_address[i], address[i].sa_data,
ETH_ALEN);
/* Reset stats */
memset(priv->spy_stat, 0,
sizeof(struct iw_quality) * IW_MAX_SPY);
/* Set number of addresses */
priv->spy_number = number;
}
/* Now, let the others play */
orinoco_unlock(priv, &flags);
/* Do NOT call commit handler */
return 0;
}
static int orinoco_ioctl_getspy(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *srq,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);
struct sockaddr *address = (struct sockaddr *) extra;
int number;
int i;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
number = priv->spy_number;
/* Create address struct */
for (i = 0; i < number; i++) {
memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
address[i].sa_family = AF_UNIX;
}
if (number > 0) {
/* Create address struct */
for (i = 0; i < number; i++) {
memcpy(address[i].sa_data, priv->spy_address[i],
ETH_ALEN);
address[i].sa_family = AF_UNIX;
}
/* Copy stats */
/* In theory, we should disable irqs while copying the stats
* because the rx path might update it in the middle...
* Bah, who care ? - Jean II */
memcpy(extra + (sizeof(struct sockaddr) * number),
priv->spy_stat, sizeof(struct iw_quality) * number);
}
/* Reset updated flags. */
for (i = 0; i < number; i++)
priv->spy_stat[i].updated = 0;
orinoco_unlock(priv, &flags);
srq->length = number;
return 0;
}
/* Trigger a scan (look for other cells in the vicinity */ /* Trigger a scan (look for other cells in the vicinity */
static int orinoco_ioctl_setscan(struct net_device *dev, static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
...@@ -4353,8 +4273,10 @@ static const iw_handler orinoco_handler[] = { ...@@ -4353,8 +4273,10 @@ static const iw_handler orinoco_handler[] = {
[SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens, [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
[SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens, [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange, [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
[SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy, [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
[SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy, [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
[SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap, [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
[SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap, [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
[SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan, [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
...@@ -4399,6 +4321,7 @@ static const struct iw_handler_def orinoco_handler_def = { ...@@ -4399,6 +4321,7 @@ static const struct iw_handler_def orinoco_handler_def = {
.standard = orinoco_handler, .standard = orinoco_handler,
.private = orinoco_private_handler, .private = orinoco_private_handler,
.private_args = orinoco_privtab, .private_args = orinoco_privtab,
.get_wireless_stats = orinoco_get_wireless_stats,
}; };
static void orinoco_get_drvinfo(struct net_device *dev, static void orinoco_get_drvinfo(struct net_device *dev,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <net/iw_handler.h>
#include <linux/version.h> #include <linux/version.h>
#include "hermes.h" #include "hermes.h"
...@@ -112,9 +113,8 @@ struct orinoco_private { ...@@ -112,9 +113,8 @@ struct orinoco_private {
u16 pm_on, pm_mcast, pm_period, pm_timeout; u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble; u16 preamble;
#ifdef WIRELESS_SPY #ifdef WIRELESS_SPY
int spy_number; struct iw_spy_data spy_data; /* iwspy support */
u_char spy_address[IW_MAX_SPY][ETH_ALEN]; struct iw_public_data wireless_data;
struct iw_quality spy_stat[IW_MAX_SPY];
#endif #endif
/* Configuration dependent variables */ /* Configuration dependent variables */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment