tree dcf2145bbf63751722f694044fe547a7dab27d1f
parent 6ae4cfb5711b6f2878c9e384617971d98c34a7f5
author Albert Lee <[EMAIL PROTECTED]> Fri, 12 Aug 2005 14:17:50 +0800
committer Jeff Garzik <[EMAIL PROTECTED]> Fri, 12 Aug 2005 10:44:20 -0400

[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 <[EMAIL PROTECTED]>
Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>

 drivers/scsi/libata-core.c |   28 +++++++++++++++++++++++++---
 1 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2697,10 +2697,33 @@ static void __atapi_pio_bytes(struct ata
        unsigned char *buf;
        unsigned int offset, count;
 
-       if (qc->curbytes == qc->nbytes - bytes)
+       if (qc->curbytes + bytes >= qc->nbytes)
                ap->pio_task_state = PIO_ST_LAST;
 
 next_sg:
+       if (unlikely(qc->cursg >= qc->n_elem)) {
+               /* 
+                * The end of qc->sg is reached and the device expects
+                * more data to transfer. In order not to overrun qc->sg
+                * and fulfill length specified in the byte count register,
+                *    - for read case, discard trailing data from the device
+                *    - for write case, padding zero data to the device
+                */
+               u16 pad_buf[1] = { 0 };
+               unsigned int words = bytes >> 1;
+               unsigned int i;
+
+               if (words) /* warning if bytes > 1 */
+                       printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+                              ap->id, bytes);
+
+               for (i = 0; i < words; i++)
+                       ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+               ap->pio_task_state = PIO_ST_LAST;
+               return;
+       }
+
        sg = &qc->sg[qc->cursg];
 
        page = sg->page;
@@ -2734,9 +2757,8 @@ next_sg:
 
        kunmap(page);
 
-       if (bytes) {
+       if (bytes)
                goto next_sg;
-       }
 }
 
 /**
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to