From 5a3d83fe47405b9eb449ede2cc2a1303072d4e7e Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 20 Mar 2017 09:44:11 -0700 Subject: [PATCH] ath10k: ps-hack, scan busy work-around. The ps-hack is not available in public firmware at this time, so ignore that for now. The scan-busy work around might fix stuck scan issues when using CT firmware (since stock firmware does not return a useful error code in busy firmware case as far as I know.) Signed-off-by: Ben Greear --- ath10k/core.c | 3 +++ ath10k/core.h | 1 + ath10k/debug.c | 6 +++++ ath10k/mac.c | 69 ++++++++++++++++++++++++++++++++++++++++---------- ath10k/wmi.c | 28 +++++++++++++++++--- ath10k/wmi.h | 7 ++++- 6 files changed, 96 insertions(+), 18 deletions(-) diff --git a/ath10k/core.c b/ath10k/core.c index cf7c4f4..977f6a5 100644 --- a/ath10k/core.c +++ b/ath10k/core.c @@ -2382,6 +2382,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, if (ar->eeprom_overrides.wmi_wd_keepalive_ms) ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_WMI_WD, ar->eeprom_overrides.wmi_wd_keepalive_ms); + if (ar->eeprom_overrides.ct_pshack) + ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_PSHACK, + ar->eeprom_overrides.ct_pshack); } return 0; diff --git a/ath10k/core.h b/ath10k/core.h index 33ff66d..226f682 100644 --- a/ath10k/core.h +++ b/ath10k/core.h @@ -1136,6 +1136,7 @@ struct ath10k { * 0 means use whatever firmware defaults to (probably 8000). * Units are actually 1/1024 of a second, but pretty close to ms, at least. */ + u32 ct_pshack; } eeprom_overrides; /* must be last */ diff --git a/ath10k/debug.c b/ath10k/debug.c index af2da82..a7e234f 100644 --- a/ath10k/debug.c +++ b/ath10k/debug.c @@ -2990,6 +2990,10 @@ static ssize_t ath10k_write_ct_special(struct file *file, if (val == 0xFFFFFFFF) val = 0; /* 0xFFFFFFFF means disable, FW uses 0 to mean disable */ } + else if (id == SET_SPECIAL_ID_PSHACK) { + ar->eeprom_overrides.ct_pshack = val; + ath10k_warn(ar, "Setting CT-PSHACK override to 0x%x\n", val); + } /* Below here are local driver hacks, and not necessarily passed directly to firmware. */ else if (id == 0x1001) { /* Set station failed-transmit kickout threshold. */ @@ -3040,6 +3044,8 @@ static ssize_t ath10k_read_ct_special(struct file *file, "id: 9 pdev failed retry threshold, U16, 10.1 firmware default is 0x40\n" "id: 0xA Enable(1)/Disable(0) baseband RIFS. Default is disabled.\n" "id: 0xB WMI WD Keepalive(ms): 0xFFFFFFFF disables, otherwise suggest 8000+.\n" + "id: 0xC Power-Save hack: 0x1 ignore PS sleep message from STA\n" + "id: 0x2 mark mcast as 'data-is-buffered' regardless\n" "\nBelow here are not actually sent to firmware directly, but configure the driver.\n" "id: 0x1001 set sta-kickout threshold due to tx-failures (0 means disable. Default is 20 * 16.)\n" "\n"; diff --git a/ath10k/mac.c b/ath10k/mac.c index 1857805..3a9afa4 100644 --- a/ath10k/mac.c +++ b/ath10k/mac.c @@ -2278,6 +2278,7 @@ static void ath10k_peer_assoc_h_rate_overrides(struct ath10k *ar, int i; int j; int hw_rix; + bool ok160 = false; /* So, what we really want here is the max number of chains the firmware * is compiled for. But, since we can have 3x3 firmware run on 2x2 chips, @@ -2301,6 +2302,10 @@ static void ath10k_peer_assoc_h_rate_overrides(struct ath10k *ar, return; } + if (ar->dev_id == QCA9984_1_0_DEVICE_ID) { + ok160 = true; + } + if (hw_nss < 3) { /* Maybe 2x2 NIC booting 3x3 988x firmware? */ /* 9887 is weird, NSS = 1, but FW rate-table is compiled for 3x3 evidently */ @@ -2388,6 +2393,9 @@ static void ath10k_peer_assoc_h_rate_overrides(struct ath10k *ar, ath10k_set_rate_enabled(hw_rix + hw_nss * 10, arg->rate_overrides, 1); /* Set HT80 rateset too */ ath10k_set_rate_enabled(hw_rix + hw_nss * 2 * 10, arg->rate_overrides, 1); + /* And for NICs that support 160Mhz, set those */ + if (ok160) + ath10k_set_rate_enabled(hw_rix + hw_nss * 3 * 10, arg->rate_overrides, 1); } } } @@ -2723,6 +2731,19 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, sta->addr, arg->peer_max_mpdu, arg->peer_flags, arg->peer_vht_rates.rx_max_rate, arg->peer_vht_rates.rx_mcs_set, arg->peer_vht_rates.tx_max_rate, arg->peer_vht_rates.tx_mcs_set); + + if ((arg->peer_vht_rates.rx_max_rate) && + (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) { + if ((arg->peer_num_spatial_streams > 1) && + (arg->peer_vht_rates.rx_max_rate == 1560)) { + /* Must be 2x2 at 160Mhz is all it can do. */ + arg->peer_bw_rxnss_override = 2; + } + else if (arg->peer_vht_rates.rx_max_rate == 780) { + /* Can only do 1x2 at 160Mhz (Long Guard Interval) */ + arg->peer_bw_rxnss_override = 1; + } + } } static void ath10k_peer_assoc_h_qos(struct ath10k *ar, @@ -3119,8 +3140,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, } ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac vdev %d up (associated) bssid %pM aid %d\n", - arvif->vdev_id, bss_conf->bssid, bss_conf->aid); + "mac vdev %d up (associated) bssid %pM aid %d bandwidth %d\n", + arvif->vdev_id, bss_conf->bssid, bss_conf->aid, ap_sta->bandwidth); WARN_ON(arvif->is_up); @@ -4832,7 +4853,8 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) vht_cap.cap |= val; } - if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) { + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && + ((ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)) { vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; } @@ -4847,6 +4869,21 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + /* If we are supporting 160Mhz or 80+80, then the NIC may be able to do a restricted NSS + * for 160 or 80+80 vs what it can do for 80Mhz. Give user-space a clue if that is the + * case. + */ + if (vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + /* Something more than 80Mhz at least */ + if (ar->dev_id == QCA9984_1_0_DEVICE_ID) { + /* Can do only 2x2 VHT160 or 80+80. + * 1560Mbps is 4x4 80Mhz or 2x2 160Mhz, long-guard-interval + */ + vht_cap.vht_mcs.rx_highest = 1560; + vht_cap.vht_mcs.tx_highest = 1560; + } + } + return vht_cap; } @@ -5261,6 +5298,7 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) { u32 value = 0; struct ath10k *ar = arvif->ar; + struct ieee80211_vif *vif = arvif->vif; int nsts; int sound_dim; @@ -5280,17 +5318,21 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) if (!value) return 0; - if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) && + (vif->type != NL80211_IFTYPE_STATION)) value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER; - if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) && + (vif->type != NL80211_IFTYPE_STATION)) value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFER | WMI_VDEV_PARAM_TXBF_SU_TX_BFER); - if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) && + (vif->type == NL80211_IFTYPE_STATION)) value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE; - if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && + (vif->type == NL80211_IFTYPE_STATION)) value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFEE | WMI_VDEV_PARAM_TXBF_SU_TX_BFEE); @@ -6390,8 +6432,8 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) if (changed & IEEE80211_RC_SUPP_RATES_CHANGED || changed & IEEE80211_RC_SMPS_CHANGED || changed & IEEE80211_RC_NSS_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n", - sta->addr); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss bandwidth: %d\n", + sta->addr, sta->bandwidth); err = ath10k_station_assoc(ar, arvif->vif, sta, true); if (err) @@ -6676,8 +6718,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * New association. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", - sta->addr); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated, bandwidth: %d\n", + sta->addr, sta->bandwidth); ret = ath10k_station_assoc(ar, vif, sta, false); if (ret) @@ -6689,8 +6731,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Tdls station authorized. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac tdls sta %pM authorized\n", - sta->addr); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac tdls sta %pM authorized, bandwidth: %d\n", + sta->addr, sta->bandwidth); ret = ath10k_station_assoc(ar, vif, sta, false); if (ret) { @@ -8524,6 +8566,7 @@ static struct ieee80211_iface_combination ath10k_10_4_ct_if_comb[] = { .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | BIT(NL80211_CHAN_WIDTH_20) | BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_160) | /* TODO: Verify --Ben */ BIT(NL80211_CHAN_WIDTH_80), #endif }, diff --git a/ath10k/wmi.c b/ath10k/wmi.c index e05fa85..d96fae0 100644 --- a/ath10k/wmi.c +++ b/ath10k/wmi.c @@ -1975,7 +1975,8 @@ static void ath10k_wmi_event_scan_started(struct ath10k *ar) } } -static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar) +static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar, + enum wmi_scan_completion_reason reason) { lockdep_assert_held(&ar->data_lock); @@ -1989,6 +1990,15 @@ static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar) break; case ATH10K_SCAN_STARTING: complete(&ar->scan.started); + if (reason == WMI_SCAN_REASON_BUSY) { + /* Kick firmware to get us back in sync */ + struct wmi_stop_scan_arg arg = { + .req_id = 1, /* FIXME */ + .req_type = WMI_SCAN_STOP_ONE, + .u.scan_id = ATH10K_SCAN_ID, + }; + ath10k_wmi_stop_scan(ar, &arg); + } __ath10k_scan_finish(ar); break; } @@ -2078,6 +2088,8 @@ ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type, return "completed [timedout]"; case WMI_SCAN_REASON_INTERNAL_FAILURE: return "completed [internal err]"; + case WMI_SCAN_REASON_BUSY: + return "completed [failed, busy]"; case WMI_SCAN_REASON_MAX: break; } @@ -2166,8 +2178,11 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) ath10k_wmi_event_scan_foreign_chan(ar, freq); break; case WMI_SCAN_EVENT_START_FAILED: - ath10k_warn(ar, "received scan start failure event\n"); - ath10k_wmi_event_scan_start_failed(ar); + ath10k_warn(ar, "scan-start-failed event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n", + ath10k_wmi_event_scan_type_str(event_type, reason), + event_type, reason, freq, req_id, scan_id, vdev_id, + ath10k_scan_state_str(ar->scan.state), ar->scan.state); + ath10k_wmi_event_scan_start_failed(ar, reason); break; case WMI_SCAN_EVENT_DEQUEUED: case WMI_SCAN_EVENT_PREEMPTED: @@ -6949,7 +6964,12 @@ ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf, struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf; ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg); - cmd->peer_bw_rxnss_override = 0; + if (arg->peer_bw_rxnss_override) + cmd->peer_bw_rxnss_override = + __cpu_to_le32((arg->peer_bw_rxnss_override - 1) | + (1<peer_bw_rxnss_override = 0; } static int diff --git a/ath10k/wmi.h b/ath10k/wmi.h index ab51e74..9ede387 100644 --- a/ath10k/wmi.h +++ b/ath10k/wmi.h @@ -3128,6 +3128,7 @@ enum wmi_scan_completion_reason { WMI_SCAN_REASON_PREEMPTED, WMI_SCAN_REASON_TIMEDOUT, WMI_SCAN_REASON_INTERNAL_FAILURE, + WMI_SCAN_REASON_BUSY = 13, /* A_EBUSY, CT firmware at least. */ WMI_SCAN_REASON_MAX, }; @@ -6152,6 +6153,7 @@ struct wmi_10_2_peer_assoc_complete_cmd_ct { struct wmi_ct_assoc_overrides overrides; } __packed; +#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31 struct wmi_10_4_peer_assoc_complete_cmd { struct wmi_10_2_peer_assoc_complete_cmd cmd; __le32 peer_bw_rxnss_override; @@ -6180,6 +6182,7 @@ struct wmi_peer_assoc_complete_arg { u32 peer_vht_caps; enum wmi_phy_mode peer_phymode; struct wmi_vht_rate_set_arg peer_vht_rates; + u32 peer_bw_rxnss_override; /* CT firmware only (beta-15 and higher ) */ bool has_rate_overrides; @@ -6545,7 +6548,9 @@ struct wmi_pdev_set_special_cmd { #define SET_SPECIAL_ID_PDEV_XRETRY_TH 9 /* Set the threshold for resetting phy due to failed retries, U16 */ #define SET_SPECIAL_ID_RIFS_ENABLE 0xA /* Enable(1)/disable(0) RIFS. Disabled by default. */ #define SET_SPECIAL_ID_WMI_WD 0xB /* Set the watchdog trigger count, 0 means disable */ - +#define SET_SPECIAL_ID_PSHACK 0xC /* flag 0x1: ignore PS sleep message from STA + * flag 0x2: mark mcast as 'data-is-buffered' regardless. + */ #define CT_CCA_TYPE_MIN0 0 #define CT_CCA_TYPE_MIN1 1