diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-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 bba2ae5df1c2..0ea97c942ced 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -110,6 +110,13 @@ static const unsigned long ata_eh_identify_timeouts[] = { | |||
110 | ULONG_MAX, | 110 | ULONG_MAX, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static const unsigned long ata_eh_flush_timeouts[] = { | ||
114 | 15000, /* be generous with flush */ | ||
115 | 15000, /* ditto */ | ||
116 | 30000, /* and even more generous */ | ||
117 | ULONG_MAX, | ||
118 | }; | ||
119 | |||
113 | static const unsigned long ata_eh_other_timeouts[] = { | 120 | static const unsigned long ata_eh_other_timeouts[] = { |
114 | 5000, /* same rationale as identify timeout */ | 121 | 5000, /* same rationale as identify timeout */ |
115 | 10000, /* ditto */ | 122 | 10000, /* ditto */ |
@@ -147,6 +154,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = { | |||
147 | .timeouts = ata_eh_other_timeouts, }, | 154 | .timeouts = ata_eh_other_timeouts, }, |
148 | { .commands = CMDS(ATA_CMD_INIT_DEV_PARAMS), | 155 | { .commands = CMDS(ATA_CMD_INIT_DEV_PARAMS), |
149 | .timeouts = ata_eh_other_timeouts, }, | 156 | .timeouts = ata_eh_other_timeouts, }, |
157 | { .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT), | ||
158 | .timeouts = ata_eh_flush_timeouts }, | ||
150 | }; | 159 | }; |
151 | #undef CMDS | 160 | #undef CMDS |
152 | 161 | ||
@@ -3112,6 +3121,82 @@ static int atapi_eh_clear_ua(struct ata_device *dev) | |||
3112 | return 0; | 3121 | return 0; |
3113 | } | 3122 | } |
3114 | 3123 | ||
3124 | /** | ||
3125 | * ata_eh_maybe_retry_flush - Retry FLUSH if necessary | ||
3126 | * @dev: ATA device which may need FLUSH retry | ||
3127 | * | ||
3128 | * If @dev failed FLUSH, it needs to be reported upper layer | ||
3129 | * immediately as it means that @dev failed to remap and already | ||
3130 | * lost at least a sector and further FLUSH retrials won't make | ||
3131 | * any difference to the lost sector. However, if FLUSH failed | ||
3132 | * for other reasons, for example transmission error, FLUSH needs | ||
3133 | * to be retried. | ||
3134 | * | ||
3135 | * This function determines whether FLUSH failure retry is | ||
3136 | * necessary and performs it if so. | ||
3137 | * | ||
3138 | * RETURNS: | ||
3139 | * 0 if EH can continue, -errno if EH needs to be repeated. | ||
3140 | */ | ||
3141 | static int ata_eh_maybe_retry_flush(struct ata_device *dev) | ||
3142 | { | ||
3143 | struct ata_link *link = dev->link; | ||
3144 | struct ata_port *ap = link->ap; | ||
3145 | struct ata_queued_cmd *qc; | ||
3146 | struct ata_taskfile tf; | ||
3147 | unsigned int err_mask; | ||
3148 | int rc = 0; | ||
3149 | |||
3150 | /* did flush fail for this device? */ | ||
3151 | if (!ata_tag_valid(link->active_tag)) | ||
3152 | return 0; | ||
3153 | |||
3154 | qc = __ata_qc_from_tag(ap, link->active_tag); | ||
3155 | if (qc->dev != dev || (qc->tf.command != ATA_CMD_FLUSH_EXT && | ||
3156 | qc->tf.command != ATA_CMD_FLUSH)) | ||
3157 | return 0; | ||
3158 | |||
3159 | /* if the device failed it, it should be reported to upper layers */ | ||
3160 | if (qc->err_mask & AC_ERR_DEV) | ||
3161 | return 0; | ||
3162 | |||
3163 | /* flush failed for some other reason, give it another shot */ | ||
3164 | ata_tf_init(dev, &tf); | ||
3165 | |||
3166 | tf.command = qc->tf.command; | ||
3167 | tf.flags |= ATA_TFLAG_DEVICE; | ||
3168 | tf.protocol = ATA_PROT_NODATA; | ||
3169 | |||
3170 | ata_dev_printk(dev, KERN_WARNING, "retrying FLUSH 0x%x Emask 0x%x\n", | ||
3171 | tf.command, qc->err_mask); | ||
3172 | |||
3173 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); | ||
3174 | if (!err_mask) { | ||
3175 | /* | ||
3176 | * FLUSH is complete but there's no way to | ||
3177 | * successfully complete a failed command from EH. | ||
3178 | * Making sure retry is allowed at least once and | ||
3179 | * retrying it should do the trick - whatever was in | ||
3180 | * the cache is already on the platter and this won't | ||
3181 | * cause infinite loop. | ||
3182 | */ | ||
3183 | qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1); | ||
3184 | } else { | ||
3185 | ata_dev_printk(dev, KERN_WARNING, "FLUSH failed Emask 0x%x\n", | ||
3186 | err_mask); | ||
3187 | rc = -EIO; | ||
3188 | |||
3189 | /* if device failed it, report it to upper layers */ | ||
3190 | if (err_mask & AC_ERR_DEV) { | ||
3191 | qc->err_mask |= AC_ERR_DEV; | ||
3192 | qc->result_tf = tf; | ||
3193 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) | ||
3194 | rc = 0; | ||
3195 | } | ||
3196 | } | ||
3197 | return rc; | ||
3198 | } | ||
3199 | |||
3115 | static int ata_link_nr_enabled(struct ata_link *link) | 3200 | static int ata_link_nr_enabled(struct ata_link *link) |
3116 | { | 3201 | { |
3117 | struct ata_device *dev; | 3202 | struct ata_device *dev; |
@@ -3455,6 +3540,15 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
3455 | } | 3540 | } |
3456 | } | 3541 | } |
3457 | 3542 | ||
3543 | /* retry flush if necessary */ | ||
3544 | ata_for_each_dev(dev, link, ALL) { | ||
3545 | if (dev->class != ATA_DEV_ATA) | ||
3546 | continue; | ||
3547 | rc = ata_eh_maybe_retry_flush(dev); | ||
3548 | if (rc) | ||
3549 | goto dev_fail; | ||
3550 | } | ||
3551 | |||
3458 | /* configure link power saving */ | 3552 | /* configure link power saving */ |
3459 | if (ehc->i.action & ATA_EH_LPM) | 3553 | if (ehc->i.action & ATA_EH_LPM) |
3460 | ata_for_each_dev(dev, link, ALL) | 3554 | ata_for_each_dev(dev, link, ALL) |