Jens Axboe wrote: > The sata_mv construct looks a bit odd. Does this work? That last The sata_mv construct worked just fine before sg chaining :) > end_mv_sg test should always be true, just being paranoid... > > diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c > index 4df8311..5397eea 100644 > --- a/drivers/ata/sata_mv.c > +++ b/drivers/ata/sata_mv.c > @@ -1138,8 +1138,9 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) > { > struct mv_port_priv *pp = qc->ap->private_data; > struct scatterlist *sg; > - struct mv_sg *mv_sg; > + struct mv_sg *mv_sg, *end_mv_sg; > > + end_mv_sg = NULL; > mv_sg = pp->sg_tbl; > ata_for_each_sg(sg, qc) { > dma_addr_t addr = sg_dma_address(sg); > @@ -1158,14 +1159,12 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) > > sg_len -= len; > addr += len; > - > - if (!sg_len && ata_sg_is_last(sg, qc)) > - mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); > - > + end_mv_sg = mv_sg; > mv_sg++; > } > - > } > + if (end_mv_sg) > + end_mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); > } > I'm testing a similar patch based on ata_fill_sg()'s method, which basically does something similar to what you've done here (see attached). I had noticed that ata_fill_sg() did not call ata_sg_is_last(). If this fixes the problem, I think the best solution would be to delete ata_sg_is_last(). In the few users that exist, we should be able to eliminate the test programmatically as you and ata_fill_sg() have done -- thereby eliminating a branch per loop in a hotpath. Off to test the attached... if that doesn't work I'll try your version, though there shouldn't be much difference. Jeff