All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libata: make ata_sg_setup_one() trim zero length sg
@ 2006-02-17  7:53 Tejun Heo
  2006-02-17 21:34 ` Jeff Garzik
  0 siblings, 1 reply; 9+ messages in thread
From: Tejun Heo @ 2006-02-17  7:53 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-ide

This patch makes ata_sg_setup_one() trim sg entry (thus making
qc->n_elem zero) if padding results in zero length sg entry.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

Jeff, currently, in both sg_setup() and sg_setup_one() cases, zero
length sg entry can reach low level driver fill_sg() function which
could possibly cause weird problems.  This and a following patch kill
such cases.

 libata-core.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2583,7 +2583,7 @@ static void ata_sg_clean(struct ata_queu
 	WARN_ON(sg == NULL);
 
 	if (qc->flags & ATA_QCFLAG_SINGLE)
-		WARN_ON(qc->n_elem != 1);
+		WARN_ON(qc->n_elem > 1);
 
 	VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
@@ -2606,7 +2606,7 @@ static void ata_sg_clean(struct ata_queu
 			kunmap_atomic(addr, KM_IRQ0);
 		}
 	} else {
-		if (sg_dma_len(&sg[0]) > 0)
+		if (qc->n_elem)
 			dma_unmap_single(ap->host_set->dev,
 				sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
 				dir);
@@ -2784,6 +2784,7 @@ static int ata_sg_setup_one(struct ata_q
 	int dir = qc->dma_dir;
 	struct scatterlist *sg = qc->__sg;
 	dma_addr_t dma_address;
+	int trim_sg = 0;
 
 	/* we must lengthen transfers to end on a 32-bit boundary */
 	qc->pad_len = sg->length & 3;
@@ -2803,13 +2804,15 @@ static int ata_sg_setup_one(struct ata_q
 		sg_dma_len(psg) = ATA_DMA_PAD_SZ;
 		/* trim sg */
 		sg->length -= qc->pad_len;
+		if (sg->length == 0)
+			trim_sg = 1;
 
 		DPRINTK("padding done, sg->length=%u pad_len=%u\n",
 			sg->length, qc->pad_len);
 	}
 
-	if (!sg->length) {
-		sg_dma_address(sg) = 0;
+	if (trim_sg) {
+		qc->n_elem--;
 		goto skip_map;
 	}
 
@@ -2822,9 +2825,9 @@ static int ata_sg_setup_one(struct ata_q
 	}
 
 	sg_dma_address(sg) = dma_address;
-skip_map:
 	sg_dma_len(sg) = sg->length;
 
+skip_map:
 	DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
 		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-02-20 21:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-17  7:53 [PATCH] libata: make ata_sg_setup_one() trim zero length sg Tejun Heo
2006-02-17 21:34 ` Jeff Garzik
2006-02-18  2:35   ` Tejun Heo
2006-02-20 10:16     ` Jeff Garzik
2006-02-20 14:48       ` [PATCH 1/3] libata: fix WARN_ON() condition in *_fill_sg() Tejun Heo
2006-02-20 21:56         ` Jeff Garzik
2006-02-20 14:48       ` [PATCHSET] libata: sg corner case fixes against Linus tree Tejun Heo
2006-02-20 14:48       ` [PATCH 2/3] libata: fix qc->n_elem == 0 case handling in ata_qc_next_sg Tejun Heo
2006-02-20 14:48       ` [PATCH 3/3] libata: make ata_sg_setup_one() trim zero length sg Tejun Heo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.