diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/ide-dma.c | 73 |
1 files changed, 30 insertions, 43 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 83885ba0496c..4d212b867c35 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -153,8 +153,11 @@ EXPORT_SYMBOL_GPL(ide_build_sglist); | |||
153 | * | 153 | * |
154 | * ide_build_dmatable() prepares a dma request. We map the command | 154 | * ide_build_dmatable() prepares a dma request. We map the command |
155 | * to get the pci bus addresses of the buffers and then build up | 155 | * to get the pci bus addresses of the buffers and then build up |
156 | * the PRD table that the IDE layer wants to be fed. The code | 156 | * the PRD table that the IDE layer wants to be fed. |
157 | * knows about the 64K wrap bug in the CS5530. | 157 | * |
158 | * Most chipsets correctly interpret a length of 0x0000 as 64KB, | ||
159 | * but at least one (e.g. CS5530) misinterprets it as zero (!). | ||
160 | * So we break the 64KB entry into two 32KB entries instead. | ||
158 | * | 161 | * |
159 | * Returns the number of built PRD entries if all went okay, | 162 | * Returns the number of built PRD entries if all went okay, |
160 | * returns 0 otherwise. | 163 | * returns 0 otherwise. |
@@ -171,15 +174,12 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) | |||
171 | int i; | 174 | int i; |
172 | struct scatterlist *sg; | 175 | struct scatterlist *sg; |
173 | 176 | ||
174 | hwif->sg_nents = i = ide_build_sglist(drive, rq); | 177 | hwif->sg_nents = ide_build_sglist(drive, rq); |
175 | 178 | if (hwif->sg_nents == 0) | |
176 | if (!i) | ||
177 | return 0; | 179 | return 0; |
178 | 180 | ||
179 | sg = hwif->sg_table; | 181 | for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) { |
180 | while (i) { | 182 | u32 cur_addr, cur_len, xcount, bcount; |
181 | u32 cur_addr; | ||
182 | u32 cur_len; | ||
183 | 183 | ||
184 | cur_addr = sg_dma_address(sg); | 184 | cur_addr = sg_dma_address(sg); |
185 | cur_len = sg_dma_len(sg); | 185 | cur_len = sg_dma_len(sg); |
@@ -191,40 +191,27 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) | |||
191 | */ | 191 | */ |
192 | 192 | ||
193 | while (cur_len) { | 193 | while (cur_len) { |
194 | if (count++ >= PRD_ENTRIES) { | 194 | if (count++ >= PRD_ENTRIES) |
195 | printk(KERN_ERR "%s: DMA table too small\n", drive->name); | ||
196 | goto use_pio_instead; | 195 | goto use_pio_instead; |
197 | } else { | 196 | |
198 | u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); | 197 | bcount = 0x10000 - (cur_addr & 0xffff); |
199 | 198 | if (bcount > cur_len) | |
200 | if (bcount > cur_len) | 199 | bcount = cur_len; |
201 | bcount = cur_len; | 200 | *table++ = cpu_to_le32(cur_addr); |
202 | *table++ = cpu_to_le32(cur_addr); | 201 | xcount = bcount & 0xffff; |
203 | xcount = bcount & 0xffff; | 202 | if (is_trm290) |
204 | if (is_trm290) | 203 | xcount = ((xcount >> 2) - 1) << 16; |
205 | xcount = ((xcount >> 2) - 1) << 16; | 204 | if (xcount == 0x0000) { |
206 | else if (xcount == 0x0000) { | 205 | if (count++ >= PRD_ENTRIES) |
207 | /* | 206 | goto use_pio_instead; |
208 | * Most chipsets correctly interpret a length of 0x0000 as 64KB, | 207 | *table++ = cpu_to_le32(0x8000); |
209 | * but at least one (e.g. CS5530) misinterprets it as zero (!). | 208 | *table++ = cpu_to_le32(cur_addr + 0x8000); |
210 | * So here we break the 64KB entry into two 32KB entries instead. | 209 | xcount = 0x8000; |
211 | */ | ||
212 | if (count++ >= PRD_ENTRIES) { | ||
213 | printk(KERN_ERR "%s: DMA table too small\n", drive->name); | ||
214 | goto use_pio_instead; | ||
215 | } | ||
216 | *table++ = cpu_to_le32(0x8000); | ||
217 | *table++ = cpu_to_le32(cur_addr + 0x8000); | ||
218 | xcount = 0x8000; | ||
219 | } | ||
220 | *table++ = cpu_to_le32(xcount); | ||
221 | cur_addr += bcount; | ||
222 | cur_len -= bcount; | ||
223 | } | 210 | } |
211 | *table++ = cpu_to_le32(xcount); | ||
212 | cur_addr += bcount; | ||
213 | cur_len -= bcount; | ||
224 | } | 214 | } |
225 | |||
226 | sg = sg_next(sg); | ||
227 | i--; | ||
228 | } | 215 | } |
229 | 216 | ||
230 | if (count) { | 217 | if (count) { |
@@ -233,14 +220,14 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) | |||
233 | return count; | 220 | return count; |
234 | } | 221 | } |
235 | 222 | ||
236 | printk(KERN_ERR "%s: empty DMA table?\n", drive->name); | ||
237 | |||
238 | use_pio_instead: | 223 | use_pio_instead: |
224 | printk(KERN_ERR "%s: %s\n", drive->name, | ||
225 | count ? "DMA table too small" : "empty DMA table?"); | ||
226 | |||
239 | ide_destroy_dmatable(drive); | 227 | ide_destroy_dmatable(drive); |
240 | 228 | ||
241 | return 0; /* revert to PIO for this request */ | 229 | return 0; /* revert to PIO for this request */ |
242 | } | 230 | } |
243 | |||
244 | EXPORT_SYMBOL_GPL(ide_build_dmatable); | 231 | EXPORT_SYMBOL_GPL(ide_build_dmatable); |
245 | #endif | 232 | #endif |
246 | 233 | ||