diff options
-rw-r--r-- | drivers/scsi/scsi_error.c | 26 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 26 | ||||
-rw-r--r-- | include/scsi/scsi_driver.h | 2 |
3 files changed, 30 insertions, 24 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index e8bee9f0ad0f..67c001457cb8 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -941,12 +941,6 @@ retry: | |||
941 | 941 | ||
942 | scsi_eh_restore_cmnd(scmd, &ses); | 942 | scsi_eh_restore_cmnd(scmd, &ses); |
943 | 943 | ||
944 | if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { | ||
945 | struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); | ||
946 | if (sdrv->eh_action) | ||
947 | rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn); | ||
948 | } | ||
949 | |||
950 | return rtn; | 944 | return rtn; |
951 | } | 945 | } |
952 | 946 | ||
@@ -964,6 +958,16 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) | |||
964 | return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0); | 958 | return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0); |
965 | } | 959 | } |
966 | 960 | ||
961 | static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn) | ||
962 | { | ||
963 | if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { | ||
964 | struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); | ||
965 | if (sdrv->eh_action) | ||
966 | rtn = sdrv->eh_action(scmd, rtn); | ||
967 | } | ||
968 | return rtn; | ||
969 | } | ||
970 | |||
967 | /** | 971 | /** |
968 | * scsi_eh_finish_cmd - Handle a cmd that eh is finished with. | 972 | * scsi_eh_finish_cmd - Handle a cmd that eh is finished with. |
969 | * @scmd: Original SCSI cmd that eh has finished. | 973 | * @scmd: Original SCSI cmd that eh has finished. |
@@ -1142,7 +1146,9 @@ static int scsi_eh_test_devices(struct list_head *cmd_list, | |||
1142 | 1146 | ||
1143 | list_for_each_entry_safe(scmd, next, cmd_list, eh_entry) | 1147 | list_for_each_entry_safe(scmd, next, cmd_list, eh_entry) |
1144 | if (scmd->device == sdev) { | 1148 | if (scmd->device == sdev) { |
1145 | if (finish_cmds) | 1149 | if (finish_cmds && |
1150 | (try_stu || | ||
1151 | scsi_eh_action(scmd, SUCCESS) == SUCCESS)) | ||
1146 | scsi_eh_finish_cmd(scmd, done_q); | 1152 | scsi_eh_finish_cmd(scmd, done_q); |
1147 | else | 1153 | else |
1148 | list_move_tail(&scmd->eh_entry, work_q); | 1154 | list_move_tail(&scmd->eh_entry, work_q); |
@@ -1283,7 +1289,8 @@ static int scsi_eh_stu(struct Scsi_Host *shost, | |||
1283 | !scsi_eh_tur(stu_scmd)) { | 1289 | !scsi_eh_tur(stu_scmd)) { |
1284 | list_for_each_entry_safe(scmd, next, | 1290 | list_for_each_entry_safe(scmd, next, |
1285 | work_q, eh_entry) { | 1291 | work_q, eh_entry) { |
1286 | if (scmd->device == sdev) | 1292 | if (scmd->device == sdev && |
1293 | scsi_eh_action(scmd, SUCCESS) == SUCCESS) | ||
1287 | scsi_eh_finish_cmd(scmd, done_q); | 1294 | scsi_eh_finish_cmd(scmd, done_q); |
1288 | } | 1295 | } |
1289 | } | 1296 | } |
@@ -1350,7 +1357,8 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, | |||
1350 | !scsi_eh_tur(bdr_scmd)) { | 1357 | !scsi_eh_tur(bdr_scmd)) { |
1351 | list_for_each_entry_safe(scmd, next, | 1358 | list_for_each_entry_safe(scmd, next, |
1352 | work_q, eh_entry) { | 1359 | work_q, eh_entry) { |
1353 | if (scmd->device == sdev) | 1360 | if (scmd->device == sdev && |
1361 | scsi_eh_action(scmd, rtn) != FAILED) | ||
1354 | scsi_eh_finish_cmd(scmd, | 1362 | scsi_eh_finish_cmd(scmd, |
1355 | done_q); | 1363 | done_q); |
1356 | } | 1364 | } |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 69725f7c32c1..35a785609364 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -110,7 +110,7 @@ static int sd_suspend_runtime(struct device *); | |||
110 | static int sd_resume(struct device *); | 110 | static int sd_resume(struct device *); |
111 | static void sd_rescan(struct device *); | 111 | static void sd_rescan(struct device *); |
112 | static int sd_done(struct scsi_cmnd *); | 112 | static int sd_done(struct scsi_cmnd *); |
113 | static int sd_eh_action(struct scsi_cmnd *, unsigned char *, int, int); | 113 | static int sd_eh_action(struct scsi_cmnd *, int); |
114 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); | 114 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); |
115 | static void scsi_disk_release(struct device *cdev); | 115 | static void scsi_disk_release(struct device *cdev); |
116 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | 116 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); |
@@ -1551,23 +1551,23 @@ static const struct block_device_operations sd_fops = { | |||
1551 | /** | 1551 | /** |
1552 | * sd_eh_action - error handling callback | 1552 | * sd_eh_action - error handling callback |
1553 | * @scmd: sd-issued command that has failed | 1553 | * @scmd: sd-issued command that has failed |
1554 | * @eh_cmnd: The command that was sent during error handling | ||
1555 | * @eh_cmnd_len: Length of eh_cmnd in bytes | ||
1556 | * @eh_disp: The recovery disposition suggested by the midlayer | 1554 | * @eh_disp: The recovery disposition suggested by the midlayer |
1557 | * | 1555 | * |
1558 | * This function is called by the SCSI midlayer upon completion of | 1556 | * This function is called by the SCSI midlayer upon completion of an |
1559 | * an error handling command (TEST UNIT READY, START STOP UNIT, | 1557 | * error test command (currently TEST UNIT READY). The result of sending |
1560 | * etc.) The command sent to the device by the error handler is | 1558 | * the eh command is passed in eh_disp. We're looking for devices that |
1561 | * stored in eh_cmnd. The result of sending the eh command is | 1559 | * fail medium access commands but are OK with non access commands like |
1562 | * passed in eh_disp. | 1560 | * test unit ready (so wrongly see the device as having a successful |
1561 | * recovery) | ||
1563 | **/ | 1562 | **/ |
1564 | static int sd_eh_action(struct scsi_cmnd *scmd, unsigned char *eh_cmnd, | 1563 | static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp) |
1565 | int eh_cmnd_len, int eh_disp) | ||
1566 | { | 1564 | { |
1567 | struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); | 1565 | struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); |
1568 | 1566 | ||
1569 | if (!scsi_device_online(scmd->device) || | 1567 | if (!scsi_device_online(scmd->device) || |
1570 | !scsi_medium_access_command(scmd)) | 1568 | !scsi_medium_access_command(scmd) || |
1569 | host_byte(scmd->result) != DID_TIME_OUT || | ||
1570 | eh_disp != SUCCESS) | ||
1571 | return eh_disp; | 1571 | return eh_disp; |
1572 | 1572 | ||
1573 | /* | 1573 | /* |
@@ -1577,9 +1577,7 @@ static int sd_eh_action(struct scsi_cmnd *scmd, unsigned char *eh_cmnd, | |||
1577 | * process of recovering or has it suffered an internal failure | 1577 | * process of recovering or has it suffered an internal failure |
1578 | * that prevents access to the storage medium. | 1578 | * that prevents access to the storage medium. |
1579 | */ | 1579 | */ |
1580 | if (host_byte(scmd->result) == DID_TIME_OUT && eh_disp == SUCCESS && | 1580 | sdkp->medium_access_timed_out++; |
1581 | eh_cmnd_len && eh_cmnd[0] == TEST_UNIT_READY) | ||
1582 | sdkp->medium_access_timed_out++; | ||
1583 | 1581 | ||
1584 | /* | 1582 | /* |
1585 | * If the device keeps failing read/write commands but TEST UNIT | 1583 | * If the device keeps failing read/write commands but TEST UNIT |
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index d443aa06a722..20fdfc2526ad 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h | |||
@@ -16,7 +16,7 @@ struct scsi_driver { | |||
16 | 16 | ||
17 | void (*rescan)(struct device *); | 17 | void (*rescan)(struct device *); |
18 | int (*done)(struct scsi_cmnd *); | 18 | int (*done)(struct scsi_cmnd *); |
19 | int (*eh_action)(struct scsi_cmnd *, unsigned char *, int, int); | 19 | int (*eh_action)(struct scsi_cmnd *, int); |
20 | }; | 20 | }; |
21 | #define to_scsi_driver(drv) \ | 21 | #define to_scsi_driver(drv) \ |
22 | container_of((drv), struct scsi_driver, gendrv) | 22 | container_of((drv), struct scsi_driver, gendrv) |