aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 13:11:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 13:11:11 -0400
commite6423407d01168f7760cdee7270d9f51d1240301 (patch)
tree979795cfa8f6946238ab31f544159142f3e7df93 /drivers/ide/ide-atapi.c
parent7f8189068726492950bf1a2dcfd9b51314560abf (diff)
parent39c58f37a10198054c656c28202fb1e6d22fd505 (diff)
Merge branch 'for-2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* 'for-2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (34 commits) ide-cd: prevent null pointer deref via cdrom_newpc_intr ide: BUG() on unknown requests ide: filter out invalid DMA xfer mode changes in HDIO_DRIVE_CMD ioctl handler ide: do not access ide_drive_t 'drive_data' field directly sl82c105: implement test_irq() method siimage: implement test_irq() method pdc202xx_old: implement test_irq() method (take 2) cmd64x: implement test_irq() method cmd640: implement test_irq() method ide: move ack_intr() method into 'struct ide_port_ops' (take 2) ide: move IRQ clearing from ack_intr() method to clear_irq() method (take 2) siimage: use ide_dma_test_irq() (take 2) cmd64x: implement clear_irq() method (take 2) ide: call clear_irq() method in ide_timer_expiry() sgiioc4: coding style cleanup ide: don't enable IORDY at a probe time ide: IORDY handling fixes ata: add ata_id_pio_need_iordy() helper (v2) ide-tape: fix build issue ide: unify interrupt reason checking ...
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c138
1 files changed, 87 insertions, 51 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 702ef64a0f12..eb2181a6a11c 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)
@@ -74,8 +77,6 @@ EXPORT_SYMBOL_GPL(ide_check_atapi_device);
74void ide_init_pc(struct ide_atapi_pc *pc) 77void ide_init_pc(struct ide_atapi_pc *pc)
75{ 78{
76 memset(pc, 0, sizeof(*pc)); 79 memset(pc, 0, sizeof(*pc));
77 pc->buf = pc->pc_buf;
78 pc->buf_size = IDE_PC_BUFFER_SIZE;
79} 80}
80EXPORT_SYMBOL_GPL(ide_init_pc); 81EXPORT_SYMBOL_GPL(ide_init_pc);
81 82
@@ -84,7 +85,7 @@ EXPORT_SYMBOL_GPL(ide_init_pc);
84 * and wait for it to be serviced. 85 * and wait for it to be serviced.
85 */ 86 */
86int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, 87int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
87 struct ide_atapi_pc *pc) 88 struct ide_atapi_pc *pc, void *buf, unsigned int bufflen)
88{ 89{
89 struct request *rq; 90 struct request *rq;
90 int error; 91 int error;
@@ -93,8 +94,8 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
93 rq->cmd_type = REQ_TYPE_SPECIAL; 94 rq->cmd_type = REQ_TYPE_SPECIAL;
94 rq->special = (char *)pc; 95 rq->special = (char *)pc;
95 96
96 if (pc->req_xfer) { 97 if (buf && bufflen) {
97 error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer, 98 error = blk_rq_map_kern(drive->queue, rq, buf, bufflen,
98 GFP_NOIO); 99 GFP_NOIO);
99 if (error) 100 if (error)
100 goto put_req; 101 goto put_req;
@@ -117,7 +118,7 @@ int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
117 ide_init_pc(&pc); 118 ide_init_pc(&pc);
118 pc.c[0] = TEST_UNIT_READY; 119 pc.c[0] = TEST_UNIT_READY;
119 120
120 return ide_queue_pc_tail(drive, disk, &pc); 121 return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
121} 122}
122EXPORT_SYMBOL_GPL(ide_do_test_unit_ready); 123EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
123 124
@@ -132,7 +133,7 @@ int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
132 if (drive->media == ide_tape) 133 if (drive->media == ide_tape)
133 pc.flags |= PC_FLAG_WAIT_FOR_DSC; 134 pc.flags |= PC_FLAG_WAIT_FOR_DSC;
134 135
135 return ide_queue_pc_tail(drive, disk, &pc); 136 return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
136} 137}
137EXPORT_SYMBOL_GPL(ide_do_start_stop); 138EXPORT_SYMBOL_GPL(ide_do_start_stop);
138 139
@@ -147,7 +148,7 @@ int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
147 pc.c[0] = ALLOW_MEDIUM_REMOVAL; 148 pc.c[0] = ALLOW_MEDIUM_REMOVAL;
148 pc.c[4] = on; 149 pc.c[4] = on;
149 150
150 return ide_queue_pc_tail(drive, disk, &pc); 151 return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
151} 152}
152EXPORT_SYMBOL_GPL(ide_set_media_lock); 153EXPORT_SYMBOL_GPL(ide_set_media_lock);
153 154
@@ -172,8 +173,6 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
172 unsigned int cmd_len, sense_len; 173 unsigned int cmd_len, sense_len;
173 int err; 174 int err;
174 175
175 debug_log("%s: enter\n", __func__);
176
177 switch (drive->media) { 176 switch (drive->media) {
178 case ide_floppy: 177 case ide_floppy:
179 cmd_len = 255; 178 cmd_len = 255;
@@ -201,8 +200,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
201 GFP_NOIO); 200 GFP_NOIO);
202 if (unlikely(err)) { 201 if (unlikely(err)) {
203 if (printk_ratelimit()) 202 if (printk_ratelimit())
204 printk(KERN_WARNING "%s: failed to map sense buffer\n", 203 printk(KERN_WARNING PFX "%s: failed to map sense "
205 drive->name); 204 "buffer\n", drive->name);
206 return; 205 return;
207 } 206 }
208 207
@@ -223,7 +222,7 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special)
223{ 222{
224 /* deferred failure from ide_prep_sense() */ 223 /* deferred failure from ide_prep_sense() */
225 if (!drive->sense_rq_armed) { 224 if (!drive->sense_rq_armed) {
226 printk(KERN_WARNING "%s: failed queue sense request\n", 225 printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
227 drive->name); 226 drive->name);
228 return -ENOMEM; 227 return -ENOMEM;
229 } 228 }
@@ -255,8 +254,6 @@ void ide_retry_pc(ide_drive_t *drive)
255 /* init pc from sense_rq */ 254 /* init pc from sense_rq */
256 ide_init_pc(pc); 255 ide_init_pc(pc);
257 memcpy(pc->c, sense_rq->cmd, 12); 256 memcpy(pc->c, sense_rq->cmd, 12);
258 pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */
259 pc->req_xfer = blk_rq_bytes(sense_rq);
260 257
261 if (drive->media == ide_tape) 258 if (drive->media == ide_tape)
262 drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; 259 drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
@@ -298,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive)
298 break; 295 break;
299 default: 296 default:
300 if (!(rq->cmd_flags & REQ_QUIET)) 297 if (!(rq->cmd_flags & REQ_QUIET))
301 printk(KERN_INFO "cmd 0x%x timed out\n", 298 printk(KERN_INFO PFX "cmd 0x%x timed out\n",
302 rq->cmd[0]); 299 rq->cmd[0]);
303 wait = 0; 300 wait = 0;
304 break; 301 break;
@@ -332,6 +329,55 @@ void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
332EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); 329EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
333 330
334/* 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/*
335 * 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
336 * 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)
337 * and will re-point interrupt handler to us. 383 * and will re-point interrupt handler to us.
@@ -365,12 +411,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
365 411
366 if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) { 412 if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
367 if (drive->media == ide_floppy) 413 if (drive->media == ide_floppy)
368 printk(KERN_ERR "%s: DMA %s error\n", 414 printk(KERN_ERR PFX "%s: DMA %s error\n",
369 drive->name, rq_data_dir(pc->rq) 415 drive->name, rq_data_dir(pc->rq)
370 ? "write" : "read"); 416 ? "write" : "read");
371 pc->flags |= PC_FLAG_DMA_ERROR; 417 pc->flags |= PC_FLAG_DMA_ERROR;
372 } else 418 } else
373 pc->xferred = pc->req_xfer; 419 rq->resid_len = 0;
374 debug_log("%s: DMA finished\n", drive->name); 420 debug_log("%s: DMA finished\n", drive->name);
375 } 421 }
376 422
@@ -379,7 +425,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
379 int uptodate, error; 425 int uptodate, error;
380 426
381 debug_log("Packet command completed, %d bytes transferred\n", 427 debug_log("Packet command completed, %d bytes transferred\n",
382 pc->xferred); 428 blk_rq_bytes(rq));
383 429
384 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; 430 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
385 431
@@ -397,8 +443,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
397 pc->rq->errors++; 443 pc->rq->errors++;
398 444
399 if (rq->cmd[0] == REQUEST_SENSE) { 445 if (rq->cmd[0] == REQUEST_SENSE) {
400 printk(KERN_ERR "%s: I/O error in request sense" 446 printk(KERN_ERR PFX "%s: I/O error in request "
401 " command\n", drive->name); 447 "sense command\n", drive->name);
402 return ide_do_reset(drive); 448 return ide_do_reset(drive);
403 } 449 }
404 450
@@ -446,8 +492,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
446 492
447 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 493 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
448 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; 494 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
449 printk(KERN_ERR "%s: The device wants to issue more interrupts " 495 printk(KERN_ERR PFX "%s: The device wants to issue more "
450 "in DMA mode\n", drive->name); 496 "interrupts in DMA mode\n", drive->name);
451 ide_dma_off(drive); 497 ide_dma_off(drive);
452 return ide_do_reset(drive); 498 return ide_do_reset(drive);
453 } 499 }
@@ -455,33 +501,22 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
455 /* Get the number of bytes to transfer on this interrupt. */ 501 /* Get the number of bytes to transfer on this interrupt. */
456 ide_read_bcount_and_ireason(drive, &bcount, &ireason); 502 ide_read_bcount_and_ireason(drive, &bcount, &ireason);
457 503
458 if (ireason & ATAPI_COD) { 504 if (ide_check_ireason(drive, rq, bcount, ireason, write))
459 printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
460 return ide_do_reset(drive); 505 return ide_do_reset(drive);
461 }
462
463 if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
464 /* Hopefully, we will never get here */
465 printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
466 "to %s!\n", drive->name,
467 (ireason & ATAPI_IO) ? "Write" : "Read",
468 (ireason & ATAPI_IO) ? "Read" : "Write");
469 return ide_do_reset(drive);
470 }
471 506
472 done = min_t(unsigned int, bcount, cmd->nleft); 507 done = min_t(unsigned int, bcount, cmd->nleft);
473 ide_pio_bytes(drive, cmd, write, done); 508 ide_pio_bytes(drive, cmd, write, done);
474 509
475 /* Update transferred byte count */ 510 /* Update transferred byte count */
476 pc->xferred += done; 511 rq->resid_len -= done;
477 512
478 bcount -= done; 513 bcount -= done;
479 514
480 if (bcount) 515 if (bcount)
481 ide_pad_transfer(drive, write, bcount); 516 ide_pad_transfer(drive, write, bcount);
482 517
483 debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n", 518 debug_log("[cmd %x] transferred %d bytes, padded %d bytes, resid: %u\n",
484 rq->cmd[0], done, bcount); 519 rq->cmd[0], done, bcount, rq->resid_len);
485 520
486 /* And set the interrupt handler again */ 521 /* And set the interrupt handler again */
487 ide_set_handler(drive, ide_pc_intr, timeout); 522 ide_set_handler(drive, ide_pc_intr, timeout);
@@ -515,13 +550,13 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
515 550
516 while (retries-- && ((ireason & ATAPI_COD) == 0 || 551 while (retries-- && ((ireason & ATAPI_COD) == 0 ||
517 (ireason & ATAPI_IO))) { 552 (ireason & ATAPI_IO))) {
518 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 553 printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing "
519 "a packet command, retrying\n", drive->name); 554 "a packet command, retrying\n", drive->name);
520 udelay(100); 555 udelay(100);
521 ireason = ide_read_ireason(drive); 556 ireason = ide_read_ireason(drive);
522 if (retries == 0) { 557 if (retries == 0) {
523 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 558 printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing"
524 "a packet command, ignoring\n", 559 " a packet command, ignoring\n",
525 drive->name); 560 drive->name);
526 ireason |= ATAPI_COD; 561 ireason |= ATAPI_COD;
527 ireason &= ~ATAPI_IO; 562 ireason &= ~ATAPI_IO;
@@ -552,7 +587,7 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
552 u8 ireason; 587 u8 ireason;
553 588
554 if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { 589 if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
555 printk(KERN_ERR "%s: Strange, packet command initiated yet " 590 printk(KERN_ERR PFX "%s: Strange, packet command initiated yet "
556 "DRQ isn't asserted\n", drive->name); 591 "DRQ isn't asserted\n", drive->name);
557 return startstop; 592 return startstop;
558 } 593 }
@@ -594,8 +629,8 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
594 ireason = ide_wait_ireason(drive, ireason); 629 ireason = ide_wait_ireason(drive, ireason);
595 630
596 if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { 631 if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
597 printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " 632 printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while "
598 "a packet command\n", drive->name); 633 "issuing a packet command\n", drive->name);
599 634
600 return ide_do_reset(drive); 635 return ide_do_reset(drive);
601 } 636 }
@@ -633,7 +668,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
633 ide_hwif_t *hwif = drive->hwif; 668 ide_hwif_t *hwif = drive->hwif;
634 ide_expiry_t *expiry = NULL; 669 ide_expiry_t *expiry = NULL;
635 struct request *rq = hwif->rq; 670 struct request *rq = hwif->rq;
636 unsigned int timeout; 671 unsigned int timeout, bytes;
637 u16 bcount; 672 u16 bcount;
638 u8 valid_tf; 673 u8 valid_tf;
639 u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT); 674 u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
@@ -649,13 +684,14 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
649 } else { 684 } else {
650 pc = drive->pc; 685 pc = drive->pc;
651 686
652 /* We haven't transferred any data yet */
653 pc->xferred = 0;
654
655 valid_tf = IDE_VALID_DEVICE; 687 valid_tf = IDE_VALID_DEVICE;
656 bcount = ((drive->media == ide_tape) ? 688 bytes = blk_rq_bytes(rq);
657 pc->req_xfer : 689 bcount = ((drive->media == ide_tape) ? bytes
658 min(pc->req_xfer, 63 * 1024)); 690 : min_t(unsigned int,
691 bytes, 63 * 1024));
692
693 /* We haven't transferred any data yet */
694 rq->resid_len = bcount;
659 695
660 if (pc->flags & PC_FLAG_DMA_ERROR) { 696 if (pc->flags & PC_FLAG_DMA_ERROR) {
661 pc->flags &= ~PC_FLAG_DMA_ERROR; 697 pc->flags &= ~PC_FLAG_DMA_ERROR;