diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 15:55:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 15:55:29 -0400 |
commit | 424a6f6ef990b7e9f56f6627bfc6c46b493faeb4 (patch) | |
tree | 0028356ed8003495fbbe1f716f359e3c8ebc35b6 /drivers/scsi/sd.c | |
parent | 1ab142d499294b844ecc81e8004db4ce029b0b61 (diff) | |
parent | cd8df932d894f3128c884e3ae1b2b484540513db (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
SCSI updates from James Bottomley:
"The update includes the usual assortment of driver updates (lpfc,
qla2xxx, qla4xxx, bfa, bnx2fc, bnx2i, isci, fcoe, hpsa) plus a huge
amount of infrastructure work in the SAS library and transport class
as well as an iSCSI update. There's also a new SCSI based virtio
driver."
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (177 commits)
[SCSI] qla4xxx: Update driver version to 5.02.00-k15
[SCSI] qla4xxx: trivial cleanup
[SCSI] qla4xxx: Fix sparse warning
[SCSI] qla4xxx: Add support for multiple session per host.
[SCSI] qla4xxx: Export CHAP index as sysfs attribute
[SCSI] scsi_transport: Export CHAP index as sysfs attribute
[SCSI] qla4xxx: Add support to display CHAP list and delete CHAP entry
[SCSI] iscsi_transport: Add support to display CHAP list and delete CHAP entry
[SCSI] pm8001: fix endian issue with code optimization.
[SCSI] pm8001: Fix possible racing condition.
[SCSI] pm8001: Fix bogus interrupt state flag issue.
[SCSI] ipr: update PCI ID definitions for new adapters
[SCSI] qla2xxx: handle default case in qla2x00_request_firmware()
[SCSI] isci: improvements in driver unloading routine
[SCSI] isci: improve phy event warnings
[SCSI] isci: debug, provide state-enum-to-string conversions
[SCSI] scsi_transport_sas: 'enable' phys on reset
[SCSI] libsas: don't recover end devices attached to disabled phys
[SCSI] libsas: fixup target_port_protocols for expanders that don't report sata
[SCSI] libsas: set attached device type and target protocols for local phys
...
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d173b90b25e9..09e3df42a402 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -107,6 +107,7 @@ static int sd_suspend(struct device *, pm_message_t state); | |||
107 | static int sd_resume(struct device *); | 107 | static int sd_resume(struct device *); |
108 | static void sd_rescan(struct device *); | 108 | static void sd_rescan(struct device *); |
109 | static int sd_done(struct scsi_cmnd *); | 109 | static int sd_done(struct scsi_cmnd *); |
110 | static int sd_eh_action(struct scsi_cmnd *, unsigned char *, int, int); | ||
110 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); | 111 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); |
111 | static void scsi_disk_release(struct device *cdev); | 112 | static void scsi_disk_release(struct device *cdev); |
112 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | 113 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); |
@@ -346,6 +347,31 @@ sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr, | |||
346 | return count; | 347 | return count; |
347 | } | 348 | } |
348 | 349 | ||
350 | static ssize_t | ||
351 | sd_show_max_medium_access_timeouts(struct device *dev, | ||
352 | struct device_attribute *attr, char *buf) | ||
353 | { | ||
354 | struct scsi_disk *sdkp = to_scsi_disk(dev); | ||
355 | |||
356 | return snprintf(buf, 20, "%u\n", sdkp->max_medium_access_timeouts); | ||
357 | } | ||
358 | |||
359 | static ssize_t | ||
360 | sd_store_max_medium_access_timeouts(struct device *dev, | ||
361 | struct device_attribute *attr, | ||
362 | const char *buf, size_t count) | ||
363 | { | ||
364 | struct scsi_disk *sdkp = to_scsi_disk(dev); | ||
365 | int err; | ||
366 | |||
367 | if (!capable(CAP_SYS_ADMIN)) | ||
368 | return -EACCES; | ||
369 | |||
370 | err = kstrtouint(buf, 10, &sdkp->max_medium_access_timeouts); | ||
371 | |||
372 | return err ? err : count; | ||
373 | } | ||
374 | |||
349 | static struct device_attribute sd_disk_attrs[] = { | 375 | static struct device_attribute sd_disk_attrs[] = { |
350 | __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, | 376 | __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, |
351 | sd_store_cache_type), | 377 | sd_store_cache_type), |
@@ -360,6 +386,9 @@ static struct device_attribute sd_disk_attrs[] = { | |||
360 | __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), | 386 | __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), |
361 | __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, | 387 | __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, |
362 | sd_store_provisioning_mode), | 388 | sd_store_provisioning_mode), |
389 | __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR, | ||
390 | sd_show_max_medium_access_timeouts, | ||
391 | sd_store_max_medium_access_timeouts), | ||
363 | __ATTR_NULL, | 392 | __ATTR_NULL, |
364 | }; | 393 | }; |
365 | 394 | ||
@@ -382,6 +411,7 @@ static struct scsi_driver sd_template = { | |||
382 | }, | 411 | }, |
383 | .rescan = sd_rescan, | 412 | .rescan = sd_rescan, |
384 | .done = sd_done, | 413 | .done = sd_done, |
414 | .eh_action = sd_eh_action, | ||
385 | }; | 415 | }; |
386 | 416 | ||
387 | /* | 417 | /* |
@@ -497,6 +527,8 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | |||
497 | max(sdkp->physical_block_size, | 527 | max(sdkp->physical_block_size, |
498 | sdkp->unmap_granularity * logical_block_size); | 528 | sdkp->unmap_granularity * logical_block_size); |
499 | 529 | ||
530 | sdkp->provisioning_mode = mode; | ||
531 | |||
500 | switch (mode) { | 532 | switch (mode) { |
501 | 533 | ||
502 | case SD_LBP_DISABLE: | 534 | case SD_LBP_DISABLE: |
@@ -524,8 +556,6 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | |||
524 | 556 | ||
525 | q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9); | 557 | q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9); |
526 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | 558 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); |
527 | |||
528 | sdkp->provisioning_mode = mode; | ||
529 | } | 559 | } |
530 | 560 | ||
531 | /** | 561 | /** |
@@ -1313,6 +1343,55 @@ static const struct block_device_operations sd_fops = { | |||
1313 | .unlock_native_capacity = sd_unlock_native_capacity, | 1343 | .unlock_native_capacity = sd_unlock_native_capacity, |
1314 | }; | 1344 | }; |
1315 | 1345 | ||
1346 | /** | ||
1347 | * sd_eh_action - error handling callback | ||
1348 | * @scmd: sd-issued command that has failed | ||
1349 | * @eh_cmnd: The command that was sent during error handling | ||
1350 | * @eh_cmnd_len: Length of eh_cmnd in bytes | ||
1351 | * @eh_disp: The recovery disposition suggested by the midlayer | ||
1352 | * | ||
1353 | * This function is called by the SCSI midlayer upon completion of | ||
1354 | * an error handling command (TEST UNIT READY, START STOP UNIT, | ||
1355 | * etc.) The command sent to the device by the error handler is | ||
1356 | * stored in eh_cmnd. The result of sending the eh command is | ||
1357 | * passed in eh_disp. | ||
1358 | **/ | ||
1359 | static int sd_eh_action(struct scsi_cmnd *scmd, unsigned char *eh_cmnd, | ||
1360 | int eh_cmnd_len, int eh_disp) | ||
1361 | { | ||
1362 | struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); | ||
1363 | |||
1364 | if (!scsi_device_online(scmd->device) || | ||
1365 | !scsi_medium_access_command(scmd)) | ||
1366 | return eh_disp; | ||
1367 | |||
1368 | /* | ||
1369 | * The device has timed out executing a medium access command. | ||
1370 | * However, the TEST UNIT READY command sent during error | ||
1371 | * handling completed successfully. Either the device is in the | ||
1372 | * process of recovering or has it suffered an internal failure | ||
1373 | * that prevents access to the storage medium. | ||
1374 | */ | ||
1375 | if (host_byte(scmd->result) == DID_TIME_OUT && eh_disp == SUCCESS && | ||
1376 | eh_cmnd_len && eh_cmnd[0] == TEST_UNIT_READY) | ||
1377 | sdkp->medium_access_timed_out++; | ||
1378 | |||
1379 | /* | ||
1380 | * If the device keeps failing read/write commands but TEST UNIT | ||
1381 | * READY always completes successfully we assume that medium | ||
1382 | * access is no longer possible and take the device offline. | ||
1383 | */ | ||
1384 | if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) { | ||
1385 | scmd_printk(KERN_ERR, scmd, | ||
1386 | "Medium access timeout failure. Offlining disk!\n"); | ||
1387 | scsi_device_set_state(scmd->device, SDEV_OFFLINE); | ||
1388 | |||
1389 | return FAILED; | ||
1390 | } | ||
1391 | |||
1392 | return eh_disp; | ||
1393 | } | ||
1394 | |||
1316 | static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) | 1395 | static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) |
1317 | { | 1396 | { |
1318 | u64 start_lba = blk_rq_pos(scmd->request); | 1397 | u64 start_lba = blk_rq_pos(scmd->request); |
@@ -1402,6 +1481,8 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |||
1402 | (!sense_valid || sense_deferred)) | 1481 | (!sense_valid || sense_deferred)) |
1403 | goto out; | 1482 | goto out; |
1404 | 1483 | ||
1484 | sdkp->medium_access_timed_out = 0; | ||
1485 | |||
1405 | switch (sshdr.sense_key) { | 1486 | switch (sshdr.sense_key) { |
1406 | case HARDWARE_ERROR: | 1487 | case HARDWARE_ERROR: |
1407 | case MEDIUM_ERROR: | 1488 | case MEDIUM_ERROR: |
@@ -2523,6 +2604,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
2523 | sdkp->RCD = 0; | 2604 | sdkp->RCD = 0; |
2524 | sdkp->ATO = 0; | 2605 | sdkp->ATO = 0; |
2525 | sdkp->first_scan = 1; | 2606 | sdkp->first_scan = 1; |
2607 | sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS; | ||
2526 | 2608 | ||
2527 | sd_revalidate_disk(gd); | 2609 | sd_revalidate_disk(gd); |
2528 | 2610 | ||