diff options
author | David S. Miller <davem@davemloft.net> | 2010-11-16 12:17:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-11-16 12:17:12 -0500 |
commit | b5e4156743c5d42b736936be7a9ee8d72e0e4ac9 (patch) | |
tree | f0edde33e7b2502ab35a4f63be1a8be31f5f4b6a /drivers/net/wireless/wl12xx/wl1271_main.c | |
parent | 6b35308850e1679741e8b646cfb7bb3ab5369888 (diff) | |
parent | b1d771ee33c6e4006676002b9d74abf45b71d3d6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 220 |
1 files changed, 177 insertions, 43 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 48a4b9961ae6..f5b1d19bc88d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -481,9 +481,9 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
481 | total += cnt; | 481 | total += cnt; |
482 | } | 482 | } |
483 | 483 | ||
484 | /* if more blocks are available now, schedule some tx work */ | 484 | /* if more blocks are available now, tx work can be scheduled */ |
485 | if (total && !skb_queue_empty(&wl->tx_queue)) | 485 | if (total) |
486 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 486 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
487 | 487 | ||
488 | /* update the host-chipset time offset */ | 488 | /* update the host-chipset time offset */ |
489 | getnstimeofday(&ts); | 489 | getnstimeofday(&ts); |
@@ -529,6 +529,15 @@ static void wl1271_irq_work(struct work_struct *work) | |||
529 | 529 | ||
530 | intr &= WL1271_INTR_MASK; | 530 | intr &= WL1271_INTR_MASK; |
531 | 531 | ||
532 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { | ||
533 | wl1271_error("watchdog interrupt received! " | ||
534 | "starting recovery."); | ||
535 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
536 | |||
537 | /* restarting the chip. ignore any other interrupt. */ | ||
538 | goto out; | ||
539 | } | ||
540 | |||
532 | if (intr & WL1271_ACX_INTR_DATA) { | 541 | if (intr & WL1271_ACX_INTR_DATA) { |
533 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 542 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
534 | 543 | ||
@@ -537,6 +546,16 @@ static void wl1271_irq_work(struct work_struct *work) | |||
537 | (wl->tx_results_count & 0xff)) | 546 | (wl->tx_results_count & 0xff)) |
538 | wl1271_tx_complete(wl); | 547 | wl1271_tx_complete(wl); |
539 | 548 | ||
549 | /* Check if any tx blocks were freed */ | ||
550 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | ||
551 | !skb_queue_empty(&wl->tx_queue)) { | ||
552 | /* | ||
553 | * In order to avoid starvation of the TX path, | ||
554 | * call the work function directly. | ||
555 | */ | ||
556 | wl1271_tx_work_locked(wl); | ||
557 | } | ||
558 | |||
540 | wl1271_rx(wl, wl->fw_status); | 559 | wl1271_rx(wl, wl->fw_status); |
541 | } | 560 | } |
542 | 561 | ||
@@ -851,12 +870,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
851 | struct ieee80211_sta *sta = txinfo->control.sta; | 870 | struct ieee80211_sta *sta = txinfo->control.sta; |
852 | unsigned long flags; | 871 | unsigned long flags; |
853 | 872 | ||
854 | /* peek into the rates configured in the STA entry */ | 873 | /* |
874 | * peek into the rates configured in the STA entry. | ||
875 | * The rates set after connection stage, The first block only BG sets: | ||
876 | * the compare is for bit 0-16 of sta_rate_set. The second block add | ||
877 | * HT rates in case of HT supported. | ||
878 | */ | ||
855 | spin_lock_irqsave(&wl->wl_lock, flags); | 879 | spin_lock_irqsave(&wl->wl_lock, flags); |
856 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | 880 | if (sta && |
881 | (sta->supp_rates[conf->channel->band] != | ||
882 | (wl->sta_rate_set & HW_BG_RATES_MASK))) { | ||
857 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | 883 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; |
858 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | 884 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); |
859 | } | 885 | } |
886 | |||
887 | #ifdef CONFIG_WL1271_HT | ||
888 | if (sta && | ||
889 | sta->ht_cap.ht_supported && | ||
890 | ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) != | ||
891 | sta->ht_cap.mcs.rx_mask[0])) { | ||
892 | /* Clean MCS bits before setting them */ | ||
893 | wl->sta_rate_set &= HW_BG_RATES_MASK; | ||
894 | wl->sta_rate_set |= | ||
895 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); | ||
896 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
897 | } | ||
898 | #endif | ||
860 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 899 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
861 | 900 | ||
862 | /* queue the packet */ | 901 | /* queue the packet */ |
@@ -867,7 +906,8 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
867 | * before that, the tx_work will not be initialized! | 906 | * before that, the tx_work will not be initialized! |
868 | */ | 907 | */ |
869 | 908 | ||
870 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 909 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) |
910 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
871 | 911 | ||
872 | /* | 912 | /* |
873 | * The workqueue is slow to process the tx_queue and we need stop | 913 | * The workqueue is slow to process the tx_queue and we need stop |
@@ -919,18 +959,19 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
919 | struct wiphy *wiphy = hw->wiphy; | 959 | struct wiphy *wiphy = hw->wiphy; |
920 | int retries = WL1271_BOOT_RETRIES; | 960 | int retries = WL1271_BOOT_RETRIES; |
921 | int ret = 0; | 961 | int ret = 0; |
962 | bool booted = false; | ||
922 | 963 | ||
923 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 964 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
924 | vif->type, vif->addr); | 965 | vif->type, vif->addr); |
925 | 966 | ||
926 | mutex_lock(&wl->mutex); | 967 | mutex_lock(&wl->mutex); |
927 | if (wl->vif) { | 968 | if (wl->vif) { |
969 | wl1271_debug(DEBUG_MAC80211, | ||
970 | "multiple vifs are not supported yet"); | ||
928 | ret = -EBUSY; | 971 | ret = -EBUSY; |
929 | goto out; | 972 | goto out; |
930 | } | 973 | } |
931 | 974 | ||
932 | wl->vif = vif; | ||
933 | |||
934 | switch (vif->type) { | 975 | switch (vif->type) { |
935 | case NL80211_IFTYPE_STATION: | 976 | case NL80211_IFTYPE_STATION: |
936 | wl->bss_type = BSS_TYPE_STA_BSS; | 977 | wl->bss_type = BSS_TYPE_STA_BSS; |
@@ -968,15 +1009,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
968 | if (ret < 0) | 1009 | if (ret < 0) |
969 | goto irq_disable; | 1010 | goto irq_disable; |
970 | 1011 | ||
971 | wl->state = WL1271_STATE_ON; | 1012 | booted = true; |
972 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 1013 | break; |
973 | |||
974 | /* update hw/fw version info in wiphy struct */ | ||
975 | wiphy->hw_version = wl->chip.id; | ||
976 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | ||
977 | sizeof(wiphy->fw_version)); | ||
978 | |||
979 | goto out; | ||
980 | 1014 | ||
981 | irq_disable: | 1015 | irq_disable: |
982 | wl1271_disable_interrupts(wl); | 1016 | wl1271_disable_interrupts(wl); |
@@ -994,8 +1028,21 @@ power_off: | |||
994 | wl1271_power_off(wl); | 1028 | wl1271_power_off(wl); |
995 | } | 1029 | } |
996 | 1030 | ||
997 | wl1271_error("firmware boot failed despite %d retries", | 1031 | if (!booted) { |
998 | WL1271_BOOT_RETRIES); | 1032 | wl1271_error("firmware boot failed despite %d retries", |
1033 | WL1271_BOOT_RETRIES); | ||
1034 | goto out; | ||
1035 | } | ||
1036 | |||
1037 | wl->vif = vif; | ||
1038 | wl->state = WL1271_STATE_ON; | ||
1039 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | ||
1040 | |||
1041 | /* update hw/fw version info in wiphy struct */ | ||
1042 | wiphy->hw_version = wl->chip.id; | ||
1043 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | ||
1044 | sizeof(wiphy->fw_version)); | ||
1045 | |||
999 | out: | 1046 | out: |
1000 | mutex_unlock(&wl->mutex); | 1047 | mutex_unlock(&wl->mutex); |
1001 | 1048 | ||
@@ -1025,6 +1072,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1025 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 1072 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
1026 | kfree(wl->scan.scanned_ch); | 1073 | kfree(wl->scan.scanned_ch); |
1027 | wl->scan.scanned_ch = NULL; | 1074 | wl->scan.scanned_ch = NULL; |
1075 | wl->scan.req = NULL; | ||
1028 | ieee80211_scan_completed(wl->hw, true); | 1076 | ieee80211_scan_completed(wl->hw, true); |
1029 | } | 1077 | } |
1030 | 1078 | ||
@@ -1312,8 +1360,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1312 | 1360 | ||
1313 | mutex_lock(&wl->mutex); | 1361 | mutex_lock(&wl->mutex); |
1314 | 1362 | ||
1315 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 1363 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
1364 | ret = -EAGAIN; | ||
1316 | goto out; | 1365 | goto out; |
1366 | } | ||
1317 | 1367 | ||
1318 | ret = wl1271_ps_elp_wakeup(wl, false); | 1368 | ret = wl1271_ps_elp_wakeup(wl, false); |
1319 | if (ret < 0) | 1369 | if (ret < 0) |
@@ -1536,6 +1586,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1536 | 1586 | ||
1537 | mutex_lock(&wl->mutex); | 1587 | mutex_lock(&wl->mutex); |
1538 | 1588 | ||
1589 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | ||
1590 | ret = -EAGAIN; | ||
1591 | goto out_unlock; | ||
1592 | } | ||
1593 | |||
1539 | ret = wl1271_ps_elp_wakeup(wl, false); | 1594 | ret = wl1271_ps_elp_wakeup(wl, false); |
1540 | if (ret < 0) | 1595 | if (ret < 0) |
1541 | goto out_unlock; | 1596 | goto out_unlock; |
@@ -1645,6 +1700,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1645 | 1700 | ||
1646 | mutex_lock(&wl->mutex); | 1701 | mutex_lock(&wl->mutex); |
1647 | 1702 | ||
1703 | if (wl->state == WL1271_STATE_OFF) { | ||
1704 | /* | ||
1705 | * We cannot return -EBUSY here because cfg80211 will expect | ||
1706 | * a call to ieee80211_scan_completed if we do - in this case | ||
1707 | * there won't be any call. | ||
1708 | */ | ||
1709 | ret = -EAGAIN; | ||
1710 | goto out; | ||
1711 | } | ||
1712 | |||
1648 | ret = wl1271_ps_elp_wakeup(wl, false); | 1713 | ret = wl1271_ps_elp_wakeup(wl, false); |
1649 | if (ret < 0) | 1714 | if (ret < 0) |
1650 | goto out; | 1715 | goto out; |
@@ -1666,8 +1731,10 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
1666 | 1731 | ||
1667 | mutex_lock(&wl->mutex); | 1732 | mutex_lock(&wl->mutex); |
1668 | 1733 | ||
1669 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 1734 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
1735 | ret = -EAGAIN; | ||
1670 | goto out; | 1736 | goto out; |
1737 | } | ||
1671 | 1738 | ||
1672 | ret = wl1271_ps_elp_wakeup(wl, false); | 1739 | ret = wl1271_ps_elp_wakeup(wl, false); |
1673 | if (ret < 0) | 1740 | if (ret < 0) |
@@ -1709,6 +1776,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1709 | { | 1776 | { |
1710 | enum wl1271_cmd_ps_mode mode; | 1777 | enum wl1271_cmd_ps_mode mode; |
1711 | struct wl1271 *wl = hw->priv; | 1778 | struct wl1271 *wl = hw->priv; |
1779 | struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
1712 | bool do_join = false; | 1780 | bool do_join = false; |
1713 | bool set_assoc = false; | 1781 | bool set_assoc = false; |
1714 | int ret; | 1782 | int ret; |
@@ -1717,6 +1785,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1717 | 1785 | ||
1718 | mutex_lock(&wl->mutex); | 1786 | mutex_lock(&wl->mutex); |
1719 | 1787 | ||
1788 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1789 | goto out; | ||
1790 | |||
1720 | ret = wl1271_ps_elp_wakeup(wl, false); | 1791 | ret = wl1271_ps_elp_wakeup(wl, false); |
1721 | if (ret < 0) | 1792 | if (ret < 0) |
1722 | goto out; | 1793 | goto out; |
@@ -1927,6 +1998,37 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1927 | } | 1998 | } |
1928 | } | 1999 | } |
1929 | 2000 | ||
2001 | /* | ||
2002 | * Takes care of: New association with HT enable, | ||
2003 | * HT information change in beacon. | ||
2004 | */ | ||
2005 | if (sta && | ||
2006 | (changed & BSS_CHANGED_HT) && | ||
2007 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | ||
2008 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true); | ||
2009 | if (ret < 0) { | ||
2010 | wl1271_warning("Set ht cap true failed %d", ret); | ||
2011 | goto out_sleep; | ||
2012 | } | ||
2013 | ret = wl1271_acx_set_ht_information(wl, | ||
2014 | bss_conf->ht_operation_mode); | ||
2015 | if (ret < 0) { | ||
2016 | wl1271_warning("Set ht information failed %d", ret); | ||
2017 | goto out_sleep; | ||
2018 | } | ||
2019 | } | ||
2020 | /* | ||
2021 | * Takes care of: New association without HT, | ||
2022 | * Disassociation. | ||
2023 | */ | ||
2024 | else if (sta && (changed & BSS_CHANGED_ASSOC)) { | ||
2025 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false); | ||
2026 | if (ret < 0) { | ||
2027 | wl1271_warning("Set ht cap false failed %d", ret); | ||
2028 | goto out_sleep; | ||
2029 | } | ||
2030 | } | ||
2031 | |||
1930 | if (changed & BSS_CHANGED_ARP_FILTER) { | 2032 | if (changed & BSS_CHANGED_ARP_FILTER) { |
1931 | __be32 addr = bss_conf->arp_addr_list[0]; | 2033 | __be32 addr = bss_conf->arp_addr_list[0]; |
1932 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | 2034 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); |
@@ -1966,6 +2068,11 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1966 | 2068 | ||
1967 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | 2069 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); |
1968 | 2070 | ||
2071 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | ||
2072 | ret = -EAGAIN; | ||
2073 | goto out; | ||
2074 | } | ||
2075 | |||
1969 | ret = wl1271_ps_elp_wakeup(wl, false); | 2076 | ret = wl1271_ps_elp_wakeup(wl, false); |
1970 | if (ret < 0) | 2077 | if (ret < 0) |
1971 | goto out; | 2078 | goto out; |
@@ -2009,6 +2116,9 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) | |||
2009 | 2116 | ||
2010 | mutex_lock(&wl->mutex); | 2117 | mutex_lock(&wl->mutex); |
2011 | 2118 | ||
2119 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2120 | goto out; | ||
2121 | |||
2012 | ret = wl1271_ps_elp_wakeup(wl, false); | 2122 | ret = wl1271_ps_elp_wakeup(wl, false); |
2013 | if (ret < 0) | 2123 | if (ret < 0) |
2014 | goto out; | 2124 | goto out; |
@@ -2030,14 +2140,14 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | |||
2030 | { | 2140 | { |
2031 | struct wl1271 *wl = hw->priv; | 2141 | struct wl1271 *wl = hw->priv; |
2032 | struct ieee80211_conf *conf = &hw->conf; | 2142 | struct ieee80211_conf *conf = &hw->conf; |
2033 | 2143 | ||
2034 | if (idx != 0) | 2144 | if (idx != 0) |
2035 | return -ENOENT; | 2145 | return -ENOENT; |
2036 | 2146 | ||
2037 | survey->channel = conf->channel; | 2147 | survey->channel = conf->channel; |
2038 | survey->filled = SURVEY_INFO_NOISE_DBM; | 2148 | survey->filled = SURVEY_INFO_NOISE_DBM; |
2039 | survey->noise = wl->noise; | 2149 | survey->noise = wl->noise; |
2040 | 2150 | ||
2041 | return 0; | 2151 | return 0; |
2042 | } | 2152 | } |
2043 | 2153 | ||
@@ -2107,14 +2217,14 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
2107 | /* mapping to indexes for wl1271_rates */ | 2217 | /* mapping to indexes for wl1271_rates */ |
2108 | static const u8 wl1271_rate_to_idx_2ghz[] = { | 2218 | static const u8 wl1271_rate_to_idx_2ghz[] = { |
2109 | /* MCS rates are used only with 11n */ | 2219 | /* MCS rates are used only with 11n */ |
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | 2220 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ |
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | 2221 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ |
2112 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | 2222 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ |
2113 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | 2223 | 4, /* CONF_HW_RXTX_RATE_MCS4 */ |
2114 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | 2224 | 3, /* CONF_HW_RXTX_RATE_MCS3 */ |
2115 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | 2225 | 2, /* CONF_HW_RXTX_RATE_MCS2 */ |
2116 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | 2226 | 1, /* CONF_HW_RXTX_RATE_MCS1 */ |
2117 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | 2227 | 0, /* CONF_HW_RXTX_RATE_MCS0 */ |
2118 | 2228 | ||
2119 | 11, /* CONF_HW_RXTX_RATE_54 */ | 2229 | 11, /* CONF_HW_RXTX_RATE_54 */ |
2120 | 10, /* CONF_HW_RXTX_RATE_48 */ | 2230 | 10, /* CONF_HW_RXTX_RATE_48 */ |
@@ -2134,12 +2244,34 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { | |||
2134 | 0 /* CONF_HW_RXTX_RATE_1 */ | 2244 | 0 /* CONF_HW_RXTX_RATE_1 */ |
2135 | }; | 2245 | }; |
2136 | 2246 | ||
2247 | /* 11n STA capabilities */ | ||
2248 | #define HW_RX_HIGHEST_RATE 72 | ||
2249 | |||
2250 | #ifdef CONFIG_WL1271_HT | ||
2251 | #define WL1271_HT_CAP { \ | ||
2252 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ | ||
2253 | .ht_supported = true, \ | ||
2254 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ | ||
2255 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | ||
2256 | .mcs = { \ | ||
2257 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ | ||
2258 | .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \ | ||
2259 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
2260 | }, \ | ||
2261 | } | ||
2262 | #else | ||
2263 | #define WL1271_HT_CAP { \ | ||
2264 | .ht_supported = false, \ | ||
2265 | } | ||
2266 | #endif | ||
2267 | |||
2137 | /* can't be const, mac80211 writes to this */ | 2268 | /* can't be const, mac80211 writes to this */ |
2138 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2269 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
2139 | .channels = wl1271_channels, | 2270 | .channels = wl1271_channels, |
2140 | .n_channels = ARRAY_SIZE(wl1271_channels), | 2271 | .n_channels = ARRAY_SIZE(wl1271_channels), |
2141 | .bitrates = wl1271_rates, | 2272 | .bitrates = wl1271_rates, |
2142 | .n_bitrates = ARRAY_SIZE(wl1271_rates), | 2273 | .n_bitrates = ARRAY_SIZE(wl1271_rates), |
2274 | .ht_cap = WL1271_HT_CAP, | ||
2143 | }; | 2275 | }; |
2144 | 2276 | ||
2145 | /* 5 GHz data rates for WL1273 */ | 2277 | /* 5 GHz data rates for WL1273 */ |
@@ -2222,14 +2354,14 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
2222 | /* mapping to indexes for wl1271_rates_5ghz */ | 2354 | /* mapping to indexes for wl1271_rates_5ghz */ |
2223 | static const u8 wl1271_rate_to_idx_5ghz[] = { | 2355 | static const u8 wl1271_rate_to_idx_5ghz[] = { |
2224 | /* MCS rates are used only with 11n */ | 2356 | /* MCS rates are used only with 11n */ |
2225 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | 2357 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ |
2226 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | 2358 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ |
2227 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | 2359 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ |
2228 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | 2360 | 4, /* CONF_HW_RXTX_RATE_MCS4 */ |
2229 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | 2361 | 3, /* CONF_HW_RXTX_RATE_MCS3 */ |
2230 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | 2362 | 2, /* CONF_HW_RXTX_RATE_MCS2 */ |
2231 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | 2363 | 1, /* CONF_HW_RXTX_RATE_MCS1 */ |
2232 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | 2364 | 0, /* CONF_HW_RXTX_RATE_MCS0 */ |
2233 | 2365 | ||
2234 | 7, /* CONF_HW_RXTX_RATE_54 */ | 2366 | 7, /* CONF_HW_RXTX_RATE_54 */ |
2235 | 6, /* CONF_HW_RXTX_RATE_48 */ | 2367 | 6, /* CONF_HW_RXTX_RATE_48 */ |
@@ -2254,6 +2386,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
2254 | .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), | 2386 | .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), |
2255 | .bitrates = wl1271_rates_5ghz, | 2387 | .bitrates = wl1271_rates_5ghz, |
2256 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2388 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
2389 | .ht_cap = WL1271_HT_CAP, | ||
2257 | }; | 2390 | }; |
2258 | 2391 | ||
2259 | static const u8 *wl1271_band_rate_to_idx[] = { | 2392 | static const u8 *wl1271_band_rate_to_idx[] = { |
@@ -2281,18 +2414,18 @@ static const struct ieee80211_ops wl1271_ops = { | |||
2281 | }; | 2414 | }; |
2282 | 2415 | ||
2283 | 2416 | ||
2284 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | 2417 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band) |
2285 | { | 2418 | { |
2286 | u8 idx; | 2419 | u8 idx; |
2287 | 2420 | ||
2288 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | 2421 | BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); |
2289 | 2422 | ||
2290 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | 2423 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { |
2291 | wl1271_error("Illegal RX rate from HW: %d", rate); | 2424 | wl1271_error("Illegal RX rate from HW: %d", rate); |
2292 | return 0; | 2425 | return 0; |
2293 | } | 2426 | } |
2294 | 2427 | ||
2295 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | 2428 | idx = wl1271_band_rate_to_idx[band][rate]; |
2296 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | 2429 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { |
2297 | wl1271_error("Unsupported RX rate from HW: %d", rate); | 2430 | wl1271_error("Unsupported RX rate from HW: %d", rate); |
2298 | return 0; | 2431 | return 0; |
@@ -2521,6 +2654,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2521 | wl->sg_enabled = true; | 2654 | wl->sg_enabled = true; |
2522 | wl->hw_pg_ver = -1; | 2655 | wl->hw_pg_ver = -1; |
2523 | 2656 | ||
2657 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | ||
2524 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2658 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
2525 | wl->tx_frames[i] = NULL; | 2659 | wl->tx_frames[i] = NULL; |
2526 | 2660 | ||