diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-05 07:13:30 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-05 07:13:30 -0400 |
commit | cedc9a478d8c6265879dc3839ef3d4849a709184 (patch) | |
tree | 0c8e0fbffdb6081381c01b8cfd93c95b168acb44 /include | |
parent | ed39f731ab2e77e58122232f6e27333331d7793d (diff) |
libata: fix ATAPI DMA alignment issues
ATAPI needs to be padded to next 4 byte boundary, if misaligned.
Original work by me, many fixes from Tejun Heo.
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/libata.h | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h index ceee1fc42c60..3ab67622ef93 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -154,6 +154,10 @@ enum { | |||
154 | ATA_SHIFT_UDMA = 0, | 154 | ATA_SHIFT_UDMA = 0, |
155 | ATA_SHIFT_MWDMA = 8, | 155 | ATA_SHIFT_MWDMA = 8, |
156 | ATA_SHIFT_PIO = 11, | 156 | ATA_SHIFT_PIO = 11, |
157 | |||
158 | /* size of buffer to pad xfers ending on unaligned boundaries */ | ||
159 | ATA_DMA_PAD_SZ = 4, | ||
160 | ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, | ||
157 | }; | 161 | }; |
158 | 162 | ||
159 | enum pio_task_states { | 163 | enum pio_task_states { |
@@ -237,9 +241,12 @@ struct ata_queued_cmd { | |||
237 | unsigned long flags; /* ATA_QCFLAG_xxx */ | 241 | unsigned long flags; /* ATA_QCFLAG_xxx */ |
238 | unsigned int tag; | 242 | unsigned int tag; |
239 | unsigned int n_elem; | 243 | unsigned int n_elem; |
244 | unsigned int orig_n_elem; | ||
240 | 245 | ||
241 | int dma_dir; | 246 | int dma_dir; |
242 | 247 | ||
248 | unsigned int pad_len; | ||
249 | |||
243 | unsigned int nsect; | 250 | unsigned int nsect; |
244 | unsigned int cursect; | 251 | unsigned int cursect; |
245 | 252 | ||
@@ -250,9 +257,11 @@ struct ata_queued_cmd { | |||
250 | unsigned int cursg_ofs; | 257 | unsigned int cursg_ofs; |
251 | 258 | ||
252 | struct scatterlist sgent; | 259 | struct scatterlist sgent; |
260 | struct scatterlist pad_sgent; | ||
253 | void *buf_virt; | 261 | void *buf_virt; |
254 | 262 | ||
255 | struct scatterlist *sg; | 263 | /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ |
264 | struct scatterlist *__sg; | ||
256 | 265 | ||
257 | ata_qc_cb_t complete_fn; | 266 | ata_qc_cb_t complete_fn; |
258 | 267 | ||
@@ -295,6 +304,9 @@ struct ata_port { | |||
295 | struct ata_prd *prd; /* our SG list */ | 304 | struct ata_prd *prd; /* our SG list */ |
296 | dma_addr_t prd_dma; /* and its DMA mapping */ | 305 | dma_addr_t prd_dma; /* and its DMA mapping */ |
297 | 306 | ||
307 | void *pad; /* array of DMA pad buffers */ | ||
308 | dma_addr_t pad_dma; | ||
309 | |||
298 | struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ | 310 | struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ |
299 | 311 | ||
300 | u8 ctl; /* cache of ATA control register */ | 312 | u8 ctl; /* cache of ATA control register */ |
@@ -458,6 +470,19 @@ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); | |||
458 | #endif /* CONFIG_PCI */ | 470 | #endif /* CONFIG_PCI */ |
459 | 471 | ||
460 | 472 | ||
473 | static inline struct scatterlist * | ||
474 | ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) | ||
475 | { | ||
476 | if (sg == &qc->pad_sgent) | ||
477 | return NULL; | ||
478 | if (++sg - qc->__sg < qc->n_elem) | ||
479 | return sg; | ||
480 | return qc->pad_len ? &qc->pad_sgent : NULL; | ||
481 | } | ||
482 | |||
483 | #define ata_for_each_sg(sg, qc) \ | ||
484 | for (sg = qc->__sg; sg; sg = ata_qc_next_sg(sg, qc)) | ||
485 | |||
461 | static inline unsigned int ata_tag_valid(unsigned int tag) | 486 | static inline unsigned int ata_tag_valid(unsigned int tag) |
462 | { | 487 | { |
463 | return (tag < ATA_MAX_QUEUE) ? 1 : 0; | 488 | return (tag < ATA_MAX_QUEUE) ? 1 : 0; |