diff options
146 files changed, 4231 insertions, 4191 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 842aa9de84a6..f45638962858 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -564,3 +564,12 @@ Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | |||
564 | 564 | ||
565 | ---------------------------- | 565 | ---------------------------- |
566 | 566 | ||
567 | What: iwlwifi disable_hw_scan module parameters | ||
568 | When: 2.6.40 | ||
569 | Why: Hareware scan is the prefer method for iwlwifi devices for | ||
570 | scanning operation. Remove software scan support for all the | ||
571 | iwlwifi devices. | ||
572 | |||
573 | Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> | ||
574 | |||
575 | ---------------------------- | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 9ddb5ac923cd..51bfd5e856e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6431,7 +6431,7 @@ WL1271 WIRELESS DRIVER | |||
6431 | M: Luciano Coelho <luciano.coelho@nokia.com> | 6431 | M: Luciano Coelho <luciano.coelho@nokia.com> |
6432 | L: linux-wireless@vger.kernel.org | 6432 | L: linux-wireless@vger.kernel.org |
6433 | W: http://wireless.kernel.org | 6433 | W: http://wireless.kernel.org |
6434 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 6434 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git |
6435 | S: Maintained | 6435 | S: Maintained |
6436 | F: drivers/net/wireless/wl12xx/wl1271* | 6436 | F: drivers/net/wireless/wl12xx/wl1271* |
6437 | F: include/linux/wl12xx.h | 6437 | F: include/linux/wl12xx.h |
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 6aa0728fa15d..189a6d1600b2 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c | |||
@@ -213,7 +213,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = { | |||
213 | { | 213 | { |
214 | .name = "wl1271", | 214 | .name = "wl1271", |
215 | .mmc = 3, | 215 | .mmc = 3, |
216 | .wires = 4, | 216 | .caps = MMC_CAP_4_BIT_DATA, |
217 | .gpio_wp = -EINVAL, | 217 | .gpio_wp = -EINVAL, |
218 | .gpio_cd = -EINVAL, | 218 | .gpio_cd = -EINVAL, |
219 | .nonremovable = true, | 219 | .nonremovable = true, |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index a93dc18a45c3..5dbb5361fd51 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -54,8 +54,6 @@ MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); | |||
54 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
55 | MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); | 55 | MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); |
56 | MODULE_FIRMWARE("ar9170.fw"); | 56 | MODULE_FIRMWARE("ar9170.fw"); |
57 | MODULE_FIRMWARE("ar9170-1.fw"); | ||
58 | MODULE_FIRMWARE("ar9170-2.fw"); | ||
59 | 57 | ||
60 | enum ar9170_requirements { | 58 | enum ar9170_requirements { |
61 | AR9170_REQ_FW1_ONLY = 1, | 59 | AR9170_REQ_FW1_ONLY = 1, |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index dd236c3b52f6..cee0191704f5 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -35,7 +35,6 @@ static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||
35 | 35 | ||
36 | struct ath_ani { | 36 | struct ath_ani { |
37 | bool caldone; | 37 | bool caldone; |
38 | int16_t noise_floor; | ||
39 | unsigned int longcal_timer; | 38 | unsigned int longcal_timer; |
40 | unsigned int shortcal_timer; | 39 | unsigned int shortcal_timer; |
41 | unsigned int resetcal_timer; | 40 | unsigned int resetcal_timer; |
@@ -103,14 +102,12 @@ enum ath_cipher { | |||
103 | * @read: Register read | 102 | * @read: Register read |
104 | * @write: Register write | 103 | * @write: Register write |
105 | * @enable_write_buffer: Enable multiple register writes | 104 | * @enable_write_buffer: Enable multiple register writes |
106 | * @disable_write_buffer: Disable multiple register writes | 105 | * @write_flush: flush buffered register writes and disable buffering |
107 | * @write_flush: Flush buffered register writes | ||
108 | */ | 106 | */ |
109 | struct ath_ops { | 107 | struct ath_ops { |
110 | unsigned int (*read)(void *, u32 reg_offset); | 108 | unsigned int (*read)(void *, u32 reg_offset); |
111 | void (*write)(void *, u32 val, u32 reg_offset); | 109 | void (*write)(void *, u32 val, u32 reg_offset); |
112 | void (*enable_write_buffer)(void *); | 110 | void (*enable_write_buffer)(void *); |
113 | void (*disable_write_buffer)(void *); | ||
114 | void (*write_flush) (void *); | 111 | void (*write_flush) (void *); |
115 | }; | 112 | }; |
116 | 113 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 94cc3354f3a6..dad726585637 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/ethtool.h> | 52 | #include <linux/ethtool.h> |
53 | #include <linux/uaccess.h> | 53 | #include <linux/uaccess.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/etherdevice.h> | ||
55 | 56 | ||
56 | #include <net/ieee80211_radiotap.h> | 57 | #include <net/ieee80211_radiotap.h> |
57 | 58 | ||
@@ -509,8 +510,71 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | |||
509 | } | 510 | } |
510 | } | 511 | } |
511 | 512 | ||
513 | struct ath_vif_iter_data { | ||
514 | const u8 *hw_macaddr; | ||
515 | u8 mask[ETH_ALEN]; | ||
516 | u8 active_mac[ETH_ALEN]; /* first active MAC */ | ||
517 | bool need_set_hw_addr; | ||
518 | bool found_active; | ||
519 | bool any_assoc; | ||
520 | }; | ||
521 | |||
522 | static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
523 | { | ||
524 | struct ath_vif_iter_data *iter_data = data; | ||
525 | int i; | ||
526 | |||
527 | if (iter_data->hw_macaddr) | ||
528 | for (i = 0; i < ETH_ALEN; i++) | ||
529 | iter_data->mask[i] &= | ||
530 | ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
531 | |||
532 | if (!iter_data->found_active) { | ||
533 | iter_data->found_active = true; | ||
534 | memcpy(iter_data->active_mac, mac, ETH_ALEN); | ||
535 | } | ||
536 | |||
537 | if (iter_data->need_set_hw_addr && iter_data->hw_macaddr) | ||
538 | if (compare_ether_addr(iter_data->hw_macaddr, mac) == 0) | ||
539 | iter_data->need_set_hw_addr = false; | ||
540 | |||
541 | if (!iter_data->any_assoc) { | ||
542 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
543 | if (avf->assoc) | ||
544 | iter_data->any_assoc = true; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif) | ||
549 | { | ||
550 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
551 | struct ath_vif_iter_data iter_data; | ||
552 | |||
553 | /* | ||
554 | * Use the hardware MAC address as reference, the hardware uses it | ||
555 | * together with the BSSID mask when matching addresses. | ||
556 | */ | ||
557 | iter_data.hw_macaddr = common->macaddr; | ||
558 | memset(&iter_data.mask, 0xff, ETH_ALEN); | ||
559 | iter_data.found_active = false; | ||
560 | iter_data.need_set_hw_addr = true; | ||
561 | |||
562 | if (vif) | ||
563 | ath_vif_iter(&iter_data, vif->addr, vif); | ||
564 | |||
565 | /* Get list of all active MAC addresses */ | ||
566 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter, | ||
567 | &iter_data); | ||
568 | memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); | ||
569 | |||
570 | if (iter_data.need_set_hw_addr && iter_data.found_active) | ||
571 | ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); | ||
572 | |||
573 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
574 | } | ||
575 | |||
512 | static void | 576 | static void |
513 | ath5k_mode_setup(struct ath5k_softc *sc) | 577 | ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif) |
514 | { | 578 | { |
515 | struct ath5k_hw *ah = sc->ah; | 579 | struct ath5k_hw *ah = sc->ah; |
516 | u32 rfilt; | 580 | u32 rfilt; |
@@ -520,7 +584,7 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
520 | ath5k_hw_set_rx_filter(ah, rfilt); | 584 | ath5k_hw_set_rx_filter(ah, rfilt); |
521 | 585 | ||
522 | if (ath5k_hw_hasbssidmask(ah)) | 586 | if (ath5k_hw_hasbssidmask(ah)) |
523 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 587 | ath5k_update_bssid_mask(sc, vif); |
524 | 588 | ||
525 | /* configure operational mode */ | 589 | /* configure operational mode */ |
526 | ath5k_hw_set_opmode(ah, sc->opmode); | 590 | ath5k_hw_set_opmode(ah, sc->opmode); |
@@ -698,13 +762,13 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
698 | flags |= AR5K_TXDESC_RTSENA; | 762 | flags |= AR5K_TXDESC_RTSENA; |
699 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | 763 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; |
700 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, | 764 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, |
701 | sc->vif, pktlen, info)); | 765 | info->control.vif, pktlen, info)); |
702 | } | 766 | } |
703 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 767 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
704 | flags |= AR5K_TXDESC_CTSENA; | 768 | flags |= AR5K_TXDESC_CTSENA; |
705 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | 769 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; |
706 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, | 770 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, |
707 | sc->vif, pktlen, info)); | 771 | info->control.vif, pktlen, info)); |
708 | } | 772 | } |
709 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 773 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
710 | ieee80211_get_hdrlen_from_skb(skb), padsize, | 774 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
@@ -806,10 +870,13 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
806 | list_add_tail(&bf->list, &sc->txbuf); | 870 | list_add_tail(&bf->list, &sc->txbuf); |
807 | } | 871 | } |
808 | 872 | ||
809 | /* beacon buffer */ | 873 | /* beacon buffers */ |
810 | bf->desc = ds; | 874 | INIT_LIST_HEAD(&sc->bcbuf); |
811 | bf->daddr = da; | 875 | for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) { |
812 | sc->bbuf = bf; | 876 | bf->desc = ds; |
877 | bf->daddr = da; | ||
878 | list_add_tail(&bf->list, &sc->bcbuf); | ||
879 | } | ||
813 | 880 | ||
814 | return 0; | 881 | return 0; |
815 | err_free: | 882 | err_free: |
@@ -824,11 +891,12 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
824 | { | 891 | { |
825 | struct ath5k_buf *bf; | 892 | struct ath5k_buf *bf; |
826 | 893 | ||
827 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
828 | list_for_each_entry(bf, &sc->txbuf, list) | 894 | list_for_each_entry(bf, &sc->txbuf, list) |
829 | ath5k_txbuf_free_skb(sc, bf); | 895 | ath5k_txbuf_free_skb(sc, bf); |
830 | list_for_each_entry(bf, &sc->rxbuf, list) | 896 | list_for_each_entry(bf, &sc->rxbuf, list) |
831 | ath5k_rxbuf_free_skb(sc, bf); | 897 | ath5k_rxbuf_free_skb(sc, bf); |
898 | list_for_each_entry(bf, &sc->bcbuf, list) | ||
899 | ath5k_txbuf_free_skb(sc, bf); | ||
832 | 900 | ||
833 | /* Free memory associated with all descriptors */ | 901 | /* Free memory associated with all descriptors */ |
834 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | 902 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); |
@@ -837,7 +905,6 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
837 | 905 | ||
838 | kfree(sc->bufptr); | 906 | kfree(sc->bufptr); |
839 | sc->bufptr = NULL; | 907 | sc->bufptr = NULL; |
840 | sc->bbuf = NULL; | ||
841 | } | 908 | } |
842 | 909 | ||
843 | 910 | ||
@@ -1083,7 +1150,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1083 | spin_unlock_bh(&sc->rxbuflock); | 1150 | spin_unlock_bh(&sc->rxbuflock); |
1084 | 1151 | ||
1085 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ | 1152 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ |
1086 | ath5k_mode_setup(sc); /* set filters, etc. */ | 1153 | ath5k_mode_setup(sc, NULL); /* set filters, etc. */ |
1087 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | 1154 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ |
1088 | 1155 | ||
1089 | return 0; | 1156 | return 0; |
@@ -1366,6 +1433,7 @@ static bool | |||
1366 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | 1433 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) |
1367 | { | 1434 | { |
1368 | sc->stats.rx_all_count++; | 1435 | sc->stats.rx_all_count++; |
1436 | sc->stats.rx_bytes_count += rs->rs_datalen; | ||
1369 | 1437 | ||
1370 | if (unlikely(rs->rs_status)) { | 1438 | if (unlikely(rs->rs_status)) { |
1371 | if (rs->rs_status & AR5K_RXERR_CRC) | 1439 | if (rs->rs_status & AR5K_RXERR_CRC) |
@@ -1544,6 +1612,7 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1544 | int i; | 1612 | int i; |
1545 | 1613 | ||
1546 | sc->stats.tx_all_count++; | 1614 | sc->stats.tx_all_count++; |
1615 | sc->stats.tx_bytes_count += skb->len; | ||
1547 | info = IEEE80211_SKB_CB(skb); | 1616 | info = IEEE80211_SKB_CB(skb); |
1548 | 1617 | ||
1549 | ieee80211_tx_info_clear_status(info); | 1618 | ieee80211_tx_info_clear_status(info); |
@@ -1642,7 +1711,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1642 | } | 1711 | } |
1643 | } | 1712 | } |
1644 | spin_unlock(&txq->lock); | 1713 | spin_unlock(&txq->lock); |
1645 | if (txq->txq_len < ATH5K_TXQ_LEN_LOW) | 1714 | if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4) |
1646 | ieee80211_wake_queue(sc->hw, txq->qnum); | 1715 | ieee80211_wake_queue(sc->hw, txq->qnum); |
1647 | } | 1716 | } |
1648 | 1717 | ||
@@ -1750,6 +1819,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1750 | { | 1819 | { |
1751 | int ret; | 1820 | int ret; |
1752 | struct ath5k_softc *sc = hw->priv; | 1821 | struct ath5k_softc *sc = hw->priv; |
1822 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
1753 | struct sk_buff *skb; | 1823 | struct sk_buff *skb; |
1754 | 1824 | ||
1755 | if (WARN_ON(!vif)) { | 1825 | if (WARN_ON(!vif)) { |
@@ -1766,11 +1836,11 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1766 | 1836 | ||
1767 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | 1837 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); |
1768 | 1838 | ||
1769 | ath5k_txbuf_free_skb(sc, sc->bbuf); | 1839 | ath5k_txbuf_free_skb(sc, avf->bbuf); |
1770 | sc->bbuf->skb = skb; | 1840 | avf->bbuf->skb = skb; |
1771 | ret = ath5k_beacon_setup(sc, sc->bbuf); | 1841 | ret = ath5k_beacon_setup(sc, avf->bbuf); |
1772 | if (ret) | 1842 | if (ret) |
1773 | sc->bbuf->skb = NULL; | 1843 | avf->bbuf->skb = NULL; |
1774 | out: | 1844 | out: |
1775 | return ret; | 1845 | return ret; |
1776 | } | 1846 | } |
@@ -1786,16 +1856,14 @@ out: | |||
1786 | static void | 1856 | static void |
1787 | ath5k_beacon_send(struct ath5k_softc *sc) | 1857 | ath5k_beacon_send(struct ath5k_softc *sc) |
1788 | { | 1858 | { |
1789 | struct ath5k_buf *bf = sc->bbuf; | ||
1790 | struct ath5k_hw *ah = sc->ah; | 1859 | struct ath5k_hw *ah = sc->ah; |
1860 | struct ieee80211_vif *vif; | ||
1861 | struct ath5k_vif *avf; | ||
1862 | struct ath5k_buf *bf; | ||
1791 | struct sk_buff *skb; | 1863 | struct sk_buff *skb; |
1792 | 1864 | ||
1793 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); | 1865 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); |
1794 | 1866 | ||
1795 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION)) { | ||
1796 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | ||
1797 | return; | ||
1798 | } | ||
1799 | /* | 1867 | /* |
1800 | * Check if the previous beacon has gone out. If | 1868 | * Check if the previous beacon has gone out. If |
1801 | * not, don't don't try to post another: skip this | 1869 | * not, don't don't try to post another: skip this |
@@ -1824,6 +1892,28 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
1824 | sc->bmisscount = 0; | 1892 | sc->bmisscount = 0; |
1825 | } | 1893 | } |
1826 | 1894 | ||
1895 | if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) { | ||
1896 | u64 tsf = ath5k_hw_get_tsf64(ah); | ||
1897 | u32 tsftu = TSF_TO_TU(tsf); | ||
1898 | int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval; | ||
1899 | vif = sc->bslot[(slot + 1) % ATH_BCBUF]; | ||
1900 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | ||
1901 | "tsf %llx tsftu %x intval %u slot %u vif %p\n", | ||
1902 | (unsigned long long)tsf, tsftu, sc->bintval, slot, vif); | ||
1903 | } else /* only one interface */ | ||
1904 | vif = sc->bslot[0]; | ||
1905 | |||
1906 | if (!vif) | ||
1907 | return; | ||
1908 | |||
1909 | avf = (void *)vif->drv_priv; | ||
1910 | bf = avf->bbuf; | ||
1911 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || | ||
1912 | sc->opmode == NL80211_IFTYPE_MONITOR)) { | ||
1913 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | ||
1914 | return; | ||
1915 | } | ||
1916 | |||
1827 | /* | 1917 | /* |
1828 | * Stop any current dma and put the new frame on the queue. | 1918 | * Stop any current dma and put the new frame on the queue. |
1829 | * This should never fail since we check above that no frames | 1919 | * This should never fail since we check above that no frames |
@@ -1836,17 +1926,17 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
1836 | 1926 | ||
1837 | /* refresh the beacon for AP mode */ | 1927 | /* refresh the beacon for AP mode */ |
1838 | if (sc->opmode == NL80211_IFTYPE_AP) | 1928 | if (sc->opmode == NL80211_IFTYPE_AP) |
1839 | ath5k_beacon_update(sc->hw, sc->vif); | 1929 | ath5k_beacon_update(sc->hw, vif); |
1840 | 1930 | ||
1841 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); | 1931 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); |
1842 | ath5k_hw_start_tx_dma(ah, sc->bhalq); | 1932 | ath5k_hw_start_tx_dma(ah, sc->bhalq); |
1843 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", | 1933 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", |
1844 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); | 1934 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); |
1845 | 1935 | ||
1846 | skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); | 1936 | skb = ieee80211_get_buffered_bc(sc->hw, vif); |
1847 | while (skb) { | 1937 | while (skb) { |
1848 | ath5k_tx_queue(sc->hw, skb, sc->cabq); | 1938 | ath5k_tx_queue(sc->hw, skb, sc->cabq); |
1849 | skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); | 1939 | skb = ieee80211_get_buffered_bc(sc->hw, vif); |
1850 | } | 1940 | } |
1851 | 1941 | ||
1852 | sc->bsent++; | 1942 | sc->bsent++; |
@@ -1876,6 +1966,12 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
1876 | u64 hw_tsf; | 1966 | u64 hw_tsf; |
1877 | 1967 | ||
1878 | intval = sc->bintval & AR5K_BEACON_PERIOD; | 1968 | intval = sc->bintval & AR5K_BEACON_PERIOD; |
1969 | if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) { | ||
1970 | intval /= ATH_BCBUF; /* staggered multi-bss beacons */ | ||
1971 | if (intval < 15) | ||
1972 | ATH5K_WARN(sc, "intval %u is too low, min 15\n", | ||
1973 | intval); | ||
1974 | } | ||
1879 | if (WARN_ON(!intval)) | 1975 | if (WARN_ON(!intval)) |
1880 | return; | 1976 | return; |
1881 | 1977 | ||
@@ -2323,6 +2419,10 @@ ath5k_init(struct ath5k_softc *sc) | |||
2323 | ath_hw_keyreset(common, (u16) i); | 2419 | ath_hw_keyreset(common, (u16) i); |
2324 | 2420 | ||
2325 | ath5k_hw_set_ack_bitrate_high(ah, true); | 2421 | ath5k_hw_set_ack_bitrate_high(ah, true); |
2422 | |||
2423 | for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) | ||
2424 | sc->bslot[i] = NULL; | ||
2425 | |||
2326 | ret = 0; | 2426 | ret = 0; |
2327 | done: | 2427 | done: |
2328 | mmiowb(); | 2428 | mmiowb(); |
@@ -2382,7 +2482,6 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2382 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2482 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2383 | "putting device to sleep\n"); | 2483 | "putting device to sleep\n"); |
2384 | } | 2484 | } |
2385 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
2386 | 2485 | ||
2387 | mmiowb(); | 2486 | mmiowb(); |
2388 | mutex_unlock(&sc->lock); | 2487 | mutex_unlock(&sc->lock); |
@@ -2587,9 +2686,9 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
2587 | } | 2686 | } |
2588 | 2687 | ||
2589 | SET_IEEE80211_PERM_ADDR(hw, mac); | 2688 | SET_IEEE80211_PERM_ADDR(hw, mac); |
2689 | memcpy(&sc->lladdr, mac, ETH_ALEN); | ||
2590 | /* All MAC address bits matter for ACKs */ | 2690 | /* All MAC address bits matter for ACKs */ |
2591 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); | 2691 | ath5k_update_bssid_mask(sc, NULL); |
2592 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
2593 | 2692 | ||
2594 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | 2693 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
2595 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); | 2694 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); |
@@ -2687,31 +2786,91 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2687 | { | 2786 | { |
2688 | struct ath5k_softc *sc = hw->priv; | 2787 | struct ath5k_softc *sc = hw->priv; |
2689 | int ret; | 2788 | int ret; |
2789 | struct ath5k_hw *ah = sc->ah; | ||
2790 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
2690 | 2791 | ||
2691 | mutex_lock(&sc->lock); | 2792 | mutex_lock(&sc->lock); |
2692 | if (sc->vif) { | 2793 | |
2693 | ret = 0; | 2794 | if ((vif->type == NL80211_IFTYPE_AP || |
2795 | vif->type == NL80211_IFTYPE_ADHOC) | ||
2796 | && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { | ||
2797 | ret = -ELNRNG; | ||
2694 | goto end; | 2798 | goto end; |
2695 | } | 2799 | } |
2696 | 2800 | ||
2697 | sc->vif = vif; | 2801 | /* Don't allow other interfaces if one ad-hoc is configured. |
2802 | * TODO: Fix the problems with ad-hoc and multiple other interfaces. | ||
2803 | * We would need to operate the HW in ad-hoc mode to allow TSF updates | ||
2804 | * for the IBSS, but this breaks with additional AP or STA interfaces | ||
2805 | * at the moment. */ | ||
2806 | if (sc->num_adhoc_vifs || | ||
2807 | (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | ||
2808 | ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); | ||
2809 | ret = -ELNRNG; | ||
2810 | goto end; | ||
2811 | } | ||
2698 | 2812 | ||
2699 | switch (vif->type) { | 2813 | switch (vif->type) { |
2700 | case NL80211_IFTYPE_AP: | 2814 | case NL80211_IFTYPE_AP: |
2701 | case NL80211_IFTYPE_STATION: | 2815 | case NL80211_IFTYPE_STATION: |
2702 | case NL80211_IFTYPE_ADHOC: | 2816 | case NL80211_IFTYPE_ADHOC: |
2703 | case NL80211_IFTYPE_MESH_POINT: | 2817 | case NL80211_IFTYPE_MESH_POINT: |
2704 | sc->opmode = vif->type; | 2818 | avf->opmode = vif->type; |
2705 | break; | 2819 | break; |
2706 | default: | 2820 | default: |
2707 | ret = -EOPNOTSUPP; | 2821 | ret = -EOPNOTSUPP; |
2708 | goto end; | 2822 | goto end; |
2709 | } | 2823 | } |
2710 | 2824 | ||
2711 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | 2825 | sc->nvifs++; |
2826 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); | ||
2712 | 2827 | ||
2828 | /* Assign the vap/adhoc to a beacon xmit slot. */ | ||
2829 | if ((avf->opmode == NL80211_IFTYPE_AP) || | ||
2830 | (avf->opmode == NL80211_IFTYPE_ADHOC)) { | ||
2831 | int slot; | ||
2832 | |||
2833 | WARN_ON(list_empty(&sc->bcbuf)); | ||
2834 | avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, | ||
2835 | list); | ||
2836 | list_del(&avf->bbuf->list); | ||
2837 | |||
2838 | avf->bslot = 0; | ||
2839 | for (slot = 0; slot < ATH_BCBUF; slot++) { | ||
2840 | if (!sc->bslot[slot]) { | ||
2841 | avf->bslot = slot; | ||
2842 | break; | ||
2843 | } | ||
2844 | } | ||
2845 | BUG_ON(sc->bslot[avf->bslot] != NULL); | ||
2846 | sc->bslot[avf->bslot] = vif; | ||
2847 | if (avf->opmode == NL80211_IFTYPE_AP) | ||
2848 | sc->num_ap_vifs++; | ||
2849 | else | ||
2850 | sc->num_adhoc_vifs++; | ||
2851 | } | ||
2852 | |||
2853 | /* Set combined mode - when APs are configured, operate in AP mode. | ||
2854 | * Otherwise use the mode of the new interface. This can currently | ||
2855 | * only deal with combinations of APs and STAs. Only one ad-hoc | ||
2856 | * interfaces is allowed above. | ||
2857 | */ | ||
2858 | if (sc->num_ap_vifs) | ||
2859 | sc->opmode = NL80211_IFTYPE_AP; | ||
2860 | else | ||
2861 | sc->opmode = vif->type; | ||
2862 | |||
2863 | ath5k_hw_set_opmode(ah, sc->opmode); | ||
2864 | |||
2865 | /* Any MAC address is fine, all others are included through the | ||
2866 | * filter. | ||
2867 | */ | ||
2868 | memcpy(&sc->lladdr, vif->addr, ETH_ALEN); | ||
2713 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2869 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2714 | ath5k_mode_setup(sc); | 2870 | |
2871 | memcpy(&avf->lladdr, vif->addr, ETH_ALEN); | ||
2872 | |||
2873 | ath5k_mode_setup(sc, vif); | ||
2715 | 2874 | ||
2716 | ret = 0; | 2875 | ret = 0; |
2717 | end: | 2876 | end: |
@@ -2724,15 +2883,29 @@ ath5k_remove_interface(struct ieee80211_hw *hw, | |||
2724 | struct ieee80211_vif *vif) | 2883 | struct ieee80211_vif *vif) |
2725 | { | 2884 | { |
2726 | struct ath5k_softc *sc = hw->priv; | 2885 | struct ath5k_softc *sc = hw->priv; |
2727 | u8 mac[ETH_ALEN] = {}; | 2886 | struct ath5k_vif *avf = (void *)vif->drv_priv; |
2887 | unsigned int i; | ||
2728 | 2888 | ||
2729 | mutex_lock(&sc->lock); | 2889 | mutex_lock(&sc->lock); |
2730 | if (sc->vif != vif) | 2890 | sc->nvifs--; |
2731 | goto end; | 2891 | |
2892 | if (avf->bbuf) { | ||
2893 | ath5k_txbuf_free_skb(sc, avf->bbuf); | ||
2894 | list_add_tail(&avf->bbuf->list, &sc->bcbuf); | ||
2895 | for (i = 0; i < ATH_BCBUF; i++) { | ||
2896 | if (sc->bslot[i] == vif) { | ||
2897 | sc->bslot[i] = NULL; | ||
2898 | break; | ||
2899 | } | ||
2900 | } | ||
2901 | avf->bbuf = NULL; | ||
2902 | } | ||
2903 | if (avf->opmode == NL80211_IFTYPE_AP) | ||
2904 | sc->num_ap_vifs--; | ||
2905 | else if (avf->opmode == NL80211_IFTYPE_ADHOC) | ||
2906 | sc->num_adhoc_vifs--; | ||
2732 | 2907 | ||
2733 | ath5k_hw_set_lladdr(sc->ah, mac); | 2908 | ath5k_update_bssid_mask(sc, NULL); |
2734 | sc->vif = NULL; | ||
2735 | end: | ||
2736 | mutex_unlock(&sc->lock); | 2909 | mutex_unlock(&sc->lock); |
2737 | } | 2910 | } |
2738 | 2911 | ||
@@ -2815,6 +2988,19 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | |||
2815 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | 2988 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; |
2816 | } | 2989 | } |
2817 | 2990 | ||
2991 | static bool ath_any_vif_assoc(struct ath5k_softc *sc) | ||
2992 | { | ||
2993 | struct ath_vif_iter_data iter_data; | ||
2994 | iter_data.hw_macaddr = NULL; | ||
2995 | iter_data.any_assoc = false; | ||
2996 | iter_data.need_set_hw_addr = false; | ||
2997 | iter_data.found_active = true; | ||
2998 | |||
2999 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter, | ||
3000 | &iter_data); | ||
3001 | return iter_data.any_assoc; | ||
3002 | } | ||
3003 | |||
2818 | #define SUPPORTED_FIF_FLAGS \ | 3004 | #define SUPPORTED_FIF_FLAGS \ |
2819 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | 3005 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ |
2820 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | 3006 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ |
@@ -2885,7 +3071,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2885 | 3071 | ||
2886 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | 3072 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons |
2887 | * and probes for any BSSID */ | 3073 | * and probes for any BSSID */ |
2888 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) | 3074 | if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) |
2889 | rfilt |= AR5K_RX_FILTER_BEACON; | 3075 | rfilt |= AR5K_RX_FILTER_BEACON; |
2890 | 3076 | ||
2891 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | 3077 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not |
@@ -3070,14 +3256,13 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3070 | struct ieee80211_bss_conf *bss_conf, | 3256 | struct ieee80211_bss_conf *bss_conf, |
3071 | u32 changes) | 3257 | u32 changes) |
3072 | { | 3258 | { |
3259 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
3073 | struct ath5k_softc *sc = hw->priv; | 3260 | struct ath5k_softc *sc = hw->priv; |
3074 | struct ath5k_hw *ah = sc->ah; | 3261 | struct ath5k_hw *ah = sc->ah; |
3075 | struct ath_common *common = ath5k_hw_common(ah); | 3262 | struct ath_common *common = ath5k_hw_common(ah); |
3076 | unsigned long flags; | 3263 | unsigned long flags; |
3077 | 3264 | ||
3078 | mutex_lock(&sc->lock); | 3265 | mutex_lock(&sc->lock); |
3079 | if (WARN_ON(sc->vif != vif)) | ||
3080 | goto unlock; | ||
3081 | 3266 | ||
3082 | if (changes & BSS_CHANGED_BSSID) { | 3267 | if (changes & BSS_CHANGED_BSSID) { |
3083 | /* Cache for later use during resets */ | 3268 | /* Cache for later use during resets */ |
@@ -3091,7 +3276,12 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3091 | sc->bintval = bss_conf->beacon_int; | 3276 | sc->bintval = bss_conf->beacon_int; |
3092 | 3277 | ||
3093 | if (changes & BSS_CHANGED_ASSOC) { | 3278 | if (changes & BSS_CHANGED_ASSOC) { |
3094 | sc->assoc = bss_conf->assoc; | 3279 | avf->assoc = bss_conf->assoc; |
3280 | if (bss_conf->assoc) | ||
3281 | sc->assoc = bss_conf->assoc; | ||
3282 | else | ||
3283 | sc->assoc = ath_any_vif_assoc(sc); | ||
3284 | |||
3095 | if (sc->opmode == NL80211_IFTYPE_STATION) | 3285 | if (sc->opmode == NL80211_IFTYPE_STATION) |
3096 | set_beacon_filter(hw, sc->assoc); | 3286 | set_beacon_filter(hw, sc->assoc); |
3097 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3287 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
@@ -3119,7 +3309,6 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3119 | BSS_CHANGED_BEACON_INT)) | 3309 | BSS_CHANGED_BEACON_INT)) |
3120 | ath5k_beacon_config(sc); | 3310 | ath5k_beacon_config(sc); |
3121 | 3311 | ||
3122 | unlock: | ||
3123 | mutex_unlock(&sc->lock); | 3312 | mutex_unlock(&sc->lock); |
3124 | } | 3313 | } |
3125 | 3314 | ||
@@ -3394,6 +3583,8 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
3394 | hw->max_rate_tries = 11; | 3583 | hw->max_rate_tries = 11; |
3395 | } | 3584 | } |
3396 | 3585 | ||
3586 | hw->vif_data_size = sizeof(struct ath5k_vif); | ||
3587 | |||
3397 | /* Finish private driver data initialization */ | 3588 | /* Finish private driver data initialization */ |
3398 | ret = ath5k_attach(pdev, hw); | 3589 | ret = ath5k_attach(pdev, hw); |
3399 | if (ret) | 3590 | if (ret) |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 7f9d0d3018e8..9a79773cdc2a 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -58,8 +58,7 @@ | |||
58 | 58 | ||
59 | #define ATH_RXBUF 40 /* number of RX buffers */ | 59 | #define ATH_RXBUF 40 /* number of RX buffers */ |
60 | #define ATH_TXBUF 200 /* number of TX buffers */ | 60 | #define ATH_TXBUF 200 /* number of TX buffers */ |
61 | #define ATH_BCBUF 1 /* number of beacon buffers */ | 61 | #define ATH_BCBUF 4 /* number of beacon buffers */ |
62 | |||
63 | #define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ | 62 | #define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ |
64 | #define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ | 63 | #define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ |
65 | 64 | ||
@@ -122,6 +121,13 @@ struct ath5k_statistics { | |||
122 | /* frame errors */ | 121 | /* frame errors */ |
123 | unsigned int rx_all_count; /* all RX frames, including errors */ | 122 | unsigned int rx_all_count; /* all RX frames, including errors */ |
124 | unsigned int tx_all_count; /* all TX frames, including errors */ | 123 | unsigned int tx_all_count; /* all TX frames, including errors */ |
124 | unsigned int rx_bytes_count; /* all RX bytes, including errored pks | ||
125 | * and the MAC headers for each packet | ||
126 | */ | ||
127 | unsigned int tx_bytes_count; /* all TX bytes, including errored pkts | ||
128 | * and the MAC headers and padding for | ||
129 | * each packet. | ||
130 | */ | ||
125 | unsigned int rxerr_crc; | 131 | unsigned int rxerr_crc; |
126 | unsigned int rxerr_phy; | 132 | unsigned int rxerr_phy; |
127 | unsigned int rxerr_phy_code[32]; | 133 | unsigned int rxerr_phy_code[32]; |
@@ -152,6 +158,14 @@ struct ath5k_statistics { | |||
152 | #define ATH_CHAN_MAX (14+14+14+252+20) | 158 | #define ATH_CHAN_MAX (14+14+14+252+20) |
153 | #endif | 159 | #endif |
154 | 160 | ||
161 | struct ath5k_vif { | ||
162 | bool assoc; /* are we associated or not */ | ||
163 | enum nl80211_iftype opmode; | ||
164 | int bslot; | ||
165 | struct ath5k_buf *bbuf; /* beacon buffer */ | ||
166 | u8 lladdr[ETH_ALEN]; | ||
167 | }; | ||
168 | |||
155 | /* Software Carrier, keeps track of the driver state | 169 | /* Software Carrier, keeps track of the driver state |
156 | * associated with an instance of a device */ | 170 | * associated with an instance of a device */ |
157 | struct ath5k_softc { | 171 | struct ath5k_softc { |
@@ -188,10 +202,11 @@ struct ath5k_softc { | |||
188 | unsigned int curmode; /* current phy mode */ | 202 | unsigned int curmode; /* current phy mode */ |
189 | struct ieee80211_channel *curchan; /* current h/w channel */ | 203 | struct ieee80211_channel *curchan; /* current h/w channel */ |
190 | 204 | ||
191 | struct ieee80211_vif *vif; | 205 | u16 nvifs; |
192 | 206 | ||
193 | enum ath5k_int imask; /* interrupt mask copy */ | 207 | enum ath5k_int imask; /* interrupt mask copy */ |
194 | 208 | ||
209 | u8 lladdr[ETH_ALEN]; | ||
195 | u8 bssidmask[ETH_ALEN]; | 210 | u8 bssidmask[ETH_ALEN]; |
196 | 211 | ||
197 | unsigned int led_pin, /* GPIO pin for driving LED */ | 212 | unsigned int led_pin, /* GPIO pin for driving LED */ |
@@ -219,7 +234,10 @@ struct ath5k_softc { | |||
219 | 234 | ||
220 | spinlock_t block; /* protects beacon */ | 235 | spinlock_t block; /* protects beacon */ |
221 | struct tasklet_struct beacontq; /* beacon intr tasklet */ | 236 | struct tasklet_struct beacontq; /* beacon intr tasklet */ |
222 | struct ath5k_buf *bbuf; /* beacon buffer */ | 237 | struct list_head bcbuf; /* beacon buffer */ |
238 | struct ieee80211_vif *bslot[ATH_BCBUF]; | ||
239 | u16 num_ap_vifs; | ||
240 | u16 num_adhoc_vifs; | ||
223 | unsigned int bhalq, /* SW q for outgoing beacons */ | 241 | unsigned int bhalq, /* SW q for outgoing beacons */ |
224 | bmisscount, /* missed beacon transmits */ | 242 | bmisscount, /* missed beacon transmits */ |
225 | bintval, /* beacon interval in TU */ | 243 | bintval, /* beacon interval in TU */ |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0f06e8490314..c2d549f871f9 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -587,6 +587,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | |||
587 | st->rxerr_jumbo*100/st->rx_all_count : 0); | 587 | st->rxerr_jumbo*100/st->rx_all_count : 0); |
588 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", | 588 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", |
589 | st->rx_all_count); | 589 | st->rx_all_count); |
590 | len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n", | ||
591 | st->rx_bytes_count); | ||
590 | 592 | ||
591 | len += snprintf(buf+len, sizeof(buf)-len, | 593 | len += snprintf(buf+len, sizeof(buf)-len, |
592 | "\nTX\n---------------------\n"); | 594 | "\nTX\n---------------------\n"); |
@@ -604,6 +606,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | |||
604 | st->txerr_filt*100/st->tx_all_count : 0); | 606 | st->txerr_filt*100/st->tx_all_count : 0); |
605 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", | 607 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", |
606 | st->tx_all_count); | 608 | st->tx_all_count); |
609 | len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n", | ||
610 | st->tx_bytes_count); | ||
607 | 611 | ||
608 | if (len > sizeof(buf)) | 612 | if (len > sizeof(buf)) |
609 | len = sizeof(buf); | 613 | len = sizeof(buf); |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 58912cd762d9..5b179d01f97d 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -167,7 +167,7 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | |||
167 | * ieee80211_duration() for a brief description of | 167 | * ieee80211_duration() for a brief description of |
168 | * what rate we should choose to TX ACKs. */ | 168 | * what rate we should choose to TX ACKs. */ |
169 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | 169 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, |
170 | sc->vif, 10, rate)); | 170 | NULL, 10, rate)); |
171 | 171 | ||
172 | ath5k_hw_reg_write(ah, tx_time, reg); | 172 | ath5k_hw_reg_write(ah, tx_time, reg); |
173 | 173 | ||
@@ -1060,7 +1060,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1060 | * XXX: rethink this after new mode changes to | 1060 | * XXX: rethink this after new mode changes to |
1061 | * mac80211 are integrated */ | 1061 | * mac80211 are integrated */ |
1062 | if (ah->ah_version == AR5K_AR5212 && | 1062 | if (ah->ah_version == AR5K_AR5212 && |
1063 | ah->ah_sc->vif != NULL) | 1063 | ah->ah_sc->nvifs) |
1064 | ath5k_hw_write_rate_duration(ah, mode); | 1064 | ath5k_hw_write_rate_duration(ah, mode); |
1065 | 1065 | ||
1066 | /* | 1066 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 0496f965314f..f2a907b4acb8 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -103,31 +103,9 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
103 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | 103 | #define ATH9K_ANI_CCK_DEF_LEVEL \ |
104 | 2 /* default level - matches the INI settings */ | 104 | 2 /* default level - matches the INI settings */ |
105 | 105 | ||
106 | /* Private to ani.c */ | 106 | static bool use_new_ani(struct ath_hw *ah) |
107 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | ||
108 | { | ||
109 | ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); | ||
110 | } | ||
111 | |||
112 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
113 | struct ath9k_channel *chan) | ||
114 | { | 107 | { |
115 | int i; | 108 | return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani; |
116 | |||
117 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | ||
118 | if (ah->ani[i].c && | ||
119 | ah->ani[i].c->channel == chan->channel) | ||
120 | return i; | ||
121 | if (ah->ani[i].c == NULL) { | ||
122 | ah->ani[i].c = chan; | ||
123 | return i; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, | ||
128 | "No more channel states left. Using channel 0\n"); | ||
129 | |||
130 | return 0; | ||
131 | } | 109 | } |
132 | 110 | ||
133 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 111 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, |
@@ -140,82 +118,34 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
140 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 118 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); |
141 | } | 119 | } |
142 | 120 | ||
143 | static void ath9k_ani_restart_old(struct ath_hw *ah) | 121 | static void ath9k_ani_restart(struct ath_hw *ah) |
144 | { | 122 | { |
145 | struct ar5416AniState *aniState; | 123 | struct ar5416AniState *aniState; |
146 | struct ath_common *common = ath9k_hw_common(ah); | 124 | struct ath_common *common = ath9k_hw_common(ah); |
125 | u32 ofdm_base = 0, cck_base = 0; | ||
147 | 126 | ||
148 | if (!DO_ANI(ah)) | 127 | if (!DO_ANI(ah)) |
149 | return; | 128 | return; |
150 | 129 | ||
151 | aniState = ah->curani; | 130 | aniState = &ah->curchan->ani; |
152 | aniState->listenTime = 0; | 131 | aniState->listenTime = 0; |
153 | 132 | ||
154 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | 133 | if (!use_new_ani(ah)) { |
155 | aniState->ofdmPhyErrBase = 0; | 134 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; |
156 | ath_print(common, ATH_DBG_ANI, | 135 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; |
157 | "OFDM Trigger is too high for hw counters\n"); | ||
158 | } else { | ||
159 | aniState->ofdmPhyErrBase = | ||
160 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | ||
161 | } | 136 | } |
162 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | ||
163 | aniState->cckPhyErrBase = 0; | ||
164 | ath_print(common, ATH_DBG_ANI, | ||
165 | "CCK Trigger is too high for hw counters\n"); | ||
166 | } else { | ||
167 | aniState->cckPhyErrBase = | ||
168 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
169 | } | ||
170 | ath_print(common, ATH_DBG_ANI, | ||
171 | "Writing ofdmbase=%u cckbase=%u\n", | ||
172 | aniState->ofdmPhyErrBase, | ||
173 | aniState->cckPhyErrBase); | ||
174 | |||
175 | ENABLE_REGWRITE_BUFFER(ah); | ||
176 | |||
177 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
178 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
179 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
180 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
181 | |||
182 | REGWRITE_BUFFER_FLUSH(ah); | ||
183 | DISABLE_REGWRITE_BUFFER(ah); | ||
184 | |||
185 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
186 | |||
187 | aniState->ofdmPhyErrCount = 0; | ||
188 | aniState->cckPhyErrCount = 0; | ||
189 | } | ||
190 | |||
191 | static void ath9k_ani_restart_new(struct ath_hw *ah) | ||
192 | { | ||
193 | struct ar5416AniState *aniState; | ||
194 | struct ath_common *common = ath9k_hw_common(ah); | ||
195 | |||
196 | if (!DO_ANI(ah)) | ||
197 | return; | ||
198 | |||
199 | aniState = ah->curani; | ||
200 | aniState->listenTime = 0; | ||
201 | |||
202 | aniState->ofdmPhyErrBase = 0; | ||
203 | aniState->cckPhyErrBase = 0; | ||
204 | 137 | ||
205 | ath_print(common, ATH_DBG_ANI, | 138 | ath_print(common, ATH_DBG_ANI, |
206 | "Writing ofdmbase=%08x cckbase=%08x\n", | 139 | "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base); |
207 | aniState->ofdmPhyErrBase, | ||
208 | aniState->cckPhyErrBase); | ||
209 | 140 | ||
210 | ENABLE_REGWRITE_BUFFER(ah); | 141 | ENABLE_REGWRITE_BUFFER(ah); |
211 | 142 | ||
212 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | 143 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
213 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | 144 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
214 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 145 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
215 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 146 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
216 | 147 | ||
217 | REGWRITE_BUFFER_FLUSH(ah); | 148 | REGWRITE_BUFFER_FLUSH(ah); |
218 | DISABLE_REGWRITE_BUFFER(ah); | ||
219 | 149 | ||
220 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 150 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
221 | 151 | ||
@@ -229,10 +159,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | |||
229 | struct ar5416AniState *aniState; | 159 | struct ar5416AniState *aniState; |
230 | int32_t rssi; | 160 | int32_t rssi; |
231 | 161 | ||
232 | if (!DO_ANI(ah)) | 162 | aniState = &ah->curchan->ani; |
233 | return; | ||
234 | |||
235 | aniState = ah->curani; | ||
236 | 163 | ||
237 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 164 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
238 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 165 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
@@ -301,10 +228,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
301 | struct ar5416AniState *aniState; | 228 | struct ar5416AniState *aniState; |
302 | int32_t rssi; | 229 | int32_t rssi; |
303 | 230 | ||
304 | if (!DO_ANI(ah)) | 231 | aniState = &ah->curchan->ani; |
305 | return; | ||
306 | |||
307 | aniState = ah->curani; | ||
308 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 232 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
309 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 233 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
310 | aniState->noiseImmunityLevel + 1)) { | 234 | aniState->noiseImmunityLevel + 1)) { |
@@ -336,7 +260,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
336 | /* Adjust the OFDM Noise Immunity Level */ | 260 | /* Adjust the OFDM Noise Immunity Level */ |
337 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | 261 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) |
338 | { | 262 | { |
339 | struct ar5416AniState *aniState = ah->curani; | 263 | struct ar5416AniState *aniState = &ah->curchan->ani; |
340 | struct ath_common *common = ath9k_hw_common(ah); | 264 | struct ath_common *common = ath9k_hw_common(ah); |
341 | const struct ani_ofdm_level_entry *entry_ofdm; | 265 | const struct ani_ofdm_level_entry *entry_ofdm; |
342 | const struct ani_cck_level_entry *entry_cck; | 266 | const struct ani_cck_level_entry *entry_cck; |
@@ -381,14 +305,19 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
381 | } | 305 | } |
382 | } | 306 | } |
383 | 307 | ||
384 | static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | 308 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) |
385 | { | 309 | { |
386 | struct ar5416AniState *aniState; | 310 | struct ar5416AniState *aniState; |
387 | 311 | ||
388 | if (!DO_ANI(ah)) | 312 | if (!DO_ANI(ah)) |
389 | return; | 313 | return; |
390 | 314 | ||
391 | aniState = ah->curani; | 315 | if (!use_new_ani(ah)) { |
316 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | aniState = &ah->curchan->ani; | ||
392 | 321 | ||
393 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | 322 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) |
394 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); | 323 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); |
@@ -399,7 +328,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | |||
399 | */ | 328 | */ |
400 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | 329 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) |
401 | { | 330 | { |
402 | struct ar5416AniState *aniState = ah->curani; | 331 | struct ar5416AniState *aniState = &ah->curchan->ani; |
403 | struct ath_common *common = ath9k_hw_common(ah); | 332 | struct ath_common *common = ath9k_hw_common(ah); |
404 | const struct ani_ofdm_level_entry *entry_ofdm; | 333 | const struct ani_ofdm_level_entry *entry_ofdm; |
405 | const struct ani_cck_level_entry *entry_cck; | 334 | const struct ani_cck_level_entry *entry_cck; |
@@ -438,14 +367,19 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
438 | entry_cck->mrc_cck_on); | 367 | entry_cck->mrc_cck_on); |
439 | } | 368 | } |
440 | 369 | ||
441 | static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) | 370 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) |
442 | { | 371 | { |
443 | struct ar5416AniState *aniState; | 372 | struct ar5416AniState *aniState; |
444 | 373 | ||
445 | if (!DO_ANI(ah)) | 374 | if (!DO_ANI(ah)) |
446 | return; | 375 | return; |
447 | 376 | ||
448 | aniState = ah->curani; | 377 | if (!use_new_ani(ah)) { |
378 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | aniState = &ah->curchan->ani; | ||
449 | 383 | ||
450 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | 384 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) |
451 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | 385 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); |
@@ -456,7 +390,7 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
456 | struct ar5416AniState *aniState; | 390 | struct ar5416AniState *aniState; |
457 | int32_t rssi; | 391 | int32_t rssi; |
458 | 392 | ||
459 | aniState = ah->curani; | 393 | aniState = &ah->curchan->ani; |
460 | 394 | ||
461 | if (ah->opmode == NL80211_IFTYPE_AP) { | 395 | if (ah->opmode == NL80211_IFTYPE_AP) { |
462 | if (aniState->firstepLevel > 0) { | 396 | if (aniState->firstepLevel > 0) { |
@@ -508,11 +442,16 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
508 | * only lower either OFDM or CCK errors per turn | 442 | * only lower either OFDM or CCK errors per turn |
509 | * we lower the other one next time | 443 | * we lower the other one next time |
510 | */ | 444 | */ |
511 | static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | 445 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) |
512 | { | 446 | { |
513 | struct ar5416AniState *aniState; | 447 | struct ar5416AniState *aniState; |
514 | 448 | ||
515 | aniState = ah->curani; | 449 | aniState = &ah->curchan->ani; |
450 | |||
451 | if (!use_new_ani(ah)) { | ||
452 | ath9k_hw_ani_lower_immunity_old(ah); | ||
453 | return; | ||
454 | } | ||
516 | 455 | ||
517 | /* lower OFDM noise immunity */ | 456 | /* lower OFDM noise immunity */ |
518 | if (aniState->ofdmNoiseImmunityLevel > 0 && | 457 | if (aniState->ofdmNoiseImmunityLevel > 0 && |
@@ -544,52 +483,20 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | |||
544 | if (conf_is_ht40(conf)) | 483 | if (conf_is_ht40(conf)) |
545 | return clockrate * 2; | 484 | return clockrate * 2; |
546 | 485 | ||
547 | return clockrate * 2; | 486 | return clockrate; |
548 | } | 487 | } |
549 | 488 | ||
550 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 489 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) |
551 | { | 490 | { |
552 | struct ar5416AniState *aniState; | 491 | int32_t listen_time; |
553 | struct ath_common *common = ath9k_hw_common(ah); | 492 | int32_t clock_rate; |
554 | u32 txFrameCount, rxFrameCount, cycleCount; | ||
555 | int32_t listenTime; | ||
556 | |||
557 | txFrameCount = REG_READ(ah, AR_TFCNT); | ||
558 | rxFrameCount = REG_READ(ah, AR_RFCNT); | ||
559 | cycleCount = REG_READ(ah, AR_CCCNT); | ||
560 | |||
561 | aniState = ah->curani; | ||
562 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | ||
563 | listenTime = 0; | ||
564 | ah->stats.ast_ani_lzero++; | ||
565 | ath_print(common, ATH_DBG_ANI, | ||
566 | "1st call: aniState->cycleCount=%d\n", | ||
567 | aniState->cycleCount); | ||
568 | } else { | ||
569 | int32_t ccdelta = cycleCount - aniState->cycleCount; | ||
570 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | ||
571 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | ||
572 | int32_t clock_rate; | ||
573 | 493 | ||
574 | /* | 494 | ath9k_hw_update_cycle_counters(ah); |
575 | * convert HW counter values to ms using mode | 495 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000; |
576 | * specifix clock rate | 496 | listen_time = ah->listen_time / clock_rate; |
577 | */ | 497 | ah->listen_time = 0; |
578 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; | ||
579 | 498 | ||
580 | listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; | 499 | return listen_time; |
581 | |||
582 | ath_print(common, ATH_DBG_ANI, | ||
583 | "cyclecount=%d, rfcount=%d, " | ||
584 | "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", | ||
585 | ccdelta, rfdelta, tfdelta, listenTime, clock_rate); | ||
586 | } | ||
587 | |||
588 | aniState->cycleCount = cycleCount; | ||
589 | aniState->txFrameCount = txFrameCount; | ||
590 | aniState->rxFrameCount = rxFrameCount; | ||
591 | |||
592 | return listenTime; | ||
593 | } | 500 | } |
594 | 501 | ||
595 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | 502 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) |
@@ -597,16 +504,13 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
597 | struct ar5416AniState *aniState; | 504 | struct ar5416AniState *aniState; |
598 | struct ath9k_channel *chan = ah->curchan; | 505 | struct ath9k_channel *chan = ah->curchan; |
599 | struct ath_common *common = ath9k_hw_common(ah); | 506 | struct ath_common *common = ath9k_hw_common(ah); |
600 | int index; | ||
601 | 507 | ||
602 | if (!DO_ANI(ah)) | 508 | if (!DO_ANI(ah)) |
603 | return; | 509 | return; |
604 | 510 | ||
605 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | 511 | aniState = &ah->curchan->ani; |
606 | aniState = &ah->ani[index]; | ||
607 | ah->curani = aniState; | ||
608 | 512 | ||
609 | if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION | 513 | if (ah->opmode != NL80211_IFTYPE_STATION |
610 | && ah->opmode != NL80211_IFTYPE_ADHOC) { | 514 | && ah->opmode != NL80211_IFTYPE_ADHOC) { |
611 | ath_print(common, ATH_DBG_ANI, | 515 | ath_print(common, ATH_DBG_ANI, |
612 | "Reset ANI state opmode %u\n", ah->opmode); | 516 | "Reset ANI state opmode %u\n", ah->opmode); |
@@ -635,17 +539,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
635 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | | 539 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | |
636 | ATH9K_RX_FILTER_PHYERR); | 540 | ATH9K_RX_FILTER_PHYERR); |
637 | 541 | ||
638 | if (ah->opmode == NL80211_IFTYPE_AP) { | 542 | ath9k_ani_restart(ah); |
639 | ah->curani->ofdmTrigHigh = | ||
640 | ah->config.ofdm_trig_high; | ||
641 | ah->curani->ofdmTrigLow = | ||
642 | ah->config.ofdm_trig_low; | ||
643 | ah->curani->cckTrigHigh = | ||
644 | ah->config.cck_trig_high; | ||
645 | ah->curani->cckTrigLow = | ||
646 | ah->config.cck_trig_low; | ||
647 | } | ||
648 | ath9k_ani_restart_old(ah); | ||
649 | return; | 543 | return; |
650 | } | 544 | } |
651 | 545 | ||
@@ -667,7 +561,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
667 | 561 | ||
668 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | 562 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
669 | ~ATH9K_RX_FILTER_PHYERR); | 563 | ~ATH9K_RX_FILTER_PHYERR); |
670 | ath9k_ani_restart_old(ah); | 564 | ath9k_ani_restart(ah); |
671 | 565 | ||
672 | ENABLE_REGWRITE_BUFFER(ah); | 566 | ENABLE_REGWRITE_BUFFER(ah); |
673 | 567 | ||
@@ -675,7 +569,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
675 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 569 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
676 | 570 | ||
677 | REGWRITE_BUFFER_FLUSH(ah); | 571 | REGWRITE_BUFFER_FLUSH(ah); |
678 | DISABLE_REGWRITE_BUFFER(ah); | ||
679 | } | 572 | } |
680 | 573 | ||
681 | /* | 574 | /* |
@@ -683,15 +576,18 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
683 | * This routine should be called for every hardware reset and for | 576 | * This routine should be called for every hardware reset and for |
684 | * every channel change. | 577 | * every channel change. |
685 | */ | 578 | */ |
686 | static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | 579 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) |
687 | { | 580 | { |
688 | struct ar5416AniState *aniState = ah->curani; | 581 | struct ar5416AniState *aniState = &ah->curchan->ani; |
689 | struct ath9k_channel *chan = ah->curchan; | 582 | struct ath9k_channel *chan = ah->curchan; |
690 | struct ath_common *common = ath9k_hw_common(ah); | 583 | struct ath_common *common = ath9k_hw_common(ah); |
691 | 584 | ||
692 | if (!DO_ANI(ah)) | 585 | if (!DO_ANI(ah)) |
693 | return; | 586 | return; |
694 | 587 | ||
588 | if (!use_new_ani(ah)) | ||
589 | return ath9k_ani_reset_old(ah, is_scanning); | ||
590 | |||
695 | BUG_ON(aniState == NULL); | 591 | BUG_ON(aniState == NULL); |
696 | ah->stats.ast_ani_reset++; | 592 | ah->stats.ast_ani_reset++; |
697 | 593 | ||
@@ -761,7 +657,7 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
761 | * enable phy counters if hw supports or if not, enable phy | 657 | * enable phy counters if hw supports or if not, enable phy |
762 | * interrupts (so we can count each one) | 658 | * interrupts (so we can count each one) |
763 | */ | 659 | */ |
764 | ath9k_ani_restart_new(ah); | 660 | ath9k_ani_restart(ah); |
765 | 661 | ||
766 | ENABLE_REGWRITE_BUFFER(ah); | 662 | ENABLE_REGWRITE_BUFFER(ah); |
767 | 663 | ||
@@ -769,30 +665,30 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
769 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 665 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
770 | 666 | ||
771 | REGWRITE_BUFFER_FLUSH(ah); | 667 | REGWRITE_BUFFER_FLUSH(ah); |
772 | DISABLE_REGWRITE_BUFFER(ah); | ||
773 | } | 668 | } |
774 | 669 | ||
775 | static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | 670 | static void ath9k_hw_ani_read_counters(struct ath_hw *ah) |
776 | struct ath9k_channel *chan) | ||
777 | { | 671 | { |
778 | struct ar5416AniState *aniState; | ||
779 | struct ath_common *common = ath9k_hw_common(ah); | 672 | struct ath_common *common = ath9k_hw_common(ah); |
780 | int32_t listenTime; | 673 | struct ar5416AniState *aniState = &ah->curchan->ani; |
781 | u32 phyCnt1, phyCnt2; | 674 | u32 ofdm_base = 0; |
675 | u32 cck_base = 0; | ||
782 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | 676 | u32 ofdmPhyErrCnt, cckPhyErrCnt; |
783 | 677 | u32 phyCnt1, phyCnt2; | |
784 | if (!DO_ANI(ah)) | 678 | int32_t listenTime; |
785 | return; | ||
786 | |||
787 | aniState = ah->curani; | ||
788 | 679 | ||
789 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 680 | listenTime = ath9k_hw_ani_get_listen_time(ah); |
790 | if (listenTime < 0) { | 681 | if (listenTime < 0) { |
791 | ah->stats.ast_ani_lneg++; | 682 | ah->stats.ast_ani_lneg++; |
792 | ath9k_ani_restart_old(ah); | 683 | ath9k_ani_restart(ah); |
793 | return; | 684 | return; |
794 | } | 685 | } |
795 | 686 | ||
687 | if (!use_new_ani(ah)) { | ||
688 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; | ||
689 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; | ||
690 | } | ||
691 | |||
796 | aniState->listenTime += listenTime; | 692 | aniState->listenTime += listenTime; |
797 | 693 | ||
798 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 694 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
@@ -800,145 +696,54 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | |||
800 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 696 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
801 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 697 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
802 | 698 | ||
803 | if (phyCnt1 < aniState->ofdmPhyErrBase || | 699 | if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { |
804 | phyCnt2 < aniState->cckPhyErrBase) { | 700 | if (phyCnt1 < ofdm_base) { |
805 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
806 | ath_print(common, ATH_DBG_ANI, | 701 | ath_print(common, ATH_DBG_ANI, |
807 | "phyCnt1 0x%x, resetting " | 702 | "phyCnt1 0x%x, resetting " |
808 | "counter value to 0x%x\n", | 703 | "counter value to 0x%x\n", |
809 | phyCnt1, | 704 | phyCnt1, ofdm_base); |
810 | aniState->ofdmPhyErrBase); | 705 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
811 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
812 | aniState->ofdmPhyErrBase); | ||
813 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | 706 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, |
814 | AR_PHY_ERR_OFDM_TIMING); | 707 | AR_PHY_ERR_OFDM_TIMING); |
815 | } | 708 | } |
816 | if (phyCnt2 < aniState->cckPhyErrBase) { | 709 | if (phyCnt2 < cck_base) { |
817 | ath_print(common, ATH_DBG_ANI, | 710 | ath_print(common, ATH_DBG_ANI, |
818 | "phyCnt2 0x%x, resetting " | 711 | "phyCnt2 0x%x, resetting " |
819 | "counter value to 0x%x\n", | 712 | "counter value to 0x%x\n", |
820 | phyCnt2, | 713 | phyCnt2, cck_base); |
821 | aniState->cckPhyErrBase); | 714 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
822 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
823 | aniState->cckPhyErrBase); | ||
824 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | 715 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, |
825 | AR_PHY_ERR_CCK_TIMING); | 716 | AR_PHY_ERR_CCK_TIMING); |
826 | } | 717 | } |
827 | return; | 718 | return; |
828 | } | 719 | } |
829 | 720 | ||
830 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 721 | ofdmPhyErrCnt = phyCnt1 - ofdm_base; |
831 | ah->stats.ast_ani_ofdmerrs += | 722 | ah->stats.ast_ani_ofdmerrs += |
832 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | 723 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; |
833 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | 724 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; |
834 | 725 | ||
835 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | 726 | cckPhyErrCnt = phyCnt2 - cck_base; |
836 | ah->stats.ast_ani_cckerrs += | 727 | ah->stats.ast_ani_cckerrs += |
837 | cckPhyErrCnt - aniState->cckPhyErrCount; | 728 | cckPhyErrCnt - aniState->cckPhyErrCount; |
838 | aniState->cckPhyErrCount = cckPhyErrCnt; | 729 | aniState->cckPhyErrCount = cckPhyErrCnt; |
839 | 730 | ||
840 | if (aniState->listenTime > 5 * ah->aniperiod) { | ||
841 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * | ||
842 | aniState->ofdmTrigLow / 1000 && | ||
843 | aniState->cckPhyErrCount <= aniState->listenTime * | ||
844 | aniState->cckTrigLow / 1000) | ||
845 | ath9k_hw_ani_lower_immunity(ah); | ||
846 | ath9k_ani_restart_old(ah); | ||
847 | } else if (aniState->listenTime > ah->aniperiod) { | ||
848 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | ||
849 | aniState->ofdmTrigHigh / 1000) { | ||
850 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
851 | ath9k_ani_restart_old(ah); | ||
852 | } else if (aniState->cckPhyErrCount > | ||
853 | aniState->listenTime * aniState->cckTrigHigh / | ||
854 | 1000) { | ||
855 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
856 | ath9k_ani_restart_old(ah); | ||
857 | } | ||
858 | } | ||
859 | } | 731 | } |
860 | 732 | ||
861 | static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | 733 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) |
862 | struct ath9k_channel *chan) | ||
863 | { | 734 | { |
864 | struct ar5416AniState *aniState; | 735 | struct ar5416AniState *aniState; |
865 | struct ath_common *common = ath9k_hw_common(ah); | 736 | struct ath_common *common = ath9k_hw_common(ah); |
866 | int32_t listenTime; | ||
867 | u32 phyCnt1, phyCnt2; | ||
868 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
869 | u32 ofdmPhyErrRate, cckPhyErrRate; | 737 | u32 ofdmPhyErrRate, cckPhyErrRate; |
870 | 738 | ||
871 | if (!DO_ANI(ah)) | 739 | if (!DO_ANI(ah)) |
872 | return; | 740 | return; |
873 | 741 | ||
874 | aniState = ah->curani; | 742 | aniState = &ah->curchan->ani; |
875 | if (WARN_ON(!aniState)) | 743 | if (WARN_ON(!aniState)) |
876 | return; | 744 | return; |
877 | 745 | ||
878 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 746 | ath9k_hw_ani_read_counters(ah); |
879 | if (listenTime <= 0) { | ||
880 | ah->stats.ast_ani_lneg++; | ||
881 | /* restart ANI period if listenTime is invalid */ | ||
882 | ath_print(common, ATH_DBG_ANI, | ||
883 | "listenTime=%d - on new ani monitor\n", | ||
884 | listenTime); | ||
885 | ath9k_ani_restart_new(ah); | ||
886 | return; | ||
887 | } | ||
888 | |||
889 | aniState->listenTime += listenTime; | ||
890 | |||
891 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
892 | |||
893 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
894 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
895 | |||
896 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
897 | phyCnt2 < aniState->cckPhyErrBase) { | ||
898 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
899 | ath_print(common, ATH_DBG_ANI, | ||
900 | "phyCnt1 0x%x, resetting " | ||
901 | "counter value to 0x%x\n", | ||
902 | phyCnt1, | ||
903 | aniState->ofdmPhyErrBase); | ||
904 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
905 | aniState->ofdmPhyErrBase); | ||
906 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
907 | AR_PHY_ERR_OFDM_TIMING); | ||
908 | } | ||
909 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
910 | ath_print(common, ATH_DBG_ANI, | ||
911 | "phyCnt2 0x%x, resetting " | ||
912 | "counter value to 0x%x\n", | ||
913 | phyCnt2, | ||
914 | aniState->cckPhyErrBase); | ||
915 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
916 | aniState->cckPhyErrBase); | ||
917 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
918 | AR_PHY_ERR_CCK_TIMING); | ||
919 | } | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
924 | ah->stats.ast_ani_ofdmerrs += | ||
925 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
926 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
927 | |||
928 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
929 | ah->stats.ast_ani_cckerrs += | ||
930 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
931 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
932 | |||
933 | ath_print(common, ATH_DBG_ANI, | ||
934 | "Errors: OFDM=0x%08x-0x%08x=%d " | ||
935 | "CCK=0x%08x-0x%08x=%d\n", | ||
936 | phyCnt1, | ||
937 | aniState->ofdmPhyErrBase, | ||
938 | ofdmPhyErrCnt, | ||
939 | phyCnt2, | ||
940 | aniState->cckPhyErrBase, | ||
941 | cckPhyErrCnt); | ||
942 | 747 | ||
943 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / | 748 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / |
944 | aniState->listenTime; | 749 | aniState->listenTime; |
@@ -948,61 +753,34 @@ static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | |||
948 | ath_print(common, ATH_DBG_ANI, | 753 | ath_print(common, ATH_DBG_ANI, |
949 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " | 754 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " |
950 | "errs=%d/s ofdm_turn=%d\n", | 755 | "errs=%d/s ofdm_turn=%d\n", |
951 | listenTime, aniState->ofdmNoiseImmunityLevel, | 756 | aniState->listenTime, |
757 | aniState->ofdmNoiseImmunityLevel, | ||
952 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | 758 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, |
953 | cckPhyErrRate, aniState->ofdmsTurn); | 759 | cckPhyErrRate, aniState->ofdmsTurn); |
954 | 760 | ||
955 | if (aniState->listenTime > 5 * ah->aniperiod) { | 761 | if (aniState->listenTime > 5 * ah->aniperiod) { |
956 | if (ofdmPhyErrRate <= aniState->ofdmTrigLow && | 762 | if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && |
957 | cckPhyErrRate <= aniState->cckTrigLow) { | 763 | cckPhyErrRate <= ah->config.cck_trig_low) { |
958 | ath_print(common, ATH_DBG_ANI, | ||
959 | "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " | ||
960 | "CCK:%d errs=%d/s(<%d) -> " | ||
961 | "ath9k_hw_ani_lower_immunity()\n", | ||
962 | aniState->listenTime, | ||
963 | aniState->ofdmNoiseImmunityLevel, | ||
964 | ofdmPhyErrRate, | ||
965 | aniState->ofdmTrigLow, | ||
966 | aniState->cckNoiseImmunityLevel, | ||
967 | cckPhyErrRate, | ||
968 | aniState->cckTrigLow); | ||
969 | ath9k_hw_ani_lower_immunity(ah); | 764 | ath9k_hw_ani_lower_immunity(ah); |
970 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | 765 | aniState->ofdmsTurn = !aniState->ofdmsTurn; |
971 | } | 766 | } |
972 | ath_print(common, ATH_DBG_ANI, | 767 | ath9k_ani_restart(ah); |
973 | "1 listenTime=%d ofdm=%d/s cck=%d/s - " | ||
974 | "calling ath9k_ani_restart_new()\n", | ||
975 | aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); | ||
976 | ath9k_ani_restart_new(ah); | ||
977 | } else if (aniState->listenTime > ah->aniperiod) { | 768 | } else if (aniState->listenTime > ah->aniperiod) { |
978 | /* check to see if need to raise immunity */ | 769 | /* check to see if need to raise immunity */ |
979 | if (ofdmPhyErrRate > aniState->ofdmTrigHigh && | 770 | if (ofdmPhyErrRate > ah->config.ofdm_trig_high && |
980 | (cckPhyErrRate <= aniState->cckTrigHigh || | 771 | (cckPhyErrRate <= ah->config.cck_trig_high || |
981 | aniState->ofdmsTurn)) { | 772 | aniState->ofdmsTurn)) { |
982 | ath_print(common, ATH_DBG_ANI, | 773 | ath9k_hw_ani_ofdm_err_trigger(ah); |
983 | "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " | 774 | ath9k_ani_restart(ah); |
984 | "ath9k_hw_ani_ofdm_err_trigger_new()\n", | ||
985 | aniState->listenTime, | ||
986 | aniState->ofdmNoiseImmunityLevel, | ||
987 | ofdmPhyErrRate, | ||
988 | aniState->ofdmTrigHigh); | ||
989 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
990 | ath9k_ani_restart_new(ah); | ||
991 | aniState->ofdmsTurn = false; | 775 | aniState->ofdmsTurn = false; |
992 | } else if (cckPhyErrRate > aniState->cckTrigHigh) { | 776 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
993 | ath_print(common, ATH_DBG_ANI, | 777 | ath9k_hw_ani_cck_err_trigger(ah); |
994 | "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " | 778 | ath9k_ani_restart(ah); |
995 | "ath9k_hw_ani_cck_err_trigger_new()\n", | ||
996 | aniState->listenTime, | ||
997 | aniState->cckNoiseImmunityLevel, | ||
998 | cckPhyErrRate, | ||
999 | aniState->cckTrigHigh); | ||
1000 | ath9k_hw_ani_cck_err_trigger_new(ah); | ||
1001 | ath9k_ani_restart_new(ah); | ||
1002 | aniState->ofdmsTurn = true; | 779 | aniState->ofdmsTurn = true; |
1003 | } | 780 | } |
1004 | } | 781 | } |
1005 | } | 782 | } |
783 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
1006 | 784 | ||
1007 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 785 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
1008 | { | 786 | { |
@@ -1023,7 +801,6 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) | |||
1023 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 801 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
1024 | 802 | ||
1025 | REGWRITE_BUFFER_FLUSH(ah); | 803 | REGWRITE_BUFFER_FLUSH(ah); |
1026 | DISABLE_REGWRITE_BUFFER(ah); | ||
1027 | } | 804 | } |
1028 | 805 | ||
1029 | /* Freeze the MIB counters, get the stats and then clear them */ | 806 | /* Freeze the MIB counters, get the stats and then clear them */ |
@@ -1041,107 +818,52 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
1041 | } | 818 | } |
1042 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | 819 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); |
1043 | 820 | ||
1044 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | 821 | void ath9k_hw_update_cycle_counters(struct ath_hw *ah) |
1045 | u32 *rxc_pcnt, | ||
1046 | u32 *rxf_pcnt, | ||
1047 | u32 *txf_pcnt) | ||
1048 | { | 822 | { |
1049 | struct ath_common *common = ath9k_hw_common(ah); | 823 | struct ath_cycle_counters cc; |
1050 | static u32 cycles, rx_clear, rx_frame, tx_frame; | 824 | bool clear; |
1051 | u32 good = 1; | ||
1052 | 825 | ||
1053 | u32 rc = REG_READ(ah, AR_RCCNT); | 826 | memcpy(&cc, &ah->cc, sizeof(cc)); |
1054 | u32 rf = REG_READ(ah, AR_RFCNT); | ||
1055 | u32 tf = REG_READ(ah, AR_TFCNT); | ||
1056 | u32 cc = REG_READ(ah, AR_CCCNT); | ||
1057 | 827 | ||
1058 | if (cycles == 0 || cycles > cc) { | 828 | /* freeze counters */ |
1059 | ath_print(common, ATH_DBG_ANI, | 829 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); |
1060 | "cycle counter wrap. ExtBusy = 0\n"); | ||
1061 | good = 0; | ||
1062 | } else { | ||
1063 | u32 cc_d = cc - cycles; | ||
1064 | u32 rc_d = rc - rx_clear; | ||
1065 | u32 rf_d = rf - rx_frame; | ||
1066 | u32 tf_d = tf - tx_frame; | ||
1067 | |||
1068 | if (cc_d != 0) { | ||
1069 | *rxc_pcnt = rc_d * 100 / cc_d; | ||
1070 | *rxf_pcnt = rf_d * 100 / cc_d; | ||
1071 | *txf_pcnt = tf_d * 100 / cc_d; | ||
1072 | } else { | ||
1073 | good = 0; | ||
1074 | } | ||
1075 | } | ||
1076 | 830 | ||
1077 | cycles = cc; | 831 | ah->cc.cycles = REG_READ(ah, AR_CCCNT); |
1078 | rx_frame = rf; | 832 | if (ah->cc.cycles < cc.cycles) { |
1079 | rx_clear = rc; | 833 | clear = true; |
1080 | tx_frame = tf; | 834 | goto skip; |
835 | } | ||
1081 | 836 | ||
1082 | return good; | 837 | ah->cc.rx_clear = REG_READ(ah, AR_RCCNT); |
1083 | } | 838 | ah->cc.rx_frame = REG_READ(ah, AR_RFCNT); |
839 | ah->cc.tx_frame = REG_READ(ah, AR_TFCNT); | ||
1084 | 840 | ||
1085 | /* | 841 | /* prevent wraparound */ |
1086 | * Process a MIB interrupt. We may potentially be invoked because | 842 | if (ah->cc.cycles & BIT(31)) |
1087 | * any of the MIB counters overflow/trigger so don't assume we're | 843 | clear = true; |
1088 | * here because a PHY error counter triggered. | ||
1089 | */ | ||
1090 | static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | ||
1091 | { | ||
1092 | u32 phyCnt1, phyCnt2; | ||
1093 | 844 | ||
1094 | /* Reset these counters regardless */ | 845 | #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field |
1095 | REG_WRITE(ah, AR_FILT_OFDM, 0); | 846 | CC_DELTA(cycles, AR_CCCNT); |
1096 | REG_WRITE(ah, AR_FILT_CCK, 0); | 847 | CC_DELTA(rx_frame, AR_RFCNT); |
1097 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | 848 | CC_DELTA(rx_clear, AR_RCCNT); |
1098 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | 849 | CC_DELTA(tx_frame, AR_TFCNT); |
850 | #undef CC_DELTA | ||
1099 | 851 | ||
1100 | /* Clear the mib counters and save them in the stats */ | 852 | ah->listen_time += (ah->cc.cycles - cc.cycles) - |
1101 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 853 | ((ah->cc.rx_frame - cc.rx_frame) + |
854 | (ah->cc.tx_frame - cc.tx_frame)); | ||
1102 | 855 | ||
1103 | if (!DO_ANI(ah)) { | 856 | skip: |
1104 | /* | 857 | if (clear) { |
1105 | * We must always clear the interrupt cause by | 858 | REG_WRITE(ah, AR_CCCNT, 0); |
1106 | * resetting the phy error regs. | 859 | REG_WRITE(ah, AR_RFCNT, 0); |
1107 | */ | 860 | REG_WRITE(ah, AR_RCCNT, 0); |
1108 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | 861 | REG_WRITE(ah, AR_TFCNT, 0); |
1109 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | 862 | memset(&ah->cc, 0, sizeof(ah->cc)); |
1110 | return; | ||
1111 | } | 863 | } |
1112 | 864 | ||
1113 | /* NB: these are not reset-on-read */ | 865 | /* unfreeze counters */ |
1114 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 866 | REG_WRITE(ah, AR_MIBC, 0); |
1115 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
1116 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
1117 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { | ||
1118 | struct ar5416AniState *aniState = ah->curani; | ||
1119 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
1120 | |||
1121 | /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ | ||
1122 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
1123 | ah->stats.ast_ani_ofdmerrs += | ||
1124 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
1125 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
1126 | |||
1127 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
1128 | ah->stats.ast_ani_cckerrs += | ||
1129 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
1130 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
1131 | |||
1132 | /* | ||
1133 | * NB: figure out which counter triggered. If both | ||
1134 | * trigger we'll only deal with one as the processing | ||
1135 | * clobbers the error counter so the trigger threshold | ||
1136 | * check will never be true. | ||
1137 | */ | ||
1138 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | ||
1139 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
1140 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | ||
1141 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
1142 | /* NB: always restart to insure the h/w counters are reset */ | ||
1143 | ath9k_ani_restart_old(ah); | ||
1144 | } | ||
1145 | } | 867 | } |
1146 | 868 | ||
1147 | /* | 869 | /* |
@@ -1149,7 +871,7 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | |||
1149 | * any of the MIB counters overflow/trigger so don't assume we're | 871 | * any of the MIB counters overflow/trigger so don't assume we're |
1150 | * here because a PHY error counter triggered. | 872 | * here because a PHY error counter triggered. |
1151 | */ | 873 | */ |
1152 | static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | 874 | void ath9k_hw_proc_mib_event(struct ath_hw *ah) |
1153 | { | 875 | { |
1154 | u32 phyCnt1, phyCnt2; | 876 | u32 phyCnt1, phyCnt2; |
1155 | 877 | ||
@@ -1175,12 +897,17 @@ static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | |||
1175 | /* NB: these are not reset-on-read */ | 897 | /* NB: these are not reset-on-read */ |
1176 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 898 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
1177 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 899 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
1178 | |||
1179 | /* NB: always restart to insure the h/w counters are reset */ | ||
1180 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | 900 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || |
1181 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) | 901 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { |
1182 | ath9k_ani_restart_new(ah); | 902 | |
903 | if (!use_new_ani(ah)) | ||
904 | ath9k_hw_ani_read_counters(ah); | ||
905 | |||
906 | /* NB: always restart to insure the h/w counters are reset */ | ||
907 | ath9k_ani_restart(ah); | ||
908 | } | ||
1183 | } | 909 | } |
910 | EXPORT_SYMBOL(ath9k_hw_proc_mib_event); | ||
1184 | 911 | ||
1185 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 912 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
1186 | { | 913 | { |
@@ -1206,61 +933,58 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1206 | 933 | ||
1207 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); | 934 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); |
1208 | 935 | ||
1209 | memset(ah->ani, 0, sizeof(ah->ani)); | 936 | if (use_new_ani(ah)) { |
1210 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 937 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; |
1211 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 938 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW; |
1212 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; | ||
1213 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; | ||
1214 | 939 | ||
1215 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | 940 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW; |
1216 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; | 941 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW; |
942 | } else { | ||
943 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
944 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1217 | 945 | ||
1218 | ah->ani[i].spurImmunityLevel = | 946 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; |
1219 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | 947 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; |
948 | } | ||
949 | |||
950 | for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { | ||
951 | struct ath9k_channel *chan = &ah->channels[i]; | ||
952 | struct ar5416AniState *ani = &chan->ani; | ||
1220 | 953 | ||
1221 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 954 | if (use_new_ani(ah)) { |
955 | ani->spurImmunityLevel = | ||
956 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1222 | 957 | ||
1223 | ah->ani[i].ofdmPhyErrBase = 0; | 958 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1224 | ah->ani[i].cckPhyErrBase = 0; | ||
1225 | 959 | ||
1226 | if (AR_SREV_9300_20_OR_LATER(ah)) | 960 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1227 | ah->ani[i].mrcCCKOff = | 961 | ani->mrcCCKOff = |
1228 | !ATH9K_ANI_ENABLE_MRC_CCK; | 962 | !ATH9K_ANI_ENABLE_MRC_CCK; |
1229 | else | 963 | else |
1230 | ah->ani[i].mrcCCKOff = true; | 964 | ani->mrcCCKOff = true; |
1231 | 965 | ||
1232 | ah->ani[i].ofdmsTurn = true; | 966 | ani->ofdmsTurn = true; |
1233 | } else { | 967 | } else { |
1234 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | 968 | ani->spurImmunityLevel = |
1235 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1236 | |||
1237 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1238 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
1239 | |||
1240 | ah->ani[i].spurImmunityLevel = | ||
1241 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | 969 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; |
1242 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | 970 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; |
1243 | 971 | ||
1244 | ah->ani[i].ofdmPhyErrBase = | 972 | ani->cckWeakSigThreshold = |
1245 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1246 | ah->ani[i].cckPhyErrBase = | ||
1247 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1248 | ah->ani[i].cckWeakSigThreshold = | ||
1249 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 973 | ATH9K_ANI_CCK_WEAK_SIG_THR; |
1250 | } | 974 | } |
1251 | 975 | ||
1252 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 976 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
1253 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 977 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
1254 | ah->ani[i].ofdmWeakSigDetectOff = | 978 | ani->ofdmWeakSigDetectOff = |
1255 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 979 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1256 | ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 980 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
1257 | } | 981 | } |
1258 | 982 | ||
1259 | /* | 983 | /* |
1260 | * since we expect some ongoing maintenance on the tables, let's sanity | 984 | * since we expect some ongoing maintenance on the tables, let's sanity |
1261 | * check here default level should not modify INI setting. | 985 | * check here default level should not modify INI setting. |
1262 | */ | 986 | */ |
1263 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 987 | if (use_new_ani(ah)) { |
1264 | const struct ani_ofdm_level_entry *entry_ofdm; | 988 | const struct ani_ofdm_level_entry *entry_ofdm; |
1265 | const struct ani_cck_level_entry *entry_cck; | 989 | const struct ani_cck_level_entry *entry_cck; |
1266 | 990 | ||
@@ -1274,50 +998,9 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1274 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | 998 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; |
1275 | } | 999 | } |
1276 | 1000 | ||
1277 | ath_print(common, ATH_DBG_ANI, | ||
1278 | "Setting OfdmErrBase = 0x%08x\n", | ||
1279 | ah->ani[0].ofdmPhyErrBase); | ||
1280 | ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
1281 | ah->ani[0].cckPhyErrBase); | ||
1282 | |||
1283 | ENABLE_REGWRITE_BUFFER(ah); | ||
1284 | |||
1285 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | ||
1286 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | ||
1287 | |||
1288 | REGWRITE_BUFFER_FLUSH(ah); | ||
1289 | DISABLE_REGWRITE_BUFFER(ah); | ||
1290 | |||
1291 | ath9k_enable_mib_counters(ah); | ||
1292 | |||
1293 | if (ah->config.enable_ani) | 1001 | if (ah->config.enable_ani) |
1294 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 1002 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
1295 | } | ||
1296 | |||
1297 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) | ||
1298 | { | ||
1299 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1300 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1301 | 1003 | ||
1302 | priv_ops->ani_reset = ath9k_ani_reset_old; | 1004 | ath9k_ani_restart(ah); |
1303 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; | 1005 | ath9k_enable_mib_counters(ah); |
1304 | |||
1305 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; | ||
1306 | ops->ani_monitor = ath9k_hw_ani_monitor_old; | ||
1307 | |||
1308 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); | ||
1309 | } | ||
1310 | |||
1311 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) | ||
1312 | { | ||
1313 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1314 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1315 | |||
1316 | priv_ops->ani_reset = ath9k_ani_reset_new; | ||
1317 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; | ||
1318 | |||
1319 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; | ||
1320 | ops->ani_monitor = ath9k_hw_ani_monitor_new; | ||
1321 | |||
1322 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); | ||
1323 | } | 1006 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index f4d0a4d48b37..98cfd8154c71 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #define HAL_PROCESS_ANI 0x00000001 | 20 | #define HAL_PROCESS_ANI 0x00000001 |
21 | 21 | ||
22 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) | 22 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan) |
23 | 23 | ||
24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
25 | 25 | ||
@@ -93,6 +93,13 @@ struct ath9k_mib_stats { | |||
93 | u32 beacons; | 93 | u32 beacons; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | struct ath_cycle_counters { | ||
97 | u32 cycles; | ||
98 | u32 rx_frame; | ||
99 | u32 rx_clear; | ||
100 | u32 tx_frame; | ||
101 | }; | ||
102 | |||
96 | /* INI default values for ANI registers */ | 103 | /* INI default values for ANI registers */ |
97 | struct ath9k_ani_default { | 104 | struct ath9k_ani_default { |
98 | u16 m1ThreshLow; | 105 | u16 m1ThreshLow; |
@@ -123,20 +130,11 @@ struct ar5416AniState { | |||
123 | u8 ofdmWeakSigDetectOff; | 130 | u8 ofdmWeakSigDetectOff; |
124 | u8 cckWeakSigThreshold; | 131 | u8 cckWeakSigThreshold; |
125 | u32 listenTime; | 132 | u32 listenTime; |
126 | u32 ofdmTrigHigh; | ||
127 | u32 ofdmTrigLow; | ||
128 | int32_t cckTrigHigh; | ||
129 | int32_t cckTrigLow; | ||
130 | int32_t rssiThrLow; | 133 | int32_t rssiThrLow; |
131 | int32_t rssiThrHigh; | 134 | int32_t rssiThrHigh; |
132 | u32 noiseFloor; | 135 | u32 noiseFloor; |
133 | u32 txFrameCount; | ||
134 | u32 rxFrameCount; | ||
135 | u32 cycleCount; | ||
136 | u32 ofdmPhyErrCount; | 136 | u32 ofdmPhyErrCount; |
137 | u32 cckPhyErrCount; | 137 | u32 cckPhyErrCount; |
138 | u32 ofdmPhyErrBase; | ||
139 | u32 cckPhyErrBase; | ||
140 | int16_t pktRssi[2]; | 138 | int16_t pktRssi[2]; |
141 | int16_t ofdmErrRssi[2]; | 139 | int16_t ofdmErrRssi[2]; |
142 | int16_t cckErrRssi[2]; | 140 | int16_t cckErrRssi[2]; |
@@ -166,8 +164,7 @@ struct ar5416Stats { | |||
166 | 164 | ||
167 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 165 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
168 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 166 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
169 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | 167 | void ath9k_hw_update_cycle_counters(struct ath_hw *ah); |
170 | u32 *rxf_pcnt, u32 *txf_pcnt); | ||
171 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 168 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
172 | void ath9k_hw_ani_init(struct ath_hw *ah); | 169 | void ath9k_hw_ani_init(struct ath_hw *ah); |
173 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 170 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 525671f52b45..ea9f4497f58c 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -613,14 +613,11 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) | |||
613 | rx_chainmask = ah->rxchainmask; | 613 | rx_chainmask = ah->rxchainmask; |
614 | tx_chainmask = ah->txchainmask; | 614 | tx_chainmask = ah->txchainmask; |
615 | 615 | ||
616 | ENABLE_REGWRITE_BUFFER(ah); | ||
617 | 616 | ||
618 | switch (rx_chainmask) { | 617 | switch (rx_chainmask) { |
619 | case 0x5: | 618 | case 0x5: |
620 | DISABLE_REGWRITE_BUFFER(ah); | ||
621 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 619 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
622 | AR_PHY_SWAP_ALT_CHAIN); | 620 | AR_PHY_SWAP_ALT_CHAIN); |
623 | ENABLE_REGWRITE_BUFFER(ah); | ||
624 | case 0x3: | 621 | case 0x3: |
625 | if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { | 622 | if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { |
626 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); | 623 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); |
@@ -630,17 +627,18 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) | |||
630 | case 0x1: | 627 | case 0x1: |
631 | case 0x2: | 628 | case 0x2: |
632 | case 0x7: | 629 | case 0x7: |
630 | ENABLE_REGWRITE_BUFFER(ah); | ||
633 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | 631 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); |
634 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | 632 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); |
635 | break; | 633 | break; |
636 | default: | 634 | default: |
635 | ENABLE_REGWRITE_BUFFER(ah); | ||
637 | break; | 636 | break; |
638 | } | 637 | } |
639 | 638 | ||
640 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); | 639 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); |
641 | 640 | ||
642 | REGWRITE_BUFFER_FLUSH(ah); | 641 | REGWRITE_BUFFER_FLUSH(ah); |
643 | DISABLE_REGWRITE_BUFFER(ah); | ||
644 | 642 | ||
645 | if (tx_chainmask == 0x5) { | 643 | if (tx_chainmask == 0x5) { |
646 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 644 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
@@ -726,7 +724,6 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
726 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); | 724 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); |
727 | 725 | ||
728 | REGWRITE_BUFFER_FLUSH(ah); | 726 | REGWRITE_BUFFER_FLUSH(ah); |
729 | DISABLE_REGWRITE_BUFFER(ah); | ||
730 | } | 727 | } |
731 | 728 | ||
732 | 729 | ||
@@ -818,7 +815,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
818 | } | 815 | } |
819 | 816 | ||
820 | REGWRITE_BUFFER_FLUSH(ah); | 817 | REGWRITE_BUFFER_FLUSH(ah); |
821 | DISABLE_REGWRITE_BUFFER(ah); | ||
822 | 818 | ||
823 | if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah)) | 819 | if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah)) |
824 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); | 820 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); |
@@ -849,7 +845,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
849 | } | 845 | } |
850 | 846 | ||
851 | REGWRITE_BUFFER_FLUSH(ah); | 847 | REGWRITE_BUFFER_FLUSH(ah); |
852 | DISABLE_REGWRITE_BUFFER(ah); | ||
853 | 848 | ||
854 | if (AR_SREV_9271(ah)) { | 849 | if (AR_SREV_9271(ah)) { |
855 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) | 850 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) |
@@ -1053,7 +1048,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1053 | enum ath9k_ani_cmd cmd, | 1048 | enum ath9k_ani_cmd cmd, |
1054 | int param) | 1049 | int param) |
1055 | { | 1050 | { |
1056 | struct ar5416AniState *aniState = ah->curani; | 1051 | struct ar5416AniState *aniState = &ah->curchan->ani; |
1057 | struct ath_common *common = ath9k_hw_common(ah); | 1052 | struct ath_common *common = ath9k_hw_common(ah); |
1058 | 1053 | ||
1059 | switch (cmd & ah->ani_function) { | 1054 | switch (cmd & ah->ani_function) { |
@@ -1225,8 +1220,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1225 | aniState->firstepLevel, | 1220 | aniState->firstepLevel, |
1226 | aniState->listenTime); | 1221 | aniState->listenTime); |
1227 | ath_print(common, ATH_DBG_ANI, | 1222 | ath_print(common, ATH_DBG_ANI, |
1228 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | 1223 | "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", |
1229 | aniState->cycleCount, | ||
1230 | aniState->ofdmPhyErrCount, | 1224 | aniState->ofdmPhyErrCount, |
1231 | aniState->cckPhyErrCount); | 1225 | aniState->cckPhyErrCount); |
1232 | 1226 | ||
@@ -1237,9 +1231,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1237 | enum ath9k_ani_cmd cmd, | 1231 | enum ath9k_ani_cmd cmd, |
1238 | int param) | 1232 | int param) |
1239 | { | 1233 | { |
1240 | struct ar5416AniState *aniState = ah->curani; | ||
1241 | struct ath_common *common = ath9k_hw_common(ah); | 1234 | struct ath_common *common = ath9k_hw_common(ah); |
1242 | struct ath9k_channel *chan = ah->curchan; | 1235 | struct ath9k_channel *chan = ah->curchan; |
1236 | struct ar5416AniState *aniState = &chan->ani; | ||
1243 | s32 value, value2; | 1237 | s32 value, value2; |
1244 | 1238 | ||
1245 | switch (cmd & ah->ani_function) { | 1239 | switch (cmd & ah->ani_function) { |
@@ -1478,15 +1472,13 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1478 | 1472 | ||
1479 | ath_print(common, ATH_DBG_ANI, | 1473 | ath_print(common, ATH_DBG_ANI, |
1480 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | 1474 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " |
1481 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | 1475 | "MRCcck=%s listenTime=%d " |
1482 | "ofdmErrs=%d cckErrs=%d\n", | 1476 | "ofdmErrs=%d cckErrs=%d\n", |
1483 | aniState->spurImmunityLevel, | 1477 | aniState->spurImmunityLevel, |
1484 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1478 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
1485 | aniState->firstepLevel, | 1479 | aniState->firstepLevel, |
1486 | !aniState->mrcCCKOff ? "on" : "off", | 1480 | !aniState->mrcCCKOff ? "on" : "off", |
1487 | aniState->listenTime, | 1481 | aniState->listenTime, |
1488 | aniState->cycleCount, | ||
1489 | aniState->listenTime, | ||
1490 | aniState->ofdmPhyErrCount, | 1482 | aniState->ofdmPhyErrCount, |
1491 | aniState->cckPhyErrCount); | 1483 | aniState->cckPhyErrCount); |
1492 | return true; | 1484 | return true; |
@@ -1526,16 +1518,12 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, | |||
1526 | */ | 1518 | */ |
1527 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | 1519 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) |
1528 | { | 1520 | { |
1529 | struct ar5416AniState *aniState; | ||
1530 | struct ath_common *common = ath9k_hw_common(ah); | 1521 | struct ath_common *common = ath9k_hw_common(ah); |
1531 | struct ath9k_channel *chan = ah->curchan; | 1522 | struct ath9k_channel *chan = ah->curchan; |
1523 | struct ar5416AniState *aniState = &chan->ani; | ||
1532 | struct ath9k_ani_default *iniDef; | 1524 | struct ath9k_ani_default *iniDef; |
1533 | int index; | ||
1534 | u32 val; | 1525 | u32 val; |
1535 | 1526 | ||
1536 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1537 | aniState = &ah->ani[index]; | ||
1538 | ah->curani = aniState; | ||
1539 | iniDef = &aniState->iniDef; | 1527 | iniDef = &aniState->iniDef; |
1540 | 1528 | ||
1541 | ath_print(common, ATH_DBG_ANI, | 1529 | ath_print(common, ATH_DBG_ANI, |
@@ -1579,8 +1567,6 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1579 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1567 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1580 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1568 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1581 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ | 1569 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ |
1582 | |||
1583 | aniState->cycleCount = 0; | ||
1584 | } | 1570 | } |
1585 | 1571 | ||
1586 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) | 1572 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index d7d1d55362e6..15f62cd0cc38 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -20,6 +20,13 @@ | |||
20 | 20 | ||
21 | #define AR9285_CLCAL_REDO_THRESH 1 | 21 | #define AR9285_CLCAL_REDO_THRESH 1 |
22 | 22 | ||
23 | enum ar9002_cal_types { | ||
24 | ADC_GAIN_CAL = BIT(0), | ||
25 | ADC_DC_CAL = BIT(1), | ||
26 | IQ_MISMATCH_CAL = BIT(2), | ||
27 | }; | ||
28 | |||
29 | |||
23 | static void ar9002_hw_setup_calibration(struct ath_hw *ah, | 30 | static void ar9002_hw_setup_calibration(struct ath_hw *ah, |
24 | struct ath9k_cal_list *currCal) | 31 | struct ath9k_cal_list *currCal) |
25 | { | 32 | { |
@@ -45,13 +52,6 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah, | |||
45 | ath_print(common, ATH_DBG_CALIBRATE, | 52 | ath_print(common, ATH_DBG_CALIBRATE, |
46 | "starting ADC DC Calibration\n"); | 53 | "starting ADC DC Calibration\n"); |
47 | break; | 54 | break; |
48 | case ADC_DC_INIT_CAL: | ||
49 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | ||
50 | ath_print(common, ATH_DBG_CALIBRATE, | ||
51 | "starting Init ADC DC Calibration\n"); | ||
52 | break; | ||
53 | case TEMP_COMP_CAL: | ||
54 | break; /* Not supported */ | ||
55 | } | 55 | } |
56 | 56 | ||
57 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | 57 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), |
@@ -96,25 +96,6 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
96 | return iscaldone; | 96 | return iscaldone; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* Assumes you are talking about the currently configured channel */ | ||
100 | static bool ar9002_hw_iscal_supported(struct ath_hw *ah, | ||
101 | enum ath9k_cal_types calType) | ||
102 | { | ||
103 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
104 | |||
105 | switch (calType & ah->supp_cals) { | ||
106 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ | ||
107 | return true; | ||
108 | case ADC_GAIN_CAL: | ||
109 | case ADC_DC_CAL: | ||
110 | if (!(conf->channel->band == IEEE80211_BAND_2GHZ && | ||
111 | conf_is_ht20(conf))) | ||
112 | return true; | ||
113 | break; | ||
114 | } | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | static void ar9002_hw_iqcal_collect(struct ath_hw *ah) | 99 | static void ar9002_hw_iqcal_collect(struct ath_hw *ah) |
119 | { | 100 | { |
120 | int i; | 101 | int i; |
@@ -541,7 +522,6 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
541 | REG_WRITE(ah, regList[i][0], regList[i][1]); | 522 | REG_WRITE(ah, regList[i][0], regList[i][1]); |
542 | 523 | ||
543 | REGWRITE_BUFFER_FLUSH(ah); | 524 | REGWRITE_BUFFER_FLUSH(ah); |
544 | DISABLE_REGWRITE_BUFFER(ah); | ||
545 | } | 525 | } |
546 | 526 | ||
547 | static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) | 527 | static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
@@ -877,24 +857,28 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
877 | 857 | ||
878 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ | 858 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ |
879 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { | 859 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { |
880 | if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) { | 860 | ah->supp_cals = IQ_MISMATCH_CAL; |
861 | |||
862 | if (AR_SREV_9160_10_OR_LATER(ah) && | ||
863 | !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) { | ||
864 | ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; | ||
865 | |||
866 | |||
881 | INIT_CAL(&ah->adcgain_caldata); | 867 | INIT_CAL(&ah->adcgain_caldata); |
882 | INSERT_CAL(ah, &ah->adcgain_caldata); | 868 | INSERT_CAL(ah, &ah->adcgain_caldata); |
883 | ath_print(common, ATH_DBG_CALIBRATE, | 869 | ath_print(common, ATH_DBG_CALIBRATE, |
884 | "enabling ADC Gain Calibration.\n"); | 870 | "enabling ADC Gain Calibration.\n"); |
885 | } | 871 | |
886 | if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) { | ||
887 | INIT_CAL(&ah->adcdc_caldata); | 872 | INIT_CAL(&ah->adcdc_caldata); |
888 | INSERT_CAL(ah, &ah->adcdc_caldata); | 873 | INSERT_CAL(ah, &ah->adcdc_caldata); |
889 | ath_print(common, ATH_DBG_CALIBRATE, | 874 | ath_print(common, ATH_DBG_CALIBRATE, |
890 | "enabling ADC DC Calibration.\n"); | 875 | "enabling ADC DC Calibration.\n"); |
891 | } | 876 | } |
892 | if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 877 | |
893 | INIT_CAL(&ah->iq_caldata); | 878 | INIT_CAL(&ah->iq_caldata); |
894 | INSERT_CAL(ah, &ah->iq_caldata); | 879 | INSERT_CAL(ah, &ah->iq_caldata); |
895 | ath_print(common, ATH_DBG_CALIBRATE, | 880 | ath_print(common, ATH_DBG_CALIBRATE, |
896 | "enabling IQ Calibration.\n"); | 881 | "enabling IQ Calibration.\n"); |
897 | } | ||
898 | 882 | ||
899 | ah->cal_list_curr = ah->cal_list; | 883 | ah->cal_list_curr = ah->cal_list; |
900 | 884 | ||
@@ -950,13 +934,6 @@ static const struct ath9k_percal_data adc_dc_cal_single_sample = { | |||
950 | ar9002_hw_adc_dccal_collect, | 934 | ar9002_hw_adc_dccal_collect, |
951 | ar9002_hw_adc_dccal_calibrate | 935 | ar9002_hw_adc_dccal_calibrate |
952 | }; | 936 | }; |
953 | static const struct ath9k_percal_data adc_init_dc_cal = { | ||
954 | ADC_DC_INIT_CAL, | ||
955 | MIN_CAL_SAMPLES, | ||
956 | INIT_LOG_COUNT, | ||
957 | ar9002_hw_adc_dccal_collect, | ||
958 | ar9002_hw_adc_dccal_calibrate | ||
959 | }; | ||
960 | 937 | ||
961 | static void ar9002_hw_init_cal_settings(struct ath_hw *ah) | 938 | static void ar9002_hw_init_cal_settings(struct ath_hw *ah) |
962 | { | 939 | { |
@@ -973,16 +950,12 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah) | |||
973 | &adc_gain_cal_single_sample; | 950 | &adc_gain_cal_single_sample; |
974 | ah->adcdc_caldata.calData = | 951 | ah->adcdc_caldata.calData = |
975 | &adc_dc_cal_single_sample; | 952 | &adc_dc_cal_single_sample; |
976 | ah->adcdc_calinitdata.calData = | ||
977 | &adc_init_dc_cal; | ||
978 | } else { | 953 | } else { |
979 | ah->iq_caldata.calData = &iq_cal_multi_sample; | 954 | ah->iq_caldata.calData = &iq_cal_multi_sample; |
980 | ah->adcgain_caldata.calData = | 955 | ah->adcgain_caldata.calData = |
981 | &adc_gain_cal_multi_sample; | 956 | &adc_gain_cal_multi_sample; |
982 | ah->adcdc_caldata.calData = | 957 | ah->adcdc_caldata.calData = |
983 | &adc_dc_cal_multi_sample; | 958 | &adc_dc_cal_multi_sample; |
984 | ah->adcdc_calinitdata.calData = | ||
985 | &adc_init_dc_cal; | ||
986 | } | 959 | } |
987 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | 960 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; |
988 | } | 961 | } |
@@ -996,7 +969,6 @@ void ar9002_hw_attach_calib_ops(struct ath_hw *ah) | |||
996 | priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; | 969 | priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; |
997 | priv_ops->init_cal = ar9002_hw_init_cal; | 970 | priv_ops->init_cal = ar9002_hw_init_cal; |
998 | priv_ops->setup_calibration = ar9002_hw_setup_calibration; | 971 | priv_ops->setup_calibration = ar9002_hw_setup_calibration; |
999 | priv_ops->iscal_supported = ar9002_hw_iscal_supported; | ||
1000 | 972 | ||
1001 | ops->calibrate = ar9002_hw_calibrate; | 973 | ops->calibrate = ar9002_hw_calibrate; |
1002 | } | 974 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index fde45082a13b..a0471f2e1c7a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -371,7 +371,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
371 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 371 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
372 | 372 | ||
373 | REGWRITE_BUFFER_FLUSH(ah); | 373 | REGWRITE_BUFFER_FLUSH(ah); |
374 | DISABLE_REGWRITE_BUFFER(ah); | ||
375 | } | 374 | } |
376 | 375 | ||
377 | udelay(1000); | 376 | udelay(1000); |
@@ -468,7 +467,6 @@ static int ar9002_hw_get_radiorev(struct ath_hw *ah) | |||
468 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); | 467 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); |
469 | 468 | ||
470 | REGWRITE_BUFFER_FLUSH(ah); | 469 | REGWRITE_BUFFER_FLUSH(ah); |
471 | DISABLE_REGWRITE_BUFFER(ah); | ||
472 | 470 | ||
473 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; | 471 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; |
474 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); | 472 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); |
@@ -574,11 +572,6 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
574 | 572 | ||
575 | ar9002_hw_attach_calib_ops(ah); | 573 | ar9002_hw_attach_calib_ops(ah); |
576 | ar9002_hw_attach_mac_ops(ah); | 574 | ar9002_hw_attach_mac_ops(ah); |
577 | |||
578 | if (modparam_force_new_ani) | ||
579 | ath9k_hw_attach_ani_ops_new(ah); | ||
580 | else | ||
581 | ath9k_hw_attach_ani_ops_old(ah); | ||
582 | } | 575 | } |
583 | 576 | ||
584 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | 577 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) |
@@ -627,6 +620,4 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | |||
627 | } | 620 | } |
628 | 621 | ||
629 | REGWRITE_BUFFER_FLUSH(ah); | 622 | REGWRITE_BUFFER_FLUSH(ah); |
630 | DISABLE_REGWRITE_BUFFER(ah); | ||
631 | |||
632 | } | 623 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index cd56c8692705..c00cdc67b55b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -415,7 +415,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | |||
415 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | 415 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); |
416 | 416 | ||
417 | REGWRITE_BUFFER_FLUSH(ah); | 417 | REGWRITE_BUFFER_FLUSH(ah); |
418 | DISABLE_REGWRITE_BUFFER(ah); | ||
419 | } | 418 | } |
420 | 419 | ||
421 | static void ar9002_olc_init(struct ath_hw *ah) | 420 | static void ar9002_olc_init(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4674ea8c9c99..9e6edffe0bd1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -18,6 +18,11 @@ | |||
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
20 | 20 | ||
21 | enum ar9003_cal_types { | ||
22 | IQ_MISMATCH_CAL = BIT(0), | ||
23 | TEMP_COMP_CAL = BIT(1), | ||
24 | }; | ||
25 | |||
21 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, | 26 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, |
22 | struct ath9k_cal_list *currCal) | 27 | struct ath9k_cal_list *currCal) |
23 | { | 28 | { |
@@ -50,11 +55,6 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, | |||
50 | ath_print(common, ATH_DBG_CALIBRATE, | 55 | ath_print(common, ATH_DBG_CALIBRATE, |
51 | "starting Temperature Compensation Calibration\n"); | 56 | "starting Temperature Compensation Calibration\n"); |
52 | break; | 57 | break; |
53 | case ADC_DC_INIT_CAL: | ||
54 | case ADC_GAIN_CAL: | ||
55 | case ADC_DC_CAL: | ||
56 | /* Not yet */ | ||
57 | break; | ||
58 | } | 58 | } |
59 | } | 59 | } |
60 | 60 | ||
@@ -314,27 +314,6 @@ static const struct ath9k_percal_data iq_cal_single_sample = { | |||
314 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) | 314 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) |
315 | { | 315 | { |
316 | ah->iq_caldata.calData = &iq_cal_single_sample; | 316 | ah->iq_caldata.calData = &iq_cal_single_sample; |
317 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
318 | } | ||
319 | |||
320 | static bool ar9003_hw_iscal_supported(struct ath_hw *ah, | ||
321 | enum ath9k_cal_types calType) | ||
322 | { | ||
323 | switch (calType & ah->supp_cals) { | ||
324 | case IQ_MISMATCH_CAL: | ||
325 | /* | ||
326 | * XXX: Run IQ Mismatch for non-CCK only | ||
327 | * Note that CHANNEL_B is never set though. | ||
328 | */ | ||
329 | return true; | ||
330 | case ADC_GAIN_CAL: | ||
331 | case ADC_DC_CAL: | ||
332 | return false; | ||
333 | case TEMP_COMP_CAL: | ||
334 | return true; | ||
335 | } | ||
336 | |||
337 | return false; | ||
338 | } | 317 | } |
339 | 318 | ||
340 | /* | 319 | /* |
@@ -773,15 +752,16 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
773 | 752 | ||
774 | /* Initialize list pointers */ | 753 | /* Initialize list pointers */ |
775 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 754 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
755 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
776 | 756 | ||
777 | if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 757 | if (ah->supp_cals & IQ_MISMATCH_CAL) { |
778 | INIT_CAL(&ah->iq_caldata); | 758 | INIT_CAL(&ah->iq_caldata); |
779 | INSERT_CAL(ah, &ah->iq_caldata); | 759 | INSERT_CAL(ah, &ah->iq_caldata); |
780 | ath_print(common, ATH_DBG_CALIBRATE, | 760 | ath_print(common, ATH_DBG_CALIBRATE, |
781 | "enabling IQ Calibration.\n"); | 761 | "enabling IQ Calibration.\n"); |
782 | } | 762 | } |
783 | 763 | ||
784 | if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) { | 764 | if (ah->supp_cals & TEMP_COMP_CAL) { |
785 | INIT_CAL(&ah->tempCompCalData); | 765 | INIT_CAL(&ah->tempCompCalData); |
786 | INSERT_CAL(ah, &ah->tempCompCalData); | 766 | INSERT_CAL(ah, &ah->tempCompCalData); |
787 | ath_print(common, ATH_DBG_CALIBRATE, | 767 | ath_print(common, ATH_DBG_CALIBRATE, |
@@ -808,7 +788,6 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) | |||
808 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; | 788 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; |
809 | priv_ops->init_cal = ar9003_hw_init_cal; | 789 | priv_ops->init_cal = ar9003_hw_init_cal; |
810 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; | 790 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; |
811 | priv_ops->iscal_supported = ar9003_hw_iscal_supported; | ||
812 | 791 | ||
813 | ops->calibrate = ar9003_hw_calibrate; | 792 | ops->calibrate = ar9003_hw_calibrate; |
814 | } | 793 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 064168909108..02c970819f79 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -333,6 +333,4 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
333 | ar9003_hw_attach_phy_ops(ah); | 333 | ar9003_hw_attach_phy_ops(ah); |
334 | ar9003_hw_attach_calib_ops(ah); | 334 | ar9003_hw_attach_calib_ops(ah); |
335 | ar9003_hw_attach_mac_ops(ah); | 335 | ar9003_hw_attach_mac_ops(ah); |
336 | |||
337 | ath9k_hw_attach_ani_ops_new(ah); | ||
338 | } | 336 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a491854fa38a..efb05599b84c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -747,9 +747,9 @@ static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) | |||
747 | static bool ar9003_hw_ani_control(struct ath_hw *ah, | 747 | static bool ar9003_hw_ani_control(struct ath_hw *ah, |
748 | enum ath9k_ani_cmd cmd, int param) | 748 | enum ath9k_ani_cmd cmd, int param) |
749 | { | 749 | { |
750 | struct ar5416AniState *aniState = ah->curani; | ||
751 | struct ath_common *common = ath9k_hw_common(ah); | 750 | struct ath_common *common = ath9k_hw_common(ah); |
752 | struct ath9k_channel *chan = ah->curchan; | 751 | struct ath9k_channel *chan = ah->curchan; |
752 | struct ar5416AniState *aniState = &chan->ani; | ||
753 | s32 value, value2; | 753 | s32 value, value2; |
754 | 754 | ||
755 | switch (cmd & ah->ani_function) { | 755 | switch (cmd & ah->ani_function) { |
@@ -1005,15 +1005,13 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
1005 | 1005 | ||
1006 | ath_print(common, ATH_DBG_ANI, | 1006 | ath_print(common, ATH_DBG_ANI, |
1007 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | 1007 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " |
1008 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | 1008 | "MRCcck=%s listenTime=%d " |
1009 | "ofdmErrs=%d cckErrs=%d\n", | 1009 | "ofdmErrs=%d cckErrs=%d\n", |
1010 | aniState->spurImmunityLevel, | 1010 | aniState->spurImmunityLevel, |
1011 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1011 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
1012 | aniState->firstepLevel, | 1012 | aniState->firstepLevel, |
1013 | !aniState->mrcCCKOff ? "on" : "off", | 1013 | !aniState->mrcCCKOff ? "on" : "off", |
1014 | aniState->listenTime, | 1014 | aniState->listenTime, |
1015 | aniState->cycleCount, | ||
1016 | aniState->listenTime, | ||
1017 | aniState->ofdmPhyErrCount, | 1015 | aniState->ofdmPhyErrCount, |
1018 | aniState->cckPhyErrCount); | 1016 | aniState->cckPhyErrCount); |
1019 | return true; | 1017 | return true; |
@@ -1067,12 +1065,9 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1067 | struct ath_common *common = ath9k_hw_common(ah); | 1065 | struct ath_common *common = ath9k_hw_common(ah); |
1068 | struct ath9k_channel *chan = ah->curchan; | 1066 | struct ath9k_channel *chan = ah->curchan; |
1069 | struct ath9k_ani_default *iniDef; | 1067 | struct ath9k_ani_default *iniDef; |
1070 | int index; | ||
1071 | u32 val; | 1068 | u32 val; |
1072 | 1069 | ||
1073 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | 1070 | aniState = &ah->curchan->ani; |
1074 | aniState = &ah->ani[index]; | ||
1075 | ah->curani = aniState; | ||
1076 | iniDef = &aniState->iniDef; | 1071 | iniDef = &aniState->iniDef; |
1077 | 1072 | ||
1078 | ath_print(common, ATH_DBG_ANI, | 1073 | ath_print(common, ATH_DBG_ANI, |
@@ -1116,8 +1111,6 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1116 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1111 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1117 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1112 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1118 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; | 1113 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; |
1119 | |||
1120 | aniState->cycleCount = 0; | ||
1121 | } | 1114 | } |
1122 | 1115 | ||
1123 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1116 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
@@ -1232,7 +1225,7 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) | |||
1232 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) | 1225 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) |
1233 | { | 1226 | { |
1234 | struct ath_common *common = ath9k_hw_common(ah); | 1227 | struct ath_common *common = ath9k_hw_common(ah); |
1235 | u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status; | 1228 | u32 status; |
1236 | 1229 | ||
1237 | if (likely(!(common->debug_mask & ATH_DBG_RESET))) | 1230 | if (likely(!(common->debug_mask & ATH_DBG_RESET))) |
1238 | return; | 1231 | return; |
@@ -1261,11 +1254,13 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) | |||
1261 | "** BB mode: BB_gen_controls=0x%08x **\n", | 1254 | "** BB mode: BB_gen_controls=0x%08x **\n", |
1262 | REG_READ(ah, AR_PHY_GEN_CTRL)); | 1255 | REG_READ(ah, AR_PHY_GEN_CTRL)); |
1263 | 1256 | ||
1264 | if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt)) | 1257 | ath9k_hw_update_cycle_counters(ah); |
1258 | #define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles) | ||
1259 | if (ah->cc_delta.cycles) | ||
1265 | ath_print(common, ATH_DBG_RESET, | 1260 | ath_print(common, ATH_DBG_RESET, |
1266 | "** BB busy times: rx_clear=%d%%, " | 1261 | "** BB busy times: rx_clear=%d%%, " |
1267 | "rx_frame=%d%%, tx_frame=%d%% **\n", | 1262 | "rx_frame=%d%%, tx_frame=%d%% **\n", |
1268 | rxc_pcnt, rxf_pcnt, txf_pcnt); | 1263 | PCT(rx_clear), PCT(rx_frame), PCT(tx_frame)); |
1269 | 1264 | ||
1270 | ath_print(common, ATH_DBG_RESET, | 1265 | ath_print(common, ATH_DBG_RESET, |
1271 | "==== BB update: done ====\n\n"); | 1266 | "==== BB update: done ====\n\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 9f8e542ef47e..de2b18ee7f77 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -241,7 +241,6 @@ struct ath_buf { | |||
241 | dma_addr_t bf_daddr; /* physical addr of desc */ | 241 | dma_addr_t bf_daddr; /* physical addr of desc */ |
242 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | 242 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ |
243 | bool bf_stale; | 243 | bool bf_stale; |
244 | bool bf_isnullfunc; | ||
245 | bool bf_tx_aborted; | 244 | bool bf_tx_aborted; |
246 | u16 bf_flags; | 245 | u16 bf_flags; |
247 | struct ath_buf_state bf_state; | 246 | struct ath_buf_state bf_state; |
@@ -349,7 +348,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
349 | u16 tid, u16 *ssn); | 348 | u16 tid, u16 *ssn); |
350 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 349 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
351 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 350 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
352 | void ath9k_enable_ps(struct ath_softc *sc); | ||
353 | 351 | ||
354 | /********/ | 352 | /********/ |
355 | /* VIFs */ | 353 | /* VIFs */ |
@@ -573,8 +571,6 @@ struct ath_ant_comb { | |||
573 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) | 571 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
574 | #define PS_WAIT_FOR_TX_ACK BIT(3) | 572 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
575 | #define PS_BEACON_SYNC BIT(4) | 573 | #define PS_BEACON_SYNC BIT(4) |
576 | #define PS_NULLFUNC_COMPLETED BIT(5) | ||
577 | #define PS_ENABLED BIT(6) | ||
578 | 574 | ||
579 | struct ath_wiphy; | 575 | struct ath_wiphy; |
580 | struct ath_rate_table; | 576 | struct ath_rate_table; |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 67ee5d735cc1..6d509484b5f6 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -186,7 +186,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
186 | return true; | 186 | return true; |
187 | } | 187 | } |
188 | 188 | ||
189 | if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) | 189 | if (!(ah->supp_cals & currCal->calData->calType)) |
190 | return true; | 190 | return true; |
191 | 191 | ||
192 | ath_print(common, ATH_DBG_CALIBRATE, | 192 | ath_print(common, ATH_DBG_CALIBRATE, |
@@ -300,7 +300,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
300 | } | 300 | } |
301 | } | 301 | } |
302 | REGWRITE_BUFFER_FLUSH(ah); | 302 | REGWRITE_BUFFER_FLUSH(ah); |
303 | DISABLE_REGWRITE_BUFFER(ah); | ||
304 | } | 303 | } |
305 | 304 | ||
306 | 305 | ||
@@ -346,34 +345,34 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
346 | struct ieee80211_channel *c = chan->chan; | 345 | struct ieee80211_channel *c = chan->chan; |
347 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 346 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
348 | 347 | ||
349 | if (!caldata) | ||
350 | return false; | ||
351 | |||
352 | chan->channelFlags &= (~CHANNEL_CW_INT); | 348 | chan->channelFlags &= (~CHANNEL_CW_INT); |
353 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 349 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
354 | ath_print(common, ATH_DBG_CALIBRATE, | 350 | ath_print(common, ATH_DBG_CALIBRATE, |
355 | "NF did not complete in calibration window\n"); | 351 | "NF did not complete in calibration window\n"); |
356 | nf = 0; | ||
357 | caldata->rawNoiseFloor = nf; | ||
358 | return false; | 352 | return false; |
359 | } else { | 353 | } |
360 | ath9k_hw_do_getnf(ah, nfarray); | 354 | |
361 | ath9k_hw_nf_sanitize(ah, nfarray); | 355 | ath9k_hw_do_getnf(ah, nfarray); |
362 | nf = nfarray[0]; | 356 | ath9k_hw_nf_sanitize(ah, nfarray); |
363 | if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) | 357 | nf = nfarray[0]; |
364 | && nf > nfThresh) { | 358 | if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) |
365 | ath_print(common, ATH_DBG_CALIBRATE, | 359 | && nf > nfThresh) { |
366 | "noise floor failed detected; " | 360 | ath_print(common, ATH_DBG_CALIBRATE, |
367 | "detected %d, threshold %d\n", | 361 | "noise floor failed detected; " |
368 | nf, nfThresh); | 362 | "detected %d, threshold %d\n", |
369 | chan->channelFlags |= CHANNEL_CW_INT; | 363 | nf, nfThresh); |
370 | } | 364 | chan->channelFlags |= CHANNEL_CW_INT; |
365 | } | ||
366 | |||
367 | if (!caldata) { | ||
368 | chan->noisefloor = nf; | ||
369 | return false; | ||
371 | } | 370 | } |
372 | 371 | ||
373 | h = caldata->nfCalHist; | 372 | h = caldata->nfCalHist; |
374 | caldata->nfcal_pending = false; | 373 | caldata->nfcal_pending = false; |
375 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); | 374 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
376 | caldata->rawNoiseFloor = h[0].privNF; | 375 | chan->noisefloor = h[0].privNF; |
377 | return true; | 376 | return true; |
378 | } | 377 | } |
379 | 378 | ||
@@ -401,10 +400,10 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
401 | 400 | ||
402 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 401 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) |
403 | { | 402 | { |
404 | if (!ah->caldata || !ah->caldata->rawNoiseFloor) | 403 | if (!ah->curchan || !ah->curchan->noisefloor) |
405 | return ath9k_hw_get_default_nf(ah, chan); | 404 | return ath9k_hw_get_default_nf(ah, chan); |
406 | 405 | ||
407 | return ah->caldata->rawNoiseFloor; | 406 | return ah->curchan->noisefloor; |
408 | } | 407 | } |
409 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 408 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
410 | 409 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 5b053a6260b2..b8973eb8d858 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -58,14 +58,6 @@ struct ar5416IniArray { | |||
58 | } \ | 58 | } \ |
59 | } while (0) | 59 | } while (0) |
60 | 60 | ||
61 | enum ath9k_cal_types { | ||
62 | ADC_DC_INIT_CAL = 0x1, | ||
63 | ADC_GAIN_CAL = 0x2, | ||
64 | ADC_DC_CAL = 0x4, | ||
65 | IQ_MISMATCH_CAL = 0x8, | ||
66 | TEMP_COMP_CAL = 0x10, | ||
67 | }; | ||
68 | |||
69 | enum ath9k_cal_state { | 61 | enum ath9k_cal_state { |
70 | CAL_INACTIVE, | 62 | CAL_INACTIVE, |
71 | CAL_WAITING, | 63 | CAL_WAITING, |
@@ -80,7 +72,7 @@ enum ath9k_cal_state { | |||
80 | #define PER_MAX_LOG_COUNT 10 | 72 | #define PER_MAX_LOG_COUNT 10 |
81 | 73 | ||
82 | struct ath9k_percal_data { | 74 | struct ath9k_percal_data { |
83 | enum ath9k_cal_types calType; | 75 | u32 calType; |
84 | u32 calNumSamples; | 76 | u32 calNumSamples; |
85 | u32 calCountMax; | 77 | u32 calCountMax; |
86 | void (*calCollect) (struct ath_hw *); | 78 | void (*calCollect) (struct ath_hw *); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index d65a896a421d..74a4570dc87f 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -488,6 +488,8 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
488 | size_t count, loff_t *ppos) | 488 | size_t count, loff_t *ppos) |
489 | { | 489 | { |
490 | struct ath_softc *sc = file->private_data; | 490 | struct ath_softc *sc = file->private_data; |
491 | struct ath_wiphy *aphy = sc->pri_wiphy; | ||
492 | struct ieee80211_channel *chan = aphy->hw->conf.channel; | ||
491 | char buf[512]; | 493 | char buf[512]; |
492 | unsigned int len = 0; | 494 | unsigned int len = 0; |
493 | int i; | 495 | int i; |
@@ -498,7 +500,8 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
498 | "primary: %s (%s chan=%d ht=%d)\n", | 500 | "primary: %s (%s chan=%d ht=%d)\n", |
499 | wiphy_name(sc->pri_wiphy->hw->wiphy), | 501 | wiphy_name(sc->pri_wiphy->hw->wiphy), |
500 | ath_wiphy_state_str(sc->pri_wiphy->state), | 502 | ath_wiphy_state_str(sc->pri_wiphy->state), |
501 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); | 503 | ieee80211_frequency_to_channel(chan->center_freq), |
504 | aphy->chan_is_ht); | ||
502 | 505 | ||
503 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | 506 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); |
504 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | 507 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); |
@@ -545,11 +548,13 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
545 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 548 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
546 | if (aphy == NULL) | 549 | if (aphy == NULL) |
547 | continue; | 550 | continue; |
551 | chan = aphy->hw->conf.channel; | ||
548 | len += snprintf(buf + len, sizeof(buf) - len, | 552 | len += snprintf(buf + len, sizeof(buf) - len, |
549 | "secondary: %s (%s chan=%d ht=%d)\n", | 553 | "secondary: %s (%s chan=%d ht=%d)\n", |
550 | wiphy_name(aphy->hw->wiphy), | 554 | wiphy_name(aphy->hw->wiphy), |
551 | ath_wiphy_state_str(aphy->state), | 555 | ath_wiphy_state_str(aphy->state), |
552 | aphy->chan_idx, aphy->chan_is_ht); | 556 | ieee80211_frequency_to_channel(chan->center_freq), |
557 | aphy->chan_is_ht); | ||
553 | } | 558 | } |
554 | if (len > sizeof(buf)) | 559 | if (len > sizeof(buf)) |
555 | len = sizeof(buf); | 560 | len = sizeof(buf); |
@@ -696,6 +701,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
696 | PR("DESC CFG Error: ", desc_cfg_err); | 701 | PR("DESC CFG Error: ", desc_cfg_err); |
697 | PR("DATA Underrun: ", data_underrun); | 702 | PR("DATA Underrun: ", data_underrun); |
698 | PR("DELIM Underrun: ", delim_underrun); | 703 | PR("DELIM Underrun: ", delim_underrun); |
704 | PR("TX-Pkts-All: ", tx_pkts_all); | ||
705 | PR("TX-Bytes-All: ", tx_bytes_all); | ||
699 | 706 | ||
700 | if (len > size) | 707 | if (len > size) |
701 | len = size; | 708 | len = size; |
@@ -709,6 +716,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
709 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 716 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
710 | struct ath_buf *bf, struct ath_tx_status *ts) | 717 | struct ath_buf *bf, struct ath_tx_status *ts) |
711 | { | 718 | { |
719 | TX_STAT_INC(txq->axq_qnum, tx_pkts_all); | ||
720 | sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len; | ||
721 | |||
712 | if (bf_isampdu(bf)) { | 722 | if (bf_isampdu(bf)) { |
713 | if (bf_isxretried(bf)) | 723 | if (bf_isxretried(bf)) |
714 | TX_STAT_INC(txq->axq_qnum, a_xretries); | 724 | TX_STAT_INC(txq->axq_qnum, a_xretries); |
@@ -803,6 +813,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
803 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | 813 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
804 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | 814 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); |
805 | 815 | ||
816 | len += snprintf(buf + len, size - len, | ||
817 | "%18s : %10u\n", "RX-Pkts-All", | ||
818 | sc->debug.stats.rxstats.rx_pkts_all); | ||
819 | len += snprintf(buf + len, size - len, | ||
820 | "%18s : %10u\n", "RX-Bytes-All", | ||
821 | sc->debug.stats.rxstats.rx_bytes_all); | ||
822 | |||
806 | if (len > size) | 823 | if (len > size) |
807 | len = size; | 824 | len = size; |
808 | 825 | ||
@@ -821,6 +838,9 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
821 | 838 | ||
822 | u32 phyerr; | 839 | u32 phyerr; |
823 | 840 | ||
841 | RX_STAT_INC(rx_pkts_all); | ||
842 | sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen; | ||
843 | |||
824 | if (rs->rs_status & ATH9K_RXERR_CRC) | 844 | if (rs->rs_status & ATH9K_RXERR_CRC) |
825 | RX_STAT_INC(crc_err); | 845 | RX_STAT_INC(crc_err); |
826 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) | 846 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5d21704e87ff..822b6f3f23c5 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -89,6 +89,10 @@ struct ath_rc_stats { | |||
89 | 89 | ||
90 | /** | 90 | /** |
91 | * struct ath_tx_stats - Statistics about TX | 91 | * struct ath_tx_stats - Statistics about TX |
92 | * @tx_pkts_all: No. of total frames transmitted, including ones that | ||
93 | may have had errors. | ||
94 | * @tx_bytes_all: No. of total bytes transmitted, including ones that | ||
95 | may have had errors. | ||
92 | * @queued: Total MPDUs (non-aggr) queued | 96 | * @queued: Total MPDUs (non-aggr) queued |
93 | * @completed: Total MPDUs (non-aggr) completed | 97 | * @completed: Total MPDUs (non-aggr) completed |
94 | * @a_aggr: Total no. of aggregates queued | 98 | * @a_aggr: Total no. of aggregates queued |
@@ -107,6 +111,8 @@ struct ath_rc_stats { | |||
107 | * @delim_urn: TX delimiter underrun errors | 111 | * @delim_urn: TX delimiter underrun errors |
108 | */ | 112 | */ |
109 | struct ath_tx_stats { | 113 | struct ath_tx_stats { |
114 | u32 tx_pkts_all; | ||
115 | u32 tx_bytes_all; | ||
110 | u32 queued; | 116 | u32 queued; |
111 | u32 completed; | 117 | u32 completed; |
112 | u32 a_aggr; | 118 | u32 a_aggr; |
@@ -124,6 +130,10 @@ struct ath_tx_stats { | |||
124 | 130 | ||
125 | /** | 131 | /** |
126 | * struct ath_rx_stats - RX Statistics | 132 | * struct ath_rx_stats - RX Statistics |
133 | * @rx_pkts_all: No. of total frames received, including ones that | ||
134 | may have had errors. | ||
135 | * @rx_bytes_all: No. of total bytes received, including ones that | ||
136 | may have had errors. | ||
127 | * @crc_err: No. of frames with incorrect CRC value | 137 | * @crc_err: No. of frames with incorrect CRC value |
128 | * @decrypt_crc_err: No. of frames whose CRC check failed after | 138 | * @decrypt_crc_err: No. of frames whose CRC check failed after |
129 | decryption process completed | 139 | decryption process completed |
@@ -136,6 +146,8 @@ struct ath_tx_stats { | |||
136 | * @phy_err_stats: Individual PHY error statistics | 146 | * @phy_err_stats: Individual PHY error statistics |
137 | */ | 147 | */ |
138 | struct ath_rx_stats { | 148 | struct ath_rx_stats { |
149 | u32 rx_pkts_all; | ||
150 | u32 rx_bytes_all; | ||
139 | u32 crc_err; | 151 | u32 crc_err; |
140 | u32 decrypt_crc_err; | 152 | u32 decrypt_crc_err; |
141 | u32 phy_err; | 153 | u32 phy_err; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index d6eed1f02e84..4fa4d8e28c64 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -179,6 +179,9 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
179 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 179 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
180 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | 180 | struct modal_eep_4k_header *pModal = &eep->modalHeader; |
181 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | 181 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; |
182 | u16 ver_minor; | ||
183 | |||
184 | ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
182 | 185 | ||
183 | switch (param) { | 186 | switch (param) { |
184 | case EEP_NFTHRESH_2: | 187 | case EEP_NFTHRESH_2: |
@@ -204,7 +207,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
204 | case EEP_DB_2: | 207 | case EEP_DB_2: |
205 | return pModal->db1_1; | 208 | return pModal->db1_1; |
206 | case EEP_MINOR_REV: | 209 | case EEP_MINOR_REV: |
207 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | 210 | return ver_minor; |
208 | case EEP_TX_MASK: | 211 | case EEP_TX_MASK: |
209 | return pBase->txMask; | 212 | return pBase->txMask; |
210 | case EEP_RX_MASK: | 213 | case EEP_RX_MASK: |
@@ -217,6 +220,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
217 | return pModal->version; | 220 | return pModal->version; |
218 | case EEP_ANT_DIV_CTL1: | 221 | case EEP_ANT_DIV_CTL1: |
219 | return pModal->antdiv_ctl1; | 222 | return pModal->antdiv_ctl1; |
223 | case EEP_TXGAIN_TYPE: | ||
224 | if (ver_minor >= AR5416_EEP_MINOR_VER_19) | ||
225 | return pBase->txGainType; | ||
226 | else | ||
227 | return AR5416_EEP_TXGAIN_ORIGINAL; | ||
220 | default: | 228 | default: |
221 | return 0; | 229 | return 0; |
222 | } | 230 | } |
@@ -500,7 +508,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
500 | } | 508 | } |
501 | 509 | ||
502 | REGWRITE_BUFFER_FLUSH(ah); | 510 | REGWRITE_BUFFER_FLUSH(ah); |
503 | DISABLE_REGWRITE_BUFFER(ah); | ||
504 | } | 511 | } |
505 | } | 512 | } |
506 | 513 | ||
@@ -832,7 +839,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
832 | } | 839 | } |
833 | 840 | ||
834 | REGWRITE_BUFFER_FLUSH(ah); | 841 | REGWRITE_BUFFER_FLUSH(ah); |
835 | DISABLE_REGWRITE_BUFFER(ah); | ||
836 | } | 842 | } |
837 | 843 | ||
838 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | 844 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index b100db2766cf..bbb54bc28a44 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -380,15 +380,6 @@ static void ath9k_enable_regwrite_buffer(void *hw_priv) | |||
380 | atomic_inc(&priv->wmi->mwrite_cnt); | 380 | atomic_inc(&priv->wmi->mwrite_cnt); |
381 | } | 381 | } |
382 | 382 | ||
383 | static void ath9k_disable_regwrite_buffer(void *hw_priv) | ||
384 | { | ||
385 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
386 | struct ath_common *common = ath9k_hw_common(ah); | ||
387 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
388 | |||
389 | atomic_dec(&priv->wmi->mwrite_cnt); | ||
390 | } | ||
391 | |||
392 | static void ath9k_regwrite_flush(void *hw_priv) | 383 | static void ath9k_regwrite_flush(void *hw_priv) |
393 | { | 384 | { |
394 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | 385 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
@@ -397,6 +388,8 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
397 | u32 rsp_status; | 388 | u32 rsp_status; |
398 | int r; | 389 | int r; |
399 | 390 | ||
391 | atomic_dec(&priv->wmi->mwrite_cnt); | ||
392 | |||
400 | mutex_lock(&priv->wmi->multi_write_mutex); | 393 | mutex_lock(&priv->wmi->multi_write_mutex); |
401 | 394 | ||
402 | if (priv->wmi->multi_write_idx) { | 395 | if (priv->wmi->multi_write_idx) { |
@@ -420,7 +413,6 @@ static const struct ath_ops ath9k_common_ops = { | |||
420 | .read = ath9k_regread, | 413 | .read = ath9k_regread, |
421 | .write = ath9k_regwrite, | 414 | .write = ath9k_regwrite, |
422 | .enable_write_buffer = ath9k_enable_regwrite_buffer, | 415 | .enable_write_buffer = ath9k_enable_regwrite_buffer, |
423 | .disable_write_buffer = ath9k_disable_regwrite_buffer, | ||
424 | .write_flush = ath9k_regwrite_flush, | 416 | .write_flush = ath9k_regwrite_flush, |
425 | }; | 417 | }; |
426 | 418 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 5124d04b240b..f12591f5d02a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -760,23 +760,12 @@ void ath9k_ani_work(struct work_struct *work) | |||
760 | ath9k_hw_ani_monitor(ah, ah->curchan); | 760 | ath9k_hw_ani_monitor(ah, ah->curchan); |
761 | 761 | ||
762 | /* Perform calibration if necessary */ | 762 | /* Perform calibration if necessary */ |
763 | if (longcal || shortcal) { | 763 | if (longcal || shortcal) |
764 | common->ani.caldone = | 764 | common->ani.caldone = |
765 | ath9k_hw_calibrate(ah, ah->curchan, | 765 | ath9k_hw_calibrate(ah, ah->curchan, |
766 | common->rx_chainmask, | 766 | common->rx_chainmask, |
767 | longcal); | 767 | longcal); |
768 | 768 | ||
769 | if (longcal) | ||
770 | common->ani.noise_floor = | ||
771 | ath9k_hw_getchan_noise(ah, ah->curchan); | ||
772 | |||
773 | ath_print(common, ATH_DBG_ANI, | ||
774 | " calibrate chan %u/%x nf: %d\n", | ||
775 | ah->curchan->channel, | ||
776 | ah->curchan->channelFlags, | ||
777 | common->ani.noise_floor); | ||
778 | } | ||
779 | |||
780 | ath9k_htc_ps_restore(priv); | 769 | ath9k_htc_ps_restore(priv); |
781 | } | 770 | } |
782 | 771 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index ffecbadaea4a..0a4ad348b699 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -128,17 +128,6 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); | 128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline void ath9k_hw_procmibevent(struct ath_hw *ah) | ||
132 | { | ||
133 | ath9k_hw_ops(ah)->ani_proc_mib_event(ah); | ||
134 | } | ||
135 | |||
136 | static inline void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
137 | struct ath9k_channel *chan) | ||
138 | { | ||
139 | ath9k_hw_ops(ah)->ani_monitor(ah, chan); | ||
140 | } | ||
141 | |||
142 | /* Private hardware call ops */ | 131 | /* Private hardware call ops */ |
143 | 132 | ||
144 | /* PHY ops */ | 133 | /* PHY ops */ |
@@ -276,15 +265,4 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah, | |||
276 | ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); | 265 | ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); |
277 | } | 266 | } |
278 | 267 | ||
279 | static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, | ||
280 | enum ath9k_cal_types calType) | ||
281 | { | ||
282 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); | ||
283 | } | ||
284 | |||
285 | static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | ||
286 | { | ||
287 | ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning); | ||
288 | } | ||
289 | |||
290 | #endif /* ATH9K_HW_OPS_H */ | 268 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 25ed65ac992c..05e9935ef160 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -299,7 +299,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) | |||
299 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 299 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
300 | 300 | ||
301 | REGWRITE_BUFFER_FLUSH(ah); | 301 | REGWRITE_BUFFER_FLUSH(ah); |
302 | DISABLE_REGWRITE_BUFFER(ah); | ||
303 | } | 302 | } |
304 | 303 | ||
305 | /* This should work for all families including legacy */ | 304 | /* This should work for all families including legacy */ |
@@ -371,10 +370,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
371 | ah->config.pcie_clock_req = 0; | 370 | ah->config.pcie_clock_req = 0; |
372 | ah->config.pcie_waen = 0; | 371 | ah->config.pcie_waen = 0; |
373 | ah->config.analog_shiftreg = 1; | 372 | ah->config.analog_shiftreg = 1; |
374 | ah->config.ofdm_trig_low = 200; | ||
375 | ah->config.ofdm_trig_high = 500; | ||
376 | ah->config.cck_trig_high = 200; | ||
377 | ah->config.cck_trig_low = 100; | ||
378 | ah->config.enable_ani = true; | 373 | ah->config.enable_ani = true; |
379 | 374 | ||
380 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 375 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
@@ -676,7 +671,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) | |||
676 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); | 671 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); |
677 | 672 | ||
678 | REGWRITE_BUFFER_FLUSH(ah); | 673 | REGWRITE_BUFFER_FLUSH(ah); |
679 | DISABLE_REGWRITE_BUFFER(ah); | ||
680 | } | 674 | } |
681 | 675 | ||
682 | static void ath9k_hw_init_pll(struct ath_hw *ah, | 676 | static void ath9k_hw_init_pll(struct ath_hw *ah, |
@@ -741,7 +735,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
741 | } | 735 | } |
742 | 736 | ||
743 | REGWRITE_BUFFER_FLUSH(ah); | 737 | REGWRITE_BUFFER_FLUSH(ah); |
744 | DISABLE_REGWRITE_BUFFER(ah); | ||
745 | 738 | ||
746 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 739 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
747 | REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); | 740 | REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); |
@@ -885,7 +878,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
885 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); | 878 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); |
886 | 879 | ||
887 | REGWRITE_BUFFER_FLUSH(ah); | 880 | REGWRITE_BUFFER_FLUSH(ah); |
888 | DISABLE_REGWRITE_BUFFER(ah); | ||
889 | 881 | ||
890 | /* | 882 | /* |
891 | * Restore TX Trigger Level to its pre-reset value. | 883 | * Restore TX Trigger Level to its pre-reset value. |
@@ -933,7 +925,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
933 | } | 925 | } |
934 | 926 | ||
935 | REGWRITE_BUFFER_FLUSH(ah); | 927 | REGWRITE_BUFFER_FLUSH(ah); |
936 | DISABLE_REGWRITE_BUFFER(ah); | ||
937 | 928 | ||
938 | if (AR_SREV_9300_20_OR_LATER(ah)) | 929 | if (AR_SREV_9300_20_OR_LATER(ah)) |
939 | ath9k_hw_reset_txstatus_ring(ah); | 930 | ath9k_hw_reset_txstatus_ring(ah); |
@@ -1031,7 +1022,6 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1031 | REG_WRITE(ah, AR_RTC_RC, rst_flags); | 1022 | REG_WRITE(ah, AR_RTC_RC, rst_flags); |
1032 | 1023 | ||
1033 | REGWRITE_BUFFER_FLUSH(ah); | 1024 | REGWRITE_BUFFER_FLUSH(ah); |
1034 | DISABLE_REGWRITE_BUFFER(ah); | ||
1035 | 1025 | ||
1036 | udelay(50); | 1026 | udelay(50); |
1037 | 1027 | ||
@@ -1070,7 +1060,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1070 | udelay(2); | 1060 | udelay(2); |
1071 | 1061 | ||
1072 | REGWRITE_BUFFER_FLUSH(ah); | 1062 | REGWRITE_BUFFER_FLUSH(ah); |
1073 | DISABLE_REGWRITE_BUFFER(ah); | ||
1074 | 1063 | ||
1075 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 1064 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
1076 | udelay(2); | 1065 | udelay(2); |
@@ -1239,7 +1228,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1239 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1228 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
1240 | return -EIO; | 1229 | return -EIO; |
1241 | 1230 | ||
1242 | if (curchan && !ah->chip_fullsleep && ah->caldata) | 1231 | if (curchan && !ah->chip_fullsleep) |
1243 | ath9k_hw_getnf(ah, curchan); | 1232 | ath9k_hw_getnf(ah, curchan); |
1244 | 1233 | ||
1245 | ah->caldata = caldata; | 1234 | ah->caldata = caldata; |
@@ -1374,7 +1363,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1374 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | 1363 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); |
1375 | 1364 | ||
1376 | REGWRITE_BUFFER_FLUSH(ah); | 1365 | REGWRITE_BUFFER_FLUSH(ah); |
1377 | DISABLE_REGWRITE_BUFFER(ah); | ||
1378 | 1366 | ||
1379 | r = ath9k_hw_rf_set_freq(ah, chan); | 1367 | r = ath9k_hw_rf_set_freq(ah, chan); |
1380 | if (r) | 1368 | if (r) |
@@ -1386,7 +1374,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1386 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | 1374 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); |
1387 | 1375 | ||
1388 | REGWRITE_BUFFER_FLUSH(ah); | 1376 | REGWRITE_BUFFER_FLUSH(ah); |
1389 | DISABLE_REGWRITE_BUFFER(ah); | ||
1390 | 1377 | ||
1391 | ah->intr_txqs = 0; | 1378 | ah->intr_txqs = 0; |
1392 | for (i = 0; i < ah->caps.total_queues; i++) | 1379 | for (i = 0; i < ah->caps.total_queues; i++) |
@@ -1434,7 +1421,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1434 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); | 1421 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); |
1435 | 1422 | ||
1436 | REGWRITE_BUFFER_FLUSH(ah); | 1423 | REGWRITE_BUFFER_FLUSH(ah); |
1437 | DISABLE_REGWRITE_BUFFER(ah); | ||
1438 | 1424 | ||
1439 | /* | 1425 | /* |
1440 | * For big endian systems turn on swapping for descriptors | 1426 | * For big endian systems turn on swapping for descriptors |
@@ -1684,7 +1670,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
1684 | REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); | 1670 | REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); |
1685 | 1671 | ||
1686 | REGWRITE_BUFFER_FLUSH(ah); | 1672 | REGWRITE_BUFFER_FLUSH(ah); |
1687 | DISABLE_REGWRITE_BUFFER(ah); | ||
1688 | 1673 | ||
1689 | beacon_period &= ~ATH9K_BEACON_ENA; | 1674 | beacon_period &= ~ATH9K_BEACON_ENA; |
1690 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { | 1675 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { |
@@ -1712,7 +1697,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
1712 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | 1697 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); |
1713 | 1698 | ||
1714 | REGWRITE_BUFFER_FLUSH(ah); | 1699 | REGWRITE_BUFFER_FLUSH(ah); |
1715 | DISABLE_REGWRITE_BUFFER(ah); | ||
1716 | 1700 | ||
1717 | REG_RMW_FIELD(ah, AR_RSSI_THR, | 1701 | REG_RMW_FIELD(ah, AR_RSSI_THR, |
1718 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); | 1702 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); |
@@ -1758,7 +1742,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
1758 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); | 1742 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); |
1759 | 1743 | ||
1760 | REGWRITE_BUFFER_FLUSH(ah); | 1744 | REGWRITE_BUFFER_FLUSH(ah); |
1761 | DISABLE_REGWRITE_BUFFER(ah); | ||
1762 | 1745 | ||
1763 | REG_SET_BIT(ah, AR_TIMER_MODE, | 1746 | REG_SET_BIT(ah, AR_TIMER_MODE, |
1764 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | | 1747 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | |
@@ -2176,7 +2159,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) | |||
2176 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); | 2159 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); |
2177 | 2160 | ||
2178 | REGWRITE_BUFFER_FLUSH(ah); | 2161 | REGWRITE_BUFFER_FLUSH(ah); |
2179 | DISABLE_REGWRITE_BUFFER(ah); | ||
2180 | } | 2162 | } |
2181 | EXPORT_SYMBOL(ath9k_hw_setrxfilter); | 2163 | EXPORT_SYMBOL(ath9k_hw_setrxfilter); |
2182 | 2164 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index df47f792cf4e..87627dd63463 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -70,19 +70,13 @@ | |||
70 | 70 | ||
71 | #define ENABLE_REGWRITE_BUFFER(_ah) \ | 71 | #define ENABLE_REGWRITE_BUFFER(_ah) \ |
72 | do { \ | 72 | do { \ |
73 | if (AR_SREV_9271(_ah)) \ | 73 | if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ |
74 | ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ | 74 | ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ |
75 | } while (0) | 75 | } while (0) |
76 | 76 | ||
77 | #define DISABLE_REGWRITE_BUFFER(_ah) \ | ||
78 | do { \ | ||
79 | if (AR_SREV_9271(_ah)) \ | ||
80 | ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \ | ||
81 | } while (0) | ||
82 | |||
83 | #define REGWRITE_BUFFER_FLUSH(_ah) \ | 77 | #define REGWRITE_BUFFER_FLUSH(_ah) \ |
84 | do { \ | 78 | do { \ |
85 | if (AR_SREV_9271(_ah)) \ | 79 | if (ath9k_hw_common(_ah)->ops->write_flush) \ |
86 | ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ | 80 | ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ |
87 | } while (0) | 81 | } while (0) |
88 | 82 | ||
@@ -342,7 +336,6 @@ struct ath9k_hw_cal_data { | |||
342 | int32_t CalValid; | 336 | int32_t CalValid; |
343 | int8_t iCoff; | 337 | int8_t iCoff; |
344 | int8_t qCoff; | 338 | int8_t qCoff; |
345 | int16_t rawNoiseFloor; | ||
346 | bool paprd_done; | 339 | bool paprd_done; |
347 | bool nfcal_pending; | 340 | bool nfcal_pending; |
348 | bool nfcal_interference; | 341 | bool nfcal_interference; |
@@ -353,9 +346,11 @@ struct ath9k_hw_cal_data { | |||
353 | 346 | ||
354 | struct ath9k_channel { | 347 | struct ath9k_channel { |
355 | struct ieee80211_channel *chan; | 348 | struct ieee80211_channel *chan; |
349 | struct ar5416AniState ani; | ||
356 | u16 channel; | 350 | u16 channel; |
357 | u32 channelFlags; | 351 | u32 channelFlags; |
358 | u32 chanmode; | 352 | u32 chanmode; |
353 | s16 noisefloor; | ||
359 | }; | 354 | }; |
360 | 355 | ||
361 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 356 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -514,14 +509,6 @@ struct ath_hw_antcomb_conf { | |||
514 | * @setup_calibration: set up calibration | 509 | * @setup_calibration: set up calibration |
515 | * @iscal_supported: used to query if a type of calibration is supported | 510 | * @iscal_supported: used to query if a type of calibration is supported |
516 | * | 511 | * |
517 | * @ani_reset: reset ANI parameters to default values | ||
518 | * @ani_lower_immunity: lower the noise immunity level. The level controls | ||
519 | * the power-based packet detection on hardware. If a power jump is | ||
520 | * detected the adapter takes it as an indication that a packet has | ||
521 | * arrived. The level ranges from 0-5. Each level corresponds to a | ||
522 | * few dB more of noise immunity. If you have a strong time-varying | ||
523 | * interference that is causing false detections (OFDM timing errors or | ||
524 | * CCK timing errors) the level can be increased. | ||
525 | * @ani_cache_ini_regs: cache the values for ANI from the initial | 512 | * @ani_cache_ini_regs: cache the values for ANI from the initial |
526 | * register settings through the register initialization. | 513 | * register settings through the register initialization. |
527 | */ | 514 | */ |
@@ -535,8 +522,6 @@ struct ath_hw_private_ops { | |||
535 | bool (*macversion_supported)(u32 macversion); | 522 | bool (*macversion_supported)(u32 macversion); |
536 | void (*setup_calibration)(struct ath_hw *ah, | 523 | void (*setup_calibration)(struct ath_hw *ah, |
537 | struct ath9k_cal_list *currCal); | 524 | struct ath9k_cal_list *currCal); |
538 | bool (*iscal_supported)(struct ath_hw *ah, | ||
539 | enum ath9k_cal_types calType); | ||
540 | 525 | ||
541 | /* PHY ops */ | 526 | /* PHY ops */ |
542 | int (*rf_set_freq)(struct ath_hw *ah, | 527 | int (*rf_set_freq)(struct ath_hw *ah, |
@@ -568,8 +553,6 @@ struct ath_hw_private_ops { | |||
568 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); | 553 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); |
569 | 554 | ||
570 | /* ANI */ | 555 | /* ANI */ |
571 | void (*ani_reset)(struct ath_hw *ah, bool is_scanning); | ||
572 | void (*ani_lower_immunity)(struct ath_hw *ah); | ||
573 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | 556 | void (*ani_cache_ini_regs)(struct ath_hw *ah); |
574 | }; | 557 | }; |
575 | 558 | ||
@@ -581,11 +564,6 @@ struct ath_hw_private_ops { | |||
581 | * | 564 | * |
582 | * @config_pci_powersave: | 565 | * @config_pci_powersave: |
583 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC | 566 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC |
584 | * | ||
585 | * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI | ||
586 | * thresholds being reached or having overflowed. | ||
587 | * @ani_monitor: called periodically by the core driver to collect | ||
588 | * MIB stats and adjust ANI if specific thresholds have been reached. | ||
589 | */ | 567 | */ |
590 | struct ath_hw_ops { | 568 | struct ath_hw_ops { |
591 | void (*config_pci_powersave)(struct ath_hw *ah, | 569 | void (*config_pci_powersave)(struct ath_hw *ah, |
@@ -626,9 +604,6 @@ struct ath_hw_ops { | |||
626 | u32 burstDuration); | 604 | u32 burstDuration); |
627 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, | 605 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, |
628 | u32 vmf); | 606 | u32 vmf); |
629 | |||
630 | void (*ani_proc_mib_event)(struct ath_hw *ah); | ||
631 | void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); | ||
632 | }; | 607 | }; |
633 | 608 | ||
634 | struct ath_nf_limits { | 609 | struct ath_nf_limits { |
@@ -689,10 +664,9 @@ struct ath_hw { | |||
689 | u32 atim_window; | 664 | u32 atim_window; |
690 | 665 | ||
691 | /* Calibration */ | 666 | /* Calibration */ |
692 | enum ath9k_cal_types supp_cals; | 667 | u32 supp_cals; |
693 | struct ath9k_cal_list iq_caldata; | 668 | struct ath9k_cal_list iq_caldata; |
694 | struct ath9k_cal_list adcgain_caldata; | 669 | struct ath9k_cal_list adcgain_caldata; |
695 | struct ath9k_cal_list adcdc_calinitdata; | ||
696 | struct ath9k_cal_list adcdc_caldata; | 670 | struct ath9k_cal_list adcdc_caldata; |
697 | struct ath9k_cal_list tempCompCalData; | 671 | struct ath9k_cal_list tempCompCalData; |
698 | struct ath9k_cal_list *cal_list; | 672 | struct ath9k_cal_list *cal_list; |
@@ -761,13 +735,13 @@ struct ath_hw { | |||
761 | /* ANI */ | 735 | /* ANI */ |
762 | u32 proc_phyerr; | 736 | u32 proc_phyerr; |
763 | u32 aniperiod; | 737 | u32 aniperiod; |
764 | struct ar5416AniState *curani; | ||
765 | struct ar5416AniState ani[255]; | ||
766 | int totalSizeDesired[5]; | 738 | int totalSizeDesired[5]; |
767 | int coarse_high[5]; | 739 | int coarse_high[5]; |
768 | int coarse_low[5]; | 740 | int coarse_low[5]; |
769 | int firpwr[5]; | 741 | int firpwr[5]; |
770 | enum ath9k_ani_cmd ani_function; | 742 | enum ath9k_ani_cmd ani_function; |
743 | struct ath_cycle_counters cc, cc_delta; | ||
744 | int32_t listen_time; | ||
771 | 745 | ||
772 | /* Bluetooth coexistance */ | 746 | /* Bluetooth coexistance */ |
773 | struct ath_btcoex_hw btcoex_hw; | 747 | struct ath_btcoex_hw btcoex_hw; |
@@ -988,8 +962,9 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | |||
988 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. | 962 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. |
989 | */ | 963 | */ |
990 | extern int modparam_force_new_ani; | 964 | extern int modparam_force_new_ani; |
991 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); | 965 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); |
992 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah); | 966 | void ath9k_hw_proc_mib_event(struct ath_hw *ah); |
967 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); | ||
993 | 968 | ||
994 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 | 969 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 |
995 | #define ATH_PCIE_CAP_LINK_L0S 1 | 970 | #define ATH_PCIE_CAP_LINK_L0S 1 |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index de3393867e37..d76003c06fe4 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | |||
56 | * on 5 MHz steps, we support the channels which we know | 56 | * on 5 MHz steps, we support the channels which we know |
57 | * we have calibration data for all cards though to make | 57 | * we have calibration data for all cards though to make |
58 | * this static */ | 58 | * this static */ |
59 | static struct ieee80211_channel ath9k_2ghz_chantable[] = { | 59 | static const struct ieee80211_channel ath9k_2ghz_chantable[] = { |
60 | CHAN2G(2412, 0), /* Channel 1 */ | 60 | CHAN2G(2412, 0), /* Channel 1 */ |
61 | CHAN2G(2417, 1), /* Channel 2 */ | 61 | CHAN2G(2417, 1), /* Channel 2 */ |
62 | CHAN2G(2422, 2), /* Channel 3 */ | 62 | CHAN2G(2422, 2), /* Channel 3 */ |
@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = { | |||
77 | * on 5 MHz steps, we support the channels which we know | 77 | * on 5 MHz steps, we support the channels which we know |
78 | * we have calibration data for all cards though to make | 78 | * we have calibration data for all cards though to make |
79 | * this static */ | 79 | * this static */ |
80 | static struct ieee80211_channel ath9k_5ghz_chantable[] = { | 80 | static const struct ieee80211_channel ath9k_5ghz_chantable[] = { |
81 | /* _We_ call this UNII 1 */ | 81 | /* _We_ call this UNII 1 */ |
82 | CHAN5G(5180, 14), /* Channel 36 */ | 82 | CHAN5G(5180, 14), /* Channel 36 */ |
83 | CHAN5G(5200, 15), /* Channel 40 */ | 83 | CHAN5G(5200, 15), /* Channel 40 */ |
@@ -477,10 +477,17 @@ err: | |||
477 | return -EIO; | 477 | return -EIO; |
478 | } | 478 | } |
479 | 479 | ||
480 | static void ath9k_init_channels_rates(struct ath_softc *sc) | 480 | static int ath9k_init_channels_rates(struct ath_softc *sc) |
481 | { | 481 | { |
482 | void *channels; | ||
483 | |||
482 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { | 484 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { |
483 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; | 485 | channels = kmemdup(ath9k_2ghz_chantable, |
486 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); | ||
487 | if (!channels) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; | ||
484 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | 491 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
485 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | 492 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = |
486 | ARRAY_SIZE(ath9k_2ghz_chantable); | 493 | ARRAY_SIZE(ath9k_2ghz_chantable); |
@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) | |||
490 | } | 497 | } |
491 | 498 | ||
492 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { | 499 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { |
493 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; | 500 | channels = kmemdup(ath9k_5ghz_chantable, |
501 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); | ||
502 | if (!channels) { | ||
503 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
504 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
505 | return -ENOMEM; | ||
506 | } | ||
507 | |||
508 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; | ||
494 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 509 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
495 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | 510 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = |
496 | ARRAY_SIZE(ath9k_5ghz_chantable); | 511 | ARRAY_SIZE(ath9k_5ghz_chantable); |
@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) | |||
499 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | 514 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = |
500 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | 515 | ARRAY_SIZE(ath9k_legacy_rates) - 4; |
501 | } | 516 | } |
517 | return 0; | ||
502 | } | 518 | } |
503 | 519 | ||
504 | static void ath9k_init_misc(struct ath_softc *sc) | 520 | static void ath9k_init_misc(struct ath_softc *sc) |
@@ -506,7 +522,6 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
506 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 522 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
507 | int i = 0; | 523 | int i = 0; |
508 | 524 | ||
509 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
510 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | 525 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); |
511 | 526 | ||
512 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | 527 | sc->config.txpowlimit = ATH_TXPOWER_MAX; |
@@ -595,8 +610,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
595 | if (ret) | 610 | if (ret) |
596 | goto err_btcoex; | 611 | goto err_btcoex; |
597 | 612 | ||
613 | ret = ath9k_init_channels_rates(sc); | ||
614 | if (ret) | ||
615 | goto err_btcoex; | ||
616 | |||
598 | ath9k_init_crypto(sc); | 617 | ath9k_init_crypto(sc); |
599 | ath9k_init_channels_rates(sc); | ||
600 | ath9k_init_misc(sc); | 618 | ath9k_init_misc(sc); |
601 | 619 | ||
602 | return 0; | 620 | return 0; |
@@ -639,6 +657,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
639 | 657 | ||
640 | hw->wiphy->interface_modes = | 658 | hw->wiphy->interface_modes = |
641 | BIT(NL80211_IFTYPE_AP) | | 659 | BIT(NL80211_IFTYPE_AP) | |
660 | BIT(NL80211_IFTYPE_WDS) | | ||
642 | BIT(NL80211_IFTYPE_STATION) | | 661 | BIT(NL80211_IFTYPE_STATION) | |
643 | BIT(NL80211_IFTYPE_ADHOC) | | 662 | BIT(NL80211_IFTYPE_ADHOC) | |
644 | BIT(NL80211_IFTYPE_MESH_POINT); | 663 | BIT(NL80211_IFTYPE_MESH_POINT); |
@@ -756,6 +775,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
756 | { | 775 | { |
757 | int i = 0; | 776 | int i = 0; |
758 | 777 | ||
778 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
779 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
780 | |||
781 | if (sc->sbands[IEEE80211_BAND_5GHZ].channels) | ||
782 | kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); | ||
783 | |||
759 | if ((sc->btcoex.no_stomp_timer) && | 784 | if ((sc->btcoex.no_stomp_timer) && |
760 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 785 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
761 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | 786 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 3efda8a8a3c1..8c13479b17cd 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -40,7 +40,6 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | |||
40 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | 40 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
41 | 41 | ||
42 | REGWRITE_BUFFER_FLUSH(ah); | 42 | REGWRITE_BUFFER_FLUSH(ah); |
43 | DISABLE_REGWRITE_BUFFER(ah); | ||
44 | } | 43 | } |
45 | 44 | ||
46 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | 45 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) |
@@ -492,8 +491,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
492 | REG_WRITE(ah, AR_DMISC(q), | 491 | REG_WRITE(ah, AR_DMISC(q), |
493 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | 492 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); |
494 | 493 | ||
495 | REGWRITE_BUFFER_FLUSH(ah); | ||
496 | |||
497 | if (qi->tqi_cbrPeriod) { | 494 | if (qi->tqi_cbrPeriod) { |
498 | REG_WRITE(ah, AR_QCBRCFG(q), | 495 | REG_WRITE(ah, AR_QCBRCFG(q), |
499 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | | 496 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | |
@@ -509,8 +506,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
509 | AR_Q_RDYTIMECFG_EN); | 506 | AR_Q_RDYTIMECFG_EN); |
510 | } | 507 | } |
511 | 508 | ||
512 | REGWRITE_BUFFER_FLUSH(ah); | ||
513 | |||
514 | REG_WRITE(ah, AR_DCHNTIME(q), | 509 | REG_WRITE(ah, AR_DCHNTIME(q), |
515 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | | 510 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | |
516 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); | 511 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); |
@@ -530,7 +525,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
530 | } | 525 | } |
531 | 526 | ||
532 | REGWRITE_BUFFER_FLUSH(ah); | 527 | REGWRITE_BUFFER_FLUSH(ah); |
533 | DISABLE_REGWRITE_BUFFER(ah); | ||
534 | 528 | ||
535 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { | 529 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { |
536 | REG_WRITE(ah, AR_DMISC(q), | 530 | REG_WRITE(ah, AR_DMISC(q), |
@@ -553,7 +547,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
553 | | AR_D_MISC_POST_FR_BKOFF_DIS); | 547 | | AR_D_MISC_POST_FR_BKOFF_DIS); |
554 | 548 | ||
555 | REGWRITE_BUFFER_FLUSH(ah); | 549 | REGWRITE_BUFFER_FLUSH(ah); |
556 | DISABLE_REGWRITE_BUFFER(ah); | ||
557 | 550 | ||
558 | /* | 551 | /* |
559 | * cwmin and cwmax should be 0 for beacon queue | 552 | * cwmin and cwmax should be 0 for beacon queue |
@@ -585,7 +578,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
585 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); | 578 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); |
586 | 579 | ||
587 | REGWRITE_BUFFER_FLUSH(ah); | 580 | REGWRITE_BUFFER_FLUSH(ah); |
588 | DISABLE_REGWRITE_BUFFER(ah); | ||
589 | 581 | ||
590 | break; | 582 | break; |
591 | case ATH9K_TX_QUEUE_PSPOLL: | 583 | case ATH9K_TX_QUEUE_PSPOLL: |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a13387882636..74c2dc8a8b8a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -459,16 +459,6 @@ void ath_ani_calibrate(unsigned long data) | |||
459 | ah->curchan, | 459 | ah->curchan, |
460 | common->rx_chainmask, | 460 | common->rx_chainmask, |
461 | longcal); | 461 | longcal); |
462 | |||
463 | if (longcal) | ||
464 | common->ani.noise_floor = ath9k_hw_getchan_noise(ah, | ||
465 | ah->curchan); | ||
466 | |||
467 | ath_print(common, ATH_DBG_ANI, | ||
468 | " calibrate chan %u/%x nf: %d\n", | ||
469 | ah->curchan->channel, | ||
470 | ah->curchan->channelFlags, | ||
471 | common->ani.noise_floor); | ||
472 | } | 462 | } |
473 | } | 463 | } |
474 | 464 | ||
@@ -723,7 +713,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
723 | * it will clear whatever condition caused | 713 | * it will clear whatever condition caused |
724 | * the interrupt. | 714 | * the interrupt. |
725 | */ | 715 | */ |
726 | ath9k_hw_procmibevent(ah); | 716 | ath9k_hw_proc_mib_event(ah); |
727 | ath9k_hw_set_interrupts(ah, ah->imask); | 717 | ath9k_hw_set_interrupts(ah, ah->imask); |
728 | } | 718 | } |
729 | 719 | ||
@@ -1384,6 +1374,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1384 | case NL80211_IFTYPE_STATION: | 1374 | case NL80211_IFTYPE_STATION: |
1385 | ic_opmode = NL80211_IFTYPE_STATION; | 1375 | ic_opmode = NL80211_IFTYPE_STATION; |
1386 | break; | 1376 | break; |
1377 | case NL80211_IFTYPE_WDS: | ||
1378 | ic_opmode = NL80211_IFTYPE_WDS; | ||
1379 | break; | ||
1387 | case NL80211_IFTYPE_ADHOC: | 1380 | case NL80211_IFTYPE_ADHOC: |
1388 | case NL80211_IFTYPE_AP: | 1381 | case NL80211_IFTYPE_AP: |
1389 | case NL80211_IFTYPE_MESH_POINT: | 1382 | case NL80211_IFTYPE_MESH_POINT: |
@@ -1491,7 +1484,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1491 | mutex_unlock(&sc->mutex); | 1484 | mutex_unlock(&sc->mutex); |
1492 | } | 1485 | } |
1493 | 1486 | ||
1494 | void ath9k_enable_ps(struct ath_softc *sc) | 1487 | static void ath9k_enable_ps(struct ath_softc *sc) |
1495 | { | 1488 | { |
1496 | struct ath_hw *ah = sc->sc_ah; | 1489 | struct ath_hw *ah = sc->sc_ah; |
1497 | 1490 | ||
@@ -1505,13 +1498,32 @@ void ath9k_enable_ps(struct ath_softc *sc) | |||
1505 | } | 1498 | } |
1506 | } | 1499 | } |
1507 | 1500 | ||
1501 | static void ath9k_disable_ps(struct ath_softc *sc) | ||
1502 | { | ||
1503 | struct ath_hw *ah = sc->sc_ah; | ||
1504 | |||
1505 | sc->ps_enabled = false; | ||
1506 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); | ||
1507 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1508 | ath9k_hw_setrxabort(ah, 0); | ||
1509 | sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | | ||
1510 | PS_WAIT_FOR_CAB | | ||
1511 | PS_WAIT_FOR_PSPOLL_DATA | | ||
1512 | PS_WAIT_FOR_TX_ACK); | ||
1513 | if (ah->imask & ATH9K_INT_TIM_TIMER) { | ||
1514 | ah->imask &= ~ATH9K_INT_TIM_TIMER; | ||
1515 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
1516 | } | ||
1517 | } | ||
1518 | |||
1519 | } | ||
1520 | |||
1508 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1521 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1509 | { | 1522 | { |
1510 | struct ath_wiphy *aphy = hw->priv; | 1523 | struct ath_wiphy *aphy = hw->priv; |
1511 | struct ath_softc *sc = aphy->sc; | 1524 | struct ath_softc *sc = aphy->sc; |
1512 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1525 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1513 | struct ieee80211_conf *conf = &hw->conf; | 1526 | struct ieee80211_conf *conf = &hw->conf; |
1514 | struct ath_hw *ah = sc->sc_ah; | ||
1515 | bool disable_radio; | 1527 | bool disable_radio; |
1516 | 1528 | ||
1517 | mutex_lock(&sc->mutex); | 1529 | mutex_lock(&sc->mutex); |
@@ -1558,35 +1570,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1558 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1570 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1559 | unsigned long flags; | 1571 | unsigned long flags; |
1560 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 1572 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1561 | if (conf->flags & IEEE80211_CONF_PS) { | 1573 | if (conf->flags & IEEE80211_CONF_PS) |
1562 | sc->ps_flags |= PS_ENABLED; | 1574 | ath9k_enable_ps(sc); |
1563 | /* | 1575 | else |
1564 | * At this point we know hardware has received an ACK | 1576 | ath9k_disable_ps(sc); |
1565 | * of a previously sent null data frame. | ||
1566 | */ | ||
1567 | if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) { | ||
1568 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; | ||
1569 | ath9k_enable_ps(sc); | ||
1570 | } | ||
1571 | } else { | ||
1572 | sc->ps_enabled = false; | ||
1573 | sc->ps_flags &= ~(PS_ENABLED | | ||
1574 | PS_NULLFUNC_COMPLETED); | ||
1575 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
1576 | if (!(ah->caps.hw_caps & | ||
1577 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1578 | ath9k_hw_setrxabort(sc->sc_ah, 0); | ||
1579 | sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | | ||
1580 | PS_WAIT_FOR_CAB | | ||
1581 | PS_WAIT_FOR_PSPOLL_DATA | | ||
1582 | PS_WAIT_FOR_TX_ACK); | ||
1583 | if (ah->imask & ATH9K_INT_TIM_TIMER) { | ||
1584 | ah->imask &= ~ATH9K_INT_TIM_TIMER; | ||
1585 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
1586 | ah->imask); | ||
1587 | } | ||
1588 | } | ||
1589 | } | ||
1590 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1577 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1591 | } | 1578 | } |
1592 | 1579 | ||
@@ -2004,15 +1991,32 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
2004 | struct ath_wiphy *aphy = hw->priv; | 1991 | struct ath_wiphy *aphy = hw->priv; |
2005 | struct ath_softc *sc = aphy->sc; | 1992 | struct ath_softc *sc = aphy->sc; |
2006 | struct ath_hw *ah = sc->sc_ah; | 1993 | struct ath_hw *ah = sc->sc_ah; |
2007 | struct ath_common *common = ath9k_hw_common(ah); | 1994 | struct ieee80211_supported_band *sband; |
2008 | struct ieee80211_conf *conf = &hw->conf; | 1995 | struct ath9k_channel *chan; |
1996 | |||
1997 | sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
1998 | if (sband && idx >= sband->n_channels) { | ||
1999 | idx -= sband->n_channels; | ||
2000 | sband = NULL; | ||
2001 | } | ||
2002 | |||
2003 | if (!sband) | ||
2004 | sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
2009 | 2005 | ||
2010 | if (idx != 0) | 2006 | if (!sband || idx >= sband->n_channels) |
2011 | return -ENOENT; | 2007 | return -ENOENT; |
2012 | 2008 | ||
2013 | survey->channel = conf->channel; | 2009 | survey->channel = &sband->channels[idx]; |
2014 | survey->filled = SURVEY_INFO_NOISE_DBM; | 2010 | chan = &ah->channels[survey->channel->hw_value]; |
2015 | survey->noise = common->ani.noise_floor; | 2011 | survey->filled = 0; |
2012 | |||
2013 | if (chan == ah->curchan) | ||
2014 | survey->filled |= SURVEY_INFO_IN_USE; | ||
2015 | |||
2016 | if (chan->noisefloor) { | ||
2017 | survey->filled |= SURVEY_INFO_NOISE_DBM; | ||
2018 | survey->noise = chan->noisefloor; | ||
2019 | } | ||
2016 | 2020 | ||
2017 | return 0; | 2021 | return 0; |
2018 | } | 2022 | } |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f7da6b20a925..aa447770eb2b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1648,13 +1648,6 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1648 | 1648 | ||
1649 | bf->bf_buf_addr = bf->bf_dmacontext; | 1649 | bf->bf_buf_addr = bf->bf_dmacontext; |
1650 | 1650 | ||
1651 | /* tag if this is a nullfunc frame to enable PS when AP acks it */ | ||
1652 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { | ||
1653 | bf->bf_isnullfunc = true; | ||
1654 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; | ||
1655 | } else | ||
1656 | bf->bf_isnullfunc = false; | ||
1657 | |||
1658 | bf->bf_tx_aborted = false; | 1651 | bf->bf_tx_aborted = false; |
1659 | 1652 | ||
1660 | return 0; | 1653 | return 0; |
@@ -2082,18 +2075,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2082 | } | 2075 | } |
2083 | 2076 | ||
2084 | /* | 2077 | /* |
2085 | * We now know the nullfunc frame has been ACKed so we | ||
2086 | * can disable RX. | ||
2087 | */ | ||
2088 | if (bf->bf_isnullfunc && | ||
2089 | (ts.ts_status & ATH9K_TX_ACKED)) { | ||
2090 | if ((sc->ps_flags & PS_ENABLED)) | ||
2091 | ath9k_enable_ps(sc); | ||
2092 | else | ||
2093 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; | ||
2094 | } | ||
2095 | |||
2096 | /* | ||
2097 | * Remove ath_buf's of the same transmit unit from txq, | 2078 | * Remove ath_buf's of the same transmit unit from txq, |
2098 | * however leave the last descriptor back as the holding | 2079 | * however leave the last descriptor back as the holding |
2099 | * descriptor for hw. | 2080 | * descriptor for hw. |
@@ -2236,17 +2217,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2236 | 2217 | ||
2237 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); | 2218 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); |
2238 | 2219 | ||
2239 | /* | ||
2240 | * Make sure null func frame is acked before configuring | ||
2241 | * hw into ps mode. | ||
2242 | */ | ||
2243 | if (bf->bf_isnullfunc && txok) { | ||
2244 | if ((sc->ps_flags & PS_ENABLED)) | ||
2245 | ath9k_enable_ps(sc); | ||
2246 | else | ||
2247 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; | ||
2248 | } | ||
2249 | |||
2250 | if (!bf_isampdu(bf)) { | 2220 | if (!bf_isampdu(bf)) { |
2251 | if (txs.ts_status & ATH9K_TXERR_XRETRY) | 2221 | if (txs.ts_status & ATH9K_TXERR_XRETRY) |
2252 | bf->bf_state.bf_type |= BUF_XRETRY; | 2222 | bf->bf_state.bf_type |= BUF_XRETRY; |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 20f2a77e54d2..6cf0c9ef47aa 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -279,6 +279,7 @@ struct ar9170 { | |||
279 | unsigned int beacon_max_len; | 279 | unsigned int beacon_max_len; |
280 | bool rx_stream; | 280 | bool rx_stream; |
281 | bool tx_stream; | 281 | bool tx_stream; |
282 | bool rx_filter; | ||
282 | unsigned int mem_blocks; | 283 | unsigned int mem_blocks; |
283 | unsigned int mem_block_size; | 284 | unsigned int mem_block_size; |
284 | unsigned int rx_size; | 285 | unsigned int rx_size; |
@@ -314,6 +315,7 @@ struct ar9170 { | |||
314 | u64 cur_mc_hash; | 315 | u64 cur_mc_hash; |
315 | u32 cur_filter; | 316 | u32 cur_filter; |
316 | unsigned int filter_state; | 317 | unsigned int filter_state; |
318 | unsigned int rx_filter_caps; | ||
317 | bool sniffer_enabled; | 319 | bool sniffer_enabled; |
318 | 320 | ||
319 | /* MAC */ | 321 | /* MAC */ |
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index 0fc83d2336fd..f78728c38294 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h | |||
@@ -59,6 +59,16 @@ static inline int carl9170_flush_cab(struct ar9170 *ar, | |||
59 | return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); | 59 | return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); |
60 | } | 60 | } |
61 | 61 | ||
62 | static inline int carl9170_rx_filter(struct ar9170 *ar, | ||
63 | const unsigned int _rx_filter) | ||
64 | { | ||
65 | __le32 rx_filter = cpu_to_le32(_rx_filter); | ||
66 | |||
67 | return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER, | ||
68 | sizeof(rx_filter), (u8 *)&rx_filter, | ||
69 | 0, NULL); | ||
70 | } | ||
71 | |||
62 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, | 72 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, |
63 | const enum carl9170_cmd_oids cmd, const unsigned int len); | 73 | const enum carl9170_cmd_oids cmd, const unsigned int len); |
64 | 74 | ||
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 36615462b87a..ae6c006bbc56 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -257,6 +257,13 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
257 | if (SUPP(CARL9170FW_USB_UP_STREAM)) | 257 | if (SUPP(CARL9170FW_USB_UP_STREAM)) |
258 | ar->fw.rx_stream = true; | 258 | ar->fw.rx_stream = true; |
259 | 259 | ||
260 | if (SUPP(CARL9170FW_RX_FILTER)) { | ||
261 | ar->fw.rx_filter = true; | ||
262 | ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL | | ||
263 | FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS | | ||
264 | FIF_PROMISC_IN_BSS; | ||
265 | } | ||
266 | |||
260 | ar->fw.vif_num = otus_desc->vif_num; | 267 | ar->fw.vif_num = otus_desc->vif_num; |
261 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; | 268 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; |
262 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); | 269 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); |
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index d4a4e1dbef06..d552166db505 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -53,6 +53,7 @@ enum carl9170_cmd_oids { | |||
53 | CARL9170_CMD_REBOOT = 0x04, | 53 | CARL9170_CMD_REBOOT = 0x04, |
54 | CARL9170_CMD_BCN_CTRL = 0x05, | 54 | CARL9170_CMD_BCN_CTRL = 0x05, |
55 | CARL9170_CMD_READ_TSF = 0x06, | 55 | CARL9170_CMD_READ_TSF = 0x06, |
56 | CARL9170_CMD_RX_FILTER = 0x07, | ||
56 | 57 | ||
57 | /* CAM */ | 58 | /* CAM */ |
58 | CARL9170_CMD_EKEY = 0x10, | 59 | CARL9170_CMD_EKEY = 0x10, |
@@ -153,6 +154,20 @@ struct carl9170_psm { | |||
153 | } __packed; | 154 | } __packed; |
154 | #define CARL9170_PSM_SIZE 4 | 155 | #define CARL9170_PSM_SIZE 4 |
155 | 156 | ||
157 | struct carl9170_rx_filter_cmd { | ||
158 | __le32 rx_filter; | ||
159 | } __packed; | ||
160 | #define CARL9170_RX_FILTER_CMD_SIZE 4 | ||
161 | |||
162 | #define CARL9170_RX_FILTER_BAD 0x01 | ||
163 | #define CARL9170_RX_FILTER_OTHER_RA 0x02 | ||
164 | #define CARL9170_RX_FILTER_DECRY_FAIL 0x04 | ||
165 | #define CARL9170_RX_FILTER_CTL_OTHER 0x08 | ||
166 | #define CARL9170_RX_FILTER_CTL_PSPOLL 0x10 | ||
167 | #define CARL9170_RX_FILTER_CTL_BACKR 0x20 | ||
168 | #define CARL9170_RX_FILTER_MGMT 0x40 | ||
169 | #define CARL9170_RX_FILTER_DATA 0x80 | ||
170 | |||
156 | struct carl9170_bcn_ctrl_cmd { | 171 | struct carl9170_bcn_ctrl_cmd { |
157 | __le32 vif_id; | 172 | __le32 vif_id; |
158 | __le32 mode; | 173 | __le32 mode; |
@@ -188,6 +203,7 @@ struct carl9170_cmd { | |||
188 | struct carl9170_rf_init rf_init; | 203 | struct carl9170_rf_init rf_init; |
189 | struct carl9170_psm psm; | 204 | struct carl9170_psm psm; |
190 | struct carl9170_bcn_ctrl_cmd bcn_ctrl; | 205 | struct carl9170_bcn_ctrl_cmd bcn_ctrl; |
206 | struct carl9170_rx_filter_cmd rx_filter; | ||
191 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; | 207 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; |
192 | } __packed; | 208 | } __packed; |
193 | } __packed; | 209 | } __packed; |
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 7cd811708fe5..71f3821f6058 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h | |||
@@ -66,6 +66,9 @@ enum carl9170fw_feature_list { | |||
66 | /* Firmware PSM support | CARL9170_CMD_PSM */ | 66 | /* Firmware PSM support | CARL9170_CMD_PSM */ |
67 | CARL9170FW_PSM, | 67 | CARL9170FW_PSM, |
68 | 68 | ||
69 | /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ | ||
70 | CARL9170FW_RX_FILTER, | ||
71 | |||
69 | /* KEEP LAST */ | 72 | /* KEEP LAST */ |
70 | __CARL9170FW_FEATURE_NUM | 73 | __CARL9170FW_FEATURE_NUM |
71 | }; | 74 | }; |
@@ -142,7 +145,7 @@ struct carl9170fw_fix_desc { | |||
142 | (sizeof(struct carl9170fw_fix_desc)) | 145 | (sizeof(struct carl9170fw_fix_desc)) |
143 | 146 | ||
144 | #define CARL9170FW_DBG_DESC_MIN_VER 1 | 147 | #define CARL9170FW_DBG_DESC_MIN_VER 1 |
145 | #define CARL9170FW_DBG_DESC_CUR_VER 2 | 148 | #define CARL9170FW_DBG_DESC_CUR_VER 3 |
146 | struct carl9170fw_dbg_desc { | 149 | struct carl9170fw_dbg_desc { |
147 | struct carl9170fw_desc_head head; | 150 | struct carl9170fw_desc_head head; |
148 | 151 | ||
@@ -150,6 +153,7 @@ struct carl9170fw_dbg_desc { | |||
150 | __le32 counter_addr; | 153 | __le32 counter_addr; |
151 | __le32 rx_total_addr; | 154 | __le32 rx_total_addr; |
152 | __le32 rx_overrun_addr; | 155 | __le32 rx_overrun_addr; |
156 | __le32 rx_filter; | ||
153 | 157 | ||
154 | /* Put your debugging definitions here */ | 158 | /* Put your debugging definitions here */ |
155 | } __packed; | 159 | } __packed; |
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index b1292ac5b703..2f471b3f05af 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -731,6 +731,9 @@ struct ar9170_stream { | |||
731 | #define SET_VAL(reg, value, newvalue) \ | 731 | #define SET_VAL(reg, value, newvalue) \ |
732 | (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | 732 | (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg)) |
733 | 733 | ||
734 | #define SET_CONSTVAL(reg, newvalue) \ | ||
735 | (((newvalue) << reg##_S) & reg) | ||
736 | |||
734 | #define MOD_VAL(reg, value, newvalue) \ | 737 | #define MOD_VAL(reg, value, newvalue) \ |
735 | (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | 738 | (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) |
736 | #endif /* __CARL9170_SHARED_HW_H */ | 739 | #endif /* __CARL9170_SHARED_HW_H */ |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 84bd38e9961c..3cc99f3f7ab5 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -380,6 +380,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw) | |||
380 | if (err) | 380 | if (err) |
381 | goto out; | 381 | goto out; |
382 | 382 | ||
383 | if (ar->fw.rx_filter) { | ||
384 | err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA | | ||
385 | CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD); | ||
386 | if (err) | ||
387 | goto out; | ||
388 | } | ||
389 | |||
383 | err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, | 390 | err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, |
384 | AR9170_DMA_TRIGGER_RXQ); | 391 | AR9170_DMA_TRIGGER_RXQ); |
385 | if (err) | 392 | if (err) |
@@ -840,8 +847,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | |||
840 | struct ar9170 *ar = hw->priv; | 847 | struct ar9170 *ar = hw->priv; |
841 | 848 | ||
842 | /* mask supported flags */ | 849 | /* mask supported flags */ |
843 | *new_flags &= FIF_ALLMULTI | FIF_FCSFAIL | FIF_PLCPFAIL | | 850 | *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps; |
844 | FIF_OTHER_BSS | FIF_PROMISC_IN_BSS; | ||
845 | 851 | ||
846 | if (!IS_ACCEPTING_CMD(ar)) | 852 | if (!IS_ACCEPTING_CMD(ar)) |
847 | return; | 853 | return; |
@@ -867,6 +873,26 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | |||
867 | WARN_ON(carl9170_set_operating_mode(ar)); | 873 | WARN_ON(carl9170_set_operating_mode(ar)); |
868 | } | 874 | } |
869 | 875 | ||
876 | if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { | ||
877 | u32 rx_filter = 0; | ||
878 | |||
879 | if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) | ||
880 | rx_filter |= CARL9170_RX_FILTER_BAD; | ||
881 | |||
882 | if (!(*new_flags & FIF_CONTROL)) | ||
883 | rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; | ||
884 | |||
885 | if (!(*new_flags & FIF_PSPOLL)) | ||
886 | rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL; | ||
887 | |||
888 | if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) { | ||
889 | rx_filter |= CARL9170_RX_FILTER_OTHER_RA; | ||
890 | rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL; | ||
891 | } | ||
892 | |||
893 | WARN_ON(carl9170_rx_filter(ar, rx_filter)); | ||
894 | } | ||
895 | |||
870 | mutex_unlock(&ar->mutex); | 896 | mutex_unlock(&ar->mutex); |
871 | } | 897 | } |
872 | 898 | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h index 53c18d34ffcc..02c34eb4ebde 100644 --- a/drivers/net/wireless/ath/carl9170/phy.h +++ b/drivers/net/wireless/ath/carl9170/phy.h | |||
@@ -423,8 +423,8 @@ | |||
423 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 | 423 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 |
424 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 | 424 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 |
425 | 425 | ||
426 | #define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c) | ||
427 | #define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c) | 426 | #define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c) |
427 | #define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c) | ||
428 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000 | 428 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000 |
429 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 | 429 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 |
430 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00 | 430 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00 |
@@ -561,7 +561,4 @@ | |||
561 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 | 561 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 |
562 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 | 562 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 |
563 | 563 | ||
564 | #define REDUCE_CHAIN_0 0x00000050 | ||
565 | #define REDUCE_CHAIN_1 0x00000051 | ||
566 | |||
567 | #endif /* __CARL9170_SHARED_PHY_H */ | 564 | #endif /* __CARL9170_SHARED_PHY_H */ |
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 0e917f80eab4..ff53f078a0b5 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | 1 | #ifndef __CARL9170_SHARED_VERSION_H |
2 | #define __CARL9170_SHARED_VERSION_H | 2 | #define __CARL9170_SHARED_VERSION_H |
3 | #define CARL9170FW_VERSION_YEAR 10 | 3 | #define CARL9170FW_VERSION_YEAR 10 |
4 | #define CARL9170FW_VERSION_MONTH 8 | 4 | #define CARL9170FW_VERSION_MONTH 9 |
5 | #define CARL9170FW_VERSION_DAY 30 | 5 | #define CARL9170FW_VERSION_DAY 28 |
6 | #define CARL9170FW_VERSION_GIT "1.8.8.1" | 6 | #define CARL9170FW_VERSION_GIT "1.8.8.3" |
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | 7 | #endif /* __CARL9170_SHARED_VERSION_H */ |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 8674a99356af..72821c456b02 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -186,7 +186,8 @@ enum { | |||
186 | #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */ | 186 | #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */ |
187 | #define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */ | 187 | #define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */ |
188 | #define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ | 188 | #define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ |
189 | #define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */ | 189 | #define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5 Ghz channel */ |
190 | #define B43_SHM_SH_CHAN_40MHZ 0x0200 /* Bit set, if 40 Mhz channel width */ | ||
190 | #define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ | 191 | #define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ |
191 | /* TSSI information */ | 192 | /* TSSI information */ |
192 | #define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */ | 193 | #define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */ |
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 8f7d7eff2d80..7b2ea6781457 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
@@ -294,8 +294,10 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) | |||
294 | */ | 294 | */ |
295 | channelcookie = new_channel; | 295 | channelcookie = new_channel; |
296 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | 296 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) |
297 | channelcookie |= 0x100; | 297 | channelcookie |= B43_SHM_SH_CHAN_5GHZ; |
298 | //FIXME set 40Mhz flag if required | 298 | /* FIXME: set 40Mhz flag if required */ |
299 | if (0) | ||
300 | channelcookie |= B43_SHM_SH_CHAN_40MHZ; | ||
299 | savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); | 301 | savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); |
300 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); | 302 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); |
301 | 303 | ||
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2466c0a52e5d..f575e757caeb 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -73,7 +73,6 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, | |||
73 | u16 value, u8 core, bool off); | 73 | u16 value, u8 core, bool off); |
74 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | 74 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, |
75 | u16 value, u8 core); | 75 | u16 value, u8 core); |
76 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel); | ||
77 | 76 | ||
78 | static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) | 77 | static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) |
79 | { | 78 | { |
@@ -223,7 +222,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) | |||
223 | if (i) | 222 | if (i) |
224 | b43err(dev->wl, "radio post init timeout\n"); | 223 | b43err(dev->wl, "radio post init timeout\n"); |
225 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | 224 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); |
226 | nphy_channel_switch(dev, dev->phy.channel); | 225 | b43_switch_channel(dev, dev->phy.channel); |
227 | b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); | 226 | b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); |
228 | b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); | 227 | b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); |
229 | b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | 228 | b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); |
@@ -3351,12 +3350,6 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, | |||
3351 | 3350 | ||
3352 | b43_chantab_phy_upload(dev, e); | 3351 | b43_chantab_phy_upload(dev, e); |
3353 | 3352 | ||
3354 | tmp = chanspec.channel; | ||
3355 | if (chanspec.b_freq == 1) | ||
3356 | tmp |= 0x0100; | ||
3357 | if (chanspec.b_width == 3) | ||
3358 | tmp |= 0x0200; | ||
3359 | b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp); | ||
3360 | 3353 | ||
3361 | if (nphy->radio_chanspec.channel == 14) { | 3354 | if (nphy->radio_chanspec.channel == 14) { |
3362 | b43_nphy_classifier(dev, 2, 0); | 3355 | b43_nphy_classifier(dev, 2, 0); |
@@ -3438,18 +3431,6 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, | |||
3438 | return 0; | 3431 | return 0; |
3439 | } | 3432 | } |
3440 | 3433 | ||
3441 | /* Tune the hardware to a new channel */ | ||
3442 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
3443 | { | ||
3444 | struct b43_phy_n *nphy = dev->phy.n; | ||
3445 | |||
3446 | struct b43_chanspec chanspec; | ||
3447 | chanspec = nphy->radio_chanspec; | ||
3448 | chanspec.channel = channel; | ||
3449 | |||
3450 | return b43_nphy_set_chanspec(dev, chanspec); | ||
3451 | } | ||
3452 | |||
3453 | static int b43_nphy_op_allocate(struct b43_wldev *dev) | 3434 | static int b43_nphy_op_allocate(struct b43_wldev *dev) |
3454 | { | 3435 | { |
3455 | struct b43_phy_n *nphy; | 3436 | struct b43_phy_n *nphy; |
@@ -3570,7 +3551,7 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | |||
3570 | } else { | 3551 | } else { |
3571 | if (dev->phy.rev >= 3) { | 3552 | if (dev->phy.rev >= 3) { |
3572 | b43_radio_init2056(dev); | 3553 | b43_radio_init2056(dev); |
3573 | b43_nphy_set_chanspec(dev, nphy->radio_chanspec); | 3554 | b43_switch_channel(dev, dev->phy.channel); |
3574 | } else { | 3555 | } else { |
3575 | b43_radio_init2055(dev); | 3556 | b43_radio_init2055(dev); |
3576 | } | 3557 | } |
@@ -3586,6 +3567,9 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) | |||
3586 | static int b43_nphy_op_switch_channel(struct b43_wldev *dev, | 3567 | static int b43_nphy_op_switch_channel(struct b43_wldev *dev, |
3587 | unsigned int new_channel) | 3568 | unsigned int new_channel) |
3588 | { | 3569 | { |
3570 | struct b43_phy_n *nphy = dev->phy.n; | ||
3571 | struct b43_chanspec chanspec; | ||
3572 | |||
3589 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 3573 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
3590 | if ((new_channel < 1) || (new_channel > 14)) | 3574 | if ((new_channel < 1) || (new_channel > 14)) |
3591 | return -EINVAL; | 3575 | return -EINVAL; |
@@ -3594,7 +3578,10 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev, | |||
3594 | return -EINVAL; | 3578 | return -EINVAL; |
3595 | } | 3579 | } |
3596 | 3580 | ||
3597 | return nphy_channel_switch(dev, new_channel); | 3581 | chanspec = nphy->radio_chanspec; |
3582 | chanspec.channel = new_channel; | ||
3583 | |||
3584 | return b43_nphy_set_chanspec(dev, chanspec); | ||
3598 | } | 3585 | } |
3599 | 3586 | ||
3600 | static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) | 3587 | static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 0f2508384c75..8d6ed5f6f46f 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -11470,6 +11470,10 @@ static int ipw_net_init(struct net_device *dev) | |||
11470 | bg_band->channels = kcalloc(geo->bg_channels, | 11470 | bg_band->channels = kcalloc(geo->bg_channels, |
11471 | sizeof(struct ieee80211_channel), | 11471 | sizeof(struct ieee80211_channel), |
11472 | GFP_KERNEL); | 11472 | GFP_KERNEL); |
11473 | if (!bg_band->channels) { | ||
11474 | rc = -ENOMEM; | ||
11475 | goto out; | ||
11476 | } | ||
11473 | /* translate geo->bg to bg_band.channels */ | 11477 | /* translate geo->bg to bg_band.channels */ |
11474 | for (i = 0; i < geo->bg_channels; i++) { | 11478 | for (i = 0; i < geo->bg_channels; i++) { |
11475 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; | 11479 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; |
@@ -11505,6 +11509,10 @@ static int ipw_net_init(struct net_device *dev) | |||
11505 | a_band->channels = kcalloc(geo->a_channels, | 11509 | a_band->channels = kcalloc(geo->a_channels, |
11506 | sizeof(struct ieee80211_channel), | 11510 | sizeof(struct ieee80211_channel), |
11507 | GFP_KERNEL); | 11511 | GFP_KERNEL); |
11512 | if (!a_band->channels) { | ||
11513 | rc = -ENOMEM; | ||
11514 | goto out; | ||
11515 | } | ||
11508 | /* translate geo->bg to a_band.channels */ | 11516 | /* translate geo->bg to a_band.channels */ |
11509 | for (i = 0; i < geo->a_channels; i++) { | 11517 | for (i = 0; i < geo->a_channels; i++) { |
11510 | a_band->channels[i].band = IEEE80211_BAND_2GHZ; | 11518 | a_band->channels[i].band = IEEE80211_BAND_2GHZ; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 56ef4ed0db47..134f54541330 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -50,14 +50,20 @@ | |||
50 | 50 | ||
51 | /* Highest firmware API version supported */ | 51 | /* Highest firmware API version supported */ |
52 | #define IWL1000_UCODE_API_MAX 3 | 52 | #define IWL1000_UCODE_API_MAX 3 |
53 | #define IWL100_UCODE_API_MAX 5 | ||
53 | 54 | ||
54 | /* Lowest firmware API version supported */ | 55 | /* Lowest firmware API version supported */ |
55 | #define IWL1000_UCODE_API_MIN 1 | 56 | #define IWL1000_UCODE_API_MIN 1 |
57 | #define IWL100_UCODE_API_MIN 5 | ||
56 | 58 | ||
57 | #define IWL1000_FW_PRE "iwlwifi-1000-" | 59 | #define IWL1000_FW_PRE "iwlwifi-1000-" |
58 | #define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" | 60 | #define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" |
59 | #define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) | 61 | #define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) |
60 | 62 | ||
63 | #define IWL100_FW_PRE "iwlwifi-100-" | ||
64 | #define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" | ||
65 | #define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) | ||
66 | |||
61 | 67 | ||
62 | /* | 68 | /* |
63 | * For 1000, use advance thermal throttling critical temperature threshold, | 69 | * For 1000, use advance thermal throttling critical temperature threshold, |
@@ -120,13 +126,13 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
120 | { | 126 | { |
121 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 127 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
122 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) | 128 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
123 | priv->cfg->num_of_queues = | 129 | priv->cfg->base_params->num_of_queues = |
124 | priv->cfg->mod_params->num_of_queues; | 130 | priv->cfg->mod_params->num_of_queues; |
125 | 131 | ||
126 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 132 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
127 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 133 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
128 | priv->hw_params.scd_bc_tbls_size = | 134 | priv->hw_params.scd_bc_tbls_size = |
129 | priv->cfg->num_of_queues * | 135 | priv->cfg->base_params->num_of_queues * |
130 | sizeof(struct iwlagn_scd_bc_tbl); | 136 | sizeof(struct iwlagn_scd_bc_tbl); |
131 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 137 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
132 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; | 138 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
@@ -244,29 +250,16 @@ static const struct iwl_ops iwl1000_ops = { | |||
244 | .led = &iwlagn_led_ops, | 250 | .led = &iwlagn_led_ops, |
245 | }; | 251 | }; |
246 | 252 | ||
247 | struct iwl_cfg iwl1000_bgn_cfg = { | 253 | static struct iwl_base_params iwl1000_base_params = { |
248 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", | ||
249 | .fw_name_pre = IWL1000_FW_PRE, | ||
250 | .ucode_api_max = IWL1000_UCODE_API_MAX, | ||
251 | .ucode_api_min = IWL1000_UCODE_API_MIN, | ||
252 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
253 | .ops = &iwl1000_ops, | ||
254 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
255 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | ||
256 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, | ||
257 | .num_of_queues = IWLAGN_NUM_QUEUES, | 254 | .num_of_queues = IWLAGN_NUM_QUEUES, |
258 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | 255 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
259 | .mod_params = &iwlagn_mod_params, | 256 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
260 | .valid_tx_ant = ANT_A, | ||
261 | .valid_rx_ant = ANT_AB, | ||
262 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 257 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
263 | .set_l0s = true, | 258 | .set_l0s = true, |
264 | .use_bsm = false, | 259 | .use_bsm = false, |
265 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 260 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
266 | .shadow_ram_support = false, | 261 | .shadow_ram_support = false, |
267 | .ht_greenfield_support = true, | ||
268 | .led_compensation = 51, | 262 | .led_compensation = 51, |
269 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
270 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 263 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
271 | .support_ct_kill_exit = true, | 264 | .support_ct_kill_exit = true, |
272 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 265 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
@@ -277,6 +270,26 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
277 | .sensitivity_calib_by_driver = true, | 270 | .sensitivity_calib_by_driver = true, |
278 | .chain_noise_calib_by_driver = true, | 271 | .chain_noise_calib_by_driver = true, |
279 | }; | 272 | }; |
273 | static struct iwl_ht_params iwl1000_ht_params = { | ||
274 | .ht_greenfield_support = true, | ||
275 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
276 | }; | ||
277 | |||
278 | struct iwl_cfg iwl1000_bgn_cfg = { | ||
279 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", | ||
280 | .fw_name_pre = IWL1000_FW_PRE, | ||
281 | .ucode_api_max = IWL1000_UCODE_API_MAX, | ||
282 | .ucode_api_min = IWL1000_UCODE_API_MIN, | ||
283 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
284 | .valid_tx_ant = ANT_A, | ||
285 | .valid_rx_ant = ANT_AB, | ||
286 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | ||
287 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, | ||
288 | .ops = &iwl1000_ops, | ||
289 | .mod_params = &iwlagn_mod_params, | ||
290 | .base_params = &iwl1000_base_params, | ||
291 | .ht_params = &iwl1000_ht_params, | ||
292 | }; | ||
280 | 293 | ||
281 | struct iwl_cfg iwl1000_bg_cfg = { | 294 | struct iwl_cfg iwl1000_bg_cfg = { |
282 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", | 295 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", |
@@ -284,30 +297,45 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
284 | .ucode_api_max = IWL1000_UCODE_API_MAX, | 297 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
285 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 298 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
286 | .sku = IWL_SKU_G, | 299 | .sku = IWL_SKU_G, |
300 | .valid_tx_ant = ANT_A, | ||
301 | .valid_rx_ant = ANT_AB, | ||
302 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | ||
303 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, | ||
287 | .ops = &iwl1000_ops, | 304 | .ops = &iwl1000_ops, |
288 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 305 | .mod_params = &iwlagn_mod_params, |
306 | .base_params = &iwl1000_base_params, | ||
307 | }; | ||
308 | |||
309 | struct iwl_cfg iwl100_bgn_cfg = { | ||
310 | .name = "Intel(R) 100 Series 1x1 BGN", | ||
311 | .fw_name_pre = IWL100_FW_PRE, | ||
312 | .ucode_api_max = IWL100_UCODE_API_MAX, | ||
313 | .ucode_api_min = IWL100_UCODE_API_MIN, | ||
314 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
315 | .valid_tx_ant = ANT_A, | ||
316 | .valid_rx_ant = ANT_A, | ||
289 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 317 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
290 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, | 318 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
291 | .num_of_queues = IWLAGN_NUM_QUEUES, | 319 | .ops = &iwl1000_ops, |
292 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
293 | .mod_params = &iwlagn_mod_params, | 320 | .mod_params = &iwlagn_mod_params, |
321 | .base_params = &iwl1000_base_params, | ||
322 | .ht_params = &iwl1000_ht_params, | ||
323 | }; | ||
324 | |||
325 | struct iwl_cfg iwl100_bg_cfg = { | ||
326 | .name = "Intel(R) 100 Series 1x1 BG", | ||
327 | .fw_name_pre = IWL100_FW_PRE, | ||
328 | .ucode_api_max = IWL100_UCODE_API_MAX, | ||
329 | .ucode_api_min = IWL100_UCODE_API_MIN, | ||
330 | .sku = IWL_SKU_G, | ||
294 | .valid_tx_ant = ANT_A, | 331 | .valid_tx_ant = ANT_A, |
295 | .valid_rx_ant = ANT_AB, | 332 | .valid_rx_ant = ANT_A, |
296 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 333 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
297 | .set_l0s = true, | 334 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
298 | .use_bsm = false, | 335 | .ops = &iwl1000_ops, |
299 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 336 | .mod_params = &iwlagn_mod_params, |
300 | .shadow_ram_support = false, | 337 | .base_params = &iwl1000_base_params, |
301 | .led_compensation = 51, | ||
302 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
303 | .support_ct_kill_exit = true, | ||
304 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
305 | .chain_noise_scale = 1000, | ||
306 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
307 | .max_event_log_size = 128, | ||
308 | .ucode_tracing = true, | ||
309 | .sensitivity_calib_by_driver = true, | ||
310 | .chain_noise_calib_by_driver = true, | ||
311 | }; | 338 | }; |
312 | 339 | ||
313 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 340 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); |
341 | MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 5d09686c3389..cfdff5487e3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -406,7 +406,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | |||
406 | unsigned int plcp_msec; | 406 | unsigned int plcp_msec; |
407 | unsigned long plcp_received_jiffies; | 407 | unsigned long plcp_received_jiffies; |
408 | 408 | ||
409 | if (priv->cfg->plcp_delta_threshold == | 409 | if (priv->cfg->base_params->plcp_delta_threshold == |
410 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { | 410 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { |
411 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); | 411 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); |
412 | return rc; | 412 | return rc; |
@@ -432,7 +432,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | |||
432 | 432 | ||
433 | if ((combined_plcp_delta > 0) && | 433 | if ((combined_plcp_delta > 0) && |
434 | ((combined_plcp_delta * 100) / plcp_msec) > | 434 | ((combined_plcp_delta * 100) / plcp_msec) > |
435 | priv->cfg->plcp_delta_threshold) { | 435 | priv->cfg->base_params->plcp_delta_threshold) { |
436 | /* | 436 | /* |
437 | * if plcp_err exceed the threshold, the following | 437 | * if plcp_err exceed the threshold, the following |
438 | * data is printed in csv format: | 438 | * data is printed in csv format: |
@@ -444,7 +444,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | |||
444 | */ | 444 | */ |
445 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | 445 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " |
446 | "%u, %d, %u mSecs\n", | 446 | "%u, %d, %u mSecs\n", |
447 | priv->cfg->plcp_delta_threshold, | 447 | priv->cfg->base_params->plcp_delta_threshold, |
448 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), | 448 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), |
449 | combined_plcp_delta, plcp_msec); | 449 | combined_plcp_delta, plcp_msec); |
450 | /* | 450 | /* |
@@ -2421,7 +2421,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2421 | } | 2421 | } |
2422 | 2422 | ||
2423 | /* Assign number of Usable TX queues */ | 2423 | /* Assign number of Usable TX queues */ |
2424 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 2424 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
2425 | 2425 | ||
2426 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | 2426 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); |
2427 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); | 2427 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); |
@@ -2722,22 +2722,12 @@ static const struct iwl_ops iwl3945_ops = { | |||
2722 | .led = &iwl3945_led_ops, | 2722 | .led = &iwl3945_led_ops, |
2723 | }; | 2723 | }; |
2724 | 2724 | ||
2725 | static struct iwl_cfg iwl3945_bg_cfg = { | 2725 | static struct iwl_base_params iwl3945_base_params = { |
2726 | .name = "3945BG", | ||
2727 | .fw_name_pre = IWL3945_FW_PRE, | ||
2728 | .ucode_api_max = IWL3945_UCODE_API_MAX, | ||
2729 | .ucode_api_min = IWL3945_UCODE_API_MIN, | ||
2730 | .sku = IWL_SKU_G, | ||
2731 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2726 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2732 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | ||
2733 | .ops = &iwl3945_ops, | ||
2734 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2735 | .mod_params = &iwl3945_mod_params, | ||
2736 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | 2727 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, |
2737 | .set_l0s = false, | 2728 | .set_l0s = false, |
2738 | .use_bsm = true, | 2729 | .use_bsm = true, |
2739 | .use_isr_legacy = true, | 2730 | .use_isr_legacy = true, |
2740 | .ht_greenfield_support = false, | ||
2741 | .led_compensation = 64, | 2731 | .led_compensation = 64, |
2742 | .broken_powersave = true, | 2732 | .broken_powersave = true, |
2743 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 2733 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
@@ -2746,25 +2736,28 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2746 | .tx_power_by_driver = true, | 2736 | .tx_power_by_driver = true, |
2747 | }; | 2737 | }; |
2748 | 2738 | ||
2739 | static struct iwl_cfg iwl3945_bg_cfg = { | ||
2740 | .name = "3945BG", | ||
2741 | .fw_name_pre = IWL3945_FW_PRE, | ||
2742 | .ucode_api_max = IWL3945_UCODE_API_MAX, | ||
2743 | .ucode_api_min = IWL3945_UCODE_API_MIN, | ||
2744 | .sku = IWL_SKU_G, | ||
2745 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | ||
2746 | .ops = &iwl3945_ops, | ||
2747 | .mod_params = &iwl3945_mod_params, | ||
2748 | .base_params = &iwl3945_base_params, | ||
2749 | }; | ||
2750 | |||
2749 | static struct iwl_cfg iwl3945_abg_cfg = { | 2751 | static struct iwl_cfg iwl3945_abg_cfg = { |
2750 | .name = "3945ABG", | 2752 | .name = "3945ABG", |
2751 | .fw_name_pre = IWL3945_FW_PRE, | 2753 | .fw_name_pre = IWL3945_FW_PRE, |
2752 | .ucode_api_max = IWL3945_UCODE_API_MAX, | 2754 | .ucode_api_max = IWL3945_UCODE_API_MAX, |
2753 | .ucode_api_min = IWL3945_UCODE_API_MIN, | 2755 | .ucode_api_min = IWL3945_UCODE_API_MIN, |
2754 | .sku = IWL_SKU_A|IWL_SKU_G, | 2756 | .sku = IWL_SKU_A|IWL_SKU_G, |
2755 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | ||
2756 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2757 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2757 | .ops = &iwl3945_ops, | 2758 | .ops = &iwl3945_ops, |
2758 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2759 | .mod_params = &iwl3945_mod_params, | 2759 | .mod_params = &iwl3945_mod_params, |
2760 | .use_isr_legacy = true, | 2760 | .base_params = &iwl3945_base_params, |
2761 | .ht_greenfield_support = false, | ||
2762 | .led_compensation = 64, | ||
2763 | .broken_powersave = true, | ||
2764 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
2765 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
2766 | .max_event_log_size = 512, | ||
2767 | .tx_power_by_driver = true, | ||
2768 | }; | 2761 | }; |
2769 | 2762 | ||
2770 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2763 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 943a9c7bfa7f..834c2f9c15d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -647,13 +647,13 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
647 | { | 647 | { |
648 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 648 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
649 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) | 649 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) |
650 | priv->cfg->num_of_queues = | 650 | priv->cfg->base_params->num_of_queues = |
651 | priv->cfg->mod_params->num_of_queues; | 651 | priv->cfg->mod_params->num_of_queues; |
652 | 652 | ||
653 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 653 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
654 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | 654 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
655 | priv->hw_params.scd_bc_tbls_size = | 655 | priv->hw_params.scd_bc_tbls_size = |
656 | priv->cfg->num_of_queues * | 656 | priv->cfg->base_params->num_of_queues * |
657 | sizeof(struct iwl4965_scd_bc_tbl); | 657 | sizeof(struct iwl4965_scd_bc_tbl); |
658 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 658 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
659 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 659 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
@@ -1724,13 +1724,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1724 | u16 ssn_idx, u8 tx_fifo) | 1724 | u16 ssn_idx, u8 tx_fifo) |
1725 | { | 1725 | { |
1726 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1726 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1727 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 1727 | (IWL49_FIRST_AMPDU_QUEUE + |
1728 | <= txq_id)) { | 1728 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { |
1729 | IWL_WARN(priv, | 1729 | IWL_WARN(priv, |
1730 | "queue number out of range: %d, must be %d to %d\n", | 1730 | "queue number out of range: %d, must be %d to %d\n", |
1731 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1731 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1732 | IWL49_FIRST_AMPDU_QUEUE + | 1732 | IWL49_FIRST_AMPDU_QUEUE + |
1733 | priv->cfg->num_of_ampdu_queues - 1); | 1733 | priv->cfg->base_params->num_of_ampdu_queues - 1); |
1734 | return -EINVAL; | 1734 | return -EINVAL; |
1735 | } | 1735 | } |
1736 | 1736 | ||
@@ -1792,13 +1792,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1792 | int ret; | 1792 | int ret; |
1793 | 1793 | ||
1794 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1794 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1795 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 1795 | (IWL49_FIRST_AMPDU_QUEUE + |
1796 | <= txq_id)) { | 1796 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { |
1797 | IWL_WARN(priv, | 1797 | IWL_WARN(priv, |
1798 | "queue number out of range: %d, must be %d to %d\n", | 1798 | "queue number out of range: %d, must be %d to %d\n", |
1799 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1799 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1800 | IWL49_FIRST_AMPDU_QUEUE + | 1800 | IWL49_FIRST_AMPDU_QUEUE + |
1801 | priv->cfg->num_of_ampdu_queues - 1); | 1801 | priv->cfg->base_params->num_of_ampdu_queues - 1); |
1802 | return -EINVAL; | 1802 | return -EINVAL; |
1803 | } | 1803 | } |
1804 | 1804 | ||
@@ -2302,26 +2302,14 @@ static const struct iwl_ops iwl4965_ops = { | |||
2302 | .led = &iwlagn_led_ops, | 2302 | .led = &iwlagn_led_ops, |
2303 | }; | 2303 | }; |
2304 | 2304 | ||
2305 | struct iwl_cfg iwl4965_agn_cfg = { | 2305 | static struct iwl_base_params iwl4965_base_params = { |
2306 | .name = "Intel(R) Wireless WiFi Link 4965AGN", | ||
2307 | .fw_name_pre = IWL4965_FW_PRE, | ||
2308 | .ucode_api_max = IWL4965_UCODE_API_MAX, | ||
2309 | .ucode_api_min = IWL4965_UCODE_API_MIN, | ||
2310 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
2311 | .eeprom_size = IWL4965_EEPROM_IMG_SIZE, | 2306 | .eeprom_size = IWL4965_EEPROM_IMG_SIZE, |
2312 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | ||
2313 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | ||
2314 | .ops = &iwl4965_ops, | ||
2315 | .num_of_queues = IWL49_NUM_QUEUES, | 2307 | .num_of_queues = IWL49_NUM_QUEUES, |
2316 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | 2308 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, |
2317 | .mod_params = &iwlagn_mod_params, | ||
2318 | .valid_tx_ant = ANT_AB, | ||
2319 | .valid_rx_ant = ANT_ABC, | ||
2320 | .pll_cfg_val = 0, | 2309 | .pll_cfg_val = 0, |
2321 | .set_l0s = true, | 2310 | .set_l0s = true, |
2322 | .use_bsm = true, | 2311 | .use_bsm = true, |
2323 | .use_isr_legacy = true, | 2312 | .use_isr_legacy = true, |
2324 | .ht_greenfield_support = false, | ||
2325 | .broken_powersave = true, | 2313 | .broken_powersave = true, |
2326 | .led_compensation = 61, | 2314 | .led_compensation = 61, |
2327 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2315 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
@@ -2333,6 +2321,21 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2333 | .ucode_tracing = true, | 2321 | .ucode_tracing = true, |
2334 | .sensitivity_calib_by_driver = true, | 2322 | .sensitivity_calib_by_driver = true, |
2335 | .chain_noise_calib_by_driver = true, | 2323 | .chain_noise_calib_by_driver = true, |
2324 | }; | ||
2325 | |||
2326 | struct iwl_cfg iwl4965_agn_cfg = { | ||
2327 | .name = "Intel(R) Wireless WiFi Link 4965AGN", | ||
2328 | .fw_name_pre = IWL4965_FW_PRE, | ||
2329 | .ucode_api_max = IWL4965_UCODE_API_MAX, | ||
2330 | .ucode_api_min = IWL4965_UCODE_API_MIN, | ||
2331 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
2332 | .valid_tx_ant = ANT_AB, | ||
2333 | .valid_rx_ant = ANT_ABC, | ||
2334 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | ||
2335 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | ||
2336 | .ops = &iwl4965_ops, | ||
2337 | .mod_params = &iwlagn_mod_params, | ||
2338 | .base_params = &iwl4965_base_params, | ||
2336 | /* | 2339 | /* |
2337 | * Force use of chains B and C for scan RX on 5 GHz band | 2340 | * Force use of chains B and C for scan RX on 5 GHz band |
2338 | * because the device has off-channel reception on chain A. | 2341 | * because the device has off-channel reception on chain A. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 21b4b23368e6..1b25ad63b5c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -170,13 +170,13 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
170 | { | 170 | { |
171 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 171 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
172 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) | 172 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
173 | priv->cfg->num_of_queues = | 173 | priv->cfg->base_params->num_of_queues = |
174 | priv->cfg->mod_params->num_of_queues; | 174 | priv->cfg->mod_params->num_of_queues; |
175 | 175 | ||
176 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 176 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
177 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 177 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
178 | priv->hw_params.scd_bc_tbls_size = | 178 | priv->hw_params.scd_bc_tbls_size = |
179 | priv->cfg->num_of_queues * | 179 | priv->cfg->base_params->num_of_queues * |
180 | sizeof(struct iwlagn_scd_bc_tbl); | 180 | sizeof(struct iwlagn_scd_bc_tbl); |
181 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 181 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
182 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; | 182 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
@@ -217,13 +217,13 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
217 | { | 217 | { |
218 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 218 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
219 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) | 219 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
220 | priv->cfg->num_of_queues = | 220 | priv->cfg->base_params->num_of_queues = |
221 | priv->cfg->mod_params->num_of_queues; | 221 | priv->cfg->mod_params->num_of_queues; |
222 | 222 | ||
223 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 223 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
224 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 224 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
225 | priv->hw_params.scd_bc_tbls_size = | 225 | priv->hw_params.scd_bc_tbls_size = |
226 | priv->cfg->num_of_queues * | 226 | priv->cfg->base_params->num_of_queues * |
227 | sizeof(struct iwlagn_scd_bc_tbl); | 227 | sizeof(struct iwlagn_scd_bc_tbl); |
228 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 228 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
229 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; | 229 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
@@ -504,27 +504,14 @@ static const struct iwl_ops iwl5150_ops = { | |||
504 | .led = &iwlagn_led_ops, | 504 | .led = &iwlagn_led_ops, |
505 | }; | 505 | }; |
506 | 506 | ||
507 | struct iwl_cfg iwl5300_agn_cfg = { | 507 | static struct iwl_base_params iwl5000_base_params = { |
508 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", | ||
509 | .fw_name_pre = IWL5000_FW_PRE, | ||
510 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
511 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
512 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
513 | .ops = &iwl5000_ops, | ||
514 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 508 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
515 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | ||
516 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
517 | .num_of_queues = IWLAGN_NUM_QUEUES, | 509 | .num_of_queues = IWLAGN_NUM_QUEUES, |
518 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | 510 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
519 | .mod_params = &iwlagn_mod_params, | ||
520 | .valid_tx_ant = ANT_ABC, | ||
521 | .valid_rx_ant = ANT_ABC, | ||
522 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 511 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
523 | .set_l0s = true, | 512 | .set_l0s = true, |
524 | .use_bsm = false, | 513 | .use_bsm = false, |
525 | .ht_greenfield_support = true, | ||
526 | .led_compensation = 51, | 514 | .led_compensation = 51, |
527 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
528 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 515 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
529 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 516 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
530 | .chain_noise_scale = 1000, | 517 | .chain_noise_scale = 1000, |
@@ -534,6 +521,26 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
534 | .sensitivity_calib_by_driver = true, | 521 | .sensitivity_calib_by_driver = true, |
535 | .chain_noise_calib_by_driver = true, | 522 | .chain_noise_calib_by_driver = true, |
536 | }; | 523 | }; |
524 | static struct iwl_ht_params iwl5000_ht_params = { | ||
525 | .ht_greenfield_support = true, | ||
526 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
527 | }; | ||
528 | |||
529 | struct iwl_cfg iwl5300_agn_cfg = { | ||
530 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", | ||
531 | .fw_name_pre = IWL5000_FW_PRE, | ||
532 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
533 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
534 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
535 | .valid_tx_ant = ANT_ABC, | ||
536 | .valid_rx_ant = ANT_ABC, | ||
537 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | ||
538 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
539 | .ops = &iwl5000_ops, | ||
540 | .mod_params = &iwlagn_mod_params, | ||
541 | .base_params = &iwl5000_base_params, | ||
542 | .ht_params = &iwl5000_ht_params, | ||
543 | }; | ||
537 | 544 | ||
538 | struct iwl_cfg iwl5100_bgn_cfg = { | 545 | struct iwl_cfg iwl5100_bgn_cfg = { |
539 | .name = "Intel(R) WiFi Link 5100 BGN", | 546 | .name = "Intel(R) WiFi Link 5100 BGN", |
@@ -541,29 +548,14 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
541 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 548 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
542 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 549 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
543 | .sku = IWL_SKU_G|IWL_SKU_N, | 550 | .sku = IWL_SKU_G|IWL_SKU_N, |
544 | .ops = &iwl5000_ops, | 551 | .valid_tx_ant = ANT_B, |
545 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 552 | .valid_rx_ant = ANT_AB, |
546 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 553 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
547 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 554 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
548 | .num_of_queues = IWLAGN_NUM_QUEUES, | 555 | .ops = &iwl5000_ops, |
549 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
550 | .mod_params = &iwlagn_mod_params, | 556 | .mod_params = &iwlagn_mod_params, |
551 | .valid_tx_ant = ANT_B, | 557 | .base_params = &iwl5000_base_params, |
552 | .valid_rx_ant = ANT_AB, | 558 | .ht_params = &iwl5000_ht_params, |
553 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
554 | .set_l0s = true, | ||
555 | .use_bsm = false, | ||
556 | .ht_greenfield_support = true, | ||
557 | .led_compensation = 51, | ||
558 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
559 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
560 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
561 | .chain_noise_scale = 1000, | ||
562 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
563 | .max_event_log_size = 512, | ||
564 | .ucode_tracing = true, | ||
565 | .sensitivity_calib_by_driver = true, | ||
566 | .chain_noise_calib_by_driver = true, | ||
567 | }; | 559 | }; |
568 | 560 | ||
569 | struct iwl_cfg iwl5100_abg_cfg = { | 561 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -572,27 +564,13 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
572 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 564 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
573 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 565 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
574 | .sku = IWL_SKU_A|IWL_SKU_G, | 566 | .sku = IWL_SKU_A|IWL_SKU_G, |
575 | .ops = &iwl5000_ops, | 567 | .valid_tx_ant = ANT_B, |
576 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 568 | .valid_rx_ant = ANT_AB, |
577 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 569 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
578 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 570 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
579 | .num_of_queues = IWLAGN_NUM_QUEUES, | 571 | .ops = &iwl5000_ops, |
580 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
581 | .mod_params = &iwlagn_mod_params, | 572 | .mod_params = &iwlagn_mod_params, |
582 | .valid_tx_ant = ANT_B, | 573 | .base_params = &iwl5000_base_params, |
583 | .valid_rx_ant = ANT_AB, | ||
584 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
585 | .set_l0s = true, | ||
586 | .use_bsm = false, | ||
587 | .led_compensation = 51, | ||
588 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
589 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
590 | .chain_noise_scale = 1000, | ||
591 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
592 | .max_event_log_size = 512, | ||
593 | .ucode_tracing = true, | ||
594 | .sensitivity_calib_by_driver = true, | ||
595 | .chain_noise_calib_by_driver = true, | ||
596 | }; | 574 | }; |
597 | 575 | ||
598 | struct iwl_cfg iwl5100_agn_cfg = { | 576 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -601,29 +579,14 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
601 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 579 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
602 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 580 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
603 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 581 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
604 | .ops = &iwl5000_ops, | 582 | .valid_tx_ant = ANT_B, |
605 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 583 | .valid_rx_ant = ANT_AB, |
606 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 584 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
607 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 585 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
608 | .num_of_queues = IWLAGN_NUM_QUEUES, | 586 | .ops = &iwl5000_ops, |
609 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
610 | .mod_params = &iwlagn_mod_params, | 587 | .mod_params = &iwlagn_mod_params, |
611 | .valid_tx_ant = ANT_B, | 588 | .base_params = &iwl5000_base_params, |
612 | .valid_rx_ant = ANT_AB, | 589 | .ht_params = &iwl5000_ht_params, |
613 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
614 | .set_l0s = true, | ||
615 | .use_bsm = false, | ||
616 | .ht_greenfield_support = true, | ||
617 | .led_compensation = 51, | ||
618 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
619 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
620 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
621 | .chain_noise_scale = 1000, | ||
622 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
623 | .max_event_log_size = 512, | ||
624 | .ucode_tracing = true, | ||
625 | .sensitivity_calib_by_driver = true, | ||
626 | .chain_noise_calib_by_driver = true, | ||
627 | }; | 590 | }; |
628 | 591 | ||
629 | struct iwl_cfg iwl5350_agn_cfg = { | 592 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -632,29 +595,14 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
632 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 595 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
633 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 596 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
634 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 597 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
635 | .ops = &iwl5000_ops, | 598 | .valid_tx_ant = ANT_ABC, |
636 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 599 | .valid_rx_ant = ANT_ABC, |
637 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 600 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
638 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 601 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
639 | .num_of_queues = IWLAGN_NUM_QUEUES, | 602 | .ops = &iwl5000_ops, |
640 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
641 | .mod_params = &iwlagn_mod_params, | 603 | .mod_params = &iwlagn_mod_params, |
642 | .valid_tx_ant = ANT_ABC, | 604 | .base_params = &iwl5000_base_params, |
643 | .valid_rx_ant = ANT_ABC, | 605 | .ht_params = &iwl5000_ht_params, |
644 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
645 | .set_l0s = true, | ||
646 | .use_bsm = false, | ||
647 | .ht_greenfield_support = true, | ||
648 | .led_compensation = 51, | ||
649 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
650 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
651 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
652 | .chain_noise_scale = 1000, | ||
653 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
654 | .max_event_log_size = 512, | ||
655 | .ucode_tracing = true, | ||
656 | .sensitivity_calib_by_driver = true, | ||
657 | .chain_noise_calib_by_driver = true, | ||
658 | }; | 606 | }; |
659 | 607 | ||
660 | struct iwl_cfg iwl5150_agn_cfg = { | 608 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -663,29 +611,14 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
663 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 611 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
664 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 612 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
665 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 613 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
666 | .ops = &iwl5150_ops, | 614 | .valid_tx_ant = ANT_A, |
667 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 615 | .valid_rx_ant = ANT_AB, |
668 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 616 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
669 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 617 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
670 | .num_of_queues = IWLAGN_NUM_QUEUES, | 618 | .ops = &iwl5150_ops, |
671 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
672 | .mod_params = &iwlagn_mod_params, | 619 | .mod_params = &iwlagn_mod_params, |
673 | .valid_tx_ant = ANT_A, | 620 | .base_params = &iwl5000_base_params, |
674 | .valid_rx_ant = ANT_AB, | 621 | .ht_params = &iwl5000_ht_params, |
675 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
676 | .set_l0s = true, | ||
677 | .use_bsm = false, | ||
678 | .ht_greenfield_support = true, | ||
679 | .led_compensation = 51, | ||
680 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
681 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
682 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
683 | .chain_noise_scale = 1000, | ||
684 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
685 | .max_event_log_size = 512, | ||
686 | .ucode_tracing = true, | ||
687 | .sensitivity_calib_by_driver = true, | ||
688 | .chain_noise_calib_by_driver = true, | ||
689 | .need_dc_calib = true, | 622 | .need_dc_calib = true, |
690 | }; | 623 | }; |
691 | 624 | ||
@@ -695,27 +628,13 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
695 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 628 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
696 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 629 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
697 | .sku = IWL_SKU_A|IWL_SKU_G, | 630 | .sku = IWL_SKU_A|IWL_SKU_G, |
698 | .ops = &iwl5150_ops, | 631 | .valid_tx_ant = ANT_A, |
699 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 632 | .valid_rx_ant = ANT_AB, |
700 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 633 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
701 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 634 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
702 | .num_of_queues = IWLAGN_NUM_QUEUES, | 635 | .ops = &iwl5150_ops, |
703 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
704 | .mod_params = &iwlagn_mod_params, | 636 | .mod_params = &iwlagn_mod_params, |
705 | .valid_tx_ant = ANT_A, | 637 | .base_params = &iwl5000_base_params, |
706 | .valid_rx_ant = ANT_AB, | ||
707 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
708 | .set_l0s = true, | ||
709 | .use_bsm = false, | ||
710 | .led_compensation = 51, | ||
711 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
712 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
713 | .chain_noise_scale = 1000, | ||
714 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
715 | .max_event_log_size = 512, | ||
716 | .ucode_tracing = true, | ||
717 | .sensitivity_calib_by_driver = true, | ||
718 | .chain_noise_calib_by_driver = true, | ||
719 | .need_dc_calib = true, | 638 | .need_dc_calib = true, |
720 | }; | 639 | }; |
721 | 640 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9f43f2770c96..6261aec5ebdc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -51,13 +51,15 @@ | |||
51 | 51 | ||
52 | /* Highest firmware API version supported */ | 52 | /* Highest firmware API version supported */ |
53 | #define IWL6000_UCODE_API_MAX 4 | 53 | #define IWL6000_UCODE_API_MAX 4 |
54 | #define IWL6050_UCODE_API_MAX 4 | 54 | #define IWL6050_UCODE_API_MAX 5 |
55 | #define IWL6000G2_UCODE_API_MAX 5 | 55 | #define IWL6000G2_UCODE_API_MAX 5 |
56 | #define IWL130_UCODE_API_MAX 5 | ||
56 | 57 | ||
57 | /* Lowest firmware API version supported */ | 58 | /* Lowest firmware API version supported */ |
58 | #define IWL6000_UCODE_API_MIN 4 | 59 | #define IWL6000_UCODE_API_MIN 4 |
59 | #define IWL6050_UCODE_API_MIN 4 | 60 | #define IWL6050_UCODE_API_MIN 4 |
60 | #define IWL6000G2_UCODE_API_MIN 4 | 61 | #define IWL6000G2_UCODE_API_MIN 4 |
62 | #define IWL130_UCODE_API_MIN 5 | ||
61 | 63 | ||
62 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 64 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
63 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 65 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
@@ -75,6 +77,9 @@ | |||
75 | #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" | 77 | #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" |
76 | #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) | 78 | #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) |
77 | 79 | ||
80 | #define IWL130_FW_PRE "iwlwifi-130-" | ||
81 | #define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode" | ||
82 | #define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api) | ||
78 | 83 | ||
79 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | 84 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) |
80 | { | 85 | { |
@@ -83,15 +88,24 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
83 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 88 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
84 | } | 89 | } |
85 | 90 | ||
86 | /* Indicate calibration version to uCode. */ | 91 | static void iwl6050_additional_nic_config(struct iwl_priv *priv) |
87 | static void iwl6000_set_calib_version(struct iwl_priv *priv) | ||
88 | { | 92 | { |
89 | if (priv->cfg->need_dc_calib && | 93 | /* Indicate calibration version to uCode. */ |
90 | (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)) | 94 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) |
91 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | 95 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, |
92 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 96 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
93 | } | 97 | } |
94 | 98 | ||
99 | static void iwl6050g2_additional_nic_config(struct iwl_priv *priv) | ||
100 | { | ||
101 | /* Indicate calibration version to uCode. */ | ||
102 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) | ||
103 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
104 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
105 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
106 | CSR_GP_DRIVER_REG_BIT_6050_1x2); | ||
107 | } | ||
108 | |||
95 | /* NIC configuration for 6000 series */ | 109 | /* NIC configuration for 6000 series */ |
96 | static void iwl6000_nic_config(struct iwl_priv *priv) | 110 | static void iwl6000_nic_config(struct iwl_priv *priv) |
97 | { | 111 | { |
@@ -117,9 +131,11 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
117 | iwl_write32(priv, CSR_GP_DRIVER_REG, | 131 | iwl_write32(priv, CSR_GP_DRIVER_REG, |
118 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 132 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
119 | } | 133 | } |
120 | /* else do nothing, uCode configured */ | 134 | /* do additional nic configuration if needed */ |
121 | if (priv->cfg->ops->lib->temp_ops.set_calib_version) | 135 | if (priv->cfg->ops->nic && |
122 | priv->cfg->ops->lib->temp_ops.set_calib_version(priv); | 136 | priv->cfg->ops->nic->additional_nic_config) { |
137 | priv->cfg->ops->nic->additional_nic_config(priv); | ||
138 | } | ||
123 | } | 139 | } |
124 | 140 | ||
125 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | 141 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { |
@@ -151,13 +167,13 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
151 | { | 167 | { |
152 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 168 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
153 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) | 169 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
154 | priv->cfg->num_of_queues = | 170 | priv->cfg->base_params->num_of_queues = |
155 | priv->cfg->mod_params->num_of_queues; | 171 | priv->cfg->mod_params->num_of_queues; |
156 | 172 | ||
157 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | 173 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; |
158 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 174 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
159 | priv->hw_params.scd_bc_tbls_size = | 175 | priv->hw_params.scd_bc_tbls_size = |
160 | priv->cfg->num_of_queues * | 176 | priv->cfg->base_params->num_of_queues * |
161 | sizeof(struct iwlagn_scd_bc_tbl); | 177 | sizeof(struct iwlagn_scd_bc_tbl); |
162 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 178 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
163 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; | 179 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
@@ -188,7 +204,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
188 | BIT(IWL_CALIB_TX_IQ) | | 204 | BIT(IWL_CALIB_TX_IQ) | |
189 | BIT(IWL_CALIB_BASE_BAND); | 205 | BIT(IWL_CALIB_BASE_BAND); |
190 | if (priv->cfg->need_dc_calib) | 206 | if (priv->cfg->need_dc_calib) |
191 | priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); | 207 | priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX); |
192 | 208 | ||
193 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | 209 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; |
194 | 210 | ||
@@ -320,7 +336,6 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
320 | .temp_ops = { | 336 | .temp_ops = { |
321 | .temperature = iwlagn_temperature, | 337 | .temperature = iwlagn_temperature, |
322 | .set_ct_kill = iwl6000_set_ct_threshold, | 338 | .set_ct_kill = iwl6000_set_ct_threshold, |
323 | .set_calib_version = iwl6000_set_calib_version, | ||
324 | }, | 339 | }, |
325 | .manage_ibss_station = iwlagn_manage_ibss_station, | 340 | .manage_ibss_station = iwlagn_manage_ibss_station, |
326 | .update_bcast_stations = iwl_update_bcast_stations, | 341 | .update_bcast_stations = iwl_update_bcast_stations, |
@@ -396,7 +411,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { | |||
396 | .temp_ops = { | 411 | .temp_ops = { |
397 | .temperature = iwlagn_temperature, | 412 | .temperature = iwlagn_temperature, |
398 | .set_ct_kill = iwl6000_set_ct_threshold, | 413 | .set_ct_kill = iwl6000_set_ct_threshold, |
399 | .set_calib_version = iwl6000_set_calib_version, | ||
400 | }, | 414 | }, |
401 | .manage_ibss_station = iwlagn_manage_ibss_station, | 415 | .manage_ibss_station = iwlagn_manage_ibss_station, |
402 | .update_bcast_stations = iwl_update_bcast_stations, | 416 | .update_bcast_stations = iwl_update_bcast_stations, |
@@ -419,6 +433,14 @@ static struct iwl_lib_ops iwl6000g2b_lib = { | |||
419 | } | 433 | } |
420 | }; | 434 | }; |
421 | 435 | ||
436 | static struct iwl_nic_ops iwl6050_nic_ops = { | ||
437 | .additional_nic_config = &iwl6050_additional_nic_config, | ||
438 | }; | ||
439 | |||
440 | static struct iwl_nic_ops iwl6050g2_nic_ops = { | ||
441 | .additional_nic_config = &iwl6050g2_additional_nic_config, | ||
442 | }; | ||
443 | |||
422 | static const struct iwl_ops iwl6000_ops = { | 444 | static const struct iwl_ops iwl6000_ops = { |
423 | .lib = &iwl6000_lib, | 445 | .lib = &iwl6000_lib, |
424 | .hcmd = &iwlagn_hcmd, | 446 | .hcmd = &iwlagn_hcmd, |
@@ -426,6 +448,22 @@ static const struct iwl_ops iwl6000_ops = { | |||
426 | .led = &iwlagn_led_ops, | 448 | .led = &iwlagn_led_ops, |
427 | }; | 449 | }; |
428 | 450 | ||
451 | static const struct iwl_ops iwl6050_ops = { | ||
452 | .lib = &iwl6000_lib, | ||
453 | .hcmd = &iwlagn_hcmd, | ||
454 | .utils = &iwlagn_hcmd_utils, | ||
455 | .led = &iwlagn_led_ops, | ||
456 | .nic = &iwl6050_nic_ops, | ||
457 | }; | ||
458 | |||
459 | static const struct iwl_ops iwl6050g2_ops = { | ||
460 | .lib = &iwl6000_lib, | ||
461 | .hcmd = &iwlagn_hcmd, | ||
462 | .utils = &iwlagn_hcmd_utils, | ||
463 | .led = &iwlagn_led_ops, | ||
464 | .nic = &iwl6050g2_nic_ops, | ||
465 | }; | ||
466 | |||
429 | static const struct iwl_ops iwl6000g2b_ops = { | 467 | static const struct iwl_ops iwl6000g2b_ops = { |
430 | .lib = &iwl6000g2b_lib, | 468 | .lib = &iwl6000g2b_lib, |
431 | .hcmd = &iwlagn_bt_hcmd, | 469 | .hcmd = &iwlagn_bt_hcmd, |
@@ -433,30 +471,16 @@ static const struct iwl_ops iwl6000g2b_ops = { | |||
433 | .led = &iwlagn_led_ops, | 471 | .led = &iwlagn_led_ops, |
434 | }; | 472 | }; |
435 | 473 | ||
436 | struct iwl_cfg iwl6000g2a_2agn_cfg = { | 474 | static struct iwl_base_params iwl6000_base_params = { |
437 | .name = "6000 Series 2x2 AGN Gen2a", | ||
438 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
439 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
440 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
441 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
442 | .ops = &iwl6000_ops, | ||
443 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 475 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
444 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
445 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
446 | .num_of_queues = IWLAGN_NUM_QUEUES, | 476 | .num_of_queues = IWLAGN_NUM_QUEUES, |
447 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | 477 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
448 | .mod_params = &iwlagn_mod_params, | ||
449 | .valid_tx_ant = ANT_AB, | ||
450 | .valid_rx_ant = ANT_AB, | ||
451 | .pll_cfg_val = 0, | 478 | .pll_cfg_val = 0, |
452 | .set_l0s = true, | 479 | .set_l0s = true, |
453 | .use_bsm = false, | 480 | .use_bsm = false, |
454 | .pa_type = IWL_PA_SYSTEM, | ||
455 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 481 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
456 | .shadow_ram_support = true, | 482 | .shadow_ram_support = true, |
457 | .ht_greenfield_support = true, | ||
458 | .led_compensation = 51, | 483 | .led_compensation = 51, |
459 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
460 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 484 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
461 | .supports_idle = true, | 485 | .supports_idle = true, |
462 | .adv_thermal_throttle = true, | 486 | .adv_thermal_throttle = true, |
@@ -468,29 +492,16 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { | |||
468 | .ucode_tracing = true, | 492 | .ucode_tracing = true, |
469 | .sensitivity_calib_by_driver = true, | 493 | .sensitivity_calib_by_driver = true, |
470 | .chain_noise_calib_by_driver = true, | 494 | .chain_noise_calib_by_driver = true, |
471 | .need_dc_calib = true, | ||
472 | }; | 495 | }; |
473 | 496 | ||
474 | struct iwl_cfg iwl6000g2a_2abg_cfg = { | 497 | static struct iwl_base_params iwl6050_base_params = { |
475 | .name = "6000 Series 2x2 ABG Gen2a", | ||
476 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
477 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
478 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
479 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
480 | .ops = &iwl6000_ops, | ||
481 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 498 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
482 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
483 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
484 | .num_of_queues = IWLAGN_NUM_QUEUES, | 499 | .num_of_queues = IWLAGN_NUM_QUEUES, |
485 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | 500 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
486 | .mod_params = &iwlagn_mod_params, | ||
487 | .valid_tx_ant = ANT_AB, | ||
488 | .valid_rx_ant = ANT_AB, | ||
489 | .pll_cfg_val = 0, | 501 | .pll_cfg_val = 0, |
490 | .set_l0s = true, | 502 | .set_l0s = true, |
491 | .use_bsm = false, | 503 | .use_bsm = false, |
492 | .pa_type = IWL_PA_SYSTEM, | 504 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
493 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
494 | .shadow_ram_support = true, | 505 | .shadow_ram_support = true, |
495 | .led_compensation = 51, | 506 | .led_compensation = 51, |
496 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 507 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -498,11 +509,57 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = { | |||
498 | .adv_thermal_throttle = true, | 509 | .adv_thermal_throttle = true, |
499 | .support_ct_kill_exit = true, | 510 | .support_ct_kill_exit = true, |
500 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
501 | .chain_noise_scale = 1000, | 512 | .chain_noise_scale = 1500, |
502 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | 513 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, |
503 | .max_event_log_size = 512, | 514 | .max_event_log_size = 1024, |
515 | .ucode_tracing = true, | ||
504 | .sensitivity_calib_by_driver = true, | 516 | .sensitivity_calib_by_driver = true, |
505 | .chain_noise_calib_by_driver = true, | 517 | .chain_noise_calib_by_driver = true, |
518 | }; | ||
519 | |||
520 | static struct iwl_ht_params iwl6000_ht_params = { | ||
521 | .ht_greenfield_support = true, | ||
522 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
523 | }; | ||
524 | |||
525 | static struct iwl_bt_params iwl6000_bt_params = { | ||
526 | .bt_statistics = true, | ||
527 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
528 | .advanced_bt_coexist = true, | ||
529 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
530 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
531 | }; | ||
532 | |||
533 | struct iwl_cfg iwl6000g2a_2agn_cfg = { | ||
534 | .name = "6000 Series 2x2 AGN Gen2a", | ||
535 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
536 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
537 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
538 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
539 | .valid_tx_ant = ANT_AB, | ||
540 | .valid_rx_ant = ANT_AB, | ||
541 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
542 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
543 | .ops = &iwl6000_ops, | ||
544 | .mod_params = &iwlagn_mod_params, | ||
545 | .base_params = &iwl6000_base_params, | ||
546 | .ht_params = &iwl6000_ht_params, | ||
547 | .need_dc_calib = true, | ||
548 | }; | ||
549 | |||
550 | struct iwl_cfg iwl6000g2a_2abg_cfg = { | ||
551 | .name = "6000 Series 2x2 ABG Gen2a", | ||
552 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
553 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
554 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
555 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
556 | .valid_tx_ant = ANT_AB, | ||
557 | .valid_rx_ant = ANT_AB, | ||
558 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
559 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
560 | .ops = &iwl6000_ops, | ||
561 | .mod_params = &iwlagn_mod_params, | ||
562 | .base_params = &iwl6000_base_params, | ||
506 | .need_dc_calib = true, | 563 | .need_dc_calib = true, |
507 | }; | 564 | }; |
508 | 565 | ||
@@ -512,32 +569,13 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = { | |||
512 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 569 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
513 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 570 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
514 | .sku = IWL_SKU_G, | 571 | .sku = IWL_SKU_G, |
515 | .ops = &iwl6000_ops, | 572 | .valid_tx_ant = ANT_AB, |
516 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 573 | .valid_rx_ant = ANT_AB, |
517 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 574 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
518 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 575 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
519 | .num_of_queues = IWLAGN_NUM_QUEUES, | 576 | .ops = &iwl6000_ops, |
520 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
521 | .mod_params = &iwlagn_mod_params, | 577 | .mod_params = &iwlagn_mod_params, |
522 | .valid_tx_ant = ANT_AB, | 578 | .base_params = &iwl6000_base_params, |
523 | .valid_rx_ant = ANT_AB, | ||
524 | .pll_cfg_val = 0, | ||
525 | .set_l0s = true, | ||
526 | .use_bsm = false, | ||
527 | .pa_type = IWL_PA_SYSTEM, | ||
528 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
529 | .shadow_ram_support = true, | ||
530 | .led_compensation = 51, | ||
531 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
532 | .supports_idle = true, | ||
533 | .adv_thermal_throttle = true, | ||
534 | .support_ct_kill_exit = true, | ||
535 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
536 | .chain_noise_scale = 1000, | ||
537 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
538 | .max_event_log_size = 512, | ||
539 | .sensitivity_calib_by_driver = true, | ||
540 | .chain_noise_calib_by_driver = true, | ||
541 | .need_dc_calib = true, | 579 | .need_dc_calib = true, |
542 | }; | 580 | }; |
543 | 581 | ||
@@ -547,41 +585,18 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { | |||
547 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 585 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
548 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 586 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
549 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 587 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
550 | .ops = &iwl6000g2b_ops, | 588 | .valid_tx_ant = ANT_AB, |
551 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 589 | .valid_rx_ant = ANT_AB, |
552 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 590 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
553 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 591 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
554 | .num_of_queues = IWLAGN_NUM_QUEUES, | 592 | .ops = &iwl6000g2b_ops, |
555 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
556 | .mod_params = &iwlagn_mod_params, | 593 | .mod_params = &iwlagn_mod_params, |
557 | .valid_tx_ant = ANT_AB, | 594 | .base_params = &iwl6000_base_params, |
558 | .valid_rx_ant = ANT_AB, | 595 | .bt_params = &iwl6000_bt_params, |
559 | .pll_cfg_val = 0, | 596 | .ht_params = &iwl6000_ht_params, |
560 | .set_l0s = true, | ||
561 | .use_bsm = false, | ||
562 | .pa_type = IWL_PA_SYSTEM, | ||
563 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
564 | .shadow_ram_support = true, | ||
565 | .ht_greenfield_support = true, | ||
566 | .led_compensation = 51, | ||
567 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
568 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
569 | .supports_idle = true, | ||
570 | .adv_thermal_throttle = true, | ||
571 | .support_ct_kill_exit = true, | ||
572 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
573 | .chain_noise_scale = 1000, | ||
574 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
575 | .max_event_log_size = 512, | ||
576 | .sensitivity_calib_by_driver = true, | ||
577 | .chain_noise_calib_by_driver = true, | ||
578 | .need_dc_calib = true, | 597 | .need_dc_calib = true, |
579 | .bt_statistics = true, | ||
580 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 598 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
581 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 599 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
582 | .advanced_bt_coexist = true, | ||
583 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
584 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
585 | }; | 600 | }; |
586 | 601 | ||
587 | struct iwl_cfg iwl6000g2b_2abg_cfg = { | 602 | struct iwl_cfg iwl6000g2b_2abg_cfg = { |
@@ -590,39 +605,17 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { | |||
590 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 605 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
591 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 606 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
592 | .sku = IWL_SKU_A|IWL_SKU_G, | 607 | .sku = IWL_SKU_A|IWL_SKU_G, |
593 | .ops = &iwl6000g2b_ops, | 608 | .valid_tx_ant = ANT_AB, |
594 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 609 | .valid_rx_ant = ANT_AB, |
595 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 610 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
596 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 611 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
597 | .num_of_queues = IWLAGN_NUM_QUEUES, | 612 | .ops = &iwl6000g2b_ops, |
598 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
599 | .mod_params = &iwlagn_mod_params, | 613 | .mod_params = &iwlagn_mod_params, |
600 | .valid_tx_ant = ANT_AB, | 614 | .base_params = &iwl6000_base_params, |
601 | .valid_rx_ant = ANT_AB, | 615 | .bt_params = &iwl6000_bt_params, |
602 | .pll_cfg_val = 0, | ||
603 | .set_l0s = true, | ||
604 | .use_bsm = false, | ||
605 | .pa_type = IWL_PA_SYSTEM, | ||
606 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
607 | .shadow_ram_support = true, | ||
608 | .led_compensation = 51, | ||
609 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
610 | .supports_idle = true, | ||
611 | .adv_thermal_throttle = true, | ||
612 | .support_ct_kill_exit = true, | ||
613 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
614 | .chain_noise_scale = 1000, | ||
615 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
616 | .max_event_log_size = 512, | ||
617 | .sensitivity_calib_by_driver = true, | ||
618 | .chain_noise_calib_by_driver = true, | ||
619 | .need_dc_calib = true, | 616 | .need_dc_calib = true, |
620 | .bt_statistics = true, | ||
621 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 617 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
622 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 618 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
623 | .advanced_bt_coexist = true, | ||
624 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
625 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
626 | }; | 619 | }; |
627 | 620 | ||
628 | struct iwl_cfg iwl6000g2b_2bgn_cfg = { | 621 | struct iwl_cfg iwl6000g2b_2bgn_cfg = { |
@@ -631,41 +624,18 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { | |||
631 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 624 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
632 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 625 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
633 | .sku = IWL_SKU_G|IWL_SKU_N, | 626 | .sku = IWL_SKU_G|IWL_SKU_N, |
634 | .ops = &iwl6000g2b_ops, | 627 | .valid_tx_ant = ANT_AB, |
635 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 628 | .valid_rx_ant = ANT_AB, |
636 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 629 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
637 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 630 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
638 | .num_of_queues = IWLAGN_NUM_QUEUES, | 631 | .ops = &iwl6000g2b_ops, |
639 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
640 | .mod_params = &iwlagn_mod_params, | 632 | .mod_params = &iwlagn_mod_params, |
641 | .valid_tx_ant = ANT_AB, | 633 | .base_params = &iwl6000_base_params, |
642 | .valid_rx_ant = ANT_AB, | 634 | .bt_params = &iwl6000_bt_params, |
643 | .pll_cfg_val = 0, | 635 | .ht_params = &iwl6000_ht_params, |
644 | .set_l0s = true, | ||
645 | .use_bsm = false, | ||
646 | .pa_type = IWL_PA_SYSTEM, | ||
647 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
648 | .shadow_ram_support = true, | ||
649 | .ht_greenfield_support = true, | ||
650 | .led_compensation = 51, | ||
651 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
652 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
653 | .supports_idle = true, | ||
654 | .adv_thermal_throttle = true, | ||
655 | .support_ct_kill_exit = true, | ||
656 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
657 | .chain_noise_scale = 1000, | ||
658 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
659 | .max_event_log_size = 512, | ||
660 | .sensitivity_calib_by_driver = true, | ||
661 | .chain_noise_calib_by_driver = true, | ||
662 | .need_dc_calib = true, | 636 | .need_dc_calib = true, |
663 | .bt_statistics = true, | ||
664 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 637 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
665 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 638 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
666 | .advanced_bt_coexist = true, | ||
667 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
668 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
669 | }; | 639 | }; |
670 | 640 | ||
671 | struct iwl_cfg iwl6000g2b_2bg_cfg = { | 641 | struct iwl_cfg iwl6000g2b_2bg_cfg = { |
@@ -674,39 +644,17 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { | |||
674 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 644 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
675 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 645 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
676 | .sku = IWL_SKU_G, | 646 | .sku = IWL_SKU_G, |
677 | .ops = &iwl6000g2b_ops, | 647 | .valid_tx_ant = ANT_AB, |
678 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 648 | .valid_rx_ant = ANT_AB, |
679 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 649 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
680 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 650 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
681 | .num_of_queues = IWLAGN_NUM_QUEUES, | 651 | .ops = &iwl6000g2b_ops, |
682 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
683 | .mod_params = &iwlagn_mod_params, | 652 | .mod_params = &iwlagn_mod_params, |
684 | .valid_tx_ant = ANT_AB, | 653 | .base_params = &iwl6000_base_params, |
685 | .valid_rx_ant = ANT_AB, | 654 | .bt_params = &iwl6000_bt_params, |
686 | .pll_cfg_val = 0, | ||
687 | .set_l0s = true, | ||
688 | .use_bsm = false, | ||
689 | .pa_type = IWL_PA_SYSTEM, | ||
690 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
691 | .shadow_ram_support = true, | ||
692 | .led_compensation = 51, | ||
693 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
694 | .supports_idle = true, | ||
695 | .adv_thermal_throttle = true, | ||
696 | .support_ct_kill_exit = true, | ||
697 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
698 | .chain_noise_scale = 1000, | ||
699 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
700 | .max_event_log_size = 512, | ||
701 | .sensitivity_calib_by_driver = true, | ||
702 | .chain_noise_calib_by_driver = true, | ||
703 | .need_dc_calib = true, | 655 | .need_dc_calib = true, |
704 | .bt_statistics = true, | ||
705 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 656 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
706 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 657 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
707 | .advanced_bt_coexist = true, | ||
708 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
709 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
710 | }; | 658 | }; |
711 | 659 | ||
712 | struct iwl_cfg iwl6000g2b_bgn_cfg = { | 660 | struct iwl_cfg iwl6000g2b_bgn_cfg = { |
@@ -715,41 +663,18 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { | |||
715 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 663 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
716 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 664 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
717 | .sku = IWL_SKU_G|IWL_SKU_N, | 665 | .sku = IWL_SKU_G|IWL_SKU_N, |
718 | .ops = &iwl6000g2b_ops, | 666 | .valid_tx_ant = ANT_A, |
719 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 667 | .valid_rx_ant = ANT_AB, |
720 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 668 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
721 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 669 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
722 | .num_of_queues = IWLAGN_NUM_QUEUES, | 670 | .ops = &iwl6000g2b_ops, |
723 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
724 | .mod_params = &iwlagn_mod_params, | 671 | .mod_params = &iwlagn_mod_params, |
725 | .valid_tx_ant = ANT_A, | 672 | .base_params = &iwl6000_base_params, |
726 | .valid_rx_ant = ANT_AB, | 673 | .bt_params = &iwl6000_bt_params, |
727 | .pll_cfg_val = 0, | 674 | .ht_params = &iwl6000_ht_params, |
728 | .set_l0s = true, | ||
729 | .use_bsm = false, | ||
730 | .pa_type = IWL_PA_SYSTEM, | ||
731 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
732 | .shadow_ram_support = true, | ||
733 | .ht_greenfield_support = true, | ||
734 | .led_compensation = 51, | ||
735 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
736 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
737 | .supports_idle = true, | ||
738 | .adv_thermal_throttle = true, | ||
739 | .support_ct_kill_exit = true, | ||
740 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
741 | .chain_noise_scale = 1000, | ||
742 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
743 | .max_event_log_size = 512, | ||
744 | .sensitivity_calib_by_driver = true, | ||
745 | .chain_noise_calib_by_driver = true, | ||
746 | .need_dc_calib = true, | 675 | .need_dc_calib = true, |
747 | .bt_statistics = true, | ||
748 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 676 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
749 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 677 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
750 | .advanced_bt_coexist = true, | ||
751 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
752 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
753 | }; | 678 | }; |
754 | 679 | ||
755 | struct iwl_cfg iwl6000g2b_bg_cfg = { | 680 | struct iwl_cfg iwl6000g2b_bg_cfg = { |
@@ -758,39 +683,17 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { | |||
758 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | 683 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, |
759 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | 684 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, |
760 | .sku = IWL_SKU_G, | 685 | .sku = IWL_SKU_G, |
761 | .ops = &iwl6000g2b_ops, | 686 | .valid_tx_ant = ANT_A, |
762 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 687 | .valid_rx_ant = ANT_AB, |
763 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | 688 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
764 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | 689 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
765 | .num_of_queues = IWLAGN_NUM_QUEUES, | 690 | .ops = &iwl6000g2b_ops, |
766 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
767 | .mod_params = &iwlagn_mod_params, | 691 | .mod_params = &iwlagn_mod_params, |
768 | .valid_tx_ant = ANT_A, | 692 | .base_params = &iwl6000_base_params, |
769 | .valid_rx_ant = ANT_AB, | 693 | .bt_params = &iwl6000_bt_params, |
770 | .pll_cfg_val = 0, | ||
771 | .set_l0s = true, | ||
772 | .use_bsm = false, | ||
773 | .pa_type = IWL_PA_SYSTEM, | ||
774 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
775 | .shadow_ram_support = true, | ||
776 | .led_compensation = 51, | ||
777 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
778 | .supports_idle = true, | ||
779 | .adv_thermal_throttle = true, | ||
780 | .support_ct_kill_exit = true, | ||
781 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE, | ||
782 | .chain_noise_scale = 1000, | ||
783 | .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, | ||
784 | .max_event_log_size = 512, | ||
785 | .sensitivity_calib_by_driver = true, | ||
786 | .chain_noise_calib_by_driver = true, | ||
787 | .need_dc_calib = true, | 694 | .need_dc_calib = true, |
788 | .bt_statistics = true, | ||
789 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | 695 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
790 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | 696 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, |
791 | .advanced_bt_coexist = true, | ||
792 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
793 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
794 | }; | 697 | }; |
795 | 698 | ||
796 | /* | 699 | /* |
@@ -802,35 +705,15 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
802 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 705 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
803 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 706 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
804 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 707 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
805 | .ops = &iwl6000_ops, | 708 | .valid_tx_ant = ANT_BC, |
806 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 709 | .valid_rx_ant = ANT_BC, |
807 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 710 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
808 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 711 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
809 | .num_of_queues = IWLAGN_NUM_QUEUES, | 712 | .ops = &iwl6000_ops, |
810 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
811 | .mod_params = &iwlagn_mod_params, | 713 | .mod_params = &iwlagn_mod_params, |
812 | .valid_tx_ant = ANT_BC, | 714 | .base_params = &iwl6000_base_params, |
813 | .valid_rx_ant = ANT_BC, | 715 | .ht_params = &iwl6000_ht_params, |
814 | .pll_cfg_val = 0, | ||
815 | .set_l0s = true, | ||
816 | .use_bsm = false, | ||
817 | .pa_type = IWL_PA_INTERNAL, | 716 | .pa_type = IWL_PA_INTERNAL, |
818 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
819 | .shadow_ram_support = true, | ||
820 | .ht_greenfield_support = true, | ||
821 | .led_compensation = 51, | ||
822 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
823 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
824 | .supports_idle = true, | ||
825 | .adv_thermal_throttle = true, | ||
826 | .support_ct_kill_exit = true, | ||
827 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
828 | .chain_noise_scale = 1000, | ||
829 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
830 | .max_event_log_size = 1024, | ||
831 | .ucode_tracing = true, | ||
832 | .sensitivity_calib_by_driver = true, | ||
833 | .chain_noise_calib_by_driver = true, | ||
834 | }; | 717 | }; |
835 | 718 | ||
836 | struct iwl_cfg iwl6000i_2abg_cfg = { | 719 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -839,33 +722,14 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
839 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 722 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
840 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 723 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
841 | .sku = IWL_SKU_A|IWL_SKU_G, | 724 | .sku = IWL_SKU_A|IWL_SKU_G, |
842 | .ops = &iwl6000_ops, | 725 | .valid_tx_ant = ANT_BC, |
843 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 726 | .valid_rx_ant = ANT_BC, |
844 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 727 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
845 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 728 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
846 | .num_of_queues = IWLAGN_NUM_QUEUES, | 729 | .ops = &iwl6000_ops, |
847 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
848 | .mod_params = &iwlagn_mod_params, | 730 | .mod_params = &iwlagn_mod_params, |
849 | .valid_tx_ant = ANT_BC, | 731 | .base_params = &iwl6000_base_params, |
850 | .valid_rx_ant = ANT_BC, | ||
851 | .pll_cfg_val = 0, | ||
852 | .set_l0s = true, | ||
853 | .use_bsm = false, | ||
854 | .pa_type = IWL_PA_INTERNAL, | 732 | .pa_type = IWL_PA_INTERNAL, |
855 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
856 | .shadow_ram_support = true, | ||
857 | .led_compensation = 51, | ||
858 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
859 | .supports_idle = true, | ||
860 | .adv_thermal_throttle = true, | ||
861 | .support_ct_kill_exit = true, | ||
862 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
863 | .chain_noise_scale = 1000, | ||
864 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
865 | .max_event_log_size = 1024, | ||
866 | .ucode_tracing = true, | ||
867 | .sensitivity_calib_by_driver = true, | ||
868 | .chain_noise_calib_by_driver = true, | ||
869 | }; | 733 | }; |
870 | 734 | ||
871 | struct iwl_cfg iwl6000i_2bg_cfg = { | 735 | struct iwl_cfg iwl6000i_2bg_cfg = { |
@@ -874,33 +738,14 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
874 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 738 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
875 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 739 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
876 | .sku = IWL_SKU_G, | 740 | .sku = IWL_SKU_G, |
877 | .ops = &iwl6000_ops, | 741 | .valid_tx_ant = ANT_BC, |
878 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 742 | .valid_rx_ant = ANT_BC, |
879 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 743 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
880 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 744 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
881 | .num_of_queues = IWLAGN_NUM_QUEUES, | 745 | .ops = &iwl6000_ops, |
882 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
883 | .mod_params = &iwlagn_mod_params, | 746 | .mod_params = &iwlagn_mod_params, |
884 | .valid_tx_ant = ANT_BC, | 747 | .base_params = &iwl6000_base_params, |
885 | .valid_rx_ant = ANT_BC, | ||
886 | .pll_cfg_val = 0, | ||
887 | .set_l0s = true, | ||
888 | .use_bsm = false, | ||
889 | .pa_type = IWL_PA_INTERNAL, | 748 | .pa_type = IWL_PA_INTERNAL, |
890 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
891 | .shadow_ram_support = true, | ||
892 | .led_compensation = 51, | ||
893 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
894 | .supports_idle = true, | ||
895 | .adv_thermal_throttle = true, | ||
896 | .support_ct_kill_exit = true, | ||
897 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
898 | .chain_noise_scale = 1000, | ||
899 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
900 | .max_event_log_size = 1024, | ||
901 | .ucode_tracing = true, | ||
902 | .sensitivity_calib_by_driver = true, | ||
903 | .chain_noise_calib_by_driver = true, | ||
904 | }; | 749 | }; |
905 | 750 | ||
906 | struct iwl_cfg iwl6050_2agn_cfg = { | 751 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -909,35 +754,14 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
909 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 754 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
910 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 755 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
911 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 756 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
757 | .valid_tx_ant = ANT_AB, | ||
758 | .valid_rx_ant = ANT_AB, | ||
912 | .ops = &iwl6000_ops, | 759 | .ops = &iwl6000_ops, |
913 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
914 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 760 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
915 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, | 761 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
916 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
917 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
918 | .mod_params = &iwlagn_mod_params, | 762 | .mod_params = &iwlagn_mod_params, |
919 | .valid_tx_ant = ANT_AB, | 763 | .base_params = &iwl6050_base_params, |
920 | .valid_rx_ant = ANT_AB, | 764 | .ht_params = &iwl6000_ht_params, |
921 | .pll_cfg_val = 0, | ||
922 | .set_l0s = true, | ||
923 | .use_bsm = false, | ||
924 | .pa_type = IWL_PA_SYSTEM, | ||
925 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | ||
926 | .shadow_ram_support = true, | ||
927 | .ht_greenfield_support = true, | ||
928 | .led_compensation = 51, | ||
929 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
930 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
931 | .supports_idle = true, | ||
932 | .adv_thermal_throttle = true, | ||
933 | .support_ct_kill_exit = true, | ||
934 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
935 | .chain_noise_scale = 1500, | ||
936 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
937 | .max_event_log_size = 1024, | ||
938 | .ucode_tracing = true, | ||
939 | .sensitivity_calib_by_driver = true, | ||
940 | .chain_noise_calib_by_driver = true, | ||
941 | .need_dc_calib = true, | 765 | .need_dc_calib = true, |
942 | }; | 766 | }; |
943 | 767 | ||
@@ -947,35 +771,14 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { | |||
947 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 771 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
948 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 772 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
949 | .sku = IWL_SKU_G|IWL_SKU_N, | 773 | .sku = IWL_SKU_G|IWL_SKU_N, |
950 | .ops = &iwl6000_ops, | 774 | .valid_tx_ant = ANT_A, |
951 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 775 | .valid_rx_ant = ANT_AB, |
952 | .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, | 776 | .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, |
953 | .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, | 777 | .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, |
954 | .num_of_queues = IWLAGN_NUM_QUEUES, | 778 | .ops = &iwl6050g2_ops, |
955 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
956 | .mod_params = &iwlagn_mod_params, | 779 | .mod_params = &iwlagn_mod_params, |
957 | .valid_tx_ant = ANT_A, | 780 | .base_params = &iwl6050_base_params, |
958 | .valid_rx_ant = ANT_AB, | 781 | .ht_params = &iwl6000_ht_params, |
959 | .pll_cfg_val = 0, | ||
960 | .set_l0s = true, | ||
961 | .use_bsm = false, | ||
962 | .pa_type = IWL_PA_SYSTEM, | ||
963 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | ||
964 | .shadow_ram_support = true, | ||
965 | .ht_greenfield_support = true, | ||
966 | .led_compensation = 51, | ||
967 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
968 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
969 | .supports_idle = true, | ||
970 | .adv_thermal_throttle = true, | ||
971 | .support_ct_kill_exit = true, | ||
972 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
973 | .chain_noise_scale = 1500, | ||
974 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
975 | .max_event_log_size = 1024, | ||
976 | .ucode_tracing = true, | ||
977 | .sensitivity_calib_by_driver = true, | ||
978 | .chain_noise_calib_by_driver = true, | ||
979 | .need_dc_calib = true, | 782 | .need_dc_calib = true, |
980 | }; | 783 | }; |
981 | 784 | ||
@@ -985,33 +788,13 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
985 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 788 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
986 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 789 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
987 | .sku = IWL_SKU_A|IWL_SKU_G, | 790 | .sku = IWL_SKU_A|IWL_SKU_G, |
988 | .ops = &iwl6000_ops, | 791 | .valid_tx_ant = ANT_AB, |
989 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 792 | .valid_rx_ant = ANT_AB, |
990 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 793 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
991 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, | 794 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
992 | .num_of_queues = IWLAGN_NUM_QUEUES, | 795 | .ops = &iwl6050_ops, |
993 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
994 | .mod_params = &iwlagn_mod_params, | 796 | .mod_params = &iwlagn_mod_params, |
995 | .valid_tx_ant = ANT_AB, | 797 | .base_params = &iwl6050_base_params, |
996 | .valid_rx_ant = ANT_AB, | ||
997 | .pll_cfg_val = 0, | ||
998 | .set_l0s = true, | ||
999 | .use_bsm = false, | ||
1000 | .pa_type = IWL_PA_SYSTEM, | ||
1001 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | ||
1002 | .shadow_ram_support = true, | ||
1003 | .led_compensation = 51, | ||
1004 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1005 | .supports_idle = true, | ||
1006 | .adv_thermal_throttle = true, | ||
1007 | .support_ct_kill_exit = true, | ||
1008 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
1009 | .chain_noise_scale = 1500, | ||
1010 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | ||
1011 | .max_event_log_size = 1024, | ||
1012 | .ucode_tracing = true, | ||
1013 | .sensitivity_calib_by_driver = true, | ||
1014 | .chain_noise_calib_by_driver = true, | ||
1015 | .need_dc_calib = true, | 798 | .need_dc_calib = true, |
1016 | }; | 799 | }; |
1017 | 800 | ||
@@ -1021,38 +804,58 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
1021 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 804 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
1022 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 805 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
1023 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 806 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1024 | .ops = &iwl6000_ops, | 807 | .valid_tx_ant = ANT_ABC, |
1025 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 808 | .valid_rx_ant = ANT_ABC, |
1026 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 809 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
1027 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 810 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
1028 | .num_of_queues = IWLAGN_NUM_QUEUES, | 811 | .ops = &iwl6000_ops, |
1029 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
1030 | .mod_params = &iwlagn_mod_params, | 812 | .mod_params = &iwlagn_mod_params, |
1031 | .valid_tx_ant = ANT_ABC, | 813 | .base_params = &iwl6000_base_params, |
1032 | .valid_rx_ant = ANT_ABC, | 814 | .ht_params = &iwl6000_ht_params, |
1033 | .pll_cfg_val = 0, | 815 | .need_dc_calib = true, |
1034 | .set_l0s = true, | 816 | }; |
1035 | .use_bsm = false, | 817 | |
1036 | .pa_type = IWL_PA_SYSTEM, | 818 | struct iwl_cfg iwl130_bgn_cfg = { |
1037 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 819 | .name = "Intel(R) 130 Series 1x1 BGN", |
1038 | .shadow_ram_support = true, | 820 | .fw_name_pre = IWL6000G2B_FW_PRE, |
1039 | .ht_greenfield_support = true, | 821 | .ucode_api_max = IWL130_UCODE_API_MAX, |
1040 | .led_compensation = 51, | 822 | .ucode_api_min = IWL130_UCODE_API_MIN, |
1041 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 823 | .sku = IWL_SKU_G|IWL_SKU_N, |
1042 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 824 | .valid_tx_ant = ANT_A, |
1043 | .supports_idle = true, | 825 | .valid_rx_ant = ANT_A, |
1044 | .adv_thermal_throttle = true, | 826 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, |
1045 | .support_ct_kill_exit = true, | 827 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, |
1046 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 828 | .ops = &iwl6000g2b_ops, |
1047 | .chain_noise_scale = 1000, | 829 | .mod_params = &iwlagn_mod_params, |
1048 | .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, | 830 | .base_params = &iwl6000_base_params, |
1049 | .max_event_log_size = 1024, | 831 | .bt_params = &iwl6000_bt_params, |
1050 | .ucode_tracing = true, | 832 | .ht_params = &iwl6000_ht_params, |
1051 | .sensitivity_calib_by_driver = true, | 833 | .need_dc_calib = true, |
1052 | .chain_noise_calib_by_driver = true, | 834 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ |
835 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | ||
836 | }; | ||
837 | |||
838 | struct iwl_cfg iwl130_bg_cfg = { | ||
839 | .name = "Intel(R) 130 Series 1x2 BG", | ||
840 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
841 | .ucode_api_max = IWL130_UCODE_API_MAX, | ||
842 | .ucode_api_min = IWL130_UCODE_API_MIN, | ||
843 | .sku = IWL_SKU_G, | ||
844 | .valid_tx_ant = ANT_A, | ||
845 | .valid_rx_ant = ANT_A, | ||
846 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
847 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
848 | .ops = &iwl6000g2b_ops, | ||
849 | .mod_params = &iwlagn_mod_params, | ||
850 | .base_params = &iwl6000_base_params, | ||
851 | .bt_params = &iwl6000_bt_params, | ||
852 | .need_dc_calib = true, | ||
853 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
854 | .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, | ||
1053 | }; | 855 | }; |
1054 | 856 | ||
1055 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 857 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
1056 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); | 858 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); |
1057 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 859 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
1058 | MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 860 | MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
861 | MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 84ad62958535..4c5ab783737f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -631,7 +631,8 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) | |||
631 | } | 631 | } |
632 | 632 | ||
633 | spin_lock_irqsave(&priv->lock, flags); | 633 | spin_lock_irqsave(&priv->lock, flags); |
634 | if (priv->cfg->bt_statistics) { | 634 | if (priv->cfg->bt_params && |
635 | priv->cfg->bt_params->bt_statistics) { | ||
635 | rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> | 636 | rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> |
636 | rx.general.common); | 637 | rx.general.common); |
637 | ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); | 638 | ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); |
@@ -786,7 +787,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
786 | } | 787 | } |
787 | 788 | ||
788 | spin_lock_irqsave(&priv->lock, flags); | 789 | spin_lock_irqsave(&priv->lock, flags); |
789 | if (priv->cfg->bt_statistics) { | 790 | if (priv->cfg->bt_params && |
791 | priv->cfg->bt_params->bt_statistics) { | ||
790 | rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> | 792 | rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> |
791 | rx.general.common); | 793 | rx.general.common); |
792 | } else { | 794 | } else { |
@@ -801,7 +803,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
801 | 803 | ||
802 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); | 804 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); |
803 | rxon_chnum = le16_to_cpu(ctx->staging.channel); | 805 | rxon_chnum = le16_to_cpu(ctx->staging.channel); |
804 | if (priv->cfg->bt_statistics) { | 806 | if (priv->cfg->bt_params && |
807 | priv->cfg->bt_params->bt_statistics) { | ||
805 | stat_band24 = !!(((struct iwl_bt_notif_statistics *) | 808 | stat_band24 = !!(((struct iwl_bt_notif_statistics *) |
806 | stat_resp)->flag & | 809 | stat_resp)->flag & |
807 | STATISTICS_REPLY_FLG_BAND_24G_MSK); | 810 | STATISTICS_REPLY_FLG_BAND_24G_MSK); |
@@ -861,16 +864,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
861 | /* If this is the "chain_noise_num_beacons", determine: | 864 | /* If this is the "chain_noise_num_beacons", determine: |
862 | * 1) Disconnected antennas (using signal strengths) | 865 | * 1) Disconnected antennas (using signal strengths) |
863 | * 2) Differential gain (using silence noise) to balance receivers */ | 866 | * 2) Differential gain (using silence noise) to balance receivers */ |
864 | if (data->beacon_count != priv->cfg->chain_noise_num_beacons) | 867 | if (data->beacon_count != |
868 | priv->cfg->base_params->chain_noise_num_beacons) | ||
865 | return; | 869 | return; |
866 | 870 | ||
867 | /* Analyze signal for disconnected antenna */ | 871 | /* Analyze signal for disconnected antenna */ |
868 | average_sig[0] = | 872 | average_sig[0] = data->chain_signal_a / |
869 | (data->chain_signal_a) / priv->cfg->chain_noise_num_beacons; | 873 | priv->cfg->base_params->chain_noise_num_beacons; |
870 | average_sig[1] = | 874 | average_sig[1] = data->chain_signal_b / |
871 | (data->chain_signal_b) / priv->cfg->chain_noise_num_beacons; | 875 | priv->cfg->base_params->chain_noise_num_beacons; |
872 | average_sig[2] = | 876 | average_sig[2] = data->chain_signal_c / |
873 | (data->chain_signal_c) / priv->cfg->chain_noise_num_beacons; | 877 | priv->cfg->base_params->chain_noise_num_beacons; |
874 | 878 | ||
875 | if (average_sig[0] >= average_sig[1]) { | 879 | if (average_sig[0] >= average_sig[1]) { |
876 | max_average_sig = average_sig[0]; | 880 | max_average_sig = average_sig[0]; |
@@ -920,7 +924,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
920 | * To be safe, simply mask out any chains that we know | 924 | * To be safe, simply mask out any chains that we know |
921 | * are not on the device. | 925 | * are not on the device. |
922 | */ | 926 | */ |
923 | if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { | 927 | if (priv->cfg->bt_params && |
928 | priv->cfg->bt_params->advanced_bt_coexist && | ||
929 | priv->bt_full_concurrent) { | ||
924 | /* operated as 1x1 in full concurrency mode */ | 930 | /* operated as 1x1 in full concurrency mode */ |
925 | active_chains &= first_antenna(priv->hw_params.valid_rx_ant); | 931 | active_chains &= first_antenna(priv->hw_params.valid_rx_ant); |
926 | } else | 932 | } else |
@@ -967,12 +973,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
967 | active_chains); | 973 | active_chains); |
968 | 974 | ||
969 | /* Analyze noise for rx balance */ | 975 | /* Analyze noise for rx balance */ |
970 | average_noise[0] = | 976 | average_noise[0] = data->chain_noise_a / |
971 | ((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons); | 977 | priv->cfg->base_params->chain_noise_num_beacons; |
972 | average_noise[1] = | 978 | average_noise[1] = data->chain_noise_b / |
973 | ((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons); | 979 | priv->cfg->base_params->chain_noise_num_beacons; |
974 | average_noise[2] = | 980 | average_noise[2] = data->chain_noise_c / |
975 | ((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons); | 981 | priv->cfg->base_params->chain_noise_num_beacons; |
976 | 982 | ||
977 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 983 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
978 | if (!(data->disconn_array[i]) && | 984 | if (!(data->disconn_array[i]) && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 5391b4627397..a358d4334a1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -39,7 +39,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | |||
39 | int p = 0; | 39 | int p = 0; |
40 | u32 flag; | 40 | u32 flag; |
41 | 41 | ||
42 | if (priv->cfg->bt_statistics) | 42 | if (priv->cfg->bt_params && |
43 | priv->cfg->bt_params->bt_statistics) | ||
43 | flag = le32_to_cpu(priv->_agn.statistics_bt.flag); | 44 | flag = le32_to_cpu(priv->_agn.statistics_bt.flag); |
44 | else | 45 | else |
45 | flag = le32_to_cpu(priv->_agn.statistics.flag); | 46 | flag = le32_to_cpu(priv->_agn.statistics.flag); |
@@ -88,7 +89,8 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
88 | * the last statistics notification from uCode | 89 | * the last statistics notification from uCode |
89 | * might not reflect the current uCode activity | 90 | * might not reflect the current uCode activity |
90 | */ | 91 | */ |
91 | if (priv->cfg->bt_statistics) { | 92 | if (priv->cfg->bt_params && |
93 | priv->cfg->bt_params->bt_statistics) { | ||
92 | ofdm = &priv->_agn.statistics_bt.rx.ofdm; | 94 | ofdm = &priv->_agn.statistics_bt.rx.ofdm; |
93 | cck = &priv->_agn.statistics_bt.rx.cck; | 95 | cck = &priv->_agn.statistics_bt.rx.cck; |
94 | general = &priv->_agn.statistics_bt.rx.general.common; | 96 | general = &priv->_agn.statistics_bt.rx.general.common; |
@@ -534,7 +536,8 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
534 | * the last statistics notification from uCode | 536 | * the last statistics notification from uCode |
535 | * might not reflect the current uCode activity | 537 | * might not reflect the current uCode activity |
536 | */ | 538 | */ |
537 | if (priv->cfg->bt_statistics) { | 539 | if (priv->cfg->bt_params && |
540 | priv->cfg->bt_params->bt_statistics) { | ||
538 | tx = &priv->_agn.statistics_bt.tx; | 541 | tx = &priv->_agn.statistics_bt.tx; |
539 | accum_tx = &priv->_agn.accum_statistics_bt.tx; | 542 | accum_tx = &priv->_agn.accum_statistics_bt.tx; |
540 | delta_tx = &priv->_agn.delta_statistics_bt.tx; | 543 | delta_tx = &priv->_agn.delta_statistics_bt.tx; |
@@ -734,7 +737,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
734 | * the last statistics notification from uCode | 737 | * the last statistics notification from uCode |
735 | * might not reflect the current uCode activity | 738 | * might not reflect the current uCode activity |
736 | */ | 739 | */ |
737 | if (priv->cfg->bt_statistics) { | 740 | if (priv->cfg->bt_params && |
741 | priv->cfg->bt_params->bt_statistics) { | ||
738 | general = &priv->_agn.statistics_bt.general.common; | 742 | general = &priv->_agn.statistics_bt.general.common; |
739 | dbg = &priv->_agn.statistics_bt.general.common.dbg; | 743 | dbg = &priv->_agn.statistics_bt.general.common.dbg; |
740 | div = &priv->_agn.statistics_bt.general.common.div; | 744 | div = &priv->_agn.statistics_bt.general.common.div; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index d86902b83630..9ca6c91eaae6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -137,7 +137,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, | |||
137 | continue; | 137 | continue; |
138 | } | 138 | } |
139 | 139 | ||
140 | delta_g = (priv->cfg->chain_noise_scale * | 140 | delta_g = (priv->cfg->base_params->chain_noise_scale * |
141 | ((s32)average_noise[default_chain] - | 141 | ((s32)average_noise[default_chain] - |
142 | (s32)average_noise[i])) / 1500; | 142 | (s32)average_noise[i])) / 1500; |
143 | 143 | ||
@@ -222,7 +222,8 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | |||
222 | return; | 222 | return; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (priv->cfg->use_rts_for_aggregation && | 225 | if (priv->cfg->ht_params && |
226 | priv->cfg->ht_params->use_rts_for_aggregation && | ||
226 | info->flags & IEEE80211_TX_CTL_AMPDU) { | 227 | info->flags & IEEE80211_TX_CTL_AMPDU) { |
227 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | 228 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; |
228 | return; | 229 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index c92b2c0cbd91..a5dbfea1bfad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -59,7 +59,7 @@ void iwl_free_isr_ict(struct iwl_priv *priv) | |||
59 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | 59 | int iwl_alloc_isr_ict(struct iwl_priv *priv) |
60 | { | 60 | { |
61 | 61 | ||
62 | if (priv->cfg->use_isr_legacy) | 62 | if (priv->cfg->base_params->use_isr_legacy) |
63 | return 0; | 63 | return 0; |
64 | /* allocate shrared data table */ | 64 | /* allocate shrared data table */ |
65 | priv->_agn.ict_tbl_vir = | 65 | priv->_agn.ict_tbl_vir = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 299fd9d59604..f5445d575fec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include "iwl-agn.h" | 40 | #include "iwl-agn.h" |
41 | #include "iwl-sta.h" | 41 | #include "iwl-sta.h" |
42 | 42 | ||
43 | static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | 43 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) |
44 | { | 44 | { |
45 | return le32_to_cpup((__le32 *)&tx_resp->status + | 45 | return le32_to_cpup((__le32 *)&tx_resp->status + |
46 | tx_resp->frame_count) & MAX_SN; | 46 | tx_resp->frame_count) & MAX_SN; |
@@ -172,7 +172,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | |||
172 | 172 | ||
173 | static void iwlagn_set_tx_status(struct iwl_priv *priv, | 173 | static void iwlagn_set_tx_status(struct iwl_priv *priv, |
174 | struct ieee80211_tx_info *info, | 174 | struct ieee80211_tx_info *info, |
175 | struct iwl5000_tx_resp *tx_resp, | 175 | struct iwlagn_tx_resp *tx_resp, |
176 | int txq_id, bool is_agg) | 176 | int txq_id, bool is_agg) |
177 | { | 177 | { |
178 | u16 status = le16_to_cpu(tx_resp->status.status); | 178 | u16 status = le16_to_cpu(tx_resp->status.status); |
@@ -223,7 +223,7 @@ const char *iwl_get_agg_tx_fail_reason(u16 status) | |||
223 | 223 | ||
224 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | 224 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, |
225 | struct iwl_ht_agg *agg, | 225 | struct iwl_ht_agg *agg, |
226 | struct iwl5000_tx_resp *tx_resp, | 226 | struct iwlagn_tx_resp *tx_resp, |
227 | int txq_id, u16 start_idx) | 227 | int txq_id, u16 start_idx) |
228 | { | 228 | { |
229 | u16 status; | 229 | u16 status; |
@@ -390,7 +390,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
390 | int index = SEQ_TO_INDEX(sequence); | 390 | int index = SEQ_TO_INDEX(sequence); |
391 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 391 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
392 | struct ieee80211_tx_info *info; | 392 | struct ieee80211_tx_info *info; |
393 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | 393 | struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; |
394 | u32 status = le16_to_cpu(tx_resp->status.status); | 394 | u32 status = le16_to_cpu(tx_resp->status.status); |
395 | int tid; | 395 | int tid; |
396 | int sta_id; | 396 | int sta_id; |
@@ -408,8 +408,10 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
408 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); | 408 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
409 | memset(&info->status, 0, sizeof(info->status)); | 409 | memset(&info->status, 0, sizeof(info->status)); |
410 | 410 | ||
411 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | 411 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> |
412 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | 412 | IWLAGN_TX_RES_TID_POS; |
413 | sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> | ||
414 | IWLAGN_TX_RES_RA_POS; | ||
413 | 415 | ||
414 | spin_lock_irqsave(&priv->sta_lock, flags); | 416 | spin_lock_irqsave(&priv->sta_lock, flags); |
415 | if (txq->sched_retry) { | 417 | if (txq->sched_retry) { |
@@ -422,7 +424,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
422 | * notification again. | 424 | * notification again. |
423 | */ | 425 | */ |
424 | if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && | 426 | if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && |
425 | priv->cfg->advanced_bt_coexist) { | 427 | priv->cfg->bt_params && |
428 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
426 | IWL_WARN(priv, "receive reply tx with bt_kill\n"); | 429 | IWL_WARN(priv, "receive reply tx with bt_kill\n"); |
427 | } | 430 | } |
428 | iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | 431 | iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); |
@@ -490,7 +493,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr) | |||
490 | 493 | ||
491 | int iwlagn_send_tx_power(struct iwl_priv *priv) | 494 | int iwlagn_send_tx_power(struct iwl_priv *priv) |
492 | { | 495 | { |
493 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | 496 | struct iwlagn_tx_power_dbm_cmd tx_power_cmd; |
494 | u8 tx_ant_cfg_cmd; | 497 | u8 tx_ant_cfg_cmd; |
495 | 498 | ||
496 | /* half dBm need to multiply */ | 499 | /* half dBm need to multiply */ |
@@ -511,8 +514,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
511 | */ | 514 | */ |
512 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | 515 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; |
513 | } | 516 | } |
514 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | 517 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; |
515 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | 518 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; |
516 | 519 | ||
517 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | 520 | if (IWL_UCODE_API(priv->ucode_ver) == 1) |
518 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | 521 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; |
@@ -589,7 +592,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | |||
589 | size_t offset) | 592 | size_t offset) |
590 | { | 593 | { |
591 | u32 address = eeprom_indirect_address(priv, offset); | 594 | u32 address = eeprom_indirect_address(priv, offset); |
592 | BUG_ON(address >= priv->cfg->eeprom_size); | 595 | BUG_ON(address >= priv->cfg->base_params->eeprom_size); |
593 | return &priv->eeprom[address]; | 596 | return &priv->eeprom[address]; |
594 | } | 597 | } |
595 | 598 | ||
@@ -637,7 +640,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
637 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | 640 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ |
638 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | 641 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ |
639 | 642 | ||
640 | if (!priv->cfg->use_isr_legacy) | 643 | if (!priv->cfg->base_params->use_isr_legacy) |
641 | rb_timeout = RX_RB_TIMEOUT; | 644 | rb_timeout = RX_RB_TIMEOUT; |
642 | 645 | ||
643 | if (priv->cfg->mod_params->amsdu_size_8K) | 646 | if (priv->cfg->mod_params->amsdu_size_8K) |
@@ -1424,7 +1427,8 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1424 | * Internal scans are passive, so we can indiscriminately set | 1427 | * Internal scans are passive, so we can indiscriminately set |
1425 | * the BT ignore flag on 2.4 GHz since it applies to TX only. | 1428 | * the BT ignore flag on 2.4 GHz since it applies to TX only. |
1426 | */ | 1429 | */ |
1427 | if (priv->cfg->advanced_bt_coexist) | 1430 | if (priv->cfg->bt_params && |
1431 | priv->cfg->bt_params->advanced_bt_coexist) | ||
1428 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; | 1432 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; |
1429 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; | 1433 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; |
1430 | break; | 1434 | break; |
@@ -1463,10 +1467,12 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1463 | if (priv->cfg->scan_tx_antennas[band]) | 1467 | if (priv->cfg->scan_tx_antennas[band]) |
1464 | scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; | 1468 | scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; |
1465 | 1469 | ||
1466 | if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { | 1470 | if (priv->cfg->bt_params && |
1471 | priv->cfg->bt_params->advanced_bt_coexist && | ||
1472 | priv->bt_full_concurrent) { | ||
1467 | /* operated as 1x1 in full concurrency mode */ | 1473 | /* operated as 1x1 in full concurrency mode */ |
1468 | scan_tx_antennas = | 1474 | scan_tx_antennas = first_antenna( |
1469 | first_antenna(priv->cfg->scan_tx_antennas[band]); | 1475 | priv->cfg->scan_tx_antennas[band]); |
1470 | } | 1476 | } |
1471 | 1477 | ||
1472 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], | 1478 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], |
@@ -1487,7 +1493,9 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1487 | 1493 | ||
1488 | rx_ant = first_antenna(active_chains); | 1494 | rx_ant = first_antenna(active_chains); |
1489 | } | 1495 | } |
1490 | if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { | 1496 | if (priv->cfg->bt_params && |
1497 | priv->cfg->bt_params->advanced_bt_coexist && | ||
1498 | priv->bt_full_concurrent) { | ||
1491 | /* operated as 1x1 in full concurrency mode */ | 1499 | /* operated as 1x1 in full concurrency mode */ |
1492 | rx_ant = first_antenna(rx_ant); | 1500 | rx_ant = first_antenna(rx_ant); |
1493 | } | 1501 | } |
@@ -1777,7 +1785,10 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
1777 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != | 1785 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != |
1778 | sizeof(bt_cmd.bt3_lookup_table)); | 1786 | sizeof(bt_cmd.bt3_lookup_table)); |
1779 | 1787 | ||
1780 | bt_cmd.prio_boost = priv->cfg->bt_prio_boost; | 1788 | if (priv->cfg->bt_params) |
1789 | bt_cmd.prio_boost = priv->cfg->bt_params->bt_prio_boost; | ||
1790 | else | ||
1791 | bt_cmd.prio_boost = 0; | ||
1781 | bt_cmd.kill_ack_mask = priv->kill_ack_mask; | 1792 | bt_cmd.kill_ack_mask = priv->kill_ack_mask; |
1782 | bt_cmd.kill_cts_mask = priv->kill_cts_mask; | 1793 | bt_cmd.kill_cts_mask = priv->kill_cts_mask; |
1783 | bt_cmd.valid = priv->bt_valid; | 1794 | bt_cmd.valid = priv->bt_valid; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 57629fba3a7d..f865685fd5f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -2939,11 +2939,14 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2939 | * overwrite if needed, pass aggregation time limit | 2939 | * overwrite if needed, pass aggregation time limit |
2940 | * to uCode in uSec | 2940 | * to uCode in uSec |
2941 | */ | 2941 | */ |
2942 | if (priv && priv->cfg->agg_time_limit && | 2942 | if (priv && priv->cfg->bt_params && |
2943 | priv->cfg->agg_time_limit >= LINK_QUAL_AGG_TIME_LIMIT_MIN && | 2943 | priv->cfg->bt_params->agg_time_limit && |
2944 | priv->cfg->agg_time_limit <= LINK_QUAL_AGG_TIME_LIMIT_MAX) | 2944 | priv->cfg->bt_params->agg_time_limit >= |
2945 | LINK_QUAL_AGG_TIME_LIMIT_MIN && | ||
2946 | priv->cfg->bt_params->agg_time_limit <= | ||
2947 | LINK_QUAL_AGG_TIME_LIMIT_MAX) | ||
2945 | lq_cmd->agg_params.agg_time_limit = | 2948 | lq_cmd->agg_params.agg_time_limit = |
2946 | cpu_to_le16(priv->cfg->agg_time_limit); | 2949 | cpu_to_le16(priv->cfg->bt_params->agg_time_limit); |
2947 | } | 2950 | } |
2948 | 2951 | ||
2949 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2952 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 9490eced1198..1e08eb455474 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -73,7 +73,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
73 | int bcn_silence_a, bcn_silence_b, bcn_silence_c; | 73 | int bcn_silence_a, bcn_silence_b, bcn_silence_c; |
74 | int last_rx_noise; | 74 | int last_rx_noise; |
75 | 75 | ||
76 | if (priv->cfg->bt_statistics) | 76 | if (priv->cfg->bt_params && |
77 | priv->cfg->bt_params->bt_statistics) | ||
77 | rx_info = &(priv->_agn.statistics_bt.rx.general.common); | 78 | rx_info = &(priv->_agn.statistics_bt.rx.general.common); |
78 | else | 79 | else |
79 | rx_info = &(priv->_agn.statistics.rx.general); | 80 | rx_info = &(priv->_agn.statistics.rx.general); |
@@ -124,7 +125,8 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
124 | struct statistics_general_common *general, *accum_general; | 125 | struct statistics_general_common *general, *accum_general; |
125 | struct statistics_tx *tx, *accum_tx; | 126 | struct statistics_tx *tx, *accum_tx; |
126 | 127 | ||
127 | if (priv->cfg->bt_statistics) { | 128 | if (priv->cfg->bt_params && |
129 | priv->cfg->bt_params->bt_statistics) { | ||
128 | prev_stats = (__le32 *)&priv->_agn.statistics_bt; | 130 | prev_stats = (__le32 *)&priv->_agn.statistics_bt; |
129 | accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; | 131 | accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; |
130 | size = sizeof(struct iwl_bt_notif_statistics); | 132 | size = sizeof(struct iwl_bt_notif_statistics); |
@@ -183,7 +185,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
183 | unsigned int plcp_msec; | 185 | unsigned int plcp_msec; |
184 | unsigned long plcp_received_jiffies; | 186 | unsigned long plcp_received_jiffies; |
185 | 187 | ||
186 | if (priv->cfg->plcp_delta_threshold == | 188 | if (priv->cfg->base_params->plcp_delta_threshold == |
187 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { | 189 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { |
188 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); | 190 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); |
189 | return rc; | 191 | return rc; |
@@ -205,7 +207,8 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
205 | struct statistics_rx_phy *ofdm; | 207 | struct statistics_rx_phy *ofdm; |
206 | struct statistics_rx_ht_phy *ofdm_ht; | 208 | struct statistics_rx_ht_phy *ofdm_ht; |
207 | 209 | ||
208 | if (priv->cfg->bt_statistics) { | 210 | if (priv->cfg->bt_params && |
211 | priv->cfg->bt_params->bt_statistics) { | ||
209 | ofdm = &pkt->u.stats_bt.rx.ofdm; | 212 | ofdm = &pkt->u.stats_bt.rx.ofdm; |
210 | ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; | 213 | ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; |
211 | combined_plcp_delta = | 214 | combined_plcp_delta = |
@@ -229,7 +232,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
229 | 232 | ||
230 | if ((combined_plcp_delta > 0) && | 233 | if ((combined_plcp_delta > 0) && |
231 | ((combined_plcp_delta * 100) / plcp_msec) > | 234 | ((combined_plcp_delta * 100) / plcp_msec) > |
232 | priv->cfg->plcp_delta_threshold) { | 235 | priv->cfg->base_params->plcp_delta_threshold) { |
233 | /* | 236 | /* |
234 | * if plcp_err exceed the threshold, | 237 | * if plcp_err exceed the threshold, |
235 | * the following data is printed in csv format: | 238 | * the following data is printed in csv format: |
@@ -242,13 +245,13 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
242 | * plcp_msec | 245 | * plcp_msec |
243 | */ | 246 | */ |
244 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | 247 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " |
245 | "%u, %u, %u, %u, %d, %u mSecs\n", | 248 | "%u, %u, %u, %u, %d, %u mSecs\n", |
246 | priv->cfg->plcp_delta_threshold, | 249 | priv->cfg->base_params->plcp_delta_threshold, |
247 | le32_to_cpu(ofdm->plcp_err), | 250 | le32_to_cpu(ofdm->plcp_err), |
248 | le32_to_cpu(ofdm->plcp_err), | 251 | le32_to_cpu(ofdm->plcp_err), |
249 | le32_to_cpu(ofdm_ht->plcp_err), | 252 | le32_to_cpu(ofdm_ht->plcp_err), |
250 | le32_to_cpu(ofdm_ht->plcp_err), | 253 | le32_to_cpu(ofdm_ht->plcp_err), |
251 | combined_plcp_delta, plcp_msec); | 254 | combined_plcp_delta, plcp_msec); |
252 | 255 | ||
253 | rc = false; | 256 | rc = false; |
254 | } | 257 | } |
@@ -262,7 +265,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
262 | int change; | 265 | int change; |
263 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 266 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
264 | 267 | ||
265 | if (priv->cfg->bt_statistics) { | 268 | if (priv->cfg->bt_params && |
269 | priv->cfg->bt_params->bt_statistics) { | ||
266 | IWL_DEBUG_RX(priv, | 270 | IWL_DEBUG_RX(priv, |
267 | "Statistics notification received (%d vs %d).\n", | 271 | "Statistics notification received (%d vs %d).\n", |
268 | (int)sizeof(struct iwl_bt_notif_statistics), | 272 | (int)sizeof(struct iwl_bt_notif_statistics), |
@@ -300,7 +304,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
300 | 304 | ||
301 | iwl_recover_from_statistics(priv, pkt); | 305 | iwl_recover_from_statistics(priv, pkt); |
302 | 306 | ||
303 | if (priv->cfg->bt_statistics) | 307 | if (priv->cfg->bt_params && |
308 | priv->cfg->bt_params->bt_statistics) | ||
304 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, | 309 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, |
305 | sizeof(priv->_agn.statistics_bt)); | 310 | sizeof(priv->_agn.statistics_bt)); |
306 | else | 311 | else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 07b2c6cadf51..0c6c4d969706 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c | |||
@@ -114,7 +114,7 @@ static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | |||
114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | 114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
115 | bool within_margin = false; | 115 | bool within_margin = false; |
116 | 116 | ||
117 | if (priv->cfg->temperature_kelvin) | 117 | if (priv->cfg->base_params->temperature_kelvin) |
118 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 118 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
119 | 119 | ||
120 | if (!priv->thermal_throttle.advanced_tt) | 120 | if (!priv->thermal_throttle.advanced_tt) |
@@ -591,7 +591,7 @@ static void iwl_bg_tt_work(struct work_struct *work) | |||
591 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 591 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
592 | return; | 592 | return; |
593 | 593 | ||
594 | if (priv->cfg->temperature_kelvin) | 594 | if (priv->cfg->base_params->temperature_kelvin) |
595 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 595 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
596 | 596 | ||
597 | if (!priv->thermal_throttle.advanced_tt) | 597 | if (!priv->thermal_throttle.advanced_tt) |
@@ -640,7 +640,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
640 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | 640 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); |
641 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | 641 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); |
642 | 642 | ||
643 | if (priv->cfg->adv_thermal_throttle) { | 643 | if (priv->cfg->base_params->adv_thermal_throttle) { |
644 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | 644 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); |
645 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | 645 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * |
646 | IWL_TI_STATE_MAX, GFP_KERNEL); | 646 | IWL_TI_STATE_MAX, GFP_KERNEL); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 5950184d9860..77753b72f236 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -224,13 +224,13 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
224 | int ret; | 224 | int ret; |
225 | 225 | ||
226 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | 226 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || |
227 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 227 | (IWLAGN_FIRST_AMPDU_QUEUE + |
228 | <= txq_id)) { | 228 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { |
229 | IWL_WARN(priv, | 229 | IWL_WARN(priv, |
230 | "queue number out of range: %d, must be %d to %d\n", | 230 | "queue number out of range: %d, must be %d to %d\n", |
231 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | 231 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, |
232 | IWLAGN_FIRST_AMPDU_QUEUE + | 232 | IWLAGN_FIRST_AMPDU_QUEUE + |
233 | priv->cfg->num_of_ampdu_queues - 1); | 233 | priv->cfg->base_params->num_of_ampdu_queues - 1); |
234 | return -EINVAL; | 234 | return -EINVAL; |
235 | } | 235 | } |
236 | 236 | ||
@@ -286,13 +286,13 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
286 | u16 ssn_idx, u8 tx_fifo) | 286 | u16 ssn_idx, u8 tx_fifo) |
287 | { | 287 | { |
288 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | 288 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || |
289 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 289 | (IWLAGN_FIRST_AMPDU_QUEUE + |
290 | <= txq_id)) { | 290 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { |
291 | IWL_ERR(priv, | 291 | IWL_ERR(priv, |
292 | "queue number out of range: %d, must be %d to %d\n", | 292 | "queue number out of range: %d, must be %d to %d\n", |
293 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | 293 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, |
294 | IWLAGN_FIRST_AMPDU_QUEUE + | 294 | IWLAGN_FIRST_AMPDU_QUEUE + |
295 | priv->cfg->num_of_ampdu_queues - 1); | 295 | priv->cfg->base_params->num_of_ampdu_queues - 1); |
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
@@ -350,7 +350,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
350 | if (ieee80211_is_back_req(fc)) | 350 | if (ieee80211_is_back_req(fc)) |
351 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | 351 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; |
352 | else if (info->band == IEEE80211_BAND_2GHZ && | 352 | else if (info->band == IEEE80211_BAND_2GHZ && |
353 | priv->cfg->advanced_bt_coexist && | 353 | priv->cfg->bt_params && |
354 | priv->cfg->bt_params->advanced_bt_coexist && | ||
354 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || | 355 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || |
355 | ieee80211_is_reassoc_req(fc) || | 356 | ieee80211_is_reassoc_req(fc) || |
356 | skb->protocol == cpu_to_be16(ETH_P_PAE))) | 357 | skb->protocol == cpu_to_be16(ETH_P_PAE))) |
@@ -444,7 +445,9 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
444 | rate_flags |= RATE_MCS_CCK_MSK; | 445 | rate_flags |= RATE_MCS_CCK_MSK; |
445 | 446 | ||
446 | /* Set up antennas */ | 447 | /* Set up antennas */ |
447 | if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { | 448 | if (priv->cfg->bt_params && |
449 | priv->cfg->bt_params->advanced_bt_coexist && | ||
450 | priv->bt_full_concurrent) { | ||
448 | /* operated as 1x1 in full concurrency mode */ | 451 | /* operated as 1x1 in full concurrency mode */ |
449 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 452 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
450 | first_antenna(priv->hw_params.valid_tx_ant)); | 453 | first_antenna(priv->hw_params.valid_tx_ant)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 8bfb0495a76b..e1dd76267dca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -307,7 +307,8 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) | |||
307 | goto restart; | 307 | goto restart; |
308 | } | 308 | } |
309 | 309 | ||
310 | if (priv->cfg->advanced_bt_coexist) { | 310 | if (priv->cfg->bt_params && |
311 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
311 | /* | 312 | /* |
312 | * Tell uCode we are ready to perform calibration | 313 | * Tell uCode we are ready to perform calibration |
313 | * need to perform this before any calibration | 314 | * need to perform this before any calibration |
@@ -330,7 +331,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) | |||
330 | { | 331 | { |
331 | struct iwl_wimax_coex_cmd coex_cmd; | 332 | struct iwl_wimax_coex_cmd coex_cmd; |
332 | 333 | ||
333 | if (priv->cfg->support_wimax_coexist) { | 334 | if (priv->cfg->base_params->support_wimax_coexist) { |
334 | /* UnMask wake up src at associated sleep */ | 335 | /* UnMask wake up src at associated sleep */ |
335 | coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; | 336 | coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; |
336 | 337 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 646864a26eaf..a6dce616ee3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2256,13 +2256,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
2256 | if (pieces.init_evtlog_size) | 2256 | if (pieces.init_evtlog_size) |
2257 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | 2257 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; |
2258 | else | 2258 | else |
2259 | priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; | 2259 | priv->_agn.init_evtlog_size = |
2260 | priv->cfg->base_params->max_event_log_size; | ||
2260 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; | 2261 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; |
2261 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; | 2262 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; |
2262 | if (pieces.inst_evtlog_size) | 2263 | if (pieces.inst_evtlog_size) |
2263 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | 2264 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; |
2264 | else | 2265 | else |
2265 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | 2266 | priv->_agn.inst_evtlog_size = |
2267 | priv->cfg->base_params->max_event_log_size; | ||
2266 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | 2268 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; |
2267 | 2269 | ||
2268 | if (ucode_capa.pan) { | 2270 | if (ucode_capa.pan) { |
@@ -2732,7 +2734,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2732 | spin_unlock_irqrestore(&priv->lock, flags); | 2734 | spin_unlock_irqrestore(&priv->lock, flags); |
2733 | priv->thermal_throttle.ct_kill_toggle = false; | 2735 | priv->thermal_throttle.ct_kill_toggle = false; |
2734 | 2736 | ||
2735 | if (priv->cfg->support_ct_kill_exit) { | 2737 | if (priv->cfg->base_params->support_ct_kill_exit) { |
2736 | adv_cmd.critical_temperature_enter = | 2738 | adv_cmd.critical_temperature_enter = |
2737 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 2739 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
2738 | adv_cmd.critical_temperature_exit = | 2740 | adv_cmd.critical_temperature_exit = |
@@ -2765,6 +2767,23 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2765 | } | 2767 | } |
2766 | } | 2768 | } |
2767 | 2769 | ||
2770 | static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) | ||
2771 | { | ||
2772 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
2773 | struct iwl_host_cmd cmd = { | ||
2774 | .id = CALIBRATION_CFG_CMD, | ||
2775 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
2776 | .data = &calib_cfg_cmd, | ||
2777 | }; | ||
2778 | |||
2779 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
2780 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
2781 | calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); | ||
2782 | |||
2783 | return iwl_send_cmd(priv, &cmd); | ||
2784 | } | ||
2785 | |||
2786 | |||
2768 | /** | 2787 | /** |
2769 | * iwl_alive_start - called after REPLY_ALIVE notification received | 2788 | * iwl_alive_start - called after REPLY_ALIVE notification received |
2770 | * from protocol/runtime uCode (initialization uCode's | 2789 | * from protocol/runtime uCode (initialization uCode's |
@@ -2801,6 +2820,10 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2801 | goto restart; | 2820 | goto restart; |
2802 | } | 2821 | } |
2803 | 2822 | ||
2823 | if (priv->hw_params.calib_rt_cfg) | ||
2824 | iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); | ||
2825 | |||
2826 | |||
2804 | /* After the ALIVE response, we can send host commands to the uCode */ | 2827 | /* After the ALIVE response, we can send host commands to the uCode */ |
2805 | set_bit(STATUS_ALIVE, &priv->status); | 2828 | set_bit(STATUS_ALIVE, &priv->status); |
2806 | 2829 | ||
@@ -2808,13 +2831,15 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2808 | /* Enable timer to monitor the driver queues */ | 2831 | /* Enable timer to monitor the driver queues */ |
2809 | mod_timer(&priv->monitor_recover, | 2832 | mod_timer(&priv->monitor_recover, |
2810 | jiffies + | 2833 | jiffies + |
2811 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | 2834 | msecs_to_jiffies( |
2835 | priv->cfg->base_params->monitor_recover_period)); | ||
2812 | } | 2836 | } |
2813 | 2837 | ||
2814 | if (iwl_is_rfkill(priv)) | 2838 | if (iwl_is_rfkill(priv)) |
2815 | return; | 2839 | return; |
2816 | 2840 | ||
2817 | if (priv->cfg->advanced_bt_coexist) { | 2841 | if (priv->cfg->bt_params && |
2842 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
2818 | /* Configure Bluetooth device coexistence support */ | 2843 | /* Configure Bluetooth device coexistence support */ |
2819 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | 2844 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; |
2820 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | 2845 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; |
@@ -2854,7 +2879,8 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2854 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | 2879 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
2855 | } | 2880 | } |
2856 | 2881 | ||
2857 | if (!priv->cfg->advanced_bt_coexist) { | 2882 | if (priv->cfg->bt_params && |
2883 | !priv->cfg->bt_params->advanced_bt_coexist) { | ||
2858 | /* Configure Bluetooth device coexistence support */ | 2884 | /* Configure Bluetooth device coexistence support */ |
2859 | priv->cfg->ops->hcmd->send_bt_config(priv); | 2885 | priv->cfg->ops->hcmd->send_bt_config(priv); |
2860 | } | 2886 | } |
@@ -2907,7 +2933,11 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2907 | 2933 | ||
2908 | /* reset BT coex data */ | 2934 | /* reset BT coex data */ |
2909 | priv->bt_status = 0; | 2935 | priv->bt_status = 0; |
2910 | priv->bt_traffic_load = priv->cfg->bt_init_traffic_load; | 2936 | if (priv->cfg->bt_params) |
2937 | priv->bt_traffic_load = | ||
2938 | priv->cfg->bt_params->bt_init_traffic_load; | ||
2939 | else | ||
2940 | priv->bt_traffic_load = 0; | ||
2911 | priv->bt_sco_active = false; | 2941 | priv->bt_sco_active = false; |
2912 | priv->bt_full_concurrent = false; | 2942 | priv->bt_full_concurrent = false; |
2913 | priv->bt_ci_compliance = 0; | 2943 | priv->bt_ci_compliance = 0; |
@@ -3201,7 +3231,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
3201 | } | 3231 | } |
3202 | 3232 | ||
3203 | if (priv->start_calib) { | 3233 | if (priv->start_calib) { |
3204 | if (priv->cfg->bt_statistics) { | 3234 | if (priv->cfg->bt_params && |
3235 | priv->cfg->bt_params->bt_statistics) { | ||
3205 | iwl_chain_noise_calibration(priv, | 3236 | iwl_chain_noise_calibration(priv, |
3206 | (void *)&priv->_agn.statistics_bt); | 3237 | (void *)&priv->_agn.statistics_bt); |
3207 | iwl_sensitivity_calibration(priv, | 3238 | iwl_sensitivity_calibration(priv, |
@@ -3400,7 +3431,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3400 | IEEE80211_HW_NEED_DTIM_PERIOD | | 3431 | IEEE80211_HW_NEED_DTIM_PERIOD | |
3401 | IEEE80211_HW_SPECTRUM_MGMT; | 3432 | IEEE80211_HW_SPECTRUM_MGMT; |
3402 | 3433 | ||
3403 | if (!priv->cfg->broken_powersave) | 3434 | if (!priv->cfg->base_params->broken_powersave) |
3404 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 3435 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
3405 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 3436 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
3406 | 3437 | ||
@@ -3725,7 +3756,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3725 | } | 3756 | } |
3726 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3757 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3727 | ret = 0; | 3758 | ret = 0; |
3728 | if (priv->cfg->use_rts_for_aggregation) { | 3759 | if (priv->cfg->ht_params && |
3760 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
3729 | struct iwl_station_priv *sta_priv = | 3761 | struct iwl_station_priv *sta_priv = |
3730 | (void *) sta->drv_priv; | 3762 | (void *) sta->drv_priv; |
3731 | /* | 3763 | /* |
@@ -3739,7 +3771,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3739 | } | 3771 | } |
3740 | break; | 3772 | break; |
3741 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3773 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3742 | if (priv->cfg->use_rts_for_aggregation) { | 3774 | if (priv->cfg->ht_params && |
3775 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
3743 | struct iwl_station_priv *sta_priv = | 3776 | struct iwl_station_priv *sta_priv = |
3744 | (void *) sta->drv_priv; | 3777 | (void *) sta->drv_priv; |
3745 | 3778 | ||
@@ -4057,7 +4090,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
4057 | priv->cfg->ops->lib->recover_from_tx_stall; | 4090 | priv->cfg->ops->lib->recover_from_tx_stall; |
4058 | } | 4091 | } |
4059 | 4092 | ||
4060 | if (!priv->cfg->use_isr_legacy) | 4093 | if (!priv->cfg->base_params->use_isr_legacy) |
4061 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 4094 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
4062 | iwl_irq_tasklet, (unsigned long)priv); | 4095 | iwl_irq_tasklet, (unsigned long)priv); |
4063 | else | 4096 | else |
@@ -4142,7 +4175,8 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
4142 | iwl_init_scan_params(priv); | 4175 | iwl_init_scan_params(priv); |
4143 | 4176 | ||
4144 | /* init bt coex */ | 4177 | /* init bt coex */ |
4145 | if (priv->cfg->advanced_bt_coexist) { | 4178 | if (priv->cfg->bt_params && |
4179 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
4146 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | 4180 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; |
4147 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | 4181 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; |
4148 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | 4182 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; |
@@ -4273,9 +4307,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4273 | /* Disabling hardware scan means that mac80211 will perform scans | 4307 | /* Disabling hardware scan means that mac80211 will perform scans |
4274 | * "the hard way", rather than using device's scan. */ | 4308 | * "the hard way", rather than using device's scan. */ |
4275 | if (cfg->mod_params->disable_hw_scan) { | 4309 | if (cfg->mod_params->disable_hw_scan) { |
4276 | if (iwl_debug_level & IWL_DL_INFO) | 4310 | dev_printk(KERN_DEBUG, &(pdev->dev), |
4277 | dev_printk(KERN_DEBUG, &(pdev->dev), | 4311 | "sw scan support is deprecated\n"); |
4278 | "Disabling hw_scan\n"); | ||
4279 | iwl_hw_ops.hw_scan = NULL; | 4312 | iwl_hw_ops.hw_scan = NULL; |
4280 | } | 4313 | } |
4281 | 4314 | ||
@@ -4788,6 +4821,22 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
4788 | {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, | 4821 | {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, |
4789 | {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, | 4822 | {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, |
4790 | {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, | 4823 | {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, |
4824 | |||
4825 | /* 100 Series WiFi */ | ||
4826 | {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)}, | ||
4827 | {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)}, | ||
4828 | {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)}, | ||
4829 | {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, | ||
4830 | {IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)}, | ||
4831 | |||
4832 | /* 130 Series WiFi */ | ||
4833 | {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)}, | ||
4834 | {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)}, | ||
4835 | {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)}, | ||
4836 | {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)}, | ||
4837 | {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)}, | ||
4838 | {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)}, | ||
4839 | |||
4791 | #endif /* CONFIG_IWL5000 */ | 4840 | #endif /* CONFIG_IWL5000 */ |
4792 | 4841 | ||
4793 | {0} | 4842 | {0} |
@@ -4876,7 +4925,8 @@ module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); | |||
4876 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | 4925 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); |
4877 | module_param_named( | 4926 | module_param_named( |
4878 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | 4927 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); |
4879 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4928 | MODULE_PARM_DESC(disable_hw_scan, |
4929 | "disable hardware scanning (default 0) (deprecated)"); | ||
4880 | 4930 | ||
4881 | module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, | 4931 | module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, |
4882 | S_IRUGO); | 4932 | S_IRUGO); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a372184ac210..eb3812a35862 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -92,6 +92,10 @@ extern struct iwl_cfg iwl6050_2abg_cfg; | |||
92 | extern struct iwl_cfg iwl6050g2_bgn_cfg; | 92 | extern struct iwl_cfg iwl6050g2_bgn_cfg; |
93 | extern struct iwl_cfg iwl1000_bgn_cfg; | 93 | extern struct iwl_cfg iwl1000_bgn_cfg; |
94 | extern struct iwl_cfg iwl1000_bg_cfg; | 94 | extern struct iwl_cfg iwl1000_bg_cfg; |
95 | extern struct iwl_cfg iwl100_bgn_cfg; | ||
96 | extern struct iwl_cfg iwl100_bg_cfg; | ||
97 | extern struct iwl_cfg iwl130_bgn_cfg; | ||
98 | extern struct iwl_cfg iwl130_bg_cfg; | ||
95 | 99 | ||
96 | extern struct iwl_mod_params iwlagn_mod_params; | 100 | extern struct iwl_mod_params iwlagn_mod_params; |
97 | extern struct iwl_hcmd_ops iwlagn_hcmd; | 101 | extern struct iwl_hcmd_ops iwlagn_hcmd; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 27e250c8d4b5..fe652568fec7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -420,12 +420,12 @@ struct iwl4965_tx_power_db { | |||
420 | 420 | ||
421 | /** | 421 | /** |
422 | * Command REPLY_TX_POWER_DBM_CMD = 0x98 | 422 | * Command REPLY_TX_POWER_DBM_CMD = 0x98 |
423 | * struct iwl5000_tx_power_dbm_cmd | 423 | * struct iwlagn_tx_power_dbm_cmd |
424 | */ | 424 | */ |
425 | #define IWL50_TX_POWER_AUTO 0x7f | 425 | #define IWLAGN_TX_POWER_AUTO 0x7f |
426 | #define IWL50_TX_POWER_NO_CLOSED (0x1 << 6) | 426 | #define IWLAGN_TX_POWER_NO_CLOSED (0x1 << 6) |
427 | 427 | ||
428 | struct iwl5000_tx_power_dbm_cmd { | 428 | struct iwlagn_tx_power_dbm_cmd { |
429 | s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ | 429 | s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ |
430 | u8 flags; | 430 | u8 flags; |
431 | s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ | 431 | s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ |
@@ -1042,7 +1042,7 @@ struct iwl4965_keyinfo { | |||
1042 | u8 key[16]; /* 16-byte unicast decryption key */ | 1042 | u8 key[16]; /* 16-byte unicast decryption key */ |
1043 | } __packed; | 1043 | } __packed; |
1044 | 1044 | ||
1045 | /* 5000 */ | 1045 | /* agn */ |
1046 | struct iwl_keyinfo { | 1046 | struct iwl_keyinfo { |
1047 | __le16 key_flags; | 1047 | __le16 key_flags; |
1048 | u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ | 1048 | u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ |
@@ -1168,7 +1168,7 @@ struct iwl4965_addsta_cmd { | |||
1168 | __le16 reserved2; | 1168 | __le16 reserved2; |
1169 | } __packed; | 1169 | } __packed; |
1170 | 1170 | ||
1171 | /* 5000 */ | 1171 | /* agn */ |
1172 | struct iwl_addsta_cmd { | 1172 | struct iwl_addsta_cmd { |
1173 | u8 mode; /* 1: modify existing, 0: add new station */ | 1173 | u8 mode; /* 1: modify existing, 0: add new station */ |
1174 | u8 reserved[3]; | 1174 | u8 reserved[3]; |
@@ -1959,12 +1959,12 @@ struct iwl4965_tx_resp { | |||
1959 | #define IWL50_TX_RES_INV_RATE_INDEX_MSK 0x80 | 1959 | #define IWL50_TX_RES_INV_RATE_INDEX_MSK 0x80 |
1960 | 1960 | ||
1961 | /* refer to ra_tid */ | 1961 | /* refer to ra_tid */ |
1962 | #define IWL50_TX_RES_TID_POS 0 | 1962 | #define IWLAGN_TX_RES_TID_POS 0 |
1963 | #define IWL50_TX_RES_TID_MSK 0x0f | 1963 | #define IWLAGN_TX_RES_TID_MSK 0x0f |
1964 | #define IWL50_TX_RES_RA_POS 4 | 1964 | #define IWLAGN_TX_RES_RA_POS 4 |
1965 | #define IWL50_TX_RES_RA_MSK 0xf0 | 1965 | #define IWLAGN_TX_RES_RA_MSK 0xf0 |
1966 | 1966 | ||
1967 | struct iwl5000_tx_resp { | 1967 | struct iwlagn_tx_resp { |
1968 | u8 frame_count; /* 1 no aggregation, >1 aggregation */ | 1968 | u8 frame_count; /* 1 no aggregation, >1 aggregation */ |
1969 | u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ | 1969 | u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ |
1970 | u8 failure_rts; /* # failures due to unsuccessful RTS */ | 1970 | u8 failure_rts; /* # failures due to unsuccessful RTS */ |
@@ -3800,6 +3800,21 @@ enum { | |||
3800 | 3800 | ||
3801 | #define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) | 3801 | #define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) |
3802 | 3802 | ||
3803 | /* This enum defines the bitmap of various calibrations to enable in both | ||
3804 | * init ucode and runtime ucode through CALIBRATION_CFG_CMD. | ||
3805 | */ | ||
3806 | enum iwl_ucode_calib_cfg { | ||
3807 | IWL_CALIB_CFG_RX_BB_IDX, | ||
3808 | IWL_CALIB_CFG_DC_IDX, | ||
3809 | IWL_CALIB_CFG_TX_IQ_IDX, | ||
3810 | IWL_CALIB_CFG_RX_IQ_IDX, | ||
3811 | IWL_CALIB_CFG_NOISE_IDX, | ||
3812 | IWL_CALIB_CFG_CRYSTAL_IDX, | ||
3813 | IWL_CALIB_CFG_TEMPERATURE_IDX, | ||
3814 | IWL_CALIB_CFG_PAPD_IDX, | ||
3815 | }; | ||
3816 | |||
3817 | |||
3803 | struct iwl_calib_cfg_elmnt_s { | 3818 | struct iwl_calib_cfg_elmnt_s { |
3804 | __le32 is_enable; | 3819 | __le32 is_enable; |
3805 | __le32 start; | 3820 | __le32 start; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5c568933ce48..516c55ae38aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -232,7 +232,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
232 | 232 | ||
233 | ht_info->ht_supported = true; | 233 | ht_info->ht_supported = true; |
234 | 234 | ||
235 | if (priv->cfg->ht_greenfield_support) | 235 | if (priv->cfg->ht_params && |
236 | priv->cfg->ht_params->ht_greenfield_support) | ||
236 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 237 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
237 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 238 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
238 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 239 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
@@ -247,11 +248,11 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
247 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 248 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
248 | 249 | ||
249 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | 250 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; |
250 | if (priv->cfg->ampdu_factor) | 251 | if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor) |
251 | ht_info->ampdu_factor = priv->cfg->ampdu_factor; | 252 | ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor; |
252 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | 253 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; |
253 | if (priv->cfg->ampdu_density) | 254 | if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density) |
254 | ht_info->ampdu_density = priv->cfg->ampdu_density; | 255 | ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density; |
255 | 256 | ||
256 | ht_info->mcs.rx_mask[0] = 0xFF; | 257 | ht_info->mcs.rx_mask[0] = 0xFF; |
257 | if (rx_chains_num >= 2) | 258 | if (rx_chains_num >= 2) |
@@ -850,8 +851,10 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); | |||
850 | */ | 851 | */ |
851 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | 852 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
852 | { | 853 | { |
853 | if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || | 854 | if (priv->cfg->bt_params && |
854 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | 855 | priv->cfg->bt_params->advanced_bt_coexist && |
856 | (priv->bt_full_concurrent || | ||
857 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | ||
855 | /* | 858 | /* |
856 | * only use chain 'A' in bt high traffic load or | 859 | * only use chain 'A' in bt high traffic load or |
857 | * full concurrency mode | 860 | * full concurrency mode |
@@ -919,8 +922,10 @@ void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
919 | else | 922 | else |
920 | active_chains = priv->hw_params.valid_rx_ant; | 923 | active_chains = priv->hw_params.valid_rx_ant; |
921 | 924 | ||
922 | if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || | 925 | if (priv->cfg->bt_params && |
923 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | 926 | priv->cfg->bt_params->advanced_bt_coexist && |
927 | (priv->bt_full_concurrent || | ||
928 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | ||
924 | /* | 929 | /* |
925 | * only use chain 'A' in bt high traffic load or | 930 | * only use chain 'A' in bt high traffic load or |
926 | * full concurrency mode | 931 | * full concurrency mode |
@@ -1362,7 +1367,7 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
1362 | * If not (unlikely), enable L0S, so there is at least some | 1367 | * If not (unlikely), enable L0S, so there is at least some |
1363 | * power savings, even without L1. | 1368 | * power savings, even without L1. |
1364 | */ | 1369 | */ |
1365 | if (priv->cfg->set_l0s) { | 1370 | if (priv->cfg->base_params->set_l0s) { |
1366 | lctl = iwl_pcie_link_ctl(priv); | 1371 | lctl = iwl_pcie_link_ctl(priv); |
1367 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | 1372 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == |
1368 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | 1373 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { |
@@ -1379,8 +1384,9 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
1379 | } | 1384 | } |
1380 | 1385 | ||
1381 | /* Configure analog phase-lock-loop before activating to D0A */ | 1386 | /* Configure analog phase-lock-loop before activating to D0A */ |
1382 | if (priv->cfg->pll_cfg_val) | 1387 | if (priv->cfg->base_params->pll_cfg_val) |
1383 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val); | 1388 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, |
1389 | priv->cfg->base_params->pll_cfg_val); | ||
1384 | 1390 | ||
1385 | /* | 1391 | /* |
1386 | * Set "initialization complete" bit to move adapter from | 1392 | * Set "initialization complete" bit to move adapter from |
@@ -1411,7 +1417,7 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
1411 | * do not disable clocks. This preserves any hardware bits already | 1417 | * do not disable clocks. This preserves any hardware bits already |
1412 | * set by default in "CLK_CTRL_REG" after reset. | 1418 | * set by default in "CLK_CTRL_REG" after reset. |
1413 | */ | 1419 | */ |
1414 | if (priv->cfg->use_bsm) | 1420 | if (priv->cfg->base_params->use_bsm) |
1415 | iwl_write_prph(priv, APMG_CLK_EN_REG, | 1421 | iwl_write_prph(priv, APMG_CLK_EN_REG, |
1416 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | 1422 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); |
1417 | else | 1423 | else |
@@ -2003,7 +2009,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2003 | 2009 | ||
2004 | mutex_lock(&priv->mutex); | 2010 | mutex_lock(&priv->mutex); |
2005 | 2011 | ||
2006 | if (WARN_ON(!iwl_is_ready_rf(priv))) { | 2012 | if (!iwl_is_ready_rf(priv)) { |
2013 | IWL_WARN(priv, "Try to add interface when device not ready\n"); | ||
2007 | err = -EINVAL; | 2014 | err = -EINVAL; |
2008 | goto out; | 2015 | goto out; |
2009 | } | 2016 | } |
@@ -2053,7 +2060,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2053 | goto out_err; | 2060 | goto out_err; |
2054 | } | 2061 | } |
2055 | 2062 | ||
2056 | if (priv->cfg->advanced_bt_coexist && | 2063 | if (priv->cfg->bt_params && |
2064 | priv->cfg->bt_params->advanced_bt_coexist && | ||
2057 | vif->type == NL80211_IFTYPE_ADHOC) { | 2065 | vif->type == NL80211_IFTYPE_ADHOC) { |
2058 | /* | 2066 | /* |
2059 | * pretend to have high BT traffic as long as we | 2067 | * pretend to have high BT traffic as long as we |
@@ -2316,7 +2324,8 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) | |||
2316 | { | 2324 | { |
2317 | if (!priv->txq) | 2325 | if (!priv->txq) |
2318 | priv->txq = kzalloc( | 2326 | priv->txq = kzalloc( |
2319 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | 2327 | sizeof(struct iwl_tx_queue) * |
2328 | priv->cfg->base_params->num_of_queues, | ||
2320 | GFP_KERNEL); | 2329 | GFP_KERNEL); |
2321 | if (!priv->txq) { | 2330 | if (!priv->txq) { |
2322 | IWL_ERR(priv, "Not enough memory for txq\n"); | 2331 | IWL_ERR(priv, "Not enough memory for txq\n"); |
@@ -2736,11 +2745,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) | |||
2736 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2745 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2737 | return -EINVAL; | 2746 | return -EINVAL; |
2738 | 2747 | ||
2739 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
2740 | IWL_DEBUG_INFO(priv, "scan in progress.\n"); | ||
2741 | return -EINVAL; | ||
2742 | } | ||
2743 | |||
2744 | if (mode >= IWL_MAX_FORCE_RESET) { | 2748 | if (mode >= IWL_MAX_FORCE_RESET) { |
2745 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); | 2749 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); |
2746 | return -EINVAL; | 2750 | return -EINVAL; |
@@ -2827,33 +2831,34 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) | |||
2827 | txq = &priv->txq[cnt]; | 2831 | txq = &priv->txq[cnt]; |
2828 | q = &txq->q; | 2832 | q = &txq->q; |
2829 | /* queue is empty, skip */ | 2833 | /* queue is empty, skip */ |
2830 | if (q->read_ptr != q->write_ptr) { | 2834 | if (q->read_ptr == q->write_ptr) |
2831 | if (q->read_ptr == q->last_read_ptr) { | 2835 | return 0; |
2832 | /* a queue has not been read from last time */ | 2836 | |
2833 | if (q->repeat_same_read_ptr > MAX_REPEAT) { | 2837 | if (q->read_ptr == q->last_read_ptr) { |
2834 | IWL_ERR(priv, | 2838 | /* a queue has not been read from last time */ |
2835 | "queue %d stuck %d time. Fw reload.\n", | 2839 | if (q->repeat_same_read_ptr > MAX_REPEAT) { |
2836 | q->id, q->repeat_same_read_ptr); | 2840 | IWL_ERR(priv, |
2837 | q->repeat_same_read_ptr = 0; | 2841 | "queue %d stuck %d time. Fw reload.\n", |
2838 | iwl_force_reset(priv, IWL_FW_RESET, false); | 2842 | q->id, q->repeat_same_read_ptr); |
2839 | } else { | ||
2840 | q->repeat_same_read_ptr++; | ||
2841 | IWL_DEBUG_RADIO(priv, | ||
2842 | "queue %d, not read %d time\n", | ||
2843 | q->id, | ||
2844 | q->repeat_same_read_ptr); | ||
2845 | if (!priv->cfg->advanced_bt_coexist) { | ||
2846 | mod_timer(&priv->monitor_recover, | ||
2847 | jiffies + msecs_to_jiffies( | ||
2848 | IWL_ONE_HUNDRED_MSECS)); | ||
2849 | return 1; | ||
2850 | } | ||
2851 | } | ||
2852 | return 0; | ||
2853 | } else { | ||
2854 | q->last_read_ptr = q->read_ptr; | ||
2855 | q->repeat_same_read_ptr = 0; | 2843 | q->repeat_same_read_ptr = 0; |
2844 | iwl_force_reset(priv, IWL_FW_RESET, false); | ||
2845 | } else { | ||
2846 | q->repeat_same_read_ptr++; | ||
2847 | IWL_DEBUG_RADIO(priv, | ||
2848 | "queue %d, not read %d time\n", | ||
2849 | q->id, | ||
2850 | q->repeat_same_read_ptr); | ||
2851 | if (priv->cfg->bt_params && | ||
2852 | !priv->cfg->bt_params->advanced_bt_coexist) { | ||
2853 | mod_timer(&priv->monitor_recover, | ||
2854 | jiffies + msecs_to_jiffies( | ||
2855 | IWL_ONE_HUNDRED_MSECS)); | ||
2856 | return 1; | ||
2857 | } | ||
2856 | } | 2858 | } |
2859 | } else { | ||
2860 | q->last_read_ptr = q->read_ptr; | ||
2861 | q->repeat_same_read_ptr = 0; | ||
2857 | } | 2862 | } |
2858 | return 0; | 2863 | return 0; |
2859 | } | 2864 | } |
@@ -2880,13 +2885,13 @@ void iwl_bg_monitor_recover(unsigned long data) | |||
2880 | return; | 2885 | return; |
2881 | } | 2886 | } |
2882 | } | 2887 | } |
2883 | if (priv->cfg->monitor_recover_period) { | 2888 | if (priv->cfg->base_params->monitor_recover_period) { |
2884 | /* | 2889 | /* |
2885 | * Reschedule the timer to occur in | 2890 | * Reschedule the timer to occur in |
2886 | * priv->cfg->monitor_recover_period | 2891 | * priv->cfg->base_params->monitor_recover_period |
2887 | */ | 2892 | */ |
2888 | mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( | 2893 | mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( |
2889 | priv->cfg->monitor_recover_period)); | 2894 | priv->cfg->base_params->monitor_recover_period)); |
2890 | } | 2895 | } |
2891 | } | 2896 | } |
2892 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | 2897 | EXPORT_SYMBOL(iwl_bg_monitor_recover); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f0302bfe85f5..6228b1c2ec96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -137,7 +137,6 @@ struct iwl_debugfs_ops { | |||
137 | struct iwl_temp_ops { | 137 | struct iwl_temp_ops { |
138 | void (*temperature)(struct iwl_priv *priv); | 138 | void (*temperature)(struct iwl_priv *priv); |
139 | void (*set_ct_kill)(struct iwl_priv *priv); | 139 | void (*set_ct_kill)(struct iwl_priv *priv); |
140 | void (*set_calib_version)(struct iwl_priv *priv); | ||
141 | }; | 140 | }; |
142 | 141 | ||
143 | struct iwl_tt_ops { | 142 | struct iwl_tt_ops { |
@@ -233,11 +232,17 @@ struct iwl_led_ops { | |||
233 | int (*off)(struct iwl_priv *priv); | 232 | int (*off)(struct iwl_priv *priv); |
234 | }; | 233 | }; |
235 | 234 | ||
235 | /* NIC specific ops */ | ||
236 | struct iwl_nic_ops { | ||
237 | void (*additional_nic_config)(struct iwl_priv *priv); | ||
238 | }; | ||
239 | |||
236 | struct iwl_ops { | 240 | struct iwl_ops { |
237 | const struct iwl_lib_ops *lib; | 241 | const struct iwl_lib_ops *lib; |
238 | const struct iwl_hcmd_ops *hcmd; | 242 | const struct iwl_hcmd_ops *hcmd; |
239 | const struct iwl_hcmd_utils_ops *utils; | 243 | const struct iwl_hcmd_utils_ops *utils; |
240 | const struct iwl_led_ops *led; | 244 | const struct iwl_led_ops *led; |
245 | const struct iwl_nic_ops *nic; | ||
241 | }; | 246 | }; |
242 | 247 | ||
243 | struct iwl_mod_params { | 248 | struct iwl_mod_params { |
@@ -250,20 +255,12 @@ struct iwl_mod_params { | |||
250 | int restart_fw; /* def: 1 = restart firmware */ | 255 | int restart_fw; /* def: 1 = restart firmware */ |
251 | }; | 256 | }; |
252 | 257 | ||
253 | /** | 258 | /* |
254 | * struct iwl_cfg | ||
255 | * @fw_name_pre: Firmware filename prefix. The api version and extension | ||
256 | * (.ucode) will be added to filename before loading from disk. The | ||
257 | * filename is constructed as fw_name_pre<api>.ucode. | ||
258 | * @ucode_api_max: Highest version of uCode API supported by driver. | ||
259 | * @ucode_api_min: Lowest version of uCode API supported by driver. | ||
260 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | ||
261 | * @max_ll_items: max number of OTP blocks | 259 | * @max_ll_items: max number of OTP blocks |
262 | * @shadow_ram_support: shadow support for OTP memory | 260 | * @shadow_ram_support: shadow support for OTP memory |
263 | * @led_compensation: compensate on the led on/off time per HW according | 261 | * @led_compensation: compensate on the led on/off time per HW according |
264 | * to the deviation to achieve the desired led frequency. | 262 | * to the deviation to achieve the desired led frequency. |
265 | * The detail algorithm is described in iwl-led.c | 263 | * The detail algorithm is described in iwl-led.c |
266 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
267 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 264 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
268 | * @adv_thermal_throttle: support advance thermal throttle | 265 | * @adv_thermal_throttle: support advance thermal throttle |
269 | * @support_ct_kill_exit: support ct kill exit condition | 266 | * @support_ct_kill_exit: support ct kill exit condition |
@@ -281,15 +278,73 @@ struct iwl_mod_params { | |||
281 | * sensitivity calibration operation | 278 | * sensitivity calibration operation |
282 | * @chain_noise_calib_by_driver: driver has the capability to perform | 279 | * @chain_noise_calib_by_driver: driver has the capability to perform |
283 | * chain noise calibration operation | 280 | * chain noise calibration operation |
284 | * @scan_antennas: available antenna for scan operation | 281 | */ |
282 | struct iwl_base_params { | ||
283 | int eeprom_size; | ||
284 | int num_of_queues; /* def: HW dependent */ | ||
285 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
286 | /* for iwl_apm_init() */ | ||
287 | u32 pll_cfg_val; | ||
288 | bool set_l0s; | ||
289 | bool use_bsm; | ||
290 | |||
291 | bool use_isr_legacy; | ||
292 | const u16 max_ll_items; | ||
293 | const bool shadow_ram_support; | ||
294 | u16 led_compensation; | ||
295 | const bool broken_powersave; | ||
296 | int chain_noise_num_beacons; | ||
297 | const bool supports_idle; | ||
298 | bool adv_thermal_throttle; | ||
299 | bool support_ct_kill_exit; | ||
300 | const bool support_wimax_coexist; | ||
301 | u8 plcp_delta_threshold; | ||
302 | s32 chain_noise_scale; | ||
303 | /* timer period for monitor the driver queues */ | ||
304 | u32 monitor_recover_period; | ||
305 | bool temperature_kelvin; | ||
306 | u32 max_event_log_size; | ||
307 | const bool tx_power_by_driver; | ||
308 | const bool ucode_tracing; | ||
309 | const bool sensitivity_calib_by_driver; | ||
310 | const bool chain_noise_calib_by_driver; | ||
311 | }; | ||
312 | /* | ||
285 | * @advanced_bt_coexist: support advanced bt coexist | 313 | * @advanced_bt_coexist: support advanced bt coexist |
286 | * @bt_init_traffic_load: specify initial bt traffic load | 314 | * @bt_init_traffic_load: specify initial bt traffic load |
287 | * @bt_prio_boost: default bt priority boost value | 315 | * @bt_prio_boost: default bt priority boost value |
288 | * @need_dc_calib: need to perform init dc calibration | ||
289 | * @bt_statistics: use BT version of statistics notification | 316 | * @bt_statistics: use BT version of statistics notification |
290 | * @agg_time_limit: maximum number of uSec in aggregation | 317 | * @agg_time_limit: maximum number of uSec in aggregation |
291 | * @ampdu_factor: Maximum A-MPDU length factor | 318 | * @ampdu_factor: Maximum A-MPDU length factor |
292 | * @ampdu_density: Minimum A-MPDU spacing | 319 | * @ampdu_density: Minimum A-MPDU spacing |
320 | */ | ||
321 | struct iwl_bt_params { | ||
322 | bool advanced_bt_coexist; | ||
323 | u8 bt_init_traffic_load; | ||
324 | u8 bt_prio_boost; | ||
325 | const bool bt_statistics; | ||
326 | u16 agg_time_limit; | ||
327 | u8 ampdu_factor; | ||
328 | u8 ampdu_density; | ||
329 | }; | ||
330 | /* | ||
331 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
332 | */ | ||
333 | struct iwl_ht_params { | ||
334 | const bool ht_greenfield_support; /* if used set to true */ | ||
335 | bool use_rts_for_aggregation; | ||
336 | }; | ||
337 | |||
338 | /** | ||
339 | * struct iwl_cfg | ||
340 | * @fw_name_pre: Firmware filename prefix. The api version and extension | ||
341 | * (.ucode) will be added to filename before loading from disk. The | ||
342 | * filename is constructed as fw_name_pre<api>.ucode. | ||
343 | * @ucode_api_max: Highest version of uCode API supported by driver. | ||
344 | * @ucode_api_min: Lowest version of uCode API supported by driver. | ||
345 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | ||
346 | * @need_dc_calib: need to perform init dc calibration | ||
347 | * @scan_antennas: available antenna for scan operation | ||
293 | * | 348 | * |
294 | * We enable the driver to be backward compatible wrt API version. The | 349 | * We enable the driver to be backward compatible wrt API version. The |
295 | * driver specifies which APIs it supports (with @ucode_api_max being the | 350 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -300,9 +355,9 @@ struct iwl_mod_params { | |||
300 | * | 355 | * |
301 | * For example, | 356 | * For example, |
302 | * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { | 357 | * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { |
303 | * Driver interacts with Firmware API version >= 2. | 358 | * Driver interacts with Firmware API version >= 2. |
304 | * } else { | 359 | * } else { |
305 | * Driver interacts with Firmware API version 1. | 360 | * Driver interacts with Firmware API version 1. |
306 | * } | 361 | * } |
307 | * | 362 | * |
308 | * The ideal usage of this infrastructure is to treat a new ucode API | 363 | * The ideal usage of this infrastructure is to treat a new ucode API |
@@ -313,59 +368,28 @@ struct iwl_mod_params { | |||
313 | * | 368 | * |
314 | */ | 369 | */ |
315 | struct iwl_cfg { | 370 | struct iwl_cfg { |
371 | /* params specific to an individual device within a device family */ | ||
316 | const char *name; | 372 | const char *name; |
317 | const char *fw_name_pre; | 373 | const char *fw_name_pre; |
318 | const unsigned int ucode_api_max; | 374 | const unsigned int ucode_api_max; |
319 | const unsigned int ucode_api_min; | 375 | const unsigned int ucode_api_min; |
376 | u8 valid_tx_ant; | ||
377 | u8 valid_rx_ant; | ||
320 | unsigned int sku; | 378 | unsigned int sku; |
321 | int eeprom_size; | ||
322 | u16 eeprom_ver; | 379 | u16 eeprom_ver; |
323 | u16 eeprom_calib_ver; | 380 | u16 eeprom_calib_ver; |
324 | int num_of_queues; /* def: HW dependent */ | ||
325 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
326 | const struct iwl_ops *ops; | 381 | const struct iwl_ops *ops; |
382 | /* module based parameters which can be set from modprobe cmd */ | ||
327 | const struct iwl_mod_params *mod_params; | 383 | const struct iwl_mod_params *mod_params; |
328 | u8 valid_tx_ant; | 384 | /* params not likely to change within a device family */ |
329 | u8 valid_rx_ant; | 385 | struct iwl_base_params *base_params; |
330 | 386 | /* params likely to change within a device family */ | |
331 | /* for iwl_apm_init() */ | 387 | struct iwl_ht_params *ht_params; |
332 | u32 pll_cfg_val; | 388 | struct iwl_bt_params *bt_params; |
333 | bool set_l0s; | 389 | enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */ |
334 | bool use_bsm; | 390 | const bool need_dc_calib; /* if used set to true */ |
335 | |||
336 | bool use_isr_legacy; | ||
337 | enum iwl_pa_type pa_type; | ||
338 | const u16 max_ll_items; | ||
339 | const bool shadow_ram_support; | ||
340 | const bool ht_greenfield_support; | ||
341 | u16 led_compensation; | ||
342 | const bool broken_powersave; | ||
343 | bool use_rts_for_aggregation; | ||
344 | int chain_noise_num_beacons; | ||
345 | const bool supports_idle; | ||
346 | bool adv_thermal_throttle; | ||
347 | bool support_ct_kill_exit; | ||
348 | const bool support_wimax_coexist; | ||
349 | u8 plcp_delta_threshold; | ||
350 | s32 chain_noise_scale; | ||
351 | /* timer period for monitor the driver queues */ | ||
352 | u32 monitor_recover_period; | ||
353 | bool temperature_kelvin; | ||
354 | u32 max_event_log_size; | ||
355 | const bool tx_power_by_driver; | ||
356 | const bool ucode_tracing; | ||
357 | const bool sensitivity_calib_by_driver; | ||
358 | const bool chain_noise_calib_by_driver; | ||
359 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; | 391 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; |
360 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; | 392 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; |
361 | bool advanced_bt_coexist; | ||
362 | u8 bt_init_traffic_load; | ||
363 | u8 bt_prio_boost; | ||
364 | const bool need_dc_calib; | ||
365 | const bool bt_statistics; | ||
366 | u16 agg_time_limit; | ||
367 | u8 ampdu_factor; | ||
368 | u8 ampdu_density; | ||
369 | }; | 393 | }; |
370 | 394 | ||
371 | /*************************** | 395 | /*************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index ecf98e7ac4ed..2aa15ab13892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -371,7 +371,8 @@ | |||
371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) | 371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) |
372 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) | 372 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) |
373 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | 373 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) |
374 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) | 374 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) |
375 | #define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008) | ||
375 | 376 | ||
376 | /* GIO Chicken Bits (PCI Express bus link power management) */ | 377 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
377 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 378 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 265ad01a443f..fc340311ea0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -356,7 +356,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
356 | const u8 *ptr; | 356 | const u8 *ptr; |
357 | char *buf; | 357 | char *buf; |
358 | u16 eeprom_ver; | 358 | u16 eeprom_ver; |
359 | size_t eeprom_len = priv->cfg->eeprom_size; | 359 | size_t eeprom_len = priv->cfg->base_params->eeprom_size; |
360 | buf_size = 4 * eeprom_len + 256; | 360 | buf_size = 4 * eeprom_len + 256; |
361 | 361 | ||
362 | if (eeprom_len % 16) { | 362 | if (eeprom_len % 16) { |
@@ -872,7 +872,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | |||
872 | struct iwl_rx_queue *rxq = &priv->rxq; | 872 | struct iwl_rx_queue *rxq = &priv->rxq; |
873 | char *buf; | 873 | char *buf; |
874 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 874 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + |
875 | (priv->cfg->num_of_queues * 32 * 8) + 400; | 875 | (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; |
876 | const u8 *ptr; | 876 | const u8 *ptr; |
877 | ssize_t ret; | 877 | ssize_t ret; |
878 | 878 | ||
@@ -971,7 +971,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
971 | int pos = 0; | 971 | int pos = 0; |
972 | int cnt; | 972 | int cnt; |
973 | int ret; | 973 | int ret; |
974 | const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues; | 974 | const size_t bufsz = sizeof(char) * 64 * |
975 | priv->cfg->base_params->num_of_queues; | ||
975 | 976 | ||
976 | if (!priv->txq) { | 977 | if (!priv->txq) { |
977 | IWL_ERR(priv, "txq not ready\n"); | 978 | IWL_ERR(priv, "txq not ready\n"); |
@@ -1415,7 +1416,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | |||
1415 | const size_t bufsz = sizeof(buf); | 1416 | const size_t bufsz = sizeof(buf); |
1416 | 1417 | ||
1417 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | 1418 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", |
1418 | priv->cfg->plcp_delta_threshold); | 1419 | priv->cfg->base_params->plcp_delta_threshold); |
1419 | 1420 | ||
1420 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1421 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1421 | } | 1422 | } |
@@ -1437,10 +1438,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | |||
1437 | return -EINVAL; | 1438 | return -EINVAL; |
1438 | if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || | 1439 | if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || |
1439 | (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) | 1440 | (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) |
1440 | priv->cfg->plcp_delta_threshold = | 1441 | priv->cfg->base_params->plcp_delta_threshold = |
1441 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; | 1442 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; |
1442 | else | 1443 | else |
1443 | priv->cfg->plcp_delta_threshold = plcp; | 1444 | priv->cfg->base_params->plcp_delta_threshold = plcp; |
1444 | return count; | 1445 | return count; |
1445 | } | 1446 | } |
1446 | 1447 | ||
@@ -1550,13 +1551,14 @@ static ssize_t iwl_dbgfs_monitor_period_write(struct file *file, | |||
1550 | if (sscanf(buf, "%d", &period) != 1) | 1551 | if (sscanf(buf, "%d", &period) != 1) |
1551 | return -EINVAL; | 1552 | return -EINVAL; |
1552 | if (period < 0 || period > IWL_MAX_MONITORING_PERIOD) | 1553 | if (period < 0 || period > IWL_MAX_MONITORING_PERIOD) |
1553 | priv->cfg->monitor_recover_period = IWL_DEF_MONITORING_PERIOD; | 1554 | priv->cfg->base_params->monitor_recover_period = |
1555 | IWL_DEF_MONITORING_PERIOD; | ||
1554 | else | 1556 | else |
1555 | priv->cfg->monitor_recover_period = period; | 1557 | priv->cfg->base_params->monitor_recover_period = period; |
1556 | 1558 | ||
1557 | if (priv->cfg->monitor_recover_period) | 1559 | if (priv->cfg->base_params->monitor_recover_period) |
1558 | mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( | 1560 | mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( |
1559 | priv->cfg->monitor_recover_period)); | 1561 | priv->cfg->base_params->monitor_recover_period)); |
1560 | else | 1562 | else |
1561 | del_timer_sync(&priv->monitor_recover); | 1563 | del_timer_sync(&priv->monitor_recover); |
1562 | return count; | 1564 | return count; |
@@ -1614,9 +1616,14 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, | |||
1614 | char buf[40]; | 1616 | char buf[40]; |
1615 | const size_t bufsz = sizeof(buf); | 1617 | const size_t bufsz = sizeof(buf); |
1616 | 1618 | ||
1617 | pos += scnprintf(buf + pos, bufsz - pos, "use %s for aggregation\n", | 1619 | if (priv->cfg->ht_params) |
1618 | (priv->cfg->use_rts_for_aggregation) ? "rts/cts" : | 1620 | pos += scnprintf(buf + pos, bufsz - pos, |
1619 | "cts-to-self"); | 1621 | "use %s for aggregation\n", |
1622 | (priv->cfg->ht_params->use_rts_for_aggregation) ? | ||
1623 | "rts/cts" : "cts-to-self"); | ||
1624 | else | ||
1625 | pos += scnprintf(buf + pos, bufsz - pos, "N/A"); | ||
1626 | |||
1620 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1627 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1621 | } | 1628 | } |
1622 | 1629 | ||
@@ -1629,6 +1636,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | |||
1629 | int buf_size; | 1636 | int buf_size; |
1630 | int rts; | 1637 | int rts; |
1631 | 1638 | ||
1639 | if (!priv->cfg->ht_params) | ||
1640 | return -EINVAL; | ||
1641 | |||
1632 | memset(buf, 0, sizeof(buf)); | 1642 | memset(buf, 0, sizeof(buf)); |
1633 | buf_size = min(count, sizeof(buf) - 1); | 1643 | buf_size = min(count, sizeof(buf) - 1); |
1634 | if (copy_from_user(buf, user_buf, buf_size)) | 1644 | if (copy_from_user(buf, user_buf, buf_size)) |
@@ -1636,9 +1646,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | |||
1636 | if (sscanf(buf, "%d", &rts) != 1) | 1646 | if (sscanf(buf, "%d", &rts) != 1) |
1637 | return -EINVAL; | 1647 | return -EINVAL; |
1638 | if (rts) | 1648 | if (rts) |
1639 | priv->cfg->use_rts_for_aggregation = true; | 1649 | priv->cfg->ht_params->use_rts_for_aggregation = true; |
1640 | else | 1650 | else |
1641 | priv->cfg->use_rts_for_aggregation = false; | 1651 | priv->cfg->ht_params->use_rts_for_aggregation = false; |
1642 | return count; | 1652 | return count; |
1643 | } | 1653 | } |
1644 | 1654 | ||
@@ -1716,7 +1726,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1716 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | 1726 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); |
1717 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | 1727 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); |
1718 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); | 1728 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); |
1719 | if (!priv->cfg->broken_powersave) { | 1729 | if (!priv->cfg->base_params->broken_powersave) { |
1720 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, | 1730 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, |
1721 | S_IWUSR | S_IRUSR); | 1731 | S_IWUSR | S_IRUSR); |
1722 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | 1732 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); |
@@ -1743,27 +1753,27 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1743 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); | 1753 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); |
1744 | DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); | 1754 | DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); |
1745 | 1755 | ||
1746 | if (priv->cfg->sensitivity_calib_by_driver) | 1756 | if (priv->cfg->base_params->sensitivity_calib_by_driver) |
1747 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 1757 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
1748 | if (priv->cfg->chain_noise_calib_by_driver) | 1758 | if (priv->cfg->base_params->chain_noise_calib_by_driver) |
1749 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 1759 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
1750 | if (priv->cfg->ucode_tracing) | 1760 | if (priv->cfg->base_params->ucode_tracing) |
1751 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 1761 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
1752 | if (priv->cfg->bt_statistics) | 1762 | if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics) |
1753 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); | 1763 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); |
1754 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); | 1764 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); |
1755 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 1765 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
1756 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 1766 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
1757 | DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); | 1767 | DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); |
1758 | if (priv->cfg->advanced_bt_coexist) | 1768 | if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) |
1759 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 1769 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); |
1760 | if (priv->cfg->sensitivity_calib_by_driver) | 1770 | if (priv->cfg->base_params->sensitivity_calib_by_driver) |
1761 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 1771 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, |
1762 | &priv->disable_sens_cal); | 1772 | &priv->disable_sens_cal); |
1763 | if (priv->cfg->chain_noise_calib_by_driver) | 1773 | if (priv->cfg->base_params->chain_noise_calib_by_driver) |
1764 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 1774 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
1765 | &priv->disable_chain_noise_cal); | 1775 | &priv->disable_chain_noise_cal); |
1766 | if (priv->cfg->tx_power_by_driver) | 1776 | if (priv->cfg->base_params->tx_power_by_driver) |
1767 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, | 1777 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, |
1768 | &priv->disable_tx_power_cal); | 1778 | &priv->disable_tx_power_cal); |
1769 | return 0; | 1779 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 74d25bcbfcb2..90a37a94c698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -684,6 +684,7 @@ struct iwl_sensitivity_ranges { | |||
684 | * @ct_kill_threshold: temperature threshold | 684 | * @ct_kill_threshold: temperature threshold |
685 | * @beacon_time_tsf_bits: number of valid tsf bits for beacon time | 685 | * @beacon_time_tsf_bits: number of valid tsf bits for beacon time |
686 | * @calib_init_cfg: setup initial calibrations for the hw | 686 | * @calib_init_cfg: setup initial calibrations for the hw |
687 | * @calib_rt_cfg: setup runtime calibrations for the hw | ||
687 | * @struct iwl_sensitivity_ranges: range of sensitivity values | 688 | * @struct iwl_sensitivity_ranges: range of sensitivity values |
688 | */ | 689 | */ |
689 | struct iwl_hw_params { | 690 | struct iwl_hw_params { |
@@ -710,6 +711,7 @@ struct iwl_hw_params { | |||
710 | /* for 1000, 6000 series and up */ | 711 | /* for 1000, 6000 series and up */ |
711 | u16 beacon_time_tsf_bits; | 712 | u16 beacon_time_tsf_bits; |
712 | u32 calib_init_cfg; | 713 | u32 calib_init_cfg; |
714 | u32 calib_rt_cfg; | ||
713 | const struct iwl_sensitivity_ranges *sens; | 715 | const struct iwl_sensitivity_ranges *sens; |
714 | }; | 716 | }; |
715 | 717 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index a45d02e555cf..88f4a80d4733 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -332,7 +332,7 @@ EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); | |||
332 | 332 | ||
333 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | 333 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) |
334 | { | 334 | { |
335 | BUG_ON(offset >= priv->cfg->eeprom_size); | 335 | BUG_ON(offset >= priv->cfg->base_params->eeprom_size); |
336 | return &priv->eeprom[offset]; | 336 | return &priv->eeprom[offset]; |
337 | } | 337 | } |
338 | EXPORT_SYMBOL(iwlcore_eeprom_query_addr); | 338 | EXPORT_SYMBOL(iwlcore_eeprom_query_addr); |
@@ -364,7 +364,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
364 | * CSR auto clock gate disable bit - | 364 | * CSR auto clock gate disable bit - |
365 | * this is only applicable for HW with OTP shadow RAM | 365 | * this is only applicable for HW with OTP shadow RAM |
366 | */ | 366 | */ |
367 | if (priv->cfg->shadow_ram_support) | 367 | if (priv->cfg->base_params->shadow_ram_support) |
368 | iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, | 368 | iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, |
369 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | 369 | CSR_RESET_LINK_PWR_MGMT_DISABLED); |
370 | } | 370 | } |
@@ -484,7 +484,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, | |||
484 | } | 484 | } |
485 | /* more in the link list, continue */ | 485 | /* more in the link list, continue */ |
486 | usedblocks++; | 486 | usedblocks++; |
487 | } while (usedblocks <= priv->cfg->max_ll_items); | 487 | } while (usedblocks <= priv->cfg->base_params->max_ll_items); |
488 | 488 | ||
489 | /* OTP has no valid blocks */ | 489 | /* OTP has no valid blocks */ |
490 | IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n"); | 490 | IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n"); |
@@ -512,8 +512,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
512 | if (priv->nvm_device_type == -ENOENT) | 512 | if (priv->nvm_device_type == -ENOENT) |
513 | return -ENOENT; | 513 | return -ENOENT; |
514 | /* allocate eeprom */ | 514 | /* allocate eeprom */ |
515 | IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size); | 515 | sz = priv->cfg->base_params->eeprom_size; |
516 | sz = priv->cfg->eeprom_size; | 516 | IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz); |
517 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | 517 | priv->eeprom = kzalloc(sz, GFP_KERNEL); |
518 | if (!priv->eeprom) { | 518 | if (!priv->eeprom) { |
519 | ret = -ENOMEM; | 519 | ret = -ENOMEM; |
@@ -554,7 +554,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
554 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | 554 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | |
555 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | 555 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); |
556 | /* traversing the linked list if no shadow ram supported */ | 556 | /* traversing the linked list if no shadow ram supported */ |
557 | if (!priv->cfg->shadow_ram_support) { | 557 | if (!priv->cfg->base_params->shadow_ram_support) { |
558 | if (iwl_find_otp_image(priv, &validblockaddr)) { | 558 | if (iwl_find_otp_image(priv, &validblockaddr)) { |
559 | ret = -ENOENT; | 559 | ret = -ENOENT; |
560 | goto done; | 560 | goto done; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index db5bfcb036ca..86c2b6fed0c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -108,13 +108,13 @@ static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx) | |||
108 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | 108 | BUG_ON(idx > IWL_MAX_BLINK_TBL); |
109 | 109 | ||
110 | IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", | 110 | IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", |
111 | priv->cfg->led_compensation); | 111 | priv->cfg->base_params->led_compensation); |
112 | led_cmd.on = | 112 | led_cmd.on = |
113 | iwl_blink_compensation(priv, blink_tbl[idx].on_time, | 113 | iwl_blink_compensation(priv, blink_tbl[idx].on_time, |
114 | priv->cfg->led_compensation); | 114 | priv->cfg->base_params->led_compensation); |
115 | led_cmd.off = | 115 | led_cmd.off = |
116 | iwl_blink_compensation(priv, blink_tbl[idx].off_time, | 116 | iwl_blink_compensation(priv, blink_tbl[idx].off_time, |
117 | priv->cfg->led_compensation); | 117 | priv->cfg->base_params->led_compensation); |
118 | 118 | ||
119 | return priv->cfg->ops->led->cmd(priv, &led_cmd); | 119 | return priv->cfg->ops->led->cmd(priv, &led_cmd); |
120 | } | 120 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 63c0ab46261f..49d7788937a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -278,9 +278,9 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
278 | 278 | ||
279 | dtimper = priv->hw->conf.ps_dtim_period ?: 1; | 279 | dtimper = priv->hw->conf.ps_dtim_period ?: 1; |
280 | 280 | ||
281 | if (priv->cfg->broken_powersave) | 281 | if (priv->cfg->base_params->broken_powersave) |
282 | iwl_power_sleep_cam_cmd(priv, &cmd); | 282 | iwl_power_sleep_cam_cmd(priv, &cmd); |
283 | else if (priv->cfg->supports_idle && | 283 | else if (priv->cfg->base_params->supports_idle && |
284 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | 284 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) |
285 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); | 285 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); |
286 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && | 286 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index c54c20023e7c..eaae49ee0c60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -259,7 +259,8 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
259 | queue_work(priv->workqueue, &priv->scan_completed); | 259 | queue_work(priv->workqueue, &priv->scan_completed); |
260 | 260 | ||
261 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && | 261 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && |
262 | priv->cfg->advanced_bt_coexist && | 262 | priv->cfg->bt_params && |
263 | priv->cfg->bt_params->advanced_bt_coexist && | ||
263 | priv->bt_status != scan_notif->bt_status) { | 264 | priv->bt_status != scan_notif->bt_status) { |
264 | if (scan_notif->bt_status) { | 265 | if (scan_notif->bt_status) { |
265 | /* BT on */ | 266 | /* BT on */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 116777122a79..43db5f38e3e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1581,16 +1581,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
1581 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1581 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1582 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1582 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1583 | 1583 | ||
1584 | if (capacity > priv->cfg->max_event_log_size) { | 1584 | if (capacity > priv->cfg->base_params->max_event_log_size) { |
1585 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 1585 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
1586 | capacity, priv->cfg->max_event_log_size); | 1586 | capacity, priv->cfg->base_params->max_event_log_size); |
1587 | capacity = priv->cfg->max_event_log_size; | 1587 | capacity = priv->cfg->base_params->max_event_log_size; |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | if (next_entry > priv->cfg->max_event_log_size) { | 1590 | if (next_entry > priv->cfg->base_params->max_event_log_size) { |
1591 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 1591 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
1592 | next_entry, priv->cfg->max_event_log_size); | 1592 | next_entry, priv->cfg->base_params->max_event_log_size); |
1593 | next_entry = priv->cfg->max_event_log_size; | 1593 | next_entry = priv->cfg->base_params->max_event_log_size; |
1594 | } | 1594 | } |
1595 | 1595 | ||
1596 | size = num_wraps ? capacity : next_entry; | 1596 | size = num_wraps ? capacity : next_entry; |
@@ -2519,7 +2519,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2519 | /* Enable timer to monitor the driver queues */ | 2519 | /* Enable timer to monitor the driver queues */ |
2520 | mod_timer(&priv->monitor_recover, | 2520 | mod_timer(&priv->monitor_recover, |
2521 | jiffies + | 2521 | jiffies + |
2522 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | 2522 | msecs_to_jiffies( |
2523 | priv->cfg->base_params->monitor_recover_period)); | ||
2523 | } | 2524 | } |
2524 | 2525 | ||
2525 | if (iwl_is_rfkill(priv)) | 2526 | if (iwl_is_rfkill(priv)) |
@@ -3881,7 +3882,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3881 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 3882 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
3882 | IEEE80211_HW_SPECTRUM_MGMT; | 3883 | IEEE80211_HW_SPECTRUM_MGMT; |
3883 | 3884 | ||
3884 | if (!priv->cfg->broken_powersave) | 3885 | if (!priv->cfg->base_params->broken_powersave) |
3885 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 3886 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
3886 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 3887 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
3887 | 3888 | ||
@@ -3966,7 +3967,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
3966 | * "the hard way", rather than using device's scan. | 3967 | * "the hard way", rather than using device's scan. |
3967 | */ | 3968 | */ |
3968 | if (iwl3945_mod_params.disable_hw_scan) { | 3969 | if (iwl3945_mod_params.disable_hw_scan) { |
3969 | IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); | 3970 | IWL_ERR(priv, "sw scan support is deprecated\n"); |
3970 | iwl3945_hw_ops.hw_scan = NULL; | 3971 | iwl3945_hw_ops.hw_scan = NULL; |
3971 | } | 3972 | } |
3972 | 3973 | ||
@@ -4291,7 +4292,8 @@ MODULE_PARM_DESC(debug, "debug output mask"); | |||
4291 | #endif | 4292 | #endif |
4292 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, | 4293 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, |
4293 | int, S_IRUGO); | 4294 | int, S_IRUGO); |
4294 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4295 | MODULE_PARM_DESC(disable_hw_scan, |
4296 | "disable hardware scanning (default 0) (deprecated)"); | ||
4295 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); | 4297 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); |
4296 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); | 4298 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); |
4297 | 4299 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 60619678f4ec..c6c0eff9b5ed 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -161,7 +161,7 @@ static int iwm_key_init(struct iwm_key *key, u8 key_index, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 163 | static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
164 | u8 key_index, const u8 *mac_addr, | 164 | u8 key_index, bool pairwise, const u8 *mac_addr, |
165 | struct key_params *params) | 165 | struct key_params *params) |
166 | { | 166 | { |
167 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | 167 | struct iwm_priv *iwm = ndev_to_iwm(ndev); |
@@ -181,7 +181,8 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
181 | } | 181 | } |
182 | 182 | ||
183 | static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | 183 | static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, |
184 | u8 key_index, const u8 *mac_addr, void *cookie, | 184 | u8 key_index, bool pairwise, const u8 *mac_addr, |
185 | void *cookie, | ||
185 | void (*callback)(void *cookie, | 186 | void (*callback)(void *cookie, |
186 | struct key_params*)) | 187 | struct key_params*)) |
187 | { | 188 | { |
@@ -206,7 +207,7 @@ static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
206 | 207 | ||
207 | 208 | ||
208 | static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | 209 | static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, |
209 | u8 key_index, const u8 *mac_addr) | 210 | u8 key_index, bool pairwise, const u8 *mac_addr) |
210 | { | 211 | { |
211 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | 212 | struct iwm_priv *iwm = ndev_to_iwm(ndev); |
212 | struct iwm_key *key = &iwm->keys[key_index]; | 213 | struct iwm_key *key = &iwm->keys[key_index]; |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 1bbdb14f7d76..5046a0005034 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -1440,7 +1440,7 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy, | |||
1440 | 1440 | ||
1441 | 1441 | ||
1442 | static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, | 1442 | static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, |
1443 | u8 idx, const u8 *mac_addr, | 1443 | u8 idx, bool pairwise, const u8 *mac_addr, |
1444 | struct key_params *params) | 1444 | struct key_params *params) |
1445 | { | 1445 | { |
1446 | struct lbs_private *priv = wiphy_priv(wiphy); | 1446 | struct lbs_private *priv = wiphy_priv(wiphy); |
@@ -1500,7 +1500,7 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
1500 | 1500 | ||
1501 | 1501 | ||
1502 | static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, | 1502 | static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, |
1503 | u8 key_index, const u8 *mac_addr) | 1503 | u8 key_index, bool pairwise, const u8 *mac_addr) |
1504 | { | 1504 | { |
1505 | 1505 | ||
1506 | lbs_deb_enter(LBS_DEB_CFG80211); | 1506 | lbs_deb_enter(LBS_DEB_CFG80211); |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 063248b35069..d5bc21e5a02c 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -33,8 +33,17 @@ MODULE_ALIAS("prism54usb"); | |||
33 | MODULE_FIRMWARE("isl3886usb"); | 33 | MODULE_FIRMWARE("isl3886usb"); |
34 | MODULE_FIRMWARE("isl3887usb"); | 34 | MODULE_FIRMWARE("isl3887usb"); |
35 | 35 | ||
36 | /* | ||
37 | * Note: | ||
38 | * | ||
39 | * Always update our wiki's device list (located at: | ||
40 | * http://wireless.kernel.org/en/users/Drivers/p54/devices ), | ||
41 | * whenever you add a new device. | ||
42 | */ | ||
43 | |||
36 | static struct usb_device_id p54u_table[] __devinitdata = { | 44 | static struct usb_device_id p54u_table[] __devinitdata = { |
37 | /* Version 1 devices (pci chip + net2280) */ | 45 | /* Version 1 devices (pci chip + net2280) */ |
46 | {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ | ||
38 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ | 47 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ |
39 | {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ | 48 | {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ |
40 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ | 49 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ |
@@ -47,7 +56,9 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
47 | {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ | 56 | {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ |
48 | {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ | 57 | {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ |
49 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ | 58 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ |
59 | {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ | ||
50 | {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ | 60 | {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ |
61 | {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */ | ||
51 | {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ | 62 | {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ |
52 | {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ | 63 | {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ |
53 | {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ | 64 | {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ |
@@ -60,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
60 | {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ | 71 | {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ |
61 | {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ | 72 | {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ |
62 | {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ | 73 | {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ |
74 | {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ | ||
63 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ | 75 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ |
64 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ | 76 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ |
65 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ | 77 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ |
@@ -80,6 +92,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
80 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ | 92 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ |
81 | {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ | 93 | {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ |
82 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ | 94 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ |
95 | {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ | ||
83 | {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ | 96 | {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ |
84 | {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ | 97 | {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ |
85 | {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ | 98 | {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 719573bbbf81..71b5971da597 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -540,11 +540,11 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
540 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); | 540 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); |
541 | 541 | ||
542 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 542 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
543 | u8 key_index, const u8 *mac_addr, | 543 | u8 key_index, bool pairwise, const u8 *mac_addr, |
544 | struct key_params *params); | 544 | struct key_params *params); |
545 | 545 | ||
546 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | 546 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, |
547 | u8 key_index, const u8 *mac_addr); | 547 | u8 key_index, bool pairwise, const u8 *mac_addr); |
548 | 548 | ||
549 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | 549 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, |
550 | u8 key_index); | 550 | u8 key_index); |
@@ -2308,8 +2308,8 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev, | |||
2308 | } | 2308 | } |
2309 | 2309 | ||
2310 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 2310 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
2311 | u8 key_index, const u8 *mac_addr, | 2311 | u8 key_index, bool pairwise, const u8 *mac_addr, |
2312 | struct key_params *params) | 2312 | struct key_params *params) |
2313 | { | 2313 | { |
2314 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2314 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2315 | struct usbnet *usbdev = priv->usbdev; | 2315 | struct usbnet *usbdev = priv->usbdev; |
@@ -2344,7 +2344,7 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
2344 | } | 2344 | } |
2345 | 2345 | ||
2346 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | 2346 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, |
2347 | u8 key_index, const u8 *mac_addr) | 2347 | u8 key_index, bool pairwise, const u8 *mac_addr) |
2348 | { | 2348 | { |
2349 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2349 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2350 | struct usbnet *usbdev = priv->usbdev; | 2350 | struct usbnet *usbdev = priv->usbdev; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 6e94356265b3..93e44c7f3a74 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1674,10 +1674,15 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1674 | 1674 | ||
1675 | /* | 1675 | /* |
1676 | * Initialize all hw fields. | 1676 | * Initialize all hw fields. |
1677 | * | ||
1678 | * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are | ||
1679 | * capable of sending the buffered frames out after the DTIM | ||
1680 | * transmission using rt2x00lib_beacondone. This will send out | ||
1681 | * multicast and broadcast traffic immediately instead of buffering it | ||
1682 | * infinitly and thus dropping it after some time. | ||
1677 | */ | 1683 | */ |
1678 | rt2x00dev->hw->flags = | 1684 | rt2x00dev->hw->flags = |
1679 | IEEE80211_HW_RX_INCLUDES_FCS | | 1685 | IEEE80211_HW_RX_INCLUDES_FCS | |
1680 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
1681 | IEEE80211_HW_SIGNAL_DBM | | 1686 | IEEE80211_HW_SIGNAL_DBM | |
1682 | IEEE80211_HW_SUPPORTS_PS | | 1687 | IEEE80211_HW_SUPPORTS_PS | |
1683 | IEEE80211_HW_PS_NULLFUNC_STACK; | 1688 | IEEE80211_HW_PS_NULLFUNC_STACK; |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2edc7742a7e9..eb8b6cab9925 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 4 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 5 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 6 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -710,8 +711,14 @@ | |||
710 | 711 | ||
711 | /* | 712 | /* |
712 | * TBTT_SYNC_CFG: | 713 | * TBTT_SYNC_CFG: |
714 | * BCN_AIFSN: Beacon AIFSN after TBTT interrupt in slots | ||
715 | * BCN_CWMIN: Beacon CWMin after TBTT interrupt in slots | ||
713 | */ | 716 | */ |
714 | #define TBTT_SYNC_CFG 0x1118 | 717 | #define TBTT_SYNC_CFG 0x1118 |
718 | #define TBTT_SYNC_CFG_TBTT_ADJUST FIELD32(0x000000ff) | ||
719 | #define TBTT_SYNC_CFG_BCN_EXP_WIN FIELD32(0x0000ff00) | ||
720 | #define TBTT_SYNC_CFG_BCN_AIFSN FIELD32(0x000f0000) | ||
721 | #define TBTT_SYNC_CFG_BCN_CWMIN FIELD32(0x00f00000) | ||
715 | 722 | ||
716 | /* | 723 | /* |
717 | * TSF_TIMER_DW0: Local lsb TSF timer, read-only | 724 | * TSF_TIMER_DW0: Local lsb TSF timer, read-only |
@@ -747,16 +754,21 @@ | |||
747 | #define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002) | 754 | #define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002) |
748 | 755 | ||
749 | /* | 756 | /* |
750 | * CH_IDLE_STA: channel idle time | 757 | * CH_IDLE_STA: channel idle time (in us) |
751 | */ | 758 | */ |
752 | #define CH_IDLE_STA 0x1130 | 759 | #define CH_IDLE_STA 0x1130 |
753 | 760 | ||
754 | /* | 761 | /* |
755 | * CH_BUSY_STA: channel busy time | 762 | * CH_BUSY_STA: channel busy time on primary channel (in us) |
756 | */ | 763 | */ |
757 | #define CH_BUSY_STA 0x1134 | 764 | #define CH_BUSY_STA 0x1134 |
758 | 765 | ||
759 | /* | 766 | /* |
767 | * CH_BUSY_STA_SEC: channel busy time on secondary channel in HT40 mode (in us) | ||
768 | */ | ||
769 | #define CH_BUSY_STA_SEC 0x1138 | ||
770 | |||
771 | /* | ||
760 | * MAC_STATUS_CFG: | 772 | * MAC_STATUS_CFG: |
761 | * BBP_RF_BUSY: When set to 0, BBP and RF are stable. | 773 | * BBP_RF_BUSY: When set to 0, BBP and RF are stable. |
762 | * if 1 or higher one of the 2 registers is busy. | 774 | * if 1 or higher one of the 2 registers is busy. |
@@ -1342,6 +1354,9 @@ | |||
1342 | * PID_TYPE: The PID latched from the PID field in the TXWI, can be used | 1354 | * PID_TYPE: The PID latched from the PID field in the TXWI, can be used |
1343 | * to match a frame with its tx result (even though the PID is | 1355 | * to match a frame with its tx result (even though the PID is |
1344 | * only 4 bits wide). | 1356 | * only 4 bits wide). |
1357 | * PID_QUEUE: Part of PID_TYPE, this is the queue index number (0-3) | ||
1358 | * PID_ENTRY: Part of PID_TYPE, this is the queue entry index number (1-3) | ||
1359 | * This identification number is calculated by ((idx % 3) + 1). | ||
1345 | * TX_SUCCESS: Indicates tx success (1) or failure (0) | 1360 | * TX_SUCCESS: Indicates tx success (1) or failure (0) |
1346 | * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) | 1361 | * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) |
1347 | * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) | 1362 | * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) |
@@ -1353,6 +1368,8 @@ | |||
1353 | #define TX_STA_FIFO 0x1718 | 1368 | #define TX_STA_FIFO 0x1718 |
1354 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) | 1369 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) |
1355 | #define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) | 1370 | #define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) |
1371 | #define TX_STA_FIFO_PID_QUEUE FIELD32(0x00000006) | ||
1372 | #define TX_STA_FIFO_PID_ENTRY FIELD32(0x00000018) | ||
1356 | #define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) | 1373 | #define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) |
1357 | #define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) | 1374 | #define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) |
1358 | #define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) | 1375 | #define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) |
@@ -1435,6 +1452,24 @@ | |||
1435 | 1452 | ||
1436 | /* | 1453 | /* |
1437 | * Security key table memory. | 1454 | * Security key table memory. |
1455 | * | ||
1456 | * The pairwise key table shares some memory with the beacon frame | ||
1457 | * buffers 6 and 7. That basically means that when beacon 6 & 7 | ||
1458 | * are used we should only use the reduced pairwise key table which | ||
1459 | * has a maximum of 222 entries. | ||
1460 | * | ||
1461 | * --------------------------------------------- | ||
1462 | * |0x4000 | Pairwise Key | Reduced Pairwise | | ||
1463 | * | | Table | Key Table | | ||
1464 | * | | Size: 256 * 32 | Size: 222 * 32 | | ||
1465 | * |0x5BC0 | |------------------- | ||
1466 | * | | | Beacon 6 | | ||
1467 | * |0x5DC0 | |------------------- | ||
1468 | * | | | Beacon 7 | | ||
1469 | * |0x5FC0 | |------------------- | ||
1470 | * |0x5FFF | | | ||
1471 | * -------------------------- | ||
1472 | * | ||
1438 | * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry | 1473 | * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry |
1439 | * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry | 1474 | * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry |
1440 | * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry | 1475 | * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry |
@@ -1584,7 +1619,8 @@ struct mac_iveiv_entry { | |||
1584 | * 2. Extract memory from FCE table for BCN 4~5 | 1619 | * 2. Extract memory from FCE table for BCN 4~5 |
1585 | * 3. Extract memory from Pair-wise key table for BCN 6~7 | 1620 | * 3. Extract memory from Pair-wise key table for BCN 6~7 |
1586 | * It occupied those memory of wcid 238~253 for BCN 6 | 1621 | * It occupied those memory of wcid 238~253 for BCN 6 |
1587 | * and wcid 222~237 for BCN 7 | 1622 | * and wcid 222~237 for BCN 7 (see Security key table memory |
1623 | * for more info). | ||
1588 | * | 1624 | * |
1589 | * IMPORTANT NOTE: Not sure why legacy driver does this, | 1625 | * IMPORTANT NOTE: Not sure why legacy driver does this, |
1590 | * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. | 1626 | * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. |
@@ -1963,10 +1999,17 @@ struct mac_iveiv_entry { | |||
1963 | * FRAG: 1 To inform TKIP engine this is a fragment. | 1999 | * FRAG: 1 To inform TKIP engine this is a fragment. |
1964 | * MIMO_PS: The remote peer is in dynamic MIMO-PS mode | 2000 | * MIMO_PS: The remote peer is in dynamic MIMO-PS mode |
1965 | * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs | 2001 | * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs |
1966 | * BW: Channel bandwidth 20MHz or 40 MHz | 2002 | * BW: Channel bandwidth 0:20MHz, 1:40 MHz (for legacy rates this will |
2003 | * duplicate the frame to both channels). | ||
1967 | * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED | 2004 | * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED |
1968 | * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will | 2005 | * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will |
1969 | * aggregate consecutive frames with the same RA and QoS TID. | 2006 | * aggregate consecutive frames with the same RA and QoS TID. If |
2007 | * a frame A with the same RA and QoS TID but AMPDU=0 is queued | ||
2008 | * directly after a frame B with AMPDU=1, frame A might still | ||
2009 | * get aggregated into the AMPDU started by frame B. So, setting | ||
2010 | * AMPDU to 0 does _not_ necessarily mean the frame is sent as | ||
2011 | * MPDU, it can still end up in an AMPDU if the previous frame | ||
2012 | * was tagged as AMPDU. | ||
1970 | */ | 2013 | */ |
1971 | #define TXWI_W0_FRAG FIELD32(0x00000001) | 2014 | #define TXWI_W0_FRAG FIELD32(0x00000001) |
1972 | #define TXWI_W0_MIMO_PS FIELD32(0x00000002) | 2015 | #define TXWI_W0_MIMO_PS FIELD32(0x00000002) |
@@ -1993,6 +2036,10 @@ struct mac_iveiv_entry { | |||
1993 | * frame was processed. If multiple frames are aggregated together | 2036 | * frame was processed. If multiple frames are aggregated together |
1994 | * (AMPDU==1) the reported tx status will always contain the packet | 2037 | * (AMPDU==1) the reported tx status will always contain the packet |
1995 | * id of the first frame. 0: Don't report tx status for this frame. | 2038 | * id of the first frame. 0: Don't report tx status for this frame. |
2039 | * PACKETID_QUEUE: Part of PACKETID, This is the queue index (0-3) | ||
2040 | * PACKETID_ENTRY: Part of PACKETID, THis is the queue entry index (1-3) | ||
2041 | * This identification number is calculated by ((idx % 3) + 1). | ||
2042 | * The (+1) is required to prevent PACKETID to become 0. | ||
1996 | */ | 2043 | */ |
1997 | #define TXWI_W1_ACK FIELD32(0x00000001) | 2044 | #define TXWI_W1_ACK FIELD32(0x00000001) |
1998 | #define TXWI_W1_NSEQ FIELD32(0x00000002) | 2045 | #define TXWI_W1_NSEQ FIELD32(0x00000002) |
@@ -2000,6 +2047,8 @@ struct mac_iveiv_entry { | |||
2000 | #define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) | 2047 | #define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) |
2001 | #define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) | 2048 | #define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) |
2002 | #define TXWI_W1_PACKETID FIELD32(0xf0000000) | 2049 | #define TXWI_W1_PACKETID FIELD32(0xf0000000) |
2050 | #define TXWI_W1_PACKETID_QUEUE FIELD32(0x30000000) | ||
2051 | #define TXWI_W1_PACKETID_ENTRY FIELD32(0xc0000000) | ||
2003 | 2052 | ||
2004 | /* | 2053 | /* |
2005 | * Word2 | 2054 | * Word2 |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3bb67492d754..10aefc4fb0cc 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -483,7 +483,8 @@ void rt2800_write_tx_data(struct queue_entry *entry, | |||
483 | txdesc->key_idx : 0xff); | 483 | txdesc->key_idx : 0xff); |
484 | rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, | 484 | rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, |
485 | txdesc->length); | 485 | txdesc->length); |
486 | rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->qid + 1); | 486 | rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid); |
487 | rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1); | ||
487 | rt2x00_desc_write(txwi, 1, word); | 488 | rt2x00_desc_write(txwi, 1, word); |
488 | 489 | ||
489 | /* | 490 | /* |
@@ -630,15 +631,90 @@ static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) | |||
630 | return true; | 631 | return true; |
631 | } | 632 | } |
632 | 633 | ||
634 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status) | ||
635 | { | ||
636 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
637 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
638 | struct txdone_entry_desc txdesc; | ||
639 | u32 word; | ||
640 | u16 mcs, real_mcs; | ||
641 | int aggr, ampdu; | ||
642 | __le32 *txwi; | ||
643 | |||
644 | /* | ||
645 | * Obtain the status about this packet. | ||
646 | */ | ||
647 | txdesc.flags = 0; | ||
648 | txwi = rt2800_drv_get_txwi(entry); | ||
649 | rt2x00_desc_read(txwi, 0, &word); | ||
650 | |||
651 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
652 | ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU); | ||
653 | |||
654 | real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS); | ||
655 | aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE); | ||
656 | |||
657 | /* | ||
658 | * If a frame was meant to be sent as a single non-aggregated MPDU | ||
659 | * but ended up in an aggregate the used tx rate doesn't correlate | ||
660 | * with the one specified in the TXWI as the whole aggregate is sent | ||
661 | * with the same rate. | ||
662 | * | ||
663 | * For example: two frames are sent to rt2x00, the first one sets | ||
664 | * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0 | ||
665 | * and requests MCS15. If the hw aggregates both frames into one | ||
666 | * AMDPU the tx status for both frames will contain MCS7 although | ||
667 | * the frame was sent successfully. | ||
668 | * | ||
669 | * Hence, replace the requested rate with the real tx rate to not | ||
670 | * confuse the rate control algortihm by providing clearly wrong | ||
671 | * data. | ||
672 | */ | ||
673 | if (aggr == 1 && ampdu == 0 && real_mcs != mcs) { | ||
674 | skbdesc->tx_rate_idx = real_mcs; | ||
675 | mcs = real_mcs; | ||
676 | } | ||
677 | |||
678 | /* | ||
679 | * Ralink has a retry mechanism using a global fallback | ||
680 | * table. We setup this fallback table to try the immediate | ||
681 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
682 | * always contains the MCS used for the last transmission, be | ||
683 | * it successful or not. | ||
684 | */ | ||
685 | if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) { | ||
686 | /* | ||
687 | * Transmission succeeded. The number of retries is | ||
688 | * mcs - real_mcs | ||
689 | */ | ||
690 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
691 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
692 | } else { | ||
693 | /* | ||
694 | * Transmission failed. The number of retries is | ||
695 | * always 7 in this case (for a total number of 8 | ||
696 | * frames sent). | ||
697 | */ | ||
698 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
699 | txdesc.retry = rt2x00dev->long_retry; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | * the frame was retried at least once | ||
704 | * -> hw used fallback rates | ||
705 | */ | ||
706 | if (txdesc.retry) | ||
707 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
708 | |||
709 | rt2x00lib_txdone(entry, &txdesc); | ||
710 | } | ||
711 | EXPORT_SYMBOL_GPL(rt2800_txdone_entry); | ||
712 | |||
633 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | 713 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev) |
634 | { | 714 | { |
635 | struct data_queue *queue; | 715 | struct data_queue *queue; |
636 | struct queue_entry *entry; | 716 | struct queue_entry *entry; |
637 | __le32 *txwi; | ||
638 | struct txdone_entry_desc txdesc; | ||
639 | u32 word; | ||
640 | u32 reg; | 717 | u32 reg; |
641 | u16 mcs, real_mcs; | ||
642 | u8 pid; | 718 | u8 pid; |
643 | int i; | 719 | int i; |
644 | 720 | ||
@@ -660,7 +736,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | |||
660 | * Skip this entry when it contains an invalid | 736 | * Skip this entry when it contains an invalid |
661 | * queue identication number. | 737 | * queue identication number. |
662 | */ | 738 | */ |
663 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1; | 739 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); |
664 | if (pid >= QID_RX) | 740 | if (pid >= QID_RX) |
665 | continue; | 741 | continue; |
666 | 742 | ||
@@ -673,7 +749,6 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | |||
673 | * order. We first check that the queue is not empty. | 749 | * order. We first check that the queue is not empty. |
674 | */ | 750 | */ |
675 | entry = NULL; | 751 | entry = NULL; |
676 | txwi = NULL; | ||
677 | while (!rt2x00queue_empty(queue)) { | 752 | while (!rt2x00queue_empty(queue)) { |
678 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 753 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
679 | if (rt2800_txdone_entry_check(entry, reg)) | 754 | if (rt2800_txdone_entry_check(entry, reg)) |
@@ -683,48 +758,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | |||
683 | if (!entry || rt2x00queue_empty(queue)) | 758 | if (!entry || rt2x00queue_empty(queue)) |
684 | break; | 759 | break; |
685 | 760 | ||
686 | 761 | rt2800_txdone_entry(entry, reg); | |
687 | /* | ||
688 | * Obtain the status about this packet. | ||
689 | */ | ||
690 | txdesc.flags = 0; | ||
691 | txwi = rt2800_drv_get_txwi(entry); | ||
692 | rt2x00_desc_read(txwi, 0, &word); | ||
693 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
694 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
695 | |||
696 | /* | ||
697 | * Ralink has a retry mechanism using a global fallback | ||
698 | * table. We setup this fallback table to try the immediate | ||
699 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
700 | * always contains the MCS used for the last transmission, be | ||
701 | * it successful or not. | ||
702 | */ | ||
703 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
704 | /* | ||
705 | * Transmission succeeded. The number of retries is | ||
706 | * mcs - real_mcs | ||
707 | */ | ||
708 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
709 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
710 | } else { | ||
711 | /* | ||
712 | * Transmission failed. The number of retries is | ||
713 | * always 7 in this case (for a total number of 8 | ||
714 | * frames sent). | ||
715 | */ | ||
716 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
717 | txdesc.retry = rt2x00dev->long_retry; | ||
718 | } | ||
719 | |||
720 | /* | ||
721 | * the frame was retried at least once | ||
722 | * -> hw used fallback rates | ||
723 | */ | ||
724 | if (txdesc.retry) | ||
725 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
726 | |||
727 | rt2x00lib_txdone(entry, &txdesc); | ||
728 | } | 762 | } |
729 | } | 763 | } |
730 | EXPORT_SYMBOL_GPL(rt2800_txdone); | 764 | EXPORT_SYMBOL_GPL(rt2800_txdone); |
@@ -1031,8 +1065,12 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
1031 | * 1 pairwise key is possible per AID, this means that the AID | 1065 | * 1 pairwise key is possible per AID, this means that the AID |
1032 | * equals our hw_key_idx. Make sure the WCID starts _after_ the | 1066 | * equals our hw_key_idx. Make sure the WCID starts _after_ the |
1033 | * last possible shared key entry. | 1067 | * last possible shared key entry. |
1068 | * | ||
1069 | * Since parts of the pairwise key table might be shared with | ||
1070 | * the beacon frame buffers 6 & 7 we should only write into the | ||
1071 | * first 222 entries. | ||
1034 | */ | 1072 | */ |
1035 | if (crypto->aid > (256 - 32)) | 1073 | if (crypto->aid > (222 - 32)) |
1036 | return -ENOSPC; | 1074 | return -ENOSPC; |
1037 | 1075 | ||
1038 | key->hw_key_idx = 32 + crypto->aid; | 1076 | key->hw_key_idx = 32 + crypto->aid; |
@@ -1159,6 +1197,102 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
1159 | } | 1197 | } |
1160 | EXPORT_SYMBOL_GPL(rt2800_config_intf); | 1198 | EXPORT_SYMBOL_GPL(rt2800_config_intf); |
1161 | 1199 | ||
1200 | static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev, | ||
1201 | struct rt2x00lib_erp *erp) | ||
1202 | { | ||
1203 | bool any_sta_nongf = !!(erp->ht_opmode & | ||
1204 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
1205 | u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
1206 | u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode; | ||
1207 | u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate; | ||
1208 | u32 reg; | ||
1209 | |||
1210 | /* default protection rate for HT20: OFDM 24M */ | ||
1211 | mm20_rate = gf20_rate = 0x4004; | ||
1212 | |||
1213 | /* default protection rate for HT40: duplicate OFDM 24M */ | ||
1214 | mm40_rate = gf40_rate = 0x4084; | ||
1215 | |||
1216 | switch (protection) { | ||
1217 | case IEEE80211_HT_OP_MODE_PROTECTION_NONE: | ||
1218 | /* | ||
1219 | * All STAs in this BSS are HT20/40 but there might be | ||
1220 | * STAs not supporting greenfield mode. | ||
1221 | * => Disable protection for HT transmissions. | ||
1222 | */ | ||
1223 | mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0; | ||
1224 | |||
1225 | break; | ||
1226 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
1227 | /* | ||
1228 | * All STAs in this BSS are HT20 or HT20/40 but there | ||
1229 | * might be STAs not supporting greenfield mode. | ||
1230 | * => Protect all HT40 transmissions. | ||
1231 | */ | ||
1232 | mm20_mode = gf20_mode = 0; | ||
1233 | mm40_mode = gf40_mode = 2; | ||
1234 | |||
1235 | break; | ||
1236 | case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: | ||
1237 | /* | ||
1238 | * Nonmember protection: | ||
1239 | * According to 802.11n we _should_ protect all | ||
1240 | * HT transmissions (but we don't have to). | ||
1241 | * | ||
1242 | * But if cts_protection is enabled we _shall_ protect | ||
1243 | * all HT transmissions using a CCK rate. | ||
1244 | * | ||
1245 | * And if any station is non GF we _shall_ protect | ||
1246 | * GF transmissions. | ||
1247 | * | ||
1248 | * We decide to protect everything | ||
1249 | * -> fall through to mixed mode. | ||
1250 | */ | ||
1251 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
1252 | /* | ||
1253 | * Legacy STAs are present | ||
1254 | * => Protect all HT transmissions. | ||
1255 | */ | ||
1256 | mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2; | ||
1257 | |||
1258 | /* | ||
1259 | * If erp protection is needed we have to protect HT | ||
1260 | * transmissions with CCK 11M long preamble. | ||
1261 | */ | ||
1262 | if (erp->cts_protection) { | ||
1263 | /* don't duplicate RTS/CTS in CCK mode */ | ||
1264 | mm20_rate = mm40_rate = 0x0003; | ||
1265 | gf20_rate = gf40_rate = 0x0003; | ||
1266 | } | ||
1267 | break; | ||
1268 | }; | ||
1269 | |||
1270 | /* check for STAs not supporting greenfield mode */ | ||
1271 | if (any_sta_nongf) | ||
1272 | gf20_mode = gf40_mode = 2; | ||
1273 | |||
1274 | /* Update HT protection config */ | ||
1275 | rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); | ||
1276 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, mm20_rate); | ||
1277 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode); | ||
1278 | rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); | ||
1279 | |||
1280 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); | ||
1281 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, mm40_rate); | ||
1282 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode); | ||
1283 | rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); | ||
1284 | |||
1285 | rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); | ||
1286 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, gf20_rate); | ||
1287 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode); | ||
1288 | rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); | ||
1289 | |||
1290 | rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); | ||
1291 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, gf40_rate); | ||
1292 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode); | ||
1293 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | ||
1294 | } | ||
1295 | |||
1162 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, | 1296 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, |
1163 | u32 changed) | 1297 | u32 changed) |
1164 | { | 1298 | { |
@@ -1203,6 +1337,9 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, | |||
1203 | erp->beacon_int * 16); | 1337 | erp->beacon_int * 16); |
1204 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1338 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1205 | } | 1339 | } |
1340 | |||
1341 | if (changed & BSS_CHANGED_HT) | ||
1342 | rt2800_config_ht_opmode(rt2x00dev, erp); | ||
1206 | } | 1343 | } |
1207 | EXPORT_SYMBOL_GPL(rt2800_config_erp); | 1344 | EXPORT_SYMBOL_GPL(rt2800_config_erp); |
1208 | 1345 | ||
@@ -1907,8 +2044,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1907 | 2044 | ||
1908 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); | 2045 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); |
1909 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); | 2046 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); |
1910 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, | 2047 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); |
1911 | !rt2x00_is_usb(rt2x00dev)); | ||
1912 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); | 2048 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); |
1913 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); | 2049 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); |
1914 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | 2050 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); |
@@ -3056,11 +3192,20 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
3056 | * Initialize all hw fields. | 3192 | * Initialize all hw fields. |
3057 | */ | 3193 | */ |
3058 | rt2x00dev->hw->flags = | 3194 | rt2x00dev->hw->flags = |
3059 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
3060 | IEEE80211_HW_SIGNAL_DBM | | 3195 | IEEE80211_HW_SIGNAL_DBM | |
3061 | IEEE80211_HW_SUPPORTS_PS | | 3196 | IEEE80211_HW_SUPPORTS_PS | |
3062 | IEEE80211_HW_PS_NULLFUNC_STACK | | 3197 | IEEE80211_HW_PS_NULLFUNC_STACK | |
3063 | IEEE80211_HW_AMPDU_AGGREGATION; | 3198 | IEEE80211_HW_AMPDU_AGGREGATION; |
3199 | /* | ||
3200 | * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices | ||
3201 | * unless we are capable of sending the buffered frames out after the | ||
3202 | * DTIM transmission using rt2x00lib_beacondone. This will send out | ||
3203 | * multicast and broadcast traffic immediately instead of buffering it | ||
3204 | * infinitly and thus dropping it after some time. | ||
3205 | */ | ||
3206 | if (!rt2x00_is_usb(rt2x00dev)) | ||
3207 | rt2x00dev->hw->flags |= | ||
3208 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; | ||
3064 | 3209 | ||
3065 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); | 3210 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
3066 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 3211 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
@@ -3071,12 +3216,13 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
3071 | * As rt2800 has a global fallback table we cannot specify | 3216 | * As rt2800 has a global fallback table we cannot specify |
3072 | * more then one tx rate per frame but since the hw will | 3217 | * more then one tx rate per frame but since the hw will |
3073 | * try several rates (based on the fallback table) we should | 3218 | * try several rates (based on the fallback table) we should |
3074 | * still initialize max_rates to the maximum number of rates | 3219 | * initialize max_report_rates to the maximum number of rates |
3075 | * we are going to try. Otherwise mac80211 will truncate our | 3220 | * we are going to try. Otherwise mac80211 will truncate our |
3076 | * reported tx rates and the rc algortihm will end up with | 3221 | * reported tx rates and the rc algortihm will end up with |
3077 | * incorrect data. | 3222 | * incorrect data. |
3078 | */ | 3223 | */ |
3079 | rt2x00dev->hw->max_rates = 7; | 3224 | rt2x00dev->hw->max_rates = 1; |
3225 | rt2x00dev->hw->max_report_rates = 7; | ||
3080 | rt2x00dev->hw->max_rate_tries = 1; | 3226 | rt2x00dev->hw->max_rate_tries = 1; |
3081 | 3227 | ||
3082 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | 3228 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); |
@@ -3333,8 +3479,12 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
3333 | switch (action) { | 3479 | switch (action) { |
3334 | case IEEE80211_AMPDU_RX_START: | 3480 | case IEEE80211_AMPDU_RX_START: |
3335 | case IEEE80211_AMPDU_RX_STOP: | 3481 | case IEEE80211_AMPDU_RX_STOP: |
3336 | /* we don't support RX aggregation yet */ | 3482 | /* |
3337 | ret = -ENOTSUPP; | 3483 | * The hw itself takes care of setting up BlockAck mechanisms. |
3484 | * So, we only have to allow mac80211 to nagotiate a BlockAck | ||
3485 | * agreement. Once that is done, the hw will BlockAck incoming | ||
3486 | * AMPDUs without further setup. | ||
3487 | */ | ||
3338 | break; | 3488 | break; |
3339 | case IEEE80211_AMPDU_TX_START: | 3489 | case IEEE80211_AMPDU_TX_START: |
3340 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 3490 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 600c5eb25c41..81cbc92e7857 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -153,6 +153,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, | |||
153 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); | 153 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
154 | 154 | ||
155 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | 155 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev); |
156 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status); | ||
156 | 157 | ||
157 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 158 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
158 | 159 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 005ee153e0cc..85a134cd62bf 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -241,6 +241,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) | |||
241 | { | 241 | { |
242 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 242 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
243 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 243 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
244 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
244 | u32 word; | 245 | u32 word; |
245 | 246 | ||
246 | if (entry->queue->qid == QID_RX) { | 247 | if (entry->queue->qid == QID_RX) { |
@@ -251,6 +252,13 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) | |||
251 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 252 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
252 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | 253 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); |
253 | rt2x00_desc_write(entry_priv->desc, 1, word); | 254 | rt2x00_desc_write(entry_priv->desc, 1, word); |
255 | |||
256 | /* | ||
257 | * Set RX IDX in register to inform hardware that we have | ||
258 | * handled this entry and it is available for reuse again. | ||
259 | */ | ||
260 | rt2800_register_write(rt2x00dev, RX_CRX_IDX, | ||
261 | entry->entry_idx); | ||
254 | } else { | 262 | } else { |
255 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 263 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
256 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | 264 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); |
@@ -599,7 +607,6 @@ static void rt2800pci_kill_tx_queue(struct data_queue *queue) | |||
599 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, | 607 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, |
600 | struct rxdone_entry_desc *rxdesc) | 608 | struct rxdone_entry_desc *rxdesc) |
601 | { | 609 | { |
602 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
603 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 610 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
604 | __le32 *rxd = entry_priv->desc; | 611 | __le32 *rxd = entry_priv->desc; |
605 | u32 word; | 612 | u32 word; |
@@ -641,12 +648,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
641 | * Process the RXWI structure that is at the start of the buffer. | 648 | * Process the RXWI structure that is at the start of the buffer. |
642 | */ | 649 | */ |
643 | rt2800_process_rxwi(entry, rxdesc); | 650 | rt2800_process_rxwi(entry, rxdesc); |
644 | |||
645 | /* | ||
646 | * Set RX IDX in register to inform hardware that we have handled | ||
647 | * this entry and it is available for reuse again. | ||
648 | */ | ||
649 | rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); | ||
650 | } | 651 | } |
651 | 652 | ||
652 | /* | 653 | /* |
@@ -660,6 +661,63 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
660 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 661 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
661 | } | 662 | } |
662 | 663 | ||
664 | static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
665 | { | ||
666 | struct data_queue *queue; | ||
667 | struct queue_entry *entry; | ||
668 | u32 status; | ||
669 | u8 qid; | ||
670 | |||
671 | while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { | ||
672 | /* Now remove the tx status from the FIFO */ | ||
673 | if (kfifo_out(&rt2x00dev->txstatus_fifo, &status, | ||
674 | sizeof(status)) != sizeof(status)) { | ||
675 | WARN_ON(1); | ||
676 | break; | ||
677 | } | ||
678 | |||
679 | qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_TYPE) - 1; | ||
680 | if (qid >= QID_RX) { | ||
681 | /* | ||
682 | * Unknown queue, this shouldn't happen. Just drop | ||
683 | * this tx status. | ||
684 | */ | ||
685 | WARNING(rt2x00dev, "Got TX status report with " | ||
686 | "unexpected pid %u, dropping", qid); | ||
687 | break; | ||
688 | } | ||
689 | |||
690 | queue = rt2x00queue_get_queue(rt2x00dev, qid); | ||
691 | if (unlikely(queue == NULL)) { | ||
692 | /* | ||
693 | * The queue is NULL, this shouldn't happen. Stop | ||
694 | * processing here and drop the tx status | ||
695 | */ | ||
696 | WARNING(rt2x00dev, "Got TX status for an unavailable " | ||
697 | "queue %u, dropping", qid); | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | if (rt2x00queue_empty(queue)) { | ||
702 | /* | ||
703 | * The queue is empty. Stop processing here | ||
704 | * and drop the tx status. | ||
705 | */ | ||
706 | WARNING(rt2x00dev, "Got TX status for an empty " | ||
707 | "queue %u, dropping", qid); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
712 | rt2800_txdone_entry(entry, status); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static void rt2800pci_txstatus_tasklet(unsigned long data) | ||
717 | { | ||
718 | rt2800pci_txdone((struct rt2x00_dev *)data); | ||
719 | } | ||
720 | |||
663 | static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | 721 | static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) |
664 | { | 722 | { |
665 | struct rt2x00_dev *rt2x00dev = dev_instance; | 723 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -684,13 +742,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | |||
684 | rt2x00pci_rxdone(rt2x00dev); | 742 | rt2x00pci_rxdone(rt2x00dev); |
685 | 743 | ||
686 | /* | 744 | /* |
687 | * 4 - Tx done interrupt. | 745 | * 4 - Auto wakeup interrupt. |
688 | */ | ||
689 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | ||
690 | rt2800_txdone(rt2x00dev); | ||
691 | |||
692 | /* | ||
693 | * 5 - Auto wakeup interrupt. | ||
694 | */ | 746 | */ |
695 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | 747 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) |
696 | rt2800pci_wakeup(rt2x00dev); | 748 | rt2800pci_wakeup(rt2x00dev); |
@@ -702,10 +754,58 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | |||
702 | return IRQ_HANDLED; | 754 | return IRQ_HANDLED; |
703 | } | 755 | } |
704 | 756 | ||
757 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | ||
758 | { | ||
759 | u32 status; | ||
760 | int i; | ||
761 | |||
762 | /* | ||
763 | * The TX_FIFO_STATUS interrupt needs special care. We should | ||
764 | * read TX_STA_FIFO but we should do it immediately as otherwise | ||
765 | * the register can overflow and we would lose status reports. | ||
766 | * | ||
767 | * Hence, read the TX_STA_FIFO register and copy all tx status | ||
768 | * reports into a kernel FIFO which is handled in the txstatus | ||
769 | * tasklet. We use a tasklet to process the tx status reports | ||
770 | * because we can schedule the tasklet multiple times (when the | ||
771 | * interrupt fires again during tx status processing). | ||
772 | * | ||
773 | * Furthermore we don't disable the TX_FIFO_STATUS | ||
774 | * interrupt here but leave it enabled so that the TX_STA_FIFO | ||
775 | * can also be read while the interrupt thread gets executed. | ||
776 | * | ||
777 | * Since we have only one producer and one consumer we don't | ||
778 | * need to lock the kfifo. | ||
779 | */ | ||
780 | for (i = 0; i < TX_ENTRIES; i++) { | ||
781 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); | ||
782 | |||
783 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | ||
784 | break; | ||
785 | |||
786 | if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) { | ||
787 | WARNING(rt2x00dev, "TX status FIFO overrun," | ||
788 | " drop tx status report.\n"); | ||
789 | break; | ||
790 | } | ||
791 | |||
792 | if (kfifo_in(&rt2x00dev->txstatus_fifo, &status, | ||
793 | sizeof(status)) != sizeof(status)) { | ||
794 | WARNING(rt2x00dev, "TX status FIFO overrun," | ||
795 | "drop tx status report.\n"); | ||
796 | break; | ||
797 | } | ||
798 | } | ||
799 | |||
800 | /* Schedule the tasklet for processing the tx status. */ | ||
801 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
802 | } | ||
803 | |||
705 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 804 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) |
706 | { | 805 | { |
707 | struct rt2x00_dev *rt2x00dev = dev_instance; | 806 | struct rt2x00_dev *rt2x00dev = dev_instance; |
708 | u32 reg; | 807 | u32 reg; |
808 | irqreturn_t ret = IRQ_HANDLED; | ||
709 | 809 | ||
710 | /* Read status and ACK all interrupts */ | 810 | /* Read status and ACK all interrupts */ |
711 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 811 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
@@ -717,15 +817,38 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
717 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 817 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
718 | return IRQ_HANDLED; | 818 | return IRQ_HANDLED; |
719 | 819 | ||
720 | /* Store irqvalue for use in the interrupt thread. */ | 820 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
721 | rt2x00dev->irqvalue[0] = reg; | 821 | rt2800pci_txstatus_interrupt(rt2x00dev); |
722 | 822 | ||
723 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 823 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || |
724 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 824 | rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || |
725 | STATE_RADIO_IRQ_OFF_ISR); | 825 | rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || |
826 | rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { | ||
827 | /* | ||
828 | * All other interrupts are handled in the interrupt thread. | ||
829 | * Store irqvalue for use in the interrupt thread. | ||
830 | */ | ||
831 | rt2x00dev->irqvalue[0] = reg; | ||
832 | |||
833 | /* | ||
834 | * Disable interrupts, will be enabled again in the | ||
835 | * interrupt thread. | ||
836 | */ | ||
837 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
838 | STATE_RADIO_IRQ_OFF_ISR); | ||
839 | |||
840 | /* | ||
841 | * Leave the TX_FIFO_STATUS interrupt enabled to not lose any | ||
842 | * tx status reports. | ||
843 | */ | ||
844 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
845 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
846 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
726 | 847 | ||
848 | ret = IRQ_WAKE_THREAD; | ||
849 | } | ||
727 | 850 | ||
728 | return IRQ_WAKE_THREAD; | 851 | return ret; |
729 | } | 852 | } |
730 | 853 | ||
731 | /* | 854 | /* |
@@ -788,6 +911,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
788 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 911 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
789 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 912 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
790 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 913 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
914 | __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); | ||
791 | if (!modparam_nohwcrypt) | 915 | if (!modparam_nohwcrypt) |
792 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 916 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
793 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); | 917 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); |
@@ -837,6 +961,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
837 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 961 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
838 | .irq_handler = rt2800pci_interrupt, | 962 | .irq_handler = rt2800pci_interrupt, |
839 | .irq_handler_thread = rt2800pci_interrupt_thread, | 963 | .irq_handler_thread = rt2800pci_interrupt_thread, |
964 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, | ||
840 | .probe_hw = rt2800pci_probe_hw, | 965 | .probe_hw = rt2800pci_probe_hw, |
841 | .get_firmware_name = rt2800pci_get_firmware_name, | 966 | .get_firmware_name = rt2800pci_get_firmware_name, |
842 | .check_firmware = rt2800_check_firmware, | 967 | .check_firmware = rt2800_check_firmware, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7832a5996a8c..75ac6624bf9e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/etherdevice.h> | 37 | #include <linux/etherdevice.h> |
38 | #include <linux/input-polldev.h> | 38 | #include <linux/input-polldev.h> |
39 | #include <linux/kfifo.h> | ||
39 | 40 | ||
40 | #include <net/mac80211.h> | 41 | #include <net/mac80211.h> |
41 | 42 | ||
@@ -457,6 +458,7 @@ struct rt2x00lib_erp { | |||
457 | short eifs; | 458 | short eifs; |
458 | 459 | ||
459 | u16 beacon_int; | 460 | u16 beacon_int; |
461 | u16 ht_opmode; | ||
460 | }; | 462 | }; |
461 | 463 | ||
462 | /* | 464 | /* |
@@ -522,6 +524,11 @@ struct rt2x00lib_ops { | |||
522 | irq_handler_t irq_handler_thread; | 524 | irq_handler_t irq_handler_thread; |
523 | 525 | ||
524 | /* | 526 | /* |
527 | * TX status tasklet handler. | ||
528 | */ | ||
529 | void (*txstatus_tasklet) (unsigned long data); | ||
530 | |||
531 | /* | ||
525 | * Device init handlers. | 532 | * Device init handlers. |
526 | */ | 533 | */ |
527 | int (*probe_hw) (struct rt2x00_dev *rt2x00dev); | 534 | int (*probe_hw) (struct rt2x00_dev *rt2x00dev); |
@@ -651,6 +658,7 @@ enum rt2x00_flags { | |||
651 | DRIVER_REQUIRE_DMA, | 658 | DRIVER_REQUIRE_DMA, |
652 | DRIVER_REQUIRE_COPY_IV, | 659 | DRIVER_REQUIRE_COPY_IV, |
653 | DRIVER_REQUIRE_L2PAD, | 660 | DRIVER_REQUIRE_L2PAD, |
661 | DRIVER_REQUIRE_TXSTATUS_FIFO, | ||
654 | 662 | ||
655 | /* | 663 | /* |
656 | * Driver features | 664 | * Driver features |
@@ -884,6 +892,16 @@ struct rt2x00_dev { | |||
884 | * and interrupt thread routine. | 892 | * and interrupt thread routine. |
885 | */ | 893 | */ |
886 | u32 irqvalue[2]; | 894 | u32 irqvalue[2]; |
895 | |||
896 | /* | ||
897 | * FIFO for storing tx status reports between isr and tasklet. | ||
898 | */ | ||
899 | struct kfifo txstatus_fifo; | ||
900 | |||
901 | /* | ||
902 | * Tasklet for processing tx status reports (rt2800pci). | ||
903 | */ | ||
904 | struct tasklet_struct txstatus_tasklet; | ||
887 | }; | 905 | }; |
888 | 906 | ||
889 | /* | 907 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 4c7ff765a8bf..54ffb5aeb34e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -103,6 +103,9 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
103 | /* Update global beacon interval time, this is needed for PS support */ | 103 | /* Update global beacon interval time, this is needed for PS support */ |
104 | rt2x00dev->beacon_int = bss_conf->beacon_int; | 104 | rt2x00dev->beacon_int = bss_conf->beacon_int; |
105 | 105 | ||
106 | if (changed & BSS_CHANGED_HT) | ||
107 | erp.ht_opmode = bss_conf->ht_operation_mode; | ||
108 | |||
106 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); | 109 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); |
107 | } | 110 | } |
108 | 111 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 053fdd3bd720..6f442b02b83e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -813,6 +813,30 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
813 | rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; | 813 | rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; |
814 | 814 | ||
815 | /* | 815 | /* |
816 | * Allocate tx status FIFO for driver use. | ||
817 | */ | ||
818 | if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) && | ||
819 | rt2x00dev->ops->lib->txstatus_tasklet) { | ||
820 | /* | ||
821 | * Allocate txstatus fifo and tasklet, we use a size of 512 | ||
822 | * for the kfifo which is big enough to store 512/4=128 tx | ||
823 | * status reports. In the worst case (tx status for all tx | ||
824 | * queues gets reported before we've got a chance to handle | ||
825 | * them) 24*4=384 tx status reports need to be cached. | ||
826 | */ | ||
827 | status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512, | ||
828 | GFP_KERNEL); | ||
829 | if (status) | ||
830 | return status; | ||
831 | |||
832 | /* tasklet for processing the tx status reports. */ | ||
833 | tasklet_init(&rt2x00dev->txstatus_tasklet, | ||
834 | rt2x00dev->ops->lib->txstatus_tasklet, | ||
835 | (unsigned long)rt2x00dev); | ||
836 | |||
837 | } | ||
838 | |||
839 | /* | ||
816 | * Register HW. | 840 | * Register HW. |
817 | */ | 841 | */ |
818 | status = ieee80211_register_hw(rt2x00dev->hw); | 842 | status = ieee80211_register_hw(rt2x00dev->hw); |
@@ -909,10 +933,8 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) | |||
909 | 933 | ||
910 | /* Enable the radio */ | 934 | /* Enable the radio */ |
911 | retval = rt2x00lib_enable_radio(rt2x00dev); | 935 | retval = rt2x00lib_enable_radio(rt2x00dev); |
912 | if (retval) { | 936 | if (retval) |
913 | rt2x00queue_uninitialize(rt2x00dev); | ||
914 | return retval; | 937 | return retval; |
915 | } | ||
916 | 938 | ||
917 | set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); | 939 | set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); |
918 | 940 | ||
@@ -1028,6 +1050,16 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1028 | cancel_work_sync(&rt2x00dev->txdone_work); | 1050 | cancel_work_sync(&rt2x00dev->txdone_work); |
1029 | 1051 | ||
1030 | /* | 1052 | /* |
1053 | * Free the tx status fifo. | ||
1054 | */ | ||
1055 | kfifo_free(&rt2x00dev->txstatus_fifo); | ||
1056 | |||
1057 | /* | ||
1058 | * Kill the tx status tasklet. | ||
1059 | */ | ||
1060 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | ||
1061 | |||
1062 | /* | ||
1031 | * Uninitialize device. | 1063 | * Uninitialize device. |
1032 | */ | 1064 | */ |
1033 | rt2x00lib_uninitialize(rt2x00dev); | 1065 | rt2x00lib_uninitialize(rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index ad3c7ff4837b..c637bcaec5f8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -60,9 +60,10 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
60 | * when using more then one tx stream (>MCS7). | 60 | * when using more then one tx stream (>MCS7). |
61 | */ | 61 | */ |
62 | if (tx_info->control.sta && txdesc->mcs > 7 && | 62 | if (tx_info->control.sta && txdesc->mcs > 7 && |
63 | (tx_info->control.sta->ht_cap.cap & | 63 | ((tx_info->control.sta->ht_cap.cap & |
64 | (WLAN_HT_CAP_SM_PS_DYNAMIC << | 64 | IEEE80211_HT_CAP_SM_PS) >> |
65 | IEEE80211_HT_CAP_SM_PS_SHIFT))) | 65 | IEEE80211_HT_CAP_SM_PS_SHIFT) == |
66 | WLAN_HT_CAP_SM_PS_DYNAMIC) | ||
66 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); | 67 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); |
67 | } else { | 68 | } else { |
68 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | 69 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); |
@@ -72,9 +73,11 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
72 | 73 | ||
73 | 74 | ||
74 | /* | 75 | /* |
75 | * Convert flags | 76 | * This frame is eligible for an AMPDU, however, don't aggregate |
77 | * frames that are intended to probe a specific tx rate. | ||
76 | */ | 78 | */ |
77 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | 79 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && |
80 | !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) | ||
78 | __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); | 81 | __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); |
79 | 82 | ||
80 | /* | 83 | /* |
@@ -84,7 +87,13 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
84 | txdesc->rate_mode = RATE_MODE_HT_MIX; | 87 | txdesc->rate_mode = RATE_MODE_HT_MIX; |
85 | if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) | 88 | if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) |
86 | txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; | 89 | txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; |
87 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 90 | |
91 | /* | ||
92 | * Set 40Mhz mode if necessary (for legacy rates this will | ||
93 | * duplicate the frame to both channels). | ||
94 | */ | ||
95 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || | ||
96 | txrate->flags & IEEE80211_TX_RC_DUP_DATA) | ||
88 | __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); | 97 | __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); |
89 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | 98 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) |
90 | __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); | 99 | __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 7862a840984a..c3c206a97d54 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -671,7 +671,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
671 | */ | 671 | */ |
672 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | | 672 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | |
673 | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | | 673 | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | |
674 | BSS_CHANGED_BEACON_INT)) | 674 | BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT)) |
675 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); | 675 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); |
676 | } | 676 | } |
677 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); | 677 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 97b3935f615b..af548c87f108 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2630,12 +2630,13 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2630 | * As rt61 has a global fallback table we cannot specify | 2630 | * As rt61 has a global fallback table we cannot specify |
2631 | * more then one tx rate per frame but since the hw will | 2631 | * more then one tx rate per frame but since the hw will |
2632 | * try several rates (based on the fallback table) we should | 2632 | * try several rates (based on the fallback table) we should |
2633 | * still initialize max_rates to the maximum number of rates | 2633 | * initialize max_report_rates to the maximum number of rates |
2634 | * we are going to try. Otherwise mac80211 will truncate our | 2634 | * we are going to try. Otherwise mac80211 will truncate our |
2635 | * reported tx rates and the rc algortihm will end up with | 2635 | * reported tx rates and the rc algortihm will end up with |
2636 | * incorrect data. | 2636 | * incorrect data. |
2637 | */ | 2637 | */ |
2638 | rt2x00dev->hw->max_rates = 7; | 2638 | rt2x00dev->hw->max_rates = 1; |
2639 | rt2x00dev->hw->max_report_rates = 7; | ||
2639 | rt2x00dev->hw->max_rate_tries = 1; | 2640 | rt2x00dev->hw->max_rate_tries = 1; |
2640 | 2641 | ||
2641 | /* | 2642 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e22f01c1818e..9be8089317e4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2063,9 +2063,14 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2063 | 2063 | ||
2064 | /* | 2064 | /* |
2065 | * Initialize all hw fields. | 2065 | * Initialize all hw fields. |
2066 | * | ||
2067 | * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are | ||
2068 | * capable of sending the buffered frames out after the DTIM | ||
2069 | * transmission using rt2x00lib_beacondone. This will send out | ||
2070 | * multicast and broadcast traffic immediately instead of buffering it | ||
2071 | * infinitly and thus dropping it after some time. | ||
2066 | */ | 2072 | */ |
2067 | rt2x00dev->hw->flags = | 2073 | rt2x00dev->hw->flags = |
2068 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
2069 | IEEE80211_HW_SIGNAL_DBM | | 2074 | IEEE80211_HW_SIGNAL_DBM | |
2070 | IEEE80211_HW_SUPPORTS_PS | | 2075 | IEEE80211_HW_SUPPORTS_PS | |
2071 | IEEE80211_HW_PS_NULLFUNC_STACK; | 2076 | IEEE80211_HW_PS_NULLFUNC_STACK; |
@@ -2365,6 +2370,7 @@ static struct usb_device_id rt73usb_device_table[] = { | |||
2365 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, | 2370 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, |
2366 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, | 2371 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, |
2367 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, | 2372 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, |
2373 | { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) }, | ||
2368 | /* CEIVA */ | 2374 | /* CEIVA */ |
2369 | { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, | 2375 | { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, |
2370 | /* CNet */ | 2376 | /* CNet */ |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 05c6badbe201..707c688da618 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -99,66 +99,19 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static void rtl8180_handle_tx(struct ieee80211_hw *dev) | 102 | static void rtl8180_handle_rx(struct ieee80211_hw *dev) |
103 | { | 103 | { |
104 | struct rtl8180_priv *priv = dev->priv; | 104 | struct rtl8180_priv *priv = dev->priv; |
105 | struct rtl8180_tx_ring *ring; | 105 | unsigned int count = 32; |
106 | int prio; | ||
107 | |||
108 | spin_lock(&priv->lock); | ||
109 | |||
110 | for (prio = 3; prio >= 0; prio--) { | ||
111 | ring = &priv->tx_ring[prio]; | ||
112 | |||
113 | while (skb_queue_len(&ring->queue)) { | ||
114 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | ||
115 | struct sk_buff *skb; | ||
116 | struct ieee80211_tx_info *info; | ||
117 | u32 flags = le32_to_cpu(entry->flags); | ||
118 | |||
119 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
120 | break; | ||
121 | |||
122 | ring->idx = (ring->idx + 1) % ring->entries; | ||
123 | skb = __skb_dequeue(&ring->queue); | ||
124 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
125 | skb->len, PCI_DMA_TODEVICE); | ||
126 | |||
127 | info = IEEE80211_SKB_CB(skb); | ||
128 | ieee80211_tx_info_clear_status(info); | ||
129 | |||
130 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
131 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
132 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
133 | |||
134 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
135 | info->status.rates[1].idx = -1; | ||
136 | |||
137 | ieee80211_tx_status(dev, skb); | ||
138 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
139 | ieee80211_wake_queue(dev, prio); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | spin_unlock(&priv->lock); | ||
144 | } | ||
145 | |||
146 | static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | ||
147 | { | ||
148 | struct rtl8180_priv *priv = dev->priv; | ||
149 | unsigned int count = 0; | ||
150 | u8 signal, agc, sq; | 106 | u8 signal, agc, sq; |
151 | 107 | ||
152 | /* handle pending Tx queue cleanup */ | 108 | while (count--) { |
153 | rtl8180_handle_tx(dev); | ||
154 | |||
155 | while (count++ < budget) { | ||
156 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; | 109 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; |
157 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; | 110 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; |
158 | u32 flags = le32_to_cpu(entry->flags); | 111 | u32 flags = le32_to_cpu(entry->flags); |
159 | 112 | ||
160 | if (flags & RTL818X_RX_DESC_FLAG_OWN) | 113 | if (flags & RTL818X_RX_DESC_FLAG_OWN) |
161 | break; | 114 | return; |
162 | 115 | ||
163 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | | 116 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | |
164 | RTL818X_RX_DESC_FLAG_FOF | | 117 | RTL818X_RX_DESC_FLAG_FOF | |
@@ -198,7 +151,7 @@ static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | |||
198 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 151 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
199 | 152 | ||
200 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 153 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
201 | ieee80211_rx(dev, skb); | 154 | ieee80211_rx_irqsafe(dev, skb); |
202 | 155 | ||
203 | skb = new_skb; | 156 | skb = new_skb; |
204 | priv->rx_buf[priv->rx_idx] = skb; | 157 | priv->rx_buf[priv->rx_idx] = skb; |
@@ -215,16 +168,41 @@ static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | |||
215 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); | 168 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); |
216 | priv->rx_idx = (priv->rx_idx + 1) % 32; | 169 | priv->rx_idx = (priv->rx_idx + 1) % 32; |
217 | } | 170 | } |
171 | } | ||
172 | |||
173 | static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) | ||
174 | { | ||
175 | struct rtl8180_priv *priv = dev->priv; | ||
176 | struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; | ||
218 | 177 | ||
219 | if (count < budget) { | 178 | while (skb_queue_len(&ring->queue)) { |
220 | /* disable polling */ | 179 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; |
221 | ieee80211_napi_complete(dev); | 180 | struct sk_buff *skb; |
181 | struct ieee80211_tx_info *info; | ||
182 | u32 flags = le32_to_cpu(entry->flags); | ||
222 | 183 | ||
223 | /* enable interrupts */ | 184 | if (flags & RTL818X_TX_DESC_FLAG_OWN) |
224 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); | 185 | return; |
225 | } | 186 | |
187 | ring->idx = (ring->idx + 1) % ring->entries; | ||
188 | skb = __skb_dequeue(&ring->queue); | ||
189 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
190 | skb->len, PCI_DMA_TODEVICE); | ||
191 | |||
192 | info = IEEE80211_SKB_CB(skb); | ||
193 | ieee80211_tx_info_clear_status(info); | ||
194 | |||
195 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
196 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
197 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
198 | |||
199 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
200 | info->status.rates[1].idx = -1; | ||
226 | 201 | ||
227 | return count; | 202 | ieee80211_tx_status_irqsafe(dev, skb); |
203 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
204 | ieee80211_wake_queue(dev, prio); | ||
205 | } | ||
228 | } | 206 | } |
229 | 207 | ||
230 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | 208 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) |
@@ -233,17 +211,31 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
233 | struct rtl8180_priv *priv = dev->priv; | 211 | struct rtl8180_priv *priv = dev->priv; |
234 | u16 reg; | 212 | u16 reg; |
235 | 213 | ||
214 | spin_lock(&priv->lock); | ||
236 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); | 215 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); |
237 | if (unlikely(reg == 0xFFFF)) | 216 | if (unlikely(reg == 0xFFFF)) { |
217 | spin_unlock(&priv->lock); | ||
238 | return IRQ_HANDLED; | 218 | return IRQ_HANDLED; |
219 | } | ||
239 | 220 | ||
240 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); | 221 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); |
241 | 222 | ||
242 | /* disable interrupts */ | 223 | if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) |
243 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | 224 | rtl8180_handle_tx(dev, 3); |
225 | |||
226 | if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) | ||
227 | rtl8180_handle_tx(dev, 2); | ||
228 | |||
229 | if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) | ||
230 | rtl8180_handle_tx(dev, 1); | ||
244 | 231 | ||
245 | /* enable polling */ | 232 | if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) |
246 | ieee80211_napi_schedule(dev); | 233 | rtl8180_handle_tx(dev, 0); |
234 | |||
235 | if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) | ||
236 | rtl8180_handle_rx(dev); | ||
237 | |||
238 | spin_unlock(&priv->lock); | ||
247 | 239 | ||
248 | return IRQ_HANDLED; | 240 | return IRQ_HANDLED; |
249 | } | 241 | } |
@@ -255,6 +247,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
255 | struct rtl8180_priv *priv = dev->priv; | 247 | struct rtl8180_priv *priv = dev->priv; |
256 | struct rtl8180_tx_ring *ring; | 248 | struct rtl8180_tx_ring *ring; |
257 | struct rtl8180_tx_desc *entry; | 249 | struct rtl8180_tx_desc *entry; |
250 | unsigned long flags; | ||
258 | unsigned int idx, prio; | 251 | unsigned int idx, prio; |
259 | dma_addr_t mapping; | 252 | dma_addr_t mapping; |
260 | u32 tx_flags; | 253 | u32 tx_flags; |
@@ -301,7 +294,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
301 | plcp_len |= 1 << 15; | 294 | plcp_len |= 1 << 15; |
302 | } | 295 | } |
303 | 296 | ||
304 | spin_lock(&priv->lock); | 297 | spin_lock_irqsave(&priv->lock, flags); |
305 | 298 | ||
306 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 299 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
307 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 300 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
@@ -325,7 +318,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
325 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 318 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
326 | ieee80211_stop_queue(dev, prio); | 319 | ieee80211_stop_queue(dev, prio); |
327 | 320 | ||
328 | spin_unlock(&priv->lock); | 321 | spin_unlock_irqrestore(&priv->lock, flags); |
329 | 322 | ||
330 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 323 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
331 | 324 | ||
@@ -871,7 +864,6 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
871 | .prepare_multicast = rtl8180_prepare_multicast, | 864 | .prepare_multicast = rtl8180_prepare_multicast, |
872 | .configure_filter = rtl8180_configure_filter, | 865 | .configure_filter = rtl8180_configure_filter, |
873 | .get_tsf = rtl8180_get_tsf, | 866 | .get_tsf = rtl8180_get_tsf, |
874 | .napi_poll = rtl8180_poll, | ||
875 | }; | 867 | }; |
876 | 868 | ||
877 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 869 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -1003,8 +995,6 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
1003 | dev->queues = 1; | 995 | dev->queues = 1; |
1004 | dev->max_signal = 65; | 996 | dev->max_signal = 65; |
1005 | 997 | ||
1006 | dev->napi_weight = 64; | ||
1007 | |||
1008 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); | 998 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); |
1009 | reg &= RTL818X_TX_CONF_HWVER_MASK; | 999 | reg &= RTL818X_TX_CONF_HWVER_MASK; |
1010 | switch (reg) { | 1000 | switch (reg) { |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 4134f4495b95..8a4cd763e5a2 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -117,10 +117,7 @@ enum { | |||
117 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 117 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
118 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | 118 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) |
119 | 119 | ||
120 | /* | 120 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 |
121 | * Enable/disable 802.11a support for WL1273 | ||
122 | */ | ||
123 | #undef WL1271_80211A_ENABLED | ||
124 | 121 | ||
125 | #define WL1271_BUSY_WORD_CNT 1 | 122 | #define WL1271_BUSY_WORD_CNT 1 |
126 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 123 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
@@ -133,6 +130,8 @@ enum { | |||
133 | 130 | ||
134 | #define ACX_TX_DESCRIPTORS 32 | 131 | #define ACX_TX_DESCRIPTORS 32 |
135 | 132 | ||
133 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | ||
134 | |||
136 | enum wl1271_state { | 135 | enum wl1271_state { |
137 | WL1271_STATE_OFF, | 136 | WL1271_STATE_OFF, |
138 | WL1271_STATE_ON, | 137 | WL1271_STATE_ON, |
@@ -301,6 +300,7 @@ struct wl1271_rx_mem_pool_addr { | |||
301 | struct wl1271_scan { | 300 | struct wl1271_scan { |
302 | struct cfg80211_scan_request *req; | 301 | struct cfg80211_scan_request *req; |
303 | bool *scanned_ch; | 302 | bool *scanned_ch; |
303 | bool failed; | ||
304 | u8 state; | 304 | u8 state; |
305 | u8 ssid[IW_ESSID_MAX_SIZE+1]; | 305 | u8 ssid[IW_ESSID_MAX_SIZE+1]; |
306 | size_t ssid_len; | 306 | size_t ssid_len; |
@@ -350,6 +350,7 @@ struct wl1271 { | |||
350 | #define WL1271_FLAG_IDLE (10) | 350 | #define WL1271_FLAG_IDLE (10) |
351 | #define WL1271_FLAG_IDLE_REQUESTED (11) | 351 | #define WL1271_FLAG_IDLE_REQUESTED (11) |
352 | #define WL1271_FLAG_PSPOLL_FAILURE (12) | 352 | #define WL1271_FLAG_PSPOLL_FAILURE (12) |
353 | #define WL1271_FLAG_STA_STATE_SENT (13) | ||
353 | unsigned long flags; | 354 | unsigned long flags; |
354 | 355 | ||
355 | struct wl1271_partition_set part; | 356 | struct wl1271_partition_set part; |
@@ -362,6 +363,7 @@ struct wl1271 { | |||
362 | u8 *fw; | 363 | u8 *fw; |
363 | size_t fw_len; | 364 | size_t fw_len; |
364 | struct wl1271_nvs_file *nvs; | 365 | struct wl1271_nvs_file *nvs; |
366 | size_t nvs_len; | ||
365 | 367 | ||
366 | s8 hw_pg_ver; | 368 | s8 hw_pg_ver; |
367 | 369 | ||
@@ -408,9 +410,15 @@ struct wl1271 { | |||
408 | /* Rx memory pool address */ | 410 | /* Rx memory pool address */ |
409 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; | 411 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; |
410 | 412 | ||
413 | /* Intermediate buffer, used for packet aggregation */ | ||
414 | u8 *aggr_buf; | ||
415 | |||
411 | /* The target interrupt mask */ | 416 | /* The target interrupt mask */ |
412 | struct work_struct irq_work; | 417 | struct work_struct irq_work; |
413 | 418 | ||
419 | /* Hardware recovery work */ | ||
420 | struct work_struct recovery_work; | ||
421 | |||
414 | /* The mbox event mask */ | 422 | /* The mbox event mask */ |
415 | u32 event_mask; | 423 | u32 event_mask; |
416 | 424 | ||
@@ -419,6 +427,7 @@ struct wl1271 { | |||
419 | 427 | ||
420 | /* Are we currently scanning */ | 428 | /* Are we currently scanning */ |
421 | struct wl1271_scan scan; | 429 | struct wl1271_scan scan; |
430 | struct delayed_work scan_complete_work; | ||
422 | 431 | ||
423 | /* Our association ID */ | 432 | /* Our association ID */ |
424 | u16 aid; | 433 | u16 aid; |
@@ -475,6 +484,8 @@ struct wl1271 { | |||
475 | 484 | ||
476 | bool sg_enabled; | 485 | bool sg_enabled; |
477 | 486 | ||
487 | bool enable_11a; | ||
488 | |||
478 | struct list_head list; | 489 | struct list_head list; |
479 | 490 | ||
480 | /* Most recently reported noise in dBm */ | 491 | /* Most recently reported noise in dBm */ |
@@ -498,14 +509,4 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
498 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | 509 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ |
499 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 510 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
500 | 511 | ||
501 | static inline bool wl1271_11a_enabled(void) | ||
502 | { | ||
503 | /* FIXME: this could be determined based on the NVS-INI file */ | ||
504 | #ifdef WL1271_80211A_ENABLED | ||
505 | return true; | ||
506 | #else | ||
507 | return false; | ||
508 | #endif | ||
509 | } | ||
510 | |||
511 | #endif | 512 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index f03ad088db8b..618993405262 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -86,40 +86,6 @@ out: | |||
86 | return ret; | 86 | return ret; |
87 | } | 87 | } |
88 | 88 | ||
89 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len) | ||
90 | { | ||
91 | struct acx_revision *rev; | ||
92 | int ret; | ||
93 | |||
94 | wl1271_debug(DEBUG_ACX, "acx fw rev"); | ||
95 | |||
96 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); | ||
97 | if (!rev) { | ||
98 | ret = -ENOMEM; | ||
99 | goto out; | ||
100 | } | ||
101 | |||
102 | ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); | ||
103 | if (ret < 0) { | ||
104 | wl1271_warning("ACX_FW_REV interrogate failed"); | ||
105 | goto out; | ||
106 | } | ||
107 | |||
108 | /* be careful with the buffer sizes */ | ||
109 | strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); | ||
110 | |||
111 | /* | ||
112 | * if the firmware version string is exactly | ||
113 | * sizeof(rev->fw_version) long or fw_len is less than | ||
114 | * sizeof(rev->fw_version) it won't be null terminated | ||
115 | */ | ||
116 | buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; | ||
117 | |||
118 | out: | ||
119 | kfree(rev); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | int wl1271_acx_tx_power(struct wl1271 *wl, int power) | 89 | int wl1271_acx_tx_power(struct wl1271 *wl, int power) |
124 | { | 90 | { |
125 | struct acx_current_tx_power *acx; | 91 | struct acx_current_tx_power *acx; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 4235bc56f750..ebb341d36e8c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -100,35 +100,6 @@ struct acx_error_counter { | |||
100 | __le32 seq_num_miss; | 100 | __le32 seq_num_miss; |
101 | } __packed; | 101 | } __packed; |
102 | 102 | ||
103 | struct acx_revision { | ||
104 | struct acx_header header; | ||
105 | |||
106 | /* | ||
107 | * The WiLink firmware version, an ASCII string x.x.x.x, | ||
108 | * that uniquely identifies the current firmware. | ||
109 | * The left most digit is incremented each time a | ||
110 | * significant change is made to the firmware, such as | ||
111 | * code redesign or new platform support. | ||
112 | * The second digit is incremented when major enhancements | ||
113 | * are added or major fixes are made. | ||
114 | * The third digit is incremented for each GA release. | ||
115 | * The fourth digit is incremented for each build. | ||
116 | * The first two digits identify a firmware release version, | ||
117 | * in other words, a unique set of features. | ||
118 | * The first three digits identify a GA release. | ||
119 | */ | ||
120 | char fw_version[20]; | ||
121 | |||
122 | /* | ||
123 | * This 4 byte field specifies the WiLink hardware version. | ||
124 | * bits 0 - 15: Reserved. | ||
125 | * bits 16 - 23: Version ID - The WiLink version ID | ||
126 | * (1 = first spin, 2 = second spin, and so on). | ||
127 | * bits 24 - 31: Chip ID - The WiLink chip ID. | ||
128 | */ | ||
129 | __le32 hw_version; | ||
130 | } __packed; | ||
131 | |||
132 | enum wl1271_psm_mode { | 103 | enum wl1271_psm_mode { |
133 | /* Active mode */ | 104 | /* Active mode */ |
134 | WL1271_PSM_CAM = 0, | 105 | WL1271_PSM_CAM = 0, |
@@ -1060,7 +1031,6 @@ enum { | |||
1060 | ACX_PEER_HT_CAP = 0x0057, | 1031 | ACX_PEER_HT_CAP = 0x0057, |
1061 | ACX_HT_BSS_OPERATION = 0x0058, | 1032 | ACX_HT_BSS_OPERATION = 0x0058, |
1062 | ACX_COEX_ACTIVITY = 0x0059, | 1033 | ACX_COEX_ACTIVITY = 0x0059, |
1063 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | ||
1064 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, | 1034 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1065 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1035 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1066 | DOT11_CUR_TX_PWR = 0x100D, | 1036 | DOT11_CUR_TX_PWR = 0x100D, |
@@ -1077,7 +1047,6 @@ enum { | |||
1077 | 1047 | ||
1078 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl); | 1048 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl); |
1079 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); | 1049 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); |
1080 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len); | ||
1081 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); | 1050 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); |
1082 | int wl1271_acx_feature_cfg(struct wl1271 *wl); | 1051 | int wl1271_acx_feature_cfg(struct wl1271 *wl); |
1083 | int wl1271_acx_mem_map(struct wl1271 *wl, | 1052 | int wl1271_acx_mem_map(struct wl1271 *wl, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index e5a7f042645f..b91021242098 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
225 | if (wl->nvs == NULL) | 225 | if (wl->nvs == NULL) |
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | /* | ||
229 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
230 | * configurations) can be removed when those NVS files stop floating | ||
231 | * around. | ||
232 | */ | ||
233 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || | ||
234 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { | ||
235 | if (wl->nvs->general_params.dual_mode_select) | ||
236 | wl->enable_11a = true; | ||
237 | } | ||
238 | |||
239 | if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && | ||
240 | (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
241 | wl->enable_11a)) { | ||
242 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
243 | wl->nvs_len, sizeof(struct wl1271_nvs_file)); | ||
244 | kfree(wl->nvs); | ||
245 | wl->nvs = NULL; | ||
246 | wl->nvs_len = 0; | ||
247 | return -EILSEQ; | ||
248 | } | ||
249 | |||
228 | /* only the first part of the NVS needs to be uploaded */ | 250 | /* only the first part of the NVS needs to be uploaded */ |
229 | nvs_len = sizeof(wl->nvs->nvs); | 251 | nvs_len = sizeof(wl->nvs->nvs); |
230 | nvs_ptr = (u8 *)wl->nvs->nvs; | 252 | nvs_ptr = (u8 *)wl->nvs->nvs; |
@@ -251,8 +273,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
251 | burst_len = nvs_ptr[0]; | 273 | burst_len = nvs_ptr[0]; |
252 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); | 274 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); |
253 | 275 | ||
254 | /* FIXME: Due to our new wl1271_translate_reg_addr function, | 276 | /* |
255 | we need to add the REGISTER_BASE to the destination */ | 277 | * Due to our new wl1271_translate_reg_addr function, |
278 | * we need to add the REGISTER_BASE to the destination | ||
279 | */ | ||
256 | dest_addr += REGISTERS_BASE; | 280 | dest_addr += REGISTERS_BASE; |
257 | 281 | ||
258 | /* We move our pointer to the data */ | 282 | /* We move our pointer to the data */ |
@@ -280,8 +304,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
280 | ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); | 304 | ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); |
281 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; | 305 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; |
282 | 306 | ||
283 | /* FIXME: The driver sets the partition here, but this is not needed, | ||
284 | since it sets to the same one as currently in use */ | ||
285 | /* Now we must set the partition correctly */ | 307 | /* Now we must set the partition correctly */ |
286 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 308 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
287 | 309 | ||
@@ -291,9 +313,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
291 | return -ENOMEM; | 313 | return -ENOMEM; |
292 | 314 | ||
293 | /* And finally we upload the NVS tables */ | 315 | /* And finally we upload the NVS tables */ |
294 | /* FIXME: In wl1271, we upload everything at once. | ||
295 | No endianness handling needed here?! The ref driver doesn't do | ||
296 | anything about it at this point */ | ||
297 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); | 316 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
298 | 317 | ||
299 | kfree(nvs_aligned); | 318 | kfree(nvs_aligned); |
@@ -491,10 +510,7 @@ int wl1271_boot(struct wl1271 *wl) | |||
491 | 510 | ||
492 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 511 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
493 | 512 | ||
494 | pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be | 513 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
495 | * WU_COUNTER_PAUSE_VAL instead of | ||
496 | * 0x3ff (magic number ). How does | ||
497 | * this work?! */ | ||
498 | pause |= WU_COUNTER_PAUSE_VAL; | 514 | pause |= WU_COUNTER_PAUSE_VAL; |
499 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); | 515 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); |
500 | 516 | ||
@@ -548,7 +564,6 @@ int wl1271_boot(struct wl1271 *wl) | |||
548 | if (ret < 0) | 564 | if (ret < 0) |
549 | goto out; | 565 | goto out; |
550 | 566 | ||
551 | /* FIXME: Need to check whether this is really what we want */ | ||
552 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 567 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
553 | WL1271_ACX_ALL_EVENTS_VECTOR); | 568 | WL1271_ACX_ALL_EVENTS_VECTOR); |
554 | 569 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index ce503ddd5a41..5d3e8485ea4e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
94 | status = le16_to_cpu(cmd->status); | 94 | status = le16_to_cpu(cmd->status); |
95 | if (status != CMD_STATUS_SUCCESS) { | 95 | if (status != CMD_STATUS_SUCCESS) { |
96 | wl1271_error("command execute failure %d", status); | 96 | wl1271_error("command execute failure %d", status); |
97 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
97 | ret = -EIO; | 98 | ret = -EIO; |
98 | } | 99 | } |
99 | 100 | ||
@@ -107,6 +108,8 @@ out: | |||
107 | int wl1271_cmd_general_parms(struct wl1271 *wl) | 108 | int wl1271_cmd_general_parms(struct wl1271 *wl) |
108 | { | 109 | { |
109 | struct wl1271_general_parms_cmd *gen_parms; | 110 | struct wl1271_general_parms_cmd *gen_parms; |
111 | struct wl1271_ini_general_params *gp = &wl->nvs->general_params; | ||
112 | bool answer = false; | ||
110 | int ret; | 113 | int ret; |
111 | 114 | ||
112 | if (!wl->nvs) | 115 | if (!wl->nvs) |
@@ -118,13 +121,24 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
118 | 121 | ||
119 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 122 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
120 | 123 | ||
121 | memcpy(&gen_parms->general_params, &wl->nvs->general_params, | 124 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); |
122 | sizeof(struct wl1271_ini_general_params)); | ||
123 | 125 | ||
124 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 126 | if (gp->tx_bip_fem_auto_detect) |
125 | if (ret < 0) | 127 | answer = true; |
128 | |||
129 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
130 | if (ret < 0) { | ||
126 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 131 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
132 | goto out; | ||
133 | } | ||
134 | |||
135 | gp->tx_bip_fem_manufacturer = | ||
136 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
137 | |||
138 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
139 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
127 | 140 | ||
141 | out: | ||
128 | kfree(gen_parms); | 142 | kfree(gen_parms); |
129 | return ret; | 143 | return ret; |
130 | } | 144 | } |
@@ -170,6 +184,39 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
170 | return ret; | 184 | return ret; |
171 | } | 185 | } |
172 | 186 | ||
187 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) | ||
188 | { | ||
189 | struct wl1271_ext_radio_parms_cmd *ext_radio_parms; | ||
190 | struct conf_rf_settings *rf = &wl->conf.rf; | ||
191 | int ret; | ||
192 | |||
193 | if (!wl->nvs) | ||
194 | return -ENODEV; | ||
195 | |||
196 | ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); | ||
197 | if (!ext_radio_parms) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; | ||
201 | |||
202 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, | ||
203 | rf->tx_per_channel_power_compensation_2, | ||
204 | CONF_TX_PWR_COMPENSATION_LEN_2); | ||
205 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, | ||
206 | rf->tx_per_channel_power_compensation_5, | ||
207 | CONF_TX_PWR_COMPENSATION_LEN_5); | ||
208 | |||
209 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", | ||
210 | ext_radio_parms, sizeof(*ext_radio_parms)); | ||
211 | |||
212 | ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); | ||
213 | if (ret < 0) | ||
214 | wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); | ||
215 | |||
216 | kfree(ext_radio_parms); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
173 | /* | 220 | /* |
174 | * Poll the mailbox event field until any of the bits in the mask is set or a | 221 | * Poll the mailbox event field until any of the bits in the mask is set or a |
175 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 222 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
@@ -182,8 +229,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
182 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 229 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
183 | 230 | ||
184 | do { | 231 | do { |
185 | if (time_after(jiffies, timeout)) | 232 | if (time_after(jiffies, timeout)) { |
233 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
186 | return -ETIMEDOUT; | 234 | return -ETIMEDOUT; |
235 | } | ||
187 | 236 | ||
188 | msleep(1); | 237 | msleep(1); |
189 | 238 | ||
@@ -390,18 +439,11 @@ out: | |||
390 | return ret; | 439 | return ret; |
391 | } | 440 | } |
392 | 441 | ||
393 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | 442 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send) |
394 | { | 443 | { |
395 | struct wl1271_cmd_ps_params *ps_params = NULL; | 444 | struct wl1271_cmd_ps_params *ps_params = NULL; |
396 | int ret = 0; | 445 | int ret = 0; |
397 | 446 | ||
398 | /* FIXME: this should be in ps.c */ | ||
399 | ret = wl1271_acx_wake_up_conditions(wl); | ||
400 | if (ret < 0) { | ||
401 | wl1271_error("couldn't set wake up conditions"); | ||
402 | goto out; | ||
403 | } | ||
404 | |||
405 | wl1271_debug(DEBUG_CMD, "cmd set ps mode"); | 447 | wl1271_debug(DEBUG_CMD, "cmd set ps mode"); |
406 | 448 | ||
407 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); | 449 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); |
@@ -412,9 +454,9 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | |||
412 | 454 | ||
413 | ps_params->ps_mode = ps_mode; | 455 | ps_params->ps_mode = ps_mode; |
414 | ps_params->send_null_data = send; | 456 | ps_params->send_null_data = send; |
415 | ps_params->retries = 5; | 457 | ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries; |
416 | ps_params->hang_over_period = 1; | 458 | ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period; |
417 | ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set); | 459 | ps_params->null_data_rate = cpu_to_le32(rates); |
418 | 460 | ||
419 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 461 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
420 | sizeof(*ps_params), 0); | 462 | sizeof(*ps_params), 0); |
@@ -428,41 +470,6 @@ out: | |||
428 | return ret; | 470 | return ret; |
429 | } | 471 | } |
430 | 472 | ||
431 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | ||
432 | size_t len) | ||
433 | { | ||
434 | struct cmd_read_write_memory *cmd; | ||
435 | int ret = 0; | ||
436 | |||
437 | wl1271_debug(DEBUG_CMD, "cmd read memory"); | ||
438 | |||
439 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
440 | if (!cmd) { | ||
441 | ret = -ENOMEM; | ||
442 | goto out; | ||
443 | } | ||
444 | |||
445 | WARN_ON(len > MAX_READ_SIZE); | ||
446 | len = min_t(size_t, len, MAX_READ_SIZE); | ||
447 | |||
448 | cmd->addr = cpu_to_le32(addr); | ||
449 | cmd->size = cpu_to_le32(len); | ||
450 | |||
451 | ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), | ||
452 | sizeof(*cmd)); | ||
453 | if (ret < 0) { | ||
454 | wl1271_error("read memory command failed: %d", ret); | ||
455 | goto out; | ||
456 | } | ||
457 | |||
458 | /* the read command got in */ | ||
459 | memcpy(answer, cmd->value, len); | ||
460 | |||
461 | out: | ||
462 | kfree(cmd); | ||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 473 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
467 | void *buf, size_t buf_len, int index, u32 rates) | 474 | void *buf, size_t buf_len, int index, u32 rates) |
468 | { | 475 | { |
@@ -523,7 +530,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) | |||
523 | } | 530 | } |
524 | 531 | ||
525 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, | 532 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
526 | WL1271_RATE_AUTOMATIC); | 533 | wl->basic_rate); |
527 | 534 | ||
528 | out: | 535 | out: |
529 | dev_kfree_skb(skb); | 536 | dev_kfree_skb(skb); |
@@ -546,7 +553,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) | |||
546 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, | 553 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, |
547 | skb->data, skb->len, | 554 | skb->data, skb->len, |
548 | CMD_TEMPL_KLV_IDX_NULL_DATA, | 555 | CMD_TEMPL_KLV_IDX_NULL_DATA, |
549 | WL1271_RATE_AUTOMATIC); | 556 | wl->basic_rate); |
550 | 557 | ||
551 | out: | 558 | out: |
552 | dev_kfree_skb(skb); | 559 | dev_kfree_skb(skb); |
@@ -623,7 +630,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
623 | 630 | ||
624 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | 631 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, |
625 | sizeof(template), 0, | 632 | sizeof(template), 0, |
626 | WL1271_RATE_AUTOMATIC); | 633 | wl->basic_rate); |
627 | } | 634 | } |
628 | 635 | ||
629 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 636 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
@@ -746,3 +753,31 @@ out_free: | |||
746 | out: | 753 | out: |
747 | return ret; | 754 | return ret; |
748 | } | 755 | } |
756 | |||
757 | int wl1271_cmd_set_sta_state(struct wl1271 *wl) | ||
758 | { | ||
759 | struct wl1271_cmd_set_sta_state *cmd; | ||
760 | int ret = 0; | ||
761 | |||
762 | wl1271_debug(DEBUG_CMD, "cmd set sta state"); | ||
763 | |||
764 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
765 | if (!cmd) { | ||
766 | ret = -ENOMEM; | ||
767 | goto out; | ||
768 | } | ||
769 | |||
770 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; | ||
771 | |||
772 | ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); | ||
773 | if (ret < 0) { | ||
774 | wl1271_error("failed to send set STA state command"); | ||
775 | goto out_free; | ||
776 | } | ||
777 | |||
778 | out_free: | ||
779 | kfree(cmd); | ||
780 | |||
781 | out: | ||
782 | return ret; | ||
783 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index af577ee8eb02..a0caf4fc37b1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -33,12 +33,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wl1271_cmd_general_parms(struct wl1271 *wl); | 34 | int wl1271_cmd_general_parms(struct wl1271 *wl); |
35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | 35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); |
36 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); | ||
36 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); | 37 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); |
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 38 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 40 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | 41 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 42 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 43 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 44 | size_t len); |
44 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 45 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
@@ -55,6 +56,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
55 | u8 key_size, const u8 *key, const u8 *addr, | 56 | u8 key_size, const u8 *key, const u8 *addr, |
56 | u32 tx_seq_32, u16 tx_seq_16); | 57 | u32 tx_seq_32, u16 tx_seq_16); |
57 | int wl1271_cmd_disconnect(struct wl1271 *wl); | 58 | int wl1271_cmd_disconnect(struct wl1271 *wl); |
59 | int wl1271_cmd_set_sta_state(struct wl1271 *wl); | ||
58 | 60 | ||
59 | enum wl1271_commands { | 61 | enum wl1271_commands { |
60 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 62 | CMD_INTERROGATE = 1, /*use this to read information elements*/ |
@@ -160,41 +162,6 @@ enum { | |||
160 | MAX_COMMAND_STATUS = 0xff | 162 | MAX_COMMAND_STATUS = 0xff |
161 | }; | 163 | }; |
162 | 164 | ||
163 | |||
164 | /* | ||
165 | * CMD_READ_MEMORY | ||
166 | * | ||
167 | * The host issues this command to read the WiLink device memory/registers. | ||
168 | * | ||
169 | * Note: The Base Band address has special handling (16 bits registers and | ||
170 | * addresses). For more information, see the hardware specification. | ||
171 | */ | ||
172 | /* | ||
173 | * CMD_WRITE_MEMORY | ||
174 | * | ||
175 | * The host issues this command to write the WiLink device memory/registers. | ||
176 | * | ||
177 | * The Base Band address has special handling (16 bits registers and | ||
178 | * addresses). For more information, see the hardware specification. | ||
179 | */ | ||
180 | #define MAX_READ_SIZE 256 | ||
181 | |||
182 | struct cmd_read_write_memory { | ||
183 | struct wl1271_cmd_header header; | ||
184 | |||
185 | /* The address of the memory to read from or write to.*/ | ||
186 | __le32 addr; | ||
187 | |||
188 | /* The amount of data in bytes to read from or write to the WiLink | ||
189 | * device.*/ | ||
190 | __le32 size; | ||
191 | |||
192 | /* The actual value read from or written to the Wilink. The source | ||
193 | of this field is the Host in WRITE command or the Wilink in READ | ||
194 | command. */ | ||
195 | u8 value[MAX_READ_SIZE]; | ||
196 | } __packed; | ||
197 | |||
198 | #define CMDMBOX_HEADER_LEN 4 | 165 | #define CMDMBOX_HEADER_LEN 4 |
199 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 166 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
200 | 167 | ||
@@ -313,7 +280,7 @@ enum wl1271_cmd_key_type { | |||
313 | KEY_WEP = 1, | 280 | KEY_WEP = 1, |
314 | KEY_TKIP = 2, | 281 | KEY_TKIP = 2, |
315 | KEY_AES = 3, | 282 | KEY_AES = 3, |
316 | KEY_GEM = 4 | 283 | KEY_GEM = 4, |
317 | }; | 284 | }; |
318 | 285 | ||
319 | /* FIXME: Add description for key-types */ | 286 | /* FIXME: Add description for key-types */ |
@@ -358,13 +325,14 @@ enum wl1271_channel_tune_bands { | |||
358 | WL1271_CHANNEL_TUNE_BAND_4_9 | 325 | WL1271_CHANNEL_TUNE_BAND_4_9 |
359 | }; | 326 | }; |
360 | 327 | ||
361 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 | 328 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 |
362 | 329 | ||
363 | #define TEST_CMD_P2G_CAL 0x02 | 330 | #define TEST_CMD_P2G_CAL 0x02 |
364 | #define TEST_CMD_CHANNEL_TUNE 0x0d | 331 | #define TEST_CMD_CHANNEL_TUNE 0x0d |
365 | #define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d | 332 | #define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d |
366 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 | 333 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 |
367 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E | 334 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E |
335 | #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 | ||
368 | 336 | ||
369 | struct wl1271_general_parms_cmd { | 337 | struct wl1271_general_parms_cmd { |
370 | struct wl1271_cmd_header header; | 338 | struct wl1271_cmd_header header; |
@@ -397,6 +365,16 @@ struct wl1271_radio_parms_cmd { | |||
397 | u8 padding3[2]; | 365 | u8 padding3[2]; |
398 | } __packed; | 366 | } __packed; |
399 | 367 | ||
368 | struct wl1271_ext_radio_parms_cmd { | ||
369 | struct wl1271_cmd_header header; | ||
370 | |||
371 | struct wl1271_cmd_test_header test; | ||
372 | |||
373 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
374 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
375 | u8 padding[3]; | ||
376 | } __packed; | ||
377 | |||
400 | struct wl1271_cmd_cal_channel_tune { | 378 | struct wl1271_cmd_cal_channel_tune { |
401 | struct wl1271_cmd_header header; | 379 | struct wl1271_cmd_header header; |
402 | 380 | ||
@@ -469,4 +447,13 @@ struct wl1271_cmd_disconnect { | |||
469 | u8 padding; | 447 | u8 padding; |
470 | } __packed; | 448 | } __packed; |
471 | 449 | ||
450 | #define WL1271_CMD_STA_STATE_CONNECTED 1 | ||
451 | |||
452 | struct wl1271_cmd_set_sta_state { | ||
453 | struct wl1271_cmd_header header; | ||
454 | |||
455 | u8 state; | ||
456 | u8 padding[3]; | ||
457 | } __packed; | ||
458 | |||
472 | #endif /* __WL1271_CMD_H__ */ | 459 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 0435ffda8f73..5f78a6cb1433 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -595,7 +595,7 @@ struct conf_tx_ac_category { | |||
595 | u16 tx_op_limit; | 595 | u16 tx_op_limit; |
596 | }; | 596 | }; |
597 | 597 | ||
598 | #define CONF_TX_MAX_TID_COUNT 7 | 598 | #define CONF_TX_MAX_TID_COUNT 8 |
599 | 599 | ||
600 | enum { | 600 | enum { |
601 | CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ | 601 | CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ |
@@ -912,6 +912,22 @@ struct conf_conn_settings { | |||
912 | u8 psm_entry_retries; | 912 | u8 psm_entry_retries; |
913 | 913 | ||
914 | /* | 914 | /* |
915 | * Specifies the maximum number of times to try transmit the PSM entry | ||
916 | * null-func frame for each PSM entry attempt | ||
917 | * | ||
918 | * Range 0 - 255 | ||
919 | */ | ||
920 | u8 psm_entry_nullfunc_retries; | ||
921 | |||
922 | /* | ||
923 | * Specifies the time to linger in active mode after successfully | ||
924 | * transmitting the PSM entry null-func frame. | ||
925 | * | ||
926 | * Range 0 - 255 TU's | ||
927 | */ | ||
928 | u8 psm_entry_hangover_period; | ||
929 | |||
930 | /* | ||
915 | * | 931 | * |
916 | * Specifies the interval of the connection keep-alive null-func | 932 | * Specifies the interval of the connection keep-alive null-func |
917 | * frame in ms. | 933 | * frame in ms. |
@@ -1016,6 +1032,64 @@ struct conf_roam_trigger_settings { | |||
1016 | u8 avg_weight_snr_data; | 1032 | u8 avg_weight_snr_data; |
1017 | }; | 1033 | }; |
1018 | 1034 | ||
1035 | struct conf_scan_settings { | ||
1036 | /* | ||
1037 | * The minimum time to wait on each channel for active scans | ||
1038 | * | ||
1039 | * Range: 0 - 65536 tu | ||
1040 | */ | ||
1041 | u16 min_dwell_time_active; | ||
1042 | |||
1043 | /* | ||
1044 | * The maximum time to wait on each channel for active scans | ||
1045 | * | ||
1046 | * Range: 0 - 65536 tu | ||
1047 | */ | ||
1048 | u16 max_dwell_time_active; | ||
1049 | |||
1050 | /* | ||
1051 | * The maximum time to wait on each channel for passive scans | ||
1052 | * | ||
1053 | * Range: 0 - 65536 tu | ||
1054 | */ | ||
1055 | u16 min_dwell_time_passive; | ||
1056 | |||
1057 | /* | ||
1058 | * The maximum time to wait on each channel for passive scans | ||
1059 | * | ||
1060 | * Range: 0 - 65536 tu | ||
1061 | */ | ||
1062 | u16 max_dwell_time_passive; | ||
1063 | |||
1064 | /* | ||
1065 | * Number of probe requests to transmit on each active scan channel | ||
1066 | * | ||
1067 | * Range: u8 | ||
1068 | */ | ||
1069 | u16 num_probe_reqs; | ||
1070 | |||
1071 | }; | ||
1072 | |||
1073 | /* these are number of channels on the band divided by two, rounded up */ | ||
1074 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | ||
1075 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | ||
1076 | |||
1077 | struct conf_rf_settings { | ||
1078 | /* | ||
1079 | * Per channel power compensation for 2.4GHz | ||
1080 | * | ||
1081 | * Range: s8 | ||
1082 | */ | ||
1083 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
1084 | |||
1085 | /* | ||
1086 | * Per channel power compensation for 5GHz | ||
1087 | * | ||
1088 | * Range: s8 | ||
1089 | */ | ||
1090 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
1091 | }; | ||
1092 | |||
1019 | struct conf_drv_settings { | 1093 | struct conf_drv_settings { |
1020 | struct conf_sg_settings sg; | 1094 | struct conf_sg_settings sg; |
1021 | struct conf_rx_settings rx; | 1095 | struct conf_rx_settings rx; |
@@ -1024,6 +1098,8 @@ struct conf_drv_settings { | |||
1024 | struct conf_itrim_settings itrim; | 1098 | struct conf_itrim_settings itrim; |
1025 | struct conf_pm_config_settings pm_config; | 1099 | struct conf_pm_config_settings pm_config; |
1026 | struct conf_roam_trigger_settings roam_trigger; | 1100 | struct conf_roam_trigger_settings roam_trigger; |
1101 | struct conf_scan_settings scan; | ||
1102 | struct conf_rf_settings rf; | ||
1027 | }; | 1103 | }; |
1028 | 1104 | ||
1029 | #endif | 1105 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 25ce2cd5e3f3..7b3f50382963 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work) | |||
41 | 41 | ||
42 | mutex_lock(&wl->mutex); | 42 | mutex_lock(&wl->mutex); |
43 | 43 | ||
44 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
45 | goto out; | ||
46 | |||
44 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) | 47 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) |
45 | goto out; | 48 | goto out; |
46 | 49 | ||
@@ -52,7 +55,7 @@ void wl1271_pspoll_work(struct work_struct *work) | |||
52 | * delivery failure occurred, and no-one changed state since, so | 55 | * delivery failure occurred, and no-one changed state since, so |
53 | * we should go back to powersave. | 56 | * we should go back to powersave. |
54 | */ | 57 | */ |
55 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); | 58 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); |
56 | 59 | ||
57 | out: | 60 | out: |
58 | mutex_unlock(&wl->mutex); | 61 | mutex_unlock(&wl->mutex); |
@@ -70,7 +73,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) | |||
70 | 73 | ||
71 | /* force active mode receive data from the AP */ | 74 | /* force active mode receive data from the AP */ |
72 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 75 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
73 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true); | 76 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
77 | wl->basic_rate, true); | ||
74 | if (ret < 0) | 78 | if (ret < 0) |
75 | return; | 79 | return; |
76 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | 80 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); |
@@ -91,6 +95,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
91 | bool *beacon_loss) | 95 | bool *beacon_loss) |
92 | { | 96 | { |
93 | int ret = 0; | 97 | int ret = 0; |
98 | u32 total_retries = wl->conf.conn.psm_entry_retries; | ||
94 | 99 | ||
95 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); | 100 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); |
96 | 101 | ||
@@ -104,10 +109,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
104 | break; | 109 | break; |
105 | } | 110 | } |
106 | 111 | ||
107 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { | 112 | if (wl->psm_entry_retry < total_retries) { |
108 | wl->psm_entry_retry++; | 113 | wl->psm_entry_retry++; |
109 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 114 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
110 | true); | 115 | wl->basic_rate, true); |
111 | } else { | 116 | } else { |
112 | wl1271_info("No ack to nullfunc from AP."); | 117 | wl1271_info("No ack to nullfunc from AP."); |
113 | wl->psm_entry_retry = 0; | 118 | wl->psm_entry_retry = 0; |
@@ -143,7 +148,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
143 | /* make sure the firmware goes to active mode - the frame to | 148 | /* make sure the firmware goes to active mode - the frame to |
144 | be sent next will indicate to the AP, that we are active. */ | 149 | be sent next will indicate to the AP, that we are active. */ |
145 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 150 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
146 | false); | 151 | wl->basic_rate, false); |
147 | break; | 152 | break; |
148 | case EVENT_EXIT_POWER_SAVE_SUCCESS: | 153 | case EVENT_EXIT_POWER_SAVE_SUCCESS: |
149 | default: | 154 | default: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 4447af1557f5..8044bba70ee7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret, i; | 55 | int ret, i; |
56 | size_t size; | ||
56 | 57 | ||
57 | /* send empty templates for fw memory reservation */ | 58 | /* send empty templates for fw memory reservation */ |
58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 59 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
61 | if (ret < 0) | 62 | if (ret < 0) |
62 | return ret; | 63 | return ret; |
63 | 64 | ||
64 | if (wl1271_11a_enabled()) { | 65 | size = sizeof(struct wl12xx_probe_req_template); |
65 | size_t size = sizeof(struct wl12xx_probe_req_template); | 66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 67 | NULL, size, 0, |
67 | NULL, size, 0, | 68 | WL1271_RATE_AUTOMATIC); |
68 | WL1271_RATE_AUTOMATIC); | 69 | if (ret < 0) |
69 | if (ret < 0) | 70 | return ret; |
70 | return ret; | ||
71 | } | ||
72 | 71 | ||
73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 72 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
74 | sizeof(struct wl12xx_null_data_template), | 73 | sizeof(struct wl12xx_null_data_template), |
@@ -223,6 +222,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
223 | if (ret < 0) | 222 | if (ret < 0) |
224 | return ret; | 223 | return ret; |
225 | 224 | ||
225 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
226 | /* Template settings */ | 229 | /* Template settings */ |
227 | ret = wl1271_init_templates_config(wl); | 230 | ret = wl1271_init_templates_config(wl); |
228 | if (ret < 0) | 231 | if (ret < 0) |
@@ -291,8 +294,16 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
291 | if (ret < 0) | 294 | if (ret < 0) |
292 | goto out_free_memmap; | 295 | goto out_free_memmap; |
293 | 296 | ||
294 | /* Default TID configuration */ | 297 | /* Default TID/AC configuration */ |
298 | BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); | ||
295 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 299 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
300 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
301 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
302 | conf_ac->cw_max, conf_ac->aifsn, | ||
303 | conf_ac->tx_op_limit); | ||
304 | if (ret < 0) | ||
305 | goto out_free_memmap; | ||
306 | |||
296 | conf_tid = &wl->conf.tx.tid_conf[i]; | 307 | conf_tid = &wl->conf.tx.tid_conf[i]; |
297 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | 308 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
298 | conf_tid->channel_type, | 309 | conf_tid->channel_type, |
@@ -305,16 +316,6 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
305 | goto out_free_memmap; | 316 | goto out_free_memmap; |
306 | } | 317 | } |
307 | 318 | ||
308 | /* Default AC configuration */ | ||
309 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
310 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
311 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
312 | conf_ac->cw_max, conf_ac->aifsn, | ||
313 | conf_ac->tx_op_limit); | ||
314 | if (ret < 0) | ||
315 | goto out_free_memmap; | ||
316 | } | ||
317 | |||
318 | /* Configure TX rate classes */ | 319 | /* Configure TX rate classes */ |
319 | ret = wl1271_acx_rate_policies(wl); | 320 | ret = wl1271_acx_rate_policies(wl); |
320 | if (ret < 0) | 321 | if (ret < 0) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 776cd7c41148..48a4b9961ae6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -124,28 +124,28 @@ static struct conf_drv_settings default_conf = { | |||
124 | }, | 124 | }, |
125 | .ac_conf_count = 4, | 125 | .ac_conf_count = 4, |
126 | .ac_conf = { | 126 | .ac_conf = { |
127 | [0] = { | 127 | [CONF_TX_AC_BE] = { |
128 | .ac = CONF_TX_AC_BE, | 128 | .ac = CONF_TX_AC_BE, |
129 | .cw_min = 15, | 129 | .cw_min = 15, |
130 | .cw_max = 63, | 130 | .cw_max = 63, |
131 | .aifsn = 3, | 131 | .aifsn = 3, |
132 | .tx_op_limit = 0, | 132 | .tx_op_limit = 0, |
133 | }, | 133 | }, |
134 | [1] = { | 134 | [CONF_TX_AC_BK] = { |
135 | .ac = CONF_TX_AC_BK, | 135 | .ac = CONF_TX_AC_BK, |
136 | .cw_min = 15, | 136 | .cw_min = 15, |
137 | .cw_max = 63, | 137 | .cw_max = 63, |
138 | .aifsn = 7, | 138 | .aifsn = 7, |
139 | .tx_op_limit = 0, | 139 | .tx_op_limit = 0, |
140 | }, | 140 | }, |
141 | [2] = { | 141 | [CONF_TX_AC_VI] = { |
142 | .ac = CONF_TX_AC_VI, | 142 | .ac = CONF_TX_AC_VI, |
143 | .cw_min = 15, | 143 | .cw_min = 15, |
144 | .cw_max = 63, | 144 | .cw_max = 63, |
145 | .aifsn = CONF_TX_AIFS_PIFS, | 145 | .aifsn = CONF_TX_AIFS_PIFS, |
146 | .tx_op_limit = 3008, | 146 | .tx_op_limit = 3008, |
147 | }, | 147 | }, |
148 | [3] = { | 148 | [CONF_TX_AC_VO] = { |
149 | .ac = CONF_TX_AC_VO, | 149 | .ac = CONF_TX_AC_VO, |
150 | .cw_min = 15, | 150 | .cw_min = 15, |
151 | .cw_max = 63, | 151 | .cw_max = 63, |
@@ -153,64 +153,40 @@ static struct conf_drv_settings default_conf = { | |||
153 | .tx_op_limit = 1504, | 153 | .tx_op_limit = 1504, |
154 | }, | 154 | }, |
155 | }, | 155 | }, |
156 | .tid_conf_count = 7, | 156 | .tid_conf_count = 4, |
157 | .tid_conf = { | 157 | .tid_conf = { |
158 | [0] = { | 158 | [CONF_TX_AC_BE] = { |
159 | .queue_id = 0, | 159 | .queue_id = CONF_TX_AC_BE, |
160 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 160 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
161 | .tsid = CONF_TX_AC_BE, | ||
162 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
163 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
164 | .apsd_conf = {0, 0}, | ||
165 | }, | ||
166 | [1] = { | ||
167 | .queue_id = 1, | ||
168 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
169 | .tsid = CONF_TX_AC_BE, | 161 | .tsid = CONF_TX_AC_BE, |
170 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 162 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
171 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 163 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
172 | .apsd_conf = {0, 0}, | 164 | .apsd_conf = {0, 0}, |
173 | }, | 165 | }, |
174 | [2] = { | 166 | [CONF_TX_AC_BK] = { |
175 | .queue_id = 2, | 167 | .queue_id = CONF_TX_AC_BK, |
176 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 168 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
177 | .tsid = CONF_TX_AC_BE, | 169 | .tsid = CONF_TX_AC_BK, |
178 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 170 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
179 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 171 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
180 | .apsd_conf = {0, 0}, | 172 | .apsd_conf = {0, 0}, |
181 | }, | 173 | }, |
182 | [3] = { | 174 | [CONF_TX_AC_VI] = { |
183 | .queue_id = 3, | 175 | .queue_id = CONF_TX_AC_VI, |
184 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 176 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
185 | .tsid = CONF_TX_AC_BE, | 177 | .tsid = CONF_TX_AC_VI, |
186 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
187 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
188 | .apsd_conf = {0, 0}, | ||
189 | }, | ||
190 | [4] = { | ||
191 | .queue_id = 4, | ||
192 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
193 | .tsid = CONF_TX_AC_BE, | ||
194 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 178 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
195 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 179 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
196 | .apsd_conf = {0, 0}, | 180 | .apsd_conf = {0, 0}, |
197 | }, | 181 | }, |
198 | [5] = { | 182 | [CONF_TX_AC_VO] = { |
199 | .queue_id = 5, | 183 | .queue_id = CONF_TX_AC_VO, |
200 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 184 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
201 | .tsid = CONF_TX_AC_BE, | 185 | .tsid = CONF_TX_AC_VO, |
202 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 186 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
203 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 187 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
204 | .apsd_conf = {0, 0}, | 188 | .apsd_conf = {0, 0}, |
205 | }, | 189 | }, |
206 | [6] = { | ||
207 | .queue_id = 6, | ||
208 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
209 | .tsid = CONF_TX_AC_BE, | ||
210 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
211 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
212 | .apsd_conf = {0, 0}, | ||
213 | } | ||
214 | }, | 190 | }, |
215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 191 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
216 | .tx_compl_timeout = 700, | 192 | .tx_compl_timeout = 700, |
@@ -238,7 +214,9 @@ static struct conf_drv_settings default_conf = { | |||
238 | .ps_poll_recovery_period = 700, | 214 | .ps_poll_recovery_period = 700, |
239 | .bet_enable = CONF_BET_MODE_ENABLE, | 215 | .bet_enable = CONF_BET_MODE_ENABLE, |
240 | .bet_max_consecutive = 10, | 216 | .bet_max_consecutive = 10, |
241 | .psm_entry_retries = 3, | 217 | .psm_entry_retries = 5, |
218 | .psm_entry_nullfunc_retries = 3, | ||
219 | .psm_entry_hangover_period = 1, | ||
242 | .keep_alive_interval = 55000, | 220 | .keep_alive_interval = 55000, |
243 | .max_listen_interval = 20, | 221 | .max_listen_interval = 20, |
244 | }, | 222 | }, |
@@ -251,15 +229,34 @@ static struct conf_drv_settings default_conf = { | |||
251 | .host_fast_wakeup_support = false | 229 | .host_fast_wakeup_support = false |
252 | }, | 230 | }, |
253 | .roam_trigger = { | 231 | .roam_trigger = { |
254 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
255 | .trigger_pacing = 1, | 232 | .trigger_pacing = 1, |
256 | .avg_weight_rssi_beacon = 20, | 233 | .avg_weight_rssi_beacon = 20, |
257 | .avg_weight_rssi_data = 10, | 234 | .avg_weight_rssi_data = 10, |
258 | .avg_weight_snr_beacon = 20, | 235 | .avg_weight_snr_beacon = 20, |
259 | .avg_weight_snr_data = 10 | 236 | .avg_weight_snr_data = 10 |
260 | } | 237 | }, |
238 | .scan = { | ||
239 | .min_dwell_time_active = 7500, | ||
240 | .max_dwell_time_active = 30000, | ||
241 | .min_dwell_time_passive = 30000, | ||
242 | .max_dwell_time_passive = 60000, | ||
243 | .num_probe_reqs = 2, | ||
244 | }, | ||
245 | .rf = { | ||
246 | .tx_per_channel_power_compensation_2 = { | ||
247 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
248 | }, | ||
249 | .tx_per_channel_power_compensation_5 = { | ||
250 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
253 | }, | ||
254 | }, | ||
261 | }; | 255 | }; |
262 | 256 | ||
257 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | ||
258 | |||
259 | |||
263 | static void wl1271_device_release(struct device *dev) | 260 | static void wl1271_device_release(struct device *dev) |
264 | { | 261 | { |
265 | 262 | ||
@@ -277,6 +274,67 @@ static struct platform_device wl1271_device = { | |||
277 | 274 | ||
278 | static LIST_HEAD(wl_list); | 275 | static LIST_HEAD(wl_list); |
279 | 276 | ||
277 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | ||
278 | void *arg) | ||
279 | { | ||
280 | struct net_device *dev = arg; | ||
281 | struct wireless_dev *wdev; | ||
282 | struct wiphy *wiphy; | ||
283 | struct ieee80211_hw *hw; | ||
284 | struct wl1271 *wl; | ||
285 | struct wl1271 *wl_temp; | ||
286 | int ret = 0; | ||
287 | |||
288 | /* Check that this notification is for us. */ | ||
289 | if (what != NETDEV_CHANGE) | ||
290 | return NOTIFY_DONE; | ||
291 | |||
292 | wdev = dev->ieee80211_ptr; | ||
293 | if (wdev == NULL) | ||
294 | return NOTIFY_DONE; | ||
295 | |||
296 | wiphy = wdev->wiphy; | ||
297 | if (wiphy == NULL) | ||
298 | return NOTIFY_DONE; | ||
299 | |||
300 | hw = wiphy_priv(wiphy); | ||
301 | if (hw == NULL) | ||
302 | return NOTIFY_DONE; | ||
303 | |||
304 | wl_temp = hw->priv; | ||
305 | list_for_each_entry(wl, &wl_list, list) { | ||
306 | if (wl == wl_temp) | ||
307 | break; | ||
308 | } | ||
309 | if (wl != wl_temp) | ||
310 | return NOTIFY_DONE; | ||
311 | |||
312 | mutex_lock(&wl->mutex); | ||
313 | |||
314 | if (wl->state == WL1271_STATE_OFF) | ||
315 | goto out; | ||
316 | |||
317 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
318 | goto out; | ||
319 | |||
320 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
321 | if (ret < 0) | ||
322 | goto out; | ||
323 | |||
324 | if ((dev->operstate == IF_OPER_UP) && | ||
325 | !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) { | ||
326 | wl1271_cmd_set_sta_state(wl); | ||
327 | wl1271_info("Association completed."); | ||
328 | } | ||
329 | |||
330 | wl1271_ps_elp_sleep(wl); | ||
331 | |||
332 | out: | ||
333 | mutex_unlock(&wl->mutex); | ||
334 | |||
335 | return NOTIFY_OK; | ||
336 | } | ||
337 | |||
280 | static void wl1271_conf_init(struct wl1271 *wl) | 338 | static void wl1271_conf_init(struct wl1271 *wl) |
281 | { | 339 | { |
282 | 340 | ||
@@ -309,6 +367,10 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
309 | if (ret < 0) | 367 | if (ret < 0) |
310 | return ret; | 368 | return ret; |
311 | 369 | ||
370 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
371 | if (ret < 0) | ||
372 | return ret; | ||
373 | |||
312 | ret = wl1271_init_templates_config(wl); | 374 | ret = wl1271_init_templates_config(wl); |
313 | if (ret < 0) | 375 | if (ret < 0) |
314 | return ret; | 376 | return ret; |
@@ -346,8 +408,16 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
346 | if (ret < 0) | 408 | if (ret < 0) |
347 | goto out_free_memmap; | 409 | goto out_free_memmap; |
348 | 410 | ||
349 | /* Default TID configuration */ | 411 | /* Default TID/AC configuration */ |
412 | BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); | ||
350 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 413 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
414 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
415 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
416 | conf_ac->cw_max, conf_ac->aifsn, | ||
417 | conf_ac->tx_op_limit); | ||
418 | if (ret < 0) | ||
419 | goto out_free_memmap; | ||
420 | |||
351 | conf_tid = &wl->conf.tx.tid_conf[i]; | 421 | conf_tid = &wl->conf.tx.tid_conf[i]; |
352 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | 422 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
353 | conf_tid->channel_type, | 423 | conf_tid->channel_type, |
@@ -360,16 +430,6 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
360 | goto out_free_memmap; | 430 | goto out_free_memmap; |
361 | } | 431 | } |
362 | 432 | ||
363 | /* Default AC configuration */ | ||
364 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
365 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
366 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
367 | conf_ac->cw_max, conf_ac->aifsn, | ||
368 | conf_ac->tx_op_limit); | ||
369 | if (ret < 0) | ||
370 | goto out_free_memmap; | ||
371 | } | ||
372 | |||
373 | /* Enable data path */ | 433 | /* Enable data path */ |
374 | ret = wl1271_cmd_data_path(wl, 1); | 434 | ret = wl1271_cmd_data_path(wl, 1); |
375 | if (ret < 0) | 435 | if (ret < 0) |
@@ -562,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
562 | return ret; | 622 | return ret; |
563 | } | 623 | } |
564 | 624 | ||
565 | /* | ||
566 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
567 | * configurations) can be removed when those NVS files stop floating | ||
568 | * around. | ||
569 | */ | ||
570 | if (fw->size != sizeof(struct wl1271_nvs_file) && | ||
571 | (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
572 | wl1271_11a_enabled())) { | ||
573 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
574 | fw->size, sizeof(struct wl1271_nvs_file)); | ||
575 | ret = -EILSEQ; | ||
576 | goto out; | ||
577 | } | ||
578 | |||
579 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 625 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
580 | 626 | ||
581 | if (!wl->nvs) { | 627 | if (!wl->nvs) { |
@@ -584,12 +630,37 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
584 | goto out; | 630 | goto out; |
585 | } | 631 | } |
586 | 632 | ||
633 | wl->nvs_len = fw->size; | ||
634 | |||
587 | out: | 635 | out: |
588 | release_firmware(fw); | 636 | release_firmware(fw); |
589 | 637 | ||
590 | return ret; | 638 | return ret; |
591 | } | 639 | } |
592 | 640 | ||
641 | static void wl1271_recovery_work(struct work_struct *work) | ||
642 | { | ||
643 | struct wl1271 *wl = | ||
644 | container_of(work, struct wl1271, recovery_work); | ||
645 | |||
646 | mutex_lock(&wl->mutex); | ||
647 | |||
648 | if (wl->state != WL1271_STATE_ON) | ||
649 | goto out; | ||
650 | |||
651 | wl1271_info("Hardware recovery in progress."); | ||
652 | |||
653 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
654 | ieee80211_connection_loss(wl->vif); | ||
655 | |||
656 | /* reboot the chipset */ | ||
657 | __wl1271_op_remove_interface(wl); | ||
658 | ieee80211_restart_hw(wl->hw); | ||
659 | |||
660 | out: | ||
661 | mutex_unlock(&wl->mutex); | ||
662 | } | ||
663 | |||
593 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 664 | static void wl1271_fw_wakeup(struct wl1271 *wl) |
594 | { | 665 | { |
595 | u32 elp_reg; | 666 | u32 elp_reg; |
@@ -610,8 +681,6 @@ static int wl1271_setup(struct wl1271 *wl) | |||
610 | return -ENOMEM; | 681 | return -ENOMEM; |
611 | } | 682 | } |
612 | 683 | ||
613 | INIT_WORK(&wl->irq_work, wl1271_irq_work); | ||
614 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | ||
615 | return 0; | 684 | return 0; |
616 | } | 685 | } |
617 | 686 | ||
@@ -768,10 +837,12 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
768 | out: | 837 | out: |
769 | mutex_unlock(&wl->mutex); | 838 | mutex_unlock(&wl->mutex); |
770 | 839 | ||
840 | cancel_work_sync(&wl->irq_work); | ||
841 | cancel_work_sync(&wl->recovery_work); | ||
842 | |||
771 | return ret; | 843 | return ret; |
772 | } | 844 | } |
773 | 845 | ||
774 | |||
775 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 846 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
776 | { | 847 | { |
777 | struct wl1271 *wl = hw->priv; | 848 | struct wl1271 *wl = hw->priv; |
@@ -814,6 +885,10 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
814 | return NETDEV_TX_OK; | 885 | return NETDEV_TX_OK; |
815 | } | 886 | } |
816 | 887 | ||
888 | static struct notifier_block wl1271_dev_notifier = { | ||
889 | .notifier_call = wl1271_dev_notify, | ||
890 | }; | ||
891 | |||
817 | static int wl1271_op_start(struct ieee80211_hw *hw) | 892 | static int wl1271_op_start(struct ieee80211_hw *hw) |
818 | { | 893 | { |
819 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 894 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -930,13 +1005,10 @@ out: | |||
930 | return ret; | 1005 | return ret; |
931 | } | 1006 | } |
932 | 1007 | ||
933 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1008 | static void __wl1271_op_remove_interface(struct wl1271 *wl) |
934 | struct ieee80211_vif *vif) | ||
935 | { | 1009 | { |
936 | struct wl1271 *wl = hw->priv; | ||
937 | int i; | 1010 | int i; |
938 | 1011 | ||
939 | mutex_lock(&wl->mutex); | ||
940 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 1012 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
941 | 1013 | ||
942 | wl1271_info("down"); | 1014 | wl1271_info("down"); |
@@ -950,10 +1022,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
950 | ieee80211_enable_dyn_ps(wl->vif); | 1022 | ieee80211_enable_dyn_ps(wl->vif); |
951 | 1023 | ||
952 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | 1024 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { |
953 | ieee80211_scan_completed(wl->hw, true); | ||
954 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 1025 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
955 | kfree(wl->scan.scanned_ch); | 1026 | kfree(wl->scan.scanned_ch); |
956 | wl->scan.scanned_ch = NULL; | 1027 | wl->scan.scanned_ch = NULL; |
1028 | ieee80211_scan_completed(wl->hw, true); | ||
957 | } | 1029 | } |
958 | 1030 | ||
959 | wl->state = WL1271_STATE_OFF; | 1031 | wl->state = WL1271_STATE_OFF; |
@@ -962,9 +1034,11 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
962 | 1034 | ||
963 | mutex_unlock(&wl->mutex); | 1035 | mutex_unlock(&wl->mutex); |
964 | 1036 | ||
1037 | cancel_delayed_work_sync(&wl->scan_complete_work); | ||
965 | cancel_work_sync(&wl->irq_work); | 1038 | cancel_work_sync(&wl->irq_work); |
966 | cancel_work_sync(&wl->tx_work); | 1039 | cancel_work_sync(&wl->tx_work); |
967 | cancel_delayed_work_sync(&wl->pspoll_work); | 1040 | cancel_delayed_work_sync(&wl->pspoll_work); |
1041 | cancel_delayed_work_sync(&wl->elp_work); | ||
968 | 1042 | ||
969 | mutex_lock(&wl->mutex); | 1043 | mutex_lock(&wl->mutex); |
970 | 1044 | ||
@@ -1006,8 +1080,19 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1006 | wl->tx_res_if = NULL; | 1080 | wl->tx_res_if = NULL; |
1007 | kfree(wl->target_mem_map); | 1081 | kfree(wl->target_mem_map); |
1008 | wl->target_mem_map = NULL; | 1082 | wl->target_mem_map = NULL; |
1083 | } | ||
1084 | |||
1085 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | ||
1086 | struct ieee80211_vif *vif) | ||
1087 | { | ||
1088 | struct wl1271 *wl = hw->priv; | ||
1009 | 1089 | ||
1090 | mutex_lock(&wl->mutex); | ||
1091 | WARN_ON(wl->vif != vif); | ||
1092 | __wl1271_op_remove_interface(wl); | ||
1010 | mutex_unlock(&wl->mutex); | 1093 | mutex_unlock(&wl->mutex); |
1094 | |||
1095 | cancel_work_sync(&wl->recovery_work); | ||
1011 | } | 1096 | } |
1012 | 1097 | ||
1013 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1098 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
@@ -1289,7 +1374,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1289 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1374 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1290 | wl1271_debug(DEBUG_PSM, "psm enabled"); | 1375 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1291 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1376 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1292 | true); | 1377 | wl->basic_rate, true); |
1293 | } | 1378 | } |
1294 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1379 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1295 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1380 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
@@ -1299,7 +1384,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1299 | 1384 | ||
1300 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) | 1385 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1301 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 1386 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
1302 | true); | 1387 | wl->basic_rate, true); |
1303 | } | 1388 | } |
1304 | 1389 | ||
1305 | if (conf->power_level != wl->power_level) { | 1390 | if (conf->power_level != wl->power_level) { |
@@ -1476,6 +1561,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1476 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 1561 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1477 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1562 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1478 | break; | 1563 | break; |
1564 | case WL1271_CIPHER_SUITE_GEM: | ||
1565 | key_type = KEY_GEM; | ||
1566 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | ||
1567 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | ||
1568 | break; | ||
1479 | default: | 1569 | default: |
1480 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); | 1570 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
1481 | 1571 | ||
@@ -1559,10 +1649,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1559 | if (ret < 0) | 1649 | if (ret < 0) |
1560 | goto out; | 1650 | goto out; |
1561 | 1651 | ||
1562 | if (wl1271_11a_enabled()) | 1652 | ret = wl1271_scan(hw->priv, ssid, len, req); |
1563 | ret = wl1271_scan(hw->priv, ssid, len, req); | ||
1564 | else | ||
1565 | ret = wl1271_scan(hw->priv, ssid, len, req); | ||
1566 | 1653 | ||
1567 | wl1271_ps_elp_sleep(wl); | 1654 | wl1271_ps_elp_sleep(wl); |
1568 | 1655 | ||
@@ -1777,12 +1864,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1777 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 1864 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1778 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 1865 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
1779 | mode = STATION_POWER_SAVE_MODE; | 1866 | mode = STATION_POWER_SAVE_MODE; |
1780 | ret = wl1271_ps_set_mode(wl, mode, true); | 1867 | ret = wl1271_ps_set_mode(wl, mode, |
1868 | wl->basic_rate, | ||
1869 | true); | ||
1781 | if (ret < 0) | 1870 | if (ret < 0) |
1782 | goto out_sleep; | 1871 | goto out_sleep; |
1783 | } | 1872 | } |
1784 | } else { | 1873 | } else { |
1785 | /* use defaults when not associated */ | 1874 | /* use defaults when not associated */ |
1875 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | ||
1786 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1876 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1787 | wl->aid = 0; | 1877 | wl->aid = 0; |
1788 | 1878 | ||
@@ -1994,21 +2084,24 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1994 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, | 2084 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, |
1995 | }; | 2085 | }; |
1996 | 2086 | ||
1997 | /* can't be const, mac80211 writes to this */ | 2087 | /* |
2088 | * Can't be const, mac80211 writes to this. The order of the channels here | ||
2089 | * is designed to improve scanning. | ||
2090 | */ | ||
1998 | static struct ieee80211_channel wl1271_channels[] = { | 2091 | static struct ieee80211_channel wl1271_channels[] = { |
1999 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, | 2092 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
2000 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, | ||
2001 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, | ||
2002 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, | ||
2003 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, | 2093 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
2004 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, | ||
2005 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, | ||
2006 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, | ||
2007 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, | 2094 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
2008 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, | ||
2009 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | ||
2010 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | ||
2011 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 2095 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
2096 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, | ||
2097 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, | ||
2098 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | ||
2099 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, | ||
2100 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, | ||
2101 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | ||
2102 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, | ||
2103 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, | ||
2104 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, | ||
2012 | }; | 2105 | }; |
2013 | 2106 | ||
2014 | /* mapping to indexes for wl1271_rates */ | 2107 | /* mapping to indexes for wl1271_rates */ |
@@ -2077,49 +2170,52 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
2077 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, | 2170 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, |
2078 | }; | 2171 | }; |
2079 | 2172 | ||
2080 | /* 5 GHz band channels for WL1273 */ | 2173 | /* |
2174 | * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this. | ||
2175 | * The order of the channels here is designed to improve scanning. | ||
2176 | */ | ||
2081 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 2177 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
2082 | { .hw_value = 183, .center_freq = 4915}, | 2178 | { .hw_value = 183, .center_freq = 4915}, |
2083 | { .hw_value = 184, .center_freq = 4920}, | ||
2084 | { .hw_value = 185, .center_freq = 4925}, | ||
2085 | { .hw_value = 187, .center_freq = 4935}, | ||
2086 | { .hw_value = 188, .center_freq = 4940}, | 2179 | { .hw_value = 188, .center_freq = 4940}, |
2087 | { .hw_value = 189, .center_freq = 4945}, | ||
2088 | { .hw_value = 192, .center_freq = 4960}, | ||
2089 | { .hw_value = 196, .center_freq = 4980}, | ||
2090 | { .hw_value = 7, .center_freq = 5035}, | ||
2091 | { .hw_value = 8, .center_freq = 5040}, | 2180 | { .hw_value = 8, .center_freq = 5040}, |
2092 | { .hw_value = 9, .center_freq = 5045}, | ||
2093 | { .hw_value = 11, .center_freq = 5055}, | ||
2094 | { .hw_value = 12, .center_freq = 5060}, | ||
2095 | { .hw_value = 16, .center_freq = 5080}, | ||
2096 | { .hw_value = 34, .center_freq = 5170}, | 2181 | { .hw_value = 34, .center_freq = 5170}, |
2097 | { .hw_value = 36, .center_freq = 5180}, | ||
2098 | { .hw_value = 38, .center_freq = 5190}, | ||
2099 | { .hw_value = 40, .center_freq = 5200}, | ||
2100 | { .hw_value = 42, .center_freq = 5210}, | ||
2101 | { .hw_value = 44, .center_freq = 5220}, | 2182 | { .hw_value = 44, .center_freq = 5220}, |
2102 | { .hw_value = 46, .center_freq = 5230}, | ||
2103 | { .hw_value = 48, .center_freq = 5240}, | ||
2104 | { .hw_value = 52, .center_freq = 5260}, | ||
2105 | { .hw_value = 56, .center_freq = 5280}, | ||
2106 | { .hw_value = 60, .center_freq = 5300}, | 2183 | { .hw_value = 60, .center_freq = 5300}, |
2107 | { .hw_value = 64, .center_freq = 5320}, | ||
2108 | { .hw_value = 100, .center_freq = 5500}, | ||
2109 | { .hw_value = 104, .center_freq = 5520}, | ||
2110 | { .hw_value = 108, .center_freq = 5540}, | ||
2111 | { .hw_value = 112, .center_freq = 5560}, | 2184 | { .hw_value = 112, .center_freq = 5560}, |
2112 | { .hw_value = 116, .center_freq = 5580}, | ||
2113 | { .hw_value = 120, .center_freq = 5600}, | ||
2114 | { .hw_value = 124, .center_freq = 5620}, | ||
2115 | { .hw_value = 128, .center_freq = 5640}, | ||
2116 | { .hw_value = 132, .center_freq = 5660}, | 2185 | { .hw_value = 132, .center_freq = 5660}, |
2186 | { .hw_value = 157, .center_freq = 5785}, | ||
2187 | { .hw_value = 184, .center_freq = 4920}, | ||
2188 | { .hw_value = 189, .center_freq = 4945}, | ||
2189 | { .hw_value = 9, .center_freq = 5045}, | ||
2190 | { .hw_value = 36, .center_freq = 5180}, | ||
2191 | { .hw_value = 46, .center_freq = 5230}, | ||
2192 | { .hw_value = 64, .center_freq = 5320}, | ||
2193 | { .hw_value = 116, .center_freq = 5580}, | ||
2117 | { .hw_value = 136, .center_freq = 5680}, | 2194 | { .hw_value = 136, .center_freq = 5680}, |
2195 | { .hw_value = 192, .center_freq = 4960}, | ||
2196 | { .hw_value = 11, .center_freq = 5055}, | ||
2197 | { .hw_value = 38, .center_freq = 5190}, | ||
2198 | { .hw_value = 48, .center_freq = 5240}, | ||
2199 | { .hw_value = 100, .center_freq = 5500}, | ||
2200 | { .hw_value = 120, .center_freq = 5600}, | ||
2118 | { .hw_value = 140, .center_freq = 5700}, | 2201 | { .hw_value = 140, .center_freq = 5700}, |
2202 | { .hw_value = 185, .center_freq = 4925}, | ||
2203 | { .hw_value = 196, .center_freq = 4980}, | ||
2204 | { .hw_value = 12, .center_freq = 5060}, | ||
2205 | { .hw_value = 40, .center_freq = 5200}, | ||
2206 | { .hw_value = 52, .center_freq = 5260}, | ||
2207 | { .hw_value = 104, .center_freq = 5520}, | ||
2208 | { .hw_value = 124, .center_freq = 5620}, | ||
2119 | { .hw_value = 149, .center_freq = 5745}, | 2209 | { .hw_value = 149, .center_freq = 5745}, |
2120 | { .hw_value = 153, .center_freq = 5765}, | ||
2121 | { .hw_value = 157, .center_freq = 5785}, | ||
2122 | { .hw_value = 161, .center_freq = 5805}, | 2210 | { .hw_value = 161, .center_freq = 5805}, |
2211 | { .hw_value = 187, .center_freq = 4935}, | ||
2212 | { .hw_value = 7, .center_freq = 5035}, | ||
2213 | { .hw_value = 16, .center_freq = 5080}, | ||
2214 | { .hw_value = 42, .center_freq = 5210}, | ||
2215 | { .hw_value = 56, .center_freq = 5280}, | ||
2216 | { .hw_value = 108, .center_freq = 5540}, | ||
2217 | { .hw_value = 128, .center_freq = 5640}, | ||
2218 | { .hw_value = 153, .center_freq = 5765}, | ||
2123 | { .hw_value = 165, .center_freq = 5825}, | 2219 | { .hw_value = 165, .center_freq = 5825}, |
2124 | }; | 2220 | }; |
2125 | 2221 | ||
@@ -2212,8 +2308,7 @@ static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | |||
2212 | struct wl1271 *wl = dev_get_drvdata(dev); | 2308 | struct wl1271 *wl = dev_get_drvdata(dev); |
2213 | ssize_t len; | 2309 | ssize_t len; |
2214 | 2310 | ||
2215 | /* FIXME: what's the maximum length of buf? page size?*/ | 2311 | len = PAGE_SIZE; |
2216 | len = 500; | ||
2217 | 2312 | ||
2218 | mutex_lock(&wl->mutex); | 2313 | mutex_lock(&wl->mutex); |
2219 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | 2314 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", |
@@ -2274,8 +2369,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, | |||
2274 | struct wl1271 *wl = dev_get_drvdata(dev); | 2369 | struct wl1271 *wl = dev_get_drvdata(dev); |
2275 | ssize_t len; | 2370 | ssize_t len; |
2276 | 2371 | ||
2277 | /* FIXME: what's the maximum length of buf? page size?*/ | 2372 | len = PAGE_SIZE; |
2278 | len = 500; | ||
2279 | 2373 | ||
2280 | mutex_lock(&wl->mutex); | 2374 | mutex_lock(&wl->mutex); |
2281 | if (wl->hw_pg_ver >= 0) | 2375 | if (wl->hw_pg_ver >= 0) |
@@ -2307,6 +2401,8 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
2307 | 2401 | ||
2308 | wl->mac80211_registered = true; | 2402 | wl->mac80211_registered = true; |
2309 | 2403 | ||
2404 | register_netdevice_notifier(&wl1271_dev_notifier); | ||
2405 | |||
2310 | wl1271_notice("loaded"); | 2406 | wl1271_notice("loaded"); |
2311 | 2407 | ||
2312 | return 0; | 2408 | return 0; |
@@ -2315,6 +2411,7 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw); | |||
2315 | 2411 | ||
2316 | void wl1271_unregister_hw(struct wl1271 *wl) | 2412 | void wl1271_unregister_hw(struct wl1271 *wl) |
2317 | { | 2413 | { |
2414 | unregister_netdevice_notifier(&wl1271_dev_notifier); | ||
2318 | ieee80211_unregister_hw(wl->hw); | 2415 | ieee80211_unregister_hw(wl->hw); |
2319 | wl->mac80211_registered = false; | 2416 | wl->mac80211_registered = false; |
2320 | 2417 | ||
@@ -2323,6 +2420,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | |||
2323 | 2420 | ||
2324 | int wl1271_init_ieee80211(struct wl1271 *wl) | 2421 | int wl1271_init_ieee80211(struct wl1271 *wl) |
2325 | { | 2422 | { |
2423 | static const u32 cipher_suites[] = { | ||
2424 | WLAN_CIPHER_SUITE_WEP40, | ||
2425 | WLAN_CIPHER_SUITE_WEP104, | ||
2426 | WLAN_CIPHER_SUITE_TKIP, | ||
2427 | WLAN_CIPHER_SUITE_CCMP, | ||
2428 | WL1271_CIPHER_SUITE_GEM, | ||
2429 | }; | ||
2430 | |||
2326 | /* The tx descriptor buffer and the TKIP space. */ | 2431 | /* The tx descriptor buffer and the TKIP space. */ |
2327 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2432 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
2328 | sizeof(struct wl1271_tx_hw_descr); | 2433 | sizeof(struct wl1271_tx_hw_descr); |
@@ -2340,13 +2445,14 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2340 | IEEE80211_HW_CONNECTION_MONITOR | | 2445 | IEEE80211_HW_CONNECTION_MONITOR | |
2341 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | 2446 | IEEE80211_HW_SUPPORTS_CQM_RSSI; |
2342 | 2447 | ||
2448 | wl->hw->wiphy->cipher_suites = cipher_suites; | ||
2449 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
2450 | |||
2343 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2451 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2344 | BIT(NL80211_IFTYPE_ADHOC); | 2452 | BIT(NL80211_IFTYPE_ADHOC); |
2345 | wl->hw->wiphy->max_scan_ssids = 1; | 2453 | wl->hw->wiphy->max_scan_ssids = 1; |
2346 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 2454 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
2347 | 2455 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | |
2348 | if (wl1271_11a_enabled()) | ||
2349 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | ||
2350 | 2456 | ||
2351 | wl->hw->queues = 4; | 2457 | wl->hw->queues = 4; |
2352 | wl->hw->max_rates = 1; | 2458 | wl->hw->max_rates = 1; |
@@ -2365,6 +2471,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2365 | struct platform_device *plat_dev = NULL; | 2471 | struct platform_device *plat_dev = NULL; |
2366 | struct wl1271 *wl; | 2472 | struct wl1271 *wl; |
2367 | int i, ret; | 2473 | int i, ret; |
2474 | unsigned int order; | ||
2368 | 2475 | ||
2369 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2476 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2370 | if (!hw) { | 2477 | if (!hw) { |
@@ -2392,6 +2499,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2392 | 2499 | ||
2393 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2500 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2394 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | 2501 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); |
2502 | INIT_WORK(&wl->irq_work, wl1271_irq_work); | ||
2503 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | ||
2504 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | ||
2505 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | ||
2395 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2506 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2396 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 2507 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
2397 | wl->default_key = 0; | 2508 | wl->default_key = 0; |
@@ -2423,11 +2534,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2423 | 2534 | ||
2424 | wl1271_debugfs_init(wl); | 2535 | wl1271_debugfs_init(wl); |
2425 | 2536 | ||
2537 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | ||
2538 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | ||
2539 | if (!wl->aggr_buf) { | ||
2540 | ret = -ENOMEM; | ||
2541 | goto err_hw; | ||
2542 | } | ||
2543 | |||
2426 | /* Register platform device */ | 2544 | /* Register platform device */ |
2427 | ret = platform_device_register(wl->plat_dev); | 2545 | ret = platform_device_register(wl->plat_dev); |
2428 | if (ret) { | 2546 | if (ret) { |
2429 | wl1271_error("couldn't register platform device"); | 2547 | wl1271_error("couldn't register platform device"); |
2430 | goto err_hw; | 2548 | goto err_aggr; |
2431 | } | 2549 | } |
2432 | dev_set_drvdata(&wl->plat_dev->dev, wl); | 2550 | dev_set_drvdata(&wl->plat_dev->dev, wl); |
2433 | 2551 | ||
@@ -2453,6 +2571,9 @@ err_bt_coex_state: | |||
2453 | err_platform: | 2571 | err_platform: |
2454 | platform_device_unregister(wl->plat_dev); | 2572 | platform_device_unregister(wl->plat_dev); |
2455 | 2573 | ||
2574 | err_aggr: | ||
2575 | free_pages((unsigned long)wl->aggr_buf, order); | ||
2576 | |||
2456 | err_hw: | 2577 | err_hw: |
2457 | wl1271_debugfs_exit(wl); | 2578 | wl1271_debugfs_exit(wl); |
2458 | kfree(plat_dev); | 2579 | kfree(plat_dev); |
@@ -2469,6 +2590,8 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | |||
2469 | int wl1271_free_hw(struct wl1271 *wl) | 2590 | int wl1271_free_hw(struct wl1271 *wl) |
2470 | { | 2591 | { |
2471 | platform_device_unregister(wl->plat_dev); | 2592 | platform_device_unregister(wl->plat_dev); |
2593 | free_pages((unsigned long)wl->aggr_buf, | ||
2594 | get_order(WL1271_AGGR_BUFFER_SIZE)); | ||
2472 | kfree(wl->plat_dev); | 2595 | kfree(wl->plat_dev); |
2473 | 2596 | ||
2474 | wl1271_debugfs_exit(wl); | 2597 | wl1271_debugfs_exit(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index a5e60e0403e5..e3c332e2f97c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 39 | ||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
43 | goto out; | ||
44 | |||
42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 45 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && | 46 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
44 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | 47 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) |
@@ -61,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
61 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | 64 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { |
62 | cancel_delayed_work(&wl->elp_work); | 65 | cancel_delayed_work(&wl->elp_work); |
63 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 66 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
64 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 67 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -96,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
96 | &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); | 99 | &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); |
97 | if (ret == 0) { | 100 | if (ret == 0) { |
98 | wl1271_error("ELP wakeup timeout!"); | 101 | wl1271_error("ELP wakeup timeout!"); |
102 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
99 | ret = -ETIMEDOUT; | 103 | ret = -ETIMEDOUT; |
100 | goto err; | 104 | goto err; |
101 | } else if (ret < 0) { | 105 | } else if (ret < 0) { |
@@ -121,7 +125,7 @@ out: | |||
121 | } | 125 | } |
122 | 126 | ||
123 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | 127 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
124 | bool send) | 128 | u32 rates, bool send) |
125 | { | 129 | { |
126 | int ret; | 130 | int ret; |
127 | 131 | ||
@@ -129,7 +133,14 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
129 | case STATION_POWER_SAVE_MODE: | 133 | case STATION_POWER_SAVE_MODE: |
130 | wl1271_debug(DEBUG_PSM, "entering psm"); | 134 | wl1271_debug(DEBUG_PSM, "entering psm"); |
131 | 135 | ||
132 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send); | 136 | ret = wl1271_acx_wake_up_conditions(wl); |
137 | if (ret < 0) { | ||
138 | wl1271_error("couldn't set wake up conditions"); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, | ||
143 | rates, send); | ||
133 | if (ret < 0) | 144 | if (ret < 0) |
134 | return ret; | 145 | return ret; |
135 | 146 | ||
@@ -152,7 +163,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
152 | if (ret < 0) | 163 | if (ret < 0) |
153 | return ret; | 164 | return ret; |
154 | 165 | ||
155 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send); | 166 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, |
167 | rates, send); | ||
156 | if (ret < 0) | 168 | if (ret < 0) |
157 | return ret; | 169 | return ret; |
158 | 170 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index 940276f517a4..6ba7b032736f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
31 | bool send); | 31 | u32 rates, bool send); |
32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); |
34 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 94da5dd7723c..bea133b6e489 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -74,7 +74,7 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | 77 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) |
78 | { | 78 | { |
79 | struct wl1271_rx_descriptor *desc; | 79 | struct wl1271_rx_descriptor *desc; |
80 | struct sk_buff *skb; | 80 | struct sk_buff *skb; |
@@ -87,16 +87,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
87 | * workaround this by not retrieving them at all. | 87 | * workaround this by not retrieving them at all. |
88 | */ | 88 | */ |
89 | if (unlikely(wl->state == WL1271_STATE_PLT)) | 89 | if (unlikely(wl->state == WL1271_STATE_PLT)) |
90 | return; | 90 | return -EINVAL; |
91 | 91 | ||
92 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 92 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
93 | if (!skb) { | 93 | if (!skb) { |
94 | wl1271_error("Couldn't allocate RX frame"); | 94 | wl1271_error("Couldn't allocate RX frame"); |
95 | return; | 95 | return -ENOMEM; |
96 | } | 96 | } |
97 | 97 | ||
98 | buf = skb_put(skb, length); | 98 | buf = skb_put(skb, length); |
99 | wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); | 99 | memcpy(buf, data, length); |
100 | 100 | ||
101 | /* the data read starts with the descriptor */ | 101 | /* the data read starts with the descriptor */ |
102 | desc = (struct wl1271_rx_descriptor *) buf; | 102 | desc = (struct wl1271_rx_descriptor *) buf; |
@@ -116,6 +116,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
116 | skb_trim(skb, skb->len - desc->pad_len); | 116 | skb_trim(skb, skb->len - desc->pad_len); |
117 | 117 | ||
118 | ieee80211_rx_ni(wl->hw, skb); | 118 | ieee80211_rx_ni(wl->hw, skb); |
119 | |||
120 | return 0; | ||
119 | } | 121 | } |
120 | 122 | ||
121 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | 123 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) |
@@ -124,31 +126,60 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
124 | u32 buf_size; | 126 | u32 buf_size; |
125 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 127 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
126 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 128 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
129 | u32 rx_counter; | ||
127 | u32 mem_block; | 130 | u32 mem_block; |
131 | u32 pkt_length; | ||
132 | u32 pkt_offset; | ||
128 | 133 | ||
129 | while (drv_rx_counter != fw_rx_counter) { | 134 | while (drv_rx_counter != fw_rx_counter) { |
130 | mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); | 135 | buf_size = 0; |
131 | buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter); | 136 | rx_counter = drv_rx_counter; |
137 | while (rx_counter != fw_rx_counter) { | ||
138 | pkt_length = wl1271_rx_get_buf_size(status, rx_counter); | ||
139 | if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) | ||
140 | break; | ||
141 | buf_size += pkt_length; | ||
142 | rx_counter++; | ||
143 | rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | ||
144 | } | ||
132 | 145 | ||
133 | if (buf_size == 0) { | 146 | if (buf_size == 0) { |
134 | wl1271_warning("received empty data"); | 147 | wl1271_warning("received empty data"); |
135 | break; | 148 | break; |
136 | } | 149 | } |
137 | 150 | ||
151 | /* | ||
152 | * Choose the block we want to read | ||
153 | * For aggregated packets, only the first memory block should | ||
154 | * be retrieved. The FW takes care of the rest. | ||
155 | */ | ||
156 | mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); | ||
138 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + | 157 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + |
139 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); | 158 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); |
140 | wl->rx_mem_pool_addr.addr_extra = | 159 | wl->rx_mem_pool_addr.addr_extra = |
141 | wl->rx_mem_pool_addr.addr + 4; | 160 | wl->rx_mem_pool_addr.addr + 4; |
142 | |||
143 | /* Choose the block we want to read */ | ||
144 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, | 161 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, |
145 | sizeof(wl->rx_mem_pool_addr), false); | 162 | sizeof(wl->rx_mem_pool_addr), false); |
146 | 163 | ||
147 | wl1271_rx_handle_data(wl, buf_size); | 164 | /* Read all available packets at once */ |
148 | 165 | wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | |
149 | wl->rx_counter++; | 166 | buf_size, true); |
150 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 167 | |
168 | /* Split data into separate packets */ | ||
169 | pkt_offset = 0; | ||
170 | while (pkt_offset < buf_size) { | ||
171 | pkt_length = wl1271_rx_get_buf_size(status, | ||
172 | drv_rx_counter); | ||
173 | if (wl1271_rx_handle_data(wl, | ||
174 | wl->aggr_buf + pkt_offset, | ||
175 | pkt_length) < 0) | ||
176 | break; | ||
177 | wl->rx_counter++; | ||
178 | drv_rx_counter++; | ||
179 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | ||
180 | pkt_offset += pkt_length; | ||
181 | } | ||
151 | } | 182 | } |
152 | 183 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, | |
153 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 184 | cpu_to_le32(wl->rx_counter)); |
154 | } | 185 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c index e4950c8e396e..909bb47995b6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c | |||
@@ -28,11 +28,43 @@ | |||
28 | #include "wl1271_scan.h" | 28 | #include "wl1271_scan.h" |
29 | #include "wl1271_acx.h" | 29 | #include "wl1271_acx.h" |
30 | 30 | ||
31 | void wl1271_scan_complete_work(struct work_struct *work) | ||
32 | { | ||
33 | struct delayed_work *dwork; | ||
34 | struct wl1271 *wl; | ||
35 | |||
36 | dwork = container_of(work, struct delayed_work, work); | ||
37 | wl = container_of(dwork, struct wl1271, scan_complete_work); | ||
38 | |||
39 | wl1271_debug(DEBUG_SCAN, "Scanning complete"); | ||
40 | |||
41 | mutex_lock(&wl->mutex); | ||
42 | |||
43 | if (wl->scan.state == WL1271_SCAN_STATE_IDLE) { | ||
44 | mutex_unlock(&wl->mutex); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
49 | kfree(wl->scan.scanned_ch); | ||
50 | wl->scan.scanned_ch = NULL; | ||
51 | mutex_unlock(&wl->mutex); | ||
52 | |||
53 | ieee80211_scan_completed(wl->hw, false); | ||
54 | |||
55 | if (wl->scan.failed) { | ||
56 | wl1271_info("Scan completed due to error."); | ||
57 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | |||
31 | static int wl1271_get_scan_channels(struct wl1271 *wl, | 62 | static int wl1271_get_scan_channels(struct wl1271 *wl, |
32 | struct cfg80211_scan_request *req, | 63 | struct cfg80211_scan_request *req, |
33 | struct basic_scan_channel_params *channels, | 64 | struct basic_scan_channel_params *channels, |
34 | enum ieee80211_band band, bool passive) | 65 | enum ieee80211_band band, bool passive) |
35 | { | 66 | { |
67 | struct conf_scan_settings *c = &wl->conf.scan; | ||
36 | int i, j; | 68 | int i, j; |
37 | u32 flags; | 69 | u32 flags; |
38 | 70 | ||
@@ -60,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, | |||
60 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", | 92 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", |
61 | req->channels[i]->beacon_found); | 93 | req->channels[i]->beacon_found); |
62 | 94 | ||
63 | channels[j].min_duration = | 95 | if (!passive) { |
64 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | 96 | channels[j].min_duration = |
65 | channels[j].max_duration = | 97 | cpu_to_le32(c->min_dwell_time_active); |
66 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | 98 | channels[j].max_duration = |
99 | cpu_to_le32(c->max_dwell_time_active); | ||
100 | } else { | ||
101 | channels[j].min_duration = | ||
102 | cpu_to_le32(c->min_dwell_time_passive); | ||
103 | channels[j].max_duration = | ||
104 | cpu_to_le32(c->max_dwell_time_passive); | ||
105 | } | ||
67 | channels[j].early_termination = 0; | 106 | channels[j].early_termination = 0; |
68 | channels[j].tx_power_att = req->channels[i]->max_power; | 107 | channels[j].tx_power_att = req->channels[i]->max_power; |
69 | channels[j].channel = req->channels[i]->hw_value; | 108 | channels[j].channel = req->channels[i]->hw_value; |
@@ -100,8 +139,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
100 | 139 | ||
101 | /* We always use high priority scans */ | 140 | /* We always use high priority scans */ |
102 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; | 141 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; |
103 | if(passive) | 142 | |
143 | /* No SSIDs means that we have a forced passive scan */ | ||
144 | if (passive || wl->scan.req->n_ssids == 0) | ||
104 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | 145 | scan_options |= WL1271_SCAN_OPT_PASSIVE; |
146 | |||
105 | cmd->params.scan_options = cpu_to_le16(scan_options); | 147 | cmd->params.scan_options = cpu_to_le16(scan_options); |
106 | 148 | ||
107 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | 149 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, |
@@ -117,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
117 | cmd->params.rx_filter_options = | 159 | cmd->params.rx_filter_options = |
118 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | 160 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); |
119 | 161 | ||
120 | cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS; | 162 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; |
121 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | 163 | cmd->params.tx_rate = cpu_to_le32(basic_rate); |
122 | cmd->params.tid_trigger = 0; | 164 | cmd->params.tid_trigger = 0; |
123 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 165 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
@@ -165,7 +207,7 @@ out: | |||
165 | 207 | ||
166 | void wl1271_scan_stm(struct wl1271 *wl) | 208 | void wl1271_scan_stm(struct wl1271 *wl) |
167 | { | 209 | { |
168 | int ret; | 210 | int ret = 0; |
169 | 211 | ||
170 | switch (wl->scan.state) { | 212 | switch (wl->scan.state) { |
171 | case WL1271_SCAN_STATE_IDLE: | 213 | case WL1271_SCAN_STATE_IDLE: |
@@ -185,7 +227,7 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
185 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, | 227 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, |
186 | wl->conf.tx.basic_rate); | 228 | wl->conf.tx.basic_rate); |
187 | if (ret == WL1271_NOTHING_TO_SCAN) { | 229 | if (ret == WL1271_NOTHING_TO_SCAN) { |
188 | if (wl1271_11a_enabled()) | 230 | if (wl->enable_11a) |
189 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | 231 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; |
190 | else | 232 | else |
191 | wl->scan.state = WL1271_SCAN_STATE_DONE; | 233 | wl->scan.state = WL1271_SCAN_STATE_DONE; |
@@ -215,18 +257,22 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
215 | break; | 257 | break; |
216 | 258 | ||
217 | case WL1271_SCAN_STATE_DONE: | 259 | case WL1271_SCAN_STATE_DONE: |
218 | ieee80211_scan_completed(wl->hw, false); | 260 | wl->scan.failed = false; |
219 | 261 | cancel_delayed_work(&wl->scan_complete_work); | |
220 | kfree(wl->scan.scanned_ch); | 262 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, |
221 | wl->scan.scanned_ch = NULL; | 263 | msecs_to_jiffies(0)); |
222 | |||
223 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
224 | break; | 264 | break; |
225 | 265 | ||
226 | default: | 266 | default: |
227 | wl1271_error("invalid scan state"); | 267 | wl1271_error("invalid scan state"); |
228 | break; | 268 | break; |
229 | } | 269 | } |
270 | |||
271 | if (ret < 0) { | ||
272 | cancel_delayed_work(&wl->scan_complete_work); | ||
273 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
274 | msecs_to_jiffies(0)); | ||
275 | } | ||
230 | } | 276 | } |
231 | 277 | ||
232 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 278 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
@@ -249,6 +295,11 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
249 | wl->scan.scanned_ch = kcalloc(req->n_channels, | 295 | wl->scan.scanned_ch = kcalloc(req->n_channels, |
250 | sizeof(*wl->scan.scanned_ch), | 296 | sizeof(*wl->scan.scanned_ch), |
251 | GFP_KERNEL); | 297 | GFP_KERNEL); |
298 | /* we assume failure so that timeout scenarios are handled correctly */ | ||
299 | wl->scan.failed = true; | ||
300 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
301 | msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); | ||
302 | |||
252 | wl1271_scan_stm(wl); | 303 | wl1271_scan_stm(wl); |
253 | 304 | ||
254 | return 0; | 305 | return 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h index f1815700f5f9..6d57127b5e6b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.h +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h | |||
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, | |||
32 | const u8 *ssid, size_t ssid_len, | 32 | const u8 *ssid, size_t ssid_len, |
33 | const u8 *ie, size_t ie_len, u8 band); | 33 | const u8 *ie, size_t ie_len, u8 band); |
34 | void wl1271_scan_stm(struct wl1271 *wl); | 34 | void wl1271_scan_stm(struct wl1271 *wl); |
35 | void wl1271_scan_complete_work(struct work_struct *work); | ||
35 | 36 | ||
36 | #define WL1271_SCAN_MAX_CHANNELS 24 | 37 | #define WL1271_SCAN_MAX_CHANNELS 24 |
37 | #define WL1271_SCAN_DEFAULT_TAG 1 | 38 | #define WL1271_SCAN_DEFAULT_TAG 1 |
@@ -39,11 +40,10 @@ void wl1271_scan_stm(struct wl1271 *wl); | |||
39 | #define WL1271_SCAN_OPT_ACTIVE 0 | 40 | #define WL1271_SCAN_OPT_ACTIVE 0 |
40 | #define WL1271_SCAN_OPT_PASSIVE 1 | 41 | #define WL1271_SCAN_OPT_PASSIVE 1 |
41 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | 42 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 |
42 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | ||
43 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | ||
44 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | 43 | #define WL1271_SCAN_BAND_2_4_GHZ 0 |
45 | #define WL1271_SCAN_BAND_5_GHZ 1 | 44 | #define WL1271_SCAN_BAND_5_GHZ 1 |
46 | #define WL1271_SCAN_PROBE_REQS 3 | 45 | |
46 | #define WL1271_SCAN_TIMEOUT 10000 /* msec */ | ||
47 | 47 | ||
48 | enum { | 48 | enum { |
49 | WL1271_SCAN_STATE_IDLE, | 49 | WL1271_SCAN_STATE_IDLE, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index f2f04663627c..4c250d7dc3fa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -274,9 +274,8 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
274 | { | 274 | { |
275 | struct wl1271 *wl = sdio_get_drvdata(func); | 275 | struct wl1271 *wl = sdio_get_drvdata(func); |
276 | 276 | ||
277 | free_irq(wl->irq, wl); | ||
278 | |||
279 | wl1271_unregister_hw(wl); | 277 | wl1271_unregister_hw(wl); |
278 | free_irq(wl->irq, wl); | ||
280 | wl1271_free_hw(wl); | 279 | wl1271_free_hw(wl); |
281 | } | 280 | } |
282 | 281 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index ced0a9e2c7e1..ef801680773f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -63,6 +63,11 @@ | |||
63 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | 63 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) |
64 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | 64 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 |
65 | 65 | ||
66 | /* HW limitation: maximum possible chunk size is 4095 bytes */ | ||
67 | #define WSPI_MAX_CHUNK_SIZE 4092 | ||
68 | |||
69 | #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) | ||
70 | |||
66 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) | 71 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) |
67 | { | 72 | { |
68 | return wl->if_priv; | 73 | return wl->if_priv; |
@@ -202,90 +207,117 @@ static int wl1271_spi_read_busy(struct wl1271 *wl) | |||
202 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 207 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
203 | size_t len, bool fixed) | 208 | size_t len, bool fixed) |
204 | { | 209 | { |
205 | struct spi_transfer t[3]; | 210 | struct spi_transfer t[2]; |
206 | struct spi_message m; | 211 | struct spi_message m; |
207 | u32 *busy_buf; | 212 | u32 *busy_buf; |
208 | u32 *cmd; | 213 | u32 *cmd; |
214 | u32 chunk_len; | ||
209 | 215 | ||
210 | cmd = &wl->buffer_cmd; | 216 | while (len > 0) { |
211 | busy_buf = wl->buffer_busyword; | 217 | chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len); |
212 | 218 | ||
213 | *cmd = 0; | 219 | cmd = &wl->buffer_cmd; |
214 | *cmd |= WSPI_CMD_READ; | 220 | busy_buf = wl->buffer_busyword; |
215 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
216 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
217 | 221 | ||
218 | if (fixed) | 222 | *cmd = 0; |
219 | *cmd |= WSPI_CMD_FIXED; | 223 | *cmd |= WSPI_CMD_READ; |
224 | *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & | ||
225 | WSPI_CMD_BYTE_LENGTH; | ||
226 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
220 | 227 | ||
221 | spi_message_init(&m); | 228 | if (fixed) |
222 | memset(t, 0, sizeof(t)); | 229 | *cmd |= WSPI_CMD_FIXED; |
223 | 230 | ||
224 | t[0].tx_buf = cmd; | 231 | spi_message_init(&m); |
225 | t[0].len = 4; | 232 | memset(t, 0, sizeof(t)); |
226 | t[0].cs_change = true; | ||
227 | spi_message_add_tail(&t[0], &m); | ||
228 | 233 | ||
229 | /* Busy and non busy words read */ | 234 | t[0].tx_buf = cmd; |
230 | t[1].rx_buf = busy_buf; | 235 | t[0].len = 4; |
231 | t[1].len = WL1271_BUSY_WORD_LEN; | 236 | t[0].cs_change = true; |
232 | t[1].cs_change = true; | 237 | spi_message_add_tail(&t[0], &m); |
233 | spi_message_add_tail(&t[1], &m); | ||
234 | 238 | ||
235 | spi_sync(wl_to_spi(wl), &m); | 239 | /* Busy and non busy words read */ |
240 | t[1].rx_buf = busy_buf; | ||
241 | t[1].len = WL1271_BUSY_WORD_LEN; | ||
242 | t[1].cs_change = true; | ||
243 | spi_message_add_tail(&t[1], &m); | ||
236 | 244 | ||
237 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && | 245 | spi_sync(wl_to_spi(wl), &m); |
238 | wl1271_spi_read_busy(wl)) { | ||
239 | memset(buf, 0, len); | ||
240 | return; | ||
241 | } | ||
242 | 246 | ||
243 | spi_message_init(&m); | 247 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
244 | memset(t, 0, sizeof(t)); | 248 | wl1271_spi_read_busy(wl)) { |
249 | memset(buf, 0, chunk_len); | ||
250 | return; | ||
251 | } | ||
245 | 252 | ||
246 | t[0].rx_buf = buf; | 253 | spi_message_init(&m); |
247 | t[0].len = len; | 254 | memset(t, 0, sizeof(t)); |
248 | t[0].cs_change = true; | ||
249 | spi_message_add_tail(&t[0], &m); | ||
250 | 255 | ||
251 | spi_sync(wl_to_spi(wl), &m); | 256 | t[0].rx_buf = buf; |
257 | t[0].len = chunk_len; | ||
258 | t[0].cs_change = true; | ||
259 | spi_message_add_tail(&t[0], &m); | ||
260 | |||
261 | spi_sync(wl_to_spi(wl), &m); | ||
262 | |||
263 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | ||
264 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len); | ||
252 | 265 | ||
253 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 266 | if (!fixed) |
254 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 267 | addr += chunk_len; |
268 | buf += chunk_len; | ||
269 | len -= chunk_len; | ||
270 | } | ||
255 | } | 271 | } |
256 | 272 | ||
257 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | 273 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
258 | size_t len, bool fixed) | 274 | size_t len, bool fixed) |
259 | { | 275 | { |
260 | struct spi_transfer t[2]; | 276 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; |
261 | struct spi_message m; | 277 | struct spi_message m; |
278 | u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; | ||
262 | u32 *cmd; | 279 | u32 *cmd; |
280 | u32 chunk_len; | ||
281 | int i; | ||
263 | 282 | ||
264 | cmd = &wl->buffer_cmd; | 283 | WARN_ON(len > WL1271_AGGR_BUFFER_SIZE); |
265 | |||
266 | *cmd = 0; | ||
267 | *cmd |= WSPI_CMD_WRITE; | ||
268 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
269 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
270 | |||
271 | if (fixed) | ||
272 | *cmd |= WSPI_CMD_FIXED; | ||
273 | 284 | ||
274 | spi_message_init(&m); | 285 | spi_message_init(&m); |
275 | memset(t, 0, sizeof(t)); | 286 | memset(t, 0, sizeof(t)); |
276 | 287 | ||
277 | t[0].tx_buf = cmd; | 288 | cmd = &commands[0]; |
278 | t[0].len = sizeof(*cmd); | 289 | i = 0; |
279 | spi_message_add_tail(&t[0], &m); | 290 | while (len > 0) { |
291 | chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len); | ||
280 | 292 | ||
281 | t[1].tx_buf = buf; | 293 | *cmd = 0; |
282 | t[1].len = len; | 294 | *cmd |= WSPI_CMD_WRITE; |
283 | spi_message_add_tail(&t[1], &m); | 295 | *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & |
296 | WSPI_CMD_BYTE_LENGTH; | ||
297 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
284 | 298 | ||
285 | spi_sync(wl_to_spi(wl), &m); | 299 | if (fixed) |
300 | *cmd |= WSPI_CMD_FIXED; | ||
286 | 301 | ||
287 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 302 | t[i].tx_buf = cmd; |
288 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 303 | t[i].len = sizeof(*cmd); |
304 | spi_message_add_tail(&t[i++], &m); | ||
305 | |||
306 | t[i].tx_buf = buf; | ||
307 | t[i].len = chunk_len; | ||
308 | spi_message_add_tail(&t[i++], &m); | ||
309 | |||
310 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | ||
311 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len); | ||
312 | |||
313 | if (!fixed) | ||
314 | addr += chunk_len; | ||
315 | buf += chunk_len; | ||
316 | len -= chunk_len; | ||
317 | cmd++; | ||
318 | } | ||
319 | |||
320 | spi_sync(wl_to_spi(wl), &m); | ||
289 | } | 321 | } |
290 | 322 | ||
291 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 323 | static irqreturn_t wl1271_irq(int irq, void *cookie) |
@@ -416,9 +448,8 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
416 | { | 448 | { |
417 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | 449 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); |
418 | 450 | ||
419 | free_irq(wl->irq, wl); | ||
420 | |||
421 | wl1271_unregister_hw(wl); | 451 | wl1271_unregister_hw(wl); |
452 | free_irq(wl->irq, wl); | ||
422 | wl1271_free_hw(wl); | 453 | wl1271_free_hw(wl); |
423 | 454 | ||
424 | return 0; | 455 | return 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 6e0952f79e9a..a3aa84386c88 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | 199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); |
200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); | 200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); |
201 | 201 | ||
202 | /* | ||
203 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
204 | * configurations) can be removed when those NVS files stop floating | ||
205 | * around. | ||
206 | */ | ||
207 | if (len != sizeof(struct wl1271_nvs_file) && | ||
208 | (len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
209 | wl1271_11a_enabled())) { | ||
210 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
211 | len, sizeof(struct wl1271_nvs_file)); | ||
212 | return -EMSGSIZE; | ||
213 | } | ||
214 | |||
215 | mutex_lock(&wl->mutex); | 202 | mutex_lock(&wl->mutex); |
216 | 203 | ||
217 | kfree(wl->nvs); | 204 | kfree(wl->nvs); |
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
224 | } | 211 | } |
225 | 212 | ||
226 | memcpy(wl->nvs, buf, len); | 213 | memcpy(wl->nvs, buf, len); |
214 | wl->nvs_len = len; | ||
227 | 215 | ||
228 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); | 216 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); |
229 | 217 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index dc0b46c93c4b..e3dc13c4d01a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -43,13 +43,17 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
43 | return -EBUSY; | 43 | return -EBUSY; |
44 | } | 44 | } |
45 | 45 | ||
46 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | 46 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, |
47 | u32 buf_offset) | ||
47 | { | 48 | { |
48 | struct wl1271_tx_hw_descr *desc; | 49 | struct wl1271_tx_hw_descr *desc; |
49 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 50 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
50 | u32 total_blocks; | 51 | u32 total_blocks; |
51 | int id, ret = -EBUSY; | 52 | int id, ret = -EBUSY; |
52 | 53 | ||
54 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) | ||
55 | return -EBUSY; | ||
56 | |||
53 | /* allocate free identifier for the packet */ | 57 | /* allocate free identifier for the packet */ |
54 | id = wl1271_tx_id(wl, skb); | 58 | id = wl1271_tx_id(wl, skb); |
55 | if (id < 0) | 59 | if (id < 0) |
@@ -82,7 +86,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
82 | return ret; | 86 | return ret; |
83 | } | 87 | } |
84 | 88 | ||
85 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 89 | static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, |
86 | u32 extra, struct ieee80211_tx_info *control) | 90 | u32 extra, struct ieee80211_tx_info *control) |
87 | { | 91 | { |
88 | struct timespec ts; | 92 | struct timespec ts; |
@@ -110,9 +114,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
110 | /* configure the tx attributes */ | 114 | /* configure the tx attributes */ |
111 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 115 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
112 | 116 | ||
113 | /* queue */ | 117 | /* queue (we use same identifiers for tid's and ac's */ |
114 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 118 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
115 | desc->tid = wl1271_tx_ac_to_tid(ac); | 119 | desc->tid = ac; |
116 | 120 | ||
117 | desc->aid = TX_HW_DEFAULT_AID; | 121 | desc->aid = TX_HW_DEFAULT_AID; |
118 | desc->reserved = 0; | 122 | desc->reserved = 0; |
@@ -133,59 +137,17 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
133 | desc->tx_attr = cpu_to_le16(tx_attr); | 137 | desc->tx_attr = cpu_to_le16(tx_attr); |
134 | 138 | ||
135 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 139 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | ||
140 | struct ieee80211_tx_info *control) | ||
141 | { | ||
142 | |||
143 | struct wl1271_tx_hw_descr *desc; | ||
144 | int len; | ||
145 | |||
146 | /* FIXME: This is a workaround for getting non-aligned packets. | ||
147 | This happens at least with EAPOL packets from the user space. | ||
148 | Our DMA requires packets to be aligned on a 4-byte boundary. | ||
149 | */ | ||
150 | if (unlikely((long)skb->data & 0x03)) { | ||
151 | int offset = (4 - (long)skb->data) & 0x03; | ||
152 | wl1271_debug(DEBUG_TX, "skb offset %d", offset); | ||
153 | |||
154 | /* check whether the current skb can be used */ | ||
155 | if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { | ||
156 | unsigned char *src = skb->data; | ||
157 | |||
158 | /* align the buffer on a 4-byte boundary */ | ||
159 | skb_reserve(skb, offset); | ||
160 | memmove(skb->data, src, skb->len); | ||
161 | } else { | ||
162 | wl1271_info("No handler, fixme!"); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | len = WL1271_TX_ALIGN(skb->len); | ||
168 | |||
169 | /* perform a fixed address block write with the packet */ | ||
170 | wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); | ||
171 | |||
172 | /* write packet new counter into the write access register */ | ||
173 | wl->tx_packets_count++; | ||
174 | |||
175 | desc = (struct wl1271_tx_hw_descr *) skb->data; | ||
176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | ||
177 | desc->id, skb, len, desc->length); | ||
178 | |||
179 | return 0; | ||
180 | } | 140 | } |
181 | 141 | ||
182 | /* caller must hold wl->mutex */ | 142 | /* caller must hold wl->mutex */ |
183 | static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | 143 | static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, |
144 | u32 buf_offset) | ||
184 | { | 145 | { |
185 | struct ieee80211_tx_info *info; | 146 | struct ieee80211_tx_info *info; |
186 | u32 extra = 0; | 147 | u32 extra = 0; |
187 | int ret = 0; | 148 | int ret = 0; |
188 | u8 idx; | 149 | u8 idx; |
150 | u32 total_len; | ||
189 | 151 | ||
190 | if (!skb) | 152 | if (!skb) |
191 | return -EINVAL; | 153 | return -EINVAL; |
@@ -208,19 +170,22 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
208 | } | 170 | } |
209 | } | 171 | } |
210 | 172 | ||
211 | ret = wl1271_tx_allocate(wl, skb, extra); | 173 | ret = wl1271_tx_allocate(wl, skb, extra, buf_offset); |
212 | if (ret < 0) | 174 | if (ret < 0) |
213 | return ret; | 175 | return ret; |
214 | 176 | ||
215 | ret = wl1271_tx_fill_hdr(wl, skb, extra, info); | 177 | wl1271_tx_fill_hdr(wl, skb, extra, info); |
216 | if (ret < 0) | ||
217 | return ret; | ||
218 | 178 | ||
219 | ret = wl1271_tx_send_packet(wl, skb, info); | 179 | /* |
220 | if (ret < 0) | 180 | * The length of each packet is stored in terms of words. Thus, we must |
221 | return ret; | 181 | * pad the skb data to make sure its length is aligned. |
182 | * The number of padding bytes is computed and set in wl1271_tx_fill_hdr | ||
183 | */ | ||
184 | total_len = WL1271_TX_ALIGN(skb->len); | ||
185 | memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); | ||
186 | memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); | ||
222 | 187 | ||
223 | return ret; | 188 | return total_len; |
224 | } | 189 | } |
225 | 190 | ||
226 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
@@ -245,7 +210,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
245 | struct sk_buff *skb; | 210 | struct sk_buff *skb; |
246 | bool woken_up = false; | 211 | bool woken_up = false; |
247 | u32 sta_rates = 0; | 212 | u32 sta_rates = 0; |
248 | u32 prev_tx_packets_count; | 213 | u32 buf_offset; |
249 | int ret; | 214 | int ret; |
250 | 215 | ||
251 | /* check if the rates supported by the AP have changed */ | 216 | /* check if the rates supported by the AP have changed */ |
@@ -262,14 +227,15 @@ void wl1271_tx_work(struct work_struct *work) | |||
262 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 227 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
263 | goto out; | 228 | goto out; |
264 | 229 | ||
265 | prev_tx_packets_count = wl->tx_packets_count; | ||
266 | |||
267 | /* if rates have changed, re-configure the rate policy */ | 230 | /* if rates have changed, re-configure the rate policy */ |
268 | if (unlikely(sta_rates)) { | 231 | if (unlikely(sta_rates)) { |
269 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | 232 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); |
270 | wl1271_acx_rate_policies(wl); | 233 | wl1271_acx_rate_policies(wl); |
271 | } | 234 | } |
272 | 235 | ||
236 | /* Prepare the transfer buffer, by aggregating all | ||
237 | * available packets */ | ||
238 | buf_offset = 0; | ||
273 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 239 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
274 | if (!woken_up) { | 240 | if (!woken_up) { |
275 | ret = wl1271_ps_elp_wakeup(wl, false); | 241 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -278,21 +244,30 @@ void wl1271_tx_work(struct work_struct *work) | |||
278 | woken_up = true; | 244 | woken_up = true; |
279 | } | 245 | } |
280 | 246 | ||
281 | ret = wl1271_tx_frame(wl, skb); | 247 | ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); |
282 | if (ret == -EBUSY) { | 248 | if (ret == -EBUSY) { |
283 | /* firmware buffer is full, lets stop transmitting. */ | 249 | /* |
250 | * Either the firmware buffer is full, or the | ||
251 | * aggregation buffer is. | ||
252 | * Queue back last skb, and stop aggregating. | ||
253 | */ | ||
284 | skb_queue_head(&wl->tx_queue, skb); | 254 | skb_queue_head(&wl->tx_queue, skb); |
285 | goto out_ack; | 255 | goto out_ack; |
286 | } else if (ret < 0) { | 256 | } else if (ret < 0) { |
287 | dev_kfree_skb(skb); | 257 | dev_kfree_skb(skb); |
288 | goto out_ack; | 258 | goto out_ack; |
289 | } | 259 | } |
260 | buf_offset += ret; | ||
261 | wl->tx_packets_count++; | ||
290 | } | 262 | } |
291 | 263 | ||
292 | out_ack: | 264 | out_ack: |
293 | /* interrupt the firmware with the new packets */ | 265 | if (buf_offset) { |
294 | if (prev_tx_packets_count != wl->tx_packets_count) | 266 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, |
267 | buf_offset, true); | ||
268 | /* interrupt the firmware with the new packets */ | ||
295 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | 269 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); |
270 | } | ||
296 | 271 | ||
297 | out: | 272 | out: |
298 | if (woken_up) | 273 | if (woken_up) |
@@ -422,8 +397,6 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
422 | struct sk_buff *skb; | 397 | struct sk_buff *skb; |
423 | 398 | ||
424 | /* TX failure */ | 399 | /* TX failure */ |
425 | /* control->flags = 0; FIXME */ | ||
426 | |||
427 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 400 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
428 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); | 401 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); |
429 | ieee80211_tx_status(wl->hw, skb); | 402 | ieee80211_tx_status(wl->hw, skb); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 48bf92621c03..d12a129ad11c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -139,23 +139,6 @@ static inline int wl1271_tx_get_queue(int queue) | |||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | /* wl1271 tx descriptor needs the tid and we need to convert it from ac */ | ||
143 | static inline int wl1271_tx_ac_to_tid(int ac) | ||
144 | { | ||
145 | switch (ac) { | ||
146 | case 0: | ||
147 | return 0; | ||
148 | case 1: | ||
149 | return 2; | ||
150 | case 2: | ||
151 | return 4; | ||
152 | case 3: | ||
153 | return 6; | ||
154 | default: | ||
155 | return 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | void wl1271_tx_work(struct work_struct *work); | 142 | void wl1271_tx_work(struct work_struct *work); |
160 | void wl1271_tx_complete(struct wl1271 *wl); | 143 | void wl1271_tx_complete(struct wl1271 *wl); |
161 | void wl1271_tx_reset(struct wl1271 *wl); | 144 | void wl1271_tx_reset(struct wl1271 *wl); |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f0518b0278a9..c08709fe36fc 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -315,8 +315,8 @@ | |||
315 | * channel for the specified amount of time. This can be used to do | 315 | * channel for the specified amount of time. This can be used to do |
316 | * off-channel operations like transmit a Public Action frame and wait for | 316 | * off-channel operations like transmit a Public Action frame and wait for |
317 | * a response while being associated to an AP on another channel. | 317 | * a response while being associated to an AP on another channel. |
318 | * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which | 318 | * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus |
319 | * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the | 319 | * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the |
320 | * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be | 320 | * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be |
321 | * optionally used to specify additional channel parameters. | 321 | * optionally used to specify additional channel parameters. |
322 | * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds | 322 | * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds |
@@ -387,6 +387,8 @@ | |||
387 | * of any other interfaces, and other interfaces will again take | 387 | * of any other interfaces, and other interfaces will again take |
388 | * precedence when they are used. | 388 | * precedence when they are used. |
389 | * | 389 | * |
390 | * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. | ||
391 | * | ||
390 | * @NL80211_CMD_MAX: highest used command number | 392 | * @NL80211_CMD_MAX: highest used command number |
391 | * @__NL80211_CMD_AFTER_LAST: internal use | 393 | * @__NL80211_CMD_AFTER_LAST: internal use |
392 | */ | 394 | */ |
@@ -489,6 +491,7 @@ enum nl80211_commands { | |||
489 | NL80211_CMD_NOTIFY_CQM, | 491 | NL80211_CMD_NOTIFY_CQM, |
490 | 492 | ||
491 | NL80211_CMD_SET_CHANNEL, | 493 | NL80211_CMD_SET_CHANNEL, |
494 | NL80211_CMD_SET_WDS_PEER, | ||
492 | 495 | ||
493 | /* add new commands above here */ | 496 | /* add new commands above here */ |
494 | 497 | ||
@@ -798,6 +801,9 @@ enum nl80211_commands { | |||
798 | * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING | 801 | * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING |
799 | * for non-automatic settings. | 802 | * for non-automatic settings. |
800 | * | 803 | * |
804 | * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly | ||
805 | * means support for per-station GTKs. | ||
806 | * | ||
801 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 807 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
802 | * @__NL80211_ATTR_AFTER_LAST: internal use | 808 | * @__NL80211_ATTR_AFTER_LAST: internal use |
803 | */ | 809 | */ |
@@ -965,6 +971,8 @@ enum nl80211_attrs { | |||
965 | NL80211_ATTR_CONTROL_PORT_ETHERTYPE, | 971 | NL80211_ATTR_CONTROL_PORT_ETHERTYPE, |
966 | NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, | 972 | NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, |
967 | 973 | ||
974 | NL80211_ATTR_SUPPORT_IBSS_RSN, | ||
975 | |||
968 | /* add attributes here, update the policy in nl80211.c */ | 976 | /* add attributes here, update the policy in nl80211.c */ |
969 | 977 | ||
970 | __NL80211_ATTR_AFTER_LAST, | 978 | __NL80211_ATTR_AFTER_LAST, |
@@ -1129,6 +1137,8 @@ enum nl80211_rate_info { | |||
1129 | * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) | 1137 | * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) |
1130 | * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this | 1138 | * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this |
1131 | * station) | 1139 | * station) |
1140 | * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) | ||
1141 | * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) | ||
1132 | */ | 1142 | */ |
1133 | enum nl80211_sta_info { | 1143 | enum nl80211_sta_info { |
1134 | __NL80211_STA_INFO_INVALID, | 1144 | __NL80211_STA_INFO_INVALID, |
@@ -1142,6 +1152,8 @@ enum nl80211_sta_info { | |||
1142 | NL80211_STA_INFO_TX_BITRATE, | 1152 | NL80211_STA_INFO_TX_BITRATE, |
1143 | NL80211_STA_INFO_RX_PACKETS, | 1153 | NL80211_STA_INFO_RX_PACKETS, |
1144 | NL80211_STA_INFO_TX_PACKETS, | 1154 | NL80211_STA_INFO_TX_PACKETS, |
1155 | NL80211_STA_INFO_TX_RETRIES, | ||
1156 | NL80211_STA_INFO_TX_FAILED, | ||
1145 | 1157 | ||
1146 | /* keep last */ | 1158 | /* keep last */ |
1147 | __NL80211_STA_INFO_AFTER_LAST, | 1159 | __NL80211_STA_INFO_AFTER_LAST, |
@@ -1400,6 +1412,7 @@ enum nl80211_reg_rule_flags { | |||
1400 | * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved | 1412 | * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved |
1401 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel | 1413 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel |
1402 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) | 1414 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) |
1415 | * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used | ||
1403 | * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number | 1416 | * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number |
1404 | * currently defined | 1417 | * currently defined |
1405 | * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use | 1418 | * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use |
@@ -1408,6 +1421,7 @@ enum nl80211_survey_info { | |||
1408 | __NL80211_SURVEY_INFO_INVALID, | 1421 | __NL80211_SURVEY_INFO_INVALID, |
1409 | NL80211_SURVEY_INFO_FREQUENCY, | 1422 | NL80211_SURVEY_INFO_FREQUENCY, |
1410 | NL80211_SURVEY_INFO_NOISE, | 1423 | NL80211_SURVEY_INFO_NOISE, |
1424 | NL80211_SURVEY_INFO_IN_USE, | ||
1411 | 1425 | ||
1412 | /* keep last */ | 1426 | /* keep last */ |
1413 | __NL80211_SURVEY_INFO_AFTER_LAST, | 1427 | __NL80211_SURVEY_INFO_AFTER_LAST, |
@@ -1654,11 +1668,14 @@ enum nl80211_auth_type { | |||
1654 | * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key | 1668 | * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key |
1655 | * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key | 1669 | * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key |
1656 | * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) | 1670 | * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) |
1671 | * @NUM_NL80211_KEYTYPES: number of defined key types | ||
1657 | */ | 1672 | */ |
1658 | enum nl80211_key_type { | 1673 | enum nl80211_key_type { |
1659 | NL80211_KEYTYPE_GROUP, | 1674 | NL80211_KEYTYPE_GROUP, |
1660 | NL80211_KEYTYPE_PAIRWISE, | 1675 | NL80211_KEYTYPE_PAIRWISE, |
1661 | NL80211_KEYTYPE_PEERKEY, | 1676 | NL80211_KEYTYPE_PEERKEY, |
1677 | |||
1678 | NUM_NL80211_KEYTYPES | ||
1662 | }; | 1679 | }; |
1663 | 1680 | ||
1664 | /** | 1681 | /** |
@@ -1689,6 +1706,9 @@ enum nl80211_wpa_versions { | |||
1689 | * CCMP keys, each six bytes in little endian | 1706 | * CCMP keys, each six bytes in little endian |
1690 | * @NL80211_KEY_DEFAULT: flag indicating default key | 1707 | * @NL80211_KEY_DEFAULT: flag indicating default key |
1691 | * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key | 1708 | * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key |
1709 | * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not | ||
1710 | * specified the default depends on whether a MAC address was | ||
1711 | * given with the command using the key or not (u32) | ||
1692 | * @__NL80211_KEY_AFTER_LAST: internal | 1712 | * @__NL80211_KEY_AFTER_LAST: internal |
1693 | * @NL80211_KEY_MAX: highest key attribute | 1713 | * @NL80211_KEY_MAX: highest key attribute |
1694 | */ | 1714 | */ |
@@ -1700,6 +1720,7 @@ enum nl80211_key_attributes { | |||
1700 | NL80211_KEY_SEQ, | 1720 | NL80211_KEY_SEQ, |
1701 | NL80211_KEY_DEFAULT, | 1721 | NL80211_KEY_DEFAULT, |
1702 | NL80211_KEY_DEFAULT_MGMT, | 1722 | NL80211_KEY_DEFAULT_MGMT, |
1723 | NL80211_KEY_TYPE, | ||
1703 | 1724 | ||
1704 | /* keep last */ | 1725 | /* keep last */ |
1705 | __NL80211_KEY_AFTER_LAST, | 1726 | __NL80211_KEY_AFTER_LAST, |
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index 95deae3968f4..4f902e1908aa 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h | |||
@@ -32,7 +32,20 @@ struct wl12xx_platform_data { | |||
32 | int board_ref_clock; | 32 | int board_ref_clock; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #ifdef CONFIG_WL12XX_PLATFORM_DATA | ||
36 | |||
35 | int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); | 37 | int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); |
38 | |||
39 | #else | ||
40 | |||
41 | static inline | ||
42 | int wl12xx_set_platform_data(const struct wl12xx_platform_data *data) | ||
43 | { | ||
44 | return -ENOSYS; | ||
45 | } | ||
46 | |||
47 | #endif | ||
48 | |||
36 | const struct wl12xx_platform_data *wl12xx_get_platform_data(void); | 49 | const struct wl12xx_platform_data *wl12xx_get_platform_data(void); |
37 | 50 | ||
38 | #endif | 51 | #endif |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a0613ff62c97..0778d04b3bbe 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -293,12 +293,14 @@ struct key_params { | |||
293 | * enum survey_info_flags - survey information flags | 293 | * enum survey_info_flags - survey information flags |
294 | * | 294 | * |
295 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in | 295 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in |
296 | * @SURVEY_INFO_IN_USE: channel is currently being used | ||
296 | * | 297 | * |
297 | * Used by the driver to indicate which info in &struct survey_info | 298 | * Used by the driver to indicate which info in &struct survey_info |
298 | * it has filled in during the get_survey(). | 299 | * it has filled in during the get_survey(). |
299 | */ | 300 | */ |
300 | enum survey_info_flags { | 301 | enum survey_info_flags { |
301 | SURVEY_INFO_NOISE_DBM = 1<<0, | 302 | SURVEY_INFO_NOISE_DBM = 1<<0, |
303 | SURVEY_INFO_IN_USE = 1<<1, | ||
302 | }; | 304 | }; |
303 | 305 | ||
304 | /** | 306 | /** |
@@ -399,6 +401,8 @@ struct station_parameters { | |||
399 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | 401 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) |
400 | * @STATION_INFO_RX_PACKETS: @rx_packets filled | 402 | * @STATION_INFO_RX_PACKETS: @rx_packets filled |
401 | * @STATION_INFO_TX_PACKETS: @tx_packets filled | 403 | * @STATION_INFO_TX_PACKETS: @tx_packets filled |
404 | * @STATION_INFO_TX_RETRIES: @tx_retries filled | ||
405 | * @STATION_INFO_TX_FAILED: @tx_failed filled | ||
402 | */ | 406 | */ |
403 | enum station_info_flags { | 407 | enum station_info_flags { |
404 | STATION_INFO_INACTIVE_TIME = 1<<0, | 408 | STATION_INFO_INACTIVE_TIME = 1<<0, |
@@ -411,6 +415,8 @@ enum station_info_flags { | |||
411 | STATION_INFO_TX_BITRATE = 1<<7, | 415 | STATION_INFO_TX_BITRATE = 1<<7, |
412 | STATION_INFO_RX_PACKETS = 1<<8, | 416 | STATION_INFO_RX_PACKETS = 1<<8, |
413 | STATION_INFO_TX_PACKETS = 1<<9, | 417 | STATION_INFO_TX_PACKETS = 1<<9, |
418 | STATION_INFO_TX_RETRIES = 1<<10, | ||
419 | STATION_INFO_TX_FAILED = 1<<11, | ||
414 | }; | 420 | }; |
415 | 421 | ||
416 | /** | 422 | /** |
@@ -460,6 +466,8 @@ struct rate_info { | |||
460 | * @txrate: current unicast bitrate to this station | 466 | * @txrate: current unicast bitrate to this station |
461 | * @rx_packets: packets received from this station | 467 | * @rx_packets: packets received from this station |
462 | * @tx_packets: packets transmitted to this station | 468 | * @tx_packets: packets transmitted to this station |
469 | * @tx_retries: cumulative retry counts | ||
470 | * @tx_failed: number of failed transmissions (retries exceeded, no ACK) | ||
463 | * @generation: generation number for nl80211 dumps. | 471 | * @generation: generation number for nl80211 dumps. |
464 | * This number should increase every time the list of stations | 472 | * This number should increase every time the list of stations |
465 | * changes, i.e. when a station is added or removed, so that | 473 | * changes, i.e. when a station is added or removed, so that |
@@ -477,6 +485,8 @@ struct station_info { | |||
477 | struct rate_info txrate; | 485 | struct rate_info txrate; |
478 | u32 rx_packets; | 486 | u32 rx_packets; |
479 | u32 tx_packets; | 487 | u32 tx_packets; |
488 | u32 tx_retries; | ||
489 | u32 tx_failed; | ||
480 | 490 | ||
481 | int generation; | 491 | int generation; |
482 | }; | 492 | }; |
@@ -1128,13 +1138,14 @@ struct cfg80211_ops { | |||
1128 | struct vif_params *params); | 1138 | struct vif_params *params); |
1129 | 1139 | ||
1130 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, | 1140 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, |
1131 | u8 key_index, const u8 *mac_addr, | 1141 | u8 key_index, bool pairwise, const u8 *mac_addr, |
1132 | struct key_params *params); | 1142 | struct key_params *params); |
1133 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, | 1143 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, |
1134 | u8 key_index, const u8 *mac_addr, void *cookie, | 1144 | u8 key_index, bool pairwise, const u8 *mac_addr, |
1145 | void *cookie, | ||
1135 | void (*callback)(void *cookie, struct key_params*)); | 1146 | void (*callback)(void *cookie, struct key_params*)); |
1136 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, | 1147 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, |
1137 | u8 key_index, const u8 *mac_addr); | 1148 | u8 key_index, bool pairwise, const u8 *mac_addr); |
1138 | int (*set_default_key)(struct wiphy *wiphy, | 1149 | int (*set_default_key)(struct wiphy *wiphy, |
1139 | struct net_device *netdev, | 1150 | struct net_device *netdev, |
1140 | u8 key_index); | 1151 | u8 key_index); |
@@ -1218,7 +1229,7 @@ struct cfg80211_ops { | |||
1218 | int (*get_tx_power)(struct wiphy *wiphy, int *dbm); | 1229 | int (*get_tx_power)(struct wiphy *wiphy, int *dbm); |
1219 | 1230 | ||
1220 | int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, | 1231 | int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, |
1221 | u8 *addr); | 1232 | const u8 *addr); |
1222 | 1233 | ||
1223 | void (*rfkill_poll)(struct wiphy *wiphy); | 1234 | void (*rfkill_poll)(struct wiphy *wiphy); |
1224 | 1235 | ||
@@ -1302,6 +1313,7 @@ struct cfg80211_ops { | |||
1302 | * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the | 1313 | * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the |
1303 | * control port protocol ethertype. The device also honours the | 1314 | * control port protocol ethertype. The device also honours the |
1304 | * control_port_no_encrypt flag. | 1315 | * control_port_no_encrypt flag. |
1316 | * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. | ||
1305 | */ | 1317 | */ |
1306 | enum wiphy_flags { | 1318 | enum wiphy_flags { |
1307 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), | 1319 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), |
@@ -1312,6 +1324,7 @@ enum wiphy_flags { | |||
1312 | WIPHY_FLAG_4ADDR_AP = BIT(5), | 1324 | WIPHY_FLAG_4ADDR_AP = BIT(5), |
1313 | WIPHY_FLAG_4ADDR_STATION = BIT(6), | 1325 | WIPHY_FLAG_4ADDR_STATION = BIT(6), |
1314 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), | 1326 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), |
1327 | WIPHY_FLAG_IBSS_RSN = BIT(7), | ||
1315 | }; | 1328 | }; |
1316 | 1329 | ||
1317 | struct mac_address { | 1330 | struct mac_address { |
@@ -2551,8 +2564,6 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
2551 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 2564 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
2552 | gfp_t gfp); | 2565 | gfp_t gfp); |
2553 | 2566 | ||
2554 | #ifdef __KERNEL__ | ||
2555 | |||
2556 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ | 2567 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
2557 | 2568 | ||
2558 | /* wiphy_printk helpers, similar to dev_printk */ | 2569 | /* wiphy_printk helpers, similar to dev_printk */ |
@@ -2599,6 +2610,4 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
2599 | #define wiphy_WARN(wiphy, format, args...) \ | 2610 | #define wiphy_WARN(wiphy, format, args...) \ |
2600 | WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args); | 2611 | WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args); |
2601 | 2612 | ||
2602 | #endif | ||
2603 | |||
2604 | #endif /* __NET_CFG80211_H */ | 2613 | #endif /* __NET_CFG80211_H */ |
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index f7dcd2c70412..8a64b811a39a 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
@@ -20,6 +20,9 @@ struct genl_multicast_group { | |||
20 | u32 id; | 20 | u32 id; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | struct genl_ops; | ||
24 | struct genl_info; | ||
25 | |||
23 | /** | 26 | /** |
24 | * struct genl_family - generic netlink family | 27 | * struct genl_family - generic netlink family |
25 | * @id: protocol family idenfitier | 28 | * @id: protocol family idenfitier |
@@ -29,6 +32,10 @@ struct genl_multicast_group { | |||
29 | * @maxattr: maximum number of attributes supported | 32 | * @maxattr: maximum number of attributes supported |
30 | * @netnsok: set to true if the family can handle network | 33 | * @netnsok: set to true if the family can handle network |
31 | * namespaces and should be presented in all of them | 34 | * namespaces and should be presented in all of them |
35 | * @pre_doit: called before an operation's doit callback, it may | ||
36 | * do additional, common, filtering and return an error | ||
37 | * @post_doit: called after an operation's doit callback, it may | ||
38 | * undo operations done by pre_doit, for example release locks | ||
32 | * @attrbuf: buffer to store parsed attributes | 39 | * @attrbuf: buffer to store parsed attributes |
33 | * @ops_list: list of all assigned operations | 40 | * @ops_list: list of all assigned operations |
34 | * @family_list: family list | 41 | * @family_list: family list |
@@ -41,6 +48,12 @@ struct genl_family { | |||
41 | unsigned int version; | 48 | unsigned int version; |
42 | unsigned int maxattr; | 49 | unsigned int maxattr; |
43 | bool netnsok; | 50 | bool netnsok; |
51 | int (*pre_doit)(struct genl_ops *ops, | ||
52 | struct sk_buff *skb, | ||
53 | struct genl_info *info); | ||
54 | void (*post_doit)(struct genl_ops *ops, | ||
55 | struct sk_buff *skb, | ||
56 | struct genl_info *info); | ||
44 | struct nlattr ** attrbuf; /* private */ | 57 | struct nlattr ** attrbuf; /* private */ |
45 | struct list_head ops_list; /* private */ | 58 | struct list_head ops_list; /* private */ |
46 | struct list_head family_list; /* private */ | 59 | struct list_head family_list; /* private */ |
@@ -55,6 +68,8 @@ struct genl_family { | |||
55 | * @genlhdr: generic netlink message header | 68 | * @genlhdr: generic netlink message header |
56 | * @userhdr: user specific header | 69 | * @userhdr: user specific header |
57 | * @attrs: netlink attributes | 70 | * @attrs: netlink attributes |
71 | * @_net: network namespace | ||
72 | * @user_ptr: user pointers | ||
58 | */ | 73 | */ |
59 | struct genl_info { | 74 | struct genl_info { |
60 | u32 snd_seq; | 75 | u32 snd_seq; |
@@ -66,6 +81,7 @@ struct genl_info { | |||
66 | #ifdef CONFIG_NET_NS | 81 | #ifdef CONFIG_NET_NS |
67 | struct net * _net; | 82 | struct net * _net; |
68 | #endif | 83 | #endif |
84 | void * user_ptr[2]; | ||
69 | }; | 85 | }; |
70 | 86 | ||
71 | static inline struct net *genl_info_net(struct genl_info *info) | 87 | static inline struct net *genl_info_net(struct genl_info *info) |
@@ -81,6 +97,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net) | |||
81 | /** | 97 | /** |
82 | * struct genl_ops - generic netlink operations | 98 | * struct genl_ops - generic netlink operations |
83 | * @cmd: command identifier | 99 | * @cmd: command identifier |
100 | * @internal_flags: flags used by the family | ||
84 | * @flags: flags | 101 | * @flags: flags |
85 | * @policy: attribute validation policy | 102 | * @policy: attribute validation policy |
86 | * @doit: standard command callback | 103 | * @doit: standard command callback |
@@ -90,6 +107,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net) | |||
90 | */ | 107 | */ |
91 | struct genl_ops { | 108 | struct genl_ops { |
92 | u8 cmd; | 109 | u8 cmd; |
110 | u8 internal_flags; | ||
93 | unsigned int flags; | 111 | unsigned int flags; |
94 | const struct nla_policy *policy; | 112 | const struct nla_policy *policy; |
95 | int (*doit)(struct sk_buff *skb, | 113 | int (*doit)(struct sk_buff *skb, |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fe8b9dae4dee..33aa2e39147b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1041,6 +1041,13 @@ enum ieee80211_tkip_key_type { | |||
1041 | * @IEEE80211_HW_NEED_DTIM_PERIOD: | 1041 | * @IEEE80211_HW_NEED_DTIM_PERIOD: |
1042 | * This device needs to know the DTIM period for the BSS before | 1042 | * This device needs to know the DTIM period for the BSS before |
1043 | * associating. | 1043 | * associating. |
1044 | * | ||
1045 | * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports | ||
1046 | * per-station GTKs as used by IBSS RSN or during fast transition. If | ||
1047 | * the device doesn't support per-station GTKs, but can be asked not | ||
1048 | * to decrypt group addressed frames, then IBSS RSN support is still | ||
1049 | * possible but software crypto will be used. Advertise the wiphy flag | ||
1050 | * only in that case. | ||
1044 | */ | 1051 | */ |
1045 | enum ieee80211_hw_flags { | 1052 | enum ieee80211_hw_flags { |
1046 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1053 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1064,6 +1071,7 @@ enum ieee80211_hw_flags { | |||
1064 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, | 1071 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, |
1065 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | 1072 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, |
1066 | IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, | 1073 | IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, |
1074 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, | ||
1067 | }; | 1075 | }; |
1068 | 1076 | ||
1069 | /** | 1077 | /** |
@@ -1109,7 +1117,10 @@ enum ieee80211_hw_flags { | |||
1109 | * @sta_data_size: size (in bytes) of the drv_priv data area | 1117 | * @sta_data_size: size (in bytes) of the drv_priv data area |
1110 | * within &struct ieee80211_sta. | 1118 | * within &struct ieee80211_sta. |
1111 | * | 1119 | * |
1112 | * @max_rates: maximum number of alternate rate retry stages | 1120 | * @max_rates: maximum number of alternate rate retry stages the hw |
1121 | * can handle. | ||
1122 | * @max_report_rates: maximum number of alternate rate retry stages | ||
1123 | * the hw can report back. | ||
1113 | * @max_rate_tries: maximum number of tries for each stage | 1124 | * @max_rate_tries: maximum number of tries for each stage |
1114 | * | 1125 | * |
1115 | * @napi_weight: weight used for NAPI polling. You must specify an | 1126 | * @napi_weight: weight used for NAPI polling. You must specify an |
@@ -1131,6 +1142,7 @@ struct ieee80211_hw { | |||
1131 | u16 max_listen_interval; | 1142 | u16 max_listen_interval; |
1132 | s8 max_signal; | 1143 | s8 max_signal; |
1133 | u8 max_rates; | 1144 | u8 max_rates; |
1145 | u8 max_report_rates; | ||
1134 | u8 max_rate_tries; | 1146 | u8 max_rate_tries; |
1135 | }; | 1147 | }; |
1136 | 1148 | ||
@@ -2578,6 +2590,22 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); | |||
2578 | void ieee80211_request_smps(struct ieee80211_vif *vif, | 2590 | void ieee80211_request_smps(struct ieee80211_vif *vif, |
2579 | enum ieee80211_smps_mode smps_mode); | 2591 | enum ieee80211_smps_mode smps_mode); |
2580 | 2592 | ||
2593 | /** | ||
2594 | * ieee80211_key_removed - disable hw acceleration for key | ||
2595 | * @key_conf: The key hw acceleration should be disabled for | ||
2596 | * | ||
2597 | * This allows drivers to indicate that the given key has been | ||
2598 | * removed from hardware acceleration, due to a new key that | ||
2599 | * was added. Don't use this if the key can continue to be used | ||
2600 | * for TX, if the key restriction is on RX only it is permitted | ||
2601 | * to keep the key for TX only and not call this function. | ||
2602 | * | ||
2603 | * Due to locking constraints, it may only be called during | ||
2604 | * @set_key. This function must be allowed to sleep, and the | ||
2605 | * key it tries to disable may still be used until it returns. | ||
2606 | */ | ||
2607 | void ieee80211_key_removed(struct ieee80211_key_conf *key_conf); | ||
2608 | |||
2581 | /* Rate control API */ | 2609 | /* Rate control API */ |
2582 | 2610 | ||
2583 | /** | 2611 | /** |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 58eab9e8e4ee..720b7a84af59 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -56,7 +56,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 58 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
59 | u16 initiator, u16 reason) | 59 | u16 initiator, u16 reason, bool tx) |
60 | { | 60 | { |
61 | struct ieee80211_local *local = sta->local; | 61 | struct ieee80211_local *local = sta->local; |
62 | struct tid_ampdu_rx *tid_rx; | 62 | struct tid_ampdu_rx *tid_rx; |
@@ -81,7 +81,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
81 | "aggregation for tid %d\n", tid); | 81 | "aggregation for tid %d\n", tid); |
82 | 82 | ||
83 | /* check if this is a self generated aggregation halt */ | 83 | /* check if this is a self generated aggregation halt */ |
84 | if (initiator == WLAN_BACK_RECIPIENT) | 84 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
85 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 85 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
86 | tid, 0, reason); | 86 | tid, 0, reason); |
87 | 87 | ||
@@ -92,10 +92,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
92 | } | 92 | } |
93 | 93 | ||
94 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 94 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
95 | u16 initiator, u16 reason) | 95 | u16 initiator, u16 reason, bool tx) |
96 | { | 96 | { |
97 | mutex_lock(&sta->ampdu_mlme.mtx); | 97 | mutex_lock(&sta->ampdu_mlme.mtx); |
98 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | 98 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx); |
99 | mutex_unlock(&sta->ampdu_mlme.mtx); | 99 | mutex_unlock(&sta->ampdu_mlme.mtx); |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c893f236acea..d4679b265ba8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -145,7 +145,8 @@ static void kfree_tid_tx(struct rcu_head *rcu_head) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
148 | enum ieee80211_back_parties initiator) | 148 | enum ieee80211_back_parties initiator, |
149 | bool tx) | ||
149 | { | 150 | { |
150 | struct ieee80211_local *local = sta->local; | 151 | struct ieee80211_local *local = sta->local; |
151 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 152 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
@@ -175,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
175 | 176 | ||
176 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | 177 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); |
177 | 178 | ||
179 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
180 | |||
178 | /* | 181 | /* |
179 | * After this packets are no longer handed right through | 182 | * After this packets are no longer handed right through |
180 | * to the driver but are put onto tid_tx->pending instead, | 183 | * to the driver but are put onto tid_tx->pending instead, |
@@ -183,6 +186,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
183 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 186 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
184 | 187 | ||
185 | tid_tx->stop_initiator = initiator; | 188 | tid_tx->stop_initiator = initiator; |
189 | tid_tx->tx_stop = tx; | ||
186 | 190 | ||
187 | ret = drv_ampdu_action(local, sta->sdata, | 191 | ret = drv_ampdu_action(local, sta->sdata, |
188 | IEEE80211_AMPDU_TX_STOP, | 192 | IEEE80211_AMPDU_TX_STOP, |
@@ -575,13 +579,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
575 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | 579 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); |
576 | 580 | ||
577 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 581 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
578 | enum ieee80211_back_parties initiator) | 582 | enum ieee80211_back_parties initiator, |
583 | bool tx) | ||
579 | { | 584 | { |
580 | int ret; | 585 | int ret; |
581 | 586 | ||
582 | mutex_lock(&sta->ampdu_mlme.mtx); | 587 | mutex_lock(&sta->ampdu_mlme.mtx); |
583 | 588 | ||
584 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); | 589 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx); |
585 | 590 | ||
586 | mutex_unlock(&sta->ampdu_mlme.mtx); | 591 | mutex_unlock(&sta->ampdu_mlme.mtx); |
587 | 592 | ||
@@ -670,7 +675,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
670 | goto unlock_sta; | 675 | goto unlock_sta; |
671 | } | 676 | } |
672 | 677 | ||
673 | if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR) | 678 | if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop) |
674 | ieee80211_send_delba(sta->sdata, ra, tid, | 679 | ieee80211_send_delba(sta->sdata, ra, tid, |
675 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 680 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
676 | 681 | ||
@@ -770,7 +775,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
770 | 775 | ||
771 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 776 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
772 | } else { | 777 | } else { |
773 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | 778 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |
779 | true); | ||
774 | } | 780 | } |
775 | 781 | ||
776 | out: | 782 | out: |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c981604b71e6..ecf9b7166ed1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -68,14 +68,42 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
68 | params && params->use_4addr >= 0) | 68 | params && params->use_4addr >= 0) |
69 | sdata->u.mgd.use_4addr = params->use_4addr; | 69 | sdata->u.mgd.use_4addr = params->use_4addr; |
70 | 70 | ||
71 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) | 71 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { |
72 | sdata->u.mntr_flags = *flags; | 72 | struct ieee80211_local *local = sdata->local; |
73 | |||
74 | if (ieee80211_sdata_running(sdata)) { | ||
75 | /* | ||
76 | * Prohibit MONITOR_FLAG_COOK_FRAMES to be | ||
77 | * changed while the interface is up. | ||
78 | * Else we would need to add a lot of cruft | ||
79 | * to update everything: | ||
80 | * cooked_mntrs, monitor and all fif_* counters | ||
81 | * reconfigure hardware | ||
82 | */ | ||
83 | if ((*flags & MONITOR_FLAG_COOK_FRAMES) != | ||
84 | (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | ||
85 | return -EBUSY; | ||
86 | |||
87 | ieee80211_adjust_monitor_flags(sdata, -1); | ||
88 | sdata->u.mntr_flags = *flags; | ||
89 | ieee80211_adjust_monitor_flags(sdata, 1); | ||
90 | |||
91 | ieee80211_configure_filter(local); | ||
92 | } else { | ||
93 | /* | ||
94 | * Because the interface is down, ieee80211_do_stop | ||
95 | * and ieee80211_do_open take care of "everything" | ||
96 | * mentioned in the comment above. | ||
97 | */ | ||
98 | sdata->u.mntr_flags = *flags; | ||
99 | } | ||
100 | } | ||
73 | 101 | ||
74 | return 0; | 102 | return 0; |
75 | } | 103 | } |
76 | 104 | ||
77 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 105 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
78 | u8 key_idx, const u8 *mac_addr, | 106 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
79 | struct key_params *params) | 107 | struct key_params *params) |
80 | { | 108 | { |
81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 109 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -103,6 +131,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
103 | if (IS_ERR(key)) | 131 | if (IS_ERR(key)) |
104 | return PTR_ERR(key); | 132 | return PTR_ERR(key); |
105 | 133 | ||
134 | if (pairwise) | ||
135 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | ||
136 | |||
106 | mutex_lock(&sdata->local->sta_mtx); | 137 | mutex_lock(&sdata->local->sta_mtx); |
107 | 138 | ||
108 | if (mac_addr) { | 139 | if (mac_addr) { |
@@ -125,7 +156,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
125 | } | 156 | } |
126 | 157 | ||
127 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 158 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
128 | u8 key_idx, const u8 *mac_addr) | 159 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
129 | { | 160 | { |
130 | struct ieee80211_sub_if_data *sdata; | 161 | struct ieee80211_sub_if_data *sdata; |
131 | struct sta_info *sta; | 162 | struct sta_info *sta; |
@@ -142,10 +173,17 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
142 | if (!sta) | 173 | if (!sta) |
143 | goto out_unlock; | 174 | goto out_unlock; |
144 | 175 | ||
145 | if (sta->key) { | 176 | if (pairwise) { |
146 | ieee80211_key_free(sdata->local, sta->key); | 177 | if (sta->ptk) { |
147 | WARN_ON(sta->key); | 178 | ieee80211_key_free(sdata->local, sta->ptk); |
148 | ret = 0; | 179 | ret = 0; |
180 | } | ||
181 | } else { | ||
182 | if (sta->gtk[key_idx]) { | ||
183 | ieee80211_key_free(sdata->local, | ||
184 | sta->gtk[key_idx]); | ||
185 | ret = 0; | ||
186 | } | ||
149 | } | 187 | } |
150 | 188 | ||
151 | goto out_unlock; | 189 | goto out_unlock; |
@@ -167,7 +205,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
167 | } | 205 | } |
168 | 206 | ||
169 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | 207 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
170 | u8 key_idx, const u8 *mac_addr, void *cookie, | 208 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
209 | void *cookie, | ||
171 | void (*callback)(void *cookie, | 210 | void (*callback)(void *cookie, |
172 | struct key_params *params)) | 211 | struct key_params *params)) |
173 | { | 212 | { |
@@ -175,7 +214,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | struct sta_info *sta = NULL; | 214 | struct sta_info *sta = NULL; |
176 | u8 seq[6] = {0}; | 215 | u8 seq[6] = {0}; |
177 | struct key_params params; | 216 | struct key_params params; |
178 | struct ieee80211_key *key; | 217 | struct ieee80211_key *key = NULL; |
179 | u32 iv32; | 218 | u32 iv32; |
180 | u16 iv16; | 219 | u16 iv16; |
181 | int err = -ENOENT; | 220 | int err = -ENOENT; |
@@ -189,7 +228,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
189 | if (!sta) | 228 | if (!sta) |
190 | goto out; | 229 | goto out; |
191 | 230 | ||
192 | key = sta->key; | 231 | if (pairwise) |
232 | key = sta->ptk; | ||
233 | else if (key_idx < NUM_DEFAULT_KEYS) | ||
234 | key = sta->gtk[key_idx]; | ||
193 | } else | 235 | } else |
194 | key = sdata->keys[key_idx]; | 236 | key = sdata->keys[key_idx]; |
195 | 237 | ||
@@ -285,6 +327,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
285 | STATION_INFO_TX_BYTES | | 327 | STATION_INFO_TX_BYTES | |
286 | STATION_INFO_RX_PACKETS | | 328 | STATION_INFO_RX_PACKETS | |
287 | STATION_INFO_TX_PACKETS | | 329 | STATION_INFO_TX_PACKETS | |
330 | STATION_INFO_TX_RETRIES | | ||
331 | STATION_INFO_TX_FAILED | | ||
288 | STATION_INFO_TX_BITRATE; | 332 | STATION_INFO_TX_BITRATE; |
289 | 333 | ||
290 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 334 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
@@ -292,6 +336,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
292 | sinfo->tx_bytes = sta->tx_bytes; | 336 | sinfo->tx_bytes = sta->tx_bytes; |
293 | sinfo->rx_packets = sta->rx_packets; | 337 | sinfo->rx_packets = sta->rx_packets; |
294 | sinfo->tx_packets = sta->tx_packets; | 338 | sinfo->tx_packets = sta->tx_packets; |
339 | sinfo->tx_retries = sta->tx_retry_count; | ||
340 | sinfo->tx_failed = sta->tx_retry_failed; | ||
295 | 341 | ||
296 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 342 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
297 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 343 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
@@ -1317,7 +1363,7 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) | |||
1317 | } | 1363 | } |
1318 | 1364 | ||
1319 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, | 1365 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, |
1320 | u8 *addr) | 1366 | const u8 *addr) |
1321 | { | 1367 | { |
1322 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1368 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1323 | 1369 | ||
@@ -1366,7 +1412,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1366 | if (!sdata->u.mgd.associated || | 1412 | if (!sdata->u.mgd.associated || |
1367 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 1413 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
1368 | mutex_lock(&sdata->local->iflist_mtx); | 1414 | mutex_lock(&sdata->local->iflist_mtx); |
1369 | ieee80211_recalc_smps(sdata->local, sdata); | 1415 | ieee80211_recalc_smps(sdata->local); |
1370 | mutex_unlock(&sdata->local->iflist_mtx); | 1416 | mutex_unlock(&sdata->local->iflist_mtx); |
1371 | return 0; | 1417 | return 0; |
1372 | } | 1418 | } |
@@ -1521,7 +1567,11 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1521 | 1567 | ||
1522 | switch (sdata->vif.type) { | 1568 | switch (sdata->vif.type) { |
1523 | case NL80211_IFTYPE_ADHOC: | 1569 | case NL80211_IFTYPE_ADHOC: |
1524 | if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1570 | case NL80211_IFTYPE_AP: |
1571 | case NL80211_IFTYPE_AP_VLAN: | ||
1572 | case NL80211_IFTYPE_P2P_GO: | ||
1573 | if (!ieee80211_is_action(mgmt->frame_control) || | ||
1574 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | ||
1525 | break; | 1575 | break; |
1526 | rcu_read_lock(); | 1576 | rcu_read_lock(); |
1527 | sta = sta_info_get(sdata, mgmt->da); | 1577 | sta = sta_info_get(sdata, mgmt->da); |
@@ -1530,6 +1580,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1530 | return -ENOLINK; | 1580 | return -ENOLINK; |
1531 | break; | 1581 | break; |
1532 | case NL80211_IFTYPE_STATION: | 1582 | case NL80211_IFTYPE_STATION: |
1583 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1533 | break; | 1584 | break; |
1534 | default: | 1585 | default: |
1535 | return -EOPNOTSUPP; | 1586 | return -EOPNOTSUPP; |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6b7ff9fb4604..50c40ea3cb4d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -196,7 +196,8 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
196 | else | 196 | else |
197 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); | 197 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); |
198 | } else { | 198 | } else { |
199 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); | 199 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
200 | 3, true); | ||
200 | ret = 0; | 201 | ret = 0; |
201 | } | 202 | } |
202 | 203 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 11f74f5f7b2f..4214bb6e12fc 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -101,16 +101,16 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
101 | ht_cap->mcs.rx_mask[32/8] |= 1; | 101 | ht_cap->mcs.rx_mask[32/8] |= 1; |
102 | } | 102 | } |
103 | 103 | ||
104 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) | 104 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) |
105 | { | 105 | { |
106 | int i; | 106 | int i; |
107 | 107 | ||
108 | cancel_work_sync(&sta->ampdu_mlme.work); | 108 | cancel_work_sync(&sta->ampdu_mlme.work); |
109 | 109 | ||
110 | for (i = 0; i < STA_TID_NUM; i++) { | 110 | for (i = 0; i < STA_TID_NUM; i++) { |
111 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); | 111 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); |
112 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 112 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
113 | WLAN_REASON_QSTA_LEAVE_QBSS); | 113 | WLAN_REASON_QSTA_LEAVE_QBSS, tx); |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
@@ -135,7 +135,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
135 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) | 135 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) |
136 | ___ieee80211_stop_rx_ba_session( | 136 | ___ieee80211_stop_rx_ba_session( |
137 | sta, tid, WLAN_BACK_RECIPIENT, | 137 | sta, tid, WLAN_BACK_RECIPIENT, |
138 | WLAN_REASON_QSTA_TIMEOUT); | 138 | WLAN_REASON_QSTA_TIMEOUT, true); |
139 | 139 | ||
140 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 140 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
141 | if (!tid_tx) | 141 | if (!tid_tx) |
@@ -146,7 +146,8 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
146 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | 146 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, |
147 | &tid_tx->state)) | 147 | &tid_tx->state)) |
148 | ___ieee80211_stop_tx_ba_session(sta, tid, | 148 | ___ieee80211_stop_tx_ba_session(sta, tid, |
149 | WLAN_BACK_INITIATOR); | 149 | WLAN_BACK_INITIATOR, |
150 | true); | ||
150 | } | 151 | } |
151 | mutex_unlock(&sta->ampdu_mlme.mtx); | 152 | mutex_unlock(&sta->ampdu_mlme.mtx); |
152 | } | 153 | } |
@@ -214,9 +215,11 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
214 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 215 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
215 | 216 | ||
216 | if (initiator == WLAN_BACK_INITIATOR) | 217 | if (initiator == WLAN_BACK_INITIATOR) |
217 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); | 218 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0, |
219 | true); | ||
218 | else | 220 | else |
219 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT); | 221 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
222 | true); | ||
220 | } | 223 | } |
221 | 224 | ||
222 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 225 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 1a3aae54f0cf..ff60c022f51d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -173,6 +173,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
173 | memcpy(skb_put(skb, ifibss->ie_len), | 173 | memcpy(skb_put(skb, ifibss->ie_len), |
174 | ifibss->ie, ifibss->ie_len); | 174 | ifibss->ie, ifibss->ie_len); |
175 | 175 | ||
176 | if (local->hw.queues >= 4) { | ||
177 | pos = skb_put(skb, 9); | ||
178 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
179 | *pos++ = 7; /* len */ | ||
180 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
181 | *pos++ = 0x50; | ||
182 | *pos++ = 0xf2; | ||
183 | *pos++ = 2; /* WME */ | ||
184 | *pos++ = 0; /* WME info */ | ||
185 | *pos++ = 1; /* WME ver */ | ||
186 | *pos++ = 0; /* U-APSD no in use */ | ||
187 | } | ||
188 | |||
176 | rcu_assign_pointer(ifibss->presp, skb); | 189 | rcu_assign_pointer(ifibss->presp, skb); |
177 | 190 | ||
178 | sdata->vif.bss_conf.beacon_int = beacon_int; | 191 | sdata->vif.bss_conf.beacon_int = beacon_int; |
@@ -266,37 +279,45 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
266 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 279 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
267 | return; | 280 | return; |
268 | 281 | ||
269 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates && | 282 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
270 | memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) { | 283 | memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) { |
271 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | ||
272 | 284 | ||
273 | rcu_read_lock(); | 285 | rcu_read_lock(); |
274 | |||
275 | sta = sta_info_get(sdata, mgmt->sa); | 286 | sta = sta_info_get(sdata, mgmt->sa); |
276 | if (sta) { | ||
277 | u32 prev_rates; | ||
278 | 287 | ||
279 | prev_rates = sta->sta.supp_rates[band]; | 288 | if (elems->supp_rates) { |
280 | /* make sure mandatory rates are always added */ | 289 | supp_rates = ieee80211_sta_get_rates(local, elems, |
281 | sta->sta.supp_rates[band] = supp_rates | | 290 | band); |
282 | ieee80211_mandatory_rates(local, band); | 291 | if (sta) { |
292 | u32 prev_rates; | ||
283 | 293 | ||
284 | if (sta->sta.supp_rates[band] != prev_rates) { | 294 | prev_rates = sta->sta.supp_rates[band]; |
295 | /* make sure mandatory rates are always added */ | ||
296 | sta->sta.supp_rates[band] = supp_rates | | ||
297 | ieee80211_mandatory_rates(local, band); | ||
298 | |||
299 | if (sta->sta.supp_rates[band] != prev_rates) { | ||
285 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 300 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
286 | printk(KERN_DEBUG "%s: updated supp_rates set " | 301 | printk(KERN_DEBUG |
287 | "for %pM based on beacon/probe_response " | 302 | "%s: updated supp_rates set " |
288 | "(0x%x -> 0x%x)\n", | 303 | "for %pM based on beacon" |
289 | sdata->name, sta->sta.addr, | 304 | "/probe_resp (0x%x -> 0x%x)\n", |
290 | prev_rates, sta->sta.supp_rates[band]); | 305 | sdata->name, sta->sta.addr, |
306 | prev_rates, | ||
307 | sta->sta.supp_rates[band]); | ||
291 | #endif | 308 | #endif |
292 | rate_control_rate_init(sta); | 309 | rate_control_rate_init(sta); |
293 | } | 310 | } |
294 | rcu_read_unlock(); | 311 | } else |
295 | } else { | 312 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
296 | rcu_read_unlock(); | 313 | mgmt->sa, supp_rates, |
297 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 314 | GFP_ATOMIC); |
298 | supp_rates, GFP_KERNEL); | ||
299 | } | 315 | } |
316 | |||
317 | if (sta && elems->wmm_info) | ||
318 | set_sta_flags(sta, WLAN_STA_WME); | ||
319 | |||
320 | rcu_read_unlock(); | ||
300 | } | 321 | } |
301 | 322 | ||
302 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 323 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 945fbf29719d..f0610fa4fbe0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -369,6 +369,7 @@ struct ieee80211_if_managed { | |||
369 | 369 | ||
370 | unsigned int flags; | 370 | unsigned int flags; |
371 | 371 | ||
372 | bool beacon_crc_valid; | ||
372 | u32 beacon_crc; | 373 | u32 beacon_crc; |
373 | 374 | ||
374 | enum { | 375 | enum { |
@@ -548,8 +549,6 @@ struct ieee80211_sub_if_data { | |||
548 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 549 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
549 | unsigned int fragment_next; | 550 | unsigned int fragment_next; |
550 | 551 | ||
551 | #define NUM_DEFAULT_KEYS 4 | ||
552 | #define NUM_DEFAULT_MGMT_KEYS 2 | ||
553 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 552 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
554 | struct ieee80211_key *default_key; | 553 | struct ieee80211_key *default_key; |
555 | struct ieee80211_key *default_mgmt_key; | 554 | struct ieee80211_key *default_mgmt_key; |
@@ -1132,6 +1131,8 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | |||
1132 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 1131 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
1133 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | 1132 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); |
1134 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1133 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1134 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | ||
1135 | const int offset); | ||
1135 | 1136 | ||
1136 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1137 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1137 | { | 1138 | { |
@@ -1172,10 +1173,10 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1172 | void ieee80211_request_smps_work(struct work_struct *work); | 1173 | void ieee80211_request_smps_work(struct work_struct *work); |
1173 | 1174 | ||
1174 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1175 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1175 | u16 initiator, u16 reason); | 1176 | u16 initiator, u16 reason, bool stop); |
1176 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1177 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1177 | u16 initiator, u16 reason); | 1178 | u16 initiator, u16 reason, bool stop); |
1178 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1179 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx); |
1179 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 1180 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
1180 | struct sta_info *sta, | 1181 | struct sta_info *sta, |
1181 | struct ieee80211_mgmt *mgmt, size_t len); | 1182 | struct ieee80211_mgmt *mgmt, size_t len); |
@@ -1189,9 +1190,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
1189 | size_t len); | 1190 | size_t len); |
1190 | 1191 | ||
1191 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1192 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1192 | enum ieee80211_back_parties initiator); | 1193 | enum ieee80211_back_parties initiator, |
1194 | bool tx); | ||
1193 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1195 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1194 | enum ieee80211_back_parties initiator); | 1196 | enum ieee80211_back_parties initiator, |
1197 | bool tx); | ||
1195 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | 1198 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); |
1196 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1199 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1197 | void ieee80211_ba_session_work(struct work_struct *work); | 1200 | void ieee80211_ba_session_work(struct work_struct *work); |
@@ -1294,8 +1297,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1294 | enum ieee80211_band band); | 1297 | enum ieee80211_band band); |
1295 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1298 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
1296 | enum ieee80211_smps_mode smps_mode); | 1299 | enum ieee80211_smps_mode smps_mode); |
1297 | void ieee80211_recalc_smps(struct ieee80211_local *local, | 1300 | void ieee80211_recalc_smps(struct ieee80211_local *local); |
1298 | struct ieee80211_sub_if_data *forsdata); | ||
1299 | 1301 | ||
1300 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1302 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
1301 | const u8 *ids, int n_ids, size_t offset); | 1303 | const u8 *ids, int n_ids, size_t offset); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 66785739dad3..e99d1b60557c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "led.h" | 24 | #include "led.h" |
25 | #include "driver-ops.h" | 25 | #include "driver-ops.h" |
26 | #include "wme.h" | 26 | #include "wme.h" |
27 | #include "rate.h" | ||
27 | 28 | ||
28 | /** | 29 | /** |
29 | * DOC: Interface list locking | 30 | * DOC: Interface list locking |
@@ -148,6 +149,26 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, | |||
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | 151 | ||
152 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | ||
153 | const int offset) | ||
154 | { | ||
155 | struct ieee80211_local *local = sdata->local; | ||
156 | u32 flags = sdata->u.mntr_flags; | ||
157 | |||
158 | #define ADJUST(_f, _s) do { \ | ||
159 | if (flags & MONITOR_FLAG_##_f) \ | ||
160 | local->fif_##_s += offset; \ | ||
161 | } while (0) | ||
162 | |||
163 | ADJUST(FCSFAIL, fcsfail); | ||
164 | ADJUST(PLCPFAIL, plcpfail); | ||
165 | ADJUST(CONTROL, control); | ||
166 | ADJUST(CONTROL, pspoll); | ||
167 | ADJUST(OTHER_BSS, other_bss); | ||
168 | |||
169 | #undef ADJUST | ||
170 | } | ||
171 | |||
151 | /* | 172 | /* |
152 | * NOTE: Be very careful when changing this function, it must NOT return | 173 | * NOTE: Be very careful when changing this function, it must NOT return |
153 | * an error on interface type changes that have been pre-checked, so most | 174 | * an error on interface type changes that have been pre-checked, so most |
@@ -240,17 +261,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
240 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 261 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
241 | } | 262 | } |
242 | 263 | ||
243 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | 264 | ieee80211_adjust_monitor_flags(sdata, 1); |
244 | local->fif_fcsfail++; | ||
245 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
246 | local->fif_plcpfail++; | ||
247 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { | ||
248 | local->fif_control++; | ||
249 | local->fif_pspoll++; | ||
250 | } | ||
251 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
252 | local->fif_other_bss++; | ||
253 | |||
254 | ieee80211_configure_filter(local); | 265 | ieee80211_configure_filter(local); |
255 | 266 | ||
256 | netif_carrier_on(dev); | 267 | netif_carrier_on(dev); |
@@ -301,6 +312,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
301 | /* STA has been freed */ | 312 | /* STA has been freed */ |
302 | goto err_del_interface; | 313 | goto err_del_interface; |
303 | } | 314 | } |
315 | |||
316 | rate_control_rate_init(sta); | ||
304 | } | 317 | } |
305 | 318 | ||
306 | /* | 319 | /* |
@@ -477,17 +490,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
477 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 490 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
478 | } | 491 | } |
479 | 492 | ||
480 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | 493 | ieee80211_adjust_monitor_flags(sdata, -1); |
481 | local->fif_fcsfail--; | ||
482 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
483 | local->fif_plcpfail--; | ||
484 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { | ||
485 | local->fif_pspoll--; | ||
486 | local->fif_control--; | ||
487 | } | ||
488 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
489 | local->fif_other_bss--; | ||
490 | |||
491 | ieee80211_configure_filter(local); | 494 | ieee80211_configure_filter(local); |
492 | break; | 495 | break; |
493 | case NL80211_IFTYPE_MESH_POINT: | 496 | case NL80211_IFTYPE_MESH_POINT: |
@@ -793,7 +796,8 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
793 | 796 | ||
794 | __ieee80211_stop_rx_ba_session( | 797 | __ieee80211_stop_rx_ba_session( |
795 | sta, tid, WLAN_BACK_RECIPIENT, | 798 | sta, tid, WLAN_BACK_RECIPIENT, |
796 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 799 | WLAN_REASON_QSTA_REQUIRE_SETUP, |
800 | true); | ||
797 | } | 801 | } |
798 | mutex_unlock(&local->sta_mtx); | 802 | mutex_unlock(&local->sta_mtx); |
799 | } else switch (sdata->vif.type) { | 803 | } else switch (sdata->vif.type) { |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6a63d1abd14d..ccd676b2f599 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -68,15 +68,21 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
68 | 68 | ||
69 | might_sleep(); | 69 | might_sleep(); |
70 | 70 | ||
71 | if (!key->local->ops->set_key) { | 71 | if (!key->local->ops->set_key) |
72 | ret = -EOPNOTSUPP; | ||
73 | goto out_unsupported; | 72 | goto out_unsupported; |
74 | } | ||
75 | 73 | ||
76 | assert_key_lock(key->local); | 74 | assert_key_lock(key->local); |
77 | 75 | ||
78 | sta = get_sta_for_key(key); | 76 | sta = get_sta_for_key(key); |
79 | 77 | ||
78 | /* | ||
79 | * If this is a per-STA GTK, check if it | ||
80 | * is supported; if not, return. | ||
81 | */ | ||
82 | if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) && | ||
83 | !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) | ||
84 | goto out_unsupported; | ||
85 | |||
80 | sdata = key->sdata; | 86 | sdata = key->sdata; |
81 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 87 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
82 | sdata = container_of(sdata->bss, | 88 | sdata = container_of(sdata->bss, |
@@ -85,31 +91,28 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
85 | 91 | ||
86 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 92 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
87 | 93 | ||
88 | if (!ret) | 94 | if (!ret) { |
89 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 95 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
96 | return 0; | ||
97 | } | ||
90 | 98 | ||
91 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) | 99 | if (ret != -ENOSPC && ret != -EOPNOTSUPP) |
92 | wiphy_err(key->local->hw.wiphy, | 100 | wiphy_err(key->local->hw.wiphy, |
93 | "failed to set key (%d, %pM) to hardware (%d)\n", | 101 | "failed to set key (%d, %pM) to hardware (%d)\n", |
94 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 102 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
95 | 103 | ||
96 | out_unsupported: | 104 | out_unsupported: |
97 | if (ret) { | 105 | switch (key->conf.cipher) { |
98 | switch (key->conf.cipher) { | 106 | case WLAN_CIPHER_SUITE_WEP40: |
99 | case WLAN_CIPHER_SUITE_WEP40: | 107 | case WLAN_CIPHER_SUITE_WEP104: |
100 | case WLAN_CIPHER_SUITE_WEP104: | 108 | case WLAN_CIPHER_SUITE_TKIP: |
101 | case WLAN_CIPHER_SUITE_TKIP: | 109 | case WLAN_CIPHER_SUITE_CCMP: |
102 | case WLAN_CIPHER_SUITE_CCMP: | 110 | case WLAN_CIPHER_SUITE_AES_CMAC: |
103 | case WLAN_CIPHER_SUITE_AES_CMAC: | 111 | /* all of these we can do in software */ |
104 | /* all of these we can do in software */ | 112 | return 0; |
105 | ret = 0; | 113 | default: |
106 | break; | 114 | return -EINVAL; |
107 | default: | ||
108 | ret = -EINVAL; | ||
109 | } | ||
110 | } | 115 | } |
111 | |||
112 | return ret; | ||
113 | } | 116 | } |
114 | 117 | ||
115 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 118 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
@@ -147,6 +150,26 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
147 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 150 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
148 | } | 151 | } |
149 | 152 | ||
153 | void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | ||
154 | { | ||
155 | struct ieee80211_key *key; | ||
156 | |||
157 | key = container_of(key_conf, struct ieee80211_key, conf); | ||
158 | |||
159 | might_sleep(); | ||
160 | assert_key_lock(key->local); | ||
161 | |||
162 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | ||
163 | |||
164 | /* | ||
165 | * Flush TX path to avoid attempts to use this key | ||
166 | * after this function returns. Until then, drivers | ||
167 | * must be prepared to handle the key. | ||
168 | */ | ||
169 | synchronize_rcu(); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | ||
172 | |||
150 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 173 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
151 | int idx) | 174 | int idx) |
152 | { | 175 | { |
@@ -202,6 +225,7 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
202 | 225 | ||
203 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 226 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
204 | struct sta_info *sta, | 227 | struct sta_info *sta, |
228 | bool pairwise, | ||
205 | struct ieee80211_key *old, | 229 | struct ieee80211_key *old, |
206 | struct ieee80211_key *new) | 230 | struct ieee80211_key *new) |
207 | { | 231 | { |
@@ -210,8 +234,14 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
210 | if (new) | 234 | if (new) |
211 | list_add(&new->list, &sdata->key_list); | 235 | list_add(&new->list, &sdata->key_list); |
212 | 236 | ||
213 | if (sta) { | 237 | if (sta && pairwise) { |
214 | rcu_assign_pointer(sta->key, new); | 238 | rcu_assign_pointer(sta->ptk, new); |
239 | } else if (sta) { | ||
240 | if (old) | ||
241 | idx = old->conf.keyidx; | ||
242 | else | ||
243 | idx = new->conf.keyidx; | ||
244 | rcu_assign_pointer(sta->gtk[idx], new); | ||
215 | } else { | 245 | } else { |
216 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); | 246 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
217 | 247 | ||
@@ -355,6 +385,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
355 | { | 385 | { |
356 | struct ieee80211_key *old_key; | 386 | struct ieee80211_key *old_key; |
357 | int idx, ret; | 387 | int idx, ret; |
388 | bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | ||
358 | 389 | ||
359 | BUG_ON(!sdata); | 390 | BUG_ON(!sdata); |
360 | BUG_ON(!key); | 391 | BUG_ON(!key); |
@@ -371,13 +402,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
371 | */ | 402 | */ |
372 | if (test_sta_flags(sta, WLAN_STA_WME)) | 403 | if (test_sta_flags(sta, WLAN_STA_WME)) |
373 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 404 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
374 | |||
375 | /* | ||
376 | * This key is for a specific sta interface, | ||
377 | * inform the driver that it should try to store | ||
378 | * this key as pairwise key. | ||
379 | */ | ||
380 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | ||
381 | } else { | 405 | } else { |
382 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 406 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
383 | struct sta_info *ap; | 407 | struct sta_info *ap; |
@@ -399,12 +423,14 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
399 | 423 | ||
400 | mutex_lock(&sdata->local->key_mtx); | 424 | mutex_lock(&sdata->local->key_mtx); |
401 | 425 | ||
402 | if (sta) | 426 | if (sta && pairwise) |
403 | old_key = sta->key; | 427 | old_key = sta->ptk; |
428 | else if (sta) | ||
429 | old_key = sta->gtk[idx]; | ||
404 | else | 430 | else |
405 | old_key = sdata->keys[idx]; | 431 | old_key = sdata->keys[idx]; |
406 | 432 | ||
407 | __ieee80211_key_replace(sdata, sta, old_key, key); | 433 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
408 | __ieee80211_key_destroy(old_key); | 434 | __ieee80211_key_destroy(old_key); |
409 | 435 | ||
410 | ieee80211_debugfs_key_add(key); | 436 | ieee80211_debugfs_key_add(key); |
@@ -423,7 +449,8 @@ static void __ieee80211_key_free(struct ieee80211_key *key) | |||
423 | */ | 449 | */ |
424 | if (key->sdata) | 450 | if (key->sdata) |
425 | __ieee80211_key_replace(key->sdata, key->sta, | 451 | __ieee80211_key_replace(key->sdata, key->sta, |
426 | key, NULL); | 452 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
453 | key, NULL); | ||
427 | __ieee80211_key_destroy(key); | 454 | __ieee80211_key_destroy(key); |
428 | } | 455 | } |
429 | 456 | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index cb9a4a65cc68..0db1c0f5f697 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -16,6 +16,9 @@ | |||
16 | #include <linux/rcupdate.h> | 16 | #include <linux/rcupdate.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | #define NUM_DEFAULT_KEYS 4 | ||
20 | #define NUM_DEFAULT_MGMT_KEYS 2 | ||
21 | |||
19 | #define WEP_IV_LEN 4 | 22 | #define WEP_IV_LEN 4 |
20 | #define WEP_ICV_LEN 4 | 23 | #define WEP_ICV_LEN 4 |
21 | #define ALG_TKIP_KEY_LEN 32 | 24 | #define ALG_TKIP_KEY_LEN 32 |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index db341a99c7c7..eb0f59977676 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -201,6 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
201 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 201 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
202 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 202 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
203 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | 203 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
204 | else if (sdata->vif.type == NL80211_IFTYPE_WDS) | ||
205 | sdata->vif.bss_conf.bssid = NULL; | ||
204 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 206 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
205 | sdata->vif.bss_conf.bssid = zero; | 207 | sdata->vif.bss_conf.bssid = zero; |
206 | } else { | 208 | } else { |
@@ -211,6 +213,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
211 | switch (sdata->vif.type) { | 213 | switch (sdata->vif.type) { |
212 | case NL80211_IFTYPE_AP: | 214 | case NL80211_IFTYPE_AP: |
213 | case NL80211_IFTYPE_ADHOC: | 215 | case NL80211_IFTYPE_ADHOC: |
216 | case NL80211_IFTYPE_WDS: | ||
214 | case NL80211_IFTYPE_MESH_POINT: | 217 | case NL80211_IFTYPE_MESH_POINT: |
215 | break; | 218 | break; |
216 | default: | 219 | default: |
@@ -295,7 +298,16 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
295 | struct ieee80211_local *local = | 298 | struct ieee80211_local *local = |
296 | container_of(work, struct ieee80211_local, restart_work); | 299 | container_of(work, struct ieee80211_local, restart_work); |
297 | 300 | ||
301 | /* wait for scan work complete */ | ||
302 | flush_workqueue(local->workqueue); | ||
303 | |||
304 | mutex_lock(&local->mtx); | ||
305 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
306 | "%s called with hardware scan in progress\n", __func__); | ||
307 | mutex_unlock(&local->mtx); | ||
308 | |||
298 | rtnl_lock(); | 309 | rtnl_lock(); |
310 | ieee80211_scan_cancel(local); | ||
299 | ieee80211_reconfig(local); | 311 | ieee80211_reconfig(local); |
300 | rtnl_unlock(); | 312 | rtnl_unlock(); |
301 | } | 313 | } |
@@ -306,15 +318,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
306 | 318 | ||
307 | trace_api_restart_hw(local); | 319 | trace_api_restart_hw(local); |
308 | 320 | ||
309 | /* wait for scan work complete */ | ||
310 | flush_workqueue(local->workqueue); | ||
311 | |||
312 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
313 | "%s called with hardware scan in progress\n", __func__); | ||
314 | |||
315 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
316 | ieee80211_scan_cancel(local); | ||
317 | |||
318 | /* use this reason, ieee80211_reconfig will unblock it */ | 321 | /* use this reason, ieee80211_reconfig will unblock it */ |
319 | ieee80211_stop_queues_by_reason(hw, | 322 | ieee80211_stop_queues_by_reason(hw, |
320 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 323 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -329,7 +332,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) | |||
329 | container_of(work, struct ieee80211_local, recalc_smps); | 332 | container_of(work, struct ieee80211_local, recalc_smps); |
330 | 333 | ||
331 | mutex_lock(&local->iflist_mtx); | 334 | mutex_lock(&local->iflist_mtx); |
332 | ieee80211_recalc_smps(local, NULL); | 335 | ieee80211_recalc_smps(local); |
333 | mutex_unlock(&local->iflist_mtx); | 336 | mutex_unlock(&local->iflist_mtx); |
334 | } | 337 | } |
335 | 338 | ||
@@ -533,6 +536,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
533 | /* set up some defaults */ | 536 | /* set up some defaults */ |
534 | local->hw.queues = 1; | 537 | local->hw.queues = 1; |
535 | local->hw.max_rates = 1; | 538 | local->hw.max_rates = 1; |
539 | local->hw.max_report_rates = 0; | ||
536 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 540 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
537 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 541 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
538 | local->user_power_level = -1; | 542 | local->user_power_level = -1; |
@@ -608,6 +612,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
608 | WLAN_CIPHER_SUITE_AES_CMAC | 612 | WLAN_CIPHER_SUITE_AES_CMAC |
609 | }; | 613 | }; |
610 | 614 | ||
615 | if (hw->max_report_rates == 0) | ||
616 | hw->max_report_rates = hw->max_rates; | ||
617 | |||
611 | /* | 618 | /* |
612 | * generic code guarantees at least one band, | 619 | * generic code guarantees at least one band, |
613 | * set this very early because much code assumes | 620 | * set this very early because much code assumes |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 77913a15f537..5695c94c49aa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -913,7 +913,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
913 | 913 | ||
914 | mutex_lock(&local->iflist_mtx); | 914 | mutex_lock(&local->iflist_mtx); |
915 | ieee80211_recalc_ps(local, -1); | 915 | ieee80211_recalc_ps(local, -1); |
916 | ieee80211_recalc_smps(local, sdata); | 916 | ieee80211_recalc_smps(local); |
917 | mutex_unlock(&local->iflist_mtx); | 917 | mutex_unlock(&local->iflist_mtx); |
918 | 918 | ||
919 | netif_tx_start_all_queues(sdata->dev); | 919 | netif_tx_start_all_queues(sdata->dev); |
@@ -921,7 +921,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
921 | } | 921 | } |
922 | 922 | ||
923 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 923 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
924 | bool remove_sta) | 924 | bool remove_sta, bool tx) |
925 | { | 925 | { |
926 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 926 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
927 | struct ieee80211_local *local = sdata->local; | 927 | struct ieee80211_local *local = sdata->local; |
@@ -960,7 +960,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
960 | sta = sta_info_get(sdata, bssid); | 960 | sta = sta_info_get(sdata, bssid); |
961 | if (sta) { | 961 | if (sta) { |
962 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 962 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
963 | ieee80211_sta_tear_down_BA_sessions(sta); | 963 | ieee80211_sta_tear_down_BA_sessions(sta, tx); |
964 | } | 964 | } |
965 | mutex_unlock(&local->sta_mtx); | 965 | mutex_unlock(&local->sta_mtx); |
966 | 966 | ||
@@ -1124,7 +1124,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1124 | 1124 | ||
1125 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1125 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
1126 | 1126 | ||
1127 | ieee80211_set_disassoc(sdata, true); | 1127 | ieee80211_set_disassoc(sdata, true, true); |
1128 | mutex_unlock(&ifmgd->mtx); | 1128 | mutex_unlock(&ifmgd->mtx); |
1129 | 1129 | ||
1130 | mutex_lock(&local->mtx); | 1130 | mutex_lock(&local->mtx); |
@@ -1197,7 +1197,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1197 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1197 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1198 | sdata->name, bssid, reason_code); | 1198 | sdata->name, bssid, reason_code); |
1199 | 1199 | ||
1200 | ieee80211_set_disassoc(sdata, true); | 1200 | ieee80211_set_disassoc(sdata, true, false); |
1201 | mutex_lock(&sdata->local->mtx); | 1201 | mutex_lock(&sdata->local->mtx); |
1202 | ieee80211_recalc_idle(sdata->local); | 1202 | ieee80211_recalc_idle(sdata->local); |
1203 | mutex_unlock(&sdata->local->mtx); | 1203 | mutex_unlock(&sdata->local->mtx); |
@@ -1229,7 +1229,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1229 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1229 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1230 | sdata->name, mgmt->sa, reason_code); | 1230 | sdata->name, mgmt->sa, reason_code); |
1231 | 1231 | ||
1232 | ieee80211_set_disassoc(sdata, true); | 1232 | ieee80211_set_disassoc(sdata, true, false); |
1233 | mutex_lock(&sdata->local->mtx); | 1233 | mutex_lock(&sdata->local->mtx); |
1234 | ieee80211_recalc_idle(sdata->local); | 1234 | ieee80211_recalc_idle(sdata->local); |
1235 | mutex_unlock(&sdata->local->mtx); | 1235 | mutex_unlock(&sdata->local->mtx); |
@@ -1291,7 +1291,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1291 | 1291 | ||
1292 | rates = 0; | 1292 | rates = 0; |
1293 | basic_rates = 0; | 1293 | basic_rates = 0; |
1294 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1294 | sband = local->hw.wiphy->bands[wk->chan->band]; |
1295 | 1295 | ||
1296 | for (i = 0; i < elems.supp_rates_len; i++) { | 1296 | for (i = 0; i < elems.supp_rates_len; i++) { |
1297 | int rate = (elems.supp_rates[i] & 0x7f) * 5; | 1297 | int rate = (elems.supp_rates[i] & 0x7f) * 5; |
@@ -1327,11 +1327,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1327 | } | 1327 | } |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 1330 | sta->sta.supp_rates[wk->chan->band] = rates; |
1331 | sdata->vif.bss_conf.basic_rates = basic_rates; | 1331 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1332 | 1332 | ||
1333 | /* cf. IEEE 802.11 9.2.12 */ | 1333 | /* cf. IEEE 802.11 9.2.12 */ |
1334 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1334 | if (wk->chan->band == IEEE80211_BAND_2GHZ && |
1335 | have_higher_than_11mbit) | 1335 | have_higher_than_11mbit) |
1336 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 1336 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
1337 | else | 1337 | else |
@@ -1639,7 +1639,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1639 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, | 1639 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, |
1640 | ifmgd->aid); | 1640 | ifmgd->aid); |
1641 | 1641 | ||
1642 | if (ncrc != ifmgd->beacon_crc) { | 1642 | if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) { |
1643 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | 1643 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, |
1644 | true); | 1644 | true); |
1645 | 1645 | ||
@@ -1670,9 +1670,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1670 | } | 1670 | } |
1671 | } | 1671 | } |
1672 | 1672 | ||
1673 | if (ncrc == ifmgd->beacon_crc) | 1673 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) |
1674 | return; | 1674 | return; |
1675 | ifmgd->beacon_crc = ncrc; | 1675 | ifmgd->beacon_crc = ncrc; |
1676 | ifmgd->beacon_crc_valid = true; | ||
1676 | 1677 | ||
1677 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1678 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1678 | erp_valid = true; | 1679 | erp_valid = true; |
@@ -1879,7 +1880,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1879 | printk(KERN_DEBUG "No probe response from AP %pM" | 1880 | printk(KERN_DEBUG "No probe response from AP %pM" |
1880 | " after %dms, disconnecting.\n", | 1881 | " after %dms, disconnecting.\n", |
1881 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1882 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1882 | ieee80211_set_disassoc(sdata, true); | 1883 | ieee80211_set_disassoc(sdata, true, true); |
1883 | mutex_unlock(&ifmgd->mtx); | 1884 | mutex_unlock(&ifmgd->mtx); |
1884 | mutex_lock(&local->mtx); | 1885 | mutex_lock(&local->mtx); |
1885 | ieee80211_recalc_idle(local); | 1886 | ieee80211_recalc_idle(local); |
@@ -2203,7 +2204,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2203 | } | 2204 | } |
2204 | 2205 | ||
2205 | /* Trying to reassociate - clear previous association state */ | 2206 | /* Trying to reassociate - clear previous association state */ |
2206 | ieee80211_set_disassoc(sdata, true); | 2207 | ieee80211_set_disassoc(sdata, true, false); |
2207 | } | 2208 | } |
2208 | mutex_unlock(&ifmgd->mtx); | 2209 | mutex_unlock(&ifmgd->mtx); |
2209 | 2210 | ||
@@ -2214,6 +2215,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2214 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 2215 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
2215 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 2216 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
2216 | 2217 | ||
2218 | ifmgd->beacon_crc_valid = false; | ||
2219 | |||
2217 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 2220 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) |
2218 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 2221 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
2219 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 2222 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
@@ -2315,7 +2318,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2315 | 2318 | ||
2316 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 2319 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2317 | if (ifmgd->associated == req->bss) { | 2320 | if (ifmgd->associated == req->bss) { |
2318 | ieee80211_set_disassoc(sdata, false); | 2321 | ieee80211_set_disassoc(sdata, false, true); |
2319 | mutex_unlock(&ifmgd->mtx); | 2322 | mutex_unlock(&ifmgd->mtx); |
2320 | assoc_bss = true; | 2323 | assoc_bss = true; |
2321 | } else { | 2324 | } else { |
@@ -2398,7 +2401,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2398 | sdata->name, req->bss->bssid, req->reason_code); | 2401 | sdata->name, req->bss->bssid, req->reason_code); |
2399 | 2402 | ||
2400 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 2403 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2401 | ieee80211_set_disassoc(sdata, false); | 2404 | ieee80211_set_disassoc(sdata, false, true); |
2402 | 2405 | ||
2403 | mutex_unlock(&ifmgd->mtx); | 2406 | mutex_unlock(&ifmgd->mtx); |
2404 | 2407 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ce671dfd238c..e37355193ed1 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -12,8 +12,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 13 | struct sta_info *sta; |
14 | 14 | ||
15 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | 15 | ieee80211_scan_cancel(local); |
16 | ieee80211_scan_cancel(local); | ||
17 | 16 | ||
18 | ieee80211_stop_queues_by_reason(hw, | 17 | ieee80211_stop_queues_by_reason(hw, |
19 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 18 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -46,7 +45,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
46 | list_for_each_entry(sta, &local->sta_list, list) { | 45 | list_for_each_entry(sta, &local->sta_list, list) { |
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 46 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
48 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 47 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
49 | ieee80211_sta_tear_down_BA_sessions(sta); | 48 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
50 | } | 49 | } |
51 | 50 | ||
52 | if (sta->uploaded) { | 51 | if (sta->uploaded) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0b0e83ebe3d5..b67221def584 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -819,6 +819,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
819 | if (unlikely((ieee80211_is_data(hdr->frame_control) || | 819 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
820 | ieee80211_is_pspoll(hdr->frame_control)) && | 820 | ieee80211_is_pspoll(hdr->frame_control)) && |
821 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 821 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
822 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | ||
822 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 823 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
823 | if ((!ieee80211_has_fromds(hdr->frame_control) && | 824 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
824 | !ieee80211_has_tods(hdr->frame_control) && | 825 | !ieee80211_has_tods(hdr->frame_control) && |
@@ -845,7 +846,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
845 | int keyidx; | 846 | int keyidx; |
846 | int hdrlen; | 847 | int hdrlen; |
847 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 848 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
848 | struct ieee80211_key *stakey = NULL; | 849 | struct ieee80211_key *sta_ptk = NULL; |
849 | int mmie_keyidx = -1; | 850 | int mmie_keyidx = -1; |
850 | __le16 fc; | 851 | __le16 fc; |
851 | 852 | ||
@@ -887,15 +888,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
887 | rx->key = NULL; | 888 | rx->key = NULL; |
888 | 889 | ||
889 | if (rx->sta) | 890 | if (rx->sta) |
890 | stakey = rcu_dereference(rx->sta->key); | 891 | sta_ptk = rcu_dereference(rx->sta->ptk); |
891 | 892 | ||
892 | fc = hdr->frame_control; | 893 | fc = hdr->frame_control; |
893 | 894 | ||
894 | if (!ieee80211_has_protected(fc)) | 895 | if (!ieee80211_has_protected(fc)) |
895 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | 896 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); |
896 | 897 | ||
897 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 898 | if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) { |
898 | rx->key = stakey; | 899 | rx->key = sta_ptk; |
899 | if ((status->flag & RX_FLAG_DECRYPTED) && | 900 | if ((status->flag & RX_FLAG_DECRYPTED) && |
900 | (status->flag & RX_FLAG_IV_STRIPPED)) | 901 | (status->flag & RX_FLAG_IV_STRIPPED)) |
901 | return RX_CONTINUE; | 902 | return RX_CONTINUE; |
@@ -911,7 +912,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
911 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | 912 | if (mmie_keyidx < NUM_DEFAULT_KEYS || |
912 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | 913 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
913 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | 914 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ |
914 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | 915 | if (rx->sta) |
916 | rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); | ||
917 | if (!rx->key) | ||
918 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
915 | } else if (!ieee80211_has_protected(fc)) { | 919 | } else if (!ieee80211_has_protected(fc)) { |
916 | /* | 920 | /* |
917 | * The frame was not protected, so skip decryption. However, we | 921 | * The frame was not protected, so skip decryption. However, we |
@@ -954,17 +958,25 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
954 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | 958 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); |
955 | keyidx = keyid >> 6; | 959 | keyidx = keyid >> 6; |
956 | 960 | ||
957 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 961 | /* check per-station GTK first, if multicast packet */ |
962 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) | ||
963 | rx->key = rcu_dereference(rx->sta->gtk[keyidx]); | ||
958 | 964 | ||
959 | /* | 965 | /* if not found, try default key */ |
960 | * RSNA-protected unicast frames should always be sent with | 966 | if (!rx->key) { |
961 | * pairwise or station-to-station keys, but for WEP we allow | 967 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
962 | * using a key index as well. | 968 | |
963 | */ | 969 | /* |
964 | if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | 970 | * RSNA-protected unicast frames should always be |
965 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | 971 | * sent with pairwise or station-to-station keys, |
966 | !is_multicast_ether_addr(hdr->addr1)) | 972 | * but for WEP we allow using a key index as well. |
967 | rx->key = NULL; | 973 | */ |
974 | if (rx->key && | ||
975 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
976 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
977 | !is_multicast_ether_addr(hdr->addr1)) | ||
978 | rx->key = NULL; | ||
979 | } | ||
968 | } | 980 | } |
969 | 981 | ||
970 | if (rx->key) { | 982 | if (rx->key) { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5171a9581631..fb274db77e3c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -249,12 +249,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
249 | return true; | 249 | return true; |
250 | } | 250 | } |
251 | 251 | ||
252 | static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 252 | static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, |
253 | bool was_hw_scan) | ||
253 | { | 254 | { |
254 | struct ieee80211_local *local = hw_to_local(hw); | 255 | struct ieee80211_local *local = hw_to_local(hw); |
255 | bool was_hw_scan; | ||
256 | 256 | ||
257 | mutex_lock(&local->mtx); | 257 | lockdep_assert_held(&local->mtx); |
258 | 258 | ||
259 | /* | 259 | /* |
260 | * It's ok to abort a not-yet-running scan (that | 260 | * It's ok to abort a not-yet-running scan (that |
@@ -265,17 +265,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
265 | if (WARN_ON(!local->scanning && !aborted)) | 265 | if (WARN_ON(!local->scanning && !aborted)) |
266 | aborted = true; | 266 | aborted = true; |
267 | 267 | ||
268 | if (WARN_ON(!local->scan_req)) { | 268 | if (WARN_ON(!local->scan_req)) |
269 | mutex_unlock(&local->mtx); | 269 | return false; |
270 | return; | ||
271 | } | ||
272 | 270 | ||
273 | was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
274 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 271 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
275 | ieee80211_queue_delayed_work(&local->hw, | 272 | int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); |
276 | &local->scan_work, 0); | 273 | if (rc == 0) |
277 | mutex_unlock(&local->mtx); | 274 | return false; |
278 | return; | ||
279 | } | 275 | } |
280 | 276 | ||
281 | kfree(local->hw_scan_req); | 277 | kfree(local->hw_scan_req); |
@@ -289,23 +285,25 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
289 | local->scanning = 0; | 285 | local->scanning = 0; |
290 | local->scan_channel = NULL; | 286 | local->scan_channel = NULL; |
291 | 287 | ||
292 | /* we only have to protect scan_req and hw/sw scan */ | 288 | return true; |
293 | mutex_unlock(&local->mtx); | 289 | } |
294 | |||
295 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
296 | if (was_hw_scan) | ||
297 | goto done; | ||
298 | |||
299 | ieee80211_configure_filter(local); | ||
300 | 290 | ||
301 | drv_sw_scan_complete(local); | 291 | static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw, |
292 | bool was_hw_scan) | ||
293 | { | ||
294 | struct ieee80211_local *local = hw_to_local(hw); | ||
302 | 295 | ||
303 | ieee80211_offchannel_return(local, true); | 296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
297 | if (!was_hw_scan) { | ||
298 | ieee80211_configure_filter(local); | ||
299 | drv_sw_scan_complete(local); | ||
300 | ieee80211_offchannel_return(local, true); | ||
301 | } | ||
304 | 302 | ||
305 | done: | ||
306 | mutex_lock(&local->mtx); | 303 | mutex_lock(&local->mtx); |
307 | ieee80211_recalc_idle(local); | 304 | ieee80211_recalc_idle(local); |
308 | mutex_unlock(&local->mtx); | 305 | mutex_unlock(&local->mtx); |
306 | |||
309 | ieee80211_mlme_notify_scan_completed(local); | 307 | ieee80211_mlme_notify_scan_completed(local); |
310 | ieee80211_ibss_notify_scan_completed(local); | 308 | ieee80211_ibss_notify_scan_completed(local); |
311 | ieee80211_mesh_notify_scan_completed(local); | 309 | ieee80211_mesh_notify_scan_completed(local); |
@@ -366,6 +364,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
366 | struct ieee80211_local *local = sdata->local; | 364 | struct ieee80211_local *local = sdata->local; |
367 | int rc; | 365 | int rc; |
368 | 366 | ||
367 | lockdep_assert_held(&local->mtx); | ||
368 | |||
369 | if (local->scan_req) | 369 | if (local->scan_req) |
370 | return -EBUSY; | 370 | return -EBUSY; |
371 | 371 | ||
@@ -447,8 +447,8 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | |||
447 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | 447 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; |
448 | } | 448 | } |
449 | 449 | ||
450 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | 450 | static void ieee80211_scan_state_decision(struct ieee80211_local *local, |
451 | unsigned long *next_delay) | 451 | unsigned long *next_delay) |
452 | { | 452 | { |
453 | bool associated = false; | 453 | bool associated = false; |
454 | bool tx_empty = true; | 454 | bool tx_empty = true; |
@@ -458,12 +458,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
458 | struct ieee80211_sub_if_data *sdata; | 458 | struct ieee80211_sub_if_data *sdata; |
459 | struct ieee80211_channel *next_chan; | 459 | struct ieee80211_channel *next_chan; |
460 | 460 | ||
461 | /* if no more bands/channels left, complete scan and advance to the idle state */ | ||
462 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
463 | __ieee80211_scan_completed(&local->hw, false); | ||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | /* | 461 | /* |
468 | * check if at least one STA interface is associated, | 462 | * check if at least one STA interface is associated, |
469 | * check if at least one STA interface has pending tx frames | 463 | * check if at least one STA interface has pending tx frames |
@@ -535,7 +529,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
535 | } | 529 | } |
536 | 530 | ||
537 | *next_delay = 0; | 531 | *next_delay = 0; |
538 | return 0; | ||
539 | } | 532 | } |
540 | 533 | ||
541 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 534 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
@@ -651,28 +644,17 @@ void ieee80211_scan_work(struct work_struct *work) | |||
651 | container_of(work, struct ieee80211_local, scan_work.work); | 644 | container_of(work, struct ieee80211_local, scan_work.work); |
652 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 645 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
653 | unsigned long next_delay = 0; | 646 | unsigned long next_delay = 0; |
647 | bool aborted, hw_scan, finish; | ||
654 | 648 | ||
655 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { | 649 | mutex_lock(&local->mtx); |
656 | bool aborted; | ||
657 | 650 | ||
651 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { | ||
658 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); | 652 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); |
659 | __ieee80211_scan_completed(&local->hw, aborted); | 653 | goto out_complete; |
660 | return; | ||
661 | } | ||
662 | |||
663 | mutex_lock(&local->mtx); | ||
664 | if (!sdata || !local->scan_req) { | ||
665 | mutex_unlock(&local->mtx); | ||
666 | return; | ||
667 | } | 654 | } |
668 | 655 | ||
669 | if (local->hw_scan_req) { | 656 | if (!sdata || !local->scan_req) |
670 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 657 | goto out; |
671 | mutex_unlock(&local->mtx); | ||
672 | if (rc) | ||
673 | __ieee80211_scan_completed(&local->hw, true); | ||
674 | return; | ||
675 | } | ||
676 | 658 | ||
677 | if (local->scan_req && !local->scanning) { | 659 | if (local->scan_req && !local->scanning) { |
678 | struct cfg80211_scan_request *req = local->scan_req; | 660 | struct cfg80211_scan_request *req = local->scan_req; |
@@ -682,21 +664,21 @@ void ieee80211_scan_work(struct work_struct *work) | |||
682 | local->scan_sdata = NULL; | 664 | local->scan_sdata = NULL; |
683 | 665 | ||
684 | rc = __ieee80211_start_scan(sdata, req); | 666 | rc = __ieee80211_start_scan(sdata, req); |
685 | mutex_unlock(&local->mtx); | 667 | if (rc) { |
686 | 668 | /* need to complete scan in cfg80211 */ | |
687 | if (rc) | 669 | local->scan_req = req; |
688 | __ieee80211_scan_completed(&local->hw, true); | 670 | aborted = true; |
689 | return; | 671 | goto out_complete; |
672 | } else | ||
673 | goto out; | ||
690 | } | 674 | } |
691 | 675 | ||
692 | mutex_unlock(&local->mtx); | ||
693 | |||
694 | /* | 676 | /* |
695 | * Avoid re-scheduling when the sdata is going away. | 677 | * Avoid re-scheduling when the sdata is going away. |
696 | */ | 678 | */ |
697 | if (!ieee80211_sdata_running(sdata)) { | 679 | if (!ieee80211_sdata_running(sdata)) { |
698 | __ieee80211_scan_completed(&local->hw, true); | 680 | aborted = true; |
699 | return; | 681 | goto out_complete; |
700 | } | 682 | } |
701 | 683 | ||
702 | /* | 684 | /* |
@@ -706,8 +688,12 @@ void ieee80211_scan_work(struct work_struct *work) | |||
706 | do { | 688 | do { |
707 | switch (local->next_scan_state) { | 689 | switch (local->next_scan_state) { |
708 | case SCAN_DECISION: | 690 | case SCAN_DECISION: |
709 | if (ieee80211_scan_state_decision(local, &next_delay)) | 691 | /* if no more bands/channels left, complete scan */ |
710 | return; | 692 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
693 | aborted = false; | ||
694 | goto out_complete; | ||
695 | } | ||
696 | ieee80211_scan_state_decision(local, &next_delay); | ||
711 | break; | 697 | break; |
712 | case SCAN_SET_CHANNEL: | 698 | case SCAN_SET_CHANNEL: |
713 | ieee80211_scan_state_set_channel(local, &next_delay); | 699 | ieee80211_scan_state_set_channel(local, &next_delay); |
@@ -725,6 +711,19 @@ void ieee80211_scan_work(struct work_struct *work) | |||
725 | } while (next_delay == 0); | 711 | } while (next_delay == 0); |
726 | 712 | ||
727 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); | 713 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); |
714 | mutex_unlock(&local->mtx); | ||
715 | return; | ||
716 | |||
717 | out_complete: | ||
718 | hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
719 | finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan); | ||
720 | mutex_unlock(&local->mtx); | ||
721 | if (finish) | ||
722 | __ieee80211_scan_completed_finish(&local->hw, hw_scan); | ||
723 | return; | ||
724 | |||
725 | out: | ||
726 | mutex_unlock(&local->mtx); | ||
728 | } | 727 | } |
729 | 728 | ||
730 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 729 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
@@ -786,21 +785,40 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
786 | return ret; | 785 | return ret; |
787 | } | 786 | } |
788 | 787 | ||
788 | /* | ||
789 | * Only call this function when a scan can't be queued -- under RTNL. | ||
790 | */ | ||
789 | void ieee80211_scan_cancel(struct ieee80211_local *local) | 791 | void ieee80211_scan_cancel(struct ieee80211_local *local) |
790 | { | 792 | { |
791 | bool abortscan; | 793 | bool abortscan; |
792 | 794 | bool finish = false; | |
793 | cancel_delayed_work_sync(&local->scan_work); | ||
794 | 795 | ||
795 | /* | 796 | /* |
796 | * Only call this function when a scan can't be | 797 | * We are only canceling software scan, or deferred scan that was not |
797 | * queued -- mostly at suspend under RTNL. | 798 | * yet really started (see __ieee80211_start_scan ). |
799 | * | ||
800 | * Regarding hardware scan: | ||
801 | * - we can not call __ieee80211_scan_completed() as when | ||
802 | * SCAN_HW_SCANNING bit is set this function change | ||
803 | * local->hw_scan_req to operate on 5G band, what race with | ||
804 | * driver which can use local->hw_scan_req | ||
805 | * | ||
806 | * - we can not cancel scan_work since driver can schedule it | ||
807 | * by ieee80211_scan_completed(..., true) to finish scan | ||
808 | * | ||
809 | * Hence low lever driver is responsible for canceling HW scan. | ||
798 | */ | 810 | */ |
811 | |||
799 | mutex_lock(&local->mtx); | 812 | mutex_lock(&local->mtx); |
800 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 813 | abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning); |
801 | (!local->scanning && local->scan_req); | 814 | if (abortscan) |
815 | finish = __ieee80211_scan_completed(&local->hw, true, false); | ||
802 | mutex_unlock(&local->mtx); | 816 | mutex_unlock(&local->mtx); |
803 | 817 | ||
804 | if (abortscan) | 818 | if (abortscan) { |
805 | __ieee80211_scan_completed(&local->hw, true); | 819 | /* The scan is canceled, but stop work from being pending */ |
820 | cancel_delayed_work_sync(&local->scan_work); | ||
821 | } | ||
822 | if (finish) | ||
823 | __ieee80211_scan_completed_finish(&local->hw, false); | ||
806 | } | 824 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ca2cba9cea87..6d8f897d8763 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -616,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
616 | struct ieee80211_sub_if_data *sdata; | 616 | struct ieee80211_sub_if_data *sdata; |
617 | struct sk_buff *skb; | 617 | struct sk_buff *skb; |
618 | unsigned long flags; | 618 | unsigned long flags; |
619 | int ret; | 619 | int ret, i; |
620 | 620 | ||
621 | might_sleep(); | 621 | might_sleep(); |
622 | 622 | ||
@@ -633,7 +633,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
633 | * will be sufficient. | 633 | * will be sufficient. |
634 | */ | 634 | */ |
635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
636 | ieee80211_sta_tear_down_BA_sessions(sta); | 636 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
637 | 637 | ||
638 | spin_lock_irqsave(&local->sta_lock, flags); | 638 | spin_lock_irqsave(&local->sta_lock, flags); |
639 | ret = sta_info_hash_del(local, sta); | 639 | ret = sta_info_hash_del(local, sta); |
@@ -644,10 +644,10 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
644 | if (ret) | 644 | if (ret) |
645 | return ret; | 645 | return ret; |
646 | 646 | ||
647 | if (sta->key) { | 647 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
648 | ieee80211_key_free(local, sta->key); | 648 | ieee80211_key_free(local, sta->gtk[i]); |
649 | WARN_ON(sta->key); | 649 | if (sta->ptk) |
650 | } | 650 | ieee80211_key_free(local, sta->ptk); |
651 | 651 | ||
652 | sta->dead = true; | 652 | sta->dead = true; |
653 | 653 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 810c5ce98316..9265acadef32 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -79,6 +79,7 @@ enum ieee80211_sta_info_flags { | |||
79 | * @dialog_token: dialog token for aggregation session | 79 | * @dialog_token: dialog token for aggregation session |
80 | * @state: session state (see above) | 80 | * @state: session state (see above) |
81 | * @stop_initiator: initiator of a session stop | 81 | * @stop_initiator: initiator of a session stop |
82 | * @tx_stop: TX DelBA frame when stopping | ||
82 | * | 83 | * |
83 | * This structure is protected by RCU and the per-station | 84 | * This structure is protected by RCU and the per-station |
84 | * spinlock. Assignments to the array holding it must hold | 85 | * spinlock. Assignments to the array holding it must hold |
@@ -95,6 +96,7 @@ struct tid_ampdu_tx { | |||
95 | unsigned long state; | 96 | unsigned long state; |
96 | u8 dialog_token; | 97 | u8 dialog_token; |
97 | u8 stop_initiator; | 98 | u8 stop_initiator; |
99 | bool tx_stop; | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | /** | 102 | /** |
@@ -197,7 +199,8 @@ enum plink_state { | |||
197 | * @hnext: hash table linked list pointer | 199 | * @hnext: hash table linked list pointer |
198 | * @local: pointer to the global information | 200 | * @local: pointer to the global information |
199 | * @sdata: virtual interface this station belongs to | 201 | * @sdata: virtual interface this station belongs to |
200 | * @key: peer key negotiated with this station, if any | 202 | * @ptk: peer key negotiated with this station, if any |
203 | * @gtk: group keys negotiated with this station, if any | ||
201 | * @rate_ctrl: rate control algorithm reference | 204 | * @rate_ctrl: rate control algorithm reference |
202 | * @rate_ctrl_priv: rate control private per-STA pointer | 205 | * @rate_ctrl_priv: rate control private per-STA pointer |
203 | * @last_tx_rate: rate used for last transmit, to report to userspace as | 206 | * @last_tx_rate: rate used for last transmit, to report to userspace as |
@@ -252,7 +255,8 @@ struct sta_info { | |||
252 | struct sta_info *hnext; | 255 | struct sta_info *hnext; |
253 | struct ieee80211_local *local; | 256 | struct ieee80211_local *local; |
254 | struct ieee80211_sub_if_data *sdata; | 257 | struct ieee80211_sub_if_data *sdata; |
255 | struct ieee80211_key *key; | 258 | struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
259 | struct ieee80211_key *ptk; | ||
256 | struct rate_control_ref *rate_ctrl; | 260 | struct rate_control_ref *rate_ctrl; |
257 | void *rate_ctrl_priv; | 261 | void *rate_ctrl_priv; |
258 | spinlock_t lock; | 262 | spinlock_t lock; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index dd85006c4fe8..3153c19893b8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -176,7 +176,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
176 | 176 | ||
177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
178 | /* the HW cannot have attempted that rate */ | 178 | /* the HW cannot have attempted that rate */ |
179 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_report_rates) { |
180 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
181 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
182 | } else if (info->status.rates[i].idx >= 0) { | 182 | } else if (info->status.rates[i].idx >= 0) { |
@@ -377,7 +377,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
377 | skb2 = skb_clone(skb, GFP_ATOMIC); | 377 | skb2 = skb_clone(skb, GFP_ATOMIC); |
378 | if (skb2) { | 378 | if (skb2) { |
379 | skb2->dev = prev_dev; | 379 | skb2->dev = prev_dev; |
380 | netif_receive_skb(skb2); | 380 | netif_rx(skb2); |
381 | } | 381 | } |
382 | } | 382 | } |
383 | 383 | ||
@@ -386,7 +386,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
386 | } | 386 | } |
387 | if (prev_dev) { | 387 | if (prev_dev) { |
388 | skb->dev = prev_dev; | 388 | skb->dev = prev_dev; |
389 | netif_receive_skb(skb); | 389 | netif_rx(skb); |
390 | skb = NULL; | 390 | skb = NULL; |
391 | } | 391 | } |
392 | rcu_read_unlock(); | 392 | rcu_read_unlock(); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e1733dcb58a7..96c594309506 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -273,6 +273,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
273 | */ | 273 | */ |
274 | return TX_DROP; | 274 | return TX_DROP; |
275 | 275 | ||
276 | if (tx->sdata->vif.type == NL80211_IFTYPE_WDS) | ||
277 | return TX_CONTINUE; | ||
278 | |||
276 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 279 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
277 | return TX_CONTINUE; | 280 | return TX_CONTINUE; |
278 | 281 | ||
@@ -529,7 +532,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
529 | 532 | ||
530 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) | 533 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) |
531 | tx->key = NULL; | 534 | tx->key = NULL; |
532 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 535 | else if (tx->sta && (key = rcu_dereference(tx->sta->ptk))) |
533 | tx->key = key; | 536 | tx->key = key; |
534 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 537 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
535 | is_multicast_ether_addr(hdr->addr1) && | 538 | is_multicast_ether_addr(hdr->addr1) && |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index aba025d748e9..0b6fc92bc0d7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1221,7 +1221,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1221 | mutex_lock(&local->sta_mtx); | 1221 | mutex_lock(&local->sta_mtx); |
1222 | 1222 | ||
1223 | list_for_each_entry(sta, &local->sta_list, list) { | 1223 | list_for_each_entry(sta, &local->sta_list, list) { |
1224 | ieee80211_sta_tear_down_BA_sessions(sta); | 1224 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
1225 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); | 1225 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); |
1226 | } | 1226 | } |
1227 | 1227 | ||
@@ -1297,16 +1297,12 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | |||
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | /* must hold iflist_mtx */ | 1299 | /* must hold iflist_mtx */ |
1300 | void ieee80211_recalc_smps(struct ieee80211_local *local, | 1300 | void ieee80211_recalc_smps(struct ieee80211_local *local) |
1301 | struct ieee80211_sub_if_data *forsdata) | ||
1302 | { | 1301 | { |
1303 | struct ieee80211_sub_if_data *sdata; | 1302 | struct ieee80211_sub_if_data *sdata; |
1304 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | 1303 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; |
1305 | int count = 0; | 1304 | int count = 0; |
1306 | 1305 | ||
1307 | if (forsdata) | ||
1308 | lockdep_assert_held(&forsdata->u.mgd.mtx); | ||
1309 | |||
1310 | lockdep_assert_held(&local->iflist_mtx); | 1306 | lockdep_assert_held(&local->iflist_mtx); |
1311 | 1307 | ||
1312 | /* | 1308 | /* |
@@ -1324,18 +1320,8 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1324 | continue; | 1320 | continue; |
1325 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1321 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1326 | goto set; | 1322 | goto set; |
1327 | if (sdata != forsdata) { | 1323 | |
1328 | /* | 1324 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); |
1329 | * This nested is ok -- we are holding the iflist_mtx | ||
1330 | * so can't get here twice or so. But it's required | ||
1331 | * since normally we acquire it first and then the | ||
1332 | * iflist_mtx. | ||
1333 | */ | ||
1334 | mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); | ||
1335 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1336 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1337 | } else | ||
1338 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1339 | 1325 | ||
1340 | if (count > 1) { | 1326 | if (count > 1) { |
1341 | smps_mode = IEEE80211_SMPS_OFF; | 1327 | smps_mode = IEEE80211_SMPS_OFF; |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 26ed3e8587c2..1781d99145e2 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -547,8 +547,20 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
547 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; | 547 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; |
548 | info.attrs = family->attrbuf; | 548 | info.attrs = family->attrbuf; |
549 | genl_info_net_set(&info, net); | 549 | genl_info_net_set(&info, net); |
550 | memset(&info.user_ptr, 0, sizeof(info.user_ptr)); | ||
550 | 551 | ||
551 | return ops->doit(skb, &info); | 552 | if (family->pre_doit) { |
553 | err = family->pre_doit(ops, skb, &info); | ||
554 | if (err) | ||
555 | return err; | ||
556 | } | ||
557 | |||
558 | err = ops->doit(skb, &info); | ||
559 | |||
560 | if (family->post_doit) | ||
561 | family->post_doit(ops, skb, &info); | ||
562 | |||
563 | return err; | ||
552 | } | 564 | } |
553 | 565 | ||
554 | static void genl_rcv(struct sk_buff *skb) | 566 | static void genl_rcv(struct sk_buff *skb) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 9c21ebf9780e..1684ad91763c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -178,26 +178,10 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
178 | char *newname) | 178 | char *newname) |
179 | { | 179 | { |
180 | struct cfg80211_registered_device *rdev2; | 180 | struct cfg80211_registered_device *rdev2; |
181 | int wiphy_idx, taken = -1, result, digits; | 181 | int result; |
182 | 182 | ||
183 | assert_cfg80211_lock(); | 183 | assert_cfg80211_lock(); |
184 | 184 | ||
185 | /* prohibit calling the thing phy%d when %d is not its number */ | ||
186 | sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); | ||
187 | if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { | ||
188 | /* count number of places needed to print wiphy_idx */ | ||
189 | digits = 1; | ||
190 | while (wiphy_idx /= 10) | ||
191 | digits++; | ||
192 | /* | ||
193 | * deny the name if it is phy<idx> where <idx> is printed | ||
194 | * without leading zeroes. taken == strlen(newname) here | ||
195 | */ | ||
196 | if (taken == strlen(PHY_NAME) + digits) | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | |||
201 | /* Ignore nop renames */ | 185 | /* Ignore nop renames */ |
202 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) | 186 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) |
203 | return 0; | 187 | return 0; |
@@ -205,7 +189,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
205 | /* Ensure another device does not already have this name. */ | 189 | /* Ensure another device does not already have this name. */ |
206 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) | 190 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) |
207 | if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) | 191 | if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) |
208 | return -EINVAL; | 192 | return -EEXIST; |
209 | 193 | ||
210 | result = device_rename(&rdev->wiphy.dev, newname); | 194 | result = device_rename(&rdev->wiphy.dev, newname); |
211 | if (result) | 195 | if (result) |
@@ -320,9 +304,11 @@ static void cfg80211_event_work(struct work_struct *work) | |||
320 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | 304 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) |
321 | { | 305 | { |
322 | static int wiphy_counter; | 306 | static int wiphy_counter; |
323 | 307 | int i; | |
324 | struct cfg80211_registered_device *rdev; | 308 | struct cfg80211_registered_device *rdev, *rdev2; |
325 | int alloc_size; | 309 | int alloc_size; |
310 | char nname[IFNAMSIZ + 1]; | ||
311 | bool found = false; | ||
326 | 312 | ||
327 | WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); | 313 | WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); |
328 | WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); | 314 | WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); |
@@ -346,16 +332,36 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
346 | 332 | ||
347 | if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { | 333 | if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { |
348 | wiphy_counter--; | 334 | wiphy_counter--; |
335 | goto too_many_devs; | ||
336 | } | ||
337 | |||
338 | /* 64k wiphy devices is enough for anyone! */ | ||
339 | for (i = 0; i < 0xFFFF; i++) { | ||
340 | found = false; | ||
341 | snprintf(nname, sizeof(nname)-1, PHY_NAME "%d", i); | ||
342 | nname[sizeof(nname)-1] = 0; | ||
343 | list_for_each_entry(rdev2, &cfg80211_rdev_list, list) | ||
344 | if (strcmp(nname, dev_name(&rdev2->wiphy.dev)) == 0) { | ||
345 | found = true; | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | if (!found) | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | if (unlikely(found)) { | ||
354 | too_many_devs: | ||
349 | mutex_unlock(&cfg80211_mutex); | 355 | mutex_unlock(&cfg80211_mutex); |
350 | /* ugh, wrapped! */ | 356 | /* ugh, too many devices already! */ |
351 | kfree(rdev); | 357 | kfree(rdev); |
352 | return NULL; | 358 | return NULL; |
353 | } | 359 | } |
354 | 360 | ||
355 | mutex_unlock(&cfg80211_mutex); | ||
356 | |||
357 | /* give it a proper name */ | 361 | /* give it a proper name */ |
358 | dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); | 362 | dev_set_name(&rdev->wiphy.dev, "%s", nname); |
363 | |||
364 | mutex_unlock(&cfg80211_mutex); | ||
359 | 365 | ||
360 | mutex_init(&rdev->mtx); | 366 | mutex_init(&rdev->mtx); |
361 | mutex_init(&rdev->devlist_mtx); | 367 | mutex_init(&rdev->devlist_mtx); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 5d89310b3587..6583cca0e2ee 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -375,7 +375,7 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); | |||
375 | /* internal helpers */ | 375 | /* internal helpers */ |
376 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 376 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
377 | struct key_params *params, int key_idx, | 377 | struct key_params *params, int key_idx, |
378 | const u8 *mac_addr); | 378 | bool pairwise, const u8 *mac_addr); |
379 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 379 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
380 | size_t ie_len, u16 reason, bool from_ap); | 380 | size_t ie_len, u16 reason, bool from_ap); |
381 | void cfg80211_sme_scan_done(struct net_device *dev); | 381 | void cfg80211_sme_scan_done(struct net_device *dev); |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 8cb6e08373b9..f33fbb79437c 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -160,7 +160,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
160 | */ | 160 | */ |
161 | if (rdev->ops->del_key) | 161 | if (rdev->ops->del_key) |
162 | for (i = 0; i < 6; i++) | 162 | for (i = 0; i < 6; i++) |
163 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); | 163 | rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL); |
164 | 164 | ||
165 | if (wdev->current_bss) { | 165 | if (wdev->current_bss) { |
166 | cfg80211_unhold_bss(wdev->current_bss); | 166 | cfg80211_unhold_bss(wdev->current_bss); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 46f371160896..caf11a427507 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -876,21 +876,53 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
876 | 876 | ||
877 | if (ieee80211_is_action(mgmt->frame_control) && | 877 | if (ieee80211_is_action(mgmt->frame_control) && |
878 | mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | 878 | mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { |
879 | /* Verify that we are associated with the destination AP */ | 879 | int err = 0; |
880 | |||
880 | wdev_lock(wdev); | 881 | wdev_lock(wdev); |
881 | 882 | ||
882 | if (!wdev->current_bss || | 883 | switch (wdev->iftype) { |
883 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, | 884 | case NL80211_IFTYPE_ADHOC: |
884 | ETH_ALEN) != 0 || | 885 | case NL80211_IFTYPE_STATION: |
885 | ((wdev->iftype == NL80211_IFTYPE_STATION || | 886 | case NL80211_IFTYPE_P2P_CLIENT: |
886 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && | 887 | if (!wdev->current_bss) { |
887 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, | 888 | err = -ENOTCONN; |
888 | ETH_ALEN) != 0)) { | 889 | break; |
889 | wdev_unlock(wdev); | 890 | } |
890 | return -ENOTCONN; | 891 | |
891 | } | 892 | if (memcmp(wdev->current_bss->pub.bssid, |
893 | mgmt->bssid, ETH_ALEN)) { | ||
894 | err = -ENOTCONN; | ||
895 | break; | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * check for IBSS DA must be done by driver as | ||
900 | * cfg80211 doesn't track the stations | ||
901 | */ | ||
902 | if (wdev->iftype == NL80211_IFTYPE_ADHOC) | ||
903 | break; | ||
892 | 904 | ||
905 | /* for station, check that DA is the AP */ | ||
906 | if (memcmp(wdev->current_bss->pub.bssid, | ||
907 | mgmt->da, ETH_ALEN)) { | ||
908 | err = -ENOTCONN; | ||
909 | break; | ||
910 | } | ||
911 | break; | ||
912 | case NL80211_IFTYPE_AP: | ||
913 | case NL80211_IFTYPE_P2P_GO: | ||
914 | case NL80211_IFTYPE_AP_VLAN: | ||
915 | if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) | ||
916 | err = -EINVAL; | ||
917 | break; | ||
918 | default: | ||
919 | err = -EOPNOTSUPP; | ||
920 | break; | ||
921 | } | ||
893 | wdev_unlock(wdev); | 922 | wdev_unlock(wdev); |
923 | |||
924 | if (err) | ||
925 | return err; | ||
894 | } | 926 | } |
895 | 927 | ||
896 | if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) | 928 | if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9c84825803ce..882dc921103b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -23,6 +23,11 @@ | |||
23 | #include "nl80211.h" | 23 | #include "nl80211.h" |
24 | #include "reg.h" | 24 | #include "reg.h" |
25 | 25 | ||
26 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | ||
27 | struct genl_info *info); | ||
28 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | ||
29 | struct genl_info *info); | ||
30 | |||
26 | /* the netlink family */ | 31 | /* the netlink family */ |
27 | static struct genl_family nl80211_fam = { | 32 | static struct genl_family nl80211_fam = { |
28 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ | 33 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ |
@@ -31,6 +36,8 @@ static struct genl_family nl80211_fam = { | |||
31 | .version = 1, /* no particular meaning now */ | 36 | .version = 1, /* no particular meaning now */ |
32 | .maxattr = NL80211_ATTR_MAX, | 37 | .maxattr = NL80211_ATTR_MAX, |
33 | .netnsok = true, | 38 | .netnsok = true, |
39 | .pre_doit = nl80211_pre_doit, | ||
40 | .post_doit = nl80211_post_doit, | ||
34 | }; | 41 | }; |
35 | 42 | ||
36 | /* internal helper: get rdev and dev */ | 43 | /* internal helper: get rdev and dev */ |
@@ -86,6 +93,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
86 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, | 93 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
87 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, | 94 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, |
88 | [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, | 95 | [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, |
96 | [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 }, | ||
89 | 97 | ||
90 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, | 98 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
91 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, | 99 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, |
@@ -161,7 +169,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
161 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | 169 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, |
162 | }; | 170 | }; |
163 | 171 | ||
164 | /* policy for the attributes */ | 172 | /* policy for the key attributes */ |
165 | static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | 173 | static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { |
166 | [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, | 174 | [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, |
167 | [NL80211_KEY_IDX] = { .type = NLA_U8 }, | 175 | [NL80211_KEY_IDX] = { .type = NLA_U8 }, |
@@ -169,6 +177,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | |||
169 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, | 177 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, |
170 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | 178 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
171 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | 179 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, |
180 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, | ||
172 | }; | 181 | }; |
173 | 182 | ||
174 | /* ifidx get helper */ | 183 | /* ifidx get helper */ |
@@ -191,6 +200,47 @@ static int nl80211_get_ifidx(struct netlink_callback *cb) | |||
191 | return res; | 200 | return res; |
192 | } | 201 | } |
193 | 202 | ||
203 | static int nl80211_prepare_netdev_dump(struct sk_buff *skb, | ||
204 | struct netlink_callback *cb, | ||
205 | struct cfg80211_registered_device **rdev, | ||
206 | struct net_device **dev) | ||
207 | { | ||
208 | int ifidx = cb->args[0]; | ||
209 | int err; | ||
210 | |||
211 | if (!ifidx) | ||
212 | ifidx = nl80211_get_ifidx(cb); | ||
213 | if (ifidx < 0) | ||
214 | return ifidx; | ||
215 | |||
216 | cb->args[0] = ifidx; | ||
217 | |||
218 | rtnl_lock(); | ||
219 | |||
220 | *dev = __dev_get_by_index(sock_net(skb->sk), ifidx); | ||
221 | if (!*dev) { | ||
222 | err = -ENODEV; | ||
223 | goto out_rtnl; | ||
224 | } | ||
225 | |||
226 | *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); | ||
227 | if (IS_ERR(dev)) { | ||
228 | err = PTR_ERR(dev); | ||
229 | goto out_rtnl; | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | out_rtnl: | ||
234 | rtnl_unlock(); | ||
235 | return err; | ||
236 | } | ||
237 | |||
238 | static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev) | ||
239 | { | ||
240 | cfg80211_unlock_rdev(rdev); | ||
241 | rtnl_unlock(); | ||
242 | } | ||
243 | |||
194 | /* IE validation */ | 244 | /* IE validation */ |
195 | static bool is_valid_ie_attr(const struct nlattr *attr) | 245 | static bool is_valid_ie_attr(const struct nlattr *attr) |
196 | { | 246 | { |
@@ -258,6 +308,7 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
258 | struct key_parse { | 308 | struct key_parse { |
259 | struct key_params p; | 309 | struct key_params p; |
260 | int idx; | 310 | int idx; |
311 | int type; | ||
261 | bool def, defmgmt; | 312 | bool def, defmgmt; |
262 | }; | 313 | }; |
263 | 314 | ||
@@ -288,6 +339,12 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
288 | if (tb[NL80211_KEY_CIPHER]) | 339 | if (tb[NL80211_KEY_CIPHER]) |
289 | k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); | 340 | k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); |
290 | 341 | ||
342 | if (tb[NL80211_KEY_TYPE]) { | ||
343 | k->type = nla_get_u32(tb[NL80211_KEY_TYPE]); | ||
344 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
291 | return 0; | 348 | return 0; |
292 | } | 349 | } |
293 | 350 | ||
@@ -312,6 +369,12 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) | |||
312 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; | 369 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; |
313 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; | 370 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; |
314 | 371 | ||
372 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | ||
373 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); | ||
374 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
315 | return 0; | 378 | return 0; |
316 | } | 379 | } |
317 | 380 | ||
@@ -321,6 +384,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | |||
321 | 384 | ||
322 | memset(k, 0, sizeof(*k)); | 385 | memset(k, 0, sizeof(*k)); |
323 | k->idx = -1; | 386 | k->idx = -1; |
387 | k->type = -1; | ||
324 | 388 | ||
325 | if (info->attrs[NL80211_ATTR_KEY]) | 389 | if (info->attrs[NL80211_ATTR_KEY]) |
326 | err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); | 390 | err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); |
@@ -385,7 +449,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | |||
385 | } else if (parse.defmgmt) | 449 | } else if (parse.defmgmt) |
386 | goto error; | 450 | goto error; |
387 | err = cfg80211_validate_key_settings(rdev, &parse.p, | 451 | err = cfg80211_validate_key_settings(rdev, &parse.p, |
388 | parse.idx, NULL); | 452 | parse.idx, false, NULL); |
389 | if (err) | 453 | if (err) |
390 | goto error; | 454 | goto error; |
391 | result->params[parse.idx].cipher = parse.p.cipher; | 455 | result->params[parse.idx].cipher = parse.p.cipher; |
@@ -404,9 +468,6 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
404 | { | 468 | { |
405 | ASSERT_WDEV_LOCK(wdev); | 469 | ASSERT_WDEV_LOCK(wdev); |
406 | 470 | ||
407 | if (!netif_running(wdev->netdev)) | ||
408 | return -ENETDOWN; | ||
409 | |||
410 | switch (wdev->iftype) { | 471 | switch (wdev->iftype) { |
411 | case NL80211_IFTYPE_AP: | 472 | case NL80211_IFTYPE_AP: |
412 | case NL80211_IFTYPE_AP_VLAN: | 473 | case NL80211_IFTYPE_AP_VLAN: |
@@ -471,6 +532,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
471 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | 532 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, |
472 | dev->wiphy.max_scan_ie_len); | 533 | dev->wiphy.max_scan_ie_len); |
473 | 534 | ||
535 | if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) | ||
536 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); | ||
537 | |||
474 | NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, | 538 | NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, |
475 | sizeof(u32) * dev->wiphy.n_cipher_suites, | 539 | sizeof(u32) * dev->wiphy.n_cipher_suites, |
476 | dev->wiphy.cipher_suites); | 540 | dev->wiphy.cipher_suites); |
@@ -603,6 +667,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
603 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 667 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
604 | } | 668 | } |
605 | CMD(set_channel, SET_CHANNEL); | 669 | CMD(set_channel, SET_CHANNEL); |
670 | CMD(set_wds_peer, SET_WDS_PEER); | ||
606 | 671 | ||
607 | #undef CMD | 672 | #undef CMD |
608 | 673 | ||
@@ -703,28 +768,18 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
703 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | 768 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) |
704 | { | 769 | { |
705 | struct sk_buff *msg; | 770 | struct sk_buff *msg; |
706 | struct cfg80211_registered_device *dev; | 771 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
707 | |||
708 | dev = cfg80211_get_dev_from_info(info); | ||
709 | if (IS_ERR(dev)) | ||
710 | return PTR_ERR(dev); | ||
711 | 772 | ||
712 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 773 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
713 | if (!msg) | 774 | if (!msg) |
714 | goto out_err; | 775 | return -ENOMEM; |
715 | |||
716 | if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) | ||
717 | goto out_free; | ||
718 | 776 | ||
719 | cfg80211_unlock_rdev(dev); | 777 | if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) { |
778 | nlmsg_free(msg); | ||
779 | return -ENOBUFS; | ||
780 | } | ||
720 | 781 | ||
721 | return genlmsg_reply(msg, info); | 782 | return genlmsg_reply(msg, info); |
722 | |||
723 | out_free: | ||
724 | nlmsg_free(msg); | ||
725 | out_err: | ||
726 | cfg80211_unlock_rdev(dev); | ||
727 | return -ENOBUFS; | ||
728 | } | 783 | } |
729 | 784 | ||
730 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | 785 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { |
@@ -813,24 +868,36 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
813 | 868 | ||
814 | static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) | 869 | static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) |
815 | { | 870 | { |
816 | struct cfg80211_registered_device *rdev; | 871 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
817 | struct net_device *netdev; | 872 | struct net_device *netdev = info->user_ptr[1]; |
818 | int result; | ||
819 | 873 | ||
820 | rtnl_lock(); | 874 | return __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); |
875 | } | ||
821 | 876 | ||
822 | result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev); | 877 | static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) |
823 | if (result) | 878 | { |
824 | goto unlock; | 879 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
880 | struct net_device *dev = info->user_ptr[1]; | ||
881 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
882 | const u8 *bssid; | ||
825 | 883 | ||
826 | result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); | 884 | if (!info->attrs[NL80211_ATTR_MAC]) |
885 | return -EINVAL; | ||
827 | 886 | ||
828 | unlock: | 887 | if (netif_running(dev)) |
829 | rtnl_unlock(); | 888 | return -EBUSY; |
830 | 889 | ||
831 | return result; | 890 | if (!rdev->ops->set_wds_peer) |
891 | return -EOPNOTSUPP; | ||
892 | |||
893 | if (wdev->iftype != NL80211_IFTYPE_WDS) | ||
894 | return -EOPNOTSUPP; | ||
895 | |||
896 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
897 | return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid); | ||
832 | } | 898 | } |
833 | 899 | ||
900 | |||
834 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | 901 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) |
835 | { | 902 | { |
836 | struct cfg80211_registered_device *rdev; | 903 | struct cfg80211_registered_device *rdev; |
@@ -843,8 +910,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
843 | u32 frag_threshold = 0, rts_threshold = 0; | 910 | u32 frag_threshold = 0, rts_threshold = 0; |
844 | u8 coverage_class = 0; | 911 | u8 coverage_class = 0; |
845 | 912 | ||
846 | rtnl_lock(); | ||
847 | |||
848 | /* | 913 | /* |
849 | * Try to find the wiphy and netdev. Normally this | 914 | * Try to find the wiphy and netdev. Normally this |
850 | * function shouldn't need the netdev, but this is | 915 | * function shouldn't need the netdev, but this is |
@@ -871,8 +936,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
871 | rdev = __cfg80211_rdev_from_info(info); | 936 | rdev = __cfg80211_rdev_from_info(info); |
872 | if (IS_ERR(rdev)) { | 937 | if (IS_ERR(rdev)) { |
873 | mutex_unlock(&cfg80211_mutex); | 938 | mutex_unlock(&cfg80211_mutex); |
874 | result = PTR_ERR(rdev); | 939 | return PTR_ERR(rdev); |
875 | goto unlock; | ||
876 | } | 940 | } |
877 | wdev = NULL; | 941 | wdev = NULL; |
878 | netdev = NULL; | 942 | netdev = NULL; |
@@ -1054,8 +1118,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1054 | mutex_unlock(&rdev->mtx); | 1118 | mutex_unlock(&rdev->mtx); |
1055 | if (netdev) | 1119 | if (netdev) |
1056 | dev_put(netdev); | 1120 | dev_put(netdev); |
1057 | unlock: | ||
1058 | rtnl_unlock(); | ||
1059 | return result; | 1121 | return result; |
1060 | } | 1122 | } |
1061 | 1123 | ||
@@ -1135,33 +1197,20 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
1135 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | 1197 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) |
1136 | { | 1198 | { |
1137 | struct sk_buff *msg; | 1199 | struct sk_buff *msg; |
1138 | struct cfg80211_registered_device *dev; | 1200 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
1139 | struct net_device *netdev; | 1201 | struct net_device *netdev = info->user_ptr[1]; |
1140 | int err; | ||
1141 | |||
1142 | err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev); | ||
1143 | if (err) | ||
1144 | return err; | ||
1145 | 1202 | ||
1146 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1203 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
1147 | if (!msg) | 1204 | if (!msg) |
1148 | goto out_err; | 1205 | return -ENOMEM; |
1149 | 1206 | ||
1150 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, | 1207 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, |
1151 | dev, netdev) < 0) | 1208 | dev, netdev) < 0) { |
1152 | goto out_free; | 1209 | nlmsg_free(msg); |
1153 | 1210 | return -ENOBUFS; | |
1154 | dev_put(netdev); | 1211 | } |
1155 | cfg80211_unlock_rdev(dev); | ||
1156 | 1212 | ||
1157 | return genlmsg_reply(msg, info); | 1213 | return genlmsg_reply(msg, info); |
1158 | |||
1159 | out_free: | ||
1160 | nlmsg_free(msg); | ||
1161 | out_err: | ||
1162 | dev_put(netdev); | ||
1163 | cfg80211_unlock_rdev(dev); | ||
1164 | return -ENOBUFS; | ||
1165 | } | 1214 | } |
1166 | 1215 | ||
1167 | static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { | 1216 | static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { |
@@ -1221,39 +1270,29 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev, | |||
1221 | 1270 | ||
1222 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 1271 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) |
1223 | { | 1272 | { |
1224 | struct cfg80211_registered_device *rdev; | 1273 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1225 | struct vif_params params; | 1274 | struct vif_params params; |
1226 | int err; | 1275 | int err; |
1227 | enum nl80211_iftype otype, ntype; | 1276 | enum nl80211_iftype otype, ntype; |
1228 | struct net_device *dev; | 1277 | struct net_device *dev = info->user_ptr[1]; |
1229 | u32 _flags, *flags = NULL; | 1278 | u32 _flags, *flags = NULL; |
1230 | bool change = false; | 1279 | bool change = false; |
1231 | 1280 | ||
1232 | memset(¶ms, 0, sizeof(params)); | 1281 | memset(¶ms, 0, sizeof(params)); |
1233 | 1282 | ||
1234 | rtnl_lock(); | ||
1235 | |||
1236 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
1237 | if (err) | ||
1238 | goto unlock_rtnl; | ||
1239 | |||
1240 | otype = ntype = dev->ieee80211_ptr->iftype; | 1283 | otype = ntype = dev->ieee80211_ptr->iftype; |
1241 | 1284 | ||
1242 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | 1285 | if (info->attrs[NL80211_ATTR_IFTYPE]) { |
1243 | ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | 1286 | ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); |
1244 | if (otype != ntype) | 1287 | if (otype != ntype) |
1245 | change = true; | 1288 | change = true; |
1246 | if (ntype > NL80211_IFTYPE_MAX) { | 1289 | if (ntype > NL80211_IFTYPE_MAX) |
1247 | err = -EINVAL; | 1290 | return -EINVAL; |
1248 | goto unlock; | ||
1249 | } | ||
1250 | } | 1291 | } |
1251 | 1292 | ||
1252 | if (info->attrs[NL80211_ATTR_MESH_ID]) { | 1293 | if (info->attrs[NL80211_ATTR_MESH_ID]) { |
1253 | if (ntype != NL80211_IFTYPE_MESH_POINT) { | 1294 | if (ntype != NL80211_IFTYPE_MESH_POINT) |
1254 | err = -EINVAL; | 1295 | return -EINVAL; |
1255 | goto unlock; | ||
1256 | } | ||
1257 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 1296 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
1258 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 1297 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
1259 | change = true; | 1298 | change = true; |
@@ -1264,20 +1303,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
1264 | change = true; | 1303 | change = true; |
1265 | err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype); | 1304 | err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype); |
1266 | if (err) | 1305 | if (err) |
1267 | goto unlock; | 1306 | return err; |
1268 | } else { | 1307 | } else { |
1269 | params.use_4addr = -1; | 1308 | params.use_4addr = -1; |
1270 | } | 1309 | } |
1271 | 1310 | ||
1272 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | 1311 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { |
1273 | if (ntype != NL80211_IFTYPE_MONITOR) { | 1312 | if (ntype != NL80211_IFTYPE_MONITOR) |
1274 | err = -EINVAL; | 1313 | return -EINVAL; |
1275 | goto unlock; | ||
1276 | } | ||
1277 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | 1314 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], |
1278 | &_flags); | 1315 | &_flags); |
1279 | if (err) | 1316 | if (err) |
1280 | goto unlock; | 1317 | return err; |
1281 | 1318 | ||
1282 | flags = &_flags; | 1319 | flags = &_flags; |
1283 | change = true; | 1320 | change = true; |
@@ -1291,17 +1328,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
1291 | if (!err && params.use_4addr != -1) | 1328 | if (!err && params.use_4addr != -1) |
1292 | dev->ieee80211_ptr->use_4addr = params.use_4addr; | 1329 | dev->ieee80211_ptr->use_4addr = params.use_4addr; |
1293 | 1330 | ||
1294 | unlock: | ||
1295 | dev_put(dev); | ||
1296 | cfg80211_unlock_rdev(rdev); | ||
1297 | unlock_rtnl: | ||
1298 | rtnl_unlock(); | ||
1299 | return err; | 1331 | return err; |
1300 | } | 1332 | } |
1301 | 1333 | ||
1302 | static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | 1334 | static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) |
1303 | { | 1335 | { |
1304 | struct cfg80211_registered_device *rdev; | 1336 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1305 | struct vif_params params; | 1337 | struct vif_params params; |
1306 | int err; | 1338 | int err; |
1307 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 1339 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
@@ -1318,19 +1350,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
1318 | return -EINVAL; | 1350 | return -EINVAL; |
1319 | } | 1351 | } |
1320 | 1352 | ||
1321 | rtnl_lock(); | ||
1322 | |||
1323 | rdev = cfg80211_get_dev_from_info(info); | ||
1324 | if (IS_ERR(rdev)) { | ||
1325 | err = PTR_ERR(rdev); | ||
1326 | goto unlock_rtnl; | ||
1327 | } | ||
1328 | |||
1329 | if (!rdev->ops->add_virtual_intf || | 1353 | if (!rdev->ops->add_virtual_intf || |
1330 | !(rdev->wiphy.interface_modes & (1 << type))) { | 1354 | !(rdev->wiphy.interface_modes & (1 << type))) |
1331 | err = -EOPNOTSUPP; | 1355 | return -EOPNOTSUPP; |
1332 | goto unlock; | ||
1333 | } | ||
1334 | 1356 | ||
1335 | if (type == NL80211_IFTYPE_MESH_POINT && | 1357 | if (type == NL80211_IFTYPE_MESH_POINT && |
1336 | info->attrs[NL80211_ATTR_MESH_ID]) { | 1358 | info->attrs[NL80211_ATTR_MESH_ID]) { |
@@ -1342,7 +1364,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
1342 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); | 1364 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); |
1343 | err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); | 1365 | err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); |
1344 | if (err) | 1366 | if (err) |
1345 | goto unlock; | 1367 | return err; |
1346 | } | 1368 | } |
1347 | 1369 | ||
1348 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 1370 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
@@ -1352,38 +1374,18 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
1352 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 1374 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
1353 | type, err ? NULL : &flags, ¶ms); | 1375 | type, err ? NULL : &flags, ¶ms); |
1354 | 1376 | ||
1355 | unlock: | ||
1356 | cfg80211_unlock_rdev(rdev); | ||
1357 | unlock_rtnl: | ||
1358 | rtnl_unlock(); | ||
1359 | return err; | 1377 | return err; |
1360 | } | 1378 | } |
1361 | 1379 | ||
1362 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | 1380 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) |
1363 | { | 1381 | { |
1364 | struct cfg80211_registered_device *rdev; | 1382 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1365 | int err; | 1383 | struct net_device *dev = info->user_ptr[1]; |
1366 | struct net_device *dev; | ||
1367 | |||
1368 | rtnl_lock(); | ||
1369 | |||
1370 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
1371 | if (err) | ||
1372 | goto unlock_rtnl; | ||
1373 | 1384 | ||
1374 | if (!rdev->ops->del_virtual_intf) { | 1385 | if (!rdev->ops->del_virtual_intf) |
1375 | err = -EOPNOTSUPP; | 1386 | return -EOPNOTSUPP; |
1376 | goto out; | ||
1377 | } | ||
1378 | |||
1379 | err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev); | ||
1380 | 1387 | ||
1381 | out: | 1388 | return rdev->ops->del_virtual_intf(&rdev->wiphy, dev); |
1382 | cfg80211_unlock_rdev(rdev); | ||
1383 | dev_put(dev); | ||
1384 | unlock_rtnl: | ||
1385 | rtnl_unlock(); | ||
1386 | return err; | ||
1387 | } | 1389 | } |
1388 | 1390 | ||
1389 | struct get_key_cookie { | 1391 | struct get_key_cookie { |
@@ -1436,11 +1438,12 @@ static void get_key_callback(void *c, struct key_params *params) | |||
1436 | 1438 | ||
1437 | static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | 1439 | static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) |
1438 | { | 1440 | { |
1439 | struct cfg80211_registered_device *rdev; | 1441 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1440 | int err; | 1442 | int err; |
1441 | struct net_device *dev; | 1443 | struct net_device *dev = info->user_ptr[1]; |
1442 | u8 key_idx = 0; | 1444 | u8 key_idx = 0; |
1443 | u8 *mac_addr = NULL; | 1445 | const u8 *mac_addr = NULL; |
1446 | bool pairwise; | ||
1444 | struct get_key_cookie cookie = { | 1447 | struct get_key_cookie cookie = { |
1445 | .error = 0, | 1448 | .error = 0, |
1446 | }; | 1449 | }; |
@@ -1456,30 +1459,28 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1456 | if (info->attrs[NL80211_ATTR_MAC]) | 1459 | if (info->attrs[NL80211_ATTR_MAC]) |
1457 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1460 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1458 | 1461 | ||
1459 | rtnl_lock(); | 1462 | pairwise = !!mac_addr; |
1460 | 1463 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | |
1461 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | 1464 | u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); |
1462 | if (err) | 1465 | if (kt >= NUM_NL80211_KEYTYPES) |
1463 | goto unlock_rtnl; | 1466 | return -EINVAL; |
1464 | 1467 | if (kt != NL80211_KEYTYPE_GROUP && | |
1465 | if (!rdev->ops->get_key) { | 1468 | kt != NL80211_KEYTYPE_PAIRWISE) |
1466 | err = -EOPNOTSUPP; | 1469 | return -EINVAL; |
1467 | goto out; | 1470 | pairwise = kt == NL80211_KEYTYPE_PAIRWISE; |
1468 | } | 1471 | } |
1469 | 1472 | ||
1473 | if (!rdev->ops->get_key) | ||
1474 | return -EOPNOTSUPP; | ||
1475 | |||
1470 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1476 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
1471 | if (!msg) { | 1477 | if (!msg) |
1472 | err = -ENOMEM; | 1478 | return -ENOMEM; |
1473 | goto out; | ||
1474 | } | ||
1475 | 1479 | ||
1476 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 1480 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
1477 | NL80211_CMD_NEW_KEY); | 1481 | NL80211_CMD_NEW_KEY); |
1478 | 1482 | if (IS_ERR(hdr)) | |
1479 | if (IS_ERR(hdr)) { | 1483 | return PTR_ERR(hdr); |
1480 | err = PTR_ERR(hdr); | ||
1481 | goto free_msg; | ||
1482 | } | ||
1483 | 1484 | ||
1484 | cookie.msg = msg; | 1485 | cookie.msg = msg; |
1485 | cookie.idx = key_idx; | 1486 | cookie.idx = key_idx; |
@@ -1489,8 +1490,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1489 | if (mac_addr) | 1490 | if (mac_addr) |
1490 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | 1491 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
1491 | 1492 | ||
1492 | err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr, | 1493 | if (pairwise && mac_addr && |
1493 | &cookie, get_key_callback); | 1494 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) |
1495 | return -ENOENT; | ||
1496 | |||
1497 | err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise, | ||
1498 | mac_addr, &cookie, get_key_callback); | ||
1494 | 1499 | ||
1495 | if (err) | 1500 | if (err) |
1496 | goto free_msg; | 1501 | goto free_msg; |
@@ -1499,28 +1504,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1499 | goto nla_put_failure; | 1504 | goto nla_put_failure; |
1500 | 1505 | ||
1501 | genlmsg_end(msg, hdr); | 1506 | genlmsg_end(msg, hdr); |
1502 | err = genlmsg_reply(msg, info); | 1507 | return genlmsg_reply(msg, info); |
1503 | goto out; | ||
1504 | 1508 | ||
1505 | nla_put_failure: | 1509 | nla_put_failure: |
1506 | err = -ENOBUFS; | 1510 | err = -ENOBUFS; |
1507 | free_msg: | 1511 | free_msg: |
1508 | nlmsg_free(msg); | 1512 | nlmsg_free(msg); |
1509 | out: | ||
1510 | cfg80211_unlock_rdev(rdev); | ||
1511 | dev_put(dev); | ||
1512 | unlock_rtnl: | ||
1513 | rtnl_unlock(); | ||
1514 | |||
1515 | return err; | 1513 | return err; |
1516 | } | 1514 | } |
1517 | 1515 | ||
1518 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | 1516 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) |
1519 | { | 1517 | { |
1520 | struct cfg80211_registered_device *rdev; | 1518 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1521 | struct key_parse key; | 1519 | struct key_parse key; |
1522 | int err; | 1520 | int err; |
1523 | struct net_device *dev; | 1521 | struct net_device *dev = info->user_ptr[1]; |
1524 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | 1522 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, |
1525 | u8 key_index); | 1523 | u8 key_index); |
1526 | 1524 | ||
@@ -1535,21 +1533,13 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1535 | if (!key.def && !key.defmgmt) | 1533 | if (!key.def && !key.defmgmt) |
1536 | return -EINVAL; | 1534 | return -EINVAL; |
1537 | 1535 | ||
1538 | rtnl_lock(); | ||
1539 | |||
1540 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
1541 | if (err) | ||
1542 | goto unlock_rtnl; | ||
1543 | |||
1544 | if (key.def) | 1536 | if (key.def) |
1545 | func = rdev->ops->set_default_key; | 1537 | func = rdev->ops->set_default_key; |
1546 | else | 1538 | else |
1547 | func = rdev->ops->set_default_mgmt_key; | 1539 | func = rdev->ops->set_default_mgmt_key; |
1548 | 1540 | ||
1549 | if (!func) { | 1541 | if (!func) |
1550 | err = -EOPNOTSUPP; | 1542 | return -EOPNOTSUPP; |
1551 | goto out; | ||
1552 | } | ||
1553 | 1543 | ||
1554 | wdev_lock(dev->ieee80211_ptr); | 1544 | wdev_lock(dev->ieee80211_ptr); |
1555 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1545 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
@@ -1566,23 +1556,16 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1566 | #endif | 1556 | #endif |
1567 | wdev_unlock(dev->ieee80211_ptr); | 1557 | wdev_unlock(dev->ieee80211_ptr); |
1568 | 1558 | ||
1569 | out: | ||
1570 | cfg80211_unlock_rdev(rdev); | ||
1571 | dev_put(dev); | ||
1572 | |||
1573 | unlock_rtnl: | ||
1574 | rtnl_unlock(); | ||
1575 | |||
1576 | return err; | 1559 | return err; |
1577 | } | 1560 | } |
1578 | 1561 | ||
1579 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | 1562 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) |
1580 | { | 1563 | { |
1581 | struct cfg80211_registered_device *rdev; | 1564 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1582 | int err; | 1565 | int err; |
1583 | struct net_device *dev; | 1566 | struct net_device *dev = info->user_ptr[1]; |
1584 | struct key_parse key; | 1567 | struct key_parse key; |
1585 | u8 *mac_addr = NULL; | 1568 | const u8 *mac_addr = NULL; |
1586 | 1569 | ||
1587 | err = nl80211_parse_key(info, &key); | 1570 | err = nl80211_parse_key(info, &key); |
1588 | if (err) | 1571 | if (err) |
@@ -1594,43 +1577,42 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
1594 | if (info->attrs[NL80211_ATTR_MAC]) | 1577 | if (info->attrs[NL80211_ATTR_MAC]) |
1595 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1578 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1596 | 1579 | ||
1597 | rtnl_lock(); | 1580 | if (key.type == -1) { |
1581 | if (mac_addr) | ||
1582 | key.type = NL80211_KEYTYPE_PAIRWISE; | ||
1583 | else | ||
1584 | key.type = NL80211_KEYTYPE_GROUP; | ||
1585 | } | ||
1598 | 1586 | ||
1599 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | 1587 | /* for now */ |
1600 | if (err) | 1588 | if (key.type != NL80211_KEYTYPE_PAIRWISE && |
1601 | goto unlock_rtnl; | 1589 | key.type != NL80211_KEYTYPE_GROUP) |
1590 | return -EINVAL; | ||
1602 | 1591 | ||
1603 | if (!rdev->ops->add_key) { | 1592 | if (!rdev->ops->add_key) |
1604 | err = -EOPNOTSUPP; | 1593 | return -EOPNOTSUPP; |
1605 | goto out; | ||
1606 | } | ||
1607 | 1594 | ||
1608 | if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) { | 1595 | if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, |
1609 | err = -EINVAL; | 1596 | key.type == NL80211_KEYTYPE_PAIRWISE, |
1610 | goto out; | 1597 | mac_addr)) |
1611 | } | 1598 | return -EINVAL; |
1612 | 1599 | ||
1613 | wdev_lock(dev->ieee80211_ptr); | 1600 | wdev_lock(dev->ieee80211_ptr); |
1614 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1601 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
1615 | if (!err) | 1602 | if (!err) |
1616 | err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, | 1603 | err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, |
1604 | key.type == NL80211_KEYTYPE_PAIRWISE, | ||
1617 | mac_addr, &key.p); | 1605 | mac_addr, &key.p); |
1618 | wdev_unlock(dev->ieee80211_ptr); | 1606 | wdev_unlock(dev->ieee80211_ptr); |
1619 | 1607 | ||
1620 | out: | ||
1621 | cfg80211_unlock_rdev(rdev); | ||
1622 | dev_put(dev); | ||
1623 | unlock_rtnl: | ||
1624 | rtnl_unlock(); | ||
1625 | |||
1626 | return err; | 1608 | return err; |
1627 | } | 1609 | } |
1628 | 1610 | ||
1629 | static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | 1611 | static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) |
1630 | { | 1612 | { |
1631 | struct cfg80211_registered_device *rdev; | 1613 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1632 | int err; | 1614 | int err; |
1633 | struct net_device *dev; | 1615 | struct net_device *dev = info->user_ptr[1]; |
1634 | u8 *mac_addr = NULL; | 1616 | u8 *mac_addr = NULL; |
1635 | struct key_parse key; | 1617 | struct key_parse key; |
1636 | 1618 | ||
@@ -1641,21 +1623,32 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1641 | if (info->attrs[NL80211_ATTR_MAC]) | 1623 | if (info->attrs[NL80211_ATTR_MAC]) |
1642 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1624 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1643 | 1625 | ||
1644 | rtnl_lock(); | 1626 | if (key.type == -1) { |
1627 | if (mac_addr) | ||
1628 | key.type = NL80211_KEYTYPE_PAIRWISE; | ||
1629 | else | ||
1630 | key.type = NL80211_KEYTYPE_GROUP; | ||
1631 | } | ||
1645 | 1632 | ||
1646 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | 1633 | /* for now */ |
1647 | if (err) | 1634 | if (key.type != NL80211_KEYTYPE_PAIRWISE && |
1648 | goto unlock_rtnl; | 1635 | key.type != NL80211_KEYTYPE_GROUP) |
1636 | return -EINVAL; | ||
1649 | 1637 | ||
1650 | if (!rdev->ops->del_key) { | 1638 | if (!rdev->ops->del_key) |
1651 | err = -EOPNOTSUPP; | 1639 | return -EOPNOTSUPP; |
1652 | goto out; | ||
1653 | } | ||
1654 | 1640 | ||
1655 | wdev_lock(dev->ieee80211_ptr); | 1641 | wdev_lock(dev->ieee80211_ptr); |
1656 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1642 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
1643 | |||
1644 | if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && | ||
1645 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
1646 | err = -ENOENT; | ||
1647 | |||
1657 | if (!err) | 1648 | if (!err) |
1658 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); | 1649 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, |
1650 | key.type == NL80211_KEYTYPE_PAIRWISE, | ||
1651 | mac_addr); | ||
1659 | 1652 | ||
1660 | #ifdef CONFIG_CFG80211_WEXT | 1653 | #ifdef CONFIG_CFG80211_WEXT |
1661 | if (!err) { | 1654 | if (!err) { |
@@ -1667,13 +1660,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1667 | #endif | 1660 | #endif |
1668 | wdev_unlock(dev->ieee80211_ptr); | 1661 | wdev_unlock(dev->ieee80211_ptr); |
1669 | 1662 | ||
1670 | out: | ||
1671 | cfg80211_unlock_rdev(rdev); | ||
1672 | dev_put(dev); | ||
1673 | |||
1674 | unlock_rtnl: | ||
1675 | rtnl_unlock(); | ||
1676 | |||
1677 | return err; | 1663 | return err; |
1678 | } | 1664 | } |
1679 | 1665 | ||
@@ -1681,36 +1667,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1681 | { | 1667 | { |
1682 | int (*call)(struct wiphy *wiphy, struct net_device *dev, | 1668 | int (*call)(struct wiphy *wiphy, struct net_device *dev, |
1683 | struct beacon_parameters *info); | 1669 | struct beacon_parameters *info); |
1684 | struct cfg80211_registered_device *rdev; | 1670 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1685 | int err; | 1671 | struct net_device *dev = info->user_ptr[1]; |
1686 | struct net_device *dev; | ||
1687 | struct beacon_parameters params; | 1672 | struct beacon_parameters params; |
1688 | int haveinfo = 0; | 1673 | int haveinfo = 0; |
1689 | 1674 | ||
1690 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) | 1675 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) |
1691 | return -EINVAL; | 1676 | return -EINVAL; |
1692 | 1677 | ||
1693 | rtnl_lock(); | ||
1694 | |||
1695 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
1696 | if (err) | ||
1697 | goto unlock_rtnl; | ||
1698 | |||
1699 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1678 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1700 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | 1679 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
1701 | err = -EOPNOTSUPP; | 1680 | return -EOPNOTSUPP; |
1702 | goto out; | ||
1703 | } | ||
1704 | 1681 | ||
1705 | switch (info->genlhdr->cmd) { | 1682 | switch (info->genlhdr->cmd) { |
1706 | case NL80211_CMD_NEW_BEACON: | 1683 | case NL80211_CMD_NEW_BEACON: |
1707 | /* these are required for NEW_BEACON */ | 1684 | /* these are required for NEW_BEACON */ |
1708 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || | 1685 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || |
1709 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || | 1686 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || |
1710 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 1687 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) |
1711 | err = -EINVAL; | 1688 | return -EINVAL; |
1712 | goto out; | ||
1713 | } | ||
1714 | 1689 | ||
1715 | call = rdev->ops->add_beacon; | 1690 | call = rdev->ops->add_beacon; |
1716 | break; | 1691 | break; |
@@ -1719,14 +1694,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1719 | break; | 1694 | break; |
1720 | default: | 1695 | default: |
1721 | WARN_ON(1); | 1696 | WARN_ON(1); |
1722 | err = -EOPNOTSUPP; | 1697 | return -EOPNOTSUPP; |
1723 | goto out; | ||
1724 | } | 1698 | } |
1725 | 1699 | ||
1726 | if (!call) { | 1700 | if (!call) |
1727 | err = -EOPNOTSUPP; | 1701 | return -EOPNOTSUPP; |
1728 | goto out; | ||
1729 | } | ||
1730 | 1702 | ||
1731 | memset(¶ms, 0, sizeof(params)); | 1703 | memset(¶ms, 0, sizeof(params)); |
1732 | 1704 | ||
@@ -1756,53 +1728,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1756 | haveinfo = 1; | 1728 | haveinfo = 1; |
1757 | } | 1729 | } |
1758 | 1730 | ||
1759 | if (!haveinfo) { | 1731 | if (!haveinfo) |
1760 | err = -EINVAL; | 1732 | return -EINVAL; |
1761 | goto out; | ||
1762 | } | ||
1763 | |||
1764 | err = call(&rdev->wiphy, dev, ¶ms); | ||
1765 | |||
1766 | out: | ||
1767 | cfg80211_unlock_rdev(rdev); | ||
1768 | dev_put(dev); | ||
1769 | unlock_rtnl: | ||
1770 | rtnl_unlock(); | ||
1771 | 1733 | ||
1772 | return err; | 1734 | return call(&rdev->wiphy, dev, ¶ms); |
1773 | } | 1735 | } |
1774 | 1736 | ||
1775 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | 1737 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) |
1776 | { | 1738 | { |
1777 | struct cfg80211_registered_device *rdev; | 1739 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1778 | int err; | 1740 | struct net_device *dev = info->user_ptr[1]; |
1779 | struct net_device *dev; | ||
1780 | 1741 | ||
1781 | rtnl_lock(); | 1742 | if (!rdev->ops->del_beacon) |
1782 | 1743 | return -EOPNOTSUPP; | |
1783 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
1784 | if (err) | ||
1785 | goto unlock_rtnl; | ||
1786 | |||
1787 | if (!rdev->ops->del_beacon) { | ||
1788 | err = -EOPNOTSUPP; | ||
1789 | goto out; | ||
1790 | } | ||
1791 | 1744 | ||
1792 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1745 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1793 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | 1746 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
1794 | err = -EOPNOTSUPP; | 1747 | return -EOPNOTSUPP; |
1795 | goto out; | ||
1796 | } | ||
1797 | err = rdev->ops->del_beacon(&rdev->wiphy, dev); | ||
1798 | |||
1799 | out: | ||
1800 | cfg80211_unlock_rdev(rdev); | ||
1801 | dev_put(dev); | ||
1802 | unlock_rtnl: | ||
1803 | rtnl_unlock(); | ||
1804 | 1748 | ||
1805 | return err; | 1749 | return rdev->ops->del_beacon(&rdev->wiphy, dev); |
1806 | } | 1750 | } |
1807 | 1751 | ||
1808 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 1752 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
@@ -1923,6 +1867,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
1923 | if (sinfo->filled & STATION_INFO_TX_PACKETS) | 1867 | if (sinfo->filled & STATION_INFO_TX_PACKETS) |
1924 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS, | 1868 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS, |
1925 | sinfo->tx_packets); | 1869 | sinfo->tx_packets); |
1870 | if (sinfo->filled & STATION_INFO_TX_RETRIES) | ||
1871 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_RETRIES, | ||
1872 | sinfo->tx_retries); | ||
1873 | if (sinfo->filled & STATION_INFO_TX_FAILED) | ||
1874 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, | ||
1875 | sinfo->tx_failed); | ||
1926 | nla_nest_end(msg, sinfoattr); | 1876 | nla_nest_end(msg, sinfoattr); |
1927 | 1877 | ||
1928 | return genlmsg_end(msg, hdr); | 1878 | return genlmsg_end(msg, hdr); |
@@ -1939,28 +1889,12 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1939 | struct cfg80211_registered_device *dev; | 1889 | struct cfg80211_registered_device *dev; |
1940 | struct net_device *netdev; | 1890 | struct net_device *netdev; |
1941 | u8 mac_addr[ETH_ALEN]; | 1891 | u8 mac_addr[ETH_ALEN]; |
1942 | int ifidx = cb->args[0]; | ||
1943 | int sta_idx = cb->args[1]; | 1892 | int sta_idx = cb->args[1]; |
1944 | int err; | 1893 | int err; |
1945 | 1894 | ||
1946 | if (!ifidx) | 1895 | err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); |
1947 | ifidx = nl80211_get_ifidx(cb); | 1896 | if (err) |
1948 | if (ifidx < 0) | 1897 | return err; |
1949 | return ifidx; | ||
1950 | |||
1951 | rtnl_lock(); | ||
1952 | |||
1953 | netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1954 | if (!netdev) { | ||
1955 | err = -ENODEV; | ||
1956 | goto out_rtnl; | ||
1957 | } | ||
1958 | |||
1959 | dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); | ||
1960 | if (IS_ERR(dev)) { | ||
1961 | err = PTR_ERR(dev); | ||
1962 | goto out_rtnl; | ||
1963 | } | ||
1964 | 1898 | ||
1965 | if (!dev->ops->dump_station) { | 1899 | if (!dev->ops->dump_station) { |
1966 | err = -EOPNOTSUPP; | 1900 | err = -EOPNOTSUPP; |
@@ -1990,21 +1924,19 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1990 | cb->args[1] = sta_idx; | 1924 | cb->args[1] = sta_idx; |
1991 | err = skb->len; | 1925 | err = skb->len; |
1992 | out_err: | 1926 | out_err: |
1993 | cfg80211_unlock_rdev(dev); | 1927 | nl80211_finish_netdev_dump(dev); |
1994 | out_rtnl: | ||
1995 | rtnl_unlock(); | ||
1996 | 1928 | ||
1997 | return err; | 1929 | return err; |
1998 | } | 1930 | } |
1999 | 1931 | ||
2000 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | 1932 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) |
2001 | { | 1933 | { |
2002 | struct cfg80211_registered_device *rdev; | 1934 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2003 | int err; | 1935 | struct net_device *dev = info->user_ptr[1]; |
2004 | struct net_device *dev; | ||
2005 | struct station_info sinfo; | 1936 | struct station_info sinfo; |
2006 | struct sk_buff *msg; | 1937 | struct sk_buff *msg; |
2007 | u8 *mac_addr = NULL; | 1938 | u8 *mac_addr = NULL; |
1939 | int err; | ||
2008 | 1940 | ||
2009 | memset(&sinfo, 0, sizeof(sinfo)); | 1941 | memset(&sinfo, 0, sizeof(sinfo)); |
2010 | 1942 | ||
@@ -2013,41 +1945,24 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
2013 | 1945 | ||
2014 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1946 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2015 | 1947 | ||
2016 | rtnl_lock(); | 1948 | if (!rdev->ops->get_station) |
2017 | 1949 | return -EOPNOTSUPP; | |
2018 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2019 | if (err) | ||
2020 | goto out_rtnl; | ||
2021 | |||
2022 | if (!rdev->ops->get_station) { | ||
2023 | err = -EOPNOTSUPP; | ||
2024 | goto out; | ||
2025 | } | ||
2026 | 1950 | ||
2027 | err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo); | 1951 | err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo); |
2028 | if (err) | 1952 | if (err) |
2029 | goto out; | 1953 | return err; |
2030 | 1954 | ||
2031 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1955 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
2032 | if (!msg) | 1956 | if (!msg) |
2033 | goto out; | 1957 | return -ENOMEM; |
2034 | 1958 | ||
2035 | if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, | 1959 | if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, |
2036 | dev, mac_addr, &sinfo) < 0) | 1960 | dev, mac_addr, &sinfo) < 0) { |
2037 | goto out_free; | 1961 | nlmsg_free(msg); |
2038 | 1962 | return -ENOBUFS; | |
2039 | err = genlmsg_reply(msg, info); | 1963 | } |
2040 | goto out; | ||
2041 | |||
2042 | out_free: | ||
2043 | nlmsg_free(msg); | ||
2044 | out: | ||
2045 | cfg80211_unlock_rdev(rdev); | ||
2046 | dev_put(dev); | ||
2047 | out_rtnl: | ||
2048 | rtnl_unlock(); | ||
2049 | 1964 | ||
2050 | return err; | 1965 | return genlmsg_reply(msg, info); |
2051 | } | 1966 | } |
2052 | 1967 | ||
2053 | /* | 1968 | /* |
@@ -2077,9 +1992,9 @@ static int get_vlan(struct genl_info *info, | |||
2077 | 1992 | ||
2078 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 1993 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
2079 | { | 1994 | { |
2080 | struct cfg80211_registered_device *rdev; | 1995 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2081 | int err; | 1996 | int err; |
2082 | struct net_device *dev; | 1997 | struct net_device *dev = info->user_ptr[1]; |
2083 | struct station_parameters params; | 1998 | struct station_parameters params; |
2084 | u8 *mac_addr = NULL; | 1999 | u8 *mac_addr = NULL; |
2085 | 2000 | ||
@@ -2117,12 +2032,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2117 | params.plink_action = | 2032 | params.plink_action = |
2118 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 2033 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
2119 | 2034 | ||
2120 | rtnl_lock(); | ||
2121 | |||
2122 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2123 | if (err) | ||
2124 | goto out_rtnl; | ||
2125 | |||
2126 | err = get_vlan(info, rdev, ¶ms.vlan); | 2035 | err = get_vlan(info, rdev, ¶ms.vlan); |
2127 | if (err) | 2036 | if (err) |
2128 | goto out; | 2037 | goto out; |
@@ -2184,19 +2093,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2184 | out: | 2093 | out: |
2185 | if (params.vlan) | 2094 | if (params.vlan) |
2186 | dev_put(params.vlan); | 2095 | dev_put(params.vlan); |
2187 | cfg80211_unlock_rdev(rdev); | ||
2188 | dev_put(dev); | ||
2189 | out_rtnl: | ||
2190 | rtnl_unlock(); | ||
2191 | 2096 | ||
2192 | return err; | 2097 | return err; |
2193 | } | 2098 | } |
2194 | 2099 | ||
2195 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | 2100 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) |
2196 | { | 2101 | { |
2197 | struct cfg80211_registered_device *rdev; | 2102 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2198 | int err; | 2103 | int err; |
2199 | struct net_device *dev; | 2104 | struct net_device *dev = info->user_ptr[1]; |
2200 | struct station_parameters params; | 2105 | struct station_parameters params; |
2201 | u8 *mac_addr = NULL; | 2106 | u8 *mac_addr = NULL; |
2202 | 2107 | ||
@@ -2233,18 +2138,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2233 | if (parse_station_flags(info, ¶ms)) | 2138 | if (parse_station_flags(info, ¶ms)) |
2234 | return -EINVAL; | 2139 | return -EINVAL; |
2235 | 2140 | ||
2236 | rtnl_lock(); | ||
2237 | |||
2238 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2239 | if (err) | ||
2240 | goto out_rtnl; | ||
2241 | |||
2242 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2141 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2243 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2142 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2244 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | 2143 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
2245 | err = -EINVAL; | 2144 | return -EINVAL; |
2246 | goto out; | ||
2247 | } | ||
2248 | 2145 | ||
2249 | err = get_vlan(info, rdev, ¶ms.vlan); | 2146 | err = get_vlan(info, rdev, ¶ms.vlan); |
2250 | if (err) | 2147 | if (err) |
@@ -2258,62 +2155,33 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2258 | goto out; | 2155 | goto out; |
2259 | } | 2156 | } |
2260 | 2157 | ||
2261 | if (!netif_running(dev)) { | ||
2262 | err = -ENETDOWN; | ||
2263 | goto out; | ||
2264 | } | ||
2265 | |||
2266 | err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, ¶ms); | 2158 | err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, ¶ms); |
2267 | 2159 | ||
2268 | out: | 2160 | out: |
2269 | if (params.vlan) | 2161 | if (params.vlan) |
2270 | dev_put(params.vlan); | 2162 | dev_put(params.vlan); |
2271 | cfg80211_unlock_rdev(rdev); | ||
2272 | dev_put(dev); | ||
2273 | out_rtnl: | ||
2274 | rtnl_unlock(); | ||
2275 | |||
2276 | return err; | 2163 | return err; |
2277 | } | 2164 | } |
2278 | 2165 | ||
2279 | static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | 2166 | static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) |
2280 | { | 2167 | { |
2281 | struct cfg80211_registered_device *rdev; | 2168 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2282 | int err; | 2169 | struct net_device *dev = info->user_ptr[1]; |
2283 | struct net_device *dev; | ||
2284 | u8 *mac_addr = NULL; | 2170 | u8 *mac_addr = NULL; |
2285 | 2171 | ||
2286 | if (info->attrs[NL80211_ATTR_MAC]) | 2172 | if (info->attrs[NL80211_ATTR_MAC]) |
2287 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2173 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2288 | 2174 | ||
2289 | rtnl_lock(); | ||
2290 | |||
2291 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2292 | if (err) | ||
2293 | goto out_rtnl; | ||
2294 | |||
2295 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2175 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2296 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2176 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2297 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | 2177 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
2298 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | 2178 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
2299 | err = -EINVAL; | 2179 | return -EINVAL; |
2300 | goto out; | ||
2301 | } | ||
2302 | |||
2303 | if (!rdev->ops->del_station) { | ||
2304 | err = -EOPNOTSUPP; | ||
2305 | goto out; | ||
2306 | } | ||
2307 | |||
2308 | err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr); | ||
2309 | 2180 | ||
2310 | out: | 2181 | if (!rdev->ops->del_station) |
2311 | cfg80211_unlock_rdev(rdev); | 2182 | return -EOPNOTSUPP; |
2312 | dev_put(dev); | ||
2313 | out_rtnl: | ||
2314 | rtnl_unlock(); | ||
2315 | 2183 | ||
2316 | return err; | 2184 | return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr); |
2317 | } | 2185 | } |
2318 | 2186 | ||
2319 | static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, | 2187 | static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, |
@@ -2376,28 +2244,12 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
2376 | struct net_device *netdev; | 2244 | struct net_device *netdev; |
2377 | u8 dst[ETH_ALEN]; | 2245 | u8 dst[ETH_ALEN]; |
2378 | u8 next_hop[ETH_ALEN]; | 2246 | u8 next_hop[ETH_ALEN]; |
2379 | int ifidx = cb->args[0]; | ||
2380 | int path_idx = cb->args[1]; | 2247 | int path_idx = cb->args[1]; |
2381 | int err; | 2248 | int err; |
2382 | 2249 | ||
2383 | if (!ifidx) | 2250 | err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); |
2384 | ifidx = nl80211_get_ifidx(cb); | 2251 | if (err) |
2385 | if (ifidx < 0) | 2252 | return err; |
2386 | return ifidx; | ||
2387 | |||
2388 | rtnl_lock(); | ||
2389 | |||
2390 | netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); | ||
2391 | if (!netdev) { | ||
2392 | err = -ENODEV; | ||
2393 | goto out_rtnl; | ||
2394 | } | ||
2395 | |||
2396 | dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); | ||
2397 | if (IS_ERR(dev)) { | ||
2398 | err = PTR_ERR(dev); | ||
2399 | goto out_rtnl; | ||
2400 | } | ||
2401 | 2253 | ||
2402 | if (!dev->ops->dump_mpath) { | 2254 | if (!dev->ops->dump_mpath) { |
2403 | err = -EOPNOTSUPP; | 2255 | err = -EOPNOTSUPP; |
@@ -2431,18 +2283,15 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
2431 | cb->args[1] = path_idx; | 2283 | cb->args[1] = path_idx; |
2432 | err = skb->len; | 2284 | err = skb->len; |
2433 | out_err: | 2285 | out_err: |
2434 | cfg80211_unlock_rdev(dev); | 2286 | nl80211_finish_netdev_dump(dev); |
2435 | out_rtnl: | ||
2436 | rtnl_unlock(); | ||
2437 | |||
2438 | return err; | 2287 | return err; |
2439 | } | 2288 | } |
2440 | 2289 | ||
2441 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | 2290 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) |
2442 | { | 2291 | { |
2443 | struct cfg80211_registered_device *rdev; | 2292 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2444 | int err; | 2293 | int err; |
2445 | struct net_device *dev; | 2294 | struct net_device *dev = info->user_ptr[1]; |
2446 | struct mpath_info pinfo; | 2295 | struct mpath_info pinfo; |
2447 | struct sk_buff *msg; | 2296 | struct sk_buff *msg; |
2448 | u8 *dst = NULL; | 2297 | u8 *dst = NULL; |
@@ -2455,53 +2304,33 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2455 | 2304 | ||
2456 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2305 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2457 | 2306 | ||
2458 | rtnl_lock(); | 2307 | if (!rdev->ops->get_mpath) |
2459 | 2308 | return -EOPNOTSUPP; | |
2460 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2461 | if (err) | ||
2462 | goto out_rtnl; | ||
2463 | |||
2464 | if (!rdev->ops->get_mpath) { | ||
2465 | err = -EOPNOTSUPP; | ||
2466 | goto out; | ||
2467 | } | ||
2468 | 2309 | ||
2469 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | 2310 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
2470 | err = -EOPNOTSUPP; | 2311 | return -EOPNOTSUPP; |
2471 | goto out; | ||
2472 | } | ||
2473 | 2312 | ||
2474 | err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo); | 2313 | err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo); |
2475 | if (err) | 2314 | if (err) |
2476 | goto out; | 2315 | return err; |
2477 | 2316 | ||
2478 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2317 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
2479 | if (!msg) | 2318 | if (!msg) |
2480 | goto out; | 2319 | return -ENOMEM; |
2481 | 2320 | ||
2482 | if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, | 2321 | if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, |
2483 | dev, dst, next_hop, &pinfo) < 0) | 2322 | dev, dst, next_hop, &pinfo) < 0) { |
2484 | goto out_free; | 2323 | nlmsg_free(msg); |
2485 | 2324 | return -ENOBUFS; | |
2486 | err = genlmsg_reply(msg, info); | 2325 | } |
2487 | goto out; | ||
2488 | |||
2489 | out_free: | ||
2490 | nlmsg_free(msg); | ||
2491 | out: | ||
2492 | cfg80211_unlock_rdev(rdev); | ||
2493 | dev_put(dev); | ||
2494 | out_rtnl: | ||
2495 | rtnl_unlock(); | ||
2496 | 2326 | ||
2497 | return err; | 2327 | return genlmsg_reply(msg, info); |
2498 | } | 2328 | } |
2499 | 2329 | ||
2500 | static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | 2330 | static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) |
2501 | { | 2331 | { |
2502 | struct cfg80211_registered_device *rdev; | 2332 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2503 | int err; | 2333 | struct net_device *dev = info->user_ptr[1]; |
2504 | struct net_device *dev; | ||
2505 | u8 *dst = NULL; | 2334 | u8 *dst = NULL; |
2506 | u8 *next_hop = NULL; | 2335 | u8 *next_hop = NULL; |
2507 | 2336 | ||
@@ -2514,42 +2343,19 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2514 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2343 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2515 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 2344 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
2516 | 2345 | ||
2517 | rtnl_lock(); | 2346 | if (!rdev->ops->change_mpath) |
2518 | 2347 | return -EOPNOTSUPP; | |
2519 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2520 | if (err) | ||
2521 | goto out_rtnl; | ||
2522 | |||
2523 | if (!rdev->ops->change_mpath) { | ||
2524 | err = -EOPNOTSUPP; | ||
2525 | goto out; | ||
2526 | } | ||
2527 | |||
2528 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2529 | err = -EOPNOTSUPP; | ||
2530 | goto out; | ||
2531 | } | ||
2532 | |||
2533 | if (!netif_running(dev)) { | ||
2534 | err = -ENETDOWN; | ||
2535 | goto out; | ||
2536 | } | ||
2537 | |||
2538 | err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop); | ||
2539 | 2348 | ||
2540 | out: | 2349 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
2541 | cfg80211_unlock_rdev(rdev); | 2350 | return -EOPNOTSUPP; |
2542 | dev_put(dev); | ||
2543 | out_rtnl: | ||
2544 | rtnl_unlock(); | ||
2545 | 2351 | ||
2546 | return err; | 2352 | return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop); |
2547 | } | 2353 | } |
2354 | |||
2548 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | 2355 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) |
2549 | { | 2356 | { |
2550 | struct cfg80211_registered_device *rdev; | 2357 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2551 | int err; | 2358 | struct net_device *dev = info->user_ptr[1]; |
2552 | struct net_device *dev; | ||
2553 | u8 *dst = NULL; | 2359 | u8 *dst = NULL; |
2554 | u8 *next_hop = NULL; | 2360 | u8 *next_hop = NULL; |
2555 | 2361 | ||
@@ -2562,75 +2368,34 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | |||
2562 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2368 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2563 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 2369 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
2564 | 2370 | ||
2565 | rtnl_lock(); | 2371 | if (!rdev->ops->add_mpath) |
2566 | 2372 | return -EOPNOTSUPP; | |
2567 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2568 | if (err) | ||
2569 | goto out_rtnl; | ||
2570 | |||
2571 | if (!rdev->ops->add_mpath) { | ||
2572 | err = -EOPNOTSUPP; | ||
2573 | goto out; | ||
2574 | } | ||
2575 | |||
2576 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2577 | err = -EOPNOTSUPP; | ||
2578 | goto out; | ||
2579 | } | ||
2580 | |||
2581 | if (!netif_running(dev)) { | ||
2582 | err = -ENETDOWN; | ||
2583 | goto out; | ||
2584 | } | ||
2585 | |||
2586 | err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop); | ||
2587 | 2373 | ||
2588 | out: | 2374 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
2589 | cfg80211_unlock_rdev(rdev); | 2375 | return -EOPNOTSUPP; |
2590 | dev_put(dev); | ||
2591 | out_rtnl: | ||
2592 | rtnl_unlock(); | ||
2593 | 2376 | ||
2594 | return err; | 2377 | return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop); |
2595 | } | 2378 | } |
2596 | 2379 | ||
2597 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | 2380 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) |
2598 | { | 2381 | { |
2599 | struct cfg80211_registered_device *rdev; | 2382 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2600 | int err; | 2383 | struct net_device *dev = info->user_ptr[1]; |
2601 | struct net_device *dev; | ||
2602 | u8 *dst = NULL; | 2384 | u8 *dst = NULL; |
2603 | 2385 | ||
2604 | if (info->attrs[NL80211_ATTR_MAC]) | 2386 | if (info->attrs[NL80211_ATTR_MAC]) |
2605 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2387 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2606 | 2388 | ||
2607 | rtnl_lock(); | 2389 | if (!rdev->ops->del_mpath) |
2608 | 2390 | return -EOPNOTSUPP; | |
2609 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2610 | if (err) | ||
2611 | goto out_rtnl; | ||
2612 | |||
2613 | if (!rdev->ops->del_mpath) { | ||
2614 | err = -EOPNOTSUPP; | ||
2615 | goto out; | ||
2616 | } | ||
2617 | |||
2618 | err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst); | ||
2619 | |||
2620 | out: | ||
2621 | cfg80211_unlock_rdev(rdev); | ||
2622 | dev_put(dev); | ||
2623 | out_rtnl: | ||
2624 | rtnl_unlock(); | ||
2625 | 2391 | ||
2626 | return err; | 2392 | return rdev->ops->del_mpath(&rdev->wiphy, dev, dst); |
2627 | } | 2393 | } |
2628 | 2394 | ||
2629 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | 2395 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) |
2630 | { | 2396 | { |
2631 | struct cfg80211_registered_device *rdev; | 2397 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2632 | int err; | 2398 | struct net_device *dev = info->user_ptr[1]; |
2633 | struct net_device *dev; | ||
2634 | struct bss_parameters params; | 2399 | struct bss_parameters params; |
2635 | 2400 | ||
2636 | memset(¶ms, 0, sizeof(params)); | 2401 | memset(¶ms, 0, sizeof(params)); |
@@ -2658,32 +2423,14 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2658 | if (info->attrs[NL80211_ATTR_AP_ISOLATE]) | 2423 | if (info->attrs[NL80211_ATTR_AP_ISOLATE]) |
2659 | params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); | 2424 | params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); |
2660 | 2425 | ||
2661 | rtnl_lock(); | 2426 | if (!rdev->ops->change_bss) |
2662 | 2427 | return -EOPNOTSUPP; | |
2663 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2664 | if (err) | ||
2665 | goto out_rtnl; | ||
2666 | |||
2667 | if (!rdev->ops->change_bss) { | ||
2668 | err = -EOPNOTSUPP; | ||
2669 | goto out; | ||
2670 | } | ||
2671 | 2428 | ||
2672 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2429 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2673 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | 2430 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
2674 | err = -EOPNOTSUPP; | 2431 | return -EOPNOTSUPP; |
2675 | goto out; | ||
2676 | } | ||
2677 | |||
2678 | err = rdev->ops->change_bss(&rdev->wiphy, dev, ¶ms); | ||
2679 | |||
2680 | out: | ||
2681 | cfg80211_unlock_rdev(rdev); | ||
2682 | dev_put(dev); | ||
2683 | out_rtnl: | ||
2684 | rtnl_unlock(); | ||
2685 | 2432 | ||
2686 | return err; | 2433 | return rdev->ops->change_bss(&rdev->wiphy, dev, ¶ms); |
2687 | } | 2434 | } |
2688 | 2435 | ||
2689 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | 2436 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { |
@@ -2762,37 +2509,26 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2762 | static int nl80211_get_mesh_params(struct sk_buff *skb, | 2509 | static int nl80211_get_mesh_params(struct sk_buff *skb, |
2763 | struct genl_info *info) | 2510 | struct genl_info *info) |
2764 | { | 2511 | { |
2765 | struct cfg80211_registered_device *rdev; | 2512 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2766 | struct mesh_config cur_params; | 2513 | struct mesh_config cur_params; |
2767 | int err; | 2514 | int err; |
2768 | struct net_device *dev; | 2515 | struct net_device *dev = info->user_ptr[1]; |
2769 | void *hdr; | 2516 | void *hdr; |
2770 | struct nlattr *pinfoattr; | 2517 | struct nlattr *pinfoattr; |
2771 | struct sk_buff *msg; | 2518 | struct sk_buff *msg; |
2772 | 2519 | ||
2773 | rtnl_lock(); | 2520 | if (!rdev->ops->get_mesh_params) |
2774 | 2521 | return -EOPNOTSUPP; | |
2775 | /* Look up our device */ | ||
2776 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2777 | if (err) | ||
2778 | goto out_rtnl; | ||
2779 | |||
2780 | if (!rdev->ops->get_mesh_params) { | ||
2781 | err = -EOPNOTSUPP; | ||
2782 | goto out; | ||
2783 | } | ||
2784 | 2522 | ||
2785 | /* Get the mesh params */ | 2523 | /* Get the mesh params */ |
2786 | err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params); | 2524 | err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params); |
2787 | if (err) | 2525 | if (err) |
2788 | goto out; | 2526 | return err; |
2789 | 2527 | ||
2790 | /* Draw up a netlink message to send back */ | 2528 | /* Draw up a netlink message to send back */ |
2791 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2529 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
2792 | if (!msg) { | 2530 | if (!msg) |
2793 | err = -ENOBUFS; | 2531 | return -ENOMEM; |
2794 | goto out; | ||
2795 | } | ||
2796 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 2532 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2797 | NL80211_CMD_GET_MESH_PARAMS); | 2533 | NL80211_CMD_GET_MESH_PARAMS); |
2798 | if (!hdr) | 2534 | if (!hdr) |
@@ -2831,21 +2567,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2831 | cur_params.dot11MeshHWMPRootMode); | 2567 | cur_params.dot11MeshHWMPRootMode); |
2832 | nla_nest_end(msg, pinfoattr); | 2568 | nla_nest_end(msg, pinfoattr); |
2833 | genlmsg_end(msg, hdr); | 2569 | genlmsg_end(msg, hdr); |
2834 | err = genlmsg_reply(msg, info); | 2570 | return genlmsg_reply(msg, info); |
2835 | goto out; | ||
2836 | 2571 | ||
2837 | nla_put_failure: | 2572 | nla_put_failure: |
2838 | genlmsg_cancel(msg, hdr); | 2573 | genlmsg_cancel(msg, hdr); |
2839 | nlmsg_free(msg); | 2574 | nlmsg_free(msg); |
2840 | err = -EMSGSIZE; | 2575 | return -ENOBUFS; |
2841 | out: | ||
2842 | /* Cleanup */ | ||
2843 | cfg80211_unlock_rdev(rdev); | ||
2844 | dev_put(dev); | ||
2845 | out_rtnl: | ||
2846 | rtnl_unlock(); | ||
2847 | |||
2848 | return err; | ||
2849 | } | 2576 | } |
2850 | 2577 | ||
2851 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ | 2578 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ |
@@ -2875,10 +2602,9 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
2875 | 2602 | ||
2876 | static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | 2603 | static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) |
2877 | { | 2604 | { |
2878 | int err; | ||
2879 | u32 mask; | 2605 | u32 mask; |
2880 | struct cfg80211_registered_device *rdev; | 2606 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2881 | struct net_device *dev; | 2607 | struct net_device *dev = info->user_ptr[1]; |
2882 | struct mesh_config cfg; | 2608 | struct mesh_config cfg; |
2883 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; | 2609 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; |
2884 | struct nlattr *parent_attr; | 2610 | struct nlattr *parent_attr; |
@@ -2890,16 +2616,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2890 | parent_attr, nl80211_meshconf_params_policy)) | 2616 | parent_attr, nl80211_meshconf_params_policy)) |
2891 | return -EINVAL; | 2617 | return -EINVAL; |
2892 | 2618 | ||
2893 | rtnl_lock(); | 2619 | if (!rdev->ops->set_mesh_params) |
2894 | 2620 | return -EOPNOTSUPP; | |
2895 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
2896 | if (err) | ||
2897 | goto out_rtnl; | ||
2898 | |||
2899 | if (!rdev->ops->set_mesh_params) { | ||
2900 | err = -EOPNOTSUPP; | ||
2901 | goto out; | ||
2902 | } | ||
2903 | 2621 | ||
2904 | /* This makes sure that there aren't more than 32 mesh config | 2622 | /* This makes sure that there aren't more than 32 mesh config |
2905 | * parameters (otherwise our bitfield scheme would not work.) */ | 2623 | * parameters (otherwise our bitfield scheme would not work.) */ |
@@ -2945,16 +2663,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2945 | nla_get_u8); | 2663 | nla_get_u8); |
2946 | 2664 | ||
2947 | /* Apply changes */ | 2665 | /* Apply changes */ |
2948 | err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); | 2666 | return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); |
2949 | |||
2950 | out: | ||
2951 | /* cleanup */ | ||
2952 | cfg80211_unlock_rdev(rdev); | ||
2953 | dev_put(dev); | ||
2954 | out_rtnl: | ||
2955 | rtnl_unlock(); | ||
2956 | |||
2957 | return err; | ||
2958 | } | 2667 | } |
2959 | 2668 | ||
2960 | #undef FILL_IN_MESH_PARAM_IF_SET | 2669 | #undef FILL_IN_MESH_PARAM_IF_SET |
@@ -3137,8 +2846,8 @@ static int validate_scan_freqs(struct nlattr *freqs) | |||
3137 | 2846 | ||
3138 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | 2847 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) |
3139 | { | 2848 | { |
3140 | struct cfg80211_registered_device *rdev; | 2849 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3141 | struct net_device *dev; | 2850 | struct net_device *dev = info->user_ptr[1]; |
3142 | struct cfg80211_scan_request *request; | 2851 | struct cfg80211_scan_request *request; |
3143 | struct cfg80211_ssid *ssid; | 2852 | struct cfg80211_ssid *ssid; |
3144 | struct ieee80211_channel *channel; | 2853 | struct ieee80211_channel *channel; |
@@ -3151,36 +2860,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3151 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 2860 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3152 | return -EINVAL; | 2861 | return -EINVAL; |
3153 | 2862 | ||
3154 | rtnl_lock(); | ||
3155 | |||
3156 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
3157 | if (err) | ||
3158 | goto out_rtnl; | ||
3159 | |||
3160 | wiphy = &rdev->wiphy; | 2863 | wiphy = &rdev->wiphy; |
3161 | 2864 | ||
3162 | if (!rdev->ops->scan) { | 2865 | if (!rdev->ops->scan) |
3163 | err = -EOPNOTSUPP; | 2866 | return -EOPNOTSUPP; |
3164 | goto out; | ||
3165 | } | ||
3166 | |||
3167 | if (!netif_running(dev)) { | ||
3168 | err = -ENETDOWN; | ||
3169 | goto out; | ||
3170 | } | ||
3171 | 2867 | ||
3172 | if (rdev->scan_req) { | 2868 | if (rdev->scan_req) |
3173 | err = -EBUSY; | 2869 | return -EBUSY; |
3174 | goto out; | ||
3175 | } | ||
3176 | 2870 | ||
3177 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 2871 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
3178 | n_channels = validate_scan_freqs( | 2872 | n_channels = validate_scan_freqs( |
3179 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 2873 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
3180 | if (!n_channels) { | 2874 | if (!n_channels) |
3181 | err = -EINVAL; | 2875 | return -EINVAL; |
3182 | goto out; | ||
3183 | } | ||
3184 | } else { | 2876 | } else { |
3185 | n_channels = 0; | 2877 | n_channels = 0; |
3186 | 2878 | ||
@@ -3193,29 +2885,23 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3193 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | 2885 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) |
3194 | n_ssids++; | 2886 | n_ssids++; |
3195 | 2887 | ||
3196 | if (n_ssids > wiphy->max_scan_ssids) { | 2888 | if (n_ssids > wiphy->max_scan_ssids) |
3197 | err = -EINVAL; | 2889 | return -EINVAL; |
3198 | goto out; | ||
3199 | } | ||
3200 | 2890 | ||
3201 | if (info->attrs[NL80211_ATTR_IE]) | 2891 | if (info->attrs[NL80211_ATTR_IE]) |
3202 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 2892 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3203 | else | 2893 | else |
3204 | ie_len = 0; | 2894 | ie_len = 0; |
3205 | 2895 | ||
3206 | if (ie_len > wiphy->max_scan_ie_len) { | 2896 | if (ie_len > wiphy->max_scan_ie_len) |
3207 | err = -EINVAL; | 2897 | return -EINVAL; |
3208 | goto out; | ||
3209 | } | ||
3210 | 2898 | ||
3211 | request = kzalloc(sizeof(*request) | 2899 | request = kzalloc(sizeof(*request) |
3212 | + sizeof(*ssid) * n_ssids | 2900 | + sizeof(*ssid) * n_ssids |
3213 | + sizeof(channel) * n_channels | 2901 | + sizeof(channel) * n_channels |
3214 | + ie_len, GFP_KERNEL); | 2902 | + ie_len, GFP_KERNEL); |
3215 | if (!request) { | 2903 | if (!request) |
3216 | err = -ENOMEM; | 2904 | return -ENOMEM; |
3217 | goto out; | ||
3218 | } | ||
3219 | 2905 | ||
3220 | if (n_ssids) | 2906 | if (n_ssids) |
3221 | request->ssids = (void *)&request->channels[n_channels]; | 2907 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -3303,18 +2989,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3303 | if (!err) { | 2989 | if (!err) { |
3304 | nl80211_send_scan_start(rdev, dev); | 2990 | nl80211_send_scan_start(rdev, dev); |
3305 | dev_hold(dev); | 2991 | dev_hold(dev); |
3306 | } | 2992 | } else { |
3307 | |||
3308 | out_free: | 2993 | out_free: |
3309 | if (err) { | ||
3310 | rdev->scan_req = NULL; | 2994 | rdev->scan_req = NULL; |
3311 | kfree(request); | 2995 | kfree(request); |
3312 | } | 2996 | } |
3313 | out: | ||
3314 | cfg80211_unlock_rdev(rdev); | ||
3315 | dev_put(dev); | ||
3316 | out_rtnl: | ||
3317 | rtnl_unlock(); | ||
3318 | 2997 | ||
3319 | return err; | 2998 | return err; |
3320 | } | 2999 | } |
@@ -3411,25 +3090,12 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
3411 | struct net_device *dev; | 3090 | struct net_device *dev; |
3412 | struct cfg80211_internal_bss *scan; | 3091 | struct cfg80211_internal_bss *scan; |
3413 | struct wireless_dev *wdev; | 3092 | struct wireless_dev *wdev; |
3414 | int ifidx = cb->args[0]; | ||
3415 | int start = cb->args[1], idx = 0; | 3093 | int start = cb->args[1], idx = 0; |
3416 | int err; | 3094 | int err; |
3417 | 3095 | ||
3418 | if (!ifidx) | 3096 | err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev); |
3419 | ifidx = nl80211_get_ifidx(cb); | 3097 | if (err) |
3420 | if (ifidx < 0) | 3098 | return err; |
3421 | return ifidx; | ||
3422 | cb->args[0] = ifidx; | ||
3423 | |||
3424 | dev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
3425 | if (!dev) | ||
3426 | return -ENODEV; | ||
3427 | |||
3428 | rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); | ||
3429 | if (IS_ERR(rdev)) { | ||
3430 | err = PTR_ERR(rdev); | ||
3431 | goto out_put_netdev; | ||
3432 | } | ||
3433 | 3099 | ||
3434 | wdev = dev->ieee80211_ptr; | 3100 | wdev = dev->ieee80211_ptr; |
3435 | 3101 | ||
@@ -3445,21 +3111,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
3445 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3111 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
3446 | rdev, wdev, scan) < 0) { | 3112 | rdev, wdev, scan) < 0) { |
3447 | idx--; | 3113 | idx--; |
3448 | goto out; | 3114 | break; |
3449 | } | 3115 | } |
3450 | } | 3116 | } |
3451 | 3117 | ||
3452 | out: | ||
3453 | spin_unlock_bh(&rdev->bss_lock); | 3118 | spin_unlock_bh(&rdev->bss_lock); |
3454 | wdev_unlock(wdev); | 3119 | wdev_unlock(wdev); |
3455 | 3120 | ||
3456 | cb->args[1] = idx; | 3121 | cb->args[1] = idx; |
3457 | err = skb->len; | 3122 | nl80211_finish_netdev_dump(rdev); |
3458 | cfg80211_unlock_rdev(rdev); | ||
3459 | out_put_netdev: | ||
3460 | dev_put(dev); | ||
3461 | 3123 | ||
3462 | return err; | 3124 | return skb->len; |
3463 | } | 3125 | } |
3464 | 3126 | ||
3465 | static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, | 3127 | static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, |
@@ -3489,6 +3151,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, | |||
3489 | if (survey->filled & SURVEY_INFO_NOISE_DBM) | 3151 | if (survey->filled & SURVEY_INFO_NOISE_DBM) |
3490 | NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE, | 3152 | NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE, |
3491 | survey->noise); | 3153 | survey->noise); |
3154 | if (survey->filled & SURVEY_INFO_IN_USE) | ||
3155 | NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); | ||
3492 | 3156 | ||
3493 | nla_nest_end(msg, infoattr); | 3157 | nla_nest_end(msg, infoattr); |
3494 | 3158 | ||
@@ -3505,29 +3169,12 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
3505 | struct survey_info survey; | 3169 | struct survey_info survey; |
3506 | struct cfg80211_registered_device *dev; | 3170 | struct cfg80211_registered_device *dev; |
3507 | struct net_device *netdev; | 3171 | struct net_device *netdev; |
3508 | int ifidx = cb->args[0]; | ||
3509 | int survey_idx = cb->args[1]; | 3172 | int survey_idx = cb->args[1]; |
3510 | int res; | 3173 | int res; |
3511 | 3174 | ||
3512 | if (!ifidx) | 3175 | res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); |
3513 | ifidx = nl80211_get_ifidx(cb); | 3176 | if (res) |
3514 | if (ifidx < 0) | 3177 | return res; |
3515 | return ifidx; | ||
3516 | cb->args[0] = ifidx; | ||
3517 | |||
3518 | rtnl_lock(); | ||
3519 | |||
3520 | netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); | ||
3521 | if (!netdev) { | ||
3522 | res = -ENODEV; | ||
3523 | goto out_rtnl; | ||
3524 | } | ||
3525 | |||
3526 | dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); | ||
3527 | if (IS_ERR(dev)) { | ||
3528 | res = PTR_ERR(dev); | ||
3529 | goto out_rtnl; | ||
3530 | } | ||
3531 | 3178 | ||
3532 | if (!dev->ops->dump_survey) { | 3179 | if (!dev->ops->dump_survey) { |
3533 | res = -EOPNOTSUPP; | 3180 | res = -EOPNOTSUPP; |
@@ -3555,10 +3202,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
3555 | cb->args[1] = survey_idx; | 3202 | cb->args[1] = survey_idx; |
3556 | res = skb->len; | 3203 | res = skb->len; |
3557 | out_err: | 3204 | out_err: |
3558 | cfg80211_unlock_rdev(dev); | 3205 | nl80211_finish_netdev_dump(dev); |
3559 | out_rtnl: | ||
3560 | rtnl_unlock(); | ||
3561 | |||
3562 | return res; | 3206 | return res; |
3563 | } | 3207 | } |
3564 | 3208 | ||
@@ -3591,8 +3235,8 @@ static bool nl80211_valid_cipher_suite(u32 cipher) | |||
3591 | 3235 | ||
3592 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | 3236 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) |
3593 | { | 3237 | { |
3594 | struct cfg80211_registered_device *rdev; | 3238 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3595 | struct net_device *dev; | 3239 | struct net_device *dev = info->user_ptr[1]; |
3596 | struct ieee80211_channel *chan; | 3240 | struct ieee80211_channel *chan; |
3597 | const u8 *bssid, *ssid, *ie = NULL; | 3241 | const u8 *bssid, *ssid, *ie = NULL; |
3598 | int err, ssid_len, ie_len = 0; | 3242 | int err, ssid_len, ie_len = 0; |
@@ -3620,6 +3264,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3620 | return err; | 3264 | return err; |
3621 | 3265 | ||
3622 | if (key.idx >= 0) { | 3266 | if (key.idx >= 0) { |
3267 | if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP) | ||
3268 | return -EINVAL; | ||
3623 | if (!key.p.key || !key.p.key_len) | 3269 | if (!key.p.key || !key.p.key_len) |
3624 | return -EINVAL; | 3270 | return -EINVAL; |
3625 | if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || | 3271 | if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || |
@@ -3634,12 +3280,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3634 | key.p.key = NULL; | 3280 | key.p.key = NULL; |
3635 | } | 3281 | } |
3636 | 3282 | ||
3637 | rtnl_lock(); | ||
3638 | |||
3639 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
3640 | if (err) | ||
3641 | goto unlock_rtnl; | ||
3642 | |||
3643 | if (key.idx >= 0) { | 3283 | if (key.idx >= 0) { |
3644 | int i; | 3284 | int i; |
3645 | bool ok = false; | 3285 | bool ok = false; |
@@ -3649,35 +3289,22 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3649 | break; | 3289 | break; |
3650 | } | 3290 | } |
3651 | } | 3291 | } |
3652 | if (!ok) { | 3292 | if (!ok) |
3653 | err = -EINVAL; | 3293 | return -EINVAL; |
3654 | goto out; | ||
3655 | } | ||
3656 | } | 3294 | } |
3657 | 3295 | ||
3658 | if (!rdev->ops->auth) { | 3296 | if (!rdev->ops->auth) |
3659 | err = -EOPNOTSUPP; | 3297 | return -EOPNOTSUPP; |
3660 | goto out; | ||
3661 | } | ||
3662 | 3298 | ||
3663 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3299 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3664 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3300 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
3665 | err = -EOPNOTSUPP; | 3301 | return -EOPNOTSUPP; |
3666 | goto out; | ||
3667 | } | ||
3668 | |||
3669 | if (!netif_running(dev)) { | ||
3670 | err = -ENETDOWN; | ||
3671 | goto out; | ||
3672 | } | ||
3673 | 3302 | ||
3674 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3303 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3675 | chan = ieee80211_get_channel(&rdev->wiphy, | 3304 | chan = ieee80211_get_channel(&rdev->wiphy, |
3676 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 3305 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
3677 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { | 3306 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) |
3678 | err = -EINVAL; | 3307 | return -EINVAL; |
3679 | goto out; | ||
3680 | } | ||
3681 | 3308 | ||
3682 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3309 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
3683 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 3310 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
@@ -3688,24 +3315,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3688 | } | 3315 | } |
3689 | 3316 | ||
3690 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 3317 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
3691 | if (!nl80211_valid_auth_type(auth_type)) { | 3318 | if (!nl80211_valid_auth_type(auth_type)) |
3692 | err = -EINVAL; | 3319 | return -EINVAL; |
3693 | goto out; | ||
3694 | } | ||
3695 | 3320 | ||
3696 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 3321 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3697 | 3322 | ||
3698 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 3323 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
3699 | ssid, ssid_len, ie, ie_len, | 3324 | ssid, ssid_len, ie, ie_len, |
3700 | key.p.key, key.p.key_len, key.idx, | 3325 | key.p.key, key.p.key_len, key.idx, |
3701 | local_state_change); | 3326 | local_state_change); |
3702 | |||
3703 | out: | ||
3704 | cfg80211_unlock_rdev(rdev); | ||
3705 | dev_put(dev); | ||
3706 | unlock_rtnl: | ||
3707 | rtnl_unlock(); | ||
3708 | return err; | ||
3709 | } | 3327 | } |
3710 | 3328 | ||
3711 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 3329 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -3789,8 +3407,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
3789 | 3407 | ||
3790 | static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | 3408 | static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) |
3791 | { | 3409 | { |
3792 | struct cfg80211_registered_device *rdev; | 3410 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3793 | struct net_device *dev; | 3411 | struct net_device *dev = info->user_ptr[1]; |
3794 | struct cfg80211_crypto_settings crypto; | 3412 | struct cfg80211_crypto_settings crypto; |
3795 | struct ieee80211_channel *chan; | 3413 | struct ieee80211_channel *chan; |
3796 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; | 3414 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; |
@@ -3805,36 +3423,19 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3805 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 3423 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
3806 | return -EINVAL; | 3424 | return -EINVAL; |
3807 | 3425 | ||
3808 | rtnl_lock(); | 3426 | if (!rdev->ops->assoc) |
3809 | 3427 | return -EOPNOTSUPP; | |
3810 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
3811 | if (err) | ||
3812 | goto unlock_rtnl; | ||
3813 | |||
3814 | if (!rdev->ops->assoc) { | ||
3815 | err = -EOPNOTSUPP; | ||
3816 | goto out; | ||
3817 | } | ||
3818 | 3428 | ||
3819 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3429 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3820 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3430 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
3821 | err = -EOPNOTSUPP; | 3431 | return -EOPNOTSUPP; |
3822 | goto out; | ||
3823 | } | ||
3824 | |||
3825 | if (!netif_running(dev)) { | ||
3826 | err = -ENETDOWN; | ||
3827 | goto out; | ||
3828 | } | ||
3829 | 3432 | ||
3830 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3433 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3831 | 3434 | ||
3832 | chan = ieee80211_get_channel(&rdev->wiphy, | 3435 | chan = ieee80211_get_channel(&rdev->wiphy, |
3833 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 3436 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
3834 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { | 3437 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) |
3835 | err = -EINVAL; | 3438 | return -EINVAL; |
3836 | goto out; | ||
3837 | } | ||
3838 | 3439 | ||
3839 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3440 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
3840 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 3441 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
@@ -3849,10 +3450,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3849 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | 3450 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); |
3850 | if (mfp == NL80211_MFP_REQUIRED) | 3451 | if (mfp == NL80211_MFP_REQUIRED) |
3851 | use_mfp = true; | 3452 | use_mfp = true; |
3852 | else if (mfp != NL80211_MFP_NO) { | 3453 | else if (mfp != NL80211_MFP_NO) |
3853 | err = -EINVAL; | 3454 | return -EINVAL; |
3854 | goto out; | ||
3855 | } | ||
3856 | } | 3455 | } |
3857 | 3456 | ||
3858 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) | 3457 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) |
@@ -3864,20 +3463,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3864 | ssid, ssid_len, ie, ie_len, use_mfp, | 3463 | ssid, ssid_len, ie, ie_len, use_mfp, |
3865 | &crypto); | 3464 | &crypto); |
3866 | 3465 | ||
3867 | out: | ||
3868 | cfg80211_unlock_rdev(rdev); | ||
3869 | dev_put(dev); | ||
3870 | unlock_rtnl: | ||
3871 | rtnl_unlock(); | ||
3872 | return err; | 3466 | return err; |
3873 | } | 3467 | } |
3874 | 3468 | ||
3875 | static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | 3469 | static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) |
3876 | { | 3470 | { |
3877 | struct cfg80211_registered_device *rdev; | 3471 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3878 | struct net_device *dev; | 3472 | struct net_device *dev = info->user_ptr[1]; |
3879 | const u8 *ie = NULL, *bssid; | 3473 | const u8 *ie = NULL, *bssid; |
3880 | int err, ie_len = 0; | 3474 | int ie_len = 0; |
3881 | u16 reason_code; | 3475 | u16 reason_code; |
3882 | bool local_state_change; | 3476 | bool local_state_change; |
3883 | 3477 | ||
@@ -3890,35 +3484,19 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3890 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) | 3484 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) |
3891 | return -EINVAL; | 3485 | return -EINVAL; |
3892 | 3486 | ||
3893 | rtnl_lock(); | 3487 | if (!rdev->ops->deauth) |
3894 | 3488 | return -EOPNOTSUPP; | |
3895 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
3896 | if (err) | ||
3897 | goto unlock_rtnl; | ||
3898 | |||
3899 | if (!rdev->ops->deauth) { | ||
3900 | err = -EOPNOTSUPP; | ||
3901 | goto out; | ||
3902 | } | ||
3903 | 3489 | ||
3904 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3490 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3905 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3491 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
3906 | err = -EOPNOTSUPP; | 3492 | return -EOPNOTSUPP; |
3907 | goto out; | ||
3908 | } | ||
3909 | |||
3910 | if (!netif_running(dev)) { | ||
3911 | err = -ENETDOWN; | ||
3912 | goto out; | ||
3913 | } | ||
3914 | 3493 | ||
3915 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3494 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3916 | 3495 | ||
3917 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); | 3496 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); |
3918 | if (reason_code == 0) { | 3497 | if (reason_code == 0) { |
3919 | /* Reason Code 0 is reserved */ | 3498 | /* Reason Code 0 is reserved */ |
3920 | err = -EINVAL; | 3499 | return -EINVAL; |
3921 | goto out; | ||
3922 | } | 3500 | } |
3923 | 3501 | ||
3924 | if (info->attrs[NL80211_ATTR_IE]) { | 3502 | if (info->attrs[NL80211_ATTR_IE]) { |
@@ -3928,23 +3506,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3928 | 3506 | ||
3929 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 3507 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3930 | 3508 | ||
3931 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | 3509 | return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, |
3932 | local_state_change); | 3510 | local_state_change); |
3933 | |||
3934 | out: | ||
3935 | cfg80211_unlock_rdev(rdev); | ||
3936 | dev_put(dev); | ||
3937 | unlock_rtnl: | ||
3938 | rtnl_unlock(); | ||
3939 | return err; | ||
3940 | } | 3511 | } |
3941 | 3512 | ||
3942 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | 3513 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) |
3943 | { | 3514 | { |
3944 | struct cfg80211_registered_device *rdev; | 3515 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3945 | struct net_device *dev; | 3516 | struct net_device *dev = info->user_ptr[1]; |
3946 | const u8 *ie = NULL, *bssid; | 3517 | const u8 *ie = NULL, *bssid; |
3947 | int err, ie_len = 0; | 3518 | int ie_len = 0; |
3948 | u16 reason_code; | 3519 | u16 reason_code; |
3949 | bool local_state_change; | 3520 | bool local_state_change; |
3950 | 3521 | ||
@@ -3957,35 +3528,19 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3957 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) | 3528 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) |
3958 | return -EINVAL; | 3529 | return -EINVAL; |
3959 | 3530 | ||
3960 | rtnl_lock(); | 3531 | if (!rdev->ops->disassoc) |
3961 | 3532 | return -EOPNOTSUPP; | |
3962 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
3963 | if (err) | ||
3964 | goto unlock_rtnl; | ||
3965 | |||
3966 | if (!rdev->ops->disassoc) { | ||
3967 | err = -EOPNOTSUPP; | ||
3968 | goto out; | ||
3969 | } | ||
3970 | 3533 | ||
3971 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3534 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3972 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3535 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
3973 | err = -EOPNOTSUPP; | 3536 | return -EOPNOTSUPP; |
3974 | goto out; | ||
3975 | } | ||
3976 | |||
3977 | if (!netif_running(dev)) { | ||
3978 | err = -ENETDOWN; | ||
3979 | goto out; | ||
3980 | } | ||
3981 | 3537 | ||
3982 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3538 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3983 | 3539 | ||
3984 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); | 3540 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); |
3985 | if (reason_code == 0) { | 3541 | if (reason_code == 0) { |
3986 | /* Reason Code 0 is reserved */ | 3542 | /* Reason Code 0 is reserved */ |
3987 | err = -EINVAL; | 3543 | return -EINVAL; |
3988 | goto out; | ||
3989 | } | 3544 | } |
3990 | 3545 | ||
3991 | if (info->attrs[NL80211_ATTR_IE]) { | 3546 | if (info->attrs[NL80211_ATTR_IE]) { |
@@ -3995,21 +3550,14 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3995 | 3550 | ||
3996 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 3551 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3997 | 3552 | ||
3998 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | 3553 | return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, |
3999 | local_state_change); | 3554 | local_state_change); |
4000 | |||
4001 | out: | ||
4002 | cfg80211_unlock_rdev(rdev); | ||
4003 | dev_put(dev); | ||
4004 | unlock_rtnl: | ||
4005 | rtnl_unlock(); | ||
4006 | return err; | ||
4007 | } | 3555 | } |
4008 | 3556 | ||
4009 | static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | 3557 | static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) |
4010 | { | 3558 | { |
4011 | struct cfg80211_registered_device *rdev; | 3559 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4012 | struct net_device *dev; | 3560 | struct net_device *dev = info->user_ptr[1]; |
4013 | struct cfg80211_ibss_params ibss; | 3561 | struct cfg80211_ibss_params ibss; |
4014 | struct wiphy *wiphy; | 3562 | struct wiphy *wiphy; |
4015 | struct cfg80211_cached_keys *connkeys = NULL; | 3563 | struct cfg80211_cached_keys *connkeys = NULL; |
@@ -4034,26 +3582,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4034 | return -EINVAL; | 3582 | return -EINVAL; |
4035 | } | 3583 | } |
4036 | 3584 | ||
4037 | rtnl_lock(); | 3585 | if (!rdev->ops->join_ibss) |
4038 | 3586 | return -EOPNOTSUPP; | |
4039 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4040 | if (err) | ||
4041 | goto unlock_rtnl; | ||
4042 | |||
4043 | if (!rdev->ops->join_ibss) { | ||
4044 | err = -EOPNOTSUPP; | ||
4045 | goto out; | ||
4046 | } | ||
4047 | |||
4048 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | ||
4049 | err = -EOPNOTSUPP; | ||
4050 | goto out; | ||
4051 | } | ||
4052 | 3587 | ||
4053 | if (!netif_running(dev)) { | 3588 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) |
4054 | err = -ENETDOWN; | 3589 | return -EOPNOTSUPP; |
4055 | goto out; | ||
4056 | } | ||
4057 | 3590 | ||
4058 | wiphy = &rdev->wiphy; | 3591 | wiphy = &rdev->wiphy; |
4059 | 3592 | ||
@@ -4071,24 +3604,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4071 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 3604 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
4072 | if (!ibss.channel || | 3605 | if (!ibss.channel || |
4073 | ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || | 3606 | ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || |
4074 | ibss.channel->flags & IEEE80211_CHAN_DISABLED) { | 3607 | ibss.channel->flags & IEEE80211_CHAN_DISABLED) |
4075 | err = -EINVAL; | 3608 | return -EINVAL; |
4076 | goto out; | ||
4077 | } | ||
4078 | 3609 | ||
4079 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 3610 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
4080 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | 3611 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; |
4081 | 3612 | ||
4082 | if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { | ||
4083 | connkeys = nl80211_parse_connkeys(rdev, | ||
4084 | info->attrs[NL80211_ATTR_KEYS]); | ||
4085 | if (IS_ERR(connkeys)) { | ||
4086 | err = PTR_ERR(connkeys); | ||
4087 | connkeys = NULL; | ||
4088 | goto out; | ||
4089 | } | ||
4090 | } | ||
4091 | |||
4092 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { | 3613 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { |
4093 | u8 *rates = | 3614 | u8 *rates = |
4094 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 3615 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
@@ -4098,10 +3619,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4098 | wiphy->bands[ibss.channel->band]; | 3619 | wiphy->bands[ibss.channel->band]; |
4099 | int i, j; | 3620 | int i, j; |
4100 | 3621 | ||
4101 | if (n_rates == 0) { | 3622 | if (n_rates == 0) |
4102 | err = -EINVAL; | 3623 | return -EINVAL; |
4103 | goto out; | ||
4104 | } | ||
4105 | 3624 | ||
4106 | for (i = 0; i < n_rates; i++) { | 3625 | for (i = 0; i < n_rates; i++) { |
4107 | int rate = (rates[i] & 0x7f) * 5; | 3626 | int rate = (rates[i] & 0x7f) * 5; |
@@ -4114,60 +3633,36 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4114 | break; | 3633 | break; |
4115 | } | 3634 | } |
4116 | } | 3635 | } |
4117 | if (!found) { | 3636 | if (!found) |
4118 | err = -EINVAL; | 3637 | return -EINVAL; |
4119 | goto out; | ||
4120 | } | ||
4121 | } | 3638 | } |
4122 | } | 3639 | } |
4123 | 3640 | ||
4124 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 3641 | if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { |
3642 | connkeys = nl80211_parse_connkeys(rdev, | ||
3643 | info->attrs[NL80211_ATTR_KEYS]); | ||
3644 | if (IS_ERR(connkeys)) | ||
3645 | return PTR_ERR(connkeys); | ||
3646 | } | ||
4125 | 3647 | ||
4126 | out: | 3648 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
4127 | cfg80211_unlock_rdev(rdev); | ||
4128 | dev_put(dev); | ||
4129 | unlock_rtnl: | ||
4130 | if (err) | 3649 | if (err) |
4131 | kfree(connkeys); | 3650 | kfree(connkeys); |
4132 | rtnl_unlock(); | ||
4133 | return err; | 3651 | return err; |
4134 | } | 3652 | } |
4135 | 3653 | ||
4136 | static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) | 3654 | static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) |
4137 | { | 3655 | { |
4138 | struct cfg80211_registered_device *rdev; | 3656 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4139 | struct net_device *dev; | 3657 | struct net_device *dev = info->user_ptr[1]; |
4140 | int err; | ||
4141 | 3658 | ||
4142 | rtnl_lock(); | 3659 | if (!rdev->ops->leave_ibss) |
4143 | 3660 | return -EOPNOTSUPP; | |
4144 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4145 | if (err) | ||
4146 | goto unlock_rtnl; | ||
4147 | |||
4148 | if (!rdev->ops->leave_ibss) { | ||
4149 | err = -EOPNOTSUPP; | ||
4150 | goto out; | ||
4151 | } | ||
4152 | |||
4153 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | ||
4154 | err = -EOPNOTSUPP; | ||
4155 | goto out; | ||
4156 | } | ||
4157 | |||
4158 | if (!netif_running(dev)) { | ||
4159 | err = -ENETDOWN; | ||
4160 | goto out; | ||
4161 | } | ||
4162 | 3661 | ||
4163 | err = cfg80211_leave_ibss(rdev, dev, false); | 3662 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) |
3663 | return -EOPNOTSUPP; | ||
4164 | 3664 | ||
4165 | out: | 3665 | return cfg80211_leave_ibss(rdev, dev, false); |
4166 | cfg80211_unlock_rdev(rdev); | ||
4167 | dev_put(dev); | ||
4168 | unlock_rtnl: | ||
4169 | rtnl_unlock(); | ||
4170 | return err; | ||
4171 | } | 3666 | } |
4172 | 3667 | ||
4173 | #ifdef CONFIG_NL80211_TESTMODE | 3668 | #ifdef CONFIG_NL80211_TESTMODE |
@@ -4177,20 +3672,12 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = { | |||
4177 | 3672 | ||
4178 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | 3673 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) |
4179 | { | 3674 | { |
4180 | struct cfg80211_registered_device *rdev; | 3675 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4181 | int err; | 3676 | int err; |
4182 | 3677 | ||
4183 | if (!info->attrs[NL80211_ATTR_TESTDATA]) | 3678 | if (!info->attrs[NL80211_ATTR_TESTDATA]) |
4184 | return -EINVAL; | 3679 | return -EINVAL; |
4185 | 3680 | ||
4186 | rtnl_lock(); | ||
4187 | |||
4188 | rdev = cfg80211_get_dev_from_info(info); | ||
4189 | if (IS_ERR(rdev)) { | ||
4190 | err = PTR_ERR(rdev); | ||
4191 | goto unlock_rtnl; | ||
4192 | } | ||
4193 | |||
4194 | err = -EOPNOTSUPP; | 3681 | err = -EOPNOTSUPP; |
4195 | if (rdev->ops->testmode_cmd) { | 3682 | if (rdev->ops->testmode_cmd) { |
4196 | rdev->testmode_info = info; | 3683 | rdev->testmode_info = info; |
@@ -4200,10 +3687,6 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | |||
4200 | rdev->testmode_info = NULL; | 3687 | rdev->testmode_info = NULL; |
4201 | } | 3688 | } |
4202 | 3689 | ||
4203 | cfg80211_unlock_rdev(rdev); | ||
4204 | |||
4205 | unlock_rtnl: | ||
4206 | rtnl_unlock(); | ||
4207 | return err; | 3690 | return err; |
4208 | } | 3691 | } |
4209 | 3692 | ||
@@ -4294,8 +3777,8 @@ EXPORT_SYMBOL(cfg80211_testmode_event); | |||
4294 | 3777 | ||
4295 | static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | 3778 | static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) |
4296 | { | 3779 | { |
4297 | struct cfg80211_registered_device *rdev; | 3780 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4298 | struct net_device *dev; | 3781 | struct net_device *dev = info->user_ptr[1]; |
4299 | struct cfg80211_connect_params connect; | 3782 | struct cfg80211_connect_params connect; |
4300 | struct wiphy *wiphy; | 3783 | struct wiphy *wiphy; |
4301 | struct cfg80211_cached_keys *connkeys = NULL; | 3784 | struct cfg80211_cached_keys *connkeys = NULL; |
@@ -4324,22 +3807,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
4324 | NL80211_MAX_NR_CIPHER_SUITES); | 3807 | NL80211_MAX_NR_CIPHER_SUITES); |
4325 | if (err) | 3808 | if (err) |
4326 | return err; | 3809 | return err; |
4327 | rtnl_lock(); | ||
4328 | |||
4329 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4330 | if (err) | ||
4331 | goto unlock_rtnl; | ||
4332 | 3810 | ||
4333 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3811 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4334 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3812 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
4335 | err = -EOPNOTSUPP; | 3813 | return -EOPNOTSUPP; |
4336 | goto out; | ||
4337 | } | ||
4338 | |||
4339 | if (!netif_running(dev)) { | ||
4340 | err = -ENETDOWN; | ||
4341 | goto out; | ||
4342 | } | ||
4343 | 3814 | ||
4344 | wiphy = &rdev->wiphy; | 3815 | wiphy = &rdev->wiphy; |
4345 | 3816 | ||
@@ -4358,39 +3829,27 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
4358 | ieee80211_get_channel(wiphy, | 3829 | ieee80211_get_channel(wiphy, |
4359 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 3830 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
4360 | if (!connect.channel || | 3831 | if (!connect.channel || |
4361 | connect.channel->flags & IEEE80211_CHAN_DISABLED) { | 3832 | connect.channel->flags & IEEE80211_CHAN_DISABLED) |
4362 | err = -EINVAL; | 3833 | return -EINVAL; |
4363 | goto out; | ||
4364 | } | ||
4365 | } | 3834 | } |
4366 | 3835 | ||
4367 | if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { | 3836 | if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { |
4368 | connkeys = nl80211_parse_connkeys(rdev, | 3837 | connkeys = nl80211_parse_connkeys(rdev, |
4369 | info->attrs[NL80211_ATTR_KEYS]); | 3838 | info->attrs[NL80211_ATTR_KEYS]); |
4370 | if (IS_ERR(connkeys)) { | 3839 | if (IS_ERR(connkeys)) |
4371 | err = PTR_ERR(connkeys); | 3840 | return PTR_ERR(connkeys); |
4372 | connkeys = NULL; | ||
4373 | goto out; | ||
4374 | } | ||
4375 | } | 3841 | } |
4376 | 3842 | ||
4377 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 3843 | err = cfg80211_connect(rdev, dev, &connect, connkeys); |
4378 | |||
4379 | out: | ||
4380 | cfg80211_unlock_rdev(rdev); | ||
4381 | dev_put(dev); | ||
4382 | unlock_rtnl: | ||
4383 | if (err) | 3844 | if (err) |
4384 | kfree(connkeys); | 3845 | kfree(connkeys); |
4385 | rtnl_unlock(); | ||
4386 | return err; | 3846 | return err; |
4387 | } | 3847 | } |
4388 | 3848 | ||
4389 | static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | 3849 | static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) |
4390 | { | 3850 | { |
4391 | struct cfg80211_registered_device *rdev; | 3851 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4392 | struct net_device *dev; | 3852 | struct net_device *dev = info->user_ptr[1]; |
4393 | int err; | ||
4394 | u16 reason; | 3853 | u16 reason; |
4395 | 3854 | ||
4396 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) | 3855 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) |
@@ -4401,36 +3860,16 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
4401 | if (reason == 0) | 3860 | if (reason == 0) |
4402 | return -EINVAL; | 3861 | return -EINVAL; |
4403 | 3862 | ||
4404 | rtnl_lock(); | ||
4405 | |||
4406 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4407 | if (err) | ||
4408 | goto unlock_rtnl; | ||
4409 | |||
4410 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3863 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4411 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3864 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
4412 | err = -EOPNOTSUPP; | 3865 | return -EOPNOTSUPP; |
4413 | goto out; | ||
4414 | } | ||
4415 | |||
4416 | if (!netif_running(dev)) { | ||
4417 | err = -ENETDOWN; | ||
4418 | goto out; | ||
4419 | } | ||
4420 | |||
4421 | err = cfg80211_disconnect(rdev, dev, reason, true); | ||
4422 | 3866 | ||
4423 | out: | 3867 | return cfg80211_disconnect(rdev, dev, reason, true); |
4424 | cfg80211_unlock_rdev(rdev); | ||
4425 | dev_put(dev); | ||
4426 | unlock_rtnl: | ||
4427 | rtnl_unlock(); | ||
4428 | return err; | ||
4429 | } | 3868 | } |
4430 | 3869 | ||
4431 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) | 3870 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) |
4432 | { | 3871 | { |
4433 | struct cfg80211_registered_device *rdev; | 3872 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4434 | struct net *net; | 3873 | struct net *net; |
4435 | int err; | 3874 | int err; |
4436 | u32 pid; | 3875 | u32 pid; |
@@ -4440,43 +3879,26 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) | |||
4440 | 3879 | ||
4441 | pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]); | 3880 | pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]); |
4442 | 3881 | ||
4443 | rtnl_lock(); | ||
4444 | |||
4445 | rdev = cfg80211_get_dev_from_info(info); | ||
4446 | if (IS_ERR(rdev)) { | ||
4447 | err = PTR_ERR(rdev); | ||
4448 | goto out_rtnl; | ||
4449 | } | ||
4450 | |||
4451 | net = get_net_ns_by_pid(pid); | 3882 | net = get_net_ns_by_pid(pid); |
4452 | if (IS_ERR(net)) { | 3883 | if (IS_ERR(net)) |
4453 | err = PTR_ERR(net); | 3884 | return PTR_ERR(net); |
4454 | goto out; | ||
4455 | } | ||
4456 | 3885 | ||
4457 | err = 0; | 3886 | err = 0; |
4458 | 3887 | ||
4459 | /* check if anything to do */ | 3888 | /* check if anything to do */ |
4460 | if (net_eq(wiphy_net(&rdev->wiphy), net)) | 3889 | if (!net_eq(wiphy_net(&rdev->wiphy), net)) |
4461 | goto out_put_net; | 3890 | err = cfg80211_switch_netns(rdev, net); |
4462 | 3891 | ||
4463 | err = cfg80211_switch_netns(rdev, net); | ||
4464 | out_put_net: | ||
4465 | put_net(net); | 3892 | put_net(net); |
4466 | out: | ||
4467 | cfg80211_unlock_rdev(rdev); | ||
4468 | out_rtnl: | ||
4469 | rtnl_unlock(); | ||
4470 | return err; | 3893 | return err; |
4471 | } | 3894 | } |
4472 | 3895 | ||
4473 | static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) | 3896 | static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) |
4474 | { | 3897 | { |
4475 | struct cfg80211_registered_device *rdev; | 3898 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4476 | int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev, | 3899 | int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev, |
4477 | struct cfg80211_pmksa *pmksa) = NULL; | 3900 | struct cfg80211_pmksa *pmksa) = NULL; |
4478 | int err; | 3901 | struct net_device *dev = info->user_ptr[1]; |
4479 | struct net_device *dev; | ||
4480 | struct cfg80211_pmksa pmksa; | 3902 | struct cfg80211_pmksa pmksa; |
4481 | 3903 | ||
4482 | memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); | 3904 | memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); |
@@ -4487,20 +3909,12 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4487 | if (!info->attrs[NL80211_ATTR_PMKID]) | 3909 | if (!info->attrs[NL80211_ATTR_PMKID]) |
4488 | return -EINVAL; | 3910 | return -EINVAL; |
4489 | 3911 | ||
4490 | rtnl_lock(); | ||
4491 | |||
4492 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4493 | if (err) | ||
4494 | goto out_rtnl; | ||
4495 | |||
4496 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); | 3912 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); |
4497 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3913 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
4498 | 3914 | ||
4499 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3915 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4500 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3916 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
4501 | err = -EOPNOTSUPP; | 3917 | return -EOPNOTSUPP; |
4502 | goto out; | ||
4503 | } | ||
4504 | 3918 | ||
4505 | switch (info->genlhdr->cmd) { | 3919 | switch (info->genlhdr->cmd) { |
4506 | case NL80211_CMD_SET_PMKSA: | 3920 | case NL80211_CMD_SET_PMKSA: |
@@ -4514,62 +3928,32 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4514 | break; | 3928 | break; |
4515 | } | 3929 | } |
4516 | 3930 | ||
4517 | if (!rdev_ops) { | 3931 | if (!rdev_ops) |
4518 | err = -EOPNOTSUPP; | 3932 | return -EOPNOTSUPP; |
4519 | goto out; | ||
4520 | } | ||
4521 | |||
4522 | err = rdev_ops(&rdev->wiphy, dev, &pmksa); | ||
4523 | |||
4524 | out: | ||
4525 | cfg80211_unlock_rdev(rdev); | ||
4526 | dev_put(dev); | ||
4527 | out_rtnl: | ||
4528 | rtnl_unlock(); | ||
4529 | 3933 | ||
4530 | return err; | 3934 | return rdev_ops(&rdev->wiphy, dev, &pmksa); |
4531 | } | 3935 | } |
4532 | 3936 | ||
4533 | static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) | 3937 | static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) |
4534 | { | 3938 | { |
4535 | struct cfg80211_registered_device *rdev; | 3939 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4536 | int err; | 3940 | struct net_device *dev = info->user_ptr[1]; |
4537 | struct net_device *dev; | ||
4538 | |||
4539 | rtnl_lock(); | ||
4540 | |||
4541 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4542 | if (err) | ||
4543 | goto out_rtnl; | ||
4544 | 3941 | ||
4545 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 3942 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4546 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 3943 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
4547 | err = -EOPNOTSUPP; | 3944 | return -EOPNOTSUPP; |
4548 | goto out; | ||
4549 | } | ||
4550 | |||
4551 | if (!rdev->ops->flush_pmksa) { | ||
4552 | err = -EOPNOTSUPP; | ||
4553 | goto out; | ||
4554 | } | ||
4555 | |||
4556 | err = rdev->ops->flush_pmksa(&rdev->wiphy, dev); | ||
4557 | |||
4558 | out: | ||
4559 | cfg80211_unlock_rdev(rdev); | ||
4560 | dev_put(dev); | ||
4561 | out_rtnl: | ||
4562 | rtnl_unlock(); | ||
4563 | 3945 | ||
4564 | return err; | 3946 | if (!rdev->ops->flush_pmksa) |
3947 | return -EOPNOTSUPP; | ||
4565 | 3948 | ||
3949 | return rdev->ops->flush_pmksa(&rdev->wiphy, dev); | ||
4566 | } | 3950 | } |
4567 | 3951 | ||
4568 | static int nl80211_remain_on_channel(struct sk_buff *skb, | 3952 | static int nl80211_remain_on_channel(struct sk_buff *skb, |
4569 | struct genl_info *info) | 3953 | struct genl_info *info) |
4570 | { | 3954 | { |
4571 | struct cfg80211_registered_device *rdev; | 3955 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4572 | struct net_device *dev; | 3956 | struct net_device *dev = info->user_ptr[1]; |
4573 | struct ieee80211_channel *chan; | 3957 | struct ieee80211_channel *chan; |
4574 | struct sk_buff *msg; | 3958 | struct sk_buff *msg; |
4575 | void *hdr; | 3959 | void *hdr; |
@@ -4591,21 +3975,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
4591 | if (!duration || !msecs_to_jiffies(duration) || duration > 5000) | 3975 | if (!duration || !msecs_to_jiffies(duration) || duration > 5000) |
4592 | return -EINVAL; | 3976 | return -EINVAL; |
4593 | 3977 | ||
4594 | rtnl_lock(); | 3978 | if (!rdev->ops->remain_on_channel) |
4595 | 3979 | return -EOPNOTSUPP; | |
4596 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4597 | if (err) | ||
4598 | goto unlock_rtnl; | ||
4599 | |||
4600 | if (!rdev->ops->remain_on_channel) { | ||
4601 | err = -EOPNOTSUPP; | ||
4602 | goto out; | ||
4603 | } | ||
4604 | |||
4605 | if (!netif_running(dev)) { | ||
4606 | err = -ENETDOWN; | ||
4607 | goto out; | ||
4608 | } | ||
4609 | 3980 | ||
4610 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 3981 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
4611 | channel_type = nla_get_u32( | 3982 | channel_type = nla_get_u32( |
@@ -4613,24 +3984,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
4613 | if (channel_type != NL80211_CHAN_NO_HT && | 3984 | if (channel_type != NL80211_CHAN_NO_HT && |
4614 | channel_type != NL80211_CHAN_HT20 && | 3985 | channel_type != NL80211_CHAN_HT20 && |
4615 | channel_type != NL80211_CHAN_HT40PLUS && | 3986 | channel_type != NL80211_CHAN_HT40PLUS && |
4616 | channel_type != NL80211_CHAN_HT40MINUS) { | 3987 | channel_type != NL80211_CHAN_HT40MINUS) |
4617 | err = -EINVAL; | 3988 | return -EINVAL; |
4618 | goto out; | ||
4619 | } | ||
4620 | } | 3989 | } |
4621 | 3990 | ||
4622 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 3991 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
4623 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 3992 | chan = rdev_freq_to_chan(rdev, freq, channel_type); |
4624 | if (chan == NULL) { | 3993 | if (chan == NULL) |
4625 | err = -EINVAL; | 3994 | return -EINVAL; |
4626 | goto out; | ||
4627 | } | ||
4628 | 3995 | ||
4629 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 3996 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
4630 | if (!msg) { | 3997 | if (!msg) |
4631 | err = -ENOMEM; | 3998 | return -ENOMEM; |
4632 | goto out; | ||
4633 | } | ||
4634 | 3999 | ||
4635 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4000 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4636 | NL80211_CMD_REMAIN_ON_CHANNEL); | 4001 | NL80211_CMD_REMAIN_ON_CHANNEL); |
@@ -4649,58 +4014,32 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
4649 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | 4014 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
4650 | 4015 | ||
4651 | genlmsg_end(msg, hdr); | 4016 | genlmsg_end(msg, hdr); |
4652 | err = genlmsg_reply(msg, info); | 4017 | |
4653 | goto out; | 4018 | return genlmsg_reply(msg, info); |
4654 | 4019 | ||
4655 | nla_put_failure: | 4020 | nla_put_failure: |
4656 | err = -ENOBUFS; | 4021 | err = -ENOBUFS; |
4657 | free_msg: | 4022 | free_msg: |
4658 | nlmsg_free(msg); | 4023 | nlmsg_free(msg); |
4659 | out: | ||
4660 | cfg80211_unlock_rdev(rdev); | ||
4661 | dev_put(dev); | ||
4662 | unlock_rtnl: | ||
4663 | rtnl_unlock(); | ||
4664 | return err; | 4024 | return err; |
4665 | } | 4025 | } |
4666 | 4026 | ||
4667 | static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, | 4027 | static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, |
4668 | struct genl_info *info) | 4028 | struct genl_info *info) |
4669 | { | 4029 | { |
4670 | struct cfg80211_registered_device *rdev; | 4030 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4671 | struct net_device *dev; | 4031 | struct net_device *dev = info->user_ptr[1]; |
4672 | u64 cookie; | 4032 | u64 cookie; |
4673 | int err; | ||
4674 | 4033 | ||
4675 | if (!info->attrs[NL80211_ATTR_COOKIE]) | 4034 | if (!info->attrs[NL80211_ATTR_COOKIE]) |
4676 | return -EINVAL; | 4035 | return -EINVAL; |
4677 | 4036 | ||
4678 | rtnl_lock(); | 4037 | if (!rdev->ops->cancel_remain_on_channel) |
4679 | 4038 | return -EOPNOTSUPP; | |
4680 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4681 | if (err) | ||
4682 | goto unlock_rtnl; | ||
4683 | |||
4684 | if (!rdev->ops->cancel_remain_on_channel) { | ||
4685 | err = -EOPNOTSUPP; | ||
4686 | goto out; | ||
4687 | } | ||
4688 | |||
4689 | if (!netif_running(dev)) { | ||
4690 | err = -ENETDOWN; | ||
4691 | goto out; | ||
4692 | } | ||
4693 | 4039 | ||
4694 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); | 4040 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); |
4695 | 4041 | ||
4696 | err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); | 4042 | return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); |
4697 | |||
4698 | out: | ||
4699 | cfg80211_unlock_rdev(rdev); | ||
4700 | dev_put(dev); | ||
4701 | unlock_rtnl: | ||
4702 | rtnl_unlock(); | ||
4703 | return err; | ||
4704 | } | 4043 | } |
4705 | 4044 | ||
4706 | static u32 rateset_to_mask(struct ieee80211_supported_band *sband, | 4045 | static u32 rateset_to_mask(struct ieee80211_supported_band *sband, |
@@ -4736,26 +4075,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4736 | struct genl_info *info) | 4075 | struct genl_info *info) |
4737 | { | 4076 | { |
4738 | struct nlattr *tb[NL80211_TXRATE_MAX + 1]; | 4077 | struct nlattr *tb[NL80211_TXRATE_MAX + 1]; |
4739 | struct cfg80211_registered_device *rdev; | 4078 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4740 | struct cfg80211_bitrate_mask mask; | 4079 | struct cfg80211_bitrate_mask mask; |
4741 | int err, rem, i; | 4080 | int rem, i; |
4742 | struct net_device *dev; | 4081 | struct net_device *dev = info->user_ptr[1]; |
4743 | struct nlattr *tx_rates; | 4082 | struct nlattr *tx_rates; |
4744 | struct ieee80211_supported_band *sband; | 4083 | struct ieee80211_supported_band *sband; |
4745 | 4084 | ||
4746 | if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) | 4085 | if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) |
4747 | return -EINVAL; | 4086 | return -EINVAL; |
4748 | 4087 | ||
4749 | rtnl_lock(); | 4088 | if (!rdev->ops->set_bitrate_mask) |
4750 | 4089 | return -EOPNOTSUPP; | |
4751 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4752 | if (err) | ||
4753 | goto unlock_rtnl; | ||
4754 | |||
4755 | if (!rdev->ops->set_bitrate_mask) { | ||
4756 | err = -EOPNOTSUPP; | ||
4757 | goto unlock; | ||
4758 | } | ||
4759 | 4090 | ||
4760 | memset(&mask, 0, sizeof(mask)); | 4091 | memset(&mask, 0, sizeof(mask)); |
4761 | /* Default to all rates enabled */ | 4092 | /* Default to all rates enabled */ |
@@ -4772,15 +4103,11 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4772 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) | 4103 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) |
4773 | { | 4104 | { |
4774 | enum ieee80211_band band = nla_type(tx_rates); | 4105 | enum ieee80211_band band = nla_type(tx_rates); |
4775 | if (band < 0 || band >= IEEE80211_NUM_BANDS) { | 4106 | if (band < 0 || band >= IEEE80211_NUM_BANDS) |
4776 | err = -EINVAL; | 4107 | return -EINVAL; |
4777 | goto unlock; | ||
4778 | } | ||
4779 | sband = rdev->wiphy.bands[band]; | 4108 | sband = rdev->wiphy.bands[band]; |
4780 | if (sband == NULL) { | 4109 | if (sband == NULL) |
4781 | err = -EINVAL; | 4110 | return -EINVAL; |
4782 | goto unlock; | ||
4783 | } | ||
4784 | nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), | 4111 | nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), |
4785 | nla_len(tx_rates), nl80211_txattr_policy); | 4112 | nla_len(tx_rates), nl80211_txattr_policy); |
4786 | if (tb[NL80211_TXRATE_LEGACY]) { | 4113 | if (tb[NL80211_TXRATE_LEGACY]) { |
@@ -4788,29 +4115,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4788 | sband, | 4115 | sband, |
4789 | nla_data(tb[NL80211_TXRATE_LEGACY]), | 4116 | nla_data(tb[NL80211_TXRATE_LEGACY]), |
4790 | nla_len(tb[NL80211_TXRATE_LEGACY])); | 4117 | nla_len(tb[NL80211_TXRATE_LEGACY])); |
4791 | if (mask.control[band].legacy == 0) { | 4118 | if (mask.control[band].legacy == 0) |
4792 | err = -EINVAL; | 4119 | return -EINVAL; |
4793 | goto unlock; | ||
4794 | } | ||
4795 | } | 4120 | } |
4796 | } | 4121 | } |
4797 | 4122 | ||
4798 | err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); | 4123 | return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); |
4799 | |||
4800 | unlock: | ||
4801 | dev_put(dev); | ||
4802 | cfg80211_unlock_rdev(rdev); | ||
4803 | unlock_rtnl: | ||
4804 | rtnl_unlock(); | ||
4805 | return err; | ||
4806 | } | 4124 | } |
4807 | 4125 | ||
4808 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | 4126 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
4809 | { | 4127 | { |
4810 | struct cfg80211_registered_device *rdev; | 4128 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4811 | struct net_device *dev; | 4129 | struct net_device *dev = info->user_ptr[1]; |
4812 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | 4130 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; |
4813 | int err; | ||
4814 | 4131 | ||
4815 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4132 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
4816 | return -EINVAL; | 4133 | return -EINVAL; |
@@ -4818,41 +4135,28 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4818 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) | 4135 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
4819 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); | 4136 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
4820 | 4137 | ||
4821 | rtnl_lock(); | ||
4822 | |||
4823 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4824 | if (err) | ||
4825 | goto unlock_rtnl; | ||
4826 | |||
4827 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4138 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4828 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && | 4139 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4829 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 4140 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4830 | err = -EOPNOTSUPP; | 4141 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4831 | goto out; | 4142 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4832 | } | 4143 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4144 | return -EOPNOTSUPP; | ||
4833 | 4145 | ||
4834 | /* not much point in registering if we can't reply */ | 4146 | /* not much point in registering if we can't reply */ |
4835 | if (!rdev->ops->mgmt_tx) { | 4147 | if (!rdev->ops->mgmt_tx) |
4836 | err = -EOPNOTSUPP; | 4148 | return -EOPNOTSUPP; |
4837 | goto out; | ||
4838 | } | ||
4839 | 4149 | ||
4840 | err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, | 4150 | return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4841 | frame_type, | 4151 | frame_type, |
4842 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4152 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
4843 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4153 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
4844 | out: | ||
4845 | cfg80211_unlock_rdev(rdev); | ||
4846 | dev_put(dev); | ||
4847 | unlock_rtnl: | ||
4848 | rtnl_unlock(); | ||
4849 | return err; | ||
4850 | } | 4154 | } |
4851 | 4155 | ||
4852 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | 4156 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
4853 | { | 4157 | { |
4854 | struct cfg80211_registered_device *rdev; | 4158 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4855 | struct net_device *dev; | 4159 | struct net_device *dev = info->user_ptr[1]; |
4856 | struct ieee80211_channel *chan; | 4160 | struct ieee80211_channel *chan; |
4857 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 4161 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
4858 | bool channel_type_valid = false; | 4162 | bool channel_type_valid = false; |
@@ -4866,28 +4170,16 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4866 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 4170 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
4867 | return -EINVAL; | 4171 | return -EINVAL; |
4868 | 4172 | ||
4869 | rtnl_lock(); | 4173 | if (!rdev->ops->mgmt_tx) |
4870 | 4174 | return -EOPNOTSUPP; | |
4871 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4872 | if (err) | ||
4873 | goto unlock_rtnl; | ||
4874 | |||
4875 | if (!rdev->ops->mgmt_tx) { | ||
4876 | err = -EOPNOTSUPP; | ||
4877 | goto out; | ||
4878 | } | ||
4879 | 4175 | ||
4880 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4176 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4881 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && | 4177 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4882 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 4178 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4883 | err = -EOPNOTSUPP; | 4179 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4884 | goto out; | 4180 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4885 | } | 4181 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4886 | 4182 | return -EOPNOTSUPP; | |
4887 | if (!netif_running(dev)) { | ||
4888 | err = -ENETDOWN; | ||
4889 | goto out; | ||
4890 | } | ||
4891 | 4183 | ||
4892 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 4184 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
4893 | channel_type = nla_get_u32( | 4185 | channel_type = nla_get_u32( |
@@ -4895,25 +4187,19 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4895 | if (channel_type != NL80211_CHAN_NO_HT && | 4187 | if (channel_type != NL80211_CHAN_NO_HT && |
4896 | channel_type != NL80211_CHAN_HT20 && | 4188 | channel_type != NL80211_CHAN_HT20 && |
4897 | channel_type != NL80211_CHAN_HT40PLUS && | 4189 | channel_type != NL80211_CHAN_HT40PLUS && |
4898 | channel_type != NL80211_CHAN_HT40MINUS) { | 4190 | channel_type != NL80211_CHAN_HT40MINUS) |
4899 | err = -EINVAL; | 4191 | return -EINVAL; |
4900 | goto out; | ||
4901 | } | ||
4902 | channel_type_valid = true; | 4192 | channel_type_valid = true; |
4903 | } | 4193 | } |
4904 | 4194 | ||
4905 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 4195 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
4906 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 4196 | chan = rdev_freq_to_chan(rdev, freq, channel_type); |
4907 | if (chan == NULL) { | 4197 | if (chan == NULL) |
4908 | err = -EINVAL; | 4198 | return -EINVAL; |
4909 | goto out; | ||
4910 | } | ||
4911 | 4199 | ||
4912 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4200 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
4913 | if (!msg) { | 4201 | if (!msg) |
4914 | err = -ENOMEM; | 4202 | return -ENOMEM; |
4915 | goto out; | ||
4916 | } | ||
4917 | 4203 | ||
4918 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4204 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4919 | NL80211_CMD_FRAME); | 4205 | NL80211_CMD_FRAME); |
@@ -4933,110 +4219,72 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4933 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | 4219 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
4934 | 4220 | ||
4935 | genlmsg_end(msg, hdr); | 4221 | genlmsg_end(msg, hdr); |
4936 | err = genlmsg_reply(msg, info); | 4222 | return genlmsg_reply(msg, info); |
4937 | goto out; | ||
4938 | 4223 | ||
4939 | nla_put_failure: | 4224 | nla_put_failure: |
4940 | err = -ENOBUFS; | 4225 | err = -ENOBUFS; |
4941 | free_msg: | 4226 | free_msg: |
4942 | nlmsg_free(msg); | 4227 | nlmsg_free(msg); |
4943 | out: | ||
4944 | cfg80211_unlock_rdev(rdev); | ||
4945 | dev_put(dev); | ||
4946 | unlock_rtnl: | ||
4947 | rtnl_unlock(); | ||
4948 | return err; | 4228 | return err; |
4949 | } | 4229 | } |
4950 | 4230 | ||
4951 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) | 4231 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) |
4952 | { | 4232 | { |
4953 | struct cfg80211_registered_device *rdev; | 4233 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4954 | struct wireless_dev *wdev; | 4234 | struct wireless_dev *wdev; |
4955 | struct net_device *dev; | 4235 | struct net_device *dev = info->user_ptr[1]; |
4956 | u8 ps_state; | 4236 | u8 ps_state; |
4957 | bool state; | 4237 | bool state; |
4958 | int err; | 4238 | int err; |
4959 | 4239 | ||
4960 | if (!info->attrs[NL80211_ATTR_PS_STATE]) { | 4240 | if (!info->attrs[NL80211_ATTR_PS_STATE]) |
4961 | err = -EINVAL; | 4241 | return -EINVAL; |
4962 | goto out; | ||
4963 | } | ||
4964 | 4242 | ||
4965 | ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); | 4243 | ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); |
4966 | 4244 | ||
4967 | if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) { | 4245 | if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) |
4968 | err = -EINVAL; | 4246 | return -EINVAL; |
4969 | goto out; | ||
4970 | } | ||
4971 | |||
4972 | rtnl_lock(); | ||
4973 | |||
4974 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4975 | if (err) | ||
4976 | goto unlock_rtnl; | ||
4977 | 4247 | ||
4978 | wdev = dev->ieee80211_ptr; | 4248 | wdev = dev->ieee80211_ptr; |
4979 | 4249 | ||
4980 | if (!rdev->ops->set_power_mgmt) { | 4250 | if (!rdev->ops->set_power_mgmt) |
4981 | err = -EOPNOTSUPP; | 4251 | return -EOPNOTSUPP; |
4982 | goto unlock_rdev; | ||
4983 | } | ||
4984 | 4252 | ||
4985 | state = (ps_state == NL80211_PS_ENABLED) ? true : false; | 4253 | state = (ps_state == NL80211_PS_ENABLED) ? true : false; |
4986 | 4254 | ||
4987 | if (state == wdev->ps) | 4255 | if (state == wdev->ps) |
4988 | goto unlock_rdev; | 4256 | return 0; |
4989 | |||
4990 | wdev->ps = state; | ||
4991 | |||
4992 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, | ||
4993 | wdev->ps_timeout)) | ||
4994 | /* assume this means it's off */ | ||
4995 | wdev->ps = false; | ||
4996 | |||
4997 | unlock_rdev: | ||
4998 | cfg80211_unlock_rdev(rdev); | ||
4999 | dev_put(dev); | ||
5000 | unlock_rtnl: | ||
5001 | rtnl_unlock(); | ||
5002 | 4257 | ||
5003 | out: | 4258 | err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state, |
4259 | wdev->ps_timeout); | ||
4260 | if (!err) | ||
4261 | wdev->ps = state; | ||
5004 | return err; | 4262 | return err; |
5005 | } | 4263 | } |
5006 | 4264 | ||
5007 | static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | 4265 | static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) |
5008 | { | 4266 | { |
5009 | struct cfg80211_registered_device *rdev; | 4267 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5010 | enum nl80211_ps_state ps_state; | 4268 | enum nl80211_ps_state ps_state; |
5011 | struct wireless_dev *wdev; | 4269 | struct wireless_dev *wdev; |
5012 | struct net_device *dev; | 4270 | struct net_device *dev = info->user_ptr[1]; |
5013 | struct sk_buff *msg; | 4271 | struct sk_buff *msg; |
5014 | void *hdr; | 4272 | void *hdr; |
5015 | int err; | 4273 | int err; |
5016 | 4274 | ||
5017 | rtnl_lock(); | ||
5018 | |||
5019 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
5020 | if (err) | ||
5021 | goto unlock_rtnl; | ||
5022 | |||
5023 | wdev = dev->ieee80211_ptr; | 4275 | wdev = dev->ieee80211_ptr; |
5024 | 4276 | ||
5025 | if (!rdev->ops->set_power_mgmt) { | 4277 | if (!rdev->ops->set_power_mgmt) |
5026 | err = -EOPNOTSUPP; | 4278 | return -EOPNOTSUPP; |
5027 | goto out; | ||
5028 | } | ||
5029 | 4279 | ||
5030 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4280 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
5031 | if (!msg) { | 4281 | if (!msg) |
5032 | err = -ENOMEM; | 4282 | return -ENOMEM; |
5033 | goto out; | ||
5034 | } | ||
5035 | 4283 | ||
5036 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4284 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
5037 | NL80211_CMD_GET_POWER_SAVE); | 4285 | NL80211_CMD_GET_POWER_SAVE); |
5038 | if (!hdr) { | 4286 | if (!hdr) { |
5039 | err = -ENOMEM; | 4287 | err = -ENOBUFS; |
5040 | goto free_msg; | 4288 | goto free_msg; |
5041 | } | 4289 | } |
5042 | 4290 | ||
@@ -5048,22 +4296,12 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | |||
5048 | NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); | 4296 | NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); |
5049 | 4297 | ||
5050 | genlmsg_end(msg, hdr); | 4298 | genlmsg_end(msg, hdr); |
5051 | err = genlmsg_reply(msg, info); | 4299 | return genlmsg_reply(msg, info); |
5052 | goto out; | ||
5053 | 4300 | ||
5054 | nla_put_failure: | 4301 | nla_put_failure: |
5055 | err = -ENOBUFS; | 4302 | err = -ENOBUFS; |
5056 | 4303 | free_msg: | |
5057 | free_msg: | ||
5058 | nlmsg_free(msg); | 4304 | nlmsg_free(msg); |
5059 | |||
5060 | out: | ||
5061 | cfg80211_unlock_rdev(rdev); | ||
5062 | dev_put(dev); | ||
5063 | |||
5064 | unlock_rtnl: | ||
5065 | rtnl_unlock(); | ||
5066 | |||
5067 | return err; | 4305 | return err; |
5068 | } | 4306 | } |
5069 | 4307 | ||
@@ -5077,42 +4315,24 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | |||
5077 | static int nl80211_set_cqm_rssi(struct genl_info *info, | 4315 | static int nl80211_set_cqm_rssi(struct genl_info *info, |
5078 | s32 threshold, u32 hysteresis) | 4316 | s32 threshold, u32 hysteresis) |
5079 | { | 4317 | { |
5080 | struct cfg80211_registered_device *rdev; | 4318 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5081 | struct wireless_dev *wdev; | 4319 | struct wireless_dev *wdev; |
5082 | struct net_device *dev; | 4320 | struct net_device *dev = info->user_ptr[1]; |
5083 | int err; | ||
5084 | 4321 | ||
5085 | if (threshold > 0) | 4322 | if (threshold > 0) |
5086 | return -EINVAL; | 4323 | return -EINVAL; |
5087 | 4324 | ||
5088 | rtnl_lock(); | ||
5089 | |||
5090 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
5091 | if (err) | ||
5092 | goto unlock_rdev; | ||
5093 | |||
5094 | wdev = dev->ieee80211_ptr; | 4325 | wdev = dev->ieee80211_ptr; |
5095 | 4326 | ||
5096 | if (!rdev->ops->set_cqm_rssi_config) { | 4327 | if (!rdev->ops->set_cqm_rssi_config) |
5097 | err = -EOPNOTSUPP; | 4328 | return -EOPNOTSUPP; |
5098 | goto unlock_rdev; | ||
5099 | } | ||
5100 | 4329 | ||
5101 | if (wdev->iftype != NL80211_IFTYPE_STATION && | 4330 | if (wdev->iftype != NL80211_IFTYPE_STATION && |
5102 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { | 4331 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
5103 | err = -EOPNOTSUPP; | 4332 | return -EOPNOTSUPP; |
5104 | goto unlock_rdev; | ||
5105 | } | ||
5106 | |||
5107 | err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, | ||
5108 | threshold, hysteresis); | ||
5109 | |||
5110 | unlock_rdev: | ||
5111 | cfg80211_unlock_rdev(rdev); | ||
5112 | dev_put(dev); | ||
5113 | rtnl_unlock(); | ||
5114 | 4333 | ||
5115 | return err; | 4334 | return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, |
4335 | threshold, hysteresis); | ||
5116 | } | 4336 | } |
5117 | 4337 | ||
5118 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | 4338 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) |
@@ -5146,6 +4366,65 @@ out: | |||
5146 | return err; | 4366 | return err; |
5147 | } | 4367 | } |
5148 | 4368 | ||
4369 | #define NL80211_FLAG_NEED_WIPHY 0x01 | ||
4370 | #define NL80211_FLAG_NEED_NETDEV 0x02 | ||
4371 | #define NL80211_FLAG_NEED_RTNL 0x04 | ||
4372 | #define NL80211_FLAG_CHECK_NETDEV_UP 0x08 | ||
4373 | #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ | ||
4374 | NL80211_FLAG_CHECK_NETDEV_UP) | ||
4375 | |||
4376 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | ||
4377 | struct genl_info *info) | ||
4378 | { | ||
4379 | struct cfg80211_registered_device *rdev; | ||
4380 | struct net_device *dev; | ||
4381 | int err; | ||
4382 | bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; | ||
4383 | |||
4384 | if (rtnl) | ||
4385 | rtnl_lock(); | ||
4386 | |||
4387 | if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { | ||
4388 | rdev = cfg80211_get_dev_from_info(info); | ||
4389 | if (IS_ERR(rdev)) { | ||
4390 | if (rtnl) | ||
4391 | rtnl_unlock(); | ||
4392 | return PTR_ERR(rdev); | ||
4393 | } | ||
4394 | info->user_ptr[0] = rdev; | ||
4395 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { | ||
4396 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4397 | if (err) { | ||
4398 | if (rtnl) | ||
4399 | rtnl_unlock(); | ||
4400 | return err; | ||
4401 | } | ||
4402 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && | ||
4403 | !netif_running(dev)) { | ||
4404 | cfg80211_unlock_rdev(rdev); | ||
4405 | dev_put(dev); | ||
4406 | if (rtnl) | ||
4407 | rtnl_unlock(); | ||
4408 | return -ENETDOWN; | ||
4409 | } | ||
4410 | info->user_ptr[0] = rdev; | ||
4411 | info->user_ptr[1] = dev; | ||
4412 | } | ||
4413 | |||
4414 | return 0; | ||
4415 | } | ||
4416 | |||
4417 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | ||
4418 | struct genl_info *info) | ||
4419 | { | ||
4420 | if (info->user_ptr[0]) | ||
4421 | cfg80211_unlock_rdev(info->user_ptr[0]); | ||
4422 | if (info->user_ptr[1]) | ||
4423 | dev_put(info->user_ptr[1]); | ||
4424 | if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) | ||
4425 | rtnl_unlock(); | ||
4426 | } | ||
4427 | |||
5149 | static struct genl_ops nl80211_ops[] = { | 4428 | static struct genl_ops nl80211_ops[] = { |
5150 | { | 4429 | { |
5151 | .cmd = NL80211_CMD_GET_WIPHY, | 4430 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -5153,12 +4432,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5153 | .dumpit = nl80211_dump_wiphy, | 4432 | .dumpit = nl80211_dump_wiphy, |
5154 | .policy = nl80211_policy, | 4433 | .policy = nl80211_policy, |
5155 | /* can be retrieved by unprivileged users */ | 4434 | /* can be retrieved by unprivileged users */ |
4435 | .internal_flags = NL80211_FLAG_NEED_WIPHY, | ||
5156 | }, | 4436 | }, |
5157 | { | 4437 | { |
5158 | .cmd = NL80211_CMD_SET_WIPHY, | 4438 | .cmd = NL80211_CMD_SET_WIPHY, |
5159 | .doit = nl80211_set_wiphy, | 4439 | .doit = nl80211_set_wiphy, |
5160 | .policy = nl80211_policy, | 4440 | .policy = nl80211_policy, |
5161 | .flags = GENL_ADMIN_PERM, | 4441 | .flags = GENL_ADMIN_PERM, |
4442 | .internal_flags = NL80211_FLAG_NEED_RTNL, | ||
5162 | }, | 4443 | }, |
5163 | { | 4444 | { |
5164 | .cmd = NL80211_CMD_GET_INTERFACE, | 4445 | .cmd = NL80211_CMD_GET_INTERFACE, |
@@ -5166,90 +4447,119 @@ static struct genl_ops nl80211_ops[] = { | |||
5166 | .dumpit = nl80211_dump_interface, | 4447 | .dumpit = nl80211_dump_interface, |
5167 | .policy = nl80211_policy, | 4448 | .policy = nl80211_policy, |
5168 | /* can be retrieved by unprivileged users */ | 4449 | /* can be retrieved by unprivileged users */ |
4450 | .internal_flags = NL80211_FLAG_NEED_NETDEV, | ||
5169 | }, | 4451 | }, |
5170 | { | 4452 | { |
5171 | .cmd = NL80211_CMD_SET_INTERFACE, | 4453 | .cmd = NL80211_CMD_SET_INTERFACE, |
5172 | .doit = nl80211_set_interface, | 4454 | .doit = nl80211_set_interface, |
5173 | .policy = nl80211_policy, | 4455 | .policy = nl80211_policy, |
5174 | .flags = GENL_ADMIN_PERM, | 4456 | .flags = GENL_ADMIN_PERM, |
4457 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4458 | NL80211_FLAG_NEED_RTNL, | ||
5175 | }, | 4459 | }, |
5176 | { | 4460 | { |
5177 | .cmd = NL80211_CMD_NEW_INTERFACE, | 4461 | .cmd = NL80211_CMD_NEW_INTERFACE, |
5178 | .doit = nl80211_new_interface, | 4462 | .doit = nl80211_new_interface, |
5179 | .policy = nl80211_policy, | 4463 | .policy = nl80211_policy, |
5180 | .flags = GENL_ADMIN_PERM, | 4464 | .flags = GENL_ADMIN_PERM, |
4465 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
4466 | NL80211_FLAG_NEED_RTNL, | ||
5181 | }, | 4467 | }, |
5182 | { | 4468 | { |
5183 | .cmd = NL80211_CMD_DEL_INTERFACE, | 4469 | .cmd = NL80211_CMD_DEL_INTERFACE, |
5184 | .doit = nl80211_del_interface, | 4470 | .doit = nl80211_del_interface, |
5185 | .policy = nl80211_policy, | 4471 | .policy = nl80211_policy, |
5186 | .flags = GENL_ADMIN_PERM, | 4472 | .flags = GENL_ADMIN_PERM, |
4473 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4474 | NL80211_FLAG_NEED_RTNL, | ||
5187 | }, | 4475 | }, |
5188 | { | 4476 | { |
5189 | .cmd = NL80211_CMD_GET_KEY, | 4477 | .cmd = NL80211_CMD_GET_KEY, |
5190 | .doit = nl80211_get_key, | 4478 | .doit = nl80211_get_key, |
5191 | .policy = nl80211_policy, | 4479 | .policy = nl80211_policy, |
5192 | .flags = GENL_ADMIN_PERM, | 4480 | .flags = GENL_ADMIN_PERM, |
4481 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4482 | NL80211_FLAG_NEED_RTNL, | ||
5193 | }, | 4483 | }, |
5194 | { | 4484 | { |
5195 | .cmd = NL80211_CMD_SET_KEY, | 4485 | .cmd = NL80211_CMD_SET_KEY, |
5196 | .doit = nl80211_set_key, | 4486 | .doit = nl80211_set_key, |
5197 | .policy = nl80211_policy, | 4487 | .policy = nl80211_policy, |
5198 | .flags = GENL_ADMIN_PERM, | 4488 | .flags = GENL_ADMIN_PERM, |
4489 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4490 | NL80211_FLAG_NEED_RTNL, | ||
5199 | }, | 4491 | }, |
5200 | { | 4492 | { |
5201 | .cmd = NL80211_CMD_NEW_KEY, | 4493 | .cmd = NL80211_CMD_NEW_KEY, |
5202 | .doit = nl80211_new_key, | 4494 | .doit = nl80211_new_key, |
5203 | .policy = nl80211_policy, | 4495 | .policy = nl80211_policy, |
5204 | .flags = GENL_ADMIN_PERM, | 4496 | .flags = GENL_ADMIN_PERM, |
4497 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4498 | NL80211_FLAG_NEED_RTNL, | ||
5205 | }, | 4499 | }, |
5206 | { | 4500 | { |
5207 | .cmd = NL80211_CMD_DEL_KEY, | 4501 | .cmd = NL80211_CMD_DEL_KEY, |
5208 | .doit = nl80211_del_key, | 4502 | .doit = nl80211_del_key, |
5209 | .policy = nl80211_policy, | 4503 | .policy = nl80211_policy, |
5210 | .flags = GENL_ADMIN_PERM, | 4504 | .flags = GENL_ADMIN_PERM, |
4505 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4506 | NL80211_FLAG_NEED_RTNL, | ||
5211 | }, | 4507 | }, |
5212 | { | 4508 | { |
5213 | .cmd = NL80211_CMD_SET_BEACON, | 4509 | .cmd = NL80211_CMD_SET_BEACON, |
5214 | .policy = nl80211_policy, | 4510 | .policy = nl80211_policy, |
5215 | .flags = GENL_ADMIN_PERM, | 4511 | .flags = GENL_ADMIN_PERM, |
5216 | .doit = nl80211_addset_beacon, | 4512 | .doit = nl80211_addset_beacon, |
4513 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4514 | NL80211_FLAG_NEED_RTNL, | ||
5217 | }, | 4515 | }, |
5218 | { | 4516 | { |
5219 | .cmd = NL80211_CMD_NEW_BEACON, | 4517 | .cmd = NL80211_CMD_NEW_BEACON, |
5220 | .policy = nl80211_policy, | 4518 | .policy = nl80211_policy, |
5221 | .flags = GENL_ADMIN_PERM, | 4519 | .flags = GENL_ADMIN_PERM, |
5222 | .doit = nl80211_addset_beacon, | 4520 | .doit = nl80211_addset_beacon, |
4521 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4522 | NL80211_FLAG_NEED_RTNL, | ||
5223 | }, | 4523 | }, |
5224 | { | 4524 | { |
5225 | .cmd = NL80211_CMD_DEL_BEACON, | 4525 | .cmd = NL80211_CMD_DEL_BEACON, |
5226 | .policy = nl80211_policy, | 4526 | .policy = nl80211_policy, |
5227 | .flags = GENL_ADMIN_PERM, | 4527 | .flags = GENL_ADMIN_PERM, |
5228 | .doit = nl80211_del_beacon, | 4528 | .doit = nl80211_del_beacon, |
4529 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4530 | NL80211_FLAG_NEED_RTNL, | ||
5229 | }, | 4531 | }, |
5230 | { | 4532 | { |
5231 | .cmd = NL80211_CMD_GET_STATION, | 4533 | .cmd = NL80211_CMD_GET_STATION, |
5232 | .doit = nl80211_get_station, | 4534 | .doit = nl80211_get_station, |
5233 | .dumpit = nl80211_dump_station, | 4535 | .dumpit = nl80211_dump_station, |
5234 | .policy = nl80211_policy, | 4536 | .policy = nl80211_policy, |
4537 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4538 | NL80211_FLAG_NEED_RTNL, | ||
5235 | }, | 4539 | }, |
5236 | { | 4540 | { |
5237 | .cmd = NL80211_CMD_SET_STATION, | 4541 | .cmd = NL80211_CMD_SET_STATION, |
5238 | .doit = nl80211_set_station, | 4542 | .doit = nl80211_set_station, |
5239 | .policy = nl80211_policy, | 4543 | .policy = nl80211_policy, |
5240 | .flags = GENL_ADMIN_PERM, | 4544 | .flags = GENL_ADMIN_PERM, |
4545 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4546 | NL80211_FLAG_NEED_RTNL, | ||
5241 | }, | 4547 | }, |
5242 | { | 4548 | { |
5243 | .cmd = NL80211_CMD_NEW_STATION, | 4549 | .cmd = NL80211_CMD_NEW_STATION, |
5244 | .doit = nl80211_new_station, | 4550 | .doit = nl80211_new_station, |
5245 | .policy = nl80211_policy, | 4551 | .policy = nl80211_policy, |
5246 | .flags = GENL_ADMIN_PERM, | 4552 | .flags = GENL_ADMIN_PERM, |
4553 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4554 | NL80211_FLAG_NEED_RTNL, | ||
5247 | }, | 4555 | }, |
5248 | { | 4556 | { |
5249 | .cmd = NL80211_CMD_DEL_STATION, | 4557 | .cmd = NL80211_CMD_DEL_STATION, |
5250 | .doit = nl80211_del_station, | 4558 | .doit = nl80211_del_station, |
5251 | .policy = nl80211_policy, | 4559 | .policy = nl80211_policy, |
5252 | .flags = GENL_ADMIN_PERM, | 4560 | .flags = GENL_ADMIN_PERM, |
4561 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4562 | NL80211_FLAG_NEED_RTNL, | ||
5253 | }, | 4563 | }, |
5254 | { | 4564 | { |
5255 | .cmd = NL80211_CMD_GET_MPATH, | 4565 | .cmd = NL80211_CMD_GET_MPATH, |
@@ -5257,30 +4567,40 @@ static struct genl_ops nl80211_ops[] = { | |||
5257 | .dumpit = nl80211_dump_mpath, | 4567 | .dumpit = nl80211_dump_mpath, |
5258 | .policy = nl80211_policy, | 4568 | .policy = nl80211_policy, |
5259 | .flags = GENL_ADMIN_PERM, | 4569 | .flags = GENL_ADMIN_PERM, |
4570 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4571 | NL80211_FLAG_NEED_RTNL, | ||
5260 | }, | 4572 | }, |
5261 | { | 4573 | { |
5262 | .cmd = NL80211_CMD_SET_MPATH, | 4574 | .cmd = NL80211_CMD_SET_MPATH, |
5263 | .doit = nl80211_set_mpath, | 4575 | .doit = nl80211_set_mpath, |
5264 | .policy = nl80211_policy, | 4576 | .policy = nl80211_policy, |
5265 | .flags = GENL_ADMIN_PERM, | 4577 | .flags = GENL_ADMIN_PERM, |
4578 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4579 | NL80211_FLAG_NEED_RTNL, | ||
5266 | }, | 4580 | }, |
5267 | { | 4581 | { |
5268 | .cmd = NL80211_CMD_NEW_MPATH, | 4582 | .cmd = NL80211_CMD_NEW_MPATH, |
5269 | .doit = nl80211_new_mpath, | 4583 | .doit = nl80211_new_mpath, |
5270 | .policy = nl80211_policy, | 4584 | .policy = nl80211_policy, |
5271 | .flags = GENL_ADMIN_PERM, | 4585 | .flags = GENL_ADMIN_PERM, |
4586 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4587 | NL80211_FLAG_NEED_RTNL, | ||
5272 | }, | 4588 | }, |
5273 | { | 4589 | { |
5274 | .cmd = NL80211_CMD_DEL_MPATH, | 4590 | .cmd = NL80211_CMD_DEL_MPATH, |
5275 | .doit = nl80211_del_mpath, | 4591 | .doit = nl80211_del_mpath, |
5276 | .policy = nl80211_policy, | 4592 | .policy = nl80211_policy, |
5277 | .flags = GENL_ADMIN_PERM, | 4593 | .flags = GENL_ADMIN_PERM, |
4594 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4595 | NL80211_FLAG_NEED_RTNL, | ||
5278 | }, | 4596 | }, |
5279 | { | 4597 | { |
5280 | .cmd = NL80211_CMD_SET_BSS, | 4598 | .cmd = NL80211_CMD_SET_BSS, |
5281 | .doit = nl80211_set_bss, | 4599 | .doit = nl80211_set_bss, |
5282 | .policy = nl80211_policy, | 4600 | .policy = nl80211_policy, |
5283 | .flags = GENL_ADMIN_PERM, | 4601 | .flags = GENL_ADMIN_PERM, |
4602 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4603 | NL80211_FLAG_NEED_RTNL, | ||
5284 | }, | 4604 | }, |
5285 | { | 4605 | { |
5286 | .cmd = NL80211_CMD_GET_REG, | 4606 | .cmd = NL80211_CMD_GET_REG, |
@@ -5305,18 +4625,24 @@ static struct genl_ops nl80211_ops[] = { | |||
5305 | .doit = nl80211_get_mesh_params, | 4625 | .doit = nl80211_get_mesh_params, |
5306 | .policy = nl80211_policy, | 4626 | .policy = nl80211_policy, |
5307 | /* can be retrieved by unprivileged users */ | 4627 | /* can be retrieved by unprivileged users */ |
4628 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4629 | NL80211_FLAG_NEED_RTNL, | ||
5308 | }, | 4630 | }, |
5309 | { | 4631 | { |
5310 | .cmd = NL80211_CMD_SET_MESH_PARAMS, | 4632 | .cmd = NL80211_CMD_SET_MESH_PARAMS, |
5311 | .doit = nl80211_set_mesh_params, | 4633 | .doit = nl80211_set_mesh_params, |
5312 | .policy = nl80211_policy, | 4634 | .policy = nl80211_policy, |
5313 | .flags = GENL_ADMIN_PERM, | 4635 | .flags = GENL_ADMIN_PERM, |
4636 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4637 | NL80211_FLAG_NEED_RTNL, | ||
5314 | }, | 4638 | }, |
5315 | { | 4639 | { |
5316 | .cmd = NL80211_CMD_TRIGGER_SCAN, | 4640 | .cmd = NL80211_CMD_TRIGGER_SCAN, |
5317 | .doit = nl80211_trigger_scan, | 4641 | .doit = nl80211_trigger_scan, |
5318 | .policy = nl80211_policy, | 4642 | .policy = nl80211_policy, |
5319 | .flags = GENL_ADMIN_PERM, | 4643 | .flags = GENL_ADMIN_PERM, |
4644 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4645 | NL80211_FLAG_NEED_RTNL, | ||
5320 | }, | 4646 | }, |
5321 | { | 4647 | { |
5322 | .cmd = NL80211_CMD_GET_SCAN, | 4648 | .cmd = NL80211_CMD_GET_SCAN, |
@@ -5328,36 +4654,48 @@ static struct genl_ops nl80211_ops[] = { | |||
5328 | .doit = nl80211_authenticate, | 4654 | .doit = nl80211_authenticate, |
5329 | .policy = nl80211_policy, | 4655 | .policy = nl80211_policy, |
5330 | .flags = GENL_ADMIN_PERM, | 4656 | .flags = GENL_ADMIN_PERM, |
4657 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4658 | NL80211_FLAG_NEED_RTNL, | ||
5331 | }, | 4659 | }, |
5332 | { | 4660 | { |
5333 | .cmd = NL80211_CMD_ASSOCIATE, | 4661 | .cmd = NL80211_CMD_ASSOCIATE, |
5334 | .doit = nl80211_associate, | 4662 | .doit = nl80211_associate, |
5335 | .policy = nl80211_policy, | 4663 | .policy = nl80211_policy, |
5336 | .flags = GENL_ADMIN_PERM, | 4664 | .flags = GENL_ADMIN_PERM, |
4665 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4666 | NL80211_FLAG_NEED_RTNL, | ||
5337 | }, | 4667 | }, |
5338 | { | 4668 | { |
5339 | .cmd = NL80211_CMD_DEAUTHENTICATE, | 4669 | .cmd = NL80211_CMD_DEAUTHENTICATE, |
5340 | .doit = nl80211_deauthenticate, | 4670 | .doit = nl80211_deauthenticate, |
5341 | .policy = nl80211_policy, | 4671 | .policy = nl80211_policy, |
5342 | .flags = GENL_ADMIN_PERM, | 4672 | .flags = GENL_ADMIN_PERM, |
4673 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4674 | NL80211_FLAG_NEED_RTNL, | ||
5343 | }, | 4675 | }, |
5344 | { | 4676 | { |
5345 | .cmd = NL80211_CMD_DISASSOCIATE, | 4677 | .cmd = NL80211_CMD_DISASSOCIATE, |
5346 | .doit = nl80211_disassociate, | 4678 | .doit = nl80211_disassociate, |
5347 | .policy = nl80211_policy, | 4679 | .policy = nl80211_policy, |
5348 | .flags = GENL_ADMIN_PERM, | 4680 | .flags = GENL_ADMIN_PERM, |
4681 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4682 | NL80211_FLAG_NEED_RTNL, | ||
5349 | }, | 4683 | }, |
5350 | { | 4684 | { |
5351 | .cmd = NL80211_CMD_JOIN_IBSS, | 4685 | .cmd = NL80211_CMD_JOIN_IBSS, |
5352 | .doit = nl80211_join_ibss, | 4686 | .doit = nl80211_join_ibss, |
5353 | .policy = nl80211_policy, | 4687 | .policy = nl80211_policy, |
5354 | .flags = GENL_ADMIN_PERM, | 4688 | .flags = GENL_ADMIN_PERM, |
4689 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4690 | NL80211_FLAG_NEED_RTNL, | ||
5355 | }, | 4691 | }, |
5356 | { | 4692 | { |
5357 | .cmd = NL80211_CMD_LEAVE_IBSS, | 4693 | .cmd = NL80211_CMD_LEAVE_IBSS, |
5358 | .doit = nl80211_leave_ibss, | 4694 | .doit = nl80211_leave_ibss, |
5359 | .policy = nl80211_policy, | 4695 | .policy = nl80211_policy, |
5360 | .flags = GENL_ADMIN_PERM, | 4696 | .flags = GENL_ADMIN_PERM, |
4697 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4698 | NL80211_FLAG_NEED_RTNL, | ||
5361 | }, | 4699 | }, |
5362 | #ifdef CONFIG_NL80211_TESTMODE | 4700 | #ifdef CONFIG_NL80211_TESTMODE |
5363 | { | 4701 | { |
@@ -5365,6 +4703,8 @@ static struct genl_ops nl80211_ops[] = { | |||
5365 | .doit = nl80211_testmode_do, | 4703 | .doit = nl80211_testmode_do, |
5366 | .policy = nl80211_policy, | 4704 | .policy = nl80211_policy, |
5367 | .flags = GENL_ADMIN_PERM, | 4705 | .flags = GENL_ADMIN_PERM, |
4706 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
4707 | NL80211_FLAG_NEED_RTNL, | ||
5368 | }, | 4708 | }, |
5369 | #endif | 4709 | #endif |
5370 | { | 4710 | { |
@@ -5372,18 +4712,24 @@ static struct genl_ops nl80211_ops[] = { | |||
5372 | .doit = nl80211_connect, | 4712 | .doit = nl80211_connect, |
5373 | .policy = nl80211_policy, | 4713 | .policy = nl80211_policy, |
5374 | .flags = GENL_ADMIN_PERM, | 4714 | .flags = GENL_ADMIN_PERM, |
4715 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4716 | NL80211_FLAG_NEED_RTNL, | ||
5375 | }, | 4717 | }, |
5376 | { | 4718 | { |
5377 | .cmd = NL80211_CMD_DISCONNECT, | 4719 | .cmd = NL80211_CMD_DISCONNECT, |
5378 | .doit = nl80211_disconnect, | 4720 | .doit = nl80211_disconnect, |
5379 | .policy = nl80211_policy, | 4721 | .policy = nl80211_policy, |
5380 | .flags = GENL_ADMIN_PERM, | 4722 | .flags = GENL_ADMIN_PERM, |
4723 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4724 | NL80211_FLAG_NEED_RTNL, | ||
5381 | }, | 4725 | }, |
5382 | { | 4726 | { |
5383 | .cmd = NL80211_CMD_SET_WIPHY_NETNS, | 4727 | .cmd = NL80211_CMD_SET_WIPHY_NETNS, |
5384 | .doit = nl80211_wiphy_netns, | 4728 | .doit = nl80211_wiphy_netns, |
5385 | .policy = nl80211_policy, | 4729 | .policy = nl80211_policy, |
5386 | .flags = GENL_ADMIN_PERM, | 4730 | .flags = GENL_ADMIN_PERM, |
4731 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
4732 | NL80211_FLAG_NEED_RTNL, | ||
5387 | }, | 4733 | }, |
5388 | { | 4734 | { |
5389 | .cmd = NL80211_CMD_GET_SURVEY, | 4735 | .cmd = NL80211_CMD_GET_SURVEY, |
@@ -5395,72 +4741,104 @@ static struct genl_ops nl80211_ops[] = { | |||
5395 | .doit = nl80211_setdel_pmksa, | 4741 | .doit = nl80211_setdel_pmksa, |
5396 | .policy = nl80211_policy, | 4742 | .policy = nl80211_policy, |
5397 | .flags = GENL_ADMIN_PERM, | 4743 | .flags = GENL_ADMIN_PERM, |
4744 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4745 | NL80211_FLAG_NEED_RTNL, | ||
5398 | }, | 4746 | }, |
5399 | { | 4747 | { |
5400 | .cmd = NL80211_CMD_DEL_PMKSA, | 4748 | .cmd = NL80211_CMD_DEL_PMKSA, |
5401 | .doit = nl80211_setdel_pmksa, | 4749 | .doit = nl80211_setdel_pmksa, |
5402 | .policy = nl80211_policy, | 4750 | .policy = nl80211_policy, |
5403 | .flags = GENL_ADMIN_PERM, | 4751 | .flags = GENL_ADMIN_PERM, |
4752 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4753 | NL80211_FLAG_NEED_RTNL, | ||
5404 | }, | 4754 | }, |
5405 | { | 4755 | { |
5406 | .cmd = NL80211_CMD_FLUSH_PMKSA, | 4756 | .cmd = NL80211_CMD_FLUSH_PMKSA, |
5407 | .doit = nl80211_flush_pmksa, | 4757 | .doit = nl80211_flush_pmksa, |
5408 | .policy = nl80211_policy, | 4758 | .policy = nl80211_policy, |
5409 | .flags = GENL_ADMIN_PERM, | 4759 | .flags = GENL_ADMIN_PERM, |
4760 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4761 | NL80211_FLAG_NEED_RTNL, | ||
5410 | }, | 4762 | }, |
5411 | { | 4763 | { |
5412 | .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, | 4764 | .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, |
5413 | .doit = nl80211_remain_on_channel, | 4765 | .doit = nl80211_remain_on_channel, |
5414 | .policy = nl80211_policy, | 4766 | .policy = nl80211_policy, |
5415 | .flags = GENL_ADMIN_PERM, | 4767 | .flags = GENL_ADMIN_PERM, |
4768 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4769 | NL80211_FLAG_NEED_RTNL, | ||
5416 | }, | 4770 | }, |
5417 | { | 4771 | { |
5418 | .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | 4772 | .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, |
5419 | .doit = nl80211_cancel_remain_on_channel, | 4773 | .doit = nl80211_cancel_remain_on_channel, |
5420 | .policy = nl80211_policy, | 4774 | .policy = nl80211_policy, |
5421 | .flags = GENL_ADMIN_PERM, | 4775 | .flags = GENL_ADMIN_PERM, |
4776 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4777 | NL80211_FLAG_NEED_RTNL, | ||
5422 | }, | 4778 | }, |
5423 | { | 4779 | { |
5424 | .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, | 4780 | .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, |
5425 | .doit = nl80211_set_tx_bitrate_mask, | 4781 | .doit = nl80211_set_tx_bitrate_mask, |
5426 | .policy = nl80211_policy, | 4782 | .policy = nl80211_policy, |
5427 | .flags = GENL_ADMIN_PERM, | 4783 | .flags = GENL_ADMIN_PERM, |
4784 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4785 | NL80211_FLAG_NEED_RTNL, | ||
5428 | }, | 4786 | }, |
5429 | { | 4787 | { |
5430 | .cmd = NL80211_CMD_REGISTER_FRAME, | 4788 | .cmd = NL80211_CMD_REGISTER_FRAME, |
5431 | .doit = nl80211_register_mgmt, | 4789 | .doit = nl80211_register_mgmt, |
5432 | .policy = nl80211_policy, | 4790 | .policy = nl80211_policy, |
5433 | .flags = GENL_ADMIN_PERM, | 4791 | .flags = GENL_ADMIN_PERM, |
4792 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4793 | NL80211_FLAG_NEED_RTNL, | ||
5434 | }, | 4794 | }, |
5435 | { | 4795 | { |
5436 | .cmd = NL80211_CMD_FRAME, | 4796 | .cmd = NL80211_CMD_FRAME, |
5437 | .doit = nl80211_tx_mgmt, | 4797 | .doit = nl80211_tx_mgmt, |
5438 | .policy = nl80211_policy, | 4798 | .policy = nl80211_policy, |
5439 | .flags = GENL_ADMIN_PERM, | 4799 | .flags = GENL_ADMIN_PERM, |
4800 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4801 | NL80211_FLAG_NEED_RTNL, | ||
5440 | }, | 4802 | }, |
5441 | { | 4803 | { |
5442 | .cmd = NL80211_CMD_SET_POWER_SAVE, | 4804 | .cmd = NL80211_CMD_SET_POWER_SAVE, |
5443 | .doit = nl80211_set_power_save, | 4805 | .doit = nl80211_set_power_save, |
5444 | .policy = nl80211_policy, | 4806 | .policy = nl80211_policy, |
5445 | .flags = GENL_ADMIN_PERM, | 4807 | .flags = GENL_ADMIN_PERM, |
4808 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4809 | NL80211_FLAG_NEED_RTNL, | ||
5446 | }, | 4810 | }, |
5447 | { | 4811 | { |
5448 | .cmd = NL80211_CMD_GET_POWER_SAVE, | 4812 | .cmd = NL80211_CMD_GET_POWER_SAVE, |
5449 | .doit = nl80211_get_power_save, | 4813 | .doit = nl80211_get_power_save, |
5450 | .policy = nl80211_policy, | 4814 | .policy = nl80211_policy, |
5451 | /* can be retrieved by unprivileged users */ | 4815 | /* can be retrieved by unprivileged users */ |
4816 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4817 | NL80211_FLAG_NEED_RTNL, | ||
5452 | }, | 4818 | }, |
5453 | { | 4819 | { |
5454 | .cmd = NL80211_CMD_SET_CQM, | 4820 | .cmd = NL80211_CMD_SET_CQM, |
5455 | .doit = nl80211_set_cqm, | 4821 | .doit = nl80211_set_cqm, |
5456 | .policy = nl80211_policy, | 4822 | .policy = nl80211_policy, |
5457 | .flags = GENL_ADMIN_PERM, | 4823 | .flags = GENL_ADMIN_PERM, |
4824 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4825 | NL80211_FLAG_NEED_RTNL, | ||
5458 | }, | 4826 | }, |
5459 | { | 4827 | { |
5460 | .cmd = NL80211_CMD_SET_CHANNEL, | 4828 | .cmd = NL80211_CMD_SET_CHANNEL, |
5461 | .doit = nl80211_set_channel, | 4829 | .doit = nl80211_set_channel, |
5462 | .policy = nl80211_policy, | 4830 | .policy = nl80211_policy, |
5463 | .flags = GENL_ADMIN_PERM, | 4831 | .flags = GENL_ADMIN_PERM, |
4832 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4833 | NL80211_FLAG_NEED_RTNL, | ||
4834 | }, | ||
4835 | { | ||
4836 | .cmd = NL80211_CMD_SET_WDS_PEER, | ||
4837 | .doit = nl80211_set_wds_peer, | ||
4838 | .policy = nl80211_policy, | ||
4839 | .flags = GENL_ADMIN_PERM, | ||
4840 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
4841 | NL80211_FLAG_NEED_RTNL, | ||
5464 | }, | 4842 | }, |
5465 | }; | 4843 | }; |
5466 | 4844 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 5ca8c7180141..503ebb86ba18 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -650,14 +650,14 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
650 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | 650 | bss = container_of(pub, struct cfg80211_internal_bss, pub); |
651 | 651 | ||
652 | spin_lock_bh(&dev->bss_lock); | 652 | spin_lock_bh(&dev->bss_lock); |
653 | if (!list_empty(&bss->list)) { | ||
654 | list_del_init(&bss->list); | ||
655 | dev->bss_generation++; | ||
656 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
653 | 657 | ||
654 | list_del(&bss->list); | 658 | kref_put(&bss->ref, bss_release); |
655 | dev->bss_generation++; | 659 | } |
656 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
657 | |||
658 | spin_unlock_bh(&dev->bss_lock); | 660 | spin_unlock_bh(&dev->bss_lock); |
659 | |||
660 | kref_put(&bss->ref, bss_release); | ||
661 | } | 661 | } |
662 | EXPORT_SYMBOL(cfg80211_unlink_bss); | 662 | EXPORT_SYMBOL(cfg80211_unlink_bss); |
663 | 663 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f161b9844542..e17b0bee6bdc 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -698,7 +698,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
698 | */ | 698 | */ |
699 | if (rdev->ops->del_key) | 699 | if (rdev->ops->del_key) |
700 | for (i = 0; i < 6; i++) | 700 | for (i = 0; i < 6; i++) |
701 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); | 701 | rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL); |
702 | 702 | ||
703 | #ifdef CONFIG_CFG80211_WEXT | 703 | #ifdef CONFIG_CFG80211_WEXT |
704 | memset(&wrqu, 0, sizeof(wrqu)); | 704 | memset(&wrqu, 0, sizeof(wrqu)); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index fb5448f7d55a..76120aeda57d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -144,19 +144,25 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) | |||
144 | 144 | ||
145 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 145 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
146 | struct key_params *params, int key_idx, | 146 | struct key_params *params, int key_idx, |
147 | const u8 *mac_addr) | 147 | bool pairwise, const u8 *mac_addr) |
148 | { | 148 | { |
149 | int i; | 149 | int i; |
150 | 150 | ||
151 | if (key_idx > 5) | 151 | if (key_idx > 5) |
152 | return -EINVAL; | 152 | return -EINVAL; |
153 | 153 | ||
154 | if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | if (pairwise && !mac_addr) | ||
158 | return -EINVAL; | ||
159 | |||
154 | /* | 160 | /* |
155 | * Disallow pairwise keys with non-zero index unless it's WEP | 161 | * Disallow pairwise keys with non-zero index unless it's WEP |
156 | * (because current deployments use pairwise WEP keys with | 162 | * (because current deployments use pairwise WEP keys with |
157 | * non-zero indizes but 802.11i clearly specifies to use zero) | 163 | * non-zero indizes but 802.11i clearly specifies to use zero) |
158 | */ | 164 | */ |
159 | if (mac_addr && key_idx && | 165 | if (pairwise && key_idx && |
160 | params->cipher != WLAN_CIPHER_SUITE_WEP40 && | 166 | params->cipher != WLAN_CIPHER_SUITE_WEP40 && |
161 | params->cipher != WLAN_CIPHER_SUITE_WEP104) | 167 | params->cipher != WLAN_CIPHER_SUITE_WEP104) |
162 | return -EINVAL; | 168 | return -EINVAL; |
@@ -677,7 +683,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | |||
677 | for (i = 0; i < 6; i++) { | 683 | for (i = 0; i < 6; i++) { |
678 | if (!wdev->connect_keys->params[i].cipher) | 684 | if (!wdev->connect_keys->params[i].cipher) |
679 | continue; | 685 | continue; |
680 | if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL, | 686 | if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL, |
681 | &wdev->connect_keys->params[i])) { | 687 | &wdev->connect_keys->params[i])) { |
682 | printk(KERN_ERR "%s: failed to set key %d\n", | 688 | printk(KERN_ERR "%s: failed to set key %d\n", |
683 | dev->name, i); | 689 | dev->name, i); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 7e5c3a45f811..6002265289c6 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev, | |||
432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
433 | 433 | ||
434 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 434 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
435 | struct net_device *dev, const u8 *addr, | 435 | struct net_device *dev, bool pairwise, |
436 | bool remove, bool tx_key, int idx, | 436 | const u8 *addr, bool remove, bool tx_key, |
437 | struct key_params *params) | 437 | int idx, struct key_params *params) |
438 | { | 438 | { |
439 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 439 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
440 | int err, i; | 440 | int err, i; |
441 | bool rejoin = false; | 441 | bool rejoin = false; |
442 | 442 | ||
443 | if (pairwise && !addr) | ||
444 | return -EINVAL; | ||
445 | |||
443 | if (!wdev->wext.keys) { | 446 | if (!wdev->wext.keys) { |
444 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), | 447 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), |
445 | GFP_KERNEL); | 448 | GFP_KERNEL); |
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
478 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | 481 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); |
479 | rejoin = true; | 482 | rejoin = true; |
480 | } | 483 | } |
481 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | 484 | |
485 | if (!pairwise && addr && | ||
486 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
487 | err = -ENOENT; | ||
488 | else | ||
489 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, | ||
490 | pairwise, addr); | ||
482 | } | 491 | } |
483 | wdev->wext.connect.privacy = false; | 492 | wdev->wext.connect.privacy = false; |
484 | /* | 493 | /* |
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
507 | if (addr) | 516 | if (addr) |
508 | tx_key = false; | 517 | tx_key = false; |
509 | 518 | ||
510 | if (cfg80211_validate_key_settings(rdev, params, idx, addr)) | 519 | if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr)) |
511 | return -EINVAL; | 520 | return -EINVAL; |
512 | 521 | ||
513 | err = 0; | 522 | err = 0; |
514 | if (wdev->current_bss) | 523 | if (wdev->current_bss) |
515 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); | 524 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, |
525 | pairwise, addr, params); | ||
516 | if (err) | 526 | if (err) |
517 | return err; | 527 | return err; |
518 | 528 | ||
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
563 | } | 573 | } |
564 | 574 | ||
565 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 575 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
566 | struct net_device *dev, const u8 *addr, | 576 | struct net_device *dev, bool pairwise, |
567 | bool remove, bool tx_key, int idx, | 577 | const u8 *addr, bool remove, bool tx_key, |
568 | struct key_params *params) | 578 | int idx, struct key_params *params) |
569 | { | 579 | { |
570 | int err; | 580 | int err; |
571 | 581 | ||
572 | /* devlist mutex needed for possible IBSS re-join */ | 582 | /* devlist mutex needed for possible IBSS re-join */ |
573 | mutex_lock(&rdev->devlist_mtx); | 583 | mutex_lock(&rdev->devlist_mtx); |
574 | wdev_lock(dev->ieee80211_ptr); | 584 | wdev_lock(dev->ieee80211_ptr); |
575 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, | 585 | err = __cfg80211_set_encryption(rdev, dev, pairwise, addr, |
576 | tx_key, idx, params); | 586 | remove, tx_key, idx, params); |
577 | wdev_unlock(dev->ieee80211_ptr); | 587 | wdev_unlock(dev->ieee80211_ptr); |
578 | mutex_unlock(&rdev->devlist_mtx); | 588 | mutex_unlock(&rdev->devlist_mtx); |
579 | 589 | ||
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
635 | else if (!remove) | 645 | else if (!remove) |
636 | return -EINVAL; | 646 | return -EINVAL; |
637 | 647 | ||
638 | return cfg80211_set_encryption(rdev, dev, NULL, remove, | 648 | return cfg80211_set_encryption(rdev, dev, false, NULL, remove, |
639 | wdev->wext.default_key == -1, | 649 | wdev->wext.default_key == -1, |
640 | idx, ¶ms); | 650 | idx, ¶ms); |
641 | } | 651 | } |
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev, | |||
725 | } | 735 | } |
726 | 736 | ||
727 | return cfg80211_set_encryption( | 737 | return cfg80211_set_encryption( |
728 | rdev, dev, addr, remove, | 738 | rdev, dev, |
739 | !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY), | ||
740 | addr, remove, | ||
729 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, | 741 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, |
730 | idx, ¶ms); | 742 | idx, ¶ms); |
731 | } | 743 | } |