Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[pandora-kernel.git] / drivers / net / wireless / bcm43xx / bcm43xx_main.c
index bad3452..a1b7838 100644 (file)
@@ -746,7 +746,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
        if (err)
                goto err_ctlreg;
        spromctl |= 0x10; /* SPROM WRITE enable. */
-       bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+       err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
        if (err)
                goto err_ctlreg;
        /* We must burn lots of CPU cycles here, but that does not
@@ -768,7 +768,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
                mdelay(20);
        }
        spromctl &= ~0x10; /* SPROM WRITE enable. */
-       bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+       err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
        if (err)
                goto err_ctlreg;
        mdelay(500);
@@ -1463,6 +1463,23 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
        }
 }
 
+static void drain_txstatus_queue(struct bcm43xx_private *bcm)
+{
+       u32 dummy;
+
+       if (bcm->current_core->rev < 5)
+               return;
+       /* Read all entries from the microcode TXstatus FIFO
+        * and throw them away.
+        */
+       while (1) {
+               dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+               if (!dummy)
+                       break;
+               dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+       }
+}
+
 static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
 {
        bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
@@ -2925,10 +2942,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
                bcm43xx_write16(bcm, 0x043C, 0x000C);
 
        if (active_wlcore) {
-               if (bcm43xx_using_pio(bcm))
+               if (bcm43xx_using_pio(bcm)) {
                        err = bcm43xx_pio_init(bcm);
-               else
+               } else {
                        err = bcm43xx_dma_init(bcm);
+                       if (err == -ENOSYS)
+                               err = bcm43xx_pio_init(bcm);
+               }
                if (err)
                        goto err_chip_cleanup;
        }
@@ -3160,17 +3180,30 @@ static int estimate_periodic_work_badness(unsigned int state)
 static void bcm43xx_periodic_work_handler(void *d)
 {
        struct bcm43xx_private *bcm = d;
+       struct net_device *net_dev = bcm->net_dev;
        unsigned long flags;
        u32 savedirqs = 0;
        int badness;
+       unsigned long orig_trans_start = 0;
 
+       mutex_lock(&bcm->mutex);
        badness = estimate_periodic_work_badness(bcm->periodic_state);
        if (badness > BADNESS_LIMIT) {
                /* Periodic work will take a long time, so we want it to
                 * be preemtible.
                 */
-               mutex_lock(&bcm->mutex);
-               netif_tx_disable(bcm->net_dev);
+
+               netif_tx_lock_bh(net_dev);
+               /* We must fake a started transmission here, as we are going to
+                * disable TX. If we wouldn't fake a TX, it would be possible to
+                * trigger the netdev watchdog, if the last real TX is already
+                * some time on the past (slightly less than 5secs)
+                */
+               orig_trans_start = net_dev->trans_start;
+               net_dev->trans_start = jiffies;
+               netif_stop_queue(net_dev);
+               netif_tx_unlock_bh(net_dev);
+
                spin_lock_irqsave(&bcm->irq_lock, flags);
                bcm43xx_mac_suspend(bcm);
                if (bcm43xx_using_pio(bcm))
@@ -3182,7 +3215,6 @@ static void bcm43xx_periodic_work_handler(void *d)
                /* Periodic work should take short time, so we want low
                 * locking overhead.
                 */
-               mutex_lock(&bcm->mutex);
                spin_lock_irqsave(&bcm->irq_lock, flags);
        }
 
@@ -3196,6 +3228,7 @@ static void bcm43xx_periodic_work_handler(void *d)
                        bcm43xx_pio_thaw_txqueues(bcm);
                bcm43xx_mac_enable(bcm);
                netif_wake_queue(bcm->net_dev);
+               net_dev->trans_start = orig_trans_start;
        }
        mmiowb();
        spin_unlock_irqrestore(&bcm->irq_lock, flags);
@@ -3516,6 +3549,7 @@ int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
        bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
        bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
        bcm43xx_security_init(bcm);
+       drain_txstatus_queue(bcm);
        ieee80211softmac_start(bcm->net_dev);
 
        /* Let's go! Be careful after enabling the IRQs.
@@ -3993,8 +4027,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
                                struct net_device *net_dev,
                                struct pci_dev *pci_dev)
 {
-       int err;
-
        bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
        bcm->ieee = netdev_priv(net_dev);
        bcm->softmac = ieee80211_priv(net_dev);
@@ -4012,22 +4044,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
                     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
                     (unsigned long)bcm);
        tasklet_disable_nosync(&bcm->isr_tasklet);
-       if (modparam_pio) {
+       if (modparam_pio)
                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;
 
        /* default to sw encryption for now */
@@ -4208,7 +4226,11 @@ static int bcm43xx_resume(struct pci_dev *pdev)
        dprintk(KERN_INFO PFX "Resuming...\n");
 
        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);
 
        bcm43xx_chipset_attach(bcm);