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

Commit 66f5772e authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge tag 'iwlwifi-fixes-for-kvalo-2019-07-30' of...

Merge tag 'iwlwifi-fixes-for-kvalo-2019-07-30' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

We have a lot of fixes, most of them are also applicable to stable.
Notably:
 * fix use-after-free issues
 * fix DMA mapping API usage errors
 * fix frame drop occurring due to reorder buffer handling in
   RSS in certain conditions
 * fix rate scale locking issues
 * disable TX A-MSDU on older NICs as it causes problems and was
   never supposed to be supported
 * new PCI IDs
 * GEO_TX_POWER_LIMIT API issue that many people were hitting
parents df612421 71b256f8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -776,7 +776,6 @@ struct iwl_rss_config_cmd {
	u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */

#define IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE 128
#define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0
#define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf

@@ -812,10 +811,12 @@ struct iwl_rxq_sync_notification {
 *
 * @IWL_MVM_RXQ_EMPTY: empty sync notification
 * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
 * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
 */
enum iwl_mvm_rxq_notif_type {
	IWL_MVM_RXQ_EMPTY,
	IWL_MVM_RXQ_NOTIF_DEL_BA,
	IWL_MVM_RXQ_NSSN_SYNC,
};

/**
+3 −1
Original line number Diff line number Diff line
@@ -1640,6 +1640,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
	init_completion(&drv->request_firmware_complete);
	INIT_LIST_HEAD(&drv->list);

	iwl_load_fw_dbg_tlv(drv->trans->dev, drv->trans);

#ifdef CONFIG_IWLWIFI_DEBUGFS
	/* Create the device debugfs entries. */
	drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
@@ -1660,8 +1662,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
err_fw:
#ifdef CONFIG_IWLWIFI_DEBUGFS
	debugfs_remove_recursive(drv->dbgfs_drv);
	iwl_fw_dbg_free(drv->trans);
#endif
	iwl_fw_dbg_free(drv->trans);
	kfree(drv);
err:
	return ERR_PTR(ret);
+21 −8
Original line number Diff line number Diff line
@@ -755,7 +755,7 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)

	for (i = 0; i < n_profiles; i++) {
		/* the tables start at element 3 */
		static int pos = 3;
		int pos = 3;

		/* The EWRD profiles officially go from 2 to 4, but we
		 * save them in sar_profiles[1-3] (because we don't
@@ -880,6 +880,22 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
	return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}

static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
{
	/*
	 * The GEO_TX_POWER_LIMIT command is not supported on earlier
	 * firmware versions.  Unfortunately, we don't have a TLV API
	 * flag to rely on, so rely on the major version which is in
	 * the first byte of ucode_ver.  This was implemented
	 * initially on version 38 and then backported to 36, 29 and
	 * 17.
	 */
	return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
	       IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 36 ||
	       IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 ||
	       IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17;
}

int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{
	struct iwl_geo_tx_power_profiles_resp *resp;
@@ -909,6 +925,9 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
		.data = { data },
	};

	if (!iwl_mvm_sar_geo_support(mvm))
		return -EOPNOTSUPP;

	ret = iwl_mvm_send_cmd(mvm, &cmd);
	if (ret) {
		IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
@@ -934,13 +953,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
	int ret, i, j;
	u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);

	/*
	 * This command is not supported on earlier firmware versions.
	 * Unfortunately, we don't have a TLV API flag to rely on, so
	 * rely on the major version which is in the first byte of
	 * ucode_ver.
	 */
	if (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) < 41)
	if (!iwl_mvm_sar_geo_support(mvm))
		return 0;

	ret = iwl_mvm_sar_get_wgds_table(mvm);
+42 −16
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
	},
};

static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
				 enum set_key_cmd cmd,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta,
@@ -474,6 +474,18 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
	ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
	ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
	ieee80211_hw_set(hw, STA_MMPDU_TXQ);
	/*
	 * On older devices, enabling TX A-MSDU occasionally leads to
	 * something getting messed up, the command read from the FIFO
	 * gets out of sync and isn't a TX command, so that we have an
	 * assert EDC.
	 *
	 * It's not clear where the bug is, but since we didn't used to
	 * support A-MSDU until moving the mac80211 iTXQs, just leave it
	 * for older devices. We also don't see this issue on any newer
	 * devices.
	 */
	if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000)
		ieee80211_hw_set(hw, TX_AMSDU);
	ieee80211_hw_set(hw, TX_FRAG_LIST);

@@ -2726,7 +2738,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,

		mvmvif->ap_early_keys[i] = NULL;

		ret = iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
		ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
		if (ret)
			goto out_quota_failed;
	}
@@ -3494,7 +3506,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
	return ret;
}

static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
				 enum set_key_cmd cmd,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta,
@@ -3553,8 +3565,6 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
			return -EOPNOTSUPP;
	}

	mutex_lock(&mvm->mutex);

	switch (cmd) {
	case SET_KEY:
		if ((vif->type == NL80211_IFTYPE_ADHOC ||
@@ -3700,7 +3710,22 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
		ret = -EINVAL;
	}

	return ret;
}

static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
			       enum set_key_cmd cmd,
			       struct ieee80211_vif *vif,
			       struct ieee80211_sta *sta,
			       struct ieee80211_key_conf *key)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	int ret;

	mutex_lock(&mvm->mutex);
	ret = __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
	mutex_unlock(&mvm->mutex);

	return ret;
}

@@ -5041,7 +5066,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
	u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
	int ret;

	lockdep_assert_held(&mvm->mutex);

	if (!iwl_mvm_has_new_rx_api(mvm))
		return;
@@ -5052,13 +5076,15 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
		atomic_set(&mvm->queue_sync_counter,
			   mvm->trans->num_rx_queues);

	ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
	ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
				      size, !notif->sync);
	if (ret) {
		IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
		goto out;
	}

	if (notif->sync) {
		lockdep_assert_held(&mvm->mutex);
		ret = wait_event_timeout(mvm->rx_sync_waitq,
					 atomic_read(&mvm->queue_sync_counter) == 0 ||
					 iwl_mvm_is_radio_killed(mvm),
+4 −4
Original line number Diff line number Diff line
@@ -1664,9 +1664,9 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
			      struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
			    const u8 *data, u32 count);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
			    int queue);
			    const u8 *data, u32 count, bool async);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
			    struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
				   struct iwl_rx_cmd_buffer *rxb);
@@ -1813,7 +1813,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
#endif /* CONFIG_IWLWIFI_DEBUGFS */

/* rate scaling */
int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync);
int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg);
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
void rs_update_last_rssi(struct iwl_mvm *mvm,
Loading