[PATCH] ide: trying to enable DMA may cause an oops
Linux Kernel Mailing List <[email protected]> Fri, 12 May 2006 18:59:49 GMT
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
commit 4abe1e2e6091d1f91fa68f7094cc44fe5c7e90c3 tree 91d11958c082096c4abe151c46cef3ff5cd1abb9 parent 78344504ec280716131d118cd488e84993f84fa3 author Willy TARREAU <willy@pcw.(none)> Sun, 07 May 2006 23:48:50 +0200 committer Willy TARREAU <willy@pcw.(none)> Sun, 07 May 2006 23:48:50 +0200 [PATCH] ide: trying to enable DMA may cause an oops If DMA is disabled on the interface at boot time, then later calling config_drive_for_dma() to try to enable it will cause an oops because hwif->ide_dma_off_quietly will be NULL. The workaround is to make those *ide_dma* functions point to a dummy one when DMA is disabled. Originally reported by Glenn Wurster, and been running on my systems since 2.4.23. Signed-off-by: Willy Tarreau <[email protected]> - Willy drivers/ide/ide-dma.c | 29 +++++++++++++++++++++++++++++ drivers/ide/setup-pci.c | 1 + include/linux/ide.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 7f408ea..9431392 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -567,6 +567,18 @@ static int dma_timer_expiry (ide_drive_t } /** + * __ide_dma_no_op - dummy DMA function. + * + * This empty function prevents non-DMA controllers from causing an oops. + */ + +int __ide_dma_no_op (void) +{ + return 0; +} + + +/** * __ide_dma_host_off - Generic DMA kill * @drive: drive to control * @@ -1215,3 +1227,20 @@ void ide_setup_dma (ide_hwif_t *hwif, un } EXPORT_SYMBOL_GPL(ide_setup_dma); + +/* + * For IDE interfaces that do not support DMA, we still need to + * initialize some pointers to dummy functions. + */ +void ide_setup_no_dma (ide_hwif_t *hwif) +{ + if (!hwif->ide_dma_off_quietly) + hwif->ide_dma_off_quietly = (int (*)(ide_drive_t *))&__ide_dma_no_op; + if (!hwif->ide_dma_host_off) + hwif->ide_dma_host_off = (int (*)(ide_drive_t *))&__ide_dma_no_op; + if (!hwif->ide_dma_host_on) + hwif->ide_dma_host_on = (int (*)(ide_drive_t *))&__ide_dma_no_op; +} + +EXPORT_SYMBOL_GPL(ide_setup_no_dma); + diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 5c14475..3ba9c82 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -507,6 +507,7 @@ static void ide_hwif_setup_dma(struct pc } else { printk(KERN_INFO "%s: %s Bus-Master DMA disabled " "(BIOS)\n", hwif->name, d->name); + ide_setup_no_dma(hwif); } } } diff --git a/include/linux/ide.h b/include/linux/ide.h index f890c49..ed7db20 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1691,6 +1691,7 @@ extern void ide_destroy_dmatable(ide_dri extern ide_startstop_t ide_dma_intr(ide_drive_t *); extern int ide_release_dma(ide_hwif_t *); extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int); +extern void ide_setup_no_dma(ide_hwif_t *); extern int __ide_dma_host_off(ide_drive_t *); extern int __ide_dma_off_quietly(ide_drive_t *); @@ -1713,6 +1714,7 @@ extern int __ide_dma_timeout(ide_drive_t #else static inline void ide_setup_dma(ide_hwif_t *x, unsigned long y, unsigned int z) {;} static inline void ide_release_dma(ide_hwif_t *x) {;} +static inline void ide_setup_no_dma(ide_hwif_t *x) {;} #endif extern void hwif_unregister(ide_hwif_t *);