Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Shawn Lin" <shawn.lin@rock-chips.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 2/2] scsi: ufs: core: Retry the full device init on fatal link loss
Date: Thu, 29 Oct 2026 02:06:39 +0000	[thread overview]
Message-ID: <sashiko-outbox-188630@kernel.org> (raw)
In-Reply-To: <20261029014839.3390579-3-shawn.lin@rock-chips.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] scsi: ufs: core: broken MCQ reconfiguration order in ufshcd_init() retry
- [High] scsi: ufs: error state cleared before ufshcd_hba_stop() in ufshcd_init()
- [High] scsi: ufs: core: missing ufs_hwmon_remove() and EE mask reset on init retry
- [Low] scsi: ufs: core: pass host_lock pointer to spin_lock_irqsave()
--

commit 23f03ec7ec12e66a1c4114bfb0fbd0cd5e4ff5c9
Author: Shawn Lin <shawn.lin@rock-chips.com>

scsi: ufs: core: Retry the full device init on fatal link loss

This commit retries ufshcd_full_device_init() up to three times in
ufshcd_init() when device initialization fails, resetting the device and
host controller and clearing latched error state between attempts.

> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index f1e54d7195370..bd82d6755739c 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -11468,8 +11468,52 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
>  
>  	/* Initialize hba, detect and initialize UFS device */
>  	ktime_t probe_start = ktime_get();
> +	int retries = 3;
>  
> -	err = ufshcd_full_device_init(hba);
> +	while (retries--) {
> +		unsigned long flags;
> +
> +		err = ufshcd_full_device_init(hba);
> +		if (!err)
> +			break;
> +
> +		if (!retries)
> +			break;
> +
> +		dev_warn(hba->dev, "UFS init failed %d, full retry (%d left)\n",
> +			 err, retries);
> +
> +		/*
> +		 * The failed attempt may have latched fatal errors and
> +		 * scheduled the error handler. Stop it and start the retry
> +		 * from a clean state, mirroring ufshcd_reset_and_restore().
> +		 */
> +		cancel_work_sync(&hba->eh_work);
> +		spin_lock_irqsave(hba->host->host_lock, flags);
> +		hba->saved_err = 0;
> +		hba->saved_uic_err = 0;
> +		hba->force_reset = false;
> +		hba->ufshcd_state = UFSHCD_STATE_RESET;
> +		spin_unlock_irqrestore(hba->host->host_lock, flags);

[Severity: Low]
In include/scsi/scsi_host.h, host_lock in struct Scsi_Host is defined by
value rather than as a pointer:

	spinlock_t		host_lock;

Should spin_lock_irqsave() and spin_unlock_irqrestore() in ufshcd_init()
take &hba->host->host_lock instead of hba->host->host_lock so that
drivers/ufs/core/ufshcd.c compiles?

> +
> +		ufshcd_device_reset(hba);
> +		ufs_put_device_desc(hba);
> +		ufshcd_hba_stop(hba);

[Severity: High]
What happens if an error or link-loss interrupt fires while the host
controller is still active during ufshcd_device_reset(), before
ufshcd_hba_stop() disables the controller?

Because cancel_work_sync(&hba->eh_work) and the clearing of hba->saved_err,
hba->saved_uic_err, and hba->ufshcd_state happen before ufshcd_hba_stop(),
resetting the attached device while controller interrupts are enabled can
trigger ufshcd_intr() -> ufshcd_check_errors():

	hba->saved_err |= hba->errors;
	hba->saved_uic_err |= hba->uic_error;
	...
	ufshcd_schedule_eh_work(hba);

Since hba->ufs_device_wlun is not set yet and hba->host_sem is not held
during ufshcd_init(), ufshcd_err_handler() can then run concurrently on
hba->eh_wq:

	down(&hba->host_sem);
	spin_lock_irqsave(&hba->host->host_lock, flags);
	if (ufshcd_err_handling_should_stop(hba)) {
		if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
			hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
		spin_unlock_irqrestore(&hba->host->host_lock, flags);
		up(&hba->host_sem);
		return;
	}

Could this overwrite hba->ufshcd_state and leave hba->saved_err and
hba->saved_uic_err latched during the retry? Should ufshcd_hba_stop(hba) be
called before cancelling hba->eh_work, clearing the error state, and
resetting the device?

[Severity: High]
Can this retry path also leak the hwmon device and struct ufs_hwmon_data if
ufshcd_full_device_init() fails in ufshcd_post_device_init() after
ufshcd_device_params_init() has already succeeded?

During ufshcd_full_device_init(), the call chain is:

	ufshcd_device_params_init()
	  ufs_get_device_desc()
	    ufshcd_temp_notif_probe()
	      ufshcd_enable_ee(hba, mask);
	      ufs_hwmon_probe(hba, mask);
	ufshcd_post_device_init()
	  ufshcd_config_pwr_mode()

If ufshcd_post_device_init() fails, ufs_put_device_desc() only frees
dev_info->model and dev_info->device_id. On the next iteration,
ufs_hwmon_probe() in drivers/ufs/core/ufs-hwmon.c allocates a new
struct ufs_hwmon_data, registers a second hwmon device, and overwrites
hba->hwmon_device:

	data = kzalloc_obj(*data);
	if (!data)
		return;
	...
	hwmon = hwmon_device_register_with_info(dev, "ufs", data, &ufs_hwmon_hba_info, NULL);
	...
	hba->hwmon_device = hwmon;

In addition, hba->ee_ctrl_mask and hba->ee_drv_mask retain the bits set by
ufshcd_enable_ee() before ufshcd_device_reset() reset the device, which
causes ufshcd_update_ee_control() on the next attempt to see an unchanged
mask and skip writing the exception event control attribute to the device.
Should the retry cleanup call ufs_hwmon_remove(hba) and clear the exception
event masks?

> +		if (ufshcd_hba_enable(hba)) {
> +			dev_err(hba->dev, "Host controller enable failed\n");
> +			ufshcd_print_evt_hist(hba);
> +			ufshcd_print_host_state(hba);
> +			goto out_release;
> +		}
> +
> +		/* Reconfigure MCQ upon controller re-enable */
> +		if (hba->mcq_enabled) {
> +			ufshcd_config_mcq(hba);
> +			ufshcd_mcq_enable(hba);
> +		}

[Severity: High]
Is the ordering of ufshcd_config_mcq(hba) and ufshcd_mcq_enable(hba) here
intended?

On the initial probe path, ufshcd_add_scsi_host() calls ufshcd_mcq_enable()
first, and ufshcd_full_device_init() calls ufshcd_config_mcq() only after
ufshcd_link_startup() completes:

	err = ufshcd_link_startup(hba);
	if (err)
		return err;

	if (hba->mcq_enabled)
		ufshcd_config_mcq(hba);

In the retry path of ufshcd_init(), calling ufshcd_config_mcq(hba) before
ufshcd_mcq_enable(hba) configures the queues and enables them in
ufshcd_mcq_make_queues_operational() before ufshcd_mcq_enable() selects
multi-circular queue mode in REG_UFS_MEM_CFG and before the next attempt's
ufshcd_link_startup(hba). Then, when ufshcd_full_device_init() runs on the
next iteration, it calls ufshcd_config_mcq(hba) a second time while the
hardware queues are already enabled.

Furthermore, if ufshcd_link_startup() encounters an error on its own retry
and calls ufshcd_hba_enable(hba), the controller reset will clear
REG_UFS_MEM_CFG again without ufshcd_mcq_enable(hba) being re-applied before
ufshcd_config_mcq(hba). Should the retry path only call
ufshcd_mcq_enable(hba) (or should ufshcd_mcq_enable(hba) be called right
before ufshcd_config_mcq(hba) inside ufshcd_full_device_init())?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261029014839.3390579-1-shawn.lin@rock-chips.com?part=2

  reply	other threads:[~2026-10-29  2:06 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29  1:48 [PATCH v2 0/2] Retry the full device init on fatal link loss Shawn Lin
2026-10-29  1:48 ` [PATCH v2 1/2] scsi: ufs: core: Move the device initialization sequence into a new function Shawn Lin
2026-10-29  1:48 ` [PATCH v2 2/2] scsi: ufs: core: Retry the full device init on fatal link loss Shawn Lin
2026-10-29  2:06   ` sashiko-bot [this message]
2026-10-29  2:17     ` Shawn Lin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-188630@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shawn.lin@rock-chips.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox