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