Skip to content

Commit cd5432c

Browse files
Weitao Wanggregkh
authored andcommitted
USB: UAS: return ENODEV when submit urbs fail with device not attached
In the scenario of entering hibernation with udisk in the system, if the udisk was gone or resume fail in the thaw phase of hibernation. Its state will be set to NOTATTACHED. At this point, usb_hub_wq was already freezed and can't not handle disconnect event. Next, in the poweroff phase of hibernation, SYNCHRONIZE_CACHE SCSI command will be sent to this udisk when poweroff this scsi device, which will cause uas_submit_urbs to be called to submit URB for sense/data/cmd pipe. However, these URBs will submit fail as device was set to NOTATTACHED state. Then, uas_submit_urbs will return a value SCSI_MLQUEUE_DEVICE_BUSY to the caller. That will lead the SCSI layer go into an ugly loop and system fail to go into hibernation. On the other hand, when we specially check for -ENODEV in function uas_queuecommand_lck, returning DID_ERROR to SCSI layer will cause device poweroff fail and system shutdown instead of entering hibernation. To fix this issue, let uas_submit_urbs to return original generic error when submitting URB failed. At the same time, we need to translate -ENODEV to DID_NOT_CONNECT for the SCSI layer. Suggested-by: Oliver Neukum <oneukum@suse.com> Cc: stable@vger.kernel.org Signed-off-by: Weitao Wang <WeitaoWang-oc@zhaoxin.com> Link: https://lore.kernel.org/r/20240306180814.4897-1-WeitaoWang-oc@zhaoxin.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4cece76 commit cd5432c

1 file changed

Lines changed: 13 additions & 15 deletions

File tree

drivers/usb/storage/uas.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -533,46 +533,44 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
533533
* daft to me.
534534
*/
535535

536-
static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
536+
static int uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
537537
{
538538
struct uas_dev_info *devinfo = cmnd->device->hostdata;
539539
struct urb *urb;
540540
int err;
541541

542542
urb = uas_alloc_sense_urb(devinfo, gfp, cmnd);
543543
if (!urb)
544-
return NULL;
544+
return -ENOMEM;
545545
usb_anchor_urb(urb, &devinfo->sense_urbs);
546546
err = usb_submit_urb(urb, gfp);
547547
if (err) {
548548
usb_unanchor_urb(urb);
549549
uas_log_cmd_state(cmnd, "sense submit err", err);
550550
usb_free_urb(urb);
551-
return NULL;
552551
}
553-
return urb;
552+
return err;
554553
}
555554

556555
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
557556
struct uas_dev_info *devinfo)
558557
{
559558
struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
560-
struct urb *urb;
561559
int err;
562560

563561
lockdep_assert_held(&devinfo->lock);
564562
if (cmdinfo->state & SUBMIT_STATUS_URB) {
565-
urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
566-
if (!urb)
567-
return SCSI_MLQUEUE_DEVICE_BUSY;
563+
err = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
564+
if (err)
565+
return err;
568566
cmdinfo->state &= ~SUBMIT_STATUS_URB;
569567
}
570568

571569
if (cmdinfo->state & ALLOC_DATA_IN_URB) {
572570
cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
573571
cmnd, DMA_FROM_DEVICE);
574572
if (!cmdinfo->data_in_urb)
575-
return SCSI_MLQUEUE_DEVICE_BUSY;
573+
return -ENOMEM;
576574
cmdinfo->state &= ~ALLOC_DATA_IN_URB;
577575
}
578576

@@ -582,7 +580,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
582580
if (err) {
583581
usb_unanchor_urb(cmdinfo->data_in_urb);
584582
uas_log_cmd_state(cmnd, "data in submit err", err);
585-
return SCSI_MLQUEUE_DEVICE_BUSY;
583+
return err;
586584
}
587585
cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
588586
cmdinfo->state |= DATA_IN_URB_INFLIGHT;
@@ -592,7 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
592590
cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
593591
cmnd, DMA_TO_DEVICE);
594592
if (!cmdinfo->data_out_urb)
595-
return SCSI_MLQUEUE_DEVICE_BUSY;
593+
return -ENOMEM;
596594
cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
597595
}
598596

@@ -602,7 +600,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
602600
if (err) {
603601
usb_unanchor_urb(cmdinfo->data_out_urb);
604602
uas_log_cmd_state(cmnd, "data out submit err", err);
605-
return SCSI_MLQUEUE_DEVICE_BUSY;
603+
return err;
606604
}
607605
cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
608606
cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
@@ -611,7 +609,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
611609
if (cmdinfo->state & ALLOC_CMD_URB) {
612610
cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd);
613611
if (!cmdinfo->cmd_urb)
614-
return SCSI_MLQUEUE_DEVICE_BUSY;
612+
return -ENOMEM;
615613
cmdinfo->state &= ~ALLOC_CMD_URB;
616614
}
617615

@@ -621,7 +619,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
621619
if (err) {
622620
usb_unanchor_urb(cmdinfo->cmd_urb);
623621
uas_log_cmd_state(cmnd, "cmd submit err", err);
624-
return SCSI_MLQUEUE_DEVICE_BUSY;
622+
return err;
625623
}
626624
cmdinfo->cmd_urb = NULL;
627625
cmdinfo->state &= ~SUBMIT_CMD_URB;
@@ -698,7 +696,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
698696
* of queueing, no matter how fatal the error
699697
*/
700698
if (err == -ENODEV) {
701-
set_host_byte(cmnd, DID_ERROR);
699+
set_host_byte(cmnd, DID_NO_CONNECT);
702700
scsi_done(cmnd);
703701
goto zombie;
704702
}

0 commit comments

Comments
 (0)