diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2007-07-06 19:13:52 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-09 12:17:35 -0400 |
commit | d26fc9551a15fdad0d5de8376a78816b8af44f00 (patch) | |
tree | 5c829c1baf499ad1f31ed4b8b41e766b290a6306 /drivers/ata | |
parent | c1e6f28cc5de37dcd113b9668a185c0b9334ba8a (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>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 80 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_cs5520.c | 4 | ||||
-rw-r--r-- | drivers/ata/pata_cs5530.c | 4 | ||||
-rw-r--r-- | drivers/ata/pata_sc1200.c | 4 |
5 files changed, 87 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 | */ | ||
4118 | static 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 | */ | ||
4223 | void 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 | |||
4152 | void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } | 4231 | void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } |
4153 | 4232 | ||
4154 | /** | 4233 | /** |
@@ -6821,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode); | |||
6821 | EXPORT_SYMBOL_GPL(ata_data_xfer); | 6900 | EXPORT_SYMBOL_GPL(ata_data_xfer); |
6822 | EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); | 6901 | EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); |
6823 | EXPORT_SYMBOL_GPL(ata_qc_prep); | 6902 | EXPORT_SYMBOL_GPL(ata_qc_prep); |
6903 | EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); | ||
6824 | EXPORT_SYMBOL_GPL(ata_noop_qc_prep); | 6904 | EXPORT_SYMBOL_GPL(ata_noop_qc_prep); |
6825 | EXPORT_SYMBOL_GPL(ata_bmdma_setup); | 6905 | EXPORT_SYMBOL_GPL(ata_bmdma_setup); |
6826 | EXPORT_SYMBOL_GPL(ata_bmdma_start); | 6906 | EXPORT_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, |