Commit db22ce68 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'wireless-drivers-2021-01-26' of...

Merge tag 'wireless-drivers-2021-01-26' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo says:

====================
wireless-drivers fixes for v5.11

Second set of fixes for v5.11. Like in last time we again have more
fixes than usual Actually a bit too much for my liking in this state
of the cycle, but due to unrelated challenges I was only able to
submit them now.

We have few important crash fixes, iwlwifi modifying read-only data
being the most reported issue, and also smaller fixes to iwlwifi.

mt76
 * fix a clang warning about enum usage
 * fix rx buffer refcounting crash

mt7601u
 * fix rx buffer refcounting crash
 * fix crash when unbplugging the device

iwlwifi
 * fix a crash where we were modifying read-only firmware data
 * lots of smaller fixes all over the driver

* tag 'wireless-drivers-2021-01-26' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers: (24 commits)
  mt7601u: fix kernel crash unplugging the device
  iwlwifi: queue: bail out on invalid freeing
  iwlwifi: mvm: guard against device removal in reprobe
  iwlwifi: Fix IWL_SUBDEVICE_NO_160 macro to use the correct bit.
  iwlwifi: mvm: clear IN_D3 after wowlan status cmd
  iwlwifi: pcie: add rules to match Qu with Hr2
  iwlwifi: mvm: invalidate IDs of internal stations at mvm start
  iwlwifi: mvm: fix the return type for DSM functions 1 and 2
  iwlwifi: pcie: reschedule in long-running memory reads
  iwlwifi: pcie: use jiffies for memory read spin time limit
  iwlwifi: pcie: fix context info memory leak
  iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
  iwlwifi: pcie: set LTR on more devices
  iwlwifi: queue: don't crash if txq->entries is NULL
  iwlwifi: fix the NMI flow for old devices
  iwlwifi: pnvm: don't try to load after failures
  iwlwifi: pnvm: don't skip everything when not reloading
  iwlwifi: pcie: avoid potential PNVM leaks
  iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
  iwlwifi: mvm: skip power command when unbinding vif during CSA
  ...
====================

Link: https://lore.kernel.org/r/20210126092202.6A367C433CA@smtp.codeaurora.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 81a86e1b 0acb20a5
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6 AX211 160MHz";
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6 AX411 160MHz";
const char iwl_ma_name[] = "Intel(R) Wi-Fi 6";
@@ -340,6 +341,18 @@ const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
	.num_rbds = IWL_NUM_RBDS_22000_HE,
};

const struct iwl_cfg iwl_qu_b0_hr_b0 = {
	.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
	IWL_DEVICE_22500,
	/*
	 * This device doesn't support receiving BlockAck with a large bitmap
	 * so we need to restrict the size of transmitted aggregation to the
	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
	 */
	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
	.num_rbds = IWL_NUM_RBDS_22000_HE,
};

const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
	.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
	.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
@@ -366,6 +379,18 @@ const struct iwl_cfg iwl_qu_c0_hr1_b0 = {
	.num_rbds = IWL_NUM_RBDS_22000_HE,
};

const struct iwl_cfg iwl_qu_c0_hr_b0 = {
	.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
	IWL_DEVICE_22500,
	/*
	 * This device doesn't support receiving BlockAck with a large bitmap
	 * so we need to restrict the size of transmitted aggregation to the
	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
	 */
	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
	.num_rbds = IWL_NUM_RBDS_22000_HE,
};

const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
	.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
	.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+50 −15
Original line number Diff line number Diff line
@@ -80,35 +80,52 @@ static void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func,
}

/*
 * Evaluate a DSM with no arguments and a single u8 return value (inside a
 * buffer object), verify and return that value.
 * Generic function to evaluate a DSM with no arguments
 * and an integer return value,
 * (as an integer object or inside a buffer object),
 * verify and assign the value in the "value" parameter.
 * return 0 in success and the appropriate errno otherwise.
 */
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func)
static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func,
				    u64 *value, size_t expected_size)
{
	union acpi_object *obj;
	int ret;
	int ret = 0;

	obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL);
	if (IS_ERR(obj))
		return -ENOENT;

	if (obj->type != ACPI_TYPE_BUFFER) {
	if (IS_ERR(obj)) {
		IWL_DEBUG_DEV_RADIO(dev,
				    "ACPI: DSM method did not return a valid object, type=%d\n",
				    obj->type);
		ret = -EINVAL;
		goto out;
				    "Failed to get  DSM object. func= %d\n",
				    func);
		return -ENOENT;
	}

	if (obj->buffer.length != sizeof(u8)) {
	if (obj->type == ACPI_TYPE_INTEGER) {
		*value = obj->integer.value;
	} else if (obj->type == ACPI_TYPE_BUFFER) {
		__le64 le_value = 0;

		if (WARN_ON_ONCE(expected_size > sizeof(le_value)))
			return -EINVAL;

		/* if the buffer size doesn't match the expected size */
		if (obj->buffer.length != expected_size)
			IWL_DEBUG_DEV_RADIO(dev,
				    "ACPI: DSM method returned invalid buffer, length=%d\n",
					    "ACPI: DSM invalid buffer size, padding or truncating (%d)\n",
					    obj->buffer.length);

		 /* assuming LE from Intel BIOS spec */
		memcpy(&le_value, obj->buffer.pointer,
		       min_t(size_t, expected_size, (size_t)obj->buffer.length));
		*value = le64_to_cpu(le_value);
	} else {
		IWL_DEBUG_DEV_RADIO(dev,
				    "ACPI: DSM method did not return a valid object, type=%d\n",
				    obj->type);
		ret = -EINVAL;
		goto out;
	}

	ret = obj->buffer.pointer[0];
	IWL_DEBUG_DEV_RADIO(dev,
			    "ACPI: DSM method evaluated: func=%d, ret=%d\n",
			    func, ret);
@@ -116,6 +133,24 @@ int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func)
	ACPI_FREE(obj);
	return ret;
}

