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); |
