From cee071276c75b232ba701080b621ea7dde177cdf Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Thu, 24 May 2018 16:18:41 +0530 Subject: [PATCH] Revert "scsi: sd: remove check_events callback" This reverts commit fe64842c81d6b2dc34321dde12530c92d5df556b. On auto platforms, it is observed that sdcard is not getting detected using usb card reader as check_events callback was removed. For usb card reader case, scsi check_events() callback is required which sends test unit ready command to check if underlying media state has changed. So instead of removing check_events() completely, simply return for embedded storage media like UFS. Change-Id: Iefd163db1a1098c01c2dbaf441f072b07b19caca Signed-off-by: Sayali Lokhande --- drivers/scsi/sd.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6e66e2ad9daf..367dde6a6e17 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1420,6 +1420,85 @@ static int media_not_present(struct scsi_disk *sdkp, return 0; } +/** + * sd_check_events - check media events + * @disk: kernel device descriptor + * @clearing: disk events currently being cleared + * + * Returns mask of DISK_EVENT_*. + * + * Note: this function is invoked from the block subsystem. + **/ +static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) +{ + struct scsi_disk *sdkp = scsi_disk(disk); + struct scsi_device *sdp = sdkp->device; + struct scsi_sense_hdr *sshdr = NULL; + int retval; + + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); + + /* Simply return for embedded storage media such as UFS */ + if (!sdp->removable) + goto out; + + /* + * If the device is offline, don't send any commands - just pretend as + * if the command failed. If the device ever comes back online, we + * can deal with it then. It is only because of unrecoverable errors + * that we would ever take a device offline in the first place. + */ + if (!scsi_device_online(sdp)) { + set_media_not_present(sdkp); + goto out; + } + + /* + * Using TEST_UNIT_READY enables differentiation between drive with + * no cartridge loaded - NOT READY, drive with changed cartridge - + * UNIT ATTENTION, or with same cartridge - GOOD STATUS. + * + * Drives that auto spin down. eg iomega jaz 1G, will be started + * by sd_spinup_disk() from sd_revalidate_disk(), which happens whenever + * sd_revalidate() is called. + */ + retval = -ENODEV; + + if (scsi_block_when_processing_errors(sdp)) { + sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); + retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, + sshdr); + } + + /* failed to execute TUR, assume media not present */ + if (host_byte(retval)) { + set_media_not_present(sdkp); + goto out; + } + + if (media_not_present(sdkp, sshdr)) + goto out; + + /* + * For removable scsi disk we have to recognise the presence + * of a disk in the drive. + */ + if (!sdkp->media_present) + sdp->changed = 1; + sdkp->media_present = 1; +out: + /* + * sdp->changed is set under the following conditions: + * + * Medium present state has changed in either direction. + * Device has indicated UNIT_ATTENTION. + */ + kfree(sshdr); + retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; + sdp->changed = 0; + return retval; +} + static int sd_sync_cache(struct scsi_disk *sdkp) { int retries, res; @@ -1612,6 +1691,7 @@ static const struct block_device_operations sd_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, #endif + .check_events = sd_check_events, .revalidate_disk = sd_revalidate_disk, .unlock_native_capacity = sd_unlock_native_capacity, .pr_ops = &sd_pr_ops,