]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/ath5k/base.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6] / drivers / net / wireless / ath5k / base.c
index c5bf8a2ef5cd14d82b1cbf77622b5722764b0d25..2028866f59951068ebb799ee3209ef22d9ff13c6 100644 (file)
@@ -43,7 +43,9 @@
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/hardirq.h>
 #include <linux/if.h>
+#include <linux/io.h>
 #include <linux/netdevice.h>
 #include <linux/cache.h>
 #include <linux/pci.h>
@@ -93,8 +95,6 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = {
        { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
        { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
        { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/
-       { PCI_VDEVICE(ATHEROS, 0x0023), .driver_data = AR5K_AR5212 }, /* 5416 */
-       { PCI_VDEVICE(ATHEROS, 0x0024), .driver_data = AR5K_AR5212 }, /* 5418 */
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
@@ -471,9 +471,6 @@ ath5k_pci_probe(struct pci_dev *pdev,
        /* Set private data */
        pci_set_drvdata(pdev, hw);
 
-       /* Enable msi for devices that support it */
-       pci_enable_msi(pdev);
-
        /* Setup interrupt handler */
        ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
        if (ret) {
@@ -551,7 +548,6 @@ err_ah:
 err_irq:
        free_irq(pdev->irq, sc);
 err_free:
-       pci_disable_msi(pdev);
        ieee80211_free_hw(hw);
 err_map:
        pci_iounmap(pdev, mem);
@@ -573,7 +569,6 @@ ath5k_pci_remove(struct pci_dev *pdev)
        ath5k_detach(pdev, hw);
        ath5k_hw_detach(sc->ah);
        free_irq(pdev->irq, sc);
-       pci_disable_msi(pdev);
        pci_iounmap(pdev, sc->iobase);
        pci_release_region(pdev, 0);
        pci_disable_device(pdev);
@@ -590,6 +585,9 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        ath5k_led_off(sc);
 
        ath5k_stop_hw(sc);
+
+       free_irq(pdev->irq, sc);
+       pci_disable_msi(pdev);
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
@@ -605,15 +603,12 @@ ath5k_pci_resume(struct pci_dev *pdev)
        struct ath5k_hw *ah = sc->ah;
        int i, err;
 
-       err = pci_set_power_state(pdev, PCI_D0);
-       if (err)
-               return err;
+       pci_restore_state(pdev);
 
        err = pci_enable_device(pdev);
        if (err)
                return err;
 
-       pci_restore_state(pdev);
        /*
         * Suspend/Resume resets the PCI configuration space, so we have to
         * re-disable the RETRY_TIMEOUT register (0x41) to keep
@@ -621,7 +616,17 @@ ath5k_pci_resume(struct pci_dev *pdev)
         */
        pci_write_config_byte(pdev, 0x41, 0);
 
-       ath5k_init(sc);
+       pci_enable_msi(pdev);
+
+       err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+       if (err) {
+               ATH5K_ERR(sc, "request_irq failed\n");
+               goto err_msi;
+       }
+
+       err = ath5k_init(sc);
+       if (err)
+               goto err_irq;
        ath5k_led_enable(sc);
 
        /*
@@ -635,6 +640,12 @@ ath5k_pci_resume(struct pci_dev *pdev)
                ath5k_hw_reset_key(ah, i);
 
        return 0;
+err_irq:
+       free_irq(pdev->irq, sc);
+err_msi:
+       pci_disable_msi(pdev);
+       pci_disable_device(pdev);
+       return err;
 }
 #endif /* CONFIG_PM */
 
@@ -1224,7 +1235,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 
        pktlen = skb->len;
 
-       if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) {
+       if (info->control.hw_key) {
                keyidx = info->control.hw_key->hw_key_idx;
                pktlen += info->control.icv_len;
        }
@@ -1249,6 +1260,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 
        txq->link = &ds->ds_link;
        ath5k_hw_tx_start(ah, txq->qnum);
+       mmiowb();
        spin_unlock_bh(&txq->lock);
 
        return 0;
@@ -1583,7 +1595,6 @@ ath5k_rx_stop(struct ath5k_softc *sc)
        ath5k_hw_stop_pcu_recv(ah);     /* disable PCU */
        ath5k_hw_set_rx_filter(ah, 0);  /* clear recv filter */
        ath5k_hw_stop_rx_dma(ah);       /* disable DMA engine */
-       mdelay(3);                      /* 3ms is long enough for 1 frame */
 
        ath5k_debug_printrxbuffs(sc, ah);
 
@@ -1702,10 +1713,6 @@ ath5k_tasklet_rx(unsigned long data)
                skb = bf->skb;
                ds = bf->desc;
 
-               /* TODO only one segment */
-               pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
-                               sc->desc_len, PCI_DMA_FROMDEVICE);
-
                /*
                 * last buffer must not be freed to ensure proper hardware
                 * function. When the hardware finishes also a packet next to
@@ -1769,8 +1776,6 @@ ath5k_tasklet_rx(unsigned long data)
                                goto next;
                }
 accept:
-               pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
-                               rs.rs_datalen, PCI_DMA_FROMDEVICE);
                pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
                                PCI_DMA_FROMDEVICE);
                bf->skb = NULL;
@@ -1858,9 +1863,6 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
        list_for_each_entry_safe(bf, bf0, &txq->q, list) {
                ds = bf->desc;
 
-               /* TODO only one segment */
-               pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
-                               sc->desc_len, PCI_DMA_FROMDEVICE);
                ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
                if (unlikely(ret == -EINPROGRESS))
                        break;
@@ -2033,8 +2035,6 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
                /* NB: hw still stops DMA, so proceed */
        }
-       pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len,
-                       PCI_DMA_TODEVICE);
 
        ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
        ath5k_hw_tx_start(ah, sc->bhalq);
@@ -2168,6 +2168,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 
        ath5k_hw_set_intr(ah, 0);
        sc->bmisscount = 0;
+       sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
 
        if (sc->opmode == IEEE80211_IF_TYPE_STA) {
                sc->imask |= AR5K_INT_BMISS;
@@ -2258,6 +2259,7 @@ ath5k_init(struct ath5k_softc *sc)
 
        ret = 0;
 done:
+       mmiowb();
        mutex_unlock(&sc->lock);
        return ret;
 }
@@ -2290,6 +2292,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
        if (!test_bit(ATH_STAT_INVALID, sc->status)) {
                ath5k_led_off(sc);
                ath5k_hw_set_intr(ah, 0);
+               synchronize_irq(sc->pdev->irq);
        }
        ath5k_txq_cleanup(sc);
        if (!test_bit(ATH_STAT_INVALID, sc->status)) {
@@ -2339,6 +2342,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
                }
        }
        ath5k_txbuf_free(sc, sc->bbuf);
+       mmiowb();
        mutex_unlock(&sc->lock);
 
        del_timer_sync(&sc->calib_tim);
@@ -2571,8 +2575,6 @@ ath5k_init_leds(struct ath5k_softc *sc)
        struct pci_dev *pdev = sc->pdev;
        char name[ATH5K_LED_MAX_NAME_LEN + 1];
 
-       sc->led_on = 0;  /* active low */
-
        /*
         * Auto-enable soft led processing for IBM cards and for
         * 5211 minipci cards.
@@ -2581,11 +2583,13 @@ ath5k_init_leds(struct ath5k_softc *sc)
            pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
                __set_bit(ATH_STAT_LEDSOFT, sc->status);
                sc->led_pin = 0;
+               sc->led_on = 0;  /* active low */
        }
        /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
        if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
                __set_bit(ATH_STAT_LEDSOFT, sc->status);
                sc->led_pin = 1;
+               sc->led_on = 1;  /* active high */
        }
        if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
                goto out;
@@ -2804,6 +2808,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                /* XXX: assoc id is set to 0 for now, mac80211 doesn't have
                 * a clean way of letting us retrieve this yet. */
                ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+               mmiowb();
        }
 
        if (conf->changed & IEEE80211_IFCC_BEACON &&
@@ -2992,6 +2997,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        }
 
 unlock:
+       mmiowb();
        mutex_unlock(&sc->lock);
        return ret;
 }
@@ -3053,8 +3059,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
 
-       mutex_lock(&sc->lock);
-
        if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
                ret = -EIO;
                goto end;
@@ -3065,11 +3069,12 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
        ret = ath5k_beacon_setup(sc, sc->bbuf);
        if (ret)
                sc->bbuf->skb = NULL;
-       else
+       else {
                ath5k_beacon_config(sc);
+               mmiowb();
+       }
 
 end:
-       mutex_unlock(&sc->lock);
        return ret;
 }