aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-07-06 19:13:52 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-09 12:17:35 -0400
commitd26fc9551a15fdad0d5de8376a78816b8af44f00 (patch)
tree5c829c1baf499ad1f31ed4b8b41e766b290a6306
parentc1e6f28cc5de37dcd113b9668a185c0b9334ba8a (diff)
libata: Support chips with 64K PRD quirk
Add ata_dumb_qc_prep and supporting logic so that a driver can just specify it needs to be helped in this area. 64K entries are split as with drivers/ide. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-core.c80
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/ata/pata_cs5520.c4
-rw-r--r--drivers/ata/pata_cs5530.c4
-rw-r--r--drivers/ata/pata_sc1200.c4
-rw-r--r--include/linux/libata.h2
6 files changed, 89 insertions, 7 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 74c4cd9ad82b..5b25311ba885 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4103,6 +4103,68 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
4103} 4103}
4104 4104
4105/** 4105/**
4106 * ata_fill_sg_dumb - Fill PCI IDE PRD table
4107 * @qc: Metadata associated with taskfile to be transferred
4108 *
4109 * Fill PCI IDE PRD (scatter-gather) table with segments
4110 * associated with the current disk command. Perform the fill
4111 * so that we avoid writing any length 64K records for
4112 * controllers that don't follow the spec.
4113 *
4114 * LOCKING:
4115 * spin_lock_irqsave(host lock)
4116 *
4117 */
4118static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
4119{
4120 struct ata_port *ap = qc->ap;
4121 struct scatterlist *sg;
4122 unsigned int idx;
4123
4124 WARN_ON(qc->__sg == NULL);
4125 WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
4126
4127 idx = 0;
4128 ata_for_each_sg(sg, qc) {
4129 u32 addr, offset;
4130 u32 sg_len, len, blen;
4131
4132 /* determine if physical DMA addr spans 64K boundary.
4133 * Note h/w doesn't support 64-bit, so we unconditionally
4134 * truncate dma_addr_t to u32.
4135 */
4136 addr = (u32) sg_dma_address(sg);
4137 sg_len = sg_dma_len(sg);
4138
4139 while (sg_len) {
4140 offset = addr & 0xffff;
4141 len = sg_len;
4142 if ((offset + sg_len) > 0x10000)
4143 len = 0x10000 - offset;
4144
4145 blen = len & 0xffff;
4146 ap->prd[idx].addr = cpu_to_le32(addr);
4147 if (blen == 0) {
4148 /* Some PATA chipsets like the CS5530 can't
4149 cope with 0x0000 meaning 64K as the spec says */
4150 ap->prd[idx].flags_len = cpu_to_le32(0x8000);
4151 blen = 0x8000;
4152 ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
4153 }
4154 ap->prd[idx].flags_len = cpu_to_le32(blen);
4155 VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
4156
4157 idx++;
4158 sg_len -= len;
4159 addr += len;
4160 }
4161 }
4162
4163 if (idx)
4164 ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
4165}
4166
4167/**
4106 * ata_check_atapi_dma - Check whether ATAPI DMA can be supported 4168 * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
4107 * @qc: Metadata associated with taskfile to check 4169 * @qc: Metadata associated with taskfile to check
4108 * 4170 *
@@ -4149,6 +4211,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
4149 ata_fill_sg(qc); 4211 ata_fill_sg(qc);
4150} 4212}
4151 4213
4214/**
4215 * ata_dumb_qc_prep - Prepare taskfile for submission
4216 * @qc: Metadata associated with taskfile to be prepared
4217 *
4218 * Prepare ATA taskfile for submission.
4219 *
4220 * LOCKING:
4221 * spin_lock_irqsave(host lock)
4222 */
4223void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
4224{
4225 if (!(qc->flags & ATA_QCFLAG_DMAMAP))
4226 return;
4227
4228 ata_fill_sg_dumb(qc);
4229}
4230
4152void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } 4231void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
4153 4232
4154/** 4233/**
@@ -6821,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode);
6821EXPORT_SYMBOL_GPL(ata_data_xfer); 6900EXPORT_SYMBOL_GPL(ata_data_xfer);
6822EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); 6901EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
6823EXPORT_SYMBOL_GPL(ata_qc_prep); 6902EXPORT_SYMBOL_GPL(ata_qc_prep);
6903EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
6824EXPORT_SYMBOL_GPL(ata_noop_qc_prep); 6904EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
6825EXPORT_SYMBOL_GPL(ata_bmdma_setup); 6905EXPORT_SYMBOL_GPL(ata_bmdma_setup);
6826EXPORT_SYMBOL_GPL(ata_bmdma_start); 6906EXPORT_SYMBOL_GPL(ata_bmdma_start);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 4ddf00c8c5f5..cfde22da07ac 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2620,7 +2620,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
2620 ata_dev_printk(dev, KERN_WARNING, 2620 ata_dev_printk(dev, KERN_WARNING,
2621 "invalid multi_count %u ignored\n", 2621 "invalid multi_count %u ignored\n",
2622 multi_count); 2622 multi_count);
2623 } 2623 }
2624 2624
2625 /* READ/WRITE LONG use a non-standard sect_size */ 2625 /* READ/WRITE LONG use a non-standard sect_size */
2626 qc->sect_size = ATA_SECT_SIZE; 2626 qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 00cf0134079c..6bf037d82b5a 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -146,7 +146,7 @@ static struct scsi_host_template cs5520_sht = {
146 .queuecommand = ata_scsi_queuecmd, 146 .queuecommand = ata_scsi_queuecmd,
147 .can_queue = ATA_DEF_QUEUE, 147 .can_queue = ATA_DEF_QUEUE,
148 .this_id = ATA_SHT_THIS_ID, 148 .this_id = ATA_SHT_THIS_ID,
149 .sg_tablesize = LIBATA_MAX_PRD, 149 .sg_tablesize = LIBATA_DUMB_MAX_PRD,
150 .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 150 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
151 .emulated = ATA_SHT_EMULATED, 151 .emulated = ATA_SHT_EMULATED,
152 .use_clustering = ATA_SHT_USE_CLUSTERING, 152 .use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -178,7 +178,7 @@ static struct ata_port_operations cs5520_port_ops = {
178 .bmdma_start = ata_bmdma_start, 178 .bmdma_start = ata_bmdma_start,
179 .bmdma_stop = ata_bmdma_stop, 179 .bmdma_stop = ata_bmdma_stop,
180 .bmdma_status = ata_bmdma_status, 180 .bmdma_status = ata_bmdma_status,
181 .qc_prep = ata_qc_prep, 181 .qc_prep = ata_dumb_qc_prep,
182 .qc_issue = ata_qc_issue_prot, 182 .qc_issue = ata_qc_issue_prot,
183 .data_xfer = ata_data_xfer, 183 .data_xfer = ata_data_xfer,
184 184
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 797a6f67e8f5..3fca5898642b 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -167,7 +167,7 @@ static struct scsi_host_template cs5530_sht = {
167 .queuecommand = ata_scsi_queuecmd, 167 .queuecommand = ata_scsi_queuecmd,
168 .can_queue = ATA_DEF_QUEUE, 168 .can_queue = ATA_DEF_QUEUE,
169 .this_id = ATA_SHT_THIS_ID, 169 .this_id = ATA_SHT_THIS_ID,
170 .sg_tablesize = LIBATA_MAX_PRD, 170 .sg_tablesize = LIBATA_DUMB_MAX_PRD,
171 .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 171 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
172 .emulated = ATA_SHT_EMULATED, 172 .emulated = ATA_SHT_EMULATED,
173 .use_clustering = ATA_SHT_USE_CLUSTERING, 173 .use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -201,7 +201,7 @@ static struct ata_port_operations cs5530_port_ops = {
201 .post_internal_cmd = ata_bmdma_post_internal_cmd, 201 .post_internal_cmd = ata_bmdma_post_internal_cmd,
202 .cable_detect = ata_cable_40wire, 202 .cable_detect = ata_cable_40wire,
203 203
204 .qc_prep = ata_qc_prep, 204 .qc_prep = ata_dumb_qc_prep,
205 .qc_issue = cs5530_qc_issue_prot, 205 .qc_issue = cs5530_qc_issue_prot,
206 206
207 .data_xfer = ata_data_xfer, 207 .data_xfer = ata_data_xfer,
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 7ff39cf9dc0b..b8b2d11e4180 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -185,7 +185,7 @@ static struct scsi_host_template sc1200_sht = {
185 .queuecommand = ata_scsi_queuecmd, 185 .queuecommand = ata_scsi_queuecmd,
186 .can_queue = ATA_DEF_QUEUE, 186 .can_queue = ATA_DEF_QUEUE,
187 .this_id = ATA_SHT_THIS_ID, 187 .this_id = ATA_SHT_THIS_ID,
188 .sg_tablesize = LIBATA_MAX_PRD, 188 .sg_tablesize = LIBATA_DUMB_MAX_PRD,
189 .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 189 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
190 .emulated = ATA_SHT_EMULATED, 190 .emulated = ATA_SHT_EMULATED,
191 .use_clustering = ATA_SHT_USE_CLUSTERING, 191 .use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -219,7 +219,7 @@ static struct ata_port_operations sc1200_port_ops = {
219 .bmdma_stop = ata_bmdma_stop, 219 .bmdma_stop = ata_bmdma_stop,
220 .bmdma_status = ata_bmdma_status, 220 .bmdma_status = ata_bmdma_status,
221 221
222 .qc_prep = ata_qc_prep, 222 .qc_prep = ata_dumb_qc_prep,
223 .qc_issue = sc1200_qc_issue_prot, 223 .qc_issue = sc1200_qc_issue_prot,
224 224
225 .data_xfer = ata_data_xfer, 225 .data_xfer = ata_data_xfer,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 8d3e391ab8d3..a3df64677ac3 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -116,6 +116,7 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
116enum { 116enum {
117 /* various global constants */ 117 /* various global constants */
118 LIBATA_MAX_PRD = ATA_MAX_PRD / 2, 118 LIBATA_MAX_PRD = ATA_MAX_PRD / 2,
119 LIBATA_DUMB_MAX_PRD = ATA_MAX_PRD / 4, /* Worst case */
119 ATA_MAX_PORTS = 8, 120 ATA_MAX_PORTS = 8,
120 ATA_DEF_QUEUE = 1, 121 ATA_DEF_QUEUE = 1,
121 /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */ 122 /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
@@ -778,6 +779,7 @@ extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
778 unsigned int buflen, int write_data); 779 unsigned int buflen, int write_data);
779extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, 780extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
780 unsigned int buflen, int write_data); 781 unsigned int buflen, int write_data);
782extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
781extern void ata_qc_prep(struct ata_queued_cmd *qc); 783extern void ata_qc_prep(struct ata_queued_cmd *qc);
782extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); 784extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
783extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); 785extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);