aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-io.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-24 18:22:47 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-24 18:22:47 -0400
commit327fa1c29466b8fe471a91fc11e9c6171163c81a (patch)
tree9dbbf65c886d5ec68299d563da0cd7df8b97c324 /drivers/ide/ide-io.c
parent122f06f8bce406169d61242a3eb667027e27cca7 (diff)
ide: move error handling code to ide-eh.c (v2)
Do some CodingStyle fixups in <linux/ide.h> while at it. v2: Add missing <linux/delay.h> include (reported by Stephen Rothwell). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r--drivers/ide/ide-io.c129
1 files changed, 1 insertions, 128 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 74d1a3e68252..2e92497b58aa 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
196} 196}
197EXPORT_SYMBOL(ide_end_drive_cmd); 197EXPORT_SYMBOL(ide_end_drive_cmd);
198 198
199static void ide_kill_rq(ide_drive_t *drive, struct request *rq) 199void ide_kill_rq(ide_drive_t *drive, struct request *rq)
200{ 200{
201 if (rq->rq_disk) { 201 if (rq->rq_disk) {
202 struct ide_driver *drv; 202 struct ide_driver *drv;
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
207 ide_end_request(drive, 0, 0); 207 ide_end_request(drive, 0, 0);
208} 208}
209 209
210static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
211{
212 ide_hwif_t *hwif = drive->hwif;
213
214 if ((stat & ATA_BUSY) ||
215 ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
216 /* other bits are useless when BUSY */
217 rq->errors |= ERROR_RESET;
218 } else if (stat & ATA_ERR) {
219 /* err has different meaning on cdrom and tape */
220 if (err == ATA_ABORTED) {
221 if ((drive->dev_flags & IDE_DFLAG_LBA) &&
222 /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
223 hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
224 return ide_stopped;
225 } else if ((err & BAD_CRC) == BAD_CRC) {
226 /* UDMA crc error, just retry the operation */
227 drive->crc_count++;
228 } else if (err & (ATA_BBK | ATA_UNC)) {
229 /* retries won't help these */
230 rq->errors = ERROR_MAX;
231 } else if (err & ATA_TRK0NF) {
232 /* help it find track zero */
233 rq->errors |= ERROR_RECAL;
234 }
235 }
236
237 if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
238 (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
239 int nsect = drive->mult_count ? drive->mult_count : 1;
240
241 ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
242 }
243
244 if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
245 ide_kill_rq(drive, rq);
246 return ide_stopped;
247 }
248
249 if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
250 rq->errors |= ERROR_RESET;
251
252 if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
253 ++rq->errors;
254 return ide_do_reset(drive);
255 }
256
257 if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
258 drive->special.b.recalibrate = 1;
259
260 ++rq->errors;
261
262 return ide_stopped;
263}
264
265static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
266{
267 ide_hwif_t *hwif = drive->hwif;
268
269 if ((stat & ATA_BUSY) ||
270 ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
271 /* other bits are useless when BUSY */
272 rq->errors |= ERROR_RESET;
273 } else {
274 /* add decoding error stuff */
275 }
276
277 if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
278 /* force an abort */
279 hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
280
281 if (rq->errors >= ERROR_MAX) {
282 ide_kill_rq(drive, rq);
283 } else {
284 if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
285 ++rq->errors;
286 return ide_do_reset(drive);
287 }
288 ++rq->errors;
289 }
290
291 return ide_stopped;
292}
293
294static ide_startstop_t
295__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
296{
297 if (drive->media == ide_disk)
298 return ide_ata_error(drive, rq, stat, err);
299 return ide_atapi_error(drive, rq, stat, err);
300}
301
302/**
303 * ide_error - handle an error on the IDE
304 * @drive: drive the error occurred on
305 * @msg: message to report
306 * @stat: status bits
307 *
308 * ide_error() takes action based on the error returned by the drive.
309 * For normal I/O that may well include retries. We deal with
310 * both new-style (taskfile) and old style command handling here.
311 * In the case of taskfile command handling there is work left to
312 * do
313 */
314
315ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
316{
317 struct request *rq;
318 u8 err;
319
320 err = ide_dump_status(drive, msg, stat);
321
322 rq = drive->hwif->rq;
323 if (rq == NULL)
324 return ide_stopped;
325
326 /* retry only "normal" I/O: */
327 if (!blk_fs_request(rq)) {
328 rq->errors = 1;
329 ide_end_drive_cmd(drive, stat, err);
330 return ide_stopped;
331 }
332
333 return __ide_error(drive, rq, stat, err);
334}
335EXPORT_SYMBOL_GPL(ide_error);
336
337static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) 210static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
338{ 211{
339 tf->nsect = drive->sect; 212 tf->nsect = drive->sect;