Skip to content

Commit

Permalink
ath10k: ps-hack, scan busy work-around.
Browse files Browse the repository at this point in the history
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 <greearb@candelatech.com>
  • Loading branch information
greearb committed Mar 20, 2017
1 parent d2bc84f commit 5a3d83f
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 18 deletions.
3 changes: 3 additions & 0 deletions ath10k/core.c
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ath10k/core.h
Expand Up @@ -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 */
Expand Down
6 changes: 6 additions & 0 deletions ath10k/debug.c
Expand Up @@ -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. */
Expand Down Expand Up @@ -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";
Expand Down
69 changes: 56 additions & 13 deletions ath10k/mac.c
Expand Up @@ -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,
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down Expand 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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;

Expand All @@ -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);

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down Expand Up @@ -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
},
Expand Down
28 changes: 24 additions & 4 deletions ath10k/wmi.c
Expand Up @@ -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);

Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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_OFFSET));
else
cmd->peer_bw_rxnss_override = 0;
}

static int
Expand Down
7 changes: 6 additions & 1 deletion ath10k/wmi.h
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 5a3d83f

Please sign in to comment.