|
79 | 79 | */
|
80 | 80 | ATA_EH_PRERESET_TIMEOUT = 10000,
|
81 | 81 | ATA_EH_FASTDRAIN_INTERVAL = 3000,
|
| 82 | + |
| 83 | + ATA_EH_UA_TRIES = 5, |
82 | 84 | };
|
83 | 85 |
|
84 | 86 | /* The following table determines how we sequence resets. Each entry
|
@@ -1356,6 +1358,37 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
|
1356 | 1358 | return 0;
|
1357 | 1359 | }
|
1358 | 1360 |
|
| 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 | + |
1359 | 1392 | /**
|
1360 | 1393 | * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
|
1361 | 1394 | * @dev: device to perform REQUEST_SENSE to
|
@@ -2774,6 +2807,53 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
|
2774 | 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 | 2857 | static int ata_link_nr_enabled(struct ata_link *link)
|
2778 | 2858 | {
|
2779 | 2859 | struct ata_device *dev;
|
@@ -3066,6 +3146,20 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
3066 | 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 | 3163 | if (ehc->i.action & ATA_EH_LPM)
|
3070 | 3164 | ata_link_for_each_dev(dev, link)
|
3071 | 3165 | ata_dev_enable_pm(dev, ap->pm_policy);
|
|
0 commit comments