[PATCH 2/3] libata: implement max_segment_size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



libata depeneded on sht->dma_boundary for demtermining maximum segment
size.  This is good enough for most controllers but inic1622 just had
to be different and it locks up if segement size is 65536 while
dma_boundary is 0xffff.

This patch implements ap->max_segment_size which can be initialized
via probe_ent (or port_info) and used in ->slave_config to configure
maximum segment size.  LLDs without braindamage can leave this alone.

Signed-off-by: Tejun Heo <htejun@xxxxxxxxx>
---
 drivers/ata/libata-core.c |    3 +++
 drivers/ata/libata-scsi.c |    9 +++++++++
 include/linux/libata.h    |    3 +++
 3 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2a496d0..b28a313 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5620,12 +5620,14 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
 		ap->pio_mask = ent->pinfo2->pio_mask;
 		ap->mwdma_mask = ent->pinfo2->mwdma_mask;
 		ap->udma_mask = ent->pinfo2->udma_mask;
+		ap->max_segment_size = ent->max_segment_size;
 		ap->flags |= ent->pinfo2->flags;
 		ap->ops = ent->pinfo2->port_ops;
 	} else {
 		ap->pio_mask = ent->pio_mask;
 		ap->mwdma_mask = ent->mwdma_mask;
 		ap->udma_mask = ent->udma_mask;
+		ap->max_segment_size = ent->max_segment_size;
 		ap->flags |= ent->port_flags;
 		ap->ops = ent->port_ops;
 	}
@@ -6110,6 +6112,7 @@ ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
 	probe_ent->pio_mask = port->pio_mask;
 	probe_ent->mwdma_mask = port->mwdma_mask;
 	probe_ent->udma_mask = port->udma_mask;
+	probe_ent->max_segment_size = port->max_segment_size;
 	probe_ent->port_ops = port->port_ops;
 	probe_ent->private_data = port->private_data;
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e8a352d..f817d13 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -823,6 +823,15 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
 		depth = min(ATA_MAX_QUEUE - 1, depth);
 		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
 	}
+
+	/* max_segment_size setting is usually not necessary as it's
+	 * automatically determined from sht->dma_boundary, but some
+	 * controllers need smaller max_segement_size than the value
+	 * determined by sht->dma_boundary.
+	 */
+	if (dev->ap->max_segment_size)
+		blk_queue_max_segment_size(sdev->request_queue,
+					   dev->ap->max_segment_size);
 }
 
 /**
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b7c86b4..bdf7fc5 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -379,6 +379,7 @@ struct ata_probe_ent {
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
+	size_t			max_segment_size;	/* optional */
 	unsigned long		irq;
 	unsigned long		irq2;
 	unsigned int		irq_flags;
@@ -550,6 +551,7 @@ struct ata_port {
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
+	size_t			max_segment_size; /* optional */
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
 	unsigned int		hw_sata_spd_limit;
 	unsigned int		sata_spd_limit;	/* SATA PHY speed limit */
@@ -658,6 +660,7 @@ struct ata_port_info {
 	unsigned long		pio_mask;
 	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
+	size_t			max_segment_size;	/* optional */
 	const struct ata_port_operations *port_ops;
 	void 			*private_data;
 };
-- 
1.4.4.2

-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux