Skip to content

Commit

Permalink
ath10k: Improve wmi retry logic, fix regdom override on 4.13.
Browse files Browse the repository at this point in the history
Backport some set-special and generic test-cmd logic into
4.9 from 4.13.

Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Dec 5, 2017
1 parent 46f19a6 commit d057d30
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 82 deletions.
1 change: 1 addition & 0 deletions ath10k-4.13/core.h
Expand Up @@ -1106,6 +1106,7 @@ struct ath10k {
u32 skid_limit;
u32 bmiss_offload_max_vdev;
int eeprom_regdom;
bool eeprom_regdom_warned;

struct work_struct svc_rdy_work;
struct sk_buff *svc_rdy_skb;
Expand Down
22 changes: 21 additions & 1 deletion ath10k-4.13/mac.c
Expand Up @@ -3749,6 +3749,10 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
struct ath10k *ar = hw->priv;
bool result;

/*ath10k_info(ar, "ath10k-reg-notifier, DFS-certified: %d, dfs-detector: %p current-rd: %d reg-addr: %p\n",
IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED), ar->dfs_detector,
ar->ath_common.regulatory.current_rd, &ar->ath_common.regulatory);*/

ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);

if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
Expand Down Expand Up @@ -8956,7 +8960,22 @@ static int ath10k_mac_init_rd(struct ath10k *ar)
rd = ar->hw_eeprom_rd;
}

ar->ath_common.regulatory.current_rd = rd;
if ((ar->eeprom_regdom != -1) &&
(ar->eeprom_regdom != rd)) {
if (!ar->eeprom_regdom_warned) {
ath10k_err(ar, "DANGER! You're overriding EEPROM-defined regulatory domain\n");
ath10k_err(ar, "from: 0x%x to 0x%x (mac-init-rd)\n",
rd, ar->eeprom_regdom);
ath10k_err(ar, "Your card was not certified to operate in the domain you chose.\n");
ath10k_err(ar, "This might result in a violation of your local regulatory rules.\n");
ath10k_err(ar, "Do not ever do this unless you really know what you are doing!\n");
ar->eeprom_regdom_warned = 1;
}
ar->ath_common.regulatory.current_rd = ar->eeprom_regdom | COUNTRY_ERD_FLAG;
}
else {
ar->ath_common.regulatory.current_rd = rd;
}
return 0;
}

Expand Down Expand Up @@ -9301,6 +9320,7 @@ int ath10k_mac_register(struct ath10k *ar)
if (!ar->hw_params.hw_ops->set_coverage_class)
ar->ops->set_coverage_class = NULL;

