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

Commit 20c62c79 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'wireless-drivers-for-davem-2017-09-25' of...

Merge tag 'wireless-drivers-for-davem-2017-09-25' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers



Kalle Valo says:

====================
wireless-drivers fixes for 4.14

Quite a lot of fixes this time. Most notable is the brcmfmac fix for a
CVE issue.

iwlwifi

* a couple of bugzilla bugs related to multicast handling

* two fixes for WoWLAN bugs that were causing queue hangs and
  re-initialization problems

* two fixes for potential uninitialized variable use reported by Dan
  Carpenter in relation to a recently introduced patch

* a fix for buffer reordering in the newly supported 9000 device
  family

* fix a race when starting aggregation

* small fix for a recent patch to wake mac80211 queues

* send non-bufferable management frames in the generic queue so they
  are not sent on queues that are under power-save

ath10k

* fix a PCI PM related gcc warning

brcmfmac

* CVE-2017-0786: add length check scan results from firmware

* respect passive scan requests from user space

qtnfmac

* fix race in tx path when using multiple interfaces

* cancel ongoing scan when removing the wireless interface
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2760f5a3 3e747fa1
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -3396,9 +3396,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)

MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);

#ifdef CONFIG_PM

static int ath10k_pci_pm_suspend(struct device *dev)
static __maybe_unused int ath10k_pci_pm_suspend(struct device *dev)
{
	struct ath10k *ar = dev_get_drvdata(dev);
	int ret;
@@ -3414,7 +3412,7 @@ static int ath10k_pci_pm_suspend(struct device *dev)
	return ret;
}

static int ath10k_pci_pm_resume(struct device *dev)
static __maybe_unused int ath10k_pci_pm_resume(struct device *dev)
{
	struct ath10k *ar = dev_get_drvdata(dev);
	int ret;
@@ -3433,7 +3431,6 @@ static int ath10k_pci_pm_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ath10k_pci_pm_ops,
			 ath10k_pci_pm_suspend,
			 ath10k_pci_pm_resume);
#endif

static struct pci_driver ath10k_pci_driver = {
	.name = "ath10k_pci",
+19 −18
Original line number Diff line number Diff line
@@ -980,7 +980,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,

	eth_broadcast_addr(params_le->bssid);
	params_le->bss_type = DOT11_BSSTYPE_ANY;
	params_le->scan_type = 0;
	params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
	params_le->channel_num = 0;
	params_le->nprobes = cpu_to_le32(-1);
	params_le->active_time = cpu_to_le32(-1);
@@ -988,12 +988,9 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
	params_le->home_time = cpu_to_le32(-1);
	memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));

	/* if request is null exit so it will be all channel broadcast scan */
	if (!request)
		return;

	n_ssids = request->n_ssids;
	n_channels = request->n_channels;

	/* Copy channel array if applicable */
	brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
		  n_channels);
@@ -1030,16 +1027,8 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
			ptr += sizeof(ssid_le);
		}
	} else {
		brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
		if ((request->ssids) && request->ssids->ssid_len) {
			brcmf_dbg(SCAN, "SSID %s len=%d\n",
				  params_le->ssid_le.SSID,
				  request->ssids->ssid_len);
			params_le->ssid_le.SSID_len =
				cpu_to_le32(request->ssids->ssid_len);
			memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
				request->ssids->ssid_len);
		}
		brcmf_dbg(SCAN, "Performing passive scan\n");
		params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
	}
	/* Adding mask to channel numbers */
	params_le->channel_num =
@@ -3162,6 +3151,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
	s32 status;
	struct brcmf_escan_result_le *escan_result_le;
	u32 escan_buflen;
	struct brcmf_bss_info_le *bss_info_le;
	struct brcmf_bss_info_le *bss = NULL;
	u32 bi_length;
