diff options
Diffstat (limited to 'packages/linux/linux-handhelds-2.6-2.6.16/block-pio.patch')
-rw-r--r-- | packages/linux/linux-handhelds-2.6-2.6.16/block-pio.patch | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/packages/linux/linux-handhelds-2.6-2.6.16/block-pio.patch b/packages/linux/linux-handhelds-2.6-2.6.16/block-pio.patch new file mode 100644 index 0000000000..294140b6e8 --- /dev/null +++ b/packages/linux/linux-handhelds-2.6-2.6.16/block-pio.patch @@ -0,0 +1,146 @@ +On architectures where highmem isn't used, arguments to kmap/unmap are +simply thrown away without being evaluated. This is fine until a +wrapper function is written. Even though it got ignored in the end, +the arguments are evaulated. As asm/highmem.h is not included by +linux/highmem.h when CONFIG_HIGHMEM is off, none of KM_* constants get +defined which results in error if those are evaluated. + +This patch makes linux/highmem.h include asm/kmap_types.h regardless +of CONFIG_HIGHMEM. To deal with the same problem, crypto subsystem +used to include asm/kmap_types.h directly. This patch kills it. + +Signed-off-by: Tejun Heo <htejun@gmail.com> + +--- + + crypto/internal.h | 1 - + include/linux/highmem.h | 1 + + 2 files changed, 1 insertions(+), 1 deletions(-) + +4e0462fa09e87da901867f37b2c7311ef714c3e7 +diff --git a/crypto/internal.h b/crypto/internal.h +index 959e602..4188672 100644 +--- a/crypto/internal.h ++++ b/crypto/internal.h +@@ -21,7 +21,6 @@ + #include <linux/kernel.h> + #include <linux/rwsem.h> + #include <linux/slab.h> +-#include <asm/kmap_types.h> + + extern struct list_head crypto_alg_list; + extern struct rw_semaphore crypto_alg_sem; +diff --git a/include/linux/highmem.h b/include/linux/highmem.h +index 6bece92..c605f01 100644 +--- a/include/linux/highmem.h ++++ b/include/linux/highmem.h +@@ -6,6 +6,7 @@ + #include <linux/mm.h> + + #include <asm/cacheflush.h> ++#include <asm/kmap_types.h> + + #ifdef CONFIG_HIGHMEM + + +When block requests are handled via DMA dma mapping functions take +care of cache coherency. Unfortunately, cache coherencly was left +unhandled until now for block PIOs, resulting in data corruption +issues on architectures with aliasing caches. + +All block PIO operations use kmap/unmap to access target memory area +and the mapping/unmapping points are the perfect places for cache +flushing. kmap/unmap are to PIO'ing cpus what dma_map/unmap are to +DMAing devices. + +This patch implements blk kmap helpers which additionally take +@direction argument and deal with cache coherency. + +Signed-off-by: Tejun Heo <htejun@gmail.com> + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 02a585f..1040029 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -17,6 +17,10 @@ + + #include <asm/scatterlist.h> + ++/* for PIO kmap helpers */ ++#include <linux/highmem.h> ++#include <linux/dma-mapping.h> ++ + struct request_queue; + typedef struct request_queue request_queue_t; + struct elevator_queue; +@@ -812,6 +816,40 @@ static inline void put_dev_sector(Sector + page_cache_release(p.v); + } + ++/* ++ * PIO kmap helpers. ++ * ++ * Block PIO requires cache flushes on architectures with aliasing ++ * caches. If a driver wants to perform PIO on a user-mappable page ++ * (page cache page), it MUST use one of the following kmap/unmap ++ * helpers unless it handles cache coherency itself. ++ */ ++static inline void * blk_kmap_atomic(struct page *page, enum km_type type, ++ enum dma_data_direction dir) ++{ ++ return kmap_atomic(page, type); ++} ++ ++static inline void blk_kunmap_atomic(void *addr, enum km_type type, ++ enum dma_data_direction dir) ++{ ++ if (dir == DMA_BIDIRECTIONAL || dir == DMA_FROM_DEVICE) ++ flush_dcache_page(kmap_atomic_to_page(addr)); ++ kunmap_atomic(addr, type); ++} ++ ++static inline void * blk_kmap(struct page *page, enum dma_data_direction dir) ++{ ++ return kmap(page); ++} ++ ++static inline void blk_kunmap(struct page *page, enum dma_data_direction dir) ++{ ++ if (dir == DMA_BIDIRECTIONAL || dir == DMA_FROM_DEVICE) ++ flush_dcache_page(page); ++ kunmap(page); ++} ++ + struct work_struct; + int kblockd_schedule_work(struct work_struct *work); + void kblockd_flush(void); +diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c +index 62ebefd..24d5e56 100644 +--- a/drivers/ide/ide-taskfile.c ++++ b/drivers/ide/ide-taskfile.c +@@ -260,6 +260,7 @@ static void ide_pio_sector(ide_drive_t * + { + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg = hwif->sg_table; ++ enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + struct page *page; + #ifdef CONFIG_HIGHMEM + unsigned long flags; +@@ -277,7 +278,7 @@ static void ide_pio_sector(ide_drive_t * + #ifdef CONFIG_HIGHMEM + local_irq_save(flags); + #endif +- buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; ++ buf = blk_kmap_atomic(page, KM_BIO_SRC_IRQ, dir) + offset; + + hwif->nleft--; + hwif->cursg_ofs++; +@@ -293,7 +294,7 @@ static void ide_pio_sector(ide_drive_t * + else + taskfile_input_data(drive, buf, SECTOR_WORDS); + +- kunmap_atomic(buf, KM_BIO_SRC_IRQ); ++ blk_kunmap_atomic(buf, KM_BIO_SRC_IRQ, dir); + #ifdef CONFIG_HIGHMEM + local_irq_restore(flags); + #endif |