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