/*ath10k_err(ar, "Calling ath_regd_init, current-rd: %d\n", ar->ath_common.regulatory.current_rd);*/
ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
ath10k_reg_notifier);
if (ret) {
Expand Down
39 changes: 18 additions & 21 deletions ath10k-4.13/wmi.c
Expand Up @@ -1847,7 +1847,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
{
int ret = -EOPNOTSUPP;
int retry = 1000;
int loops = 0;

might_sleep();

Expand All @@ -1859,23 +1859,15 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
}

wait_event_timeout(ar->wmi.tx_credits_wq, ({
/* try to send pending beacons first. they take priority */
ath10k_wmi_tx_beacons_nowait(ar);

while (--retry) {
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
if ((ret == -ENOBUFS) &&
!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
/* CE transport logic is full, maybe we cannot reap entries fast
* enough?
*/
ath10k_err(ar, "CE transport is full, sleeping for 1ms\n");
msleep(1);
continue;
}
break;
if (loops++ == 0) {
/* try to send pending beacons first. they take priority. But, only
* the first time through this loop. --Ben
*/
ath10k_wmi_tx_beacons_nowait(ar);
}

ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);

if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
ret = -ESHUTDOWN;

Expand Down Expand Up @@ -4947,15 +4939,14 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)

if ((ar->eeprom_regdom != -1) &&
(ar->eeprom_regdom != ar->ath_common.regulatory.current_rd)) {
static int do_once = 1;
if (do_once) {
ath10k_err(ar, "DANGER! You're overriding EEPROM-defined regulatory domain,"
"\nfrom: 0x%x to 0x%x\n",
if (!ar->eeprom_regdom_warned) {
ath10k_err(ar, "DANGER! You're overriding EEPROM-defined regulatory domain\n");
ath10k_err(ar, "from: 0x%x to 0x%x (svc-ready-work)\n",
ar->ath_common.regulatory.current_rd, ar->eeprom_regdom);
ath10k_err(ar, "Your card was not certified to operate in the domain you chose.\n");
ath10k_err(ar, "This might result in a violation of your local regulatory rules.\n");
ath10k_err(ar, "Do not ever do this unless you really know what you are doing!\n");
do_once = 0;
ar->eeprom_regdom_warned = 1;
}
ar->ath_common.regulatory.current_rd = ar->eeprom_regdom | COUNTRY_ERD_FLAG;
}
Expand Down Expand Up @@ -6980,6 +6971,12 @@ ath10k_wmi_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
cmd->vdev_id = __cpu_to_le32(vdev_id);
ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);

/* Steal a high bit. Stock firmware should ignore it,
* CT 10.1 (at least) firmware built after Nov 29 will
* pay attention and flush if requested.
*/
cmd->peer_macaddr.word1 |= __cpu_to_le32(0x80000000);

ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer delete vdev_id %d peer_addr %pM\n",
vdev_id, peer_addr);
Expand Down
10 changes: 5 additions & 5 deletions ath10k-4.13/wmi.h
Expand Up @@ -1144,13 +1144,13 @@ enum wmi_10x_cmd_id {
WMI_10X_PDEV_PKTLOG_ENABLE_CMDID,
WMI_10X_PDEV_PKTLOG_DISABLE_CMDID,
WMI_10X_PDEV_SET_WMM_PARAMS_CMDID,
WMI_10X_PDEV_SET_HT_CAP_IE_CMDID,
WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, /* 10 */
WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID,
WMI_10X_PDEV_SET_BASE_MACADDR_CMDID,
WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID,
WMI_10X_PDEV_SET_QUIET_MODE_CMDID,
WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID,
WMI_10X_PDEV_GET_TPC_CONFIG_CMDID,
WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, /* 16 */

/* VDEV(virtual device) specific commands */
WMI_10X_VDEV_CREATE_CMDID,
Expand All @@ -1163,7 +1163,7 @@ enum wmi_10x_cmd_id {
WMI_10X_VDEV_STANDBY_RESPONSE_CMDID,
WMI_10X_VDEV_RESUME_RESPONSE_CMDID,
WMI_10X_VDEV_SET_PARAM_CMDID,
WMI_10X_VDEV_INSTALL_KEY_CMDID,
WMI_10X_VDEV_INSTALL_KEY_CMDID, /* 27 */

/* peer specific commands */
WMI_10X_PEER_CREATE_CMDID,
Expand All @@ -1173,15 +1173,15 @@ enum wmi_10x_cmd_id {
WMI_10X_PEER_ASSOC_CMDID,
WMI_10X_PEER_ADD_WDS_ENTRY_CMDID,
WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID,
WMI_10X_PEER_MCAST_GROUP_CMDID,
WMI_10X_PEER_MCAST_GROUP_CMDID, /* 35 */

/* beacon/management specific commands */

WMI_10X_BCN_TX_CMDID,
WMI_10X_BCN_PRB_TMPL_CMDID,
WMI_10X_BCN_FILTER_RX_CMDID,
WMI_10X_PRB_REQ_FILTER_RX_CMDID,
WMI_10X_MGMT_TX_CMDID,
WMI_10X_MGMT_TX_CMDID, /* 40 */

/* commands to directly control ba negotiation directly from host. */
WMI_10X_ADDBA_CLEAR_RESP_CMDID,
Expand Down
23 changes: 23 additions & 0 deletions ath10k-4.9/ahb.c
Expand Up @@ -33,6 +33,9 @@ static const struct of_device_id ath10k_ahb_of_match[] = {

MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);

#define QCA4019_SRAM_ADDR 0x000C0000
#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */

static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
{
return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
Expand Down Expand Up @@ -699,6 +702,25 @@ static int ath10k_ahb_hif_power_up(struct ath10k *ar)
return ret;
}

static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
{
u32 val = 0, region = addr & 0xfffff;

val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);

if (region >= QCA4019_SRAM_ADDR && region <=
(QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) {
/* SRAM contents for QCA4019 can be directly accessed and
* no conversions are required
*/
val |= region;
} else {
val |= 0x100000 | region;
}

return val;
}

static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {
.tx_sg = ath10k_pci_hif_tx_sg,
.diag_read = ath10k_pci_hif_diag_read,
Expand Down Expand Up @@ -766,6 +788,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
ar_pci->mem_len = ar_ahb->mem_len;
ar_pci->ar = ar;
ar_pci->bus_ops = &ath10k_ahb_bus_ops;
ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;

ret = ath10k_pci_setup_resource(ar);
if (ret) {
Expand Down
20 changes: 19 additions & 1 deletion ath10k-4.9/core.c
Expand Up @@ -330,6 +330,8 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
[ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",
[ATH10K_FW_FEATURE_NO_PS] = "no-ps",
[ATH10K_FW_FEATURE_WMI_10X_CT] = "wmi-10.x-CT",
[ATH10K_FW_FEATURE_CT_RXSWCRYPT] = "rxswcrypt-CT",
[ATH10K_FW_FEATURE_HAS_TXSTATUS_NOACK] = "txstatus-noack",
Expand Down Expand Up @@ -1861,7 +1863,7 @@ static int ath10k_download_cal_data(struct ath10k *ar)

ret = ath10k_download_and_run_otp(ar);
if (ret) {
ath10k_err(ar, "failed to run otp: %d\n", ret);
ath10k_err(ar, "failed to run otp: %d (download-cal-data)\n", ret);
return ret;
}

Expand Down Expand Up @@ -2613,9 +2615,25 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (ar->eeprom_overrides.rate_bw_disable_mask)
ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_BW_DISABLE_MASK,
ar->eeprom_overrides.rate_bw_disable_mask);
if (ar->eeprom_overrides.txbf_cv_msg)
ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_TXBF_CV_MSG,
ar->eeprom_overrides.txbf_cv_msg);
if (ar->eeprom_overrides.rx_all_mgt)
ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_RX_ALL_MGT,
ar->eeprom_overrides.rx_all_mgt);
if (ar->eeprom_overrides.tx_debug)
ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_TX_DBG,
ar->eeprom_overrides.tx_debug);

if (ar->eeprom_overrides.su_sounding_timer_ms)
ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->txbf_sound_period_cmdid,
ar->eeprom_overrides.su_sounding_timer_ms);

/* See WMI_FWTEST_CMDID in wlan_dev.c in firmware for these hard-coded values. */
/* Set default MU sounding period. */
if (ar->eeprom_overrides.mu_sounding_timer_ms)
ath10k_wmi_pdev_set_fwtest(ar, 81,
ar->eeprom_overrides.mu_sounding_timer_ms);
}

return 0;
Expand Down
15 changes: 15 additions & 0 deletions ath10k-4.9/core.h
Expand Up @@ -640,6 +640,16 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,

/* Firmware allow other BSS mesh broadcast/multicast frames without
* creating monitor interface. Appropriate rxfilters are programmed for
* mesh vdev by firmware itself. This feature flags will be used for
* not creating monitor vdev while configuring mesh node.
*/
ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16,

/* Firmware does not support power save in station mode. */
ATH10K_FW_FEATURE_NO_PS = 17,

/* tx-status has the noack bits (CT firmware version 14 and higher ) */
ATH10K_FW_FEATURE_HAS_TXSTATUS_NOACK = 30,

Expand Down Expand Up @@ -1052,6 +1062,7 @@ struct ath10k {
u32 skid_limit;
u32 bmiss_offload_max_vdev;
int eeprom_regdom;
bool eeprom_regdom_warned;

struct work_struct svc_rdy_work;
struct sk_buff *svc_rdy_skb;
Expand Down Expand Up @@ -1140,6 +1151,8 @@ struct ath10k {
u8 tx_sta_bw_mask; /* 0: all, 0x1: 20Mhz, 0x2 40Mhz, 0x4 80Mhz */
bool allow_ibss_amsdu;
bool rifs_enable_override;
bool txbf_cv_msg;
bool rx_all_mgt;
#define CT_DISABLE_20MHZ 0x1
#define CT_DISABLE_40MHZ 0x2
#define CT_DISABLE_80MHZ 0x4
Expand All @@ -1155,6 +1168,8 @@ struct ath10k {
*/
u32 ct_pshack;
u32 ct_csi;
u32 mu_sounding_timer_ms;
u32 su_sounding_timer_ms;
} eeprom_overrides;

/* must be last */
Expand Down
50 changes: 47 additions & 3 deletions ath10k-4.9/debug.c
Expand Up @@ -3021,6 +3021,18 @@ static ssize_t ath10k_write_ct_special(struct file *file,
ath10k_warn(ar, "Setting pdev rate-bw-disable-mask to 0x%x. Will take effect next time rates are configured.\n",
val);
}
else if (id == SET_SPECIAL_ID_TXBF_CV_MSG) {
ar->eeprom_overrides.txbf_cv_msg = val;

ath10k_warn(ar, "Setting pdev txbf-cv-msg to 0x%x.\n",
val);
}
else if (id == SET_SPECIAL_ID_RX_ALL_MGT) {
ar->eeprom_overrides.rx_all_mgt = val;

ath10k_warn(ar, "Setting pdev rx-all-mgt to 0x%x.\n",
val);
}
else if (id == SET_SPECIAL_ID_TX_DBG) {
/* Set TX debugging */
ar->eeprom_overrides.tx_debug = val;
Expand All @@ -3038,12 +3050,42 @@ static ssize_t ath10k_write_ct_special(struct file *file,
ath10k_mac_set_pdev_kickout(ar);
goto unlock;
}
else if (id == 0x1002) {
/* Set SU sounding frame timer. */
ar->eeprom_overrides.su_sounding_timer_ms = val;

ath10k_warn(ar, "Setting pdev su-sounding-timer-ms to 0x%x\n",
val);

ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->txbf_sound_period_cmdid,
ar->eeprom_overrides.su_sounding_timer_ms);
goto unlock;
}
else if (id == 0x1003) {
/* Set MU sounding frame timer. */
ar->eeprom_overrides.mu_sounding_timer_ms = val;

ath10k_warn(ar, "Setting pdev mu-sounding-timer-ms to 0x%x\n",
val);

/* Search for WMI_FWTEST_CMDID in core.c */
ath10k_wmi_pdev_set_fwtest(ar, 81,
ar->eeprom_overrides.mu_sounding_timer_ms);
goto unlock;
}
/* else, pass it through to firmware...but will not be stored locally, so
* won't survive through firmware reboots, etc.
*/

/* Send it to the firmware. */
ret = ath10k_wmi_pdev_set_special(ar, id, val);
if ((id & 0xFF0000) == 0xFF0000) {
/* Send it to the firmware through the fwtest (stock-ish) API */
/* Search for WMI_FWTEST_CMDID in core.c */
ret = ath10k_wmi_pdev_set_fwtest(ar, id & 0xFFFF, val);
}
else {
/* Send it to the firmware though ct-special API */
ret = ath10k_wmi_pdev_set_special(ar, id, val);
}
unlock:
mutex_unlock(&ar->conf_mutex);

Expand Down Expand Up @@ -3082,8 +3124,10 @@ static ssize_t ath10k_read_ct_special(struct file *file,
"id: 0xD Enable CSI reporting for at least probe requests.\n"
"id: 0xE set rate-bandwidth-disable-mask: 20Mhz 0x1, 40Mhz 0x2, 80Mhz 0x4, 160Mhz 0x8.\n"
" Takes effect next time rates are set. Set to 0x0 for default rates.\n"
"\nBelow here are not actually sent to firmware directly, but configure the driver.\n"
"\nBelow here should work with most firmware, including non-CT firmware.\n"
"id: 0x1001 set sta-kickout threshold due to tx-failures (0 means disable. Default is 20 * 16.)\n"
"id: 0x1002 set su-sounding-timer-ms (0 means use defaults next FW reload. Default is 100, max is 500)\n"
"id: 0x1003 set mu-sounding-timer-ms (0 means use defaults next FW reload. Default is 40)\n"
"\n";

return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
Expand Down

0 comments on commit d057d30

Please sign in to comment.