Commit cde49b05 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'upstream-fixes' of...

Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream-fixes
parents cfadbd29 41072a1b
...@@ -2897,6 +2897,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ...@@ -2897,6 +2897,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
goto err_out_map; goto err_out_map;
} }
ai->wifidev = init_wifidev(ai, dev); ai->wifidev = init_wifidev(ai, dev);
if (!ai->wifidev)
goto err_out_reg;
set_bit(FLAG_REGISTERED,&ai->flags); set_bit(FLAG_REGISTERED,&ai->flags);
airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
...@@ -2908,11 +2910,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ...@@ -2908,11 +2910,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
for( i = 0; i < MAX_FIDS; i++ ) for( i = 0; i < MAX_FIDS; i++ )
ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ if (setup_proc_entry(dev, dev->priv) < 0)
goto err_out_wifi;
netif_start_queue(dev); netif_start_queue(dev);
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
return dev; return dev;
err_out_wifi:
unregister_netdev(ai->wifidev);
free_netdev(ai->wifidev);
err_out_reg:
unregister_netdev(dev);
err_out_map: err_out_map:
if (test_bit(FLAG_MPI,&ai->flags) && pci) { if (test_bit(FLAG_MPI,&ai->flags) && pci) {
pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma); pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
...@@ -3089,7 +3098,8 @@ static int airo_thread(void *data) { ...@@ -3089,7 +3098,8 @@ static int airo_thread(void *data) {
set_bit(JOB_AUTOWEP, &ai->jobs); set_bit(JOB_AUTOWEP, &ai->jobs);
break; break;
} }
if (!kthread_should_stop()) { if (!kthread_should_stop() &&
!freezing(current)) {
unsigned long wake_at; unsigned long wake_at;
if (!ai->expires || !ai->scan_timeout) { if (!ai->expires || !ai->scan_timeout) {
wake_at = max(ai->expires, wake_at = max(ai->expires,
...@@ -3101,7 +3111,8 @@ static int airo_thread(void *data) { ...@@ -3101,7 +3111,8 @@ static int airo_thread(void *data) {
schedule_timeout(wake_at - jiffies); schedule_timeout(wake_at - jiffies);
continue; continue;
} }
} else if (!kthread_should_stop()) { } else if (!kthread_should_stop() &&
!freezing(current)) {
schedule(); schedule();
continue; continue;
} }
...@@ -4495,6 +4506,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4495,6 +4506,8 @@ static int setup_proc_entry( struct net_device *dev,
apriv->proc_entry = create_proc_entry(apriv->proc_name, apriv->proc_entry = create_proc_entry(apriv->proc_name,
S_IFDIR|airo_perm, S_IFDIR|airo_perm,
airo_entry); airo_entry);
if (!apriv->proc_entry)
goto fail;
apriv->proc_entry->uid = proc_uid; apriv->proc_entry->uid = proc_uid;
apriv->proc_entry->gid = proc_gid; apriv->proc_entry->gid = proc_gid;
apriv->proc_entry->owner = THIS_MODULE; apriv->proc_entry->owner = THIS_MODULE;
...@@ -4503,6 +4516,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4503,6 +4516,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("StatsDelta", entry = create_proc_entry("StatsDelta",
S_IFREG | (S_IRUGO&proc_perm), S_IFREG | (S_IRUGO&proc_perm),
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_stats_delta;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4513,6 +4528,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4513,6 +4528,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("Stats", entry = create_proc_entry("Stats",
S_IFREG | (S_IRUGO&proc_perm), S_IFREG | (S_IRUGO&proc_perm),
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_stats;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4523,6 +4540,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4523,6 +4540,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("Status", entry = create_proc_entry("Status",
S_IFREG | (S_IRUGO&proc_perm), S_IFREG | (S_IRUGO&proc_perm),
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_status;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4533,6 +4552,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4533,6 +4552,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("Config", entry = create_proc_entry("Config",
S_IFREG | proc_perm, S_IFREG | proc_perm,
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_config;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4543,6 +4564,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4543,6 +4564,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("SSID", entry = create_proc_entry("SSID",
S_IFREG | proc_perm, S_IFREG | proc_perm,
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_ssid;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4553,6 +4576,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4553,6 +4576,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("APList", entry = create_proc_entry("APList",
S_IFREG | proc_perm, S_IFREG | proc_perm,
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_aplist;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4563,6 +4588,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4563,6 +4588,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("BSSList", entry = create_proc_entry("BSSList",
S_IFREG | proc_perm, S_IFREG | proc_perm,
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_bsslist;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4573,6 +4600,8 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4573,6 +4600,8 @@ static int setup_proc_entry( struct net_device *dev,
entry = create_proc_entry("WepKey", entry = create_proc_entry("WepKey",
S_IFREG | proc_perm, S_IFREG | proc_perm,
apriv->proc_entry); apriv->proc_entry);
if (!entry)
goto fail_wepkey;
entry->uid = proc_uid; entry->uid = proc_uid;
entry->gid = proc_gid; entry->gid = proc_gid;
entry->data = dev; entry->data = dev;
...@@ -4580,6 +4609,25 @@ static int setup_proc_entry( struct net_device *dev, ...@@ -4580,6 +4609,25 @@ static int setup_proc_entry( struct net_device *dev,
SETPROC_OPS(entry, proc_wepkey_ops); SETPROC_OPS(entry, proc_wepkey_ops);
return 0; return 0;
fail_wepkey:
remove_proc_entry("BSSList", apriv->proc_entry);
fail_bsslist:
remove_proc_entry("APList", apriv->proc_entry);
fail_aplist:
remove_proc_entry("SSID", apriv->proc_entry);
fail_ssid:
remove_proc_entry("Config", apriv->proc_entry);
fail_config:
remove_proc_entry("Status", apriv->proc_entry);
fail_status:
remove_proc_entry("Stats", apriv->proc_entry);
fail_stats:
remove_proc_entry("StatsDelta", apriv->proc_entry);
fail_stats_delta:
remove_proc_entry(apriv->proc_name, airo_entry);
fail:
return -ENOMEM;
} }
static int takedown_proc_entry( struct net_device *dev, static int takedown_proc_entry( struct net_device *dev,
...@@ -5924,7 +5972,6 @@ static int airo_get_essid(struct net_device *dev, ...@@ -5924,7 +5972,6 @@ static int airo_get_essid(struct net_device *dev,
/* Get the current SSID */ /* Get the current SSID */
memcpy(extra, status_rid.SSID, status_rid.SSIDlen); memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
extra[status_rid.SSIDlen] = '\0';
/* If none, we may want to get the one that was set */ /* If none, we may want to get the one that was set */
/* Push it out ! */ /* Push it out ! */
......
...@@ -1678,11 +1678,9 @@ static int atmel_get_essid(struct net_device *dev, ...@@ -1678,11 +1678,9 @@ static int atmel_get_essid(struct net_device *dev,
/* Get the current SSID */ /* Get the current SSID */
if (priv->new_SSID_size != 0) { if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size); memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0';
dwrq->length = priv->new_SSID_size; dwrq->length = priv->new_SSID_size;
} else { } else {
memcpy(extra, priv->SSID, priv->SSID_size); memcpy(extra, priv->SSID, priv->SSID_size);
extra[priv->SSID_size] = '\0';
dwrq->length = priv->SSID_size; dwrq->length = priv->SSID_size;
} }
......
...@@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) ...@@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
struct bcm43xx_dmaring *ring; struct bcm43xx_dmaring *ring;
int err = -ENOMEM; int err = -ENOMEM;
int dma64 = 0; int dma64 = 0;
u32 sbtmstatehi; u64 mask = bcm43xx_get_supported_dma_mask(bcm);
int nobits;
sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); if (mask == DMA_64BIT_MASK) {
if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
dma64 = 1; dma64 = 1;
nobits = 64;
} else if (mask == DMA_32BIT_MASK)
nobits = 32;
else
nobits = 30;
err = pci_set_dma_mask(bcm->pci_dev, mask);
err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
if (err) {
#ifdef CONFIG_BCM43XX_PIO
printk(KERN_WARNING PFX "DMA not supported on this device."
" Falling back to PIO.\n");
bcm->__using_pio = 1;
return -ENOSYS;
#else
printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
"Please recompile the driver with PIO support.\n");
return -ENODEV;
#endif /* CONFIG_BCM43XX_PIO */
}
/* setup TX DMA channels. */ /* setup TX DMA channels. */
ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
...@@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) ...@@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
dma->rx_ring3 = ring; dma->rx_ring3 = ring;
} }
dprintk(KERN_INFO PFX "%s DMA initialized\n", dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
dma64 ? "64-bit" : "32-bit");
err = 0; err = 0;
out: out:
return err; return err;
......
...@@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, ...@@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
struct ieee80211_txb *txb); struct ieee80211_txb *txb);
void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
/* Helper function that returns the dma mask for this device. */
static inline
u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
{
int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
BCM43xx_SBTMSTATEHIGH_DMA64BIT;
u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
if (dma64)
return DMA_64BIT_MASK;
bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
return DMA_32BIT_MASK;
return DMA_30BIT_MASK;
}
#else /* CONFIG_BCM43XX_DMA */ #else /* CONFIG_BCM43XX_DMA */
......
...@@ -242,7 +242,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ...@@ -242,7 +242,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
//TODO //TODO
break; break;
case BCM43xx_LED_ASSOC: case BCM43xx_LED_ASSOC:
if (bcm->softmac->associated) if (bcm->softmac->associnfo.associated)
turn_on = 1; turn_on = 1;
break; break;
#ifdef CONFIG_BCM43XX_DEBUG #ifdef CONFIG_BCM43XX_DEBUG
......
...@@ -2925,10 +2925,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, ...@@ -2925,10 +2925,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
bcm43xx_write16(bcm, 0x043C, 0x000C); bcm43xx_write16(bcm, 0x043C, 0x000C);
if (active_wlcore) { if (active_wlcore) {
if (bcm43xx_using_pio(bcm)) if (bcm43xx_using_pio(bcm)) {
err = bcm43xx_pio_init(bcm); err = bcm43xx_pio_init(bcm);
else } else {
err = bcm43xx_dma_init(bcm); err = bcm43xx_dma_init(bcm);
if (err == -ENOSYS)
err = bcm43xx_pio_init(bcm);
}
if (err) if (err)
goto err_chip_cleanup; goto err_chip_cleanup;
} }
...@@ -3164,12 +3167,12 @@ static void bcm43xx_periodic_work_handler(void *d) ...@@ -3164,12 +3167,12 @@ static void bcm43xx_periodic_work_handler(void *d)
u32 savedirqs = 0; u32 savedirqs = 0;
int badness; int badness;
mutex_lock(&bcm->mutex);
badness = estimate_periodic_work_badness(bcm->periodic_state); badness = estimate_periodic_work_badness(bcm->periodic_state);
if (badness > BADNESS_LIMIT) { if (badness > BADNESS_LIMIT) {
/* Periodic work will take a long time, so we want it to /* Periodic work will take a long time, so we want it to
* be preemtible. * be preemtible.
*/ */
mutex_lock(&bcm->mutex);
netif_tx_disable(bcm->net_dev); netif_tx_disable(bcm->net_dev);
spin_lock_irqsave(&bcm->irq_lock, flags); spin_lock_irqsave(&bcm->irq_lock, flags);
bcm43xx_mac_suspend(bcm); bcm43xx_mac_suspend(bcm);
...@@ -3182,7 +3185,6 @@ static void bcm43xx_periodic_work_handler(void *d) ...@@ -3182,7 +3185,6 @@ static void bcm43xx_periodic_work_handler(void *d)
/* Periodic work should take short time, so we want low /* Periodic work should take short time, so we want low
* locking overhead. * locking overhead.
*/ */
mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags); spin_lock_irqsave(&bcm->irq_lock, flags);
} }
...@@ -3993,8 +3995,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, ...@@ -3993,8 +3995,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
struct net_device *net_dev, struct net_device *net_dev,
struct pci_dev *pci_dev) struct pci_dev *pci_dev)
{ {
int err;
bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
bcm->ieee = netdev_priv(net_dev); bcm->ieee = netdev_priv(net_dev);
bcm->softmac = ieee80211_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev);
...@@ -4012,22 +4012,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, ...@@ -4012,22 +4012,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
(void (*)(unsigned long))bcm43xx_interrupt_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
(unsigned long)bcm); (unsigned long)bcm);
tasklet_disable_nosync(&bcm->isr_tasklet); tasklet_disable_nosync(&bcm->isr_tasklet);
if (modparam_pio) { if (modparam_pio)
bcm->__using_pio = 1; bcm->__using_pio = 1;
} else {
err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
if (err) {
#ifdef CONFIG_BCM43XX_PIO
printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
bcm->__using_pio = 1;
#else
printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
"Recompile the driver with PIO support, please.\n");
return -ENODEV;
#endif /* CONFIG_BCM43XX_PIO */
}
}
bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
/* default to sw encryption for now */ /* default to sw encryption for now */
...@@ -4208,7 +4194,11 @@ static int bcm43xx_resume(struct pci_dev *pdev) ...@@ -4208,7 +4194,11 @@ static int bcm43xx_resume(struct pci_dev *pdev)
dprintk(KERN_INFO PFX "Resuming...\n"); dprintk(KERN_INFO PFX "Resuming...\n");
pci_set_power_state(pdev, 0); pci_set_power_state(pdev, 0);
pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) {
printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
return err;
}
pci_restore_state(pdev); pci_restore_state(pdev);
bcm43xx_chipset_attach(bcm); bcm43xx_chipset_attach(bcm);
......
...@@ -847,7 +847,7 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d ...@@ -847,7 +847,7 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
unsigned long flags; unsigned long flags;
wstats = &bcm->stats.wstats; wstats = &bcm->stats.wstats;
if (!mac->associated) { if (!mac->associnfo.associated) {
wstats->miss.beacon = 0; wstats->miss.beacon = 0;
// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
wstats->discard.retries = 0; wstats->discard.retries = 0;
......
...@@ -2457,6 +2457,7 @@ void free_orinocodev(struct net_device *dev) ...@@ -2457,6 +2457,7 @@ void free_orinocodev(struct net_device *dev)
/* Wireless extensions */ /* Wireless extensions */
/********************************************************************/ /********************************************************************/
/* Return : < 0 -> error code ; >= 0 -> length */
static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
char buf[IW_ESSID_MAX_SIZE+1]) char buf[IW_ESSID_MAX_SIZE+1])
{ {
...@@ -2501,9 +2502,9 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, ...@@ -2501,9 +2502,9 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
len = le16_to_cpu(essidbuf.len); len = le16_to_cpu(essidbuf.len);
BUG_ON(len > IW_ESSID_MAX_SIZE); BUG_ON(len > IW_ESSID_MAX_SIZE);
memset(buf, 0, IW_ESSID_MAX_SIZE+1); memset(buf, 0, IW_ESSID_MAX_SIZE);
memcpy(buf, p, len); memcpy(buf, p, len);
buf[len] = '\0'; err = len;
fail_unlock: fail_unlock:
orinoco_unlock(priv, &flags); orinoco_unlock(priv, &flags);
...@@ -3027,17 +3028,18 @@ static int orinoco_ioctl_getessid(struct net_device *dev, ...@@ -3027,17 +3028,18 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
if (netif_running(dev)) { if (netif_running(dev)) {
err = orinoco_hw_get_essid(priv, &active, essidbuf); err = orinoco_hw_get_essid(priv, &active, essidbuf);
if (err) if (err < 0)
return err; return err;
erq->length = err;
} else { } else {
if (orinoco_lock(priv, &flags) != 0) if (orinoco_lock(priv, &flags) != 0)
return -EBUSY; return -EBUSY;
memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
erq->length = strlen(priv->desired_essid);
orinoco_unlock(priv, &flags); orinoco_unlock(priv, &flags);
} }
erq->flags = 1; erq->flags = 1;
erq->length = strlen(essidbuf);
return 0; return 0;
} }
...@@ -3075,10 +3077,10 @@ static int orinoco_ioctl_getnick(struct net_device *dev, ...@@ -3075,10 +3077,10 @@ static int orinoco_ioctl_getnick(struct net_device *dev,
if (orinoco_lock(priv, &flags) != 0) if (orinoco_lock(priv, &flags) != 0)
return -EBUSY; return -EBUSY;
memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1); memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
orinoco_unlock(priv, &flags); orinoco_unlock(priv, &flags);
nrq->length = strlen(nickbuf); nrq->length = strlen(priv->nick);
return 0; return 0;
} }
......
...@@ -1198,7 +1198,6 @@ static int ray_get_essid(struct net_device *dev, ...@@ -1198,7 +1198,6 @@ static int ray_get_essid(struct net_device *dev,
/* Get the essid that was set */ /* Get the essid that was set */
memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Push it out ! */ /* Push it out ! */
dwrq->length = strlen(extra); dwrq->length = strlen(extra);
......
...@@ -193,10 +193,8 @@ static void zd1201_usbrx(struct urb *urb) ...@@ -193,10 +193,8 @@ static void zd1201_usbrx(struct urb *urb)
struct sk_buff *skb; struct sk_buff *skb;
unsigned char type; unsigned char type;
if (!zd) { if (!zd)
free = 1; return;
goto exit;
}
switch(urb->status) { switch(urb->status) {
case -EILSEQ: case -EILSEQ:
......
...@@ -1099,7 +1099,7 @@ static void link_led_handler(void *p) ...@@ -1099,7 +1099,7 @@ static void link_led_handler(void *p)
int r; int r;
spin_lock_irq(&mac->lock); spin_lock_irq(&mac->lock);
is_associated = sm->associated != 0; is_associated = sm->associnfo.associated != 0;
spin_unlock_irq(&mac->lock); spin_unlock_irq(&mac->lock);
r = zd_chip_control_leds(chip, r = zd_chip_control_leds(chip,
......
...@@ -63,13 +63,11 @@ struct ieee80211softmac_wpa { ...@@ -63,13 +63,11 @@ struct ieee80211softmac_wpa {
/* /*
* Information about association * Information about association
*
* Do we need a lock for this?
* We only ever use this structure inlined
* into our global struct. I've used its lock,
* but maybe we need a local one here?
*/ */
struct ieee80211softmac_assoc_info { struct ieee80211softmac_assoc_info {
struct mutex mutex;
/* /*
* This is the requested ESSID. It is written * This is the requested ESSID. It is written
* only by the WX handlers. * only by the WX handlers.
...@@ -99,12 +97,13 @@ struct ieee80211softmac_assoc_info { ...@@ -99,12 +97,13 @@ struct ieee80211softmac_assoc_info {
* *
* bssfixed is used for SIOCSIWAP. * bssfixed is used for SIOCSIWAP.
*/ */
u8 static_essid:1, u8 static_essid;
short_preamble_available:1, u8 short_preamble_available;
associating:1, u8 associating;
assoc_wait:1, u8 associated;
bssvalid:1, u8 assoc_wait;
bssfixed:1; u8 bssvalid;
u8 bssfixed;
/* Scan retries remaining */ /* Scan retries remaining */
int scan_retry; int scan_retry;
...@@ -230,10 +229,8 @@ struct ieee80211softmac_device { ...@@ -230,10 +229,8 @@ struct ieee80211softmac_device {
/* this lock protects this structure */ /* this lock protects this structure */
spinlock_t lock; spinlock_t lock;
/* couple of flags */ u8 running; /* SoftMAC started? */
u8 scanning:1, /* protects scanning from being done multiple times at once */ u8 scanning;
associated:1,
running:1;
struct ieee80211softmac_scaninfo *scaninfo; struct ieee80211softmac_scaninfo *scaninfo;
struct ieee80211softmac_assoc_info associnfo; struct ieee80211softmac_assoc_info associnfo;
...@@ -295,7 +292,7 @@ static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device ...@@ -295,7 +292,7 @@ static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device
{ {
struct ieee80211softmac_txrates *txrates = &mac->txrates; struct ieee80211softmac_txrates *txrates = &mac->txrates;
if (!mac->associated) if (!mac->associnfo.associated)
return txrates->mgt_mcast_rate; return txrates->mgt_mcast_rate;
/* We are associated, sending unicast frame */ /* We are associated, sending unicast frame */
......
...@@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft ...@@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
dprintk(KERN_INFO PFX "sent association request!\n"); dprintk(KERN_INFO PFX "sent association request!\n");
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
mac->associated = 0; /* just to make sure */ mac->associnfo.associated = 0; /* just to make sure */
/* Set a timer for timeout */ /* Set a timer for timeout */
/* FIXME: make timeout configurable */ /* FIXME: make timeout configurable */
...@@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d) ...@@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d)
{ {
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
struct ieee80211softmac_network *n; struct ieee80211softmac_network *n;
unsigned long flags;
spin_lock_irqsave(&mac->lock, flags); mutex_lock(&mac->associnfo.mutex);
/* we might race against ieee80211softmac_handle_assoc_response, /* we might race against ieee80211softmac_handle_assoc_response,
* so make sure only one of us does something */ * so make sure only one of us does something */
if (!mac->associnfo.associating) { if (!mac->associnfo.associating)
spin_unlock_irqrestore(&mac->lock, flags); goto out;
return;
}
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0; mac->associnfo.bssvalid = 0;
mac->associated = 0; mac->associnfo.associated = 0;
n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "assoc request timed out!\n"); dprintk(KERN_INFO PFX "assoc request timed out!\n");
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
out:
mutex_unlock(&mac->associnfo.mutex);
} }
void void
...@@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) ...@@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
netif_carrier_off(mac->dev); netif_carrier_off(mac->dev);
mac->associated = 0; mac->associnfo.associated = 0;
mac->associnfo.bssvalid = 0; mac->associnfo.bssvalid = 0;
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
ieee80211softmac_init_bss(mac); ieee80211softmac_init_bss(mac);
...@@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas ...@@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas
{ {
struct ieee80211softmac_network *found; struct ieee80211softmac_network *found;
if (mac->associnfo.bssvalid && mac->associated) { if (mac->associnfo.bssvalid && mac->associnfo.associated) {
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
if (found) if (found)
ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
...@@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d) ...@@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d)
int bssvalid; int bssvalid;
unsigned long flags; unsigned long flags;
mutex_lock(&mac->associnfo.mutex);
if (!mac->associnfo.associating)
goto out;
/* ieee80211_disassoc might clear this */ /* ieee80211_disassoc might clear this */
bssvalid = mac->associnfo.bssvalid; bssvalid = mac->associnfo.bssvalid;
/* meh */ /* meh */
if (mac->associated) if (mac->associnfo.associated)
ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
spin_unlock_irqrestore(&mac->lock, flags);
/* try to find the requested network in our list, if we found one already */ /* try to find the requested network in our list, if we found one already */
if (bssvalid || mac->associnfo.bssfixed) if (bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
...@@ -260,9 +259,7 @@ ieee80211softmac_assoc_work(void *d) ...@@ -260,9 +259,7 @@ ieee80211softmac_assoc_work(void *d)
if (!found) { if (!found) {
if (mac->associnfo.scan_retry > 0) { if (mac->associnfo.scan_retry > 0) {
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.scan_retry--; mac->associnfo.scan_retry--;
spin_unlock_irqrestore(&mac->lock, flags);
/* We know of no such network. Let's scan. /* We know of no such network. Let's scan.
* NB: this also happens if we had no memory to copy the network info... * NB: this also happens if we had no memory to copy the network info...
...@@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d) ...@@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d)
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
if (ieee80211softmac_start_scan(mac)) if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return; goto out;
} else { } else {
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
mac->associated = 0; mac->associnfo.associated = 0;
spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
/* reset the retry counter for the next user request since we /* reset the retry counter for the next user request since we
* break out and don't reschedule ourselves after this point. */ * break out and don't reschedule ourselves after this point. */
mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
return; goto out;
} }
} }
...@@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d) ...@@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
mac->associnfo.assoc_wait = 1; mac->associnfo.assoc_wait = 1;
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
} }
return; goto out;
} }
if (!found->authenticated && !found->authenticating) { if (!found->authenticated && !found->authenticating) {
/* This relies on the fact that _auth_req only queues the work, /* This relies on the fact that _auth_req only queues the work,
...@@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d) ...@@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d)
mac->associnfo.assoc_wait = 0; mac->associnfo.assoc_wait = 0;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
} }
return; goto out;
} }
/* finally! now we can start associating */ /* finally! now we can start associating */
mac->associnfo.assoc_wait = 0; mac->associnfo.assoc_wait = 0;
ieee80211softmac_assoc(mac, found); ieee80211softmac_assoc(mac, found);
out:
mutex_unlock(&mac->associnfo.mutex);
} }
/* call this to do whatever is necessary when we're associated */ /* call this to do whatever is necessary when we're associated */
...@@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac, ...@@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
mac->bssinfo.supported_rates = net->supported_rates; mac->bssinfo.supported_rates = net->supported_rates;
ieee80211softmac_recalc_txrates(mac); ieee80211softmac_recalc_txrates(mac);
mac->associated = 1; mac->associnfo.associated = 1;
mac->associnfo.short_preamble_available = mac->associnfo.short_preamble_available =
(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
...@@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, ...@@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0; mac->associnfo.bssvalid = 0;
mac->associated = 0; mac->associnfo.associated = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
} }
......
...@@ -304,7 +304,7 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, ...@@ -304,7 +304,7 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
2 + /* Auth Transaction Seq */ 2 + /* Auth Transaction Seq */
2 + /* Status Code */ 2 + /* Status Code */
/* Challenge Text IE */ /* Challenge Text IE */
is_shared_response ? 0 : 1 + 1 + net->challenge_len (is_shared_response ? 1 + 1 + net->challenge_len : 0)
); );
if (unlikely((*pkt) == NULL)) if (unlikely((*pkt) == NULL))
return 0; return 0;
...@@ -475,8 +475,13 @@ int ieee80211softmac_handle_beacon(struct net_device *dev, ...@@ -475,8 +475,13 @@ int ieee80211softmac_handle_beacon(struct net_device *dev,
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) /* This might race, but we don't really care and it's not worth
* adding heavyweight locking in this fastpath.
*/
if (mac->associnfo.associated) {
if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
ieee80211softmac_process_erp(mac, network->erp_value); ieee80211softmac_process_erp(mac, network->erp_value);
}
return 0; return 0;
} }
......
...@@ -57,6 +57,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) ...@@ -57,6 +57,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
INIT_LIST_HEAD(&softmac->network_list); INIT_LIST_HEAD(&softmac->network_list);
INIT_LIST_HEAD(&softmac->events); INIT_LIST_HEAD(&softmac->events);
mutex_init(&softmac->associnfo.mutex);
INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
softmac->start_scan = ieee80211softmac_start_scan_implementation; softmac->start_scan = ieee80211softmac_start_scan_implementation;
......
...@@ -73,13 +73,14 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, ...@@ -73,13 +73,14 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
struct ieee80211softmac_network *n; struct ieee80211softmac_network *n;
struct ieee80211softmac_auth_queue_item *authptr; struct ieee80211softmac_auth_queue_item *authptr;
int length = 0; int length = 0;
unsigned long flags;
mutex_lock(&sm->associnfo.mutex);
/* Check if we're already associating to this or another network /* Check if we're already associating to this or another network
* If it's another network, cancel and start over with our new network * If it's another network, cancel and start over with our new network
* If it's our network, ignore the change, we're already doing it! * If it's our network, ignore the change, we're already doing it!
*/ */
if((sm->associnfo.associating || sm->associated) && if((sm->associnfo.associating || sm->associnfo.associated) &&
(data->essid.flags && data->essid.length)) { (data->essid.flags && data->essid.length)) {
/* Get the associating network */ /* Get the associating network */
n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
...@@ -87,10 +88,9 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, ...@@ -87,10 +88,9 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
!memcmp(n->essid.data, extra, n->essid.len)) { !memcmp(n->essid.data, extra, n->essid.len)) {
dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n", dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
MAC_ARG(sm->associnfo.bssid)); MAC_ARG(sm->associnfo.bssid));
return 0; goto out;
} else { } else {
dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
spin_lock_irqsave(&sm->lock,flags);
/* Cancel assoc work */ /* Cancel assoc work */
cancel_delayed_work(&sm->associnfo.work); cancel_delayed_work(&sm->associnfo.work);
/* We don't have to do this, but it's a little cleaner */ /* We don't have to do this, but it's a little cleaner */
...@@ -98,14 +98,13 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, ...@@ -98,14 +98,13 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
cancel_delayed_work(&authptr->work); cancel_delayed_work(&authptr->work);
sm->associnfo.bssvalid = 0; sm->associnfo.bssvalid = 0;
sm->associnfo.bssfixed = 0; sm->associnfo.bssfixed = 0;
spin_unlock_irqrestore(&sm->lock,flags);
flush_scheduled_work(); flush_scheduled_work();
sm->associnfo.associating = 0;
sm->associnfo.associated = 0;
} }
} }
spin_lock_irqsave(&sm->lock, flags);
sm->associnfo.static_essid = 0; sm->associnfo.static_essid = 0;
sm->associnfo.assoc_wait = 0; sm->associnfo.assoc_wait = 0;
...@@ -121,10 +120,12 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, ...@@ -121,10 +120,12 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
* If applicable, we have already copied the data in */ * If applicable, we have already copied the data in */
sm->associnfo.req_essid.len = length; sm->associnfo.req_essid.len = length;
sm->associnfo.associating = 1;
/* queue lower level code to do work (if necessary) */ /* queue lower level code to do work (if necessary) */
schedule_work(&sm->associnfo.work); schedule_work(&sm->associnfo.work);
out:
mutex_unlock(&sm->associnfo.mutex);
spin_unlock_irqrestore(&sm->lock, flags);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
...@@ -136,10 +137,8 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, ...@@ -136,10 +137,8 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev,
char *extra) char *extra)
{ {
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
unsigned long flags;
/* avoid getting inconsistent information */ mutex_lock(&sm->associnfo.mutex);
spin_lock_irqsave(&sm->lock, flags);
/* If all fails, return ANY (empty) */ /* If all fails, return ANY (empty) */
data->essid.length = 0; data->essid.length = 0;
data->essid.flags = 0; /* active */ data->essid.flags = 0; /* active */
...@@ -152,12 +151,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, ...@@ -152,12 +151,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev,
} }
/* If we're associating/associated, return that */ /* If we're associating/associated, return that */
if (sm->associated || sm->associnfo.associating) { if (sm->associnfo.associated || sm->associnfo.associating) {
data->essid.length = sm->associnfo.associate_essid.len; data->essid.length = sm->associnfo.associate_essid.len;
data->essid.flags = 1; /* active */ data->essid.flags = 1; /* active */
memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
} }
spin_unlock_irqrestore(&sm->lock, flags); mutex_unlock(&sm->associnfo.mutex);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
...@@ -322,15 +322,15 @@ ieee80211softmac_wx_get_wap(struct net_device *net_dev, ...@@ -322,15 +322,15 @@ ieee80211softmac_wx_get_wap(struct net_device *net_dev,
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
int err = 0; int err = 0;
unsigned long flags;
spin_lock_irqsave(&mac->lock, flags); mutex_lock(&mac->associnfo.mutex);
if (mac->associnfo.bssvalid) if (mac->associnfo.bssvalid)
memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
else else
memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
data->ap_addr.sa_family = ARPHRD_ETHER; data->ap_addr.sa_family = ARPHRD_ETHER;
spin_unlock_irqrestore(&mac->lock, flags); mutex_unlock(&mac->associnfo.mutex);
return err; return err;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
...@@ -342,28 +342,27 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, ...@@ -342,28 +342,27 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
char *extra) char *extra)
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
unsigned long flags;
/* sanity check */ /* sanity check */
if (data->ap_addr.sa_family != ARPHRD_ETHER) { if (data->ap_addr.sa_family != ARPHRD_ETHER) {
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&mac->lock, flags); mutex_lock(&mac->associnfo.mutex);
if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
/* the bssid we have is not to be fixed any longer, /* the bssid we have is not to be fixed any longer,
* and we should reassociate to the best AP. */ * and we should reassociate to the best AP. */
mac->associnfo.bssfixed = 0; mac->associnfo.bssfixed = 0;
/* force reassociation */ /* force reassociation */
mac->associnfo.bssvalid = 0; mac->associnfo.bssvalid = 0;
if (mac->associated) if (mac->associnfo.associated)
schedule_work(&mac->associnfo.work); schedule_work(&mac->associnfo.work);
} else if (is_zero_ether_addr(data->ap_addr.sa_data)) { } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
/* the bssid we have is no longer fixed */ /* the bssid we have is no longer fixed */
mac->associnfo.bssfixed = 0; mac->associnfo.bssfixed = 0;
} else { } else {
if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
if (mac->associnfo.associating || mac->associated) { if (mac->associnfo.associating || mac->associnfo.associated) {
/* bssid unchanged and associated or associating - just return */ /* bssid unchanged and associated or associating - just return */
goto out; goto out;
} }
...@@ -378,7 +377,8 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, ...@@ -378,7 +377,8 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
} }
out: out:
spin_unlock_irqrestore(&mac->lock, flags); mutex_unlock(&mac->associnfo.mutex);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
...@@ -395,6 +395,7 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, ...@@ -395,6 +395,7 @@ ieee80211softmac_wx_set_genie(struct net_device *dev,
char *buf; char *buf;
int i; int i;
mutex_lock(&mac->associnfo.mutex);
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
/* bleh. shouldn't be locked for that kmalloc... */ /* bleh. shouldn't be locked for that kmalloc... */
...@@ -432,6 +433,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, ...@@ -432,6 +433,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev,
out: out:
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
mutex_unlock(&mac->associnfo.mutex);
return err; return err;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
...@@ -447,6 +450,7 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, ...@@ -447,6 +450,7 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
int err = 0; int err = 0;
int space = wrqu->data.length; int space = wrqu->data.length;
mutex_lock(&mac->associnfo.mutex);
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
wrqu->data.length = 0; wrqu->data.length = 0;
...@@ -459,6 +463,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, ...@@ -459,6 +463,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
err = -E2BIG; err = -E2BIG;
} }
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
mutex_lock(&mac->associnfo.mutex);
return err; return err;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
...@@ -473,10 +479,13 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, ...@@ -473,10 +479,13 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
struct iw_mlme *mlme = (struct iw_mlme *)extra; struct iw_mlme *mlme = (struct iw_mlme *)extra;
u16 reason = cpu_to_le16(mlme->reason_code); u16 reason = cpu_to_le16(mlme->reason_code);
struct ieee80211softmac_network *net; struct ieee80211softmac_network *net;
int err = -EINVAL;
mutex_lock(&mac->associnfo.mutex);
if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) { if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n"); printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
return -EINVAL; goto out;
} }
switch (mlme->cmd) { switch (mlme->cmd) {
...@@ -484,14 +493,22 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, ...@@ -484,14 +493,22 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data); net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
if (!net) { if (!net) {
printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n"); printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
return -EINVAL; goto out;
} }
return ieee80211softmac_deauth_req(mac, net, reason); return ieee80211softmac_deauth_req(mac, net, reason);
case IW_MLME_DISASSOC: case IW_MLME_DISASSOC:
ieee80211softmac_send_disassoc_req(mac, reason); ieee80211softmac_send_disassoc_req(mac, reason);
return 0; mac->associnfo.associated = 0;
mac->associnfo.associating = 0;
err = 0;
goto out;
default: default:
return -EOPNOTSUPP; err = -EOPNOTSUPP;
} }
out:
mutex_unlock(&mac->associnfo.mutex);
return err;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
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