Skip to content

Commit

Permalink
libata: make qc->nbytes include extra buffers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Jan 23, 2008
1 parent ff2aeb1 commit 0bcc65a
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
14 changes: 10 additions & 4 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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))
Expand Down
3 changes: 2 additions & 1 deletion include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 0bcc65a

Please sign in to comment.