diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 138 |
1 files changed, 72 insertions, 66 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3a1c156d275f..2b3cf39dd4b1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #include "reg.h" | 59 | #include "reg.h" |
60 | #include "debug.h" | 60 | #include "debug.h" |
61 | 61 | ||
62 | static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | 62 | static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ |
63 | static int modparam_nohwcrypt; | 63 | static int modparam_nohwcrypt; |
64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -376,7 +376,7 @@ static int ath5k_stop_hw(struct ath5k_softc *sc); | |||
376 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | 376 | static irqreturn_t ath5k_intr(int irq, void *dev_id); |
377 | static void ath5k_tasklet_reset(unsigned long data); | 377 | static void ath5k_tasklet_reset(unsigned long data); |
378 | 378 | ||
379 | static void ath5k_calibrate(unsigned long data); | 379 | static void ath5k_tasklet_calibrate(unsigned long data); |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * Module init/exit functions | 382 | * Module init/exit functions |
@@ -471,7 +471,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
471 | * DMA to work so force a reasonable value here if it | 471 | * DMA to work so force a reasonable value here if it |
472 | * comes up zero. | 472 | * comes up zero. |
473 | */ | 473 | */ |
474 | csz = L1_CACHE_BYTES / sizeof(u32); | 474 | csz = L1_CACHE_BYTES >> 2; |
475 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | 475 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); |
476 | } | 476 | } |
477 | /* | 477 | /* |
@@ -544,7 +544,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
544 | __set_bit(ATH_STAT_INVALID, sc->status); | 544 | __set_bit(ATH_STAT_INVALID, sc->status); |
545 | 545 | ||
546 | sc->iobase = mem; /* So we can unmap it on detach */ | 546 | sc->iobase = mem; /* So we can unmap it on detach */ |
547 | sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ | 547 | sc->common.cachelsz = csz << 2; /* convert to bytes */ |
548 | sc->opmode = NL80211_IFTYPE_STATION; | 548 | sc->opmode = NL80211_IFTYPE_STATION; |
549 | sc->bintval = 1000; | 549 | sc->bintval = 1000; |
550 | mutex_init(&sc->lock); | 550 | mutex_init(&sc->lock); |
@@ -799,8 +799,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
799 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | 799 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); |
800 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | 800 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); |
801 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 801 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
802 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | ||
802 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 803 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
803 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); | ||
804 | 804 | ||
805 | ret = ath5k_eeprom_read_mac(ah, mac); | 805 | ret = ath5k_eeprom_read_mac(ah, mac); |
806 | if (ret) { | 806 | if (ret) { |
@@ -1071,10 +1071,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | /* | 1073 | /* |
1074 | * Set/change channels. If the channel is really being changed, | 1074 | * Set/change channels. We always reset the chip. |
1075 | * it's done by reseting the chip. To accomplish this we must | 1075 | * To accomplish this we must first cleanup any pending DMA, |
1076 | * first cleanup any pending DMA, then restart stuff after a la | 1076 | * then restart stuff after a la ath5k_init. |
1077 | * ath5k_init. | ||
1078 | * | 1077 | * |
1079 | * Called with sc->lock. | 1078 | * Called with sc->lock. |
1080 | */ | 1079 | */ |
@@ -1084,19 +1083,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1084 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", | 1083 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", |
1085 | sc->curchan->center_freq, chan->center_freq); | 1084 | sc->curchan->center_freq, chan->center_freq); |
1086 | 1085 | ||
1087 | if (chan->center_freq != sc->curchan->center_freq || | 1086 | /* |
1088 | chan->hw_value != sc->curchan->hw_value) { | 1087 | * To switch channels clear any pending DMA operations; |
1089 | 1088 | * wait long enough for the RX fifo to drain, reset the | |
1090 | /* | 1089 | * hardware at the new frequency, and then re-enable |
1091 | * To switch channels clear any pending DMA operations; | 1090 | * the relevant bits of the h/w. |
1092 | * wait long enough for the RX fifo to drain, reset the | 1091 | */ |
1093 | * hardware at the new frequency, and then re-enable | 1092 | return ath5k_reset(sc, chan); |
1094 | * the relevant bits of the h/w. | ||
1095 | */ | ||
1096 | return ath5k_reset(sc, chan); | ||
1097 | } | ||
1098 | |||
1099 | return 0; | ||
1100 | } | 1093 | } |
1101 | 1094 | ||
1102 | static void | 1095 | static void |
@@ -1158,27 +1151,20 @@ static | |||
1158 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | 1151 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) |
1159 | { | 1152 | { |
1160 | struct sk_buff *skb; | 1153 | struct sk_buff *skb; |
1161 | unsigned int off; | ||
1162 | 1154 | ||
1163 | /* | 1155 | /* |
1164 | * Allocate buffer with headroom_needed space for the | 1156 | * Allocate buffer with headroom_needed space for the |
1165 | * fake physical layer header at the start. | 1157 | * fake physical layer header at the start. |
1166 | */ | 1158 | */ |
1167 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | 1159 | skb = ath_rxbuf_alloc(&sc->common, |
1160 | sc->rxbufsize + sc->common.cachelsz - 1, | ||
1161 | GFP_ATOMIC); | ||
1168 | 1162 | ||
1169 | if (!skb) { | 1163 | if (!skb) { |
1170 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | 1164 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", |
1171 | sc->rxbufsize + sc->cachelsz - 1); | 1165 | sc->rxbufsize + sc->common.cachelsz - 1); |
1172 | return NULL; | 1166 | return NULL; |
1173 | } | 1167 | } |
1174 | /* | ||
1175 | * Cache-line-align. This is important (for the | ||
1176 | * 5210 at least) as not doing so causes bogus data | ||
1177 | * in rx'd frames. | ||
1178 | */ | ||
1179 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1180 | if (off != 0) | ||
1181 | skb_reserve(skb, sc->cachelsz - off); | ||
1182 | 1168 | ||
1183 | *skb_addr = pci_map_single(sc->pdev, | 1169 | *skb_addr = pci_map_single(sc->pdev, |
1184 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | 1170 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); |
@@ -1620,10 +1606,10 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1620 | struct ath5k_buf *bf; | 1606 | struct ath5k_buf *bf; |
1621 | int ret; | 1607 | int ret; |
1622 | 1608 | ||
1623 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); | 1609 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); |
1624 | 1610 | ||
1625 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | 1611 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", |
1626 | sc->cachelsz, sc->rxbufsize); | 1612 | sc->common.cachelsz, sc->rxbufsize); |
1627 | 1613 | ||
1628 | spin_lock_bh(&sc->rxbuflock); | 1614 | spin_lock_bh(&sc->rxbuflock); |
1629 | sc->rxlink = NULL; | 1615 | sc->rxlink = NULL; |
@@ -2371,7 +2357,7 @@ ath5k_init(struct ath5k_softc *sc) | |||
2371 | sc->curband = &sc->sbands[sc->curchan->band]; | 2357 | sc->curband = &sc->sbands[sc->curchan->band]; |
2372 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2358 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2373 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2359 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2374 | AR5K_INT_FATAL | AR5K_INT_GLOBAL; | 2360 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; |
2375 | ret = ath5k_reset(sc, NULL); | 2361 | ret = ath5k_reset(sc, NULL); |
2376 | if (ret) | 2362 | if (ret) |
2377 | goto done; | 2363 | goto done; |
@@ -2388,8 +2374,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2388 | /* Set ack to be sent at low bit-rates */ | 2374 | /* Set ack to be sent at low bit-rates */ |
2389 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2375 | ath5k_hw_set_ack_bitrate_high(ah, false); |
2390 | 2376 | ||
2391 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | 2377 | /* Set PHY calibration inteval */ |
2392 | msecs_to_jiffies(ath5k_calinterval * 1000))); | 2378 | ah->ah_cal_intval = ath5k_calinterval; |
2393 | 2379 | ||
2394 | ret = 0; | 2380 | ret = 0; |
2395 | done: | 2381 | done: |
@@ -2453,37 +2439,39 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2453 | ret = ath5k_stop_locked(sc); | 2439 | ret = ath5k_stop_locked(sc); |
2454 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | 2440 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { |
2455 | /* | 2441 | /* |
2456 | * Set the chip in full sleep mode. Note that we are | 2442 | * Don't set the card in full sleep mode! |
2457 | * careful to do this only when bringing the interface | 2443 | * |
2458 | * completely to a stop. When the chip is in this state | 2444 | * a) When the device is in this state it must be carefully |
2459 | * it must be carefully woken up or references to | 2445 | * woken up or references to registers in the PCI clock |
2460 | * registers in the PCI clock domain may freeze the bus | 2446 | * domain may freeze the bus (and system). This varies |
2461 | * (and system). This varies by chip and is mostly an | 2447 | * by chip and is mostly an issue with newer parts |
2462 | * issue with newer parts that go to sleep more quickly. | 2448 | * (madwifi sources mentioned srev >= 0x78) that go to |
2463 | */ | 2449 | * sleep more quickly. |
2464 | if (sc->ah->ah_mac_srev >= 0x78) { | 2450 | * |
2465 | /* | 2451 | * b) On older chips full sleep results a weird behaviour |
2466 | * XXX | 2452 | * during wakeup. I tested various cards with srev < 0x78 |
2467 | * don't put newer MAC revisions > 7.8 to sleep because | 2453 | * and they don't wake up after module reload, a second |
2468 | * of the above mentioned problems | 2454 | * module reload is needed to bring the card up again. |
2469 | */ | 2455 | * |
2470 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " | 2456 | * Until we figure out what's going on don't enable |
2471 | "not putting device to sleep\n"); | 2457 | * full chip reset on any chip (this is what Legacy HAL |
2472 | } else { | 2458 | * and Sam's HAL do anyway). Instead Perform a full reset |
2473 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2459 | * on the device (same as initial state after attach) and |
2474 | "putting device to full sleep\n"); | 2460 | * leave it idle (keep MAC/BB on warm reset) */ |
2475 | ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); | 2461 | ret = ath5k_hw_on_hold(sc->ah); |
2476 | } | 2462 | |
2463 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2464 | "putting device to sleep\n"); | ||
2477 | } | 2465 | } |
2478 | ath5k_txbuf_free(sc, sc->bbuf); | 2466 | ath5k_txbuf_free(sc, sc->bbuf); |
2479 | 2467 | ||
2480 | mmiowb(); | 2468 | mmiowb(); |
2481 | mutex_unlock(&sc->lock); | 2469 | mutex_unlock(&sc->lock); |
2482 | 2470 | ||
2483 | del_timer_sync(&sc->calib_tim); | ||
2484 | tasklet_kill(&sc->rxtq); | 2471 | tasklet_kill(&sc->rxtq); |
2485 | tasklet_kill(&sc->txtq); | 2472 | tasklet_kill(&sc->txtq); |
2486 | tasklet_kill(&sc->restq); | 2473 | tasklet_kill(&sc->restq); |
2474 | tasklet_kill(&sc->calib); | ||
2487 | tasklet_kill(&sc->beacontq); | 2475 | tasklet_kill(&sc->beacontq); |
2488 | 2476 | ||
2489 | ath5k_rfkill_hw_stop(sc->ah); | 2477 | ath5k_rfkill_hw_stop(sc->ah); |
@@ -2539,6 +2527,9 @@ ath5k_intr(int irq, void *dev_id) | |||
2539 | if (status & AR5K_INT_BMISS) { | 2527 | if (status & AR5K_INT_BMISS) { |
2540 | /* TODO */ | 2528 | /* TODO */ |
2541 | } | 2529 | } |
2530 | if (status & AR5K_INT_SWI) { | ||
2531 | tasklet_schedule(&sc->calib); | ||
2532 | } | ||
2542 | if (status & AR5K_INT_MIB) { | 2533 | if (status & AR5K_INT_MIB) { |
2543 | /* | 2534 | /* |
2544 | * These stats are also used for ANI i think | 2535 | * These stats are also used for ANI i think |
@@ -2555,6 +2546,8 @@ ath5k_intr(int irq, void *dev_id) | |||
2555 | if (unlikely(!counter)) | 2546 | if (unlikely(!counter)) |
2556 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2547 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2557 | 2548 | ||
2549 | ath5k_hw_calibration_poll(ah); | ||
2550 | |||
2558 | return IRQ_HANDLED; | 2551 | return IRQ_HANDLED; |
2559 | } | 2552 | } |
2560 | 2553 | ||
@@ -2571,11 +2564,19 @@ ath5k_tasklet_reset(unsigned long data) | |||
2571 | * for temperature/environment changes. | 2564 | * for temperature/environment changes. |
2572 | */ | 2565 | */ |
2573 | static void | 2566 | static void |
2574 | ath5k_calibrate(unsigned long data) | 2567 | ath5k_tasklet_calibrate(unsigned long data) |
2575 | { | 2568 | { |
2576 | struct ath5k_softc *sc = (void *)data; | 2569 | struct ath5k_softc *sc = (void *)data; |
2577 | struct ath5k_hw *ah = sc->ah; | 2570 | struct ath5k_hw *ah = sc->ah; |
2578 | 2571 | ||
2572 | /* Only full calibration for now */ | ||
2573 | if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) | ||
2574 | return; | ||
2575 | |||
2576 | /* Stop queues so that calibration | ||
2577 | * doesn't interfere with tx */ | ||
2578 | ieee80211_stop_queues(sc->hw); | ||
2579 | |||
2579 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", | 2580 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", |
2580 | ieee80211_frequency_to_channel(sc->curchan->center_freq), | 2581 | ieee80211_frequency_to_channel(sc->curchan->center_freq), |
2581 | sc->curchan->hw_value); | 2582 | sc->curchan->hw_value); |
@@ -2593,8 +2594,11 @@ ath5k_calibrate(unsigned long data) | |||
2593 | ieee80211_frequency_to_channel( | 2594 | ieee80211_frequency_to_channel( |
2594 | sc->curchan->center_freq)); | 2595 | sc->curchan->center_freq)); |
2595 | 2596 | ||
2596 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | 2597 | ah->ah_swi_mask = 0; |
2597 | msecs_to_jiffies(ath5k_calinterval * 1000))); | 2598 | |
2599 | /* Wake queues */ | ||
2600 | ieee80211_wake_queues(sc->hw); | ||
2601 | |||
2598 | } | 2602 | } |
2599 | 2603 | ||
2600 | 2604 | ||
@@ -2811,9 +2815,11 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2811 | 2815 | ||
2812 | mutex_lock(&sc->lock); | 2816 | mutex_lock(&sc->lock); |
2813 | 2817 | ||
2814 | ret = ath5k_chan_set(sc, conf->channel); | 2818 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
2815 | if (ret < 0) | 2819 | ret = ath5k_chan_set(sc, conf->channel); |
2816 | goto unlock; | 2820 | if (ret < 0) |
2821 | goto unlock; | ||
2822 | } | ||
2817 | 2823 | ||
2818 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && | 2824 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && |
2819 | (sc->power_level != conf->power_level)) { | 2825 | (sc->power_level != conf->power_level)) { |