/*
 * Evaluate a DSM with no arguments and a u8 return value,
 */
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func, u8 *value)
{
	int ret;
	u64 val;

	ret = iwl_acpi_get_dsm_integer(dev, rev, func, &val, sizeof(u8));

	if (ret < 0)
		return ret;

	/* cast val (u64) to be u8 */
	*value = (u8)val;
	return 0;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u8);

union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
+4 −3
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (C) 2017 Intel Deutschland GmbH
 * Copyright (C) 2018-2020 Intel Corporation
 * Copyright (C) 2018-2021 Intel Corporation
 */
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@@ -99,7 +99,7 @@ struct iwl_fw_runtime;

void *iwl_acpi_get_object(struct device *dev, acpi_string method);

int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func);
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func, u8 *value);

union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
					 union acpi_object *data,
@@ -159,7 +159,8 @@ static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
	return ERR_PTR(-ENOENT);
}

static inline int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func)
static inline
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func, u8 *value)
{
	return -ENOENT;
}
+31 −25
Original line number Diff line number Diff line
@@ -224,20 +224,19 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
int iwl_pnvm_load(struct iwl_trans *trans,
		  struct iwl_notif_wait_data *notif_wait)
{
	const struct firmware *pnvm;
	struct iwl_notification_wait pnvm_wait;
	static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
						PNVM_INIT_COMPLETE_NTFY) };
	char pnvm_name[64];
	int ret;

	/* if the SKU_ID is empty, there's nothing to do */
	if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
		return 0;

	/* if we already have it, nothing to do either */
	if (trans->pnvm_loaded)
		return 0;
	/* load from disk only if we haven't done it (or tried) before */
	if (!trans->pnvm_loaded) {
		const struct firmware *pnvm;
		char pnvm_name[64];
		int ret;

		/*
		 * The prefix unfortunately includes a hyphen at the end, so
@@ -254,11 +253,18 @@ int iwl_pnvm_load(struct iwl_trans *trans,
		if (ret) {
			IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n",
				     pnvm_name, ret);
			/*
			 * Pretend we've loaded it - at least we've tried and
			 * couldn't load it at all, so there's no point in
			 * trying again over and over.
			 */
			trans->pnvm_loaded = true;
		} else {
			iwl_pnvm_parse(trans, pnvm->data, pnvm->size);

			release_firmware(pnvm);
		}
	}

	iwl_init_notification_wait(notif_wait, &pnvm_wait,
				   ntf_cmds, ARRAY_SIZE(ntf_cmds),
+5 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (C) 2005-2014, 2018-2020 Intel Corporation
 * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
 * Copyright (C) 2016-2017 Intel Deutschland GmbH
 */
#ifndef __IWL_CONFIG_H__
@@ -445,7 +445,7 @@ struct iwl_cfg {
#define IWL_CFG_CORES_BT_GNSS		0x5

#define IWL_SUBDEVICE_RF_ID(subdevice)	((u16)((subdevice) & 0x00F0) >> 4)
#define IWL_SUBDEVICE_NO_160(subdevice)	((u16)((subdevice) & 0x0100) >> 9)
#define IWL_SUBDEVICE_NO_160(subdevice)	((u16)((subdevice) & 0x0200) >> 9)
#define IWL_SUBDEVICE_CORES(subdevice)	((u16)((subdevice) & 0x1C00) >> 10)

struct iwl_dev_info {
@@ -491,6 +491,7 @@ extern const char iwl9260_killer_1550_name[];
extern const char iwl9560_killer_1550i_name[];
extern const char iwl9560_killer_1550s_name[];
extern const char iwl_ax200_name[];
extern const char iwl_ax203_name[];
extern const char iwl_ax201_name[];
extern const char iwl_ax101_name[];
extern const char iwl_ax200_killer_1650w_name[];
@@ -574,6 +575,8 @@ extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
extern const struct iwl_cfg iwl_qu_b0_hr1_b0;
extern const struct iwl_cfg iwl_qu_c0_hr1_b0;
extern const struct iwl_cfg iwl_quz_a0_hr1_b0;
extern const struct iwl_cfg iwl_qu_b0_hr_b0;
extern const struct iwl_cfg iwl_qu_c0_hr_b0;
extern const struct iwl_cfg iwl_ax200_cfg_cc;
extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
Loading