diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2015-06-15 13:25:32 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2015-06-15 13:25:32 +0300 |
commit | d9378080a12ba314476fcccf4ce1328794e4e230 (patch) | |
tree | 78640c772386f691e927a1ec86694a3292e0adcc /drivers/net/wireless | |
parent | ed8e0ed53b317f72df907298fb653a976b083dc4 (diff) | |
parent | 3e2d8e1b82af3e67c8d369f3c006b8f882399742 (diff) | |
download | op-kernel-dev-d9378080a12ba314476fcccf4ce1328794e4e230.zip op-kernel-dev-d9378080a12ba314476fcccf4ce1328794e4e230.tar.gz |
Merge ath-next from ath.git
Major changes:
wil6210:
* add modparam for bcast ring size
* support hidden SSID
* add per-MCS Rx stats
Diffstat (limited to 'drivers/net/wireless')
21 files changed, 326 insertions, 209 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index bcccae1..59496a9 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -48,6 +48,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca988x hw2.0", .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .has_shifted_cc_wraparound = true, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -1084,6 +1085,22 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) if (status) goto err; + /* Some of of qca988x solutions are having global reset issue + * during target initialization. Bypassing PLL setting before + * downloading firmware and letting the SoC run on REF_CLK is + * fixing the problem. Corresponding firmware change is also needed + * to set the clock source once the target is initialized. + */ + if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, + ar->fw_features)) { + status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1); + if (status) { + ath10k_err(ar, "could not write to skip_clock_init: %d\n", + status); + goto err; + } + } + status = ath10k_download_fw(ar, mode); if (status) goto err; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 70fcdc9..78094f2 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -284,15 +284,6 @@ struct ath10k_sta { #endif }; -struct ath10k_chanctx { - /* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally - * mac80211 should allow some sort of explicit locking to guarantee - * that the publicly available chanctx_conf can be accessed safely at - * all times. - */ - struct ieee80211_chanctx_conf conf; -}; - #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) enum ath10k_beacon_state { @@ -468,6 +459,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING, + /* Firmware supports bypassing PLL setting on init. */ + ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; @@ -577,6 +571,13 @@ struct ath10k { u32 patch_load_addr; int uart_pin; + /* This is true if given HW chip has a quirky Cycle Counter + * wraparound which resets to 0x7fffffff instead of 0. All + * other CC related counters (e.g. Rx Clear Count) are divided + * by 2 so they never wraparound themselves. + */ + bool has_shifted_cc_wraparound; + struct ath10k_hw_params_fw { const char *dir; const char *fw; @@ -694,6 +695,14 @@ struct ath10k { u32 survey_last_cycle_count; struct survey_info survey[ATH10K_NUM_CHANS]; + /* Channel info events are expected to come in pairs without and with + * COMPLETE flag set respectively for each channel visit during scan. + * + * However there are deviations from this rule. This flag is used to + * avoid reporting garbage data. + */ + bool ch_info_can_report_survey; + struct dfs_pattern_detector *dfs_detector; unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */ diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 839a879..5997f00 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -15,6 +15,7 @@ */ #include <linux/types.h> +#include "core.h" #include "hw.h" const struct ath10k_hw_regs qca988x_regs = { @@ -56,3 +57,23 @@ const struct ath10k_hw_regs qca6174_regs = { .soc_chip_id_address = 0x000f0, .scratch_3_address = 0x0028, }; + +void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, + u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) +{ + u32 cc_fix = 0; + + survey->filled |= SURVEY_INFO_TIME | + SURVEY_INFO_TIME_BUSY; + + if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) { + cc_fix = 0x7fffffff; + survey->filled &= ~SURVEY_INFO_TIME_BUSY; + } + + cc -= cc_prev - cc_fix; + rcc -= rcc_prev; + + survey->time = CCNT_TO_MSEC(cc); + survey->time_busy = CCNT_TO_MSEC(rcc); +} diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 89e09cb..85cca29 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -169,6 +169,9 @@ struct ath10k_hw_regs { extern const struct ath10k_hw_regs qca988x_regs; extern const struct ath10k_hw_regs qca6174_regs; +void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, + u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); + #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) @@ -449,6 +452,9 @@ enum ath10k_hw_rate_cck { #define SCRATCH_3_ADDRESS ar->regs->scratch_3_address #define CPU_INTR_ADDRESS 0x0010 +/* Cycle counters are running at 88MHz */ +#define CCNT_TO_MSEC(x) ((x) / 88000) + /* Firmware indications to the Host via SCRATCH_3 register. */ #define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS) #define FW_IND_EVENT_PENDING 1 diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0ed422a..c48c744 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar) return ret; } -static void ath10k_mac_chan_reconfigure(struct ath10k *ar) -{ - struct ath10k_vif *arvif; - struct cfg80211_chan_def def; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n"); - - /* First stop monitor interface. Some FW versions crash if there's a - * lone monitor interface. */ - if (ar->monitor_started) - ath10k_monitor_stop(ar); - - list_for_each_entry(arvif, &ar->arvifs, list) { - if (!arvif->is_started) - continue; - - if (!arvif->is_up) - continue; - - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) - continue; - - ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) { - ath10k_warn(ar, "failed to down vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - /* all vdevs are downed now - attempt to restart and re-up them */ - - list_for_each_entry(arvif, &ar->arvifs, list) { - if (!arvif->is_started) - continue; - - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) - continue; - - ret = ath10k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", - ret); - - ret = ath10k_mac_setup_prb_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", - ret); - - if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) - continue; - - ret = ath10k_vdev_restart(arvif, &def); - if (ret) { - ath10k_warn(ar, "failed to restart vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - - if (!arvif->is_up) - continue; - - ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { - ath10k_warn(ar, "failed to bring vdev up %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - ath10k_monitor_recalc(ar); -} - static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) { int ret; @@ -6144,7 +6067,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, } static void -ath10k_mac_update_rx_channel(struct ath10k *ar) +ath10k_mac_update_rx_channel(struct ath10k *ar, + struct ieee80211_chanctx_conf *ctx, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) { struct cfg80211_chan_def *def = NULL; @@ -6154,6 +6080,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->data_lock); + WARN_ON(ctx && vifs); + WARN_ON(vifs && n_vifs != 1); + /* FIXME: Sort of an optimization and a workaround. Peers and vifs are * on a linked list now. Doing a lookup peer -> vif -> chanctx for each * ppdu on Rx may reduce performance on low-end systems. It should be @@ -6165,36 +6094,28 @@ ath10k_mac_update_rx_channel(struct ath10k *ar) * affected much. */ rcu_read_lock(); - if (ath10k_mac_num_chanctxs(ar) == 1) { + if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) { ieee80211_iter_chan_contexts_atomic(ar->hw, ath10k_mac_get_any_chandef_iter, &def); + + if (vifs) + def = &vifs[0].new_ctx->def; + ar->rx_channel = def->chan; + } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) { + ar->rx_channel = ctx->def.chan; } else { ar->rx_channel = NULL; } rcu_read_unlock(); } -static void -ath10k_mac_chan_ctx_init(struct ath10k *ar, - struct ath10k_chanctx *arctx, - struct ieee80211_chanctx_conf *conf) -{ - lockdep_assert_held(&ar->conf_mutex); - lockdep_assert_held(&ar->data_lock); - - memset(arctx, 0, sizeof(*arctx)); - - arctx->conf = *conf; -} - static int ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chanctx add freq %hu width %d ptr %p\n", @@ -6203,8 +6124,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); - ath10k_mac_chan_ctx_init(ar, arctx, ctx); - ath10k_mac_update_rx_channel(ar); + ath10k_mac_update_rx_channel(ar, ctx, NULL, 0); spin_unlock_bh(&ar->data_lock); ath10k_recalc_radar_detection(ar); @@ -6228,7 +6148,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); - ath10k_mac_update_rx_channel(ar); + ath10k_mac_update_rx_channel(ar, NULL, NULL, 0); spin_unlock_bh(&ar->data_lock); ath10k_recalc_radar_detection(ar); @@ -6243,16 +6163,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, u32 changed) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; mutex_lock(&ar->conf_mutex); ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n", - arctx->conf.def.chan->center_freq, - ctx->def.chan->center_freq, - arctx->conf.def.width, ctx->def.width, - ctx, changed); + "mac chanctx change freq %hu width %d ptr %p changed %x\n", + ctx->def.chan->center_freq, ctx->def.width, ctx, changed); /* This shouldn't really happen because channel switching should use * switch_vif_chanctx(). @@ -6260,10 +6176,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) goto unlock; - spin_lock_bh(&ar->data_lock); - arctx->conf = *ctx; - spin_unlock_bh(&ar->data_lock); - ath10k_recalc_radar_detection(ar); /* FIXME: How to configure Rx chains properly? */ @@ -6283,7 +6195,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret; @@ -6298,11 +6209,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, return -EBUSY; } - ret = ath10k_vdev_start(arvif, &arctx->conf.def); + ret = ath10k_vdev_start(arvif, &ctx->def); if (ret) { ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n", arvif->vdev_id, vif->addr, - arctx->conf.def.chan->center_freq, ret); + ctx->def.chan->center_freq, ret); goto err; } @@ -6377,7 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif; - struct ath10k_chanctx *arctx_new, *arctx_old; + int ret; int i; mutex_lock(&ar->conf_mutex); @@ -6386,38 +6297,81 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, "mac chanctx switch n_vifs %d mode %d\n", n_vifs, mode); - spin_lock_bh(&ar->data_lock); + /* First stop monitor interface. Some FW versions crash if there's a + * lone monitor interface. + */ + if (ar->monitor_started) + ath10k_monitor_stop(ar); + for (i = 0; i < n_vifs; i++) { arvif = ath10k_vif_to_arvif(vifs[i].vif); - arctx_new = (void *)vifs[i].new_ctx->drv_priv; - arctx_old = (void *)vifs[i].old_ctx->drv_priv; ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n", + "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", arvif->vdev_id, vifs[i].old_ctx->def.chan->center_freq, vifs[i].new_ctx->def.chan->center_freq, vifs[i].old_ctx->def.width, - vifs[i].new_ctx->def.width, - arctx_old, arctx_new); + vifs[i].new_ctx->def.width); - if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { - ath10k_mac_chan_ctx_init(ar, arctx_new, - vifs[i].new_ctx); - } + if (WARN_ON(!arvif->is_started)) + continue; - arctx_new->conf = *vifs[i].new_ctx; + if (WARN_ON(!arvif->is_up)) + continue; - /* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not - * yet updated chanctx_conf pointer. - */ - arctx_old->conf = *vifs[i].new_ctx; + ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) { + ath10k_warn(ar, "failed to down vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } } - ath10k_mac_update_rx_channel(ar); + + /* All relevant vdevs are downed and associated channel resources + * should be available for the channel switch now. + */ + + spin_lock_bh(&ar->data_lock); + ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); spin_unlock_bh(&ar->data_lock); - /* FIXME: Reconfigure only affected vifs */ - ath10k_mac_chan_reconfigure(ar); + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", + ret); + + ret = ath10k_mac_setup_prb_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", + ret); + + ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); + if (ret) { + ath10k_warn(ar, "failed to restart vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + + ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid); + if (ret) { + ath10k_warn(ar, "failed to bring vdev up %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + ath10k_monitor_recalc(ar); mutex_unlock(&ar->conf_mutex); return 0; @@ -6914,7 +6868,6 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->vif_data_size = sizeof(struct ath10k_vif); ar->hw->sta_data_size = sizeof(struct ath10k_sta); - ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx); ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 17a060e..ea656e0 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1424,7 +1424,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) struct ath10k_ce_ring *ce_ring; struct ce_desc *ce_desc; struct sk_buff *skb; - unsigned int id; int i; ar = pci_pipe->hif_ce_state; @@ -1448,8 +1447,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) continue; ce_ring->per_transfer_context[i] = NULL; - id = MS(__le16_to_cpu(ce_desc[i].flags), - CE_DESC_FLAGS_META_DATA); ar_pci->msg_callbacks_current.tx_completion(ar, skb); } @@ -2850,6 +2847,7 @@ err_free_pipes: ath10k_pci_free_pipes(ar); err_sleep: + ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); err_core_destroy: @@ -2927,8 +2925,10 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); /* QCA6174 2.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE); +MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE); /* QCA6174 3.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); +MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 563fde7..8fdba38 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -402,7 +402,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) - return; + goto out; trace_ath10k_wmi_event(ar, id, skb->data, skb->len); @@ -521,6 +521,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) break; } +out: dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 0fabe68..6c046c2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -27,6 +27,7 @@ #include "testmode.h" #include "wmi-ops.h" #include "p2p.h" +#include "hw.h" /* MAIN WMI cmd track */ static struct wmi_cmd_map wmi_cmd_map = { @@ -1450,6 +1451,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); if (ret) { ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); + dev_kfree_skb(skb); return ret; } @@ -1636,20 +1638,22 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) } if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { - /* During scanning chan info is reported twice for each - * visited channel. The reported cycle count is global - * and per-channel cycle count must be calculated */ - - cycle_count -= ar->survey_last_cycle_count; - rx_clear_count -= ar->survey_last_rx_clear_count; - - survey = &ar->survey[idx]; - survey->time = WMI_CHAN_INFO_MSEC(cycle_count); - survey->time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count); - survey->noise = noise_floor; - survey->filled = SURVEY_INFO_TIME | - SURVEY_INFO_TIME_BUSY | - SURVEY_INFO_NOISE_DBM; + if (ar->ch_info_can_report_survey) { + survey = &ar->survey[idx]; + survey->noise = noise_floor; + survey->filled = SURVEY_INFO_NOISE_DBM; + + ath10k_hw_fill_survey_time(ar, + survey, + cycle_count, + rx_clear_count, + ar->survey_last_cycle_count, + ar->survey_last_rx_clear_count); + } + + ar->ch_info_can_report_survey = false; + } else { + ar->ch_info_can_report_survey = true; } ar->survey_last_rx_clear_count = rx_clear_count; @@ -3219,7 +3223,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) - return; + goto out; trace_ath10k_wmi_event(ar, id, skb->data, skb->len); @@ -3323,6 +3327,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) break; } +out: dev_kfree_skb(skb); } @@ -3336,7 +3341,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) - return; + goto out; trace_ath10k_wmi_event(ar, id, skb->data, skb->len); @@ -3459,7 +3464,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) - return; + goto out; trace_ath10k_wmi_event(ar, id, skb->data, skb->len); @@ -3567,6 +3572,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) break; } +out: dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index cad72ae..cf44a3d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4665,7 +4665,6 @@ struct wmi_peer_sta_kickout_event { } __packed; #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0) -#define WMI_CHAN_INFO_MSEC(x) ((x) / 88000) /* Beacon filter wmi command info */ #define BCN_FLT_MAX_SUPPORTED_IES 256 diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 19f88b4..05d25a9 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1527,8 +1527,8 @@ struct wmi_connect_event { __le32 nw_type; } sta; struct { - u8 phymode; u8 aid; + u8 phymode; u8 mac_addr[ETH_ALEN]; u8 auth; u8 keymgmt; diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index dbfcdd1..c79cfe0 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -289,6 +289,26 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, } wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); + wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); + + for (i = 0; i < request->n_ssids; i++) { + wil_dbg_misc(wil, "SSID[%d]", i); + print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, + request->ssids[i].ssid, + request->ssids[i].ssid_len); + } + + if (request->n_ssids) + rc = wmi_set_ssid(wil, request->ssids[0].ssid_len, + request->ssids[0].ssid); + else + rc = wmi_set_ssid(wil, 0, NULL); + + if (rc) { + wil_err(wil, "set SSID for scan request failed: %d\n", rc); + return rc; + } + wil->scan_request = request; mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); @@ -778,6 +798,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); const u8 *pr_ies = NULL; size_t pr_ies_len = 0; + u8 hidden_ssid; wil_dbg_misc(wil, "%s()\n", __func__); @@ -790,6 +811,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, channel->center_freq, info->privacy ? "secure" : "open"); wil_dbg_misc(wil, "Privacy: %d auth_type %d\n", info->privacy, info->auth_type); + wil_dbg_misc(wil, "Hidden SSID mode: %d\n", + info->hidden_ssid); wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval, info->dtim_period); print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, @@ -835,10 +858,28 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, wil->privacy = info->privacy; + switch (info->hidden_ssid) { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + hidden_ssid = WMI_HIDDEN_SSID_DISABLED; + break; + + case NL80211_HIDDEN_SSID_ZERO_LEN: + hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY; + break; + + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + hidden_ssid = WMI_HIDDEN_SSID_CLEAR; + break; + + default: + rc = -EOPNOTSUPP; + goto out; + } + netif_carrier_on(ndev); rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, - channel->hw_value); + channel->hw_value, hidden_ssid); if (rc) goto err_pcp_start; @@ -1023,8 +1064,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { static void wil_wiphy_init(struct wiphy *wiphy) { - /* TODO: set real value */ - wiphy->max_scan_ssids = 10; + wiphy->max_scan_ssids = 1; wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; wiphy->max_num_pmkids = 0 /* TODO: */; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 8f9c072..75219a1 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1360,7 +1360,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) { struct wil6210_priv *wil = s->private; - int i, tid; + int i, tid, mcs; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { struct wil_sta_info *p = &wil->sta[i]; @@ -1390,6 +1390,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) } } spin_unlock_bh(&p->tid_rx_lock); + seq_puts(s, "Rx/MCS:"); + for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); + mcs++) + seq_printf(s, " %lld", + p->stats.rx_per_mcs[mcs]); + seq_puts(s, "\n"); } } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6d704ae..b9febab 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -100,6 +100,8 @@ module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO); MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order"); +module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO); +MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order"); #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 6042f61..8ef18ac 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -132,7 +132,7 @@ static void wil_dev_setup(struct net_device *dev) dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; } -void *wil_if_alloc(struct device *dev, void __iomem *csr) +void *wil_if_alloc(struct device *dev) { struct net_device *ndev; struct wireless_dev *wdev; @@ -147,7 +147,6 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) } wil = wdev_to_wil(wdev); - wil->csr = csr; wil->wdev = wdev; wil_dbg_misc(wil, "%s()\n", __func__); diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 58c7916..aa3ecc6 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -163,7 +163,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct wil6210_priv *wil; struct device *dev = &pdev->dev; - void __iomem *csr; int rc; /* check HW */ @@ -178,9 +177,28 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENODEV; } + wil = wil_if_alloc(dev); + if (IS_ERR(wil)) { + rc = (int)PTR_ERR(wil); + dev_err(dev, "wil_if_alloc failed: %d\n", rc); + return rc; + } + wil->pdev = pdev; + pci_set_drvdata(pdev, wil); + /* rollback to if_free */ + + wil->platform_handle = + wil_platform_init(&pdev->dev, &wil->platform_ops); + if (!wil->platform_handle) { + rc = -ENODEV; + wil_err(wil, "wil_platform_init failed\n"); + goto if_free; + } + /* rollback to err_plat */ + rc = pci_enable_device(pdev); if (rc) { - dev_err(&pdev->dev, + wil_err(wil, "pci_enable_device failed, retry with MSI only\n"); /* Work around for platforms that can't allocate IRQ: * retry with MSI only @@ -188,47 +206,37 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pdev->msi_enabled = 1; rc = pci_enable_device(pdev); } - if (rc) - return -ENODEV; + if (rc) { + wil_err(wil, + "pci_enable_device failed, even with MSI only\n"); + goto err_plat; + } /* rollback to err_disable_pdev */ rc = pci_request_region(pdev, 0, WIL_NAME); if (rc) { - dev_err(&pdev->dev, "pci_request_region failed\n"); + wil_err(wil, "pci_request_region failed\n"); goto err_disable_pdev; } /* rollback to err_release_reg */ - csr = pci_ioremap_bar(pdev, 0); - if (!csr) { - dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); + wil->csr = pci_ioremap_bar(pdev, 0); + if (!wil->csr) { + wil_err(wil, "pci_ioremap_bar failed\n"); rc = -ENODEV; goto err_release_reg; } /* rollback to err_iounmap */ - dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr); + wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr); - wil = wil_if_alloc(dev, csr); - if (IS_ERR(wil)) { - rc = (int)PTR_ERR(wil); - dev_err(dev, "wil_if_alloc failed: %d\n", rc); - goto err_iounmap; - } - /* rollback to if_free */ - - pci_set_drvdata(pdev, wil); - wil->pdev = pdev; wil_set_capabilities(wil); wil6210_clear_irq(wil); - wil->platform_handle = - wil_platform_init(&pdev->dev, &wil->platform_ops); - /* FW should raise IRQ when ready */ rc = wil_if_pcie_enable(wil); if (rc) { wil_err(wil, "Enable device failed\n"); - goto if_free; + goto err_iounmap; } /* rollback to bus_disable */ @@ -243,18 +251,19 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; - bus_disable: +bus_disable: wil_if_pcie_disable(wil); - if_free: +err_iounmap: + pci_iounmap(pdev, wil->csr); +err_release_reg: + pci_release_region(pdev, 0); +err_disable_pdev: + pci_disable_device(pdev); +err_plat: if (wil->platform_ops.uninit) wil->platform_ops.uninit(wil->platform_handle); +if_free: wil_if_free(wil); - err_iounmap: - pci_iounmap(pdev, csr); - err_release_reg: - pci_release_region(pdev, 0); - err_disable_pdev: - pci_disable_device(pdev); return rc; } @@ -269,12 +278,12 @@ static void wil_pcie_remove(struct pci_dev *pdev) wil6210_debugfs_remove(wil); wil_if_remove(wil); wil_if_pcie_disable(wil); - if (wil->platform_ops.uninit) - wil->platform_ops.uninit(wil->platform_handle); - wil_if_free(wil); pci_iounmap(pdev, csr); pci_release_region(pdev, 0); pci_disable_device(pdev); + if (wil->platform_ops.uninit) + wil->platform_ops.uninit(wil->platform_handle); + wil_if_free(wil); } static const struct pci_device_id wil6210_pcie_ids[] = { @@ -291,7 +300,27 @@ static struct pci_driver wil6210_driver = { .name = WIL_NAME, }; -module_pci_driver(wil6210_driver); +static int __init wil6210_driver_init(void) +{ + int rc; + + rc = wil_platform_modinit(); + if (rc) + return rc; + + rc = pci_register_driver(&wil6210_driver); + if (rc) + wil_platform_modexit(); + return rc; +} +module_init(wil6210_driver_init); + +static void __exit wil6210_driver_exit(void) +{ + pci_unregister_driver(&wil6210_driver); + wil_platform_modexit(); +} +module_exit(wil6210_driver_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 0113dac..aa20af8 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -427,6 +427,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, cid = wil_rxdesc_cid(d); stats = &wil->sta[cid].stats; stats->last_mcs_rx = wil_rxdesc_mcs(d); + if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) + stats->rx_per_mcs[stats->last_mcs_rx]++; /* use radiotap header only if required */ if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f3513a1..275355d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -281,7 +281,7 @@ struct fw_map { }; /* array size should be in sync with actual definition in the wmi.c */ -extern const struct fw_map fw_mapping[7]; +extern const struct fw_map fw_mapping[8]; /** * mk_cidxtid - construct @cidxtid field @@ -464,6 +464,7 @@ enum wil_sta_status { }; #define WIL_STA_TID_NUM (16) +#define WIL_MCS_MAX (12) /* Maximum MCS supported */ struct wil_net_stats { unsigned long rx_packets; @@ -473,6 +474,7 @@ struct wil_net_stats { unsigned long tx_errors; unsigned long rx_dropped; u16 last_mcs_rx; + u64 rx_per_mcs[WIL_MCS_MAX + 1]; }; /** @@ -684,7 +686,7 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count); -void *wil_if_alloc(struct device *dev, void __iomem *csr); +void *wil_if_alloc(struct device *dev); void wil_if_free(struct wil6210_priv *wil); int wil_if_add(struct wil6210_priv *wil); void wil_if_remove(struct wil6210_priv *wil); @@ -762,7 +764,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev); void wil_wdev_free(struct wil6210_priv *wil); int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); -int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); +int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, + u8 chan, u8 hidden_ssid); int wmi_pcp_stop(struct wil6210_priv *wil); void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event); diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.c b/drivers/net/wireless/ath/wil6210/wil_platform.c index 976a071..de15f14 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.c +++ b/drivers/net/wireless/ath/wil6210/wil_platform.c @@ -17,6 +17,15 @@ #include "linux/device.h" #include "wil_platform.h" +int __init wil_platform_modinit(void) +{ + return 0; +} + +void wil_platform_modexit(void) +{ +} + /** * wil_platform_init() - wil6210 platform module init * @@ -26,10 +35,11 @@ */ void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops) { - void *handle = NULL; + void *handle = ops; /* to return some non-NULL for 'void' impl. */ if (!ops) { - dev_err(dev, "Invalid parameter. Cannot init platform module\n"); + dev_err(dev, + "Invalid parameter. Cannot init platform module\n"); return NULL; } diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h index 158c73b..d7fa19b 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.h +++ b/drivers/net/wireless/ath/wil6210/wil_platform.h @@ -31,4 +31,7 @@ struct wil_platform_ops { void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops); +int __init wil_platform_modinit(void); +void wil_platform_modexit(void); + #endif /* __WIL_PLATFORM_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 3dc8daf..c759759 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -85,6 +85,7 @@ const struct fw_map fw_mapping[] = { {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */ {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */ {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */ + {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf 512b */ {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */ /* * 920000..930000 ucode code RAM @@ -824,7 +825,8 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); } -int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) +int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, + u8 chan, u8 hidden_ssid) { int rc; @@ -834,6 +836,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) .disable_sec_offload = 1, .channel = chan - 1, .pcp_max_assoc_sta = max_assoc_sta, + .hidden_ssid = hidden_ssid, }; struct { struct wil6210_mbox_hdr_wmi wmi; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index cc04ab7..6e90e78 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -495,10 +495,18 @@ struct wmi_power_mgmt_cfg_cmd { /* * WMI_PCP_START_CMDID */ + +enum wmi_hidden_ssid { + WMI_HIDDEN_SSID_DISABLED = 0, + WMI_HIDDEN_SSID_SEND_EMPTY = 1, + WMI_HIDDEN_SSID_CLEAR = 2, +}; + struct wmi_pcp_start_cmd { __le16 bcon_interval; u8 pcp_max_assoc_sta; - u8 reserved0[9]; + u8 hidden_ssid; + u8 reserved0[8]; u8 network_type; u8 channel; u8 disable_sec_offload; |