Commit d9378080 authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge ath-next from ath.git

Major changes:

wil6210:

* add modparam for bcast ring size
* support hidden SSID
* add per-MCS Rx stats
parents ed8e0ed5 3e2d8e1b
......@@ -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;
......
......@@ -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_ */
......
......@@ -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);
}
......@@ -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
......
......@@ -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;
......
......@@ -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);
......@@ -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);
}
......
......@@ -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);
}