diff options
author | Borislav Petkov <petkovbb@gmail.com> | 2009-04-26 04:39:07 -0400 |
---|---|---|
committer | Borislav Petkov <petkovbb@gmail.com> | 2009-05-15 00:44:45 -0400 |
commit | 103f7033bd0f7b65ff3e0a5ea72449d08010b031 (patch) | |
tree | bf1e416a235ffde137c94ad1d5da8542b0e5ab4e | |
parent | 239f7e25346e22c4a94bde004d845e7397947c01 (diff) |
ide: unify interrupt reason checking
Add ide_check_ireason() function that handles all ATAPI devices.
Reorganize all unlikely cases in ireason checking further down in the
code path.
In addition, add PFX for printks originating from ide-atapi. Finally,
remove ide_cd_check_ireason.
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
-rw-r--r-- | drivers/ide/ide-atapi.c | 95 | ||||
-rw-r--r-- | drivers/ide/ide-cd.c | 47 | ||||
-rw-r--r-- | include/linux/ide.h | 2 |
3 files changed, 71 insertions, 73 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3075b0414667..1125ce29809b 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -10,6 +10,9 @@ | |||
10 | 10 | ||
11 | #include <scsi/scsi.h> | 11 | #include <scsi/scsi.h> |
12 | 12 | ||
13 | #define DRV_NAME "ide-atapi" | ||
14 | #define PFX DRV_NAME ": " | ||
15 | |||
13 | #ifdef DEBUG | 16 | #ifdef DEBUG |
14 | #define debug_log(fmt, args...) \ | 17 | #define debug_log(fmt, args...) \ |
15 | printk(KERN_INFO "ide: " fmt, ## args) | 18 | printk(KERN_INFO "ide: " fmt, ## args) |
@@ -197,8 +200,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) | |||
197 | GFP_NOIO); | 200 | GFP_NOIO); |
198 | if (unlikely(err)) { | 201 | if (unlikely(err)) { |
199 | if (printk_ratelimit()) | 202 | if (printk_ratelimit()) |
200 | printk(KERN_WARNING "%s: failed to map sense buffer\n", | 203 | printk(KERN_WARNING PFX "%s: failed to map sense " |
201 | drive->name); | 204 | "buffer\n", drive->name); |
202 | return; | 205 | return; |
203 | } | 206 | } |
204 | 207 | ||
@@ -219,7 +222,7 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special) | |||
219 | { | 222 | { |
220 | /* deferred failure from ide_prep_sense() */ | 223 | /* deferred failure from ide_prep_sense() */ |
221 | if (!drive->sense_rq_armed) { | 224 | if (!drive->sense_rq_armed) { |
222 | printk(KERN_WARNING "%s: failed queue sense request\n", | 225 | printk(KERN_WARNING PFX "%s: error queuing a sense request\n", |
223 | drive->name); | 226 | drive->name); |
224 | return -ENOMEM; | 227 | return -ENOMEM; |
225 | } | 228 | } |
@@ -292,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive) | |||
292 | break; | 295 | break; |
293 | default: | 296 | default: |
294 | if (!(rq->cmd_flags & REQ_QUIET)) | 297 | if (!(rq->cmd_flags & REQ_QUIET)) |
295 | printk(KERN_INFO "cmd 0x%x timed out\n", | 298 | printk(KERN_INFO PFX "cmd 0x%x timed out\n", |
296 | rq->cmd[0]); | 299 | rq->cmd[0]); |
297 | wait = 0; | 300 | wait = 0; |
298 | break; | 301 | break; |
@@ -326,6 +329,55 @@ void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) | |||
326 | EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); | 329 | EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); |
327 | 330 | ||
328 | /* | 331 | /* |
332 | * Check the contents of the interrupt reason register and attempt to recover if | ||
333 | * there are problems. | ||
334 | * | ||
335 | * Returns: | ||
336 | * - 0 if everything's ok | ||
337 | * - 1 if the request has to be terminated. | ||
338 | */ | ||
339 | int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len, | ||
340 | int ireason, int rw) | ||
341 | { | ||
342 | ide_hwif_t *hwif = drive->hwif; | ||
343 | |||
344 | debug_log("ireason: 0x%x, rw: 0x%x\n", ireason, rw); | ||
345 | |||
346 | if (ireason == (!rw << 1)) | ||
347 | return 0; | ||
348 | else if (ireason == (rw << 1)) { | ||
349 | printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n", | ||
350 | drive->name, __func__); | ||
351 | |||
352 | if (dev_is_idecd(drive)) | ||
353 | ide_pad_transfer(drive, rw, len); | ||
354 | } else if (!rw && ireason == ATAPI_COD) { | ||
355 | if (dev_is_idecd(drive)) { | ||
356 | /* | ||
357 | * Some drives (ASUS) seem to tell us that status info | ||
358 | * is available. Just get it and ignore. | ||
359 | */ | ||
360 | (void)hwif->tp_ops->read_status(hwif); | ||
361 | return 0; | ||
362 | } | ||
363 | } else { | ||
364 | if (ireason & ATAPI_COD) | ||
365 | printk(KERN_ERR PFX "%s: CoD != 0 in %s\n", drive->name, | ||
366 | __func__); | ||
367 | |||
368 | /* drive wants a command packet, or invalid ireason... */ | ||
369 | printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n", | ||
370 | drive->name, __func__, ireason); | ||
371 | } | ||
372 | |||
373 | if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC) | ||
374 | rq->cmd_flags |= REQ_FAILED; | ||
375 | |||
376 | return 1; | ||
377 | } | ||
378 | EXPORT_SYMBOL_GPL(ide_check_ireason); | ||
379 | |||
380 | /* | ||
329 | * This is the usual interrupt handler which will be called during a packet | 381 | * This is the usual interrupt handler which will be called during a packet |
330 | * command. We will transfer some of the data (as requested by the drive) | 382 | * command. We will transfer some of the data (as requested by the drive) |
331 | * and will re-point interrupt handler to us. | 383 | * and will re-point interrupt handler to us. |
@@ -359,7 +411,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
359 | 411 | ||
360 | if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) { | 412 | if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) { |
361 | if (drive->media == ide_floppy) | 413 | if (drive->media == ide_floppy) |
362 | printk(KERN_ERR "%s: DMA %s error\n", | 414 | printk(KERN_ERR PFX "%s: DMA %s error\n", |
363 | drive->name, rq_data_dir(pc->rq) | 415 | drive->name, rq_data_dir(pc->rq) |
364 | ? "write" : "read"); | 416 | ? "write" : "read"); |
365 | pc->flags |= PC_FLAG_DMA_ERROR; | 417 | pc->flags |= PC_FLAG_DMA_ERROR; |
@@ -391,8 +443,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
391 | pc->rq->errors++; | 443 | pc->rq->errors++; |
392 | 444 | ||
393 | if (rq->cmd[0] == REQUEST_SENSE) { | 445 | if (rq->cmd[0] == REQUEST_SENSE) { |
394 | printk(KERN_ERR "%s: I/O error in request sense" | 446 | printk(KERN_ERR PFX "%s: I/O error in request " |
395 | " command\n", drive->name); | 447 | "sense command\n", drive->name); |
396 | return ide_do_reset(drive); | 448 | return ide_do_reset(drive); |
397 | } | 449 | } |
398 | 450 | ||
@@ -434,8 +486,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
434 | 486 | ||
435 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | 487 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
436 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | 488 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; |
437 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | 489 | printk(KERN_ERR PFX "%s: The device wants to issue more " |
438 | "in DMA mode\n", drive->name); | 490 | "interrupts in DMA mode\n", drive->name); |
439 | ide_dma_off(drive); | 491 | ide_dma_off(drive); |
440 | return ide_do_reset(drive); | 492 | return ide_do_reset(drive); |
441 | } | 493 | } |
@@ -443,19 +495,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
443 | /* Get the number of bytes to transfer on this interrupt. */ | 495 | /* Get the number of bytes to transfer on this interrupt. */ |
444 | ide_read_bcount_and_ireason(drive, &bcount, &ireason); | 496 | ide_read_bcount_and_ireason(drive, &bcount, &ireason); |
445 | 497 | ||
446 | if (ireason & ATAPI_COD) { | 498 | if (ide_check_ireason(drive, rq, bcount, ireason, write)) |
447 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | ||
448 | return ide_do_reset(drive); | 499 | return ide_do_reset(drive); |
449 | } | ||
450 | |||
451 | if (((ireason & ATAPI_IO) == ATAPI_IO) == write) { | ||
452 | /* Hopefully, we will never get here */ | ||
453 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | ||
454 | "to %s!\n", drive->name, | ||
455 | (ireason & ATAPI_IO) ? "Write" : "Read", | ||
456 | (ireason & ATAPI_IO) ? "Read" : "Write"); | ||
457 | return ide_do_reset(drive); | ||
458 | } | ||
459 | 500 | ||
460 | done = min_t(unsigned int, bcount, cmd->nleft); | 501 | done = min_t(unsigned int, bcount, cmd->nleft); |
461 | ide_pio_bytes(drive, cmd, write, done); | 502 | ide_pio_bytes(drive, cmd, write, done); |
@@ -503,13 +544,13 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | |||
503 | 544 | ||
504 | while (retries-- && ((ireason & ATAPI_COD) == 0 || | 545 | while (retries-- && ((ireason & ATAPI_COD) == 0 || |
505 | (ireason & ATAPI_IO))) { | 546 | (ireason & ATAPI_IO))) { |
506 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | 547 | printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing " |
507 | "a packet command, retrying\n", drive->name); | 548 | "a packet command, retrying\n", drive->name); |
508 | udelay(100); | 549 | udelay(100); |
509 | ireason = ide_read_ireason(drive); | 550 | ireason = ide_read_ireason(drive); |
510 | if (retries == 0) { | 551 | if (retries == 0) { |
511 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | 552 | printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing" |
512 | "a packet command, ignoring\n", | 553 | " a packet command, ignoring\n", |
513 | drive->name); | 554 | drive->name); |
514 | ireason |= ATAPI_COD; | 555 | ireason |= ATAPI_COD; |
515 | ireason &= ~ATAPI_IO; | 556 | ireason &= ~ATAPI_IO; |
@@ -540,7 +581,7 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | |||
540 | u8 ireason; | 581 | u8 ireason; |
541 | 582 | ||
542 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { | 583 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { |
543 | printk(KERN_ERR "%s: Strange, packet command initiated yet " | 584 | printk(KERN_ERR PFX "%s: Strange, packet command initiated yet " |
544 | "DRQ isn't asserted\n", drive->name); | 585 | "DRQ isn't asserted\n", drive->name); |
545 | return startstop; | 586 | return startstop; |
546 | } | 587 | } |
@@ -582,8 +623,8 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | |||
582 | ireason = ide_wait_ireason(drive, ireason); | 623 | ireason = ide_wait_ireason(drive, ireason); |
583 | 624 | ||
584 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { | 625 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { |
585 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " | 626 | printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while " |
586 | "a packet command\n", drive->name); | 627 | "issuing a packet command\n", drive->name); |
587 | 628 | ||
588 | return ide_do_reset(drive); | 629 | return ide_do_reset(drive); |
589 | } | 630 | } |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index dca41ae0d048..d299713bfdc1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -410,50 +410,6 @@ end_request: | |||
410 | return 2; | 410 | return 2; |
411 | } | 411 | } |
412 | 412 | ||
413 | /* | ||
414 | * Check the contents of the interrupt reason register from the cdrom | ||
415 | * and attempt to recover if there are problems. Returns 0 if everything's | ||
416 | * ok; nonzero if the request has been terminated. | ||
417 | */ | ||
418 | static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, | ||
419 | int len, int ireason, int rw) | ||
420 | { | ||
421 | ide_hwif_t *hwif = drive->hwif; | ||
422 | |||
423 | ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw); | ||
424 | |||
425 | /* | ||
426 | * ireason == 0: the drive wants to receive data from us | ||
427 | * ireason == 2: the drive is expecting to transfer data to us | ||
428 | */ | ||
429 | if (ireason == (!rw << 1)) | ||
430 | return 0; | ||
431 | else if (ireason == (rw << 1)) { | ||
432 | |||
433 | /* whoops... */ | ||
434 | printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n", | ||
435 | drive->name, __func__); | ||
436 | |||
437 | ide_pad_transfer(drive, rw, len); | ||
438 | } else if (rw == 0 && ireason == 1) { | ||
439 | /* | ||
440 | * Some drives (ASUS) seem to tell us that status info is | ||
441 | * available. Just get it and ignore. | ||
442 | */ | ||
443 | (void)hwif->tp_ops->read_status(hwif); | ||
444 | return 0; | ||
445 | } else { | ||
446 | /* drive wants a command packet, or invalid ireason... */ | ||
447 | printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n", | ||
448 | drive->name, __func__, ireason); | ||
449 | } | ||
450 | |||
451 | if (rq->cmd_type == REQ_TYPE_ATA_PC) | ||
452 | rq->cmd_flags |= REQ_FAILED; | ||
453 | |||
454 | return -1; | ||
455 | } | ||
456 | |||
457 | static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) | 413 | static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) |
458 | { | 414 | { |
459 | struct request *rq = cmd->rq; | 415 | struct request *rq = cmd->rq; |
@@ -645,8 +601,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
645 | goto out_end; | 601 | goto out_end; |
646 | } | 602 | } |
647 | 603 | ||
648 | /* check which way to transfer data */ | 604 | rc = ide_check_ireason(drive, rq, len, ireason, write); |
649 | rc = ide_cd_check_ireason(drive, rq, len, ireason, write); | ||
650 | if (rc) | 605 | if (rc) |
651 | goto out_end; | 606 | goto out_end; |
652 | 607 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 59aedcd7faee..70a2c94d6680 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -1125,6 +1125,8 @@ void SELECT_MASK(ide_drive_t *, int); | |||
1125 | u8 ide_read_error(ide_drive_t *); | 1125 | u8 ide_read_error(ide_drive_t *); |
1126 | void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *); | 1126 | void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *); |
1127 | 1127 | ||
1128 | int ide_check_ireason(ide_drive_t *, struct request *, int, int, int); | ||
1129 | |||
1128 | int ide_check_atapi_device(ide_drive_t *, const char *); | 1130 | int ide_check_atapi_device(ide_drive_t *, const char *); |
1129 | 1131 | ||
1130 | void ide_init_pc(struct ide_atapi_pc *); | 1132 | void ide_init_pc(struct ide_atapi_pc *); |