aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <petkovbb@gmail.com>2009-04-26 04:39:07 -0400
committerBorislav Petkov <petkovbb@gmail.com>2009-05-15 00:44:45 -0400
commit103f7033bd0f7b65ff3e0a5ea72449d08010b031 (patch)
treebf1e416a235ffde137c94ad1d5da8542b0e5ab4e
parent239f7e25346e22c4a94bde004d845e7397947c01 (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.c95
-rw-r--r--drivers/ide/ide-cd.c47
-rw-r--r--include/linux/ide.h2
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)
326EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); 329EXPORT_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 */
339int 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}
378EXPORT_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 */
418static 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
457static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) 413static 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);
1125u8 ide_read_error(ide_drive_t *); 1125u8 ide_read_error(ide_drive_t *);
1126void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *); 1126void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *);
1127 1127
1128int ide_check_ireason(ide_drive_t *, struct request *, int, int, int);
1129
1128int ide_check_atapi_device(ide_drive_t *, const char *); 1130int ide_check_atapi_device(ide_drive_t *, const char *);
1129 1131
1130void ide_init_pc(struct ide_atapi_pc *); 1132void ide_init_pc(struct ide_atapi_pc *);