patch-2.4.7 linux/drivers/net/wireless/airo.c
Next file: linux/drivers/net/yellowfin.c
Previous file: linux/drivers/net/winbond-840.c
Back to the patch index
Back to the overall index
- Lines: 333
- Date:
Tue Jul 17 18:53:55 2001
- Orig file:
v2.4.6/linux/drivers/net/wireless/airo.c
- Orig date:
Tue Jul 3 17:08:20 2001
diff -u --recursive --new-file v2.4.6/linux/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c
@@ -333,7 +333,8 @@
#define EV_LINK 0x80
#define EV_AWAKE 0x100
#define EV_UNKNOWN 0x800
-#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX | EV_UNKNOWN)
+#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX)
+#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
/* The RIDs */
#define RID_CAPABILITIES 0xFF00
@@ -656,7 +657,6 @@
// A few details needed for WEP (Wireless Equivalent Privacy)
#define MAX_KEY_SIZE 13 // 128 (?) bits
#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP
-#define MAX_KEYS 4 // 4 different keys
typedef struct wep_key_t {
u16 len;
u8 key[16]; /* 40-bit and 104-bit keys */
@@ -724,11 +724,12 @@
spinlock_t aux_lock;
spinlock_t cmd_lock;
int flags;
-#define FLAG_PROMISC 0x01
+#define FLAG_PROMISC IFF_PROMISC
#define FLAG_RADIO_OFF 0x02
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap);
int (*header_parse)(struct sk_buff*, unsigned char *);
+ unsigned short *flash;
#ifdef WIRELESS_EXT
int need_commit; // Need to set config
struct iw_statistics wstats; // wireless stats
@@ -949,10 +950,17 @@
Cmd cmd;
Resp rsp;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmd=CMD_SETMODE;
- cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
- issuecommand(ai, &cmd, &rsp);
+ /* For some reason this command takes a lot of time (~20 ms) and it's
+ * run in an interrupt handler, so we'd better be sure we needed it
+ * before executing it.
+ */
+ if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd=CMD_SETMODE;
+ cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
+ issuecommand(ai, &cmd, &rsp);
+ ai->flags^=IFF_PROMISC;
+ }
if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
/* Turn on multicast. (Should be already setup...) */
@@ -994,6 +1002,8 @@
void stop_airo_card( struct net_device *dev, int freeres )
{
struct airo_info *ai = (struct airo_info*)dev->priv;
+ if (ai->flash)
+ kfree(ai->flash);
takedown_proc_entry( dev, ai );
if (ai->registered) {
unregister_netdev( dev );
@@ -1113,11 +1123,10 @@
}
int reset_airo_card( struct net_device *dev ) {
- int i, flags;
+ int i;
struct airo_info *ai = (struct airo_info*)dev->priv;
disable_MAC(ai);
- spin_lock_irqsave(&ai->cmd_lock, flags);
waitbusy (ai);
OUT4500(ai,COMMAND,CMD_SOFTRESET);
set_current_state (TASK_UNINTERRUPTIBLE);
@@ -1125,7 +1134,6 @@
waitbusy (ai);
set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (HZ/5);
- spin_unlock_irqrestore(&ai->cmd_lock, flags);
if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) {
printk( KERN_ERR "airo: MAC could not be enabled\n" );
return -1;
@@ -1359,10 +1367,10 @@
apriv->stats.tx_errors++;
}
}
- if ( status & ~STATUS_INTS )
+ if ( status & ~STATUS_INTS & ~IGNORE_INTS )
printk( KERN_WARNING
"airo: Got weird status %x\n",
- status & ~STATUS_INTS );
+ status & ~STATUS_INTS & ~IGNORE_INTS );
OUT4500( apriv, EVACK, status & STATUS_INTS );
OUT4500( apriv, EVINTEN, savedInterrupts );
@@ -1446,6 +1454,10 @@
int rc;
memset( &mySsid, 0, sizeof( mySsid ) );
+ if (ai->flash) {
+ kfree (ai->flash);
+ ai->flash = NULL;
+ }
/* The NOP is the first step in getting the card going */
cmd.cmd = NOP;
@@ -1562,6 +1574,10 @@
// PC4500 didn't notice command, try again
OUT4500(ai, COMMAND, pCmd->cmd);
}
+ if (!(max_tries & 255) && !in_interrupt()) {
+ set_current_state(TASK_RUNNING);
+ schedule();
+ }
}
if ( max_tries == -1 ) {
printk( KERN_ERR
@@ -3134,9 +3150,12 @@
/* Set the SSID */
memset(essid, 0, sizeof(essid));
- copy_from_user(essid,
+ if (copy_from_user(essid,
wrq->u.data.pointer,
- wrq->u.data.length);
+ wrq->u.data.length)) {
+ rc = -EFAULT;
+ break;
+ }
memcpy(SSID_rid.ssids[index].ssid, essid,
sizeof(essid) - 1);
SSID_rid.ssids[index].len = wrq->u.data.length - 1;
@@ -3199,7 +3218,11 @@
break;
}
memset(name, 0, sizeof(name));
- copy_from_user(name, wrq->u.data.pointer, wrq->u.data.length);
+ if (copy_from_user(name, wrq->u.data.pointer,
+ wrq->u.data.length)) {
+ rc = -EFAULT;
+ break;
+ }
memcpy(config.nodeName, name, 16);
local->need_commit = 1;
}
@@ -3395,7 +3418,7 @@
break;
}
/* Check the index (none -> use current) */
- if ((index < 0) || (index >= MAX_KEYS))
+ if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1))
index = current_index;
/* Set the length */
if (wrq->u.encoding.length > MIN_KEY_SIZE)
@@ -3433,7 +3456,7 @@
} else {
/* Do we want to just set the transmit key index ? */
int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
- if ((index >= 0) && (index < MAX_KEYS)) {
+ if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) {
set_wep_key(local, index, 0, 0, 1);
} else
/* Don't complain if only change the mode */
@@ -3490,7 +3513,7 @@
}
/* Which key do we want ? -1 -> tx index */
- if((index < 0) || (index >= MAX_KEYS))
+ if((index < 0) || (index >= (cap_rid.softCap&0x80)?4:1))
index = get_wep_key(local, 0xffff);
wrq->u.encoding.flags |= index + 1;
/* Copy the key to the user buffer */
@@ -3614,7 +3637,7 @@
range.num_encoding_sizes = 2;
} else
range.num_encoding_sizes = 1;
- range.max_encoding_tokens = 4; // 4 keys
+ range.max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
} else {
range.num_encoding_sizes = 0;
range.max_encoding_tokens = 0;
@@ -3785,8 +3808,14 @@
memcpy(address[i].sa_data, local->spy_address[i], 6);
address[i].sa_family = AF_UNIX;
}
- copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number);
- copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number);
+ if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number)) {
+ rc = -EFAULT;
+ break;
+ }
+ if (copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number)) {
+ rc = -EFAULT;
+ break;
+ }
for (i=0; i<local->spy_number; i++)
local->spy_stat[i].updated = 0;
}
@@ -3833,7 +3862,10 @@
*/
{
aironet_ioctl com;
- copy_from_user(&com,rq->ifr_data,sizeof(com));
+ if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
+ rc = -EFAULT;
+ break;
+ }
/* Seperate R/W functions bracket legality here
*/
@@ -4035,7 +4067,8 @@
if(comp->len > sizeof(iobuf))
return -EINVAL;
- copy_from_user(iobuf,comp->data,comp->len);
+ if (copy_from_user(iobuf,comp->data,comp->len))
+ return -EFAULT;
if((*writer)((struct airo_info *)dev->priv, ridcode, iobuf,comp->len))
return -EIO;
return 0;
@@ -4056,9 +4089,8 @@
int setflashmode(struct airo_info *);
int flashgchar(struct airo_info *,int,int);
int flashpchar(struct airo_info *,int,int);
- int flashputbuf(struct airo_info *, unsigned short *);
+ int flashputbuf(struct airo_info *);
int flashrestart(struct airo_info *,struct net_device *);
- unsigned short * flashbuffer;
/* Only super-user can modify flash */
if (!capable(CAP_NET_ADMIN))
@@ -4070,32 +4102,34 @@
return cmdreset((struct airo_info *)dev->priv);
case AIROFLSHSTFL:
+ if (!((struct airo_info *)dev->priv)->flash &&
+ (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
return setflashmode((struct airo_info *)dev->priv);
case AIROFLSHGCHR: /* Get char from aux */
if(comp->len != sizeof(int))
return -EINVAL;
- copy_from_user(&z,comp->data,comp->len);
+ if (copy_from_user(&z,comp->data,comp->len))
+ return -EFAULT;
return flashgchar((struct airo_info *)dev->priv,z,8000);
case AIROFLSHPCHR: /* Send char to card. */
if(comp->len != sizeof(int))
return -EINVAL;
- copy_from_user(&z,comp->data,comp->len);
+ if (copy_from_user(&z,comp->data,comp->len))
+ return -EFAULT;
return flashpchar((struct airo_info *)dev->priv,z,8000);
case AIROFLPUTBUF: /* Send 32k to card */
- if(comp->len > FLASHSIZE)
- return -EINVAL;
- if ((flashbuffer = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+ if (!((struct airo_info *)dev->priv)->flash)
return -ENOMEM;
- if(copy_from_user(flashbuffer,comp->data,comp->len)) {
- kfree (flashbuffer);
+ if(comp->len > FLASHSIZE)
return -EINVAL;
- }
+ if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+ return -EFAULT;
- flashputbuf((struct airo_info *)dev->priv,flashbuffer);
- kfree (flashbuffer);
+ flashputbuf((struct airo_info *)dev->priv);
return 0;
case AIRORESTART:
@@ -4115,11 +4149,8 @@
*/
int cmdreset(struct airo_info *ai) {
- int flags;
-
disable_MAC(ai);
- spin_lock_irqsave(&ai->cmd_lock, flags);
if(!waitbusy (ai)){
printk(KERN_INFO "Waitbusy hang before RESET\n");
return -EBUSY;
@@ -4134,7 +4165,6 @@
printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
return -EBUSY;
}
- spin_unlock_irqrestore(&ai->cmd_lock, flags);
return 0;
}
@@ -4144,16 +4174,12 @@
*/
int setflashmode (struct airo_info *ai) {
- int flags;
-
- spin_lock_irqsave(&ai->cmd_lock, flags);
OUT4500(ai, SWS0, FLASH_COMMAND);
OUT4500(ai, SWS1, FLASH_COMMAND);
OUT4500(ai, SWS0, FLASH_COMMAND);
OUT4500(ai, COMMAND,0x10);
set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (HZ/2); /* 500ms delay */
- spin_unlock_irqrestore(&ai->cmd_lock, flags);
if(!waitbusy(ai)) {
printk(KERN_INFO "Waitbusy hang after setflash mode\n");
@@ -4237,7 +4263,7 @@
* send to the card
*/
-int flashputbuf(struct airo_info *ai, unsigned short *bufp){
+int flashputbuf(struct airo_info *ai){
int nwords;
/* Write stuff */
@@ -4245,7 +4271,7 @@
OUT4500(ai,AUXOFF,0);
for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
- OUT4500(ai,AUXDATA,bufp[nwords] & 0xffff);
+ OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
}
OUT4500(ai,SWS0,0x8000);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)