aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath5k/base.c99
1 files changed, 63 insertions, 36 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index d9769c527346..ff3fad794b61 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -43,7 +43,9 @@
43#include <linux/version.h> 43#include <linux/version.h>
44#include <linux/module.h> 44#include <linux/module.h>
45#include <linux/delay.h> 45#include <linux/delay.h>
46#include <linux/hardirq.h>
46#include <linux/if.h> 47#include <linux/if.h>
48#include <linux/io.h>
47#include <linux/netdevice.h> 49#include <linux/netdevice.h>
48#include <linux/cache.h> 50#include <linux/cache.h>
49#include <linux/pci.h> 51#include <linux/pci.h>
@@ -471,9 +473,6 @@ ath5k_pci_probe(struct pci_dev *pdev,
471 /* Set private data */ 473 /* Set private data */
472 pci_set_drvdata(pdev, hw); 474 pci_set_drvdata(pdev, hw);
473 475
474 /* Enable msi for devices that support it */
475 pci_enable_msi(pdev);
476
477 /* Setup interrupt handler */ 476 /* Setup interrupt handler */
478 ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); 477 ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
479 if (ret) { 478 if (ret) {
@@ -551,7 +550,6 @@ err_ah:
551err_irq: 550err_irq:
552 free_irq(pdev->irq, sc); 551 free_irq(pdev->irq, sc);
553err_free: 552err_free:
554 pci_disable_msi(pdev);
555 ieee80211_free_hw(hw); 553 ieee80211_free_hw(hw);
556err_map: 554err_map:
557 pci_iounmap(pdev, mem); 555 pci_iounmap(pdev, mem);
@@ -573,7 +571,6 @@ ath5k_pci_remove(struct pci_dev *pdev)
573 ath5k_detach(pdev, hw); 571 ath5k_detach(pdev, hw);
574 ath5k_hw_detach(sc->ah); 572 ath5k_hw_detach(sc->ah);
575 free_irq(pdev->irq, sc); 573 free_irq(pdev->irq, sc);
576 pci_disable_msi(pdev);
577 pci_iounmap(pdev, sc->iobase); 574 pci_iounmap(pdev, sc->iobase);
578 pci_release_region(pdev, 0); 575 pci_release_region(pdev, 0);
579 pci_disable_device(pdev); 576 pci_disable_device(pdev);
@@ -590,6 +587,9 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
590 ath5k_led_off(sc); 587 ath5k_led_off(sc);
591 588
592 ath5k_stop_hw(sc); 589 ath5k_stop_hw(sc);
590
591 free_irq(pdev->irq, sc);
592 pci_disable_msi(pdev);
593 pci_save_state(pdev); 593 pci_save_state(pdev);
594 pci_disable_device(pdev); 594 pci_disable_device(pdev);
595 pci_set_power_state(pdev, PCI_D3hot); 595 pci_set_power_state(pdev, PCI_D3hot);
@@ -605,15 +605,12 @@ ath5k_pci_resume(struct pci_dev *pdev)
605 struct ath5k_hw *ah = sc->ah; 605 struct ath5k_hw *ah = sc->ah;
606 int i, err; 606 int i, err;
607 607
608 err = pci_set_power_state(pdev, PCI_D0); 608 pci_restore_state(pdev);
609 if (err)
610 return err;
611 609
612 err = pci_enable_device(pdev); 610 err = pci_enable_device(pdev);
613 if (err) 611 if (err)
614 return err; 612 return err;
615 613
616 pci_restore_state(pdev);
617 /* 614 /*
618 * Suspend/Resume resets the PCI configuration space, so we have to 615 * Suspend/Resume resets the PCI configuration space, so we have to
619 * re-disable the RETRY_TIMEOUT register (0x41) to keep 616 * re-disable the RETRY_TIMEOUT register (0x41) to keep
@@ -621,7 +618,17 @@ ath5k_pci_resume(struct pci_dev *pdev)
621 */ 618 */
622 pci_write_config_byte(pdev, 0x41, 0); 619 pci_write_config_byte(pdev, 0x41, 0);
623 620
624 ath5k_init(sc); 621 pci_enable_msi(pdev);
622
623 err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
624 if (err) {
625 ATH5K_ERR(sc, "request_irq failed\n");
626 goto err_msi;
627 }
628
629 err = ath5k_init(sc);
630 if (err)
631 goto err_irq;
625 ath5k_led_enable(sc); 632 ath5k_led_enable(sc);
626 633
627 /* 634 /*
@@ -635,6 +642,12 @@ ath5k_pci_resume(struct pci_dev *pdev)
635 ath5k_hw_reset_key(ah, i); 642 ath5k_hw_reset_key(ah, i);
636 643
637 return 0; 644 return 0;
645err_irq:
646 free_irq(pdev->irq, sc);
647err_msi:
648 pci_disable_msi(pdev);
649 pci_disable_device(pdev);
650 return err;
638} 651}
639#endif /* CONFIG_PM */ 652#endif /* CONFIG_PM */
640 653
@@ -1224,7 +1237,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1224 1237
1225 pktlen = skb->len; 1238 pktlen = skb->len;
1226 1239
1227 if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) { 1240 if (info->control.hw_key) {
1228 keyidx = info->control.hw_key->hw_key_idx; 1241 keyidx = info->control.hw_key->hw_key_idx;
1229 pktlen += info->control.icv_len; 1242 pktlen += info->control.icv_len;
1230 } 1243 }
@@ -1249,6 +1262,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1249 1262
1250 txq->link = &ds->ds_link; 1263 txq->link = &ds->ds_link;
1251 ath5k_hw_tx_start(ah, txq->qnum); 1264 ath5k_hw_tx_start(ah, txq->qnum);
1265 mmiowb();
1252 spin_unlock_bh(&txq->lock); 1266 spin_unlock_bh(&txq->lock);
1253 1267
1254 return 0; 1268 return 0;
@@ -1583,7 +1597,6 @@ ath5k_rx_stop(struct ath5k_softc *sc)
1583 ath5k_hw_stop_pcu_recv(ah); /* disable PCU */ 1597 ath5k_hw_stop_pcu_recv(ah); /* disable PCU */
1584 ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ 1598 ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
1585 ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ 1599 ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
1586 mdelay(3); /* 3ms is long enough for 1 frame */
1587 1600
1588 ath5k_debug_printrxbuffs(sc, ah); 1601 ath5k_debug_printrxbuffs(sc, ah);
1589 1602
@@ -1682,31 +1695,44 @@ ath5k_tasklet_rx(unsigned long data)
1682 struct ath5k_rx_status rs = {}; 1695 struct ath5k_rx_status rs = {};
1683 struct sk_buff *skb; 1696 struct sk_buff *skb;
1684 struct ath5k_softc *sc = (void *)data; 1697 struct ath5k_softc *sc = (void *)data;
1685 struct ath5k_buf *bf; 1698 struct ath5k_buf *bf, *bf_last;
1686 struct ath5k_desc *ds; 1699 struct ath5k_desc *ds;
1687 int ret; 1700 int ret;
1688 int hdrlen; 1701 int hdrlen;
1689 int pad; 1702 int pad;
1690 1703
1691 spin_lock(&sc->rxbuflock); 1704 spin_lock(&sc->rxbuflock);
1705 if (list_empty(&sc->rxbuf)) {
1706 ATH5K_WARN(sc, "empty rx buf pool\n");
1707 goto unlock;
1708 }
1709 bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
1692 do { 1710 do {
1693 rxs.flag = 0; 1711 rxs.flag = 0;
1694 1712
1695 if (unlikely(list_empty(&sc->rxbuf))) {
1696 ATH5K_WARN(sc, "empty rx buf pool\n");
1697 break;
1698 }
1699 bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); 1713 bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
1700 BUG_ON(bf->skb == NULL); 1714 BUG_ON(bf->skb == NULL);
1701 skb = bf->skb; 1715 skb = bf->skb;
1702 ds = bf->desc; 1716 ds = bf->desc;
1703 1717
1704 /* TODO only one segment */ 1718 /*
1705 pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, 1719 * last buffer must not be freed to ensure proper hardware
1706 sc->desc_len, PCI_DMA_FROMDEVICE); 1720 * function. When the hardware finishes also a packet next to
1707 1721 * it, we are sure, it doesn't use it anymore and we can go on.
1708 if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ 1722 */
1709 break; 1723 if (bf_last == bf)
1724 bf->flags |= 1;
1725 if (bf->flags) {
1726 struct ath5k_buf *bf_next = list_entry(bf->list.next,
1727 struct ath5k_buf, list);
1728 ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
1729 &rs);
1730 if (ret)
1731 break;
1732 bf->flags &= ~1;
1733 /* skip the overwritten one (even status is martian) */
1734 goto next;
1735 }
1710 1736
1711 ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); 1737 ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
1712 if (unlikely(ret == -EINPROGRESS)) 1738 if (unlikely(ret == -EINPROGRESS))
@@ -1752,8 +1778,6 @@ ath5k_tasklet_rx(unsigned long data)
1752 goto next; 1778 goto next;
1753 } 1779 }
1754accept: 1780accept:
1755 pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
1756 rs.rs_datalen, PCI_DMA_FROMDEVICE);
1757 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, 1781 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
1758 PCI_DMA_FROMDEVICE); 1782 PCI_DMA_FROMDEVICE);
1759 bf->skb = NULL; 1783 bf->skb = NULL;
@@ -1816,6 +1840,7 @@ accept:
1816next: 1840next:
1817 list_move_tail(&bf->list, &sc->rxbuf); 1841 list_move_tail(&bf->list, &sc->rxbuf);
1818 } while (ath5k_rxbuf_setup(sc, bf) == 0); 1842 } while (ath5k_rxbuf_setup(sc, bf) == 0);
1843unlock:
1819 spin_unlock(&sc->rxbuflock); 1844 spin_unlock(&sc->rxbuflock);
1820} 1845}
1821 1846
@@ -1840,9 +1865,6 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
1840 list_for_each_entry_safe(bf, bf0, &txq->q, list) { 1865 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
1841 ds = bf->desc; 1866 ds = bf->desc;
1842 1867
1843 /* TODO only one segment */
1844 pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
1845 sc->desc_len, PCI_DMA_FROMDEVICE);
1846 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); 1868 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
1847 if (unlikely(ret == -EINPROGRESS)) 1869 if (unlikely(ret == -EINPROGRESS))
1848 break; 1870 break;
@@ -2015,8 +2037,6 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2015 ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); 2037 ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
2016 /* NB: hw still stops DMA, so proceed */ 2038 /* NB: hw still stops DMA, so proceed */
2017 } 2039 }
2018 pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len,
2019 PCI_DMA_TODEVICE);
2020 2040
2021 ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); 2041 ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
2022 ath5k_hw_tx_start(ah, sc->bhalq); 2042 ath5k_hw_tx_start(ah, sc->bhalq);
@@ -2240,6 +2260,7 @@ ath5k_init(struct ath5k_softc *sc)
2240 2260
2241 ret = 0; 2261 ret = 0;
2242done: 2262done:
2263 mmiowb();
2243 mutex_unlock(&sc->lock); 2264 mutex_unlock(&sc->lock);
2244 return ret; 2265 return ret;
2245} 2266}
@@ -2272,6 +2293,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
2272 if (!test_bit(ATH_STAT_INVALID, sc->status)) { 2293 if (!test_bit(ATH_STAT_INVALID, sc->status)) {
2273 ath5k_led_off(sc); 2294 ath5k_led_off(sc);
2274 ath5k_hw_set_intr(ah, 0); 2295 ath5k_hw_set_intr(ah, 0);
2296 synchronize_irq(sc->pdev->irq);
2275 } 2297 }
2276 ath5k_txq_cleanup(sc); 2298 ath5k_txq_cleanup(sc);
2277 if (!test_bit(ATH_STAT_INVALID, sc->status)) { 2299 if (!test_bit(ATH_STAT_INVALID, sc->status)) {
@@ -2321,9 +2343,13 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2321 } 2343 }
2322 } 2344 }
2323 ath5k_txbuf_free(sc, sc->bbuf); 2345 ath5k_txbuf_free(sc, sc->bbuf);
2346 mmiowb();
2324 mutex_unlock(&sc->lock); 2347 mutex_unlock(&sc->lock);
2325 2348
2326 del_timer_sync(&sc->calib_tim); 2349 del_timer_sync(&sc->calib_tim);
2350 tasklet_kill(&sc->rxtq);
2351 tasklet_kill(&sc->txtq);
2352 tasklet_kill(&sc->restq);
2327 2353
2328 return ret; 2354 return ret;
2329} 2355}
@@ -2550,8 +2576,6 @@ ath5k_init_leds(struct ath5k_softc *sc)
2550 struct pci_dev *pdev = sc->pdev; 2576 struct pci_dev *pdev = sc->pdev;
2551 char name[ATH5K_LED_MAX_NAME_LEN + 1]; 2577 char name[ATH5K_LED_MAX_NAME_LEN + 1];
2552 2578
2553 sc->led_on = 0; /* active low */
2554
2555 /* 2579 /*
2556 * Auto-enable soft led processing for IBM cards and for 2580 * Auto-enable soft led processing for IBM cards and for
2557 * 5211 minipci cards. 2581 * 5211 minipci cards.
@@ -2560,11 +2584,13 @@ ath5k_init_leds(struct ath5k_softc *sc)
2560 pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { 2584 pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
2561 __set_bit(ATH_STAT_LEDSOFT, sc->status); 2585 __set_bit(ATH_STAT_LEDSOFT, sc->status);
2562 sc->led_pin = 0; 2586 sc->led_pin = 0;
2587 sc->led_on = 0; /* active low */
2563 } 2588 }
2564 /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ 2589 /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
2565 if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { 2590 if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
2566 __set_bit(ATH_STAT_LEDSOFT, sc->status); 2591 __set_bit(ATH_STAT_LEDSOFT, sc->status);
2567 sc->led_pin = 1; 2592 sc->led_pin = 1;
2593 sc->led_on = 1; /* active high */
2568 } 2594 }
2569 if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) 2595 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
2570 goto out; 2596 goto out;
@@ -2783,6 +2809,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2783 /* XXX: assoc id is set to 0 for now, mac80211 doesn't have 2809 /* XXX: assoc id is set to 0 for now, mac80211 doesn't have
2784 * a clean way of letting us retrieve this yet. */ 2810 * a clean way of letting us retrieve this yet. */
2785 ath5k_hw_set_associd(ah, ah->ah_bssid, 0); 2811 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
2812 mmiowb();
2786 } 2813 }
2787 2814
2788 if (conf->changed & IEEE80211_IFCC_BEACON && 2815 if (conf->changed & IEEE80211_IFCC_BEACON &&
@@ -2971,6 +2998,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2971 } 2998 }
2972 2999
2973unlock: 3000unlock:
3001 mmiowb();
2974 mutex_unlock(&sc->lock); 3002 mutex_unlock(&sc->lock);
2975 return ret; 3003 return ret;
2976} 3004}
@@ -3032,8 +3060,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
3032 3060
3033 ath5k_debug_dump_skb(sc, skb, "BC ", 1); 3061 ath5k_debug_dump_skb(sc, skb, "BC ", 1);
3034 3062
3035 mutex_lock(&sc->lock);
3036
3037 if (sc->opmode != IEEE80211_IF_TYPE_IBSS) { 3063 if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
3038 ret = -EIO; 3064 ret = -EIO;
3039 goto end; 3065 goto end;
@@ -3044,11 +3070,12 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
3044 ret = ath5k_beacon_setup(sc, sc->bbuf); 3070 ret = ath5k_beacon_setup(sc, sc->bbuf);
3045 if (ret) 3071 if (ret)
3046 sc->bbuf->skb = NULL; 3072 sc->bbuf->skb = NULL;
3047 else 3073 else {
3048 ath5k_beacon_config(sc); 3074 ath5k_beacon_config(sc);
3075 mmiowb();
3076 }
3049 3077
3050end: 3078end:
3051 mutex_unlock(&sc->lock);
3052 return ret; 3079 return ret;
3053} 3080}
3054 3081