diff options
-rw-r--r-- | drivers/ata/libata-eh.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 33ac5ea4f531..f2dd99122bd6 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -79,6 +79,8 @@ enum { | |||
79 | */ | 79 | */ |
80 | ATA_EH_PRERESET_TIMEOUT = 10000, | 80 | ATA_EH_PRERESET_TIMEOUT = 10000, |
81 | ATA_EH_FASTDRAIN_INTERVAL = 3000, | 81 | ATA_EH_FASTDRAIN_INTERVAL = 3000, |
82 | |||
83 | ATA_EH_UA_TRIES = 5, | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | /* The following table determines how we sequence resets. Each entry | 86 | /* The following table determines how we sequence resets. Each entry |
@@ -1357,6 +1359,37 @@ static int ata_eh_read_log_10h(struct ata_device *dev, | |||
1357 | } | 1359 | } |
1358 | 1360 | ||
1359 | /** | 1361 | /** |
1362 | * atapi_eh_tur - perform ATAPI TEST_UNIT_READY | ||
1363 | * @dev: target ATAPI device | ||
1364 | * @r_sense_key: out parameter for sense_key | ||
1365 | * | ||
1366 | * Perform ATAPI TEST_UNIT_READY. | ||
1367 | * | ||
1368 | * LOCKING: | ||
1369 | * EH context (may sleep). | ||
1370 | * | ||
1371 | * RETURNS: | ||
1372 | * 0 on success, AC_ERR_* mask on failure. | ||
1373 | */ | ||
1374 | static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) | ||
1375 | { | ||
1376 | u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 }; | ||
1377 | struct ata_taskfile tf; | ||
1378 | unsigned int err_mask; | ||
1379 | |||
1380 | ata_tf_init(dev, &tf); | ||
1381 | |||
1382 | tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
1383 | tf.command = ATA_CMD_PACKET; | ||
1384 | tf.protocol = ATAPI_PROT_NODATA; | ||
1385 | |||
1386 | err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); | ||
1387 | if (err_mask == AC_ERR_DEV) | ||
1388 | *r_sense_key = tf.feature >> 4; | ||
1389 | return err_mask; | ||
1390 | } | ||
1391 | |||
1392 | /** | ||
1360 | * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE | 1393 | * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE |
1361 | * @dev: device to perform REQUEST_SENSE to | 1394 | * @dev: device to perform REQUEST_SENSE to |
1362 | * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) | 1395 | * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) |
@@ -2774,6 +2807,53 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) | |||
2774 | return rc; | 2807 | return rc; |
2775 | } | 2808 | } |
2776 | 2809 | ||
2810 | /** | ||
2811 | * atapi_eh_clear_ua - Clear ATAPI UNIT ATTENTION after reset | ||
2812 | * @dev: ATAPI device to clear UA for | ||
2813 | * | ||
2814 | * Resets and other operations can make an ATAPI device raise | ||
2815 | * UNIT ATTENTION which causes the next operation to fail. This | ||
2816 | * function clears UA. | ||
2817 | * | ||
2818 | * LOCKING: | ||
2819 | * EH context (may sleep). | ||
2820 | * | ||
2821 | * RETURNS: | ||
2822 | * 0 on success, -errno on failure. | ||
2823 | */ | ||
2824 | static int atapi_eh_clear_ua(struct ata_device *dev) | ||
2825 | { | ||
2826 | int i; | ||
2827 | |||
2828 | for (i = 0; i < ATA_EH_UA_TRIES; i++) { | ||
2829 | u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; | ||
2830 | u8 sense_key = 0; | ||
2831 | unsigned int err_mask; | ||
2832 | |||
2833 | err_mask = atapi_eh_tur(dev, &sense_key); | ||
2834 | if (err_mask != 0 && err_mask != AC_ERR_DEV) { | ||
2835 | ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY " | ||
2836 | "failed (err_mask=0x%x)\n", err_mask); | ||
2837 | return -EIO; | ||
2838 | } | ||
2839 | |||
2840 | if (!err_mask || sense_key != UNIT_ATTENTION) | ||
2841 | return 0; | ||
2842 | |||
2843 | err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key); | ||
2844 | if (err_mask) { | ||
2845 | ata_dev_printk(dev, KERN_WARNING, "failed to clear " | ||
2846 | "UNIT ATTENTION (err_mask=0x%x)\n", err_mask); | ||
2847 | return -EIO; | ||
2848 | } | ||
2849 | } | ||
2850 | |||
2851 | ata_dev_printk(dev, KERN_WARNING, | ||
2852 | "UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES); | ||
2853 | |||
2854 | return 0; | ||
2855 | } | ||
2856 | |||
2777 | static int ata_link_nr_enabled(struct ata_link *link) | 2857 | static int ata_link_nr_enabled(struct ata_link *link) |
2778 | { | 2858 | { |
2779 | struct ata_device *dev; | 2859 | struct ata_device *dev; |
@@ -3066,6 +3146,20 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
3066 | ehc->i.flags &= ~ATA_EHI_SETMODE; | 3146 | ehc->i.flags &= ~ATA_EHI_SETMODE; |
3067 | } | 3147 | } |
3068 | 3148 | ||
3149 | /* If reset has been issued, clear UA to avoid | ||
3150 | * disrupting the current users of the device. | ||
3151 | */ | ||
3152 | if (ehc->i.flags & ATA_EHI_DID_RESET) { | ||
3153 | ata_link_for_each_dev(dev, link) { | ||
3154 | if (dev->class != ATA_DEV_ATAPI) | ||
3155 | continue; | ||
3156 | rc = atapi_eh_clear_ua(dev); | ||
3157 | if (rc) | ||
3158 | goto dev_fail; | ||
3159 | } | ||
3160 | } | ||
3161 | |||
3162 | /* configure link power saving */ | ||
3069 | if (ehc->i.action & ATA_EH_LPM) | 3163 | if (ehc->i.action & ATA_EH_LPM) |
3070 | ata_link_for_each_dev(dev, link) | 3164 | ata_link_for_each_dev(dev, link) |
3071 | ata_dev_enable_pm(dev, ap->pm_policy); | 3165 | ata_dev_enable_pm(dev, ap->pm_policy); |