If device shutdown is blocking for a few seconds after xhci_pci_shutdown, disk_check_events will get scheduled becase block.events_dfl_poll_msecs is set to 2000 by user space. usb-storage can get USB access error and then call usb_reset_device. Some SanDisk USB flashes, 0781:5567 and 0781:5581, are lost after reboot. This can be simulated by injecting mdelay(5000) at the end of i915_driver_shutdown. Add event block in sd_shutdown to prevent disk_check_events scheduled during the potential blocking. [ 27.324042][ T1] shutdown[1]: Rebooting. [ 27.548410][ T1] sd 1:0:0:0: [sda] Synchronizing SCSI cache [ 30.060554][ T225] usb 4-4: device not accepting address 2, error -108 [ 32.838110][ T1] ACPI: PM: Preparing to enter system sleep state S5 [ 32.851746][ T1] reboot: Restarting system [ 32.856127][ T1] reboot: machine restart Before bd738d859e71 ("drm/i915: Prevent modesets during driver init/ shutdown"), plymouthd can commit modeset during i915 shutdown process, this brings ten seconds delay. [ 36.519606][ T1] shutdown[1]: Rebooting. [ 36.763427][ T1] sd 1:0:0:0: [sda] Synchronizing SCSI cache [ 37.229513][ T7030] i915 0000:00:02.0: drm_WARN_ON(!intel_irqs_enabled(dev_priv)) ... [ 39.008748][ T4356] usb 4-4: device not accepting address 2, error -108 [ 43.116781][ T4356] usb usb4-port4: Cannot enable. Maybe the USB cable is bad? [ 47.196768][ T185] usb usb4-port4: Cannot enable. Maybe the USB cable is bad? [ 47.204511][ T185] usb 4-4: USB disconnect, device number 2 [ 48.438385][ T1] i915 0000:00:02.0: i915 raw-wakerefs=6 wakelocks=6 on cleanup Signed-off-by: Jiajia Liu <liujiajia@xxxxxxxxxx> --- block/disk-events.c | 1 + drivers/scsi/sd.c | 4 ++++ drivers/scsi/sd.h | 1 + include/linux/blkdev.h | 1 + 4 files changed, 7 insertions(+) diff --git a/block/disk-events.c b/block/disk-events.c index 2f697224386a..2c998fb360a5 100644 --- a/block/disk-events.c +++ b/block/disk-events.c @@ -94,6 +94,7 @@ void disk_block_events(struct gendisk *disk) mutex_unlock(&ev->block_mutex); } +EXPORT_SYMBOL_GPL(disk_block_events); static void __disk_unblock_events(struct gendisk *disk, bool check_now) { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 950d8c9fb884..86199991f2e3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -4064,6 +4064,7 @@ static int sd_remove(struct device *dev) device_del(&sdkp->disk_dev); del_gendisk(sdkp->disk); + sdkp->remove = 1; if (!sdkp->suspended) sd_shutdown(dev); @@ -4162,6 +4163,9 @@ static void sd_shutdown(struct device *dev) if (!sdkp) return; /* this can happen */ + if (sdkp->device->removable && !sdkp->remove) + disk_block_events(sdkp->disk); + if (pm_runtime_suspended(dev)) return; diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 36382eca941c..ff7004681267 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -156,6 +156,7 @@ struct scsi_disk { unsigned ignore_medium_access_errors : 1; unsigned rscs : 1; /* reduced stream control support */ unsigned use_atomic_write_boundary : 1; + unsigned remove : 1; }; #define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e39c45bc0a97..7739713c5202 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -879,6 +879,7 @@ int __register_blkdev(unsigned int major, const char *name, void unregister_blkdev(unsigned int major, const char *name); bool disk_check_media_change(struct gendisk *disk); +void disk_block_events(struct gendisk *disk); void set_capacity(struct gendisk *disk, sector_t size); #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED -- 2.25.1