Commit edeee68c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "All fixes in drivers. The largest diffstat in ufs is caused by the doc
  update with the next being the qcom null pointer deref fix"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: ufs: ufs-qcom: Fix ESI null pointer dereference
  scsi: ufs: core: Rename ufshcd_wait_for_doorbell_clr()
  scsi: ufs: core: Fix the return value documentation
  scsi: ufs: core: Remove WARN_ON_ONCE() call from ufshcd_uic_cmd_compl()
  scsi: ufs: core: Fix IRQ lock inversion for the SCSI host lock
  scsi: qla4xxx: Prevent a potential error pointer dereference
  scsi: ufs: ufs-pci: Add support for Intel Wildcat Lake
  scsi: fnic: Remove a useless struct mempool forward declaration
parents afd58777 6300d5c5
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -323,8 +323,6 @@ enum fnic_state {
	FNIC_IN_ETH_TRANS_FC_MODE,
};

struct mempool;

enum fnic_role_e {
	FNIC_ROLE_FCP_INITIATOR = 0,
};
+2 −0
Original line number Diff line number Diff line
@@ -6606,6 +6606,8 @@ static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,

	ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0);
	vfree(dst_addr);
	if (IS_ERR(ep))
		return NULL;
	return ep;
}

+44 −32
Original line number Diff line number Diff line
@@ -1303,7 +1303,7 @@ static u32 ufshcd_pending_cmds(struct ufs_hba *hba)
 *
 * Return: 0 upon success; -EBUSY upon timeout.
 */
static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba,
static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba,
					u64 wait_timeout_us)
{
	int ret = 0;
@@ -1431,7 +1431,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
	down_write(&hba->clk_scaling_lock);

	if (!hba->clk_scaling.is_allowed ||
	    ufshcd_wait_for_doorbell_clr(hba, timeout_us)) {
	    ufshcd_wait_for_pending_cmds(hba, timeout_us)) {
		ret = -EBUSY;
		up_write(&hba->clk_scaling_lock);
		mutex_unlock(&hba->wb_mutex);
@@ -3199,7 +3199,8 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
}

/*
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
		struct ufshcd_lrb *lrbp, int max_timeout)
@@ -3275,7 +3276,6 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
		}
	}

	WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
	return err;
}

@@ -3294,7 +3294,8 @@ static void ufshcd_dev_man_unlock(struct ufs_hba *hba)
}

/*
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
			  const u32 tag, int timeout)
@@ -3317,7 +3318,8 @@ static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
 * @cmd_type: specifies the type (NOP, Query...)
 * @timeout: timeout in milliseconds
 *
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 *
 * NOTE: Since there is only one available tag for device management commands,
 * it is expected you hold the hba->dev_cmd.lock mutex.
@@ -3363,6 +3365,10 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
	(*request)->upiu_req.selector = selector;
}

/*
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_query_flag_retry(struct ufs_hba *hba,
	enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res)
{
@@ -3383,7 +3389,6 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
		dev_err(hba->dev,
			"%s: query flag, opcode %d, idn %d, failed with error %d after %d retries\n",
			__func__, opcode, idn, ret, retries);
	WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
	return ret;
}

@@ -3395,7 +3400,8 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
 * @index: flag index to access
 * @flag_res: the flag value after the query request completes
 *
 * Return: 0 for success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
			enum flag_idn idn, u8 index, bool *flag_res)
@@ -3451,7 +3457,6 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,

out_unlock:
	ufshcd_dev_man_unlock(hba);
	WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
	return err;
}

@@ -3464,7 +3469,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
 * @selector: selector field
 * @attr_val: the attribute value after the query request completes
 *
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
		      enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
@@ -3513,7 +3519,6 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,

out_unlock:
	ufshcd_dev_man_unlock(hba);
	WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
	return err;
}

@@ -3528,7 +3533,8 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
 * @attr_val: the attribute value after the query request
 * completes
 *
 * Return: 0 for success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_query_attr_retry(struct ufs_hba *hba,
	enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
@@ -3551,12 +3557,12 @@ int ufshcd_query_attr_retry(struct ufs_hba *hba,
		dev_err(hba->dev,
			"%s: query attribute, idn %d, failed with error %d after %d retries\n",
			__func__, idn, ret, QUERY_REQ_RETRIES);
	WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
	return ret;
}

/*
 * Return: 0 if successful; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int __ufshcd_query_descriptor(struct ufs_hba *hba,
			enum query_opcode opcode, enum desc_idn idn, u8 index,
@@ -3615,7 +3621,6 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
out_unlock:
	hba->dev_cmd.query.descriptor = NULL;
	ufshcd_dev_man_unlock(hba);
	WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
	return err;
}

@@ -3632,7 +3637,8 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
 * The buf_len parameter will contain, on return, the length parameter
 * received on the response.
 *
 * Return: 0 for success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
				  enum query_opcode opcode,
@@ -3650,7 +3656,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
			break;
	}

	WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
	return err;
}

@@ -3663,7 +3668,8 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
 * @param_read_buf: pointer to buffer where parameter would be read
 * @param_size: sizeof(param_read_buf)
 *
 * Return: 0 in case of success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_read_desc_param(struct ufs_hba *hba,
			   enum desc_idn desc_id,
@@ -3730,7 +3736,6 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
out:
	if (is_kmalloc)
		kfree(desc_buf);
	WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
	return ret;
}

@@ -4781,7 +4786,8 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
 *
 * Set fDeviceInit flag and poll until device toggles it.
 *
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_complete_dev_init(struct ufs_hba *hba)
{
@@ -5135,7 +5141,8 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
 * not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT
 * and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations.
 *
 * Return: 0 upon success; < 0 upon failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_verify_dev_init(struct ufs_hba *hba)
{
@@ -5559,9 +5566,9 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
	irqreturn_t retval = IRQ_NONE;
	struct uic_command *cmd;

	spin_lock(hba->host->host_lock);
	guard(spinlock_irqsave)(hba->host->host_lock);
	cmd = hba->active_uic_cmd;
	if (WARN_ON_ONCE(!cmd))
	if (!cmd)
		goto unlock;

	if (ufshcd_is_auto_hibern8_error(hba, intr_status))
@@ -5586,8 +5593,6 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
		ufshcd_add_uic_command_trace(hba, cmd, UFS_CMD_COMP);

unlock:
	spin_unlock(hba->host->host_lock);

	return retval;
}

@@ -5869,7 +5874,8 @@ static inline int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask)
 * as the device is allowed to manage its own way of handling background
 * operations.
 *
 * Return: zero on success, non-zero on failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
{
@@ -5908,7 +5914,8 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
 * host is idle so that BKOPS are managed effectively without any negative
 * impacts.
 *
 * Return: zero on success, non-zero on failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
{
@@ -6058,6 +6065,10 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
				__func__, err);
}

/*
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id)
{
	struct utp_upiu_query_v4_0 *upiu_resp;
@@ -6920,7 +6931,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
	bool queue_eh_work = false;
	irqreturn_t retval = IRQ_NONE;

	spin_lock(hba->host->host_lock);
	guard(spinlock_irqsave)(hba->host->host_lock);
	hba->errors |= UFSHCD_ERROR_MASK & intr_status;

	if (hba->errors & INT_FATAL_ERRORS) {
@@ -6979,7 +6990,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
	 */
	hba->errors = 0;
	hba->uic_error = 0;
	spin_unlock(hba->host->host_lock);

	return retval;
}

