aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-02-15 09:50:42 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2015-02-15 09:50:42 -0500
commit139e170da98a23c3ce9ecb68cf042bdad10ce647 (patch)
tree0c6d4d070d3a98e320c0922475b1ba77877ee5d8
parent7777d8c7ef6fc12e9336ac29289d83ff54974f8f (diff)
ath10k: add TxBF support
If firmware advertises support for TxBF then the driver has to instruct the firmware accordingly during runtime. Without this patch connecting to an AP with beamformer support would yield abysmal Rx performance. This has been tested with wmi-tlv and qca6174 while acting as a STA beamformee only. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c79
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h5
2 files changed, 84 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index a367450ec611..f9c1507478ea 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1779,6 +1779,68 @@ static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
1779 ath10k_smps_map[smps]); 1779 ath10k_smps_map[smps]);
1780} 1780}
1781 1781
1782static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
1783 struct ieee80211_vif *vif,
1784 struct ieee80211_sta_vht_cap vht_cap)
1785{
1786 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
1787 int ret;
1788 u32 param;
1789 u32 value;
1790
1791 if (!(ar->vht_cap_info &
1792 (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
1793 IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
1794 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
1795 IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
1796 return 0;
1797
1798 param = ar->wmi.vdev_param->txbf;
1799 value = 0;
1800
1801 if (WARN_ON(param == WMI_VDEV_PARAM_UNSUPPORTED))
1802 return 0;
1803
1804 /* The following logic is correct. If a remote STA advertises support
1805 * for being a beamformer then we should enable us being a beamformee.
1806 */
1807
1808 if (ar->vht_cap_info &
1809 (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
1810 IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
1811 if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
1812 value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
1813
1814 if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
1815 value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
1816 }
1817
1818 if (ar->vht_cap_info &
1819 (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
1820 IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
1821 if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
1822 value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
1823
1824 if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
1825 value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
1826 }
1827
1828 if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFEE)
1829 value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
1830
1831 if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFER)
1832 value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
1833
1834 ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, value);
1835 if (ret) {
1836 ath10k_warn(ar, "failed to submit vdev param txbf 0x%x: %d\n",
1837 value, ret);
1838 return ret;
1839 }
1840
1841 return 0;
1842}
1843
1782/* can be called only in mac80211 callbacks due to `key_count` usage */ 1844/* can be called only in mac80211 callbacks due to `key_count` usage */
1783static void ath10k_bss_assoc(struct ieee80211_hw *hw, 1845static void ath10k_bss_assoc(struct ieee80211_hw *hw,
1784 struct ieee80211_vif *vif, 1846 struct ieee80211_vif *vif,
@@ -1787,6 +1849,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
1787 struct ath10k *ar = hw->priv; 1849 struct ath10k *ar = hw->priv;
1788 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); 1850 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
1789 struct ieee80211_sta_ht_cap ht_cap; 1851 struct ieee80211_sta_ht_cap ht_cap;
1852 struct ieee80211_sta_vht_cap vht_cap;
1790 struct wmi_peer_assoc_complete_arg peer_arg; 1853 struct wmi_peer_assoc_complete_arg peer_arg;
1791 struct ieee80211_sta *ap_sta; 1854 struct ieee80211_sta *ap_sta;
1792 int ret; 1855 int ret;
@@ -1809,6 +1872,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
1809 /* ap_sta must be accessed only within rcu section which must be left 1872 /* ap_sta must be accessed only within rcu section which must be left
1810 * before calling ath10k_setup_peer_smps() which might sleep. */ 1873 * before calling ath10k_setup_peer_smps() which might sleep. */
1811 ht_cap = ap_sta->ht_cap; 1874 ht_cap = ap_sta->ht_cap;
1875 vht_cap = ap_sta->vht_cap;
1812 1876
1813 ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg); 1877 ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
1814 if (ret) { 1878 if (ret) {
@@ -1834,6 +1898,13 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
1834 return; 1898 return;
1835 } 1899 }
1836 1900
1901 ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
1902 if (ret) {
1903 ath10k_warn(ar, "failed to recalc txbf for vdev %i on bss %pM: %d\n",
1904 arvif->vdev_id, bss_conf->bssid, ret);
1905 return;
1906 }
1907
1837 ath10k_dbg(ar, ATH10K_DBG_MAC, 1908 ath10k_dbg(ar, ATH10K_DBG_MAC,
1838 "mac vdev %d up (associated) bssid %pM aid %d\n", 1909 "mac vdev %d up (associated) bssid %pM aid %d\n",
1839 arvif->vdev_id, bss_conf->bssid, bss_conf->aid); 1910 arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
@@ -1858,6 +1929,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
1858{ 1929{
1859 struct ath10k *ar = hw->priv; 1930 struct ath10k *ar = hw->priv;
1860 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); 1931 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
1932 struct ieee80211_sta_vht_cap vht_cap = {};
1861 int ret; 1933 int ret;
1862 1934
1863 lockdep_assert_held(&ar->conf_mutex); 1935 lockdep_assert_held(&ar->conf_mutex);
@@ -1872,6 +1944,13 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
1872 1944
1873 arvif->def_wep_key_idx = -1; 1945 arvif->def_wep_key_idx = -1;
1874 1946
1947 ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
1948 if (ret) {
1949 ath10k_warn(ar, "failed to recalc txbf for vdev %i: %d\n",
1950 arvif->vdev_id, ret);
1951 return;
1952 }
1953
1875 arvif->is_up = false; 1954 arvif->is_up = false;
1876} 1955}
1877 1956
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 0eb0959275aa..28c1822af6cf 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3749,6 +3749,11 @@ enum wmi_10x_vdev_param {
3749 WMI_10X_VDEV_PARAM_VHT80_RATEMASK, 3749 WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
3750}; 3750};
3751 3751
3752#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
3753#define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
3754#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
3755#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
3756
3752/* slot time long */ 3757/* slot time long */
3753#define WMI_VDEV_SLOT_TIME_LONG 0x1 3758#define WMI_VDEV_SLOT_TIME_LONG 0x1
3754/* slot time short */ 3759/* slot time short */