@@ -3181,11 +3171,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,

	if (status == BRCMF_E_STATUS_PARTIAL) {
		brcmf_dbg(SCAN, "ESCAN Partial result\n");
		if (e->datalen < sizeof(*escan_result_le)) {
			brcmf_err("invalid event data length\n");
			goto exit;
		}
		escan_result_le = (struct brcmf_escan_result_le *) data;
		if (!escan_result_le) {
			brcmf_err("Invalid escan result (NULL pointer)\n");
			goto exit;
		}
		escan_buflen = le32_to_cpu(escan_result_le->buflen);
		if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||
		    escan_buflen > e->datalen ||
		    escan_buflen < sizeof(*escan_result_le)) {
			brcmf_err("Invalid escan buffer length: %d\n",
				  escan_buflen);
			goto exit;
		}
		if (le16_to_cpu(escan_result_le->bss_count) != 1) {
			brcmf_err("Invalid bss_count %d: ignoring\n",
				  escan_result_le->bss_count);
@@ -3202,9 +3204,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
		}

		bi_length = le32_to_cpu(bss_info_le->length);
		if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
					WL_ESCAN_RESULTS_FIXED_SIZE)) {
			brcmf_err("Invalid bss_info length %d: ignoring\n",
		if (bi_length != escan_buflen -	WL_ESCAN_RESULTS_FIXED_SIZE) {
			brcmf_err("Ignoring invalid bss_info length: %d\n",
				  bi_length);
			goto exit;
		}
+5 −0
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@
#define BRCMF_SCAN_PARAMS_COUNT_MASK	0x0000ffff
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT	16

/* scan type definitions */
#define BRCMF_SCANTYPE_DEFAULT		0xFF
#define BRCMF_SCANTYPE_ACTIVE		0
#define BRCMF_SCANTYPE_PASSIVE		1

#define BRCMF_WSEC_MAX_PSK_LEN		32
#define	BRCMF_WSEC_PASSPHRASE		BIT(0)

+1 −1
Original line number Diff line number Diff line
@@ -2167,7 +2167,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
	 * 1. We are not using a unified image
	 * 2. We are using a unified image but had an error while exiting D3
	 */
	set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
	set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
	set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
	/*
	 * When switching images we return 1, which causes mac80211
+59 −3
Original line number Diff line number Diff line
@@ -1546,6 +1546,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
	struct iwl_mvm_mc_iter_data *data = _data;
	struct iwl_mvm *mvm = data->mvm;
	struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd;
	struct iwl_host_cmd hcmd = {
		.id = MCAST_FILTER_CMD,
		.flags = CMD_ASYNC,
		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
	};
	int ret, len;

	/* if we don't have free ports, mcast frames will be dropped */
@@ -1560,7 +1565,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
	memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
	len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);

	ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
	hcmd.len[0] = len;
	hcmd.data[0] = cmd;

	ret = iwl_mvm_send_cmd(mvm, &hcmd);
	if (ret)
		IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
}
@@ -1635,6 +1643,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
	if (!cmd)
		goto out;

	if (changed_flags & FIF_ALLMULTI)
		cmd->pass_all = !!(*total_flags & FIF_ALLMULTI);

	if (cmd->pass_all)
		cmd->count = 0;

	iwl_mvm_recalc_multicast(mvm);
out:
	mutex_unlock(&mvm->mutex);
@@ -2563,7 +2577,7 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
			 * queues, so we should never get a second deferred
			 * frame for the RA/TID.
			 */
			iwl_mvm_start_mac_queues(mvm, info->hw_queue);
			iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));
			ieee80211_free_txskb(mvm->hw, skb);
		}
	}
@@ -3975,6 +3989,43 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
	return ret;
}

static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
{
	if (drop) {
		if (iwl_mvm_has_new_tx_api(mvm))
			/* TODO new tx api */
			WARN_ONCE(1,
				  "Need to implement flush TX queue\n");
		else
			iwl_mvm_flush_tx_path(mvm,
				iwl_mvm_flushable_queues(mvm) & queues,
				0);
	} else {
		if (iwl_mvm_has_new_tx_api(mvm)) {
			struct ieee80211_sta *sta;
			int i;

			mutex_lock(&mvm->mutex);

			for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
				sta = rcu_dereference_protected(
						mvm->fw_id_to_mac_id[i],
						lockdep_is_held(&mvm->mutex));
				if (IS_ERR_OR_NULL(sta))
					continue;

				iwl_mvm_wait_sta_queues_empty(mvm,
						iwl_mvm_sta_from_mac80211(sta));
			}

			mutex_unlock(&mvm->mutex);
		} else {
			iwl_trans_wait_tx_queues_empty(mvm->trans,
						       queues);
		}
	}
}

static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif, u32 queues, bool drop)
{
@@ -3985,7 +4036,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
	int i;
	u32 msk = 0;

	if (!vif || vif->type != NL80211_IFTYPE_STATION)
	if (!vif) {
		iwl_mvm_flush_no_vif(mvm, queues, drop);
		return;
	}

	if (vif->type != NL80211_IFTYPE_STATION)
		return;

	/* Make sure we're done with the deferred traffic before flushing */
Loading