aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/sd.c87
-rw-r--r--drivers/scsi/sd.h1
2 files changed, 41 insertions, 47 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b179b0e39a3b..8d488a9fef00 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -991,50 +991,30 @@ out:
991 991
992static void set_media_not_present(struct scsi_disk *sdkp) 992static void set_media_not_present(struct scsi_disk *sdkp)
993{ 993{
994 if (sdkp->media_present)
995 sdkp->device->changed = 1;
996 sdkp->media_present = 0; 994 sdkp->media_present = 0;
997 sdkp->capacity = 0; 995 sdkp->capacity = 0;
998} 996 sdkp->device->changed = 1;
999
1000static int media_not_present(struct scsi_disk *sdkp,
1001 struct scsi_sense_hdr *sshdr)
1002{
1003 if (!scsi_sense_valid(sshdr))
1004 return 0;
1005
1006 /* not invoked for commands that could return deferred errors */
1007 switch (sshdr->sense_key) {
1008 case UNIT_ATTENTION:
1009 sdkp->device->changed = 1;
1010 /* fall through */
1011 case NOT_READY:
1012 /* medium not present */
1013 if (sshdr->asc == 0x3A) {
1014 set_media_not_present(sdkp);
1015 return 1;
1016 }
1017 }
1018 return 0;
1019} 997}
1020 998
1021/** 999/**
1022 * sd_check_events - check media events 1000 * sd_media_changed - check if our medium changed
1023 * @disk: kernel device descriptor 1001 * @disk: kernel device descriptor
1024 * @clearing: disk events currently being cleared
1025 * 1002 *
1026 * Returns mask of DISK_EVENT_*. 1003 * Returns 0 if not applicable or no change; 1 if change
1027 * 1004 *
1028 * Note: this function is invoked from the block subsystem. 1005 * Note: this function is invoked from the block subsystem.
1029 **/ 1006 **/
1030static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) 1007static int sd_media_changed(struct gendisk *disk)
1031{ 1008{
1032 struct scsi_disk *sdkp = scsi_disk(disk); 1009 struct scsi_disk *sdkp = scsi_disk(disk);
1033 struct scsi_device *sdp = sdkp->device; 1010 struct scsi_device *sdp = sdkp->device;
1034 struct scsi_sense_hdr *sshdr = NULL; 1011 struct scsi_sense_hdr *sshdr = NULL;
1035 int retval; 1012 int retval;
1036 1013
1037 SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); 1014 SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
1015
1016 if (!sdp->removable)
1017 return 0;
1038 1018
1039 /* 1019 /*
1040 * If the device is offline, don't send any commands - just pretend as 1020 * If the device is offline, don't send any commands - just pretend as
@@ -1044,6 +1024,7 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
1044 */ 1024 */
1045 if (!scsi_device_online(sdp)) { 1025 if (!scsi_device_online(sdp)) {
1046 set_media_not_present(sdkp); 1026 set_media_not_present(sdkp);
1027 retval = 1;
1047 goto out; 1028 goto out;
1048 } 1029 }
1049 1030
@@ -1064,30 +1045,26 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
1064 sshdr); 1045 sshdr);
1065 } 1046 }
1066 1047
1067 /* failed to execute TUR, assume media not present */ 1048 if (retval) {
1068 if (host_byte(retval)) {
1069 set_media_not_present(sdkp); 1049 set_media_not_present(sdkp);
1050 retval = 1;
1070 goto out; 1051 goto out;
1071 } 1052 }
1072 1053
1073 if (media_not_present(sdkp, sshdr))
1074 goto out;
1075
1076 /* 1054 /*
1077 * For removable scsi disk we have to recognise the presence 1055 * For removable scsi disk we have to recognise the presence
1078 * of a disk in the drive. 1056 * of a disk in the drive. This is kept in the struct scsi_disk
1057 * struct and tested at open ! Daniel Roche (dan@lectra.fr)
1079 */ 1058 */
1080 if (!sdkp->media_present)
1081 sdp->changed = 1;
1082 sdkp->media_present = 1; 1059 sdkp->media_present = 1;
1060
1061 retval = sdp->changed;
1062 sdp->changed = 0;
1083out: 1063out:
1084 /* for backward compatibility */ 1064 if (retval != sdkp->previous_state)
1085 if (sdp->changed)
1086 sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); 1065 sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
1066 sdkp->previous_state = retval;
1087 kfree(sshdr); 1067 kfree(sshdr);
1088
1089 retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
1090 sdp->changed = 0;
1091 return retval; 1068 return retval;
1092} 1069}
1093 1070
@@ -1180,7 +1157,7 @@ static const struct block_device_operations sd_fops = {
1180#ifdef CONFIG_COMPAT 1157#ifdef CONFIG_COMPAT
1181 .compat_ioctl = sd_compat_ioctl, 1158 .compat_ioctl = sd_compat_ioctl,
1182#endif 1159#endif
1183 .check_events = sd_check_events, 1160 .media_changed = sd_media_changed,
1184 .revalidate_disk = sd_revalidate_disk, 1161 .revalidate_disk = sd_revalidate_disk,
1185 .unlock_native_capacity = sd_unlock_native_capacity, 1162 .unlock_native_capacity = sd_unlock_native_capacity,
1186}; 1163};
@@ -1316,6 +1293,23 @@ static int sd_done(struct scsi_cmnd *SCpnt)
1316 return good_bytes; 1293 return good_bytes;
1317} 1294}
1318 1295
1296static int media_not_present(struct scsi_disk *sdkp,
1297 struct scsi_sense_hdr *sshdr)
1298{
1299
1300 if (!scsi_sense_valid(sshdr))
1301 return 0;
1302 /* not invoked for commands that could return deferred errors */
1303 if (sshdr->sense_key != NOT_READY &&
1304 sshdr->sense_key != UNIT_ATTENTION)
1305 return 0;
1306 if (sshdr->asc != 0x3A) /* medium not present */
1307 return 0;
1308
1309 set_media_not_present(sdkp);
1310 return 1;
1311}
1312
1319/* 1313/*
1320 * spinup disk - called only in sd_revalidate_disk() 1314 * spinup disk - called only in sd_revalidate_disk()
1321 */ 1315 */
@@ -1490,7 +1484,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
1490 */ 1484 */
1491 if (sdp->removable && 1485 if (sdp->removable &&
1492 sense_valid && sshdr->sense_key == NOT_READY) 1486 sense_valid && sshdr->sense_key == NOT_READY)
1493 set_media_not_present(sdkp); 1487 sdp->changed = 1;
1494 1488
1495 /* 1489 /*
1496 * We used to set media_present to 0 here to indicate no media 1490 * We used to set media_present to 0 here to indicate no media
@@ -2345,10 +2339,8 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2345 2339
2346 gd->driverfs_dev = &sdp->sdev_gendev; 2340 gd->driverfs_dev = &sdp->sdev_gendev;
2347 gd->flags = GENHD_FL_EXT_DEVT; 2341 gd->flags = GENHD_FL_EXT_DEVT;
2348 if (sdp->removable) { 2342 if (sdp->removable)
2349 gd->flags |= GENHD_FL_REMOVABLE; 2343 gd->flags |= GENHD_FL_REMOVABLE;
2350 gd->events |= DISK_EVENT_MEDIA_CHANGE;
2351 }
2352 2344
2353 add_disk(gd); 2345 add_disk(gd);
2354 sd_dif_config_host(sdkp); 2346 sd_dif_config_host(sdkp);
@@ -2430,6 +2422,7 @@ static int sd_probe(struct device *dev)
2430 sdkp->disk = gd; 2422 sdkp->disk = gd;
2431 sdkp->index = index; 2423 sdkp->index = index;
2432 atomic_set(&sdkp->openers, 0); 2424 atomic_set(&sdkp->openers, 0);
2425 sdkp->previous_state = 1;
2433 2426
2434 if (!sdp->request_queue->rq_timeout) { 2427 if (!sdp->request_queue->rq_timeout) {
2435 if (sdp->type != TYPE_MOD) 2428 if (sdp->type != TYPE_MOD)
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index c9d8f6ca49e2..55488faf0815 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -55,6 +55,7 @@ struct scsi_disk {
55 u8 media_present; 55 u8 media_present;
56 u8 write_prot; 56 u8 write_prot;
57 u8 protection_type;/* Data Integrity Field */ 57 u8 protection_type;/* Data Integrity Field */
58 unsigned previous_state : 1;
58 unsigned ATO : 1; /* state of disk ATO bit */ 59 unsigned ATO : 1; /* state of disk ATO bit */
59 unsigned WCE : 1; /* state of disk WCE bit */ 60 unsigned WCE : 1; /* state of disk WCE bit */
60 unsigned RCD : 1; /* state of disk RCD bit, unused */ 61 unsigned RCD : 1; /* state of disk RCD bit, unused */