diff options
| -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 | ||
