Commit 654f4201 authored by Javier Achirica's avatar Javier Achirica Committed by Jeff Garzik

[wireless airo] Replaces task queues by simpler kernel_thread

parent 068a96bf
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/workqueue.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -959,8 +959,6 @@ static void disable_MAC(struct airo_info *ai, int lock); ...@@ -959,8 +959,6 @@ static void disable_MAC(struct airo_info *ai, int lock);
static void enable_interrupts(struct airo_info*); static void enable_interrupts(struct airo_info*);
static void disable_interrupts(struct airo_info*); static void disable_interrupts(struct airo_info*);
static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
static u16 sendcommand(struct airo_info *ai, Cmd *pCmd);
static void completecommand(struct airo_info *ai, Resp *pRsp);
static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap); static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap); int whichbap);
...@@ -980,6 +978,8 @@ static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket); ...@@ -980,6 +978,8 @@ static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
*regs); *regs);
static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
#ifdef WIRELESS_EXT #ifdef WIRELESS_EXT
struct iw_statistics *airo_get_wireless_stats (struct net_device *dev); struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
...@@ -990,8 +990,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp); ...@@ -990,8 +990,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp);
int flashcard(struct net_device *dev, aironet_ioctl *comp); int flashcard(struct net_device *dev, aironet_ioctl *comp);
#endif /* CISCO_EXT */ #endif /* CISCO_EXT */
#ifdef MICSUPPORT #ifdef MICSUPPORT
static void micinit(struct airo_info *ai, MICRid *micr); static void micinit(struct airo_info *ai);
static void micsetup(struct airo_info *ai); static int micsetup(struct airo_info *ai);
static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen); static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
#endif #endif
...@@ -1009,41 +1009,50 @@ struct airo_info { ...@@ -1009,41 +1009,50 @@ struct airo_info {
int need_commit; // Need to set config int need_commit; // Need to set config
char keyindex; // Used with auto wep char keyindex; // Used with auto wep
char defindex; // Used with auto wep char defindex; // Used with auto wep
struct timer_list timer;
struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_entry;
struct airo_info *next; struct airo_info *next;
spinlock_t aux_lock; spinlock_t aux_lock;
unsigned long flags; unsigned long flags;
#define FLAG_PROMISC IFF_PROMISC /* 0x100 - include/linux/if.h */ #define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */
#define FLAG_RADIO_OFF 0x02 /* User disabling of MAC */ #define FLAG_RADIO_OFF 0 /* User disabling of MAC */
#define FLAG_RADIO_DOWN 0x08 /* ifup/ifdown disabling of MAC */ #define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */
#define FLAG_FLASHING 0x10 #define FLAG_RADIO_MASK 0x03
#define FLAG_ADHOC 0x01 /* Needed by MIC */ #define FLAG_FLASHING 2
#define FLAG_MIC_CAPABLE 0x20 #define FLAG_ADHOC 3 /* Needed by MIC */
#define FLAG_UPDATE_MULTI 0x40 #define FLAG_MIC_CAPABLE 4
#define FLAG_UPDATE_UNI 0x80 #define FLAG_UPDATE_MULTI 5
#define FLAG_802_11 0x200 #define FLAG_UPDATE_UNI 6
#define FLAG_PENDING_XMIT 0x400 #define FLAG_802_11 7
#define FLAG_PENDING_XMIT11 0x800 #define FLAG_PENDING_XMIT 9
#define FLAG_PCI 0x1000 #define FLAG_PENDING_XMIT11 10
#define FLAG_PCI 11
#define JOB_MASK 0xff0000
#define JOB_DIE 16
#define JOB_XMIT 17
#define JOB_XMIT11 18
#define JOB_STATS 19
#define JOB_PROMISC 20
#define JOB_MIC 21
#define JOB_EVENT 22
#define JOB_AUTOWEP 23
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap); int whichbap);
unsigned short *flash; unsigned short *flash;
tdsRssiEntry *rssi; tdsRssiEntry *rssi;
struct semaphore sem;
struct task_struct *task; struct task_struct *task;
struct work_struct stats_task; struct semaphore sem;
struct work_struct promisc_task; pid_t thr_pid;
wait_queue_head_t thr_wait;
struct completion thr_exited;
unsigned long expires;
struct { struct {
struct sk_buff *skb; struct sk_buff *skb;
int fid; int fid;
struct work_struct task;
} xmit, xmit11; } xmit, xmit11;
struct net_device *wifidev; struct net_device *wifidev;
#ifdef WIRELESS_EXT #ifdef WIRELESS_EXT
struct iw_statistics wstats; // wireless stats struct iw_statistics wstats; // wireless stats
unsigned long scan_timestamp; /* Time started to scan */ unsigned long scan_timestamp; /* Time started to scan */
struct work_struct event_task;
#if WIRELESS_EXT > 15 #if WIRELESS_EXT > 15
struct iw_spy_data spy_data; struct iw_spy_data spy_data;
#else /* WIRELESS_EXT > 15 */ #else /* WIRELESS_EXT > 15 */
...@@ -1057,7 +1066,6 @@ struct airo_info { ...@@ -1057,7 +1066,6 @@ struct airo_info {
/* MIC stuff */ /* MIC stuff */
mic_module mod[2]; mic_module mod[2];
mic_statistics micstats; mic_statistics micstats;
struct work_struct mic_task;
}; };
static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
...@@ -1207,9 +1215,9 @@ static int writeConfigRid(struct airo_info*ai, int lock) { ...@@ -1207,9 +1215,9 @@ static int writeConfigRid(struct airo_info*ai, int lock) {
cfgr = ai->config; cfgr = ai->config;
if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS) if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS)
ai->flags |= FLAG_ADHOC; set_bit(FLAG_ADHOC, &ai->flags);
else else
ai->flags &= ~FLAG_ADHOC; clear_bit(FLAG_ADHOC, &ai->flags);
for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s); for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);
...@@ -1273,7 +1281,7 @@ static int airo_open(struct net_device *dev) { ...@@ -1273,7 +1281,7 @@ static int airo_open(struct net_device *dev) {
struct airo_info *info = dev->priv; struct airo_info *info = dev->priv;
Resp rsp; Resp rsp;
if (info->flags & FLAG_FLASHING) if (test_bit(FLAG_FLASHING, &info->flags))
return -EIO; return -EIO;
/* Make sure the card is configured. /* Make sure the card is configured.
...@@ -1287,7 +1295,7 @@ static int airo_open(struct net_device *dev) { ...@@ -1287,7 +1295,7 @@ static int airo_open(struct net_device *dev) {
if (info->wifidev != dev) { if (info->wifidev != dev) {
/* Power on the MAC controller (which may have been disabled) */ /* Power on the MAC controller (which may have been disabled) */
info->flags &= ~FLAG_RADIO_DOWN; clear_bit(FLAG_RADIO_DOWN, &info->flags);
enable_interrupts(info); enable_interrupts(info);
} }
enable_MAC(info, &rsp, 1); enable_MAC(info, &rsp, 1);
...@@ -1345,7 +1353,7 @@ static void get_tx_error(struct airo_info *ai, u32 fid) ...@@ -1345,7 +1353,7 @@ static void get_tx_error(struct airo_info *ai, u32 fid)
} }
} }
static void airo_do_xmit(struct net_device *dev) { static void airo_end_xmit(struct net_device *dev) {
u16 status; u16 status;
int i; int i;
struct airo_info *priv = dev->priv; struct airo_info *priv = dev->priv;
...@@ -1353,17 +1361,10 @@ static void airo_do_xmit(struct net_device *dev) { ...@@ -1353,17 +1361,10 @@ static void airo_do_xmit(struct net_device *dev) {
int fid = priv->xmit.fid; int fid = priv->xmit.fid;
u32 *fids = priv->fids; u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) { clear_bit(JOB_XMIT, &priv->flags);
priv->flags |= FLAG_PENDING_XMIT; clear_bit(FLAG_PENDING_XMIT, &priv->flags);
netif_stop_queue(dev);
priv->xmit.task.func = (void (*)(void *))airo_do_xmit;
priv->xmit.task.data = (void *)dev;
schedule_work(&priv->xmit.task);
return;
}
status = transmit_802_3_packet (priv, fids[fid], skb->data); status = transmit_802_3_packet (priv, fids[fid], skb->data);
up(&priv->sem); up(&priv->sem);
priv->flags &= ~FLAG_PENDING_XMIT;
i = 0; i = 0;
if ( status == SUCCESS ) { if ( status == SUCCESS ) {
...@@ -1407,11 +1408,17 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { ...@@ -1407,11 +1408,17 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
fids[i] |= (len << 16); fids[i] |= (len << 16);
priv->xmit.skb = skb; priv->xmit.skb = skb;
priv->xmit.fid = i; priv->xmit.fid = i;
airo_do_xmit(dev); if (down_trylock(&priv->sem) != 0) {
set_bit(FLAG_PENDING_XMIT, &priv->flags);
netif_stop_queue(dev);
set_bit(JOB_XMIT, &priv->flags);
wake_up_interruptible(&priv->thr_wait);
} else
airo_end_xmit(dev);
return 0; return 0;
} }
static void airo_do_xmit11(struct net_device *dev) { static void airo_end_xmit11(struct net_device *dev) {
u16 status; u16 status;
int i; int i;
struct airo_info *priv = dev->priv; struct airo_info *priv = dev->priv;
...@@ -1419,17 +1426,10 @@ static void airo_do_xmit11(struct net_device *dev) { ...@@ -1419,17 +1426,10 @@ static void airo_do_xmit11(struct net_device *dev) {
int fid = priv->xmit11.fid; int fid = priv->xmit11.fid;
u32 *fids = priv->fids; u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) { clear_bit(JOB_XMIT11, &priv->flags);
priv->flags |= FLAG_PENDING_XMIT11; clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
netif_stop_queue(dev);
priv->xmit11.task.func = (void (*)(void *))airo_do_xmit11;
priv->xmit11.task.data = (void *)dev;
schedule_work(&priv->xmit11.task);
return;
}
status = transmit_802_11_packet (priv, fids[fid], skb->data); status = transmit_802_11_packet (priv, fids[fid], skb->data);
up(&priv->sem); up(&priv->sem);
priv->flags &= ~FLAG_PENDING_XMIT11;
i = MAX_FIDS / 2; i = MAX_FIDS / 2;
if ( status == SUCCESS ) { if ( status == SUCCESS ) {
...@@ -1473,7 +1473,13 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { ...@@ -1473,7 +1473,13 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
fids[i] |= (len << 16); fids[i] |= (len << 16);
priv->xmit11.skb = skb; priv->xmit11.skb = skb;
priv->xmit11.fid = i; priv->xmit11.fid = i;
airo_do_xmit11(dev); if (down_trylock(&priv->sem) != 0) {
set_bit(FLAG_PENDING_XMIT11, &priv->flags);
netif_stop_queue(dev);
set_bit(JOB_XMIT11, &priv->flags);
wake_up_interruptible(&priv->thr_wait);
} else
airo_end_xmit11(dev);
return 0; return 0;
} }
...@@ -1481,29 +1487,24 @@ static void airo_read_stats(struct airo_info *ai) { ...@@ -1481,29 +1487,24 @@ static void airo_read_stats(struct airo_info *ai) {
StatsRid stats_rid; StatsRid stats_rid;
u32 *vals = stats_rid.vals; u32 *vals = stats_rid.vals;
if (down_trylock(&ai->sem) == 0) { clear_bit(JOB_STATS, &ai->flags);
readStatsRid(ai, &stats_rid, RID_STATS, 0); readStatsRid(ai, &stats_rid, RID_STATS, 0);
up(&ai->sem); up(&ai->sem);
ai->stats.rx_packets = vals[43] + vals[44] + vals[45]; ai->stats.rx_packets = vals[43] + vals[44] + vals[45];
ai->stats.tx_packets = vals[39] + vals[40] + vals[41]; ai->stats.tx_packets = vals[39] + vals[40] + vals[41];
ai->stats.rx_bytes = vals[92]; ai->stats.rx_bytes = vals[92];
ai->stats.tx_bytes = vals[91]; ai->stats.tx_bytes = vals[91];
ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; 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.tx_errors = vals[42] + ai->stats.tx_fifo_errors;
ai->stats.multicast = vals[43]; ai->stats.multicast = vals[43];
ai->stats.collisions = vals[89]; ai->stats.collisions = vals[89];
/* detailed rx_errors: */ /* detailed rx_errors: */
ai->stats.rx_length_errors = vals[3]; ai->stats.rx_length_errors = vals[3];
ai->stats.rx_crc_errors = vals[4]; ai->stats.rx_crc_errors = vals[4];
ai->stats.rx_frame_errors = vals[2]; ai->stats.rx_frame_errors = vals[2];
ai->stats.rx_fifo_errors = vals[0]; ai->stats.rx_fifo_errors = vals[0];
} else {
ai->stats_task.func = (void (*)(void *))airo_read_stats;
ai->stats_task.data = (void *)ai;
schedule_work(&ai->stats_task);
}
} }
struct net_device_stats *airo_get_stats(struct net_device *dev) struct net_device_stats *airo_get_stats(struct net_device *dev)
...@@ -1511,46 +1512,37 @@ struct net_device_stats *airo_get_stats(struct net_device *dev) ...@@ -1511,46 +1512,37 @@ struct net_device_stats *airo_get_stats(struct net_device *dev)
struct airo_info *local = dev->priv; struct airo_info *local = dev->priv;
/* Get stats out of the card if available */ /* Get stats out of the card if available */
airo_read_stats(local); if (down_trylock(&local->sem) != 0) {
set_bit(JOB_STATS, &local->flags);
wake_up_interruptible(&local->thr_wait);
} else
airo_read_stats(local);
return &local->stats; return &local->stats;
} }
static void airo_end_promisc(struct airo_info *ai) {
Resp rsp;
if ((IN4500(ai, EVSTAT) & EV_CMD) != 0) {
completecommand(ai, &rsp);
up(&ai->sem);
} else {
ai->promisc_task.func = (void (*)(void *))airo_end_promisc;
ai->promisc_task.data = (void *)ai;
schedule_work(&ai->promisc_task);
}
}
static void airo_set_promisc(struct airo_info *ai) { static void airo_set_promisc(struct airo_info *ai) {
Cmd cmd; Cmd cmd;
Resp rsp;
if (down_trylock(&ai->sem) == 0) { memset(&cmd, 0, sizeof(cmd));
memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_SETMODE;
cmd.cmd=CMD_SETMODE; clear_bit(JOB_PROMISC, &ai->flags);
cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
sendcommand(ai, &cmd); issuecommand(ai, &cmd, &rsp);
airo_end_promisc(ai); up(&ai->sem);
} else {
ai->promisc_task.func = (void (*)(void *))airo_set_promisc;
ai->promisc_task.data = (void *)ai;
schedule_work(&ai->promisc_task);
}
} }
static void airo_set_multicast_list(struct net_device *dev) { static void airo_set_multicast_list(struct net_device *dev) {
struct airo_info *ai = dev->priv; struct airo_info *ai = dev->priv;
if ((dev->flags ^ ai->flags) & IFF_PROMISC) { if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
ai->flags ^= IFF_PROMISC; change_bit(FLAG_PROMISC, &ai->flags);
airo_set_promisc(ai); if (down_trylock(&ai->sem) != 0) {
set_bit(JOB_PROMISC, &ai->flags);
wake_up_interruptible(&ai->thr_wait);
} else
airo_set_promisc(ai);
} }
if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
...@@ -1596,7 +1588,7 @@ static int airo_close(struct net_device *dev) { ...@@ -1596,7 +1588,7 @@ static int airo_close(struct net_device *dev) {
* That's the method that is most friendly towards the network * That's the method that is most friendly towards the network
* stack (i.e. the network stack won't try to broadcast * stack (i.e. the network stack won't try to broadcast
* anything on the interface and routes are gone. Jean II */ * anything on the interface and routes are gone. Jean II */
ai->flags |= FLAG_RADIO_DOWN; set_bit(FLAG_RADIO_DOWN, &ai->flags);
disable_MAC(ai, 1); disable_MAC(ai, 1);
#endif #endif
disable_interrupts( ai ); disable_interrupts( ai );
...@@ -1611,8 +1603,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) ...@@ -1611,8 +1603,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
struct airo_info *ai = dev->priv; struct airo_info *ai = dev->priv;
disable_interrupts(ai); disable_interrupts(ai);
free_irq( dev->irq, dev ); free_irq( dev->irq, dev );
if (auto_wep)
del_timer_sync(&ai->timer);
takedown_proc_entry( dev, ai ); takedown_proc_entry( dev, ai );
if (ai->registered) { if (ai->registered) {
unregister_netdev( dev ); unregister_netdev( dev );
...@@ -1623,7 +1613,9 @@ void stop_airo_card( struct net_device *dev, int freeres ) ...@@ -1623,7 +1613,9 @@ void stop_airo_card( struct net_device *dev, int freeres )
} }
ai->registered = 0; ai->registered = 0;
} }
flush_scheduled_work(); set_bit(JOB_DIE, &ai->flags);
kill_proc(ai->thr_pid, SIGTERM, 1);
wait_for_completion(&ai->thr_exited);
if (ai->flash) if (ai->flash)
kfree(ai->flash); kfree(ai->flash);
if (ai->rssi) if (ai->rssi)
...@@ -1728,9 +1720,14 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ) ...@@ -1728,9 +1720,14 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
sema_init(&ai->sem, 1); sema_init(&ai->sem, 1);
ai->need_commit = 0; ai->need_commit = 0;
ai->config.len = 0; ai->config.len = 0;
init_waitqueue_head (&ai->thr_wait);
init_completion (&ai->thr_exited);
ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
if (ai->thr_pid < 0)
goto err_out_free;
rc = add_airo_dev( dev ); rc = add_airo_dev( dev );
if (rc) if (rc)
goto err_out_free; goto err_out_thr;
/* The Airo-specific entries in the device structure. */ /* The Airo-specific entries in the device structure. */
dev->hard_start_xmit = &airo_start_xmit; dev->hard_start_xmit = &airo_start_xmit;
...@@ -1770,7 +1767,7 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ) ...@@ -1770,7 +1767,7 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
} }
} else { } else {
ai->bap_read = fast_bap_read; ai->bap_read = fast_bap_read;
ai->flags |= FLAG_FLASHING; set_bit(FLAG_FLASHING, &ai->flags);
} }
rc = register_netdev(dev); rc = register_netdev(dev);
...@@ -1801,6 +1798,10 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ) ...@@ -1801,6 +1798,10 @@ struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
err_out_unlink: err_out_unlink:
del_airo_dev(dev); del_airo_dev(dev);
err_out_thr:
set_bit(JOB_DIE, &ai->flags);
kill_proc(ai->thr_pid, SIGTERM, 1);
wait_for_completion(&ai->thr_exited);
err_out_free: err_out_free:
kfree(dev); kfree(dev);
return NULL; return NULL;
...@@ -1864,38 +1865,102 @@ static void airo_send_event(struct net_device *dev) { ...@@ -1864,38 +1865,102 @@ static void airo_send_event(struct net_device *dev) {
union iwreq_data wrqu; union iwreq_data wrqu;
StatusRid status_rid; StatusRid status_rid;
if (down_trylock(&ai->sem) == 0) { clear_bit(JOB_EVENT, &ai->flags);
PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
up(&ai->sem); up(&ai->sem);
wrqu.data.length = 0; wrqu.data.length = 0;
wrqu.data.flags = 0; wrqu.data.flags = 0;
memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN); memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER; wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */ /* Send event to user space */
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
} else {
ai->event_task.func = (void (*)(void *))airo_send_event;
ai->event_task.data = (void *)dev;
schedule_work(&ai->event_task);
}
} }
#endif #endif
static void airo_read_mic(struct airo_info *ai) { static int airo_thread(void *data) {
MICRid mic_rid; struct net_device *dev = data;
struct airo_info *ai = dev->priv;
int locked;
daemonize("%s", dev->name);
allow_signal(SIGTERM);
if (down_trylock(&ai->sem) == 0) { while(1) {
PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); if (signal_pending(current))
up(&ai->sem); flush_signals(current);
/* make swsusp happy with our thread */
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
if (test_bit(JOB_DIE, &ai->flags))
break;
if (ai->flags & JOB_MASK) {
locked = down_interruptible(&ai->sem);
} else {
wait_queue_t wait;
init_waitqueue_entry(&wait, current);
add_wait_queue(&ai->thr_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (ai->flags & JOB_MASK)
break;
if (ai->expires) {
if (time_after_eq(jiffies,ai->expires)){
set_bit(JOB_AUTOWEP,&ai->flags);
break;
}
if (!signal_pending(current)) {
schedule_timeout(ai->expires - jiffies);
continue;
}
} else if (!signal_pending(current)) {
schedule();
continue;
}
break;
}
current->state = TASK_RUNNING;
remove_wait_queue(&ai->thr_wait, &wait);
locked = 1;
}
if (locked)
continue;
if (test_bit(JOB_DIE, &ai->flags)) {
up(&ai->sem);
break;
}
if (test_bit(FLAG_FLASHING, &ai->flags)) {
up(&ai->sem);
continue;
}
if (test_bit(JOB_XMIT, &ai->flags))
airo_end_xmit(dev);
else if (test_bit(JOB_XMIT11, &ai->flags))
airo_end_xmit11(dev);
else if (test_bit(JOB_STATS, &ai->flags))
airo_read_stats(ai);
else if (test_bit(JOB_PROMISC, &ai->flags))
airo_set_promisc(ai);
#ifdef MICSUPPORT #ifdef MICSUPPORT
micinit (ai, &mic_rid); else if (test_bit(JOB_MIC, &ai->flags))
micinit(ai);
#endif #endif
} else { #if WIRELESS_EXT > 13
ai->mic_task.func = (void (*)(void *))airo_read_mic; else if (test_bit(JOB_EVENT, &ai->flags))
ai->mic_task.data = (void *)ai; airo_send_event(dev);
schedule_work(&ai->mic_task); #endif
else if (test_bit(JOB_AUTOWEP, &ai->flags))
timer_func(dev);
} }
complete_and_exit (&ai->thr_exited, 0);
} }
static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) { static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
...@@ -1927,8 +1992,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -1927,8 +1992,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
if ( status & EV_MIC ) { if ( status & EV_MIC ) {
OUT4500( apriv, EVACK, EV_MIC ); OUT4500( apriv, EVACK, EV_MIC );
if (apriv->flags & FLAG_MIC_CAPABLE) #ifdef MICSUPPORT
airo_read_mic( apriv ); if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_MIC, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
micinit (apriv);
}
#endif
} }
if ( status & EV_LINK ) { if ( status & EV_LINK ) {
#if WIRELESS_EXT > 13 #if WIRELESS_EXT > 13
...@@ -1970,15 +2042,18 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -1970,15 +2042,18 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
#define RC_NOAUTH 9 /* Station requesting (Re)Association is not #define RC_NOAUTH 9 /* Station requesting (Re)Association is not
Authenticated with the responding station */ Authenticated with the responding station */
if (newStatus != ASSOCIATED) { if (newStatus != ASSOCIATED) {
if (auto_wep && !timer_pending(&apriv->timer)) { if (auto_wep && !apriv->expires) {
apriv->timer.expires = RUN_AT(HZ*3); apriv->expires = RUN_AT(3*HZ);
add_timer(&apriv->timer); wake_up_interruptible(&apriv->thr_wait);
} }
} else { } else {
struct task_struct *task = apriv->task; struct task_struct *task = apriv->task;
if (auto_wep)
apriv->expires = 0;
if (task) if (task)
wake_up_process (task); wake_up_process (task);
apriv->flags|=FLAG_UPDATE_UNI|FLAG_UPDATE_MULTI; set_bit(FLAG_UPDATE_UNI, &apriv->flags);
set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
} }
#if WIRELESS_EXT > 13 #if WIRELESS_EXT > 13
/* Question : is ASSOCIATED the only status /* Question : is ASSOCIATED the only status
...@@ -1999,7 +2074,11 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -1999,7 +2074,11 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
apriv->scan_timestamp = 0; apriv->scan_timestamp = 0;
} }
airo_send_event(dev); if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
airo_send_event(dev);
} else { } else {
memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER; wrqu.ap_addr.sa_family = ARPHRD_ETHER;
...@@ -2030,7 +2109,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2030,7 +2109,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
fid = IN4500( apriv, RXFID ); fid = IN4500( apriv, RXFID );
/* Get the packet length */ /* Get the packet length */
if (apriv->flags & FLAG_802_11) { if (test_bit(FLAG_802_11, &apriv->flags)) {
bap_setup (apriv, fid, 4, BAP0); bap_setup (apriv, fid, 4, BAP0);
bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0); bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0);
/* Bad CRC. Ignore packet */ /* Bad CRC. Ignore packet */
...@@ -2049,7 +2128,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2049,7 +2128,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
len = 0; len = 0;
} }
if (len) { if (len) {
if (apriv->flags & FLAG_802_11) { if (test_bit(FLAG_802_11, &apriv->flags)) {
bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0); bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);
fc = le16_to_cpu(fc); fc = le16_to_cpu(fc);
switch (fc & 0xc) { switch (fc & 0xc) {
...@@ -2078,7 +2157,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2078,7 +2157,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
} }
if (len) { if (len) {
buffer = (u16*)skb_put (skb, len + hdrlen); buffer = (u16*)skb_put (skb, len + hdrlen);
if (apriv->flags & FLAG_802_11) { if (test_bit(FLAG_802_11, &apriv->flags)) {
buffer[0] = fc; buffer[0] = fc;
bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
if (hdrlen == 24) if (hdrlen == 24)
...@@ -2125,11 +2204,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2125,11 +2204,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
char *sa; char *sa;
struct iw_quality wstats; struct iw_quality wstats;
/* Prepare spy data : addr + qual */ /* Prepare spy data : addr + qual */
sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6); if (!test_bit(FLAG_802_11, &apriv->flags)) {
if (!(apriv->flags & FLAG_802_11)) { sa = (char*)buffer + 6;
bap_setup (apriv, fid, 8, BAP0); bap_setup (apriv, fid, 8, BAP0);
bap_read (apriv, (u16*)hdr.rssi, 2, BAP0); bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
} } else
sa = (char*)buffer + 10;
wstats.qual = hdr.rssi[0]; wstats.qual = hdr.rssi[0];
if (apriv->rssi) if (apriv->rssi)
wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
...@@ -2146,12 +2226,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2146,12 +2226,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
int i; int i;
char *sa; char *sa;
sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6); sa = (char*)buffer + (test_bit(FLAG_802_11, &apriv->flags) ? 10 : 6);
for (i=0; i<apriv->spy_number; i++) for (i=0; i<apriv->spy_number; i++)
if (!memcmp(sa,apriv->spy_address[i],ETH_ALEN)) if (!memcmp(sa,apriv->spy_address[i],ETH_ALEN))
{ {
if (!(apriv->flags & FLAG_802_11)) { if (!test_bit(FLAG_802_11, &apriv->flags)) {
bap_setup (apriv, fid, 8, BAP0); bap_setup (apriv, fid, 8, BAP0);
bap_read (apriv, (u16*)hdr.rssi, 2, BAP0); bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
} }
...@@ -2169,7 +2249,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2169,7 +2249,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
#endif /* WIRELESS_EXT > 15 */ #endif /* WIRELESS_EXT > 15 */
OUT4500( apriv, EVACK, EV_RX); OUT4500( apriv, EVACK, EV_RX);
if (apriv->flags & FLAG_802_11) { if (test_bit(FLAG_802_11, &apriv->flags)) {
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
skb->dev = apriv->wifidev; skb->dev = apriv->wifidev;
...@@ -2207,10 +2287,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2207,10 +2287,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
/* Set up to be used again */ /* Set up to be used again */
apriv->fids[index] &= 0xffff; apriv->fids[index] &= 0xffff;
if (index < MAX_FIDS / 2) { if (index < MAX_FIDS / 2) {
if (!(apriv->flags & FLAG_PENDING_XMIT)) if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
netif_wake_queue(dev); netif_wake_queue(dev);
} else { } else {
if (!(apriv->flags & FLAG_PENDING_XMIT11)) if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
netif_wake_queue(apriv->wifidev); netif_wake_queue(apriv->wifidev);
} }
} else { } else {
...@@ -2270,7 +2350,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { ...@@ -2270,7 +2350,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
* instead of this flag, but I don't trust it *within* the * instead of this flag, but I don't trust it *within* the
* open/close functions, and testing both flags together is * open/close functions, and testing both flags together is
* "cheaper" - Jean II */ * "cheaper" - Jean II */
if (ai->flags & (FLAG_RADIO_OFF|FLAG_RADIO_DOWN)) return SUCCESS; if (ai->flags & FLAG_RADIO_MASK) return SUCCESS;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_ENABLE; cmd.cmd = MAC_ENABLE;
if (!lock) if (!lock)
...@@ -2391,10 +2471,10 @@ static u16 setup_card(struct airo_info *ai, u8 *mac) ...@@ -2391,10 +2471,10 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
#ifdef MICSUPPORT #ifdef MICSUPPORT
if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1)) { if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
(micsetup(ai) == SUCCESS)) {
ai->config.opmode |= MODE_MIC; ai->config.opmode |= MODE_MIC;
ai->flags |= FLAG_MIC_CAPABLE; set_bit(FLAG_MIC_CAPABLE, &ai->flags);
micsetup(ai);
} }
#endif #endif
...@@ -2460,34 +2540,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac) ...@@ -2460,34 +2540,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac)
rc = readWepKeyRid(ai, &wkr, 0); rc = readWepKeyRid(ai, &wkr, 0);
} while(lastindex != wkr.kindex); } while(lastindex != wkr.kindex);
if (auto_wep && !timer_pending(&ai->timer)) { if (auto_wep) {
ai->timer.expires = RUN_AT(HZ*3); ai->expires = RUN_AT(3*HZ);
add_timer(&ai->timer); wake_up_interruptible(&ai->thr_wait);
} }
return SUCCESS;
}
static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
// Im really paranoid about letting it run forever!
int max_tries = 600000;
if (sendcommand(ai, pCmd) == (u16)ERROR)
return ERROR;
while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
if (!in_interrupt() && (max_tries & 255) == 0)
schedule();
}
if ( max_tries == -1 ) {
printk( KERN_ERR
"airo: Max tries exceeded waiting for command\n" );
return ERROR;
}
completecommand(ai, pRsp);
return SUCCESS; return SUCCESS;
} }
static u16 sendcommand(struct airo_info *ai, Cmd *pCmd) { static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
// Im really paranoid about letting it run forever! // Im really paranoid about letting it run forever!
int max_tries = 600000; int max_tries = 600000;
u16 cmd; u16 cmd;
...@@ -2506,10 +2567,16 @@ static u16 sendcommand(struct airo_info *ai, Cmd *pCmd) { ...@@ -2506,10 +2567,16 @@ static u16 sendcommand(struct airo_info *ai, Cmd *pCmd) {
"airo: Max tries exceeded when issueing command\n" ); "airo: Max tries exceeded when issueing command\n" );
return ERROR; return ERROR;
} }
return SUCCESS;
}
static void completecommand(struct airo_info *ai, Resp *pRsp) { while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
if (!in_atomic() && (max_tries & 255) == 0)
schedule();
}
if ( max_tries == -1 ) {
printk( KERN_ERR
"airo: Max tries exceeded waiting for command\n" );
return ERROR;
}
// command completed // command completed
pRsp->status = IN4500(ai, STATUS); pRsp->status = IN4500(ai, STATUS);
pRsp->rsp0 = IN4500(ai, RESP0); pRsp->rsp0 = IN4500(ai, RESP0);
...@@ -2522,6 +2589,8 @@ static void completecommand(struct airo_info *ai, Resp *pRsp) { ...@@ -2522,6 +2589,8 @@ static void completecommand(struct airo_info *ai, Resp *pRsp) {
} }
// acknowledge processing the status/response // acknowledge processing the status/response
OUT4500(ai, EVACK, EV_CMD); OUT4500(ai, EVACK, EV_CMD);
return SUCCESS;
} }
/* Sets up the bap to start exchange data. whichbap should /* Sets up the bap to start exchange data. whichbap should
...@@ -2808,7 +2877,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) ...@@ -2808,7 +2877,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
len -= ETH_ALEN * 2; len -= ETH_ALEN * 2;
#ifdef MICSUPPORT #ifdef MICSUPPORT
if ((ai->flags & FLAG_MIC_CAPABLE) && ai->micstats.enabled && if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
(ntohs(((u16 *)pPacket)[6]) != 0x888E)) { (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS) if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
return ERROR; return ERROR;
...@@ -3316,7 +3385,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { ...@@ -3316,7 +3385,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
if ((ai->config.rmode & 0xff) >= RXMODE_RFMON) if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
ai->need_commit = 2; ai->need_commit = 2;
ai->config.rmode &= 0xfe00; ai->config.rmode &= 0xfe00;
ai->flags &= ~FLAG_802_11; clear_bit (FLAG_802_11, &ai->flags);
ai->config.opmode &= 0xFF00; ai->config.opmode &= 0xFF00;
ai->config.scanMode = SCANMODE_ACTIVE; ai->config.scanMode = SCANMODE_ACTIVE;
if ( line[0] == 'a' ) { if ( line[0] == 'a' ) {
...@@ -3326,11 +3395,11 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { ...@@ -3326,11 +3395,11 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
if ( line[0] == 'r' ) { if ( line[0] == 'r' ) {
ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
ai->config.scanMode = SCANMODE_PASSIVE; ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11; set_bit (FLAG_802_11, &ai->flags);
} else if ( line[0] == 'y' ) { } else if ( line[0] == 'y' ) {
ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER; ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
ai->config.scanMode = SCANMODE_PASSIVE; ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11; set_bit (FLAG_802_11, &ai->flags);
} else if ( line[0] == 'l' ) } else if ( line[0] == 'l' )
ai->config.rmode |= RXMODE_LANMON; ai->config.rmode |= RXMODE_LANMON;
} }
...@@ -3341,9 +3410,9 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { ...@@ -3341,9 +3410,9 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
else if (!strncmp(line,"Radio: ", 7)) { else if (!strncmp(line,"Radio: ", 7)) {
line += 7; line += 7;
if (!strncmp(line,"off",3)) { if (!strncmp(line,"off",3)) {
ai->flags |= FLAG_RADIO_OFF; set_bit (FLAG_RADIO_OFF, &ai->flags);
} else { } else {
ai->flags &= ~FLAG_RADIO_OFF; clear_bit (FLAG_RADIO_OFF, &ai->flags);
} }
} }
/*** NodeName processing */ /*** NodeName processing */
...@@ -3545,7 +3614,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) { ...@@ -3545,7 +3614,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
(ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode): (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode):
(ai->config.opmode & 0xFF) == 2 ? "AP" : (ai->config.opmode & 0xFF) == 2 ? "AP" :
(ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error", (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error",
ai->flags&FLAG_RADIO_OFF ? "off" : "on", test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on",
ai->config.nodeName, ai->config.nodeName,
ai->config.powerSaveMode == 0 ? "CAM" : ai->config.powerSaveMode == 0 ? "CAM" :
ai->config.powerSaveMode == 1 ? "PSP" : ai->config.powerSaveMode == 1 ? "PSP" :
...@@ -4003,23 +4072,14 @@ static struct net_device_list { ...@@ -4003,23 +4072,14 @@ static struct net_device_list {
will switch WEP modes to see if that will help. If the card is will switch WEP modes to see if that will help. If the card is
associated we will check every minute to see if anything has associated we will check every minute to see if anything has
changed. */ changed. */
static void timer_func( u_long data ) { static void timer_func( struct net_device *dev ) {
struct net_device *dev = (struct net_device*)data;
struct airo_info *apriv = dev->priv; struct airo_info *apriv = dev->priv;
u16 linkstat = IN4500(apriv, LINKSTAT);
Resp rsp; Resp rsp;
if (!(apriv->flags & FLAG_FLASHING) && (linkstat != 0x400)) {
/* We don't have a link so try changing the authtype */ /* We don't have a link so try changing the authtype */
if (down_trylock(&apriv->sem) != 0) { readConfigRid(apriv, 0);
apriv->timer.expires = RUN_AT(1); disable_MAC(apriv, 0);
add_timer(&apriv->timer); switch(apriv->config.authType) {
return;
}
readConfigRid(apriv, 0);
disable_MAC(apriv, 0);
switch(apriv->config.authType) {
case AUTH_ENCRYPT: case AUTH_ENCRYPT:
/* So drop to OPEN */ /* So drop to OPEN */
apriv->config.authType = AUTH_OPEN; apriv->config.authType = AUTH_OPEN;
...@@ -4038,16 +4098,15 @@ static void timer_func( u_long data ) { ...@@ -4038,16 +4098,15 @@ static void timer_func( u_long data ) {
break; break;
default: /* We'll escalate to SHAREDKEY */ default: /* We'll escalate to SHAREDKEY */
apriv->config.authType = AUTH_SHAREDKEY; apriv->config.authType = AUTH_SHAREDKEY;
} }
apriv->need_commit = 1; apriv->need_commit = 1;
writeConfigRid(apriv, 0); writeConfigRid(apriv, 0);
enable_MAC(apriv, &rsp, 0); enable_MAC(apriv, &rsp, 0);
up(&apriv->sem); up(&apriv->sem);
/* Schedule check to see if the change worked */ /* Schedule check to see if the change worked */
apriv->timer.expires = RUN_AT(HZ*3); clear_bit(JOB_AUTOWEP, &apriv->flags);
add_timer(&apriv->timer); apriv->expires = RUN_AT(HZ*3);
}
} }
static int add_airo_dev( struct net_device *dev ) { static int add_airo_dev( struct net_device *dev ) {
...@@ -4055,15 +4114,6 @@ static int add_airo_dev( struct net_device *dev ) { ...@@ -4055,15 +4114,6 @@ static int add_airo_dev( struct net_device *dev ) {
if ( !node ) if ( !node )
return -ENOMEM; return -ENOMEM;
if ( auto_wep ) {
struct airo_info *apriv=dev->priv;
struct timer_list *timer = &apriv->timer;
timer->function = timer_func;
timer->data = (u_long)dev;
init_timer(timer);
}
node->dev = dev; node->dev = dev;
node->next = airo_devices; node->next = airo_devices;
airo_devices = node; airo_devices = node;
...@@ -4094,7 +4144,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev, ...@@ -4094,7 +4144,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
return -ENODEV; return -ENODEV;
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
((struct airo_info *)dev->priv)->flags |= FLAG_PCI; clear_bit (FLAG_PCI, &((struct airo_info *)dev->priv)->flags);
return 0; return 0;
} }
...@@ -4140,7 +4190,7 @@ static void __exit airo_cleanup_module( void ) ...@@ -4140,7 +4190,7 @@ static void __exit airo_cleanup_module( void )
while( airo_devices ) { while( airo_devices ) {
printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name ); printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
if (((struct airo_info *)airo_devices->dev->priv)->flags & FLAG_PCI) if (test_bit(FLAG_PCI, &((struct airo_info *)airo_devices->dev->priv)->flags))
is_pci = 1; is_pci = 1;
#endif #endif
stop_airo_card( airo_devices->dev, 1 ); stop_airo_card( airo_devices->dev, 1 );
...@@ -4614,28 +4664,28 @@ static int airo_set_mode(struct net_device *dev, ...@@ -4614,28 +4664,28 @@ static int airo_set_mode(struct net_device *dev,
local->config.opmode |= MODE_STA_IBSS; local->config.opmode |= MODE_STA_IBSS;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE; local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; clear_bit (FLAG_802_11, &local->flags);
break; break;
case IW_MODE_INFRA: case IW_MODE_INFRA:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_STA_ESS; local->config.opmode |= MODE_STA_ESS;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE; local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; clear_bit (FLAG_802_11, &local->flags);
break; break;
case IW_MODE_MASTER: case IW_MODE_MASTER:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP; local->config.opmode |= MODE_AP;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE; local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; clear_bit (FLAG_802_11, &local->flags);
break; break;
case IW_MODE_REPEAT: case IW_MODE_REPEAT:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP_RPTR; local->config.opmode |= MODE_AP_RPTR;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE; local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; clear_bit (FLAG_802_11, &local->flags);
break; break;
case IW_MODE_MONITOR: case IW_MODE_MONITOR:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
...@@ -4643,7 +4693,7 @@ static int airo_set_mode(struct net_device *dev, ...@@ -4643,7 +4693,7 @@ static int airo_set_mode(struct net_device *dev,
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
local->config.scanMode = SCANMODE_PASSIVE; local->config.scanMode = SCANMODE_PASSIVE;
local->flags |= FLAG_802_11; set_bit (FLAG_802_11, &local->flags);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -4832,14 +4882,14 @@ static int airo_set_txpow(struct net_device *dev, ...@@ -4832,14 +4882,14 @@ static int airo_set_txpow(struct net_device *dev,
readCapabilityRid(local, &cap_rid); readCapabilityRid(local, &cap_rid);
if (vwrq->disabled) { if (vwrq->disabled) {
local->flags |= FLAG_RADIO_OFF; set_bit (FLAG_RADIO_OFF, &local->flags);
local->need_commit = 1; local->need_commit = 1;
return -EINPROGRESS; /* Call commit handler */ return -EINPROGRESS; /* Call commit handler */
} }
if (vwrq->flags != IW_TXPOW_MWATT) { if (vwrq->flags != IW_TXPOW_MWATT) {
return -EINVAL; return -EINVAL;
} }
local->flags &= ~FLAG_RADIO_OFF; clear_bit (FLAG_RADIO_OFF, &local->flags);
for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
if ((vwrq->value==cap_rid.txPowerLevels[i])) { if ((vwrq->value==cap_rid.txPowerLevels[i])) {
local->config.txPower = vwrq->value; local->config.txPower = vwrq->value;
...@@ -4863,7 +4913,7 @@ static int airo_get_txpow(struct net_device *dev, ...@@ -4863,7 +4913,7 @@ static int airo_get_txpow(struct net_device *dev,
vwrq->value = local->config.txPower; vwrq->value = local->config.txPower;
vwrq->fixed = 1; /* No power control */ vwrq->fixed = 1; /* No power control */
vwrq->disabled = (local->flags & FLAG_RADIO_OFF); vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags);
vwrq->flags = IW_TXPOW_MWATT; vwrq->flags = IW_TXPOW_MWATT;
return 0; return 0;
...@@ -5513,10 +5563,14 @@ static int airo_config_commit(struct net_device *dev, ...@@ -5513,10 +5563,14 @@ static int airo_config_commit(struct net_device *dev,
writeSsidRid(local, &SSID_rid); writeSsidRid(local, &SSID_rid);
writeAPListRid(local, &APList_rid); writeAPListRid(local, &APList_rid);
} }
writeConfigRid(local, 1); if (down_interruptible(&local->sem))
enable_MAC(local, &rsp, 1); return -ERESTARTSYS;
writeConfigRid(local, 0);
enable_MAC(local, &rsp, 0);
if (local->need_commit > 1) if (local->need_commit > 1)
airo_set_promisc(local); airo_set_promisc(local);
else
up(&local->sem);
return 0; return 0;
} }
...@@ -6055,7 +6109,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { ...@@ -6055,7 +6109,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
unsigned char *iobuf; unsigned char *iobuf;
struct airo_info *ai = dev->priv; struct airo_info *ai = dev->priv;
if (ai->flags & FLAG_FLASHING) if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO; return -EIO;
switch(comp->command) switch(comp->command)
...@@ -6123,7 +6177,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { ...@@ -6123,7 +6177,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (ai->flags & FLAG_FLASHING) if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO; return -EIO;
ridcode = 0; ridcode = 0;
...@@ -6197,13 +6251,13 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { ...@@ -6197,13 +6251,13 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
if (comp->command == AIROPCFG) { if (comp->command == AIROPCFG) {
ConfigRid *cfg = (ConfigRid *)iobuf; ConfigRid *cfg = (ConfigRid *)iobuf;
if (ai->flags & FLAG_MIC_CAPABLE) if (test_bit(FLAG_MIC_CAPABLE, &ai->flags))
cfg->opmode |= MODE_MIC; cfg->opmode |= MODE_MIC;
if ((cfg->opmode & 0xFF) == MODE_STA_IBSS) if ((cfg->opmode & 0xFF) == MODE_STA_IBSS)
ai->flags |= FLAG_ADHOC; set_bit (FLAG_ADHOC, &ai->flags);
else else
ai->flags &= ~FLAG_ADHOC; clear_bit (FLAG_ADHOC, &ai->flags);
} }
if((*writer)(ai, ridcode, iobuf,comp->len,1)) { if((*writer)(ai, ridcode, iobuf,comp->len,1)) {
...@@ -6314,7 +6368,7 @@ int cmdreset(struct airo_info *ai) { ...@@ -6314,7 +6368,7 @@ int cmdreset(struct airo_info *ai) {
*/ */
int setflashmode (struct airo_info *ai) { int setflashmode (struct airo_info *ai) {
ai->flags |= FLAG_FLASHING; set_bit (FLAG_FLASHING, &ai->flags);
OUT4500(ai, SWS0, FLASH_COMMAND); OUT4500(ai, SWS0, FLASH_COMMAND);
OUT4500(ai, SWS1, FLASH_COMMAND); OUT4500(ai, SWS1, FLASH_COMMAND);
...@@ -6330,7 +6384,7 @@ int setflashmode (struct airo_info *ai) { ...@@ -6330,7 +6384,7 @@ int setflashmode (struct airo_info *ai) {
schedule_timeout (HZ/2); /* 500ms delay */ schedule_timeout (HZ/2); /* 500ms delay */
if(!waitbusy(ai)) { if(!waitbusy(ai)) {
ai->flags &= ~FLAG_FLASHING; clear_bit (FLAG_FLASHING, &ai->flags);
printk(KERN_INFO "Waitbusy hang after setflash mode\n"); printk(KERN_INFO "Waitbusy hang after setflash mode\n");
return -EIO; return -EIO;
} }
...@@ -6436,7 +6490,7 @@ int flashrestart(struct airo_info *ai,struct net_device *dev){ ...@@ -6436,7 +6490,7 @@ int flashrestart(struct airo_info *ai,struct net_device *dev){
set_current_state (TASK_UNINTERRUPTIBLE); set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (HZ); /* Added 12/7/00 */ schedule_timeout (HZ); /* Added 12/7/00 */
ai->flags &= ~FLAG_FLASHING; clear_bit (FLAG_FLASHING, &ai->flags);
status = setup_card(ai, dev->dev_addr); status = setup_card(ai, dev->dev_addr);
for( i = 0; i < MAX_FIDS; i++ ) { for( i = 0; i < MAX_FIDS; i++ ) {
......
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