Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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;
+18 −9
Original line number Diff line number Diff line
@@ -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_ */
+21 −0
Original line number Diff line number Diff line
@@ -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);
}
+6 −0
Original line number Diff line number Diff line
@@ -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
+82 −129
Original line number Diff line number Diff line
@@ -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;

Loading