patch-2.4.22 linux-2.4.22/drivers/net/wireless/airo.c
Next file: linux-2.4.22/drivers/net/wireless/airport.c
Previous file: linux-2.4.22/drivers/net/wan/z85230.c
Back to the patch index
Back to the overall index
- Lines: 1511
- Date:
2003-08-25 04:44:42.000000000 -0700
- Orig file:
linux-2.4.21/drivers/net/wireless/airo.c
- Orig date:
2003-06-13 07:51:35.000000000 -0700
diff -urN linux-2.4.21/drivers/net/wireless/airo.c linux-2.4.22/drivers/net/wireless/airo.c
@@ -97,12 +97,12 @@
infront of the label, that statistic will not be included in the list
of statistics in the /proc filesystem */
-#define IGNLABEL 0&(int)
+#define IGNLABEL(comment) 0
static char *statsLabels[] = {
"RxOverrun",
- IGNLABEL "RxPlcpCrcErr",
- IGNLABEL "RxPlcpFormatErr",
- IGNLABEL "RxPlcpLengthErr",
+ IGNLABEL("RxPlcpCrcErr"),
+ IGNLABEL("RxPlcpFormatErr"),
+ IGNLABEL("RxPlcpLengthErr"),
"RxMacCrcErr",
"RxMacCrcOk",
"RxWepErr",
@@ -146,15 +146,15 @@
"HostRxBc",
"HostRxUc",
"HostRxDiscard",
- IGNLABEL "HmacTxMc",
- IGNLABEL "HmacTxBc",
- IGNLABEL "HmacTxUc",
- IGNLABEL "HmacTxFail",
- IGNLABEL "HmacRxMc",
- IGNLABEL "HmacRxBc",
- IGNLABEL "HmacRxUc",
- IGNLABEL "HmacRxDiscard",
- IGNLABEL "HmacRxAccepted",
+ IGNLABEL("HmacTxMc"),
+ IGNLABEL("HmacTxBc"),
+ IGNLABEL("HmacTxUc"),
+ IGNLABEL("HmacTxFail"),
+ IGNLABEL("HmacRxMc"),
+ IGNLABEL("HmacRxBc"),
+ IGNLABEL("HmacRxUc"),
+ IGNLABEL("HmacRxDiscard"),
+ IGNLABEL("HmacRxAccepted"),
"SsidMismatch",
"ApMismatch",
"RatesMismatch",
@@ -162,26 +162,26 @@
"AuthTimeout",
"AssocReject",
"AssocTimeout",
- IGNLABEL "ReasonOutsideTable",
- IGNLABEL "ReasonStatus1",
- IGNLABEL "ReasonStatus2",
- IGNLABEL "ReasonStatus3",
- IGNLABEL "ReasonStatus4",
- IGNLABEL "ReasonStatus5",
- IGNLABEL "ReasonStatus6",
- IGNLABEL "ReasonStatus7",
- IGNLABEL "ReasonStatus8",
- IGNLABEL "ReasonStatus9",
- IGNLABEL "ReasonStatus10",
- IGNLABEL "ReasonStatus11",
- IGNLABEL "ReasonStatus12",
- IGNLABEL "ReasonStatus13",
- IGNLABEL "ReasonStatus14",
- IGNLABEL "ReasonStatus15",
- IGNLABEL "ReasonStatus16",
- IGNLABEL "ReasonStatus17",
- IGNLABEL "ReasonStatus18",
- IGNLABEL "ReasonStatus19",
+ IGNLABEL("ReasonOutsideTable"),
+ IGNLABEL("ReasonStatus1"),
+ IGNLABEL("ReasonStatus2"),
+ IGNLABEL("ReasonStatus3"),
+ IGNLABEL("ReasonStatus4"),
+ IGNLABEL("ReasonStatus5"),
+ IGNLABEL("ReasonStatus6"),
+ IGNLABEL("ReasonStatus7"),
+ IGNLABEL("ReasonStatus8"),
+ IGNLABEL("ReasonStatus9"),
+ IGNLABEL("ReasonStatus10"),
+ IGNLABEL("ReasonStatus11"),
+ IGNLABEL("ReasonStatus12"),
+ IGNLABEL("ReasonStatus13"),
+ IGNLABEL("ReasonStatus14"),
+ IGNLABEL("ReasonStatus15"),
+ IGNLABEL("ReasonStatus16"),
+ IGNLABEL("ReasonStatus17"),
+ IGNLABEL("ReasonStatus18"),
+ IGNLABEL("ReasonStatus19"),
"RxMan",
"TxMan",
"RxRefresh",
@@ -654,9 +654,38 @@
u16 currentXmitRate;
u16 apDevExtensions;
u16 normalizedSignalStrength;
- u16 _reserved1;
+ u16 shortPreamble;
u8 apIP[4];
- u16 _reserved[7];
+ u8 noisePercent; /* Noise percent in last second */
+ u8 noisedBm; /* Noise dBm in last second */
+ u8 noiseAvePercent; /* Noise percent in last minute */
+ u8 noiseAvedBm; /* Noise dBm in last minute */
+ u8 noiseMaxPercent; /* Highest noise percent in last minute */
+ u8 noiseMaxdBm; /* Highest noise dbm in last minute */
+ u16 load;
+ u8 carrier[4];
+ u16 assocStatus;
+#define STAT_NOPACKETS 0
+#define STAT_NOCARRIERSET 10
+#define STAT_GOTCARRIERSET 11
+#define STAT_WRONGSSID 20
+#define STAT_BADCHANNEL 25
+#define STAT_BADBITRATES 30
+#define STAT_BADPRIVACY 35
+#define STAT_APFOUND 40
+#define STAT_APREJECTED 50
+#define STAT_AUTHENTICATING 60
+#define STAT_DEAUTHENTICATED 61
+#define STAT_AUTHTIMEOUT 62
+#define STAT_ASSOCIATING 70
+#define STAT_DEASSOCIATED 71
+#define STAT_ASSOCTIMEOUT 72
+#define STAT_NOTAIROAP 73
+#define STAT_ASSOCIATED 80
+#define STAT_LEAPING 90
+#define STAT_LEAPFAILED 91
+#define STAT_LEAPTIMEDOUT 92
+#define STAT_LEAPCOMPLETE 93
} StatusRid;
typedef struct {
@@ -894,7 +923,7 @@
#ifdef WIRELESS_EXT
// Frequency list (map channels to frequencies)
-const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
// A few details needed for WEP (Wireless Equivalent Privacy)
@@ -929,8 +958,8 @@
static void OUT4500( struct airo_info *, u16 register, u16 value );
static unsigned short IN4500( struct airo_info *, u16 register );
static u16 setup_card(struct airo_info*, u8 *mac);
-static int enable_MAC( struct airo_info *ai, Resp *rsp );
-static void disable_MAC(struct airo_info *ai);
+static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );
+static void disable_MAC(struct airo_info *ai, int lock);
static void enable_interrupts(struct airo_info*);
static void disable_interrupts(struct airo_info*);
static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
@@ -944,11 +973,11 @@
static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen,
int whichbap);
static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);
-static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len);
+static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);
static int PC4500_writerid(struct airo_info*, u16 rid, const void
- *pBuf, int len);
+ *pBuf, int len, int lock);
static int do_writerid( struct airo_info*, u16 rid, const void *rid_data,
- int len );
+ int len, int dummy );
static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);
static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);
static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
@@ -976,7 +1005,7 @@
int open;
struct net_device *dev;
/* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we
- use the high bit to mark wether it is in use. */
+ use the high bit to mark whether it is in use. */
#define MAX_FIDS 6
int fids[MAX_FIDS];
int registered;
@@ -992,19 +1021,21 @@
#define FLAG_PROMISC IFF_PROMISC /* 0x100 - include/linux/if.h */
#define FLAG_RADIO_OFF 0x02 /* User disabling of MAC */
#define FLAG_RADIO_DOWN 0x08 /* ifup/ifdown disabling of MAC */
-#define FLAG_LOCKED 2 /* 0x04 - use as a bit offset */
#define FLAG_FLASHING 0x10
#define FLAG_ADHOC 0x01 /* Needed by MIC */
#define FLAG_MIC_CAPABLE 0x20
#define FLAG_UPDATE_MULTI 0x40
#define FLAG_UPDATE_UNI 0x80
#define FLAG_802_11 0x200
+#define FLAG_PENDING_XMIT 0x400
+#define FLAG_PENDING_XMIT11 0x800
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap);
unsigned short *flash;
tdsRssiEntry *rssi;
struct semaphore sem;
struct task_struct *task;
+ struct tq_struct stats_task;
struct tq_struct promisc_task;
struct {
struct sk_buff *skb;
@@ -1062,7 +1093,7 @@
ai->task = NULL;
}
rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
- list, sizeof(*list));
+ list, sizeof(*list), 1);
list->len = le16_to_cpu(list->len);
list->index = le16_to_cpu(list->index);
@@ -1077,7 +1108,7 @@
static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) {
int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,
- wkr, sizeof(*wkr));
+ wkr, sizeof(*wkr), 1);
wkr->len = le16_to_cpu(wkr->len);
wkr->kindex = le16_to_cpu(wkr->kindex);
@@ -1086,17 +1117,17 @@
}
/* In the writeXXXRid routines we copy the rids so that we don't screwup
* the originals when we endian them... */
-static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) {
+static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) {
int rc;
WepKeyRid wkr = *pwkr;
wkr.len = cpu_to_le16(wkr.len);
wkr.kindex = cpu_to_le16(wkr.kindex);
wkr.klen = cpu_to_le16(wkr.klen);
- rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr));
+ rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc);
if (perm) {
- rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr));
+ rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
if (rc!=SUCCESS) {
printk(KERN_ERR "airo: WEP_PERM set %x\n", rc);
}
@@ -1106,7 +1137,7 @@
static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {
int i;
- int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr));
+ int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
ssidr->len = le16_to_cpu(ssidr->len);
for(i = 0; i < 3; i++) {
@@ -1123,10 +1154,10 @@
for(i = 0; i < 3; i++) {
ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);
}
- rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr));
+ rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), 1);
return rc;
}
-static int readConfigRid(struct airo_info*ai) {
+static int readConfigRid(struct airo_info*ai, int lock) {
int rc;
u16 *s;
ConfigRid cfg;
@@ -1134,7 +1165,7 @@
if (ai->config.len)
return SUCCESS;
- rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg));
+ rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock);
if (rc != SUCCESS)
return rc;
@@ -1163,7 +1194,7 @@
}
}
}
-static int writeConfigRid(struct airo_info*ai) {
+static int writeConfigRid(struct airo_info*ai, int lock) {
u16 *s;
ConfigRid cfgr;
@@ -1190,33 +1221,34 @@
for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++)
*s = cpu_to_le16(*s);
- return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr));
+ return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock);
}
static int readStatusRid(struct airo_info*ai, StatusRid *statr) {
- int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr));
+ int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), 1);
u16 *s;
statr->len = le16_to_cpu(statr->len);
for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);
- for(s = &statr->beaconPeriod; s <= &statr->_reserved[9]; s++)
+ for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++)
*s = le16_to_cpu(*s);
-
+ statr->load = le16_to_cpu(statr->load);
+ statr->assocStatus = le16_to_cpu(statr->assocStatus);
return rc;
}
static int readAPListRid(struct airo_info*ai, APListRid *aplr) {
- int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr));
+ int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
aplr->len = le16_to_cpu(aplr->len);
return rc;
}
static int writeAPListRid(struct airo_info*ai, APListRid *aplr) {
int rc;
aplr->len = cpu_to_le16(aplr->len);
- rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr));
+ rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
return rc;
}
static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) {
- int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr));
+ int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), 1);
u16 *s;
capr->len = le16_to_cpu(capr->len);
@@ -1227,8 +1259,8 @@
*s = le16_to_cpu(*s);
return rc;
}
-static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid) {
- int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr));
+static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {
+ int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);
u32 *i;
sr->len = le16_to_cpu(sr->len);
@@ -1248,8 +1280,8 @@
* is open (to pipeline changes and speed-up card setup). If
* those changes are not yet commited, do it now - Jean II */
if(info->need_commit) {
- disable_MAC(info);
- writeConfigRid(info);
+ disable_MAC(info, 1);
+ writeConfigRid(info, 1);
}
if (info->wifidev != dev) {
@@ -1257,7 +1289,7 @@
info->flags &= ~FLAG_RADIO_DOWN;
enable_interrupts(info);
}
- enable_MAC(info, &rsp);
+ enable_MAC(info, &rsp, 1);
netif_start_queue(dev);
return 0;
@@ -1321,6 +1353,7 @@
u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) {
+ priv->flags |= FLAG_PENDING_XMIT;
netif_stop_queue(dev);
priv->xmit.task.routine = (void (*)(void *))airo_do_xmit;
priv->xmit.task.data = (void *)dev;
@@ -1329,6 +1362,7 @@
}
status = transmit_802_3_packet (priv, fids[fid], skb->data);
up(&priv->sem);
+ priv->flags &= ~FLAG_PENDING_XMIT;
i = 0;
if ( status == SUCCESS ) {
@@ -1340,14 +1374,12 @@
}
if (i < MAX_FIDS / 2)
netif_wake_queue(dev);
- else
- netif_stop_queue(dev);
dev_kfree_skb(skb);
}
static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
s16 len;
- int i;
+ int i, j;
struct airo_info *priv = dev->priv;
u32 *fids = priv->fids;
@@ -1358,19 +1390,23 @@
/* Find a vacant FID */
for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
+ for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ );
- if ( i == MAX_FIDS / 2 ) {
- priv->stats.tx_fifo_errors++;
- dev_kfree_skb(skb);
- } else {
- /* check min length*/
- len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- /* Mark fid as used & save length for later */
- fids[i] |= (len << 16);
- priv->xmit.skb = skb;
- priv->xmit.fid = i;
- airo_do_xmit(dev);
+ if ( j >= MAX_FIDS / 2 ) {
+ netif_stop_queue(dev);
+
+ if (i == MAX_FIDS / 2) {
+ priv->stats.tx_fifo_errors++;
+ return 1;
+ }
}
+ /* check min length*/
+ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ /* Mark fid as used & save length for later */
+ fids[i] |= (len << 16);
+ priv->xmit.skb = skb;
+ priv->xmit.fid = i;
+ airo_do_xmit(dev);
return 0;
}
@@ -1383,6 +1419,7 @@
u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) {
+ priv->flags |= FLAG_PENDING_XMIT11;
netif_stop_queue(dev);
priv->xmit11.task.routine = (void (*)(void *))airo_do_xmit11;
priv->xmit11.task.data = (void *)dev;
@@ -1391,6 +1428,7 @@
}
status = transmit_802_11_packet (priv, fids[fid], skb->data);
up(&priv->sem);
+ priv->flags &= ~FLAG_PENDING_XMIT11;
i = MAX_FIDS / 2;
if ( status == SUCCESS ) {
@@ -1402,14 +1440,12 @@
}
if (i < MAX_FIDS)
netif_wake_queue(dev);
- else
- netif_stop_queue(dev);
dev_kfree_skb(skb);
}
static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
s16 len;
- int i;
+ int i, j;
struct airo_info *priv = dev->priv;
u32 *fids = priv->fids;
@@ -1420,45 +1456,61 @@
/* Find a vacant FID */
for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
+ for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ );
- if ( i == MAX_FIDS ) {
- priv->stats.tx_fifo_errors++;
- dev_kfree_skb(skb);
- } else {
- /* check min length*/
- len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- /* Mark fid as used & save length for later */
- fids[i] |= (len << 16);
- priv->xmit11.skb = skb;
- priv->xmit11.fid = i;
- airo_do_xmit11(dev);
+ if ( j >= MAX_FIDS ) {
+ netif_stop_queue(dev);
+
+ if (i == MAX_FIDS) {
+ priv->stats.tx_fifo_errors++;
+ return 1;
+ }
}
+ /* check min length*/
+ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ /* Mark fid as used & save length for later */
+ fids[i] |= (len << 16);
+ priv->xmit11.skb = skb;
+ priv->xmit11.fid = i;
+ airo_do_xmit11(dev);
return 0;
}
-struct net_device_stats *airo_get_stats(struct net_device *dev)
-{
- struct airo_info *local = dev->priv;
+static void airo_read_stats(struct airo_info *ai) {
StatsRid stats_rid;
u32 *vals = stats_rid.vals;
- /* Get stats out of the card */
- readStatsRid(local, &stats_rid, RID_STATS);
+ if (down_trylock(&ai->sem) == 0) {
+ readStatsRid(ai, &stats_rid, RID_STATS, 0);
+ up(&ai->sem);
- local->stats.rx_packets = vals[43] + vals[44] + vals[45];
- local->stats.tx_packets = vals[39] + vals[40] + vals[41];
- local->stats.rx_bytes = vals[92];
- local->stats.tx_bytes = vals[91];
- local->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];
- local->stats.tx_errors = vals[42] + local->stats.tx_fifo_errors;
- local->stats.multicast = vals[43];
- local->stats.collisions = vals[89];
-
- /* detailed rx_errors: */
- local->stats.rx_length_errors = vals[3];
- local->stats.rx_crc_errors = vals[4];
- local->stats.rx_frame_errors = vals[2];
- local->stats.rx_fifo_errors = vals[0];
+ ai->stats.rx_packets = vals[43] + vals[44] + vals[45];
+ ai->stats.tx_packets = vals[39] + vals[40] + vals[41];
+ ai->stats.rx_bytes = vals[92];
+ ai->stats.tx_bytes = vals[91];
+ ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];
+ ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors;
+ ai->stats.multicast = vals[43];
+ ai->stats.collisions = vals[89];
+
+ /* detailed rx_errors: */
+ ai->stats.rx_length_errors = vals[3];
+ ai->stats.rx_crc_errors = vals[4];
+ ai->stats.rx_frame_errors = vals[2];
+ ai->stats.rx_fifo_errors = vals[0];
+ } else {
+ ai->stats_task.routine = (void (*)(void *))airo_read_stats;
+ ai->stats_task.data = (void *)ai;
+ schedule_task(&ai->stats_task);
+ }
+}
+
+struct net_device_stats *airo_get_stats(struct net_device *dev)
+{
+ struct airo_info *local = dev->priv;
+
+ /* Get stats out of the card if available */
+ airo_read_stats(local);
return &local->stats;
}
@@ -1513,9 +1565,9 @@
memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
ai->need_commit = 1;
- disable_MAC(ai);
- writeConfigRid (ai);
- enable_MAC(ai, &rsp);
+ disable_MAC(ai, 1);
+ writeConfigRid (ai, 1);
+ enable_MAC(ai, &rsp, 1);
memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
if (ai->wifidev)
memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
@@ -1544,7 +1596,7 @@
* stack (i.e. the network stack won't try to broadcast
* anything on the interface and routes are gone. Jean II */
ai->flags |= FLAG_RADIO_DOWN;
- disable_MAC(ai);
+ disable_MAC(ai, 1);
#endif
disable_interrupts( ai );
}
@@ -1557,6 +1609,8 @@
{
struct airo_info *ai = dev->priv;
flush_scheduled_tasks();
+ disable_interrupts(ai);
+ free_irq( dev->irq, dev );
if (ai->flash)
kfree(ai->flash);
if (ai->rssi)
@@ -1571,8 +1625,6 @@
}
ai->registered = 0;
}
- disable_interrupts(ai);
- free_irq( dev->irq, dev );
if (auto_wep) del_timer_sync(&ai->timer);
if (freeres) {
/* PCMCIA frees this stuff, so only for PCI and ISA */
@@ -1768,6 +1820,9 @@
int i;
struct airo_info *ai = dev->priv;
+
+ if (down_interruptible(&ai->sem))
+ return -1;
waitbusy (ai);
OUT4500(ai,COMMAND,CMD_SOFTRESET);
set_current_state (TASK_UNINTERRUPTIBLE);
@@ -1777,6 +1832,7 @@
schedule_timeout (HZ/5);
if ( setup_card(ai, dev->dev_addr ) != SUCCESS ) {
printk( KERN_ERR "airo: MAC could not be enabled\n" );
+ up(&ai->sem);
return -1;
} else {
printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
@@ -1794,6 +1850,7 @@
}
enable_interrupts( ai );
netif_wake_queue(dev);
+ up(&ai->sem);
return 0;
}
@@ -1806,9 +1863,7 @@
StatusRid status_rid;
if (down_trylock(&ai->sem) == 0) {
- __set_bit(FLAG_LOCKED, &ai->flags);
- PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid));
- clear_bit(FLAG_LOCKED, &ai->flags);
+ PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
up(&ai->sem);
wrqu.data.length = 0;
wrqu.data.flags = 0;
@@ -1829,9 +1884,7 @@
MICRid mic_rid;
if (down_trylock(&ai->sem) == 0) {
- __set_bit(FLAG_LOCKED, &ai->flags);
- PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid));
- clear_bit(FLAG_LOCKED, &ai->flags);
+ PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
up(&ai->sem);
#ifdef MICSUPPORT
micinit (ai, &mic_rid);
@@ -1869,7 +1922,8 @@
if ( status & EV_MIC ) {
OUT4500( apriv, EVACK, EV_MIC );
- airo_read_mic( apriv );
+ if (apriv->flags & FLAG_MIC_CAPABLE)
+ airo_read_mic( apriv );
}
if ( status & EV_LINK ) {
#if WIRELESS_EXT > 13
@@ -2060,6 +2114,28 @@
}
}
if (len) {
+#if WIRELESS_EXT > 15
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ if (apriv->spy_data.spy_number > 0) {
+ char *sa;
+ struct iw_quality wstats;
+ /* Prepare spy data : addr + qual */
+ sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6);
+ if (!(apriv->flags & FLAG_802_11)) {
+ bap_setup (apriv, fid, 8, BAP0);
+ bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
+ }
+ wstats.qual = hdr.rssi[0];
+ if (apriv->rssi)
+ wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
+ else
+ wstats.level = (hdr.rssi[1] + 321) / 2;
+ wstats.updated = 3;
+ /* Update spy records */
+ wireless_spy_update(dev, sa, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+#else /* WIRELESS_EXT > 15 */
#ifdef WIRELESS_SPY
if (apriv->spy_number > 0) {
int i;
@@ -2085,6 +2161,7 @@
}
}
#endif /* WIRELESS_SPY */
+#endif /* WIRELESS_EXT > 15 */
OUT4500( apriv, EVACK, EV_RX);
if (apriv->flags & FLAG_802_11) {
@@ -2116,17 +2193,23 @@
if ( ( apriv->fids[i] & 0xffff ) == fid ) {
len = apriv->fids[i] >> 16;
index = i;
- /* Set up to be used again */
- apriv->fids[i] &= 0xffff;
}
}
if (index != -1) {
- netif_wake_queue(dev);
if (status & EV_TXEXC)
get_tx_error(apriv, index);
- }
- OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
- if (index==-1) {
+ OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
+ /* Set up to be used again */
+ apriv->fids[index] &= 0xffff;
+ if (index < MAX_FIDS / 2) {
+ if (!(apriv->flags & FLAG_PENDING_XMIT))
+ netif_wake_queue(dev);
+ } else {
+ if (!(apriv->flags & FLAG_PENDING_XMIT11))
+ netif_wake_queue(apriv->wifidev);
+ }
+ } else {
+ OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );
}
}
@@ -2172,7 +2255,7 @@
return rc;
}
-static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
+static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
int rc;
Cmd cmd;
@@ -2185,7 +2268,7 @@
if (ai->flags & (FLAG_RADIO_OFF|FLAG_RADIO_DOWN)) return SUCCESS;
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_ENABLE;
- if (test_bit(FLAG_LOCKED, &ai->flags) != 0)
+ if (!lock)
return issuecommand(ai, &cmd, rsp);
if (down_interruptible(&ai->sem))
@@ -2195,13 +2278,13 @@
return rc;
}
-static void disable_MAC( struct airo_info *ai ) {
+static void disable_MAC( struct airo_info *ai, int lock ) {
Cmd cmd;
Resp rsp;
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_DISABLE; // disable in case already enabled
- if (test_bit(FLAG_LOCKED, &ai->flags) != 0) {
+ if (!lock) {
issuecommand(ai, &cmd, &rsp);
return;
}
@@ -2219,7 +2302,7 @@
/* Enable the interrupts */
OUT4500( ai, EVINTEN, STATUS_INTS );
/* Note there is a race condition between the last two lines that
- I dont know how to get rid of right now... */
+ I don't know how to get rid of right now... */
}
static void disable_interrupts( struct airo_info *ai ) {
@@ -2279,13 +2362,13 @@
CapabilityRid cap_rid;
// general configuration (read/modify/write)
- status = readConfigRid(ai);
+ status = readConfigRid(ai, 1);
if ( status != SUCCESS ) return ERROR;
status = readCapabilityRid(ai, &cap_rid);
if ( status != SUCCESS ) return ERROR;
- status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));
+ status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),1);
if ( status == SUCCESS ) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
@@ -2349,14 +2432,14 @@
}
}
- status = writeConfigRid(ai);
+ status = writeConfigRid(ai, 1);
if ( status != SUCCESS ) return ERROR;
/* Set up the SSID list */
status = writeSsidRid(ai, &mySsid);
if ( status != SUCCESS ) return ERROR;
- status = enable_MAC(ai, &rsp);
+ status = enable_MAC(ai, &rsp, 1);
if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
return ERROR;
@@ -2500,7 +2583,7 @@
u16 next;
int words;
int i;
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&ai->aux_lock, flags);
page = IN4500(ai, SWS0+whichbap);
@@ -2571,13 +2654,12 @@
/* Note, that we are using BAP1 which is also used by transmit, so
* we must get a lock. */
-static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
+static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, int lock)
{
- u16 status, dolock = 0;
+ u16 status;
int rc = SUCCESS;
- if (test_bit(FLAG_LOCKED, &ai->flags) == 0) {
- dolock = 1;
+ if (lock) {
if (down_interruptible(&ai->sem))
return ERROR;
}
@@ -2605,7 +2687,7 @@
// read remainder of the rid
rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1);
done:
- if (dolock)
+ if (lock)
up(&ai->sem);
return rc;
}
@@ -2613,13 +2695,14 @@
/* Note, that we are using BAP1 which is also used by transmit, so
* make sure this isnt called when a transmit is happening */
static int PC4500_writerid(struct airo_info *ai, u16 rid,
- const void *pBuf, int len)
+ const void *pBuf, int len, int lock)
{
- u16 status, dolock = 0;
+ u16 status;
int rc = SUCCESS;
- if (test_bit(FLAG_LOCKED, &ai->flags) == 0) {
- dolock = 1;
+ *(u16*)pBuf = cpu_to_le16((u16)len);
+
+ if (lock) {
if (down_interruptible(&ai->sem))
return ERROR;
}
@@ -2637,7 +2720,7 @@
// ---now commit the rid data
rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS);
done:
- if (dolock)
+ if (lock)
up(&ai->sem);
return rc;
}
@@ -2646,6 +2729,7 @@
one for now. */
static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
{
+ unsigned int loop = 3000;
Cmd cmd;
Resp rsp;
u16 txFid;
@@ -2656,17 +2740,22 @@
if (down_interruptible(&ai->sem))
return ERROR;
if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
- txFid = 0;
+ txFid = ERROR;
goto done;
}
if ( (rsp.status & 0xFF00) != 0) {
- txFid = 0;
+ txFid = ERROR;
goto done;
}
/* wait for the allocate event/indication
* It makes me kind of nervous that this can just sit here and spin,
* but in practice it only loops like four times. */
- while ( (IN4500(ai, EVSTAT) & EV_ALLOC) == 0) ;
+ while (((IN4500(ai, EVSTAT) & EV_ALLOC) == 0) && --loop);
+ if (!loop) {
+ txFid = ERROR;
+ goto done;
+ }
+
// get the allocated fid and acknowledge
txFid = IN4500(ai, TXALLOCFID);
OUT4500(ai, EVACK, EV_ALLOC);
@@ -2707,7 +2796,7 @@
len >>= 16;
- if (len < ETH_ALEN * 2) {
+ if (len <= ETH_ALEN * 2) {
printk( KERN_WARNING "Short packet %d\n", len );
return ERROR;
}
@@ -3158,10 +3247,10 @@
return -ENOMEM;
}
- readStatsRid(apriv, &stats, rid);
+ readStatsRid(apriv, &stats, rid, 1);
j = 0;
- for(i=0; (int)statsLabels[i]!=-1 &&
+ for(i=0; statsLabels[i]!=(char *)-1 &&
i*4<stats.len; i++){
if (!statsLabels[i]) continue;
if (j+strlen(statsLabels[i])+16>4096) {
@@ -3193,18 +3282,21 @@
return value;
}
+static int airo_config_commit(struct net_device *dev,
+ struct iw_request_info *info, void *zwrq,
+ char *extra);
+
static void proc_config_on_close( struct inode *inode, struct file *file ) {
struct proc_data *data = file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
- Resp rsp;
char *line;
- int need_reset = 0;
if ( !data->writelen ) return;
- readConfigRid(ai);
+ readConfigRid(ai, 1);
+ ai->need_commit = 1;
line = data->wbuffer;
while( line[0] ) {
@@ -3212,19 +3304,22 @@
if ( !strncmp( line, "Mode: ", 6 ) ) {
line += 6;
if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
- need_reset = 1;
+ ai->need_commit = 2;
ai->config.rmode &= 0xfe00;
ai->flags &= ~FLAG_802_11;
ai->config.opmode &= 0xFF00;
+ ai->config.scanMode = SCANMODE_ACTIVE;
if ( line[0] == 'a' ) {
ai->config.opmode |= 0;
} else {
ai->config.opmode |= 1;
if ( line[0] == 'r' ) {
ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
+ ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11;
} else if ( line[0] == 'y' ) {
ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
+ ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11;
} else if ( line[0] == 'l' )
ai->config.rmode |= RXMODE_LANMON;
@@ -3390,22 +3485,7 @@
while( line[0] && line[0] != '\n' ) line++;
if ( line[0] ) line++;
}
- disable_MAC(ai);
- if (need_reset) {
- APListRid APList_rid;
- SsidRid SSID_rid;
-
- readAPListRid(ai, &APList_rid);
- readSsidRid(ai, &SSID_rid);
- reset_airo_card(dev);
- disable_MAC(ai);
- writeSsidRid(ai, &SSID_rid);
- writeAPListRid(ai, &APList_rid);
- }
- writeConfigRid(ai);
- enable_MAC(ai, &rsp);
- if (need_reset)
- airo_set_promisc(ai);
+ airo_config_commit(dev, NULL, NULL, NULL);
}
static char *get_rmode(u16 mode) {
@@ -3443,7 +3523,7 @@
data->maxwritelen = 2048;
data->on_close = proc_config_on_close;
- readConfigRid(ai);
+ readConfigRid(ai, 1);
i = sprintf( data->rbuffer,
"Mode: %s\n"
@@ -3535,9 +3615,9 @@
offset < data->writelen ) offset++;
offset++;
}
- disable_MAC(ai);
+ disable_MAC(ai, 1);
writeSsidRid(ai, &SSID_rid);
- enable_MAC(ai, &rsp);
+ enable_MAC(ai, &rsp, 1);
}
inline static u8 hexVal(char c) {
@@ -3576,20 +3656,20 @@
}
}
}
- disable_MAC(ai);
+ disable_MAC(ai, 1);
writeAPListRid(ai, &APList_rid);
- enable_MAC(ai, &rsp);
+ enable_MAC(ai, &rsp, 1);
}
/* This function wraps PC4500_writerid with a MAC disable */
static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
- int len ) {
+ int len, int dummy ) {
int rc;
Resp rsp;
- disable_MAC(ai);
- rc = PC4500_writerid(ai, rid, rid_data, len);
- enable_MAC(ai, &rsp);
+ disable_MAC(ai, 1);
+ rc = PC4500_writerid(ai, rid, rid_data, len, 1);
+ enable_MAC(ai, &rsp, 1);
return rc;
}
@@ -3617,7 +3697,7 @@
}
static int set_wep_key(struct airo_info *ai, u16 index,
- const char *key, u16 keylen, int perm ) {
+ const char *key, u16 keylen, int perm, int lock ) {
static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
WepKeyRid wkr;
@@ -3639,7 +3719,7 @@
printk(KERN_INFO "Setting key %d\n", index);
}
- writeWepKeyRid(ai, &wkr, perm);
+ writeWepKeyRid(ai, &wkr, perm, lock);
return 0;
}
@@ -3662,7 +3742,7 @@
(data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
index = data->wbuffer[0] - '0';
if (data->wbuffer[1] == '\n') {
- set_wep_key(ai, index, 0, 0, 1);
+ set_wep_key(ai, index, 0, 0, 1, 1);
return;
}
j = 2;
@@ -3681,7 +3761,7 @@
break;
}
}
- set_wep_key(ai, index, key, i/3, 1);
+ set_wep_key(ai, index, key, i/3, 1, 1);
}
static int proc_wepkey_open( struct inode *inode, struct file *file ) {
@@ -3937,10 +4017,9 @@
add_timer(&apriv->timer);
return;
}
- __set_bit(FLAG_LOCKED, &apriv->flags);
- readConfigRid(apriv);
- disable_MAC(apriv);
+ readConfigRid(apriv, 0);
+ disable_MAC(apriv, 0);
switch(apriv->config.authType) {
case AUTH_ENCRYPT:
/* So drop to OPEN */
@@ -3948,13 +4027,13 @@
break;
case AUTH_SHAREDKEY:
if (apriv->keyindex < auto_wep) {
- set_wep_key(apriv, apriv->keyindex, 0, 0, 0);
+ set_wep_key(apriv, apriv->keyindex, 0, 0, 0, 0);
apriv->config.authType = AUTH_SHAREDKEY;
apriv->keyindex++;
} else {
/* Drop to ENCRYPT */
apriv->keyindex = 0;
- set_wep_key(apriv, apriv->defindex, 0, 0, 0);
+ set_wep_key(apriv, apriv->defindex, 0, 0, 0, 0);
apriv->config.authType = AUTH_ENCRYPT;
}
break;
@@ -3962,9 +4041,8 @@
apriv->config.authType = AUTH_SHAREDKEY;
}
apriv->need_commit = 1;
- writeConfigRid(apriv);
- enable_MAC(apriv, &rsp);
- clear_bit(FLAG_LOCKED, &apriv->flags);
+ writeConfigRid(apriv, 0);
+ enable_MAC(apriv, &rsp, 0);
up(&apriv->sem);
/* Schedule check to see if the change worked */
@@ -4144,9 +4222,11 @@
struct airo_info *local = dev->priv;
StatusRid status_rid; /* Card status info */
- readStatusRid(local, &status_rid);
+ if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
+ status_rid.channel = local->config.channelSet;
+ else
+ readStatusRid(local, &status_rid);
- /* Will return zero in infrastructure mode */
#ifdef WEXT_USECHANNELS
fwrq->m = ((int)status_rid.channel) + 1;
fwrq->e = 0;
@@ -4200,9 +4280,9 @@
SSID_rid.ssids[index].len = dwrq->length - 1;
}
/* Write it to the card */
- disable_MAC(local);
+ disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid);
- enable_MAC(local, &rsp);
+ enable_MAC(local, &rsp, 1);
return 0;
}
@@ -4264,9 +4344,9 @@
memset(&APList_rid, 0, sizeof(APList_rid));
APList_rid.len = sizeof(APList_rid);
memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
- disable_MAC(local);
+ disable_MAC(local, 1);
writeAPListRid(local, &APList_rid);
- enable_MAC(local, &rsp);
+ enable_MAC(local, &rsp, 1);
}
return 0;
}
@@ -4515,28 +4595,52 @@
char *extra)
{
struct airo_info *local = dev->priv;
+ int commit = 1;
+
+ if ((local->config.rmode & 0xff) >= RXMODE_RFMON)
+ commit = 2;
switch(*uwrq) {
case IW_MODE_ADHOC:
local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_STA_IBSS;
+ local->config.rmode &= 0xfe00;
+ local->config.scanMode = SCANMODE_ACTIVE;
+ local->flags &= ~FLAG_802_11;
break;
case IW_MODE_INFRA:
local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_STA_ESS;
+ local->config.rmode &= 0xfe00;
+ local->config.scanMode = SCANMODE_ACTIVE;
+ local->flags &= ~FLAG_802_11;
break;
case IW_MODE_MASTER:
local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP;
+ local->config.rmode &= 0xfe00;
+ local->config.scanMode = SCANMODE_ACTIVE;
+ local->flags &= ~FLAG_802_11;
break;
case IW_MODE_REPEAT:
local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP_RPTR;
+ local->config.rmode &= 0xfe00;
+ local->config.scanMode = SCANMODE_ACTIVE;
+ local->flags &= ~FLAG_802_11;
+ break;
+ case IW_MODE_MONITOR:
+ local->config.opmode &= 0xFF00;
+ local->config.opmode |= MODE_STA_ESS;
+ local->config.rmode &= 0xfe00;
+ local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
+ local->config.scanMode = SCANMODE_PASSIVE;
+ local->flags |= FLAG_802_11;
break;
default:
return -EINVAL;
}
- local->need_commit = 1;
+ local->need_commit = commit;
return -EINPROGRESS; /* Call commit handler */
}
@@ -4622,7 +4726,7 @@
/* Copy the key in the driver */
memcpy(key.key, extra, dwrq->length);
/* Send the key to the card */
- set_wep_key(local, index, key.key, key.len, 1);
+ set_wep_key(local, index, key.key, key.len, 1, 1);
}
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
@@ -4636,7 +4740,7 @@
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) {
- set_wep_key(local, index, 0, 0, 1);
+ set_wep_key(local, index, 0, 0, 1, 1);
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
@@ -4841,7 +4945,7 @@
readCapabilityRid(local, &cap_rid);
dwrq->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(range));
+ memset(range, 0, sizeof(*range));
range->min_nwid = 0x0000;
range->max_nwid = 0x0000;
range->num_channels = 14;
@@ -5132,7 +5236,7 @@
Resp rsp;
/* Note : you may have realised that, as this is a SET operation,
- * this is priviledged and therefore a normal user can't
+ * this is privileged and therefore a normal user can't
* perform scanning.
* This is not an error, while the device perform scanning,
* traffic doesn't flow, so it's a perfect DoS...
@@ -5154,7 +5258,7 @@
/*------------------------------------------------------------------*/
/*
- * Translate scan data returned from the card to a card independant
+ * Translate scan data returned from the card to a card independent
* format that the Wireless Tools will understand - Jean II
*/
static inline char *airo_translate_scan(struct net_device *dev,
@@ -5281,7 +5385,7 @@
* consequences are begnign. So I don't bother fixing it - Javier */
/* Try to read the first entry of the scan result */
- rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList));
+ rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1);
if((rc) || (BSSList.index == 0xffff)) {
/* Client error, no scan results...
* The caller need to restart the scan. */
@@ -5297,7 +5401,7 @@
/* Read next entry */
rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
- &BSSList, sizeof(BSSList));
+ &BSSList, sizeof(BSSList), 1);
}
/* Length of data */
dwrq->length = (current_ev - extra);
@@ -5307,6 +5411,7 @@
}
#endif /* WIRELESS_EXT > 13 */
+#if WIRELESS_EXT <= 15
#ifdef WIRELESS_SPY
/*------------------------------------------------------------------*/
/*
@@ -5369,6 +5474,7 @@
return 0;
}
#endif /* WIRELESS_SPY */
+#endif /* WIRELESS_EXT <= 15 */
/*------------------------------------------------------------------*/
/*
@@ -5387,9 +5493,22 @@
/* Some of the "SET" function may have modified some of the
* parameters. It's now time to commit them in the card */
- disable_MAC(local);
- writeConfigRid(local);
- enable_MAC(local, &rsp);
+ disable_MAC(local, 1);
+ if (local->need_commit > 1) {
+ APListRid APList_rid;
+ SsidRid SSID_rid;
+
+ readAPListRid(local, &APList_rid);
+ readSsidRid(local, &SSID_rid);
+ reset_airo_card(dev);
+ disable_MAC(local, 1);
+ writeSsidRid(local, &SSID_rid);
+ writeAPListRid(local, &APList_rid);
+ }
+ writeConfigRid(local, 1);
+ enable_MAC(local, &rsp, 1);
+ if (local->need_commit > 1)
+ airo_set_promisc(local);
return 0;
}
@@ -5426,6 +5545,12 @@
(iw_handler) NULL, /* SIOCGIWPRIV */
(iw_handler) NULL, /* SIOCSIWSTATS */
(iw_handler) NULL, /* SIOCGIWSTATS */
+#if WIRELESS_EXT > 15
+ iw_handler_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+#else /* WIRELESS_EXT > 15 */
#ifdef WIRELESS_SPY
(iw_handler) airo_set_spy, /* SIOCSIWSPY */
(iw_handler) airo_get_spy, /* SIOCGIWSPY */
@@ -5435,6 +5560,7 @@
#endif /* WIRELESS_SPY */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
+#endif /* WIRELESS_EXT > 15 */
(iw_handler) airo_set_wap, /* SIOCSIWAP */
(iw_handler) airo_get_wap, /* SIOCGIWAP */
(iw_handler) NULL, /* -- hole -- */
@@ -5488,6 +5614,10 @@
standard: (iw_handler *) airo_handler,
private: (iw_handler *) airo_private_handler,
private_args: (struct iw_priv_args *) airo_private_args,
+#if WIRELESS_EXT > 15
+ spy_offset: ((void *) (&((struct airo_info *) NULL)->spy_data) -
+ (void *) NULL),
+#endif /* WIRELESS_EXT > 15 */
};
#endif /* WIRELESS_EXT > 12 */
@@ -5822,7 +5952,7 @@
break;
}
- /* Seperate R/W functions bracket legality here
+ /* Separate R/W functions bracket legality here
*/
if ( com.command <= AIROGMICSTATS )
rc = readrids(dev,&com);
@@ -5860,7 +5990,6 @@
*
* TODO :
* o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
- * o Find the noise level
*
* Jean
*/
@@ -5873,7 +6002,7 @@
/* Get stats out of the card */
readStatusRid(local, &status_rid);
- readStatsRid(local, &stats_rid, RID_STATS);
+ readStatsRid(local, &stats_rid, RID_STATS, 1);
/* The status */
local->wstats.status = status_rid.mode;
@@ -5884,8 +6013,13 @@
local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
else
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
- local->wstats.qual.noise = 0;
- local->wstats.qual.updated = 3;
+ if (status_rid.len >= 124) {
+ local->wstats.qual.noise = 256 - status_rid.noisedBm;
+ local->wstats.qual.updated = 7;
+ } else {
+ local->wstats.qual.noise = 0;
+ local->wstats.qual.updated = 3;
+ }
/* Packets discarded in the wireless adapter due to wireless
* specific problems */
@@ -5900,6 +6034,7 @@
#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
+#define RIDS_SIZE 2048
/*
* This just translates from driver IOCTL codes to the command codes to
* feed to the radio's host interface. Things can be added/deleted
@@ -5908,7 +6043,7 @@
*/
static int readrids(struct net_device *dev, aironet_ioctl *comp) {
unsigned short ridcode;
- unsigned char iobuf[2048];
+ unsigned char *iobuf;
struct airo_info *ai = dev->priv;
if (ai->flags & FLAG_FLASHING)
@@ -5917,7 +6052,7 @@
switch(comp->command)
{
case AIROGCAP: ridcode = RID_CAPABILITIES; break;
- case AIROGCFG: writeConfigRid (ai);
+ case AIROGCFG: writeConfigRid (ai, 1);
ridcode = RID_CONFIG; break;
case AIROGSLIST: ridcode = RID_SSID; break;
case AIROGVLIST: ridcode = RID_APLIST; break;
@@ -5946,15 +6081,21 @@
break;
}
- PC4500_readrid(ai,ridcode,iobuf,sizeof(iobuf));
+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ PC4500_readrid(ai,ridcode,iobuf,RIDS_SIZE, 1);
/* get the count of bytes in the rid docs say 1st 2 bytes is it.
* then return it to the user
* 9/22/2000 Honor user given length
*/
if (copy_to_user(comp->data, iobuf,
- min((int)comp->len, (int)sizeof(iobuf))))
+ min((int)comp->len, (int)RIDS_SIZE))) {
+ kfree (iobuf);
return -EFAULT;
+ }
+ kfree (iobuf);
return 0;
}
@@ -5966,8 +6107,8 @@
struct airo_info *ai = dev->priv;
int ridcode, enabled;
Resp rsp;
- static int (* writer)(struct airo_info *, u16 rid, const void *, int);
- unsigned char iobuf[2048];
+ static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
+ unsigned char *iobuf;
/* Only super-user can write RIDs */
if (!capable(CAP_NET_ADMIN))
@@ -5996,7 +6137,7 @@
* same with MAC off
*/
case AIROPMACON:
- if (enable_MAC(ai, &rsp) != 0)
+ if (enable_MAC(ai, &rsp, 1) != 0)
return -EIO;
return 0;
@@ -6005,7 +6146,7 @@
* as disable_MAC. it's probably so short the compiler does not gen one.
*/
case AIROPMACOFF:
- disable_MAC(ai);
+ disable_MAC(ai, 1);
return 0;
/* This command merely clears the counts does not actually store any data
@@ -6013,25 +6154,36 @@
* writerid routines.
*/
case AIROPSTCLR:
- PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,sizeof(iobuf));
+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDS_SIZE, 1);
enabled = ai->micstats.enabled;
memset(&ai->micstats,0,sizeof(ai->micstats));
ai->micstats.enabled = enabled;
if (copy_to_user(comp->data, iobuf,
- min((int)comp->len, (int)sizeof(iobuf))))
+ min((int)comp->len, (int)RIDS_SIZE))) {
+ kfree (iobuf);
return -EFAULT;
+ }
+ kfree (iobuf);
return 0;
default:
return -EOPNOTSUPP; /* Blarg! */
}
- if(comp->len > sizeof(iobuf))
+ if(comp->len > RIDS_SIZE)
return -EINVAL;
- if (copy_from_user(iobuf,comp->data,comp->len))
+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(iobuf,comp->data,comp->len)) {
+ kfree (iobuf);
return -EFAULT;
+ }
if (comp->command == AIROPCFG) {
ConfigRid *cfg = (ConfigRid *)iobuf;
@@ -6045,8 +6197,11 @@
ai->flags &= ~FLAG_ADHOC;
}
- if((*writer)(ai, ridcode, iobuf,comp->len))
+ if((*writer)(ai, ridcode, iobuf,comp->len,1)) {
+ kfree (iobuf);
return -EIO;
+ }
+ kfree (iobuf);
return 0;
}
@@ -6125,7 +6280,7 @@
*/
int cmdreset(struct airo_info *ai) {
- disable_MAC(ai);
+ disable_MAC(ai, 1);
if(!waitbusy (ai)){
printk(KERN_INFO "Waitbusy hang before RESET\n");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)