]> err.no Git - linux-2.6/commitdiff
libata: make qc->nbytes include extra buffers
authorTejun Heo <htejun@gmail.com>
Wed, 5 Dec 2007 07:43:12 +0000 (16:43 +0900)
committerJeff Garzik <jeff@garzik.org>
Wed, 23 Jan 2008 10:24:15 +0000 (05:24 -0500)
qc->nbytes didn't use to include extra buffers setup by libata core
layer and my be odd.  This patch makes qc->nbytes include any extra
buffers setup by libata core layer and guaranteed to be aligned on 4
byte boundary.

This value is to be used to program the host controller.  As this
represents the actual length of buffer available to the controller and
the controller must be able to deal with short transfers for ATAPI
commands which can transfer variable length, this shouldn't break any
controllers while making problems like rounding-down and controllers
choking up on odd transfer bytes much less likely.

The unmodified value is stored in new field qc->raw_nbytes.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/libata-core.c
include/linux/libata.h

index e998028302dae2643eab8706967c190f5ea8574e..ee72994500a37e5f1825adac9875dcdc7f169d05 100644 (file)
@@ -4763,13 +4763,15 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 }
 
 static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
-                                      unsigned int *n_elem_extra)
+                                      unsigned int *n_elem_extra,
+                                      unsigned int *nbytes_extra)
 {
        struct ata_port *ap = qc->ap;
        unsigned int n_elem = qc->n_elem;
        struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL;
 
        *n_elem_extra = 0;
+       *nbytes_extra = 0;
 
        /* needs padding? */
        qc->pad_len = qc->nbytes & 3;
@@ -4833,6 +4835,7 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
                esg = &qc->extra_sg[1];
 
                (*n_elem_extra)++;
+               (*nbytes_extra) += 4 - qc->pad_len;
        }
 
        if (copy_lsg)
@@ -4866,11 +4869,11 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
 static int ata_sg_setup(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       unsigned int n_elem, n_elem_extra;
+       unsigned int n_elem, n_elem_extra, nbytes_extra;
 
        VPRINTK("ENTER, ata%u\n", ap->print_id);
 
-       n_elem = ata_sg_setup_extra(qc, &n_elem_extra);
+       n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra);
 
        if (n_elem) {
                n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir);
@@ -4885,7 +4888,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
 
        qc->n_elem = qc->mapped_n_elem = n_elem;
        qc->n_elem += n_elem_extra;
-
+       qc->nbytes += nbytes_extra;
        qc->flags |= ATA_QCFLAG_DMAMAP;
 
        return 0;
@@ -5949,6 +5952,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
         */
        BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes));
 
+       /* ata_sg_setup() may update nbytes */
+       qc->raw_nbytes = qc->nbytes;
+
        if (ata_is_dma(prot) || (ata_is_pio(prot) &&
                                 (ap->flags & ATA_FLAG_PIO_DMA)))
                if (ata_sg_setup(qc))
index 162f8b5509ac577f35d4b4f0e8bb47d8d0b2da00..7b7c78e42077e7fc55027e879025db51a5a933ec 100644 (file)
@@ -466,6 +466,7 @@ struct ata_queued_cmd {
        unsigned int            sect_size;
 
        unsigned int            nbytes;
+       unsigned int            raw_nbytes;
        unsigned int            curbytes;
 
        struct scatterlist      *cursg;
@@ -1362,7 +1363,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
        qc->flags = 0;
        qc->cursg = NULL;
        qc->cursg_ofs = 0;
-       qc->nbytes = qc->curbytes = 0;
+       qc->nbytes = qc->raw_nbytes = qc->curbytes = 0;
        qc->n_elem = 0;
        qc->mapped_n_elem = 0;
        qc->n_iter = 0;