aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAlbert Lee <albertcc@tw.ibm.com>2005-08-12 02:17:50 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-12 02:44:20 -0400
commit563a6e1fb0af58433beec1ab418e1fafbd100b56 (patch)
treedcf2145bbf63751722f694044fe547a7dab27d1f /drivers/scsi
parent6ae4cfb5711b6f2878c9e384617971d98c34a7f5 (diff)
[PATCH] libata handle the case when device returns/needs extra data
PATCH 2/2: handle the case when device returns/needs extra data Description: Sometimes the device returns/needs extra data than expected. Changes: Modify __atapi_pio_bytes() to handle the case where device returns/needs extra data. - for read case, discard trailing data from the device - for write case, padding zero data to the device Signed-off-by: Albert Lee <albertcc@tw.ibm.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libata-core.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 8f6e536d8924..9add4c521b6b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2697,10 +2697,33 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
2697 unsigned char *buf; 2697 unsigned char *buf;
2698 unsigned int offset, count; 2698 unsigned int offset, count;
2699 2699
2700 if (qc->curbytes == qc->nbytes - bytes) 2700 if (qc->curbytes + bytes >= qc->nbytes)
2701 ap->pio_task_state = PIO_ST_LAST; 2701 ap->pio_task_state = PIO_ST_LAST;
2702 2702
2703next_sg: 2703next_sg:
2704 if (unlikely(qc->cursg >= qc->n_elem)) {
2705 /*
2706 * The end of qc->sg is reached and the device expects
2707 * more data to transfer. In order not to overrun qc->sg
2708 * and fulfill length specified in the byte count register,
2709 * - for read case, discard trailing data from the device
2710 * - for write case, padding zero data to the device
2711 */
2712 u16 pad_buf[1] = { 0 };
2713 unsigned int words = bytes >> 1;
2714 unsigned int i;
2715
2716 if (words) /* warning if bytes > 1 */
2717 printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
2718 ap->id, bytes);
2719
2720 for (i = 0; i < words; i++)
2721 ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
2722
2723 ap->pio_task_state = PIO_ST_LAST;
2724 return;
2725 }
2726
2704 sg = &qc->sg[qc->cursg]; 2727 sg = &qc->sg[qc->cursg];
2705 2728
2706 page = sg->page; 2729 page = sg->page;
@@ -2734,9 +2757,8 @@ next_sg:
2734 2757
2735 kunmap(page); 2758 kunmap(page);
2736 2759
2737 if (bytes) { 2760 if (bytes)
2738 goto next_sg; 2761 goto next_sg;
2739 }
2740} 2762}
2741 2763
2742/** 2764/**