SCSI fixes on 20220729
Four fixes, three in drivers. The two biggest fixes are ufs and the remaining driver and core fix are small and obvious (and the core fix is low risk). Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCYuQu2yYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishQ+vAQCtzbtY kY4Lg3jOVSgvXT220sCVnOoXJKHmORVWm7XXsAEAjVFLTVGhh/Voxlkhl/lxGnKV DJQWSdq6MjoxK56z2a4= =GGBX -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "Four fixes, three in drivers. The two biggest fixes are ufs and the remaining driver and core fix are small and obvious (and the core fix is low risk)" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: ufs: core: Fix a race condition related to device management scsi: core: Fix warning in scsi_alloc_sgtables() scsi: ufs: host: Hold reference returned by of_parse_phandle() scsi: mpt3sas: Stop fw fault watchdog work item during system shutdown
This commit is contained in:
commit
1c8ac1c4af
drivers
@ -11386,6 +11386,7 @@ scsih_shutdown(struct pci_dev *pdev)
|
||||
_scsih_ir_shutdown(ioc);
|
||||
_scsih_nvme_shutdown(ioc);
|
||||
mpt3sas_base_mask_interrupts(ioc);
|
||||
mpt3sas_base_stop_watchdog(ioc);
|
||||
ioc->shost_recovery = 1;
|
||||
mpt3sas_base_make_ioc_ready(ioc, SOFT_RESET);
|
||||
ioc->shost_recovery = 0;
|
||||
|
@ -450,7 +450,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
|
||||
goto out_put_request;
|
||||
|
||||
ret = 0;
|
||||
if (hdr->iovec_count) {
|
||||
if (hdr->iovec_count && hdr->dxfer_len) {
|
||||
struct iov_iter i;
|
||||
struct iovec *iov = NULL;
|
||||
|
||||
|
@ -2953,37 +2953,59 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||
static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
|
||||
struct ufshcd_lrb *lrbp, int max_timeout)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long time_left;
|
||||
unsigned long time_left = msecs_to_jiffies(max_timeout);
|
||||
unsigned long flags;
|
||||
bool pending;
|
||||
int err;
|
||||
|
||||
retry:
|
||||
time_left = wait_for_completion_timeout(hba->dev_cmd.complete,
|
||||
msecs_to_jiffies(max_timeout));
|
||||
time_left);
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
hba->dev_cmd.complete = NULL;
|
||||
if (likely(time_left)) {
|
||||
/*
|
||||
* The completion handler called complete() and the caller of
|
||||
* this function still owns the @lrbp tag so the code below does
|
||||
* not trigger any race conditions.
|
||||
*/
|
||||
hba->dev_cmd.complete = NULL;
|
||||
err = ufshcd_get_tr_ocs(lrbp);
|
||||
if (!err)
|
||||
err = ufshcd_dev_cmd_completion(hba, lrbp);
|
||||
}
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
if (!time_left) {
|
||||
} else {
|
||||
err = -ETIMEDOUT;
|
||||
dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
|
||||
__func__, lrbp->task_tag);
|
||||
if (!ufshcd_clear_cmds(hba, 1U << lrbp->task_tag))
|
||||
if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) {
|
||||
/* successfully cleared the command, retry if needed */
|
||||
err = -EAGAIN;
|
||||
/*
|
||||
* in case of an error, after clearing the doorbell,
|
||||
* we also need to clear the outstanding_request
|
||||
* field in hba
|
||||
*/
|
||||
spin_lock_irqsave(&hba->outstanding_lock, flags);
|
||||
__clear_bit(lrbp->task_tag, &hba->outstanding_reqs);
|
||||
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
|
||||
/*
|
||||
* Since clearing the command succeeded we also need to
|
||||
* clear the task tag bit from the outstanding_reqs
|
||||
* variable.
|
||||
*/
|
||||
spin_lock_irqsave(&hba->outstanding_lock, flags);
|
||||
pending = test_bit(lrbp->task_tag,
|
||||
&hba->outstanding_reqs);
|
||||
if (pending) {
|
||||
hba->dev_cmd.complete = NULL;
|
||||
__clear_bit(lrbp->task_tag,
|
||||
&hba->outstanding_reqs);
|
||||
}
|
||||
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
|
||||
|
||||
if (!pending) {
|
||||
/*
|
||||
* The completion handler ran while we tried to
|
||||
* clear the command.
|
||||
*/
|
||||
time_left = 1;
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
dev_err(hba->dev, "%s: failed to clear tag %d\n",
|
||||
__func__, lrbp->task_tag);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -108,9 +108,20 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool phandle_exists(const struct device_node *np,
|
||||
const char *phandle_name, int index)
|
||||
{
|
||||
struct device_node *parse_np = of_parse_phandle(np, phandle_name, index);
|
||||
|
||||
if (parse_np)
|
||||
of_node_put(parse_np);
|
||||
|
||||
return parse_np != NULL;
|
||||
}
|
||||
|
||||
#define MAX_PROP_SIZE 32
|
||||
static int ufshcd_populate_vreg(struct device *dev, const char *name,
|
||||
struct ufs_vreg **out_vreg)
|
||||
struct ufs_vreg **out_vreg)
|
||||
{
|
||||
char prop_name[MAX_PROP_SIZE];
|
||||
struct ufs_vreg *vreg = NULL;
|
||||
@ -122,7 +133,7 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
|
||||
}
|
||||
|
||||
snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
|
||||
if (!of_parse_phandle(np, prop_name, 0)) {
|
||||
if (!phandle_exists(np, prop_name, 0)) {
|
||||
dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
|
||||
__func__, prop_name);
|
||||
goto out;
|
||||
|
Loading…
Reference in New Issue
Block a user