@@ -7454,7 +7465,8 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 * @sg_list:	Pointer to SG list when DATA IN/OUT UPIU is required in ARPMB operation
 * @dir:	DMA direction
 *
 * Return: zero on success, non-zero on failure.
 * Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
 * < 0 if another error occurred.
 */
int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu,
			 struct utp_upiu_req *rsp_upiu, struct ufs_ehs *req_ehs,
+15 −24
Original line number Diff line number Diff line
@@ -2070,17 +2070,6 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data)
	return IRQ_HANDLED;
}

static void ufs_qcom_irq_free(struct ufs_qcom_irq *uqi)
{
	for (struct ufs_qcom_irq *q = uqi; q->irq; q++)
		devm_free_irq(q->hba->dev, q->irq, q->hba);

	platform_device_msi_free_irqs_all(uqi->hba->dev);
	devm_kfree(uqi->hba->dev, uqi);
}

DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *, if (_T) ufs_qcom_irq_free(_T))

static int ufs_qcom_config_esi(struct ufs_hba *hba)
{
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -2095,18 +2084,18 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
	 */
	nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL];

	struct ufs_qcom_irq *qi __free(ufs_qcom_irq) =
		devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL);
	if (!qi)
		return -ENOMEM;
	/* Preset so __free() has a pointer to hba in all error paths */
	qi[0].hba = hba;

	ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs,
						      ufs_qcom_write_msi_msg);
	if (ret) {
		dev_err(hba->dev, "Failed to request Platform MSI %d\n", ret);
		return ret;
		dev_warn(hba->dev, "Platform MSI not supported or failed, continuing without ESI\n");
		return ret; /* Continue without ESI */
	}

	struct ufs_qcom_irq *qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL);

	if (!qi) {
		platform_device_msi_free_irqs_all(hba->dev);
		return -ENOMEM;
	}

	for (int idx = 0; idx < nr_irqs; idx++) {
@@ -2117,15 +2106,17 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
		ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler,
				       IRQF_SHARED, "qcom-mcq-esi", qi + idx);
		if (ret) {
			dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n",
			dev_err(hba->dev, "%s: Failed to request IRQ for %d, err = %d\n",
				__func__, qi[idx].irq, ret);
			qi[idx].irq = 0;
			/* Free previously allocated IRQs */
			for (int j = 0; j < idx; j++)
				devm_free_irq(hba->dev, qi[j].irq, qi + j);
			platform_device_msi_free_irqs_all(hba->dev);
			devm_kfree(hba->dev, qi);
			return ret;
		}
	}

	retain_and_null_ptr(qi);

	if (host->hw_ver.major >= 6) {
		ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1),
			    REG_UFS_CFG3);
+1 −0
Original line number Diff line number Diff line
@@ -630,6 +630,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = {
	{ PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
	{ PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
	{ PCI_VDEVICE(INTEL, 0xE447), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
	{ PCI_VDEVICE(INTEL, 0x4D47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
	{ }	/* terminate list */
};