[PATCH] ide-dma.c, kernel 2.4.23

From: Glenn Wurster
Date: Sun Dec 07 2003 - 18:01:44 EST



Greetings.

Attached is a small patch to fix a serious Oops bug in the IDE/DMA
drivers. It has been written against 2.4.23. The problem stems from
a null function pointer which is called during configuration of the
IDE controller. The function pointer is NULL iff DMA is not available
for the drive, so the problem will not be seen on DMA capable IDE
controllers.

I am not subscribed, so please CC me on any followup e-mails. If you
need more information or wish changes to the patch, you can contact me
directly. Furthermore, if another patch to fix the same problem has
already been discussed, I would be glad to test it if someone forwards
me a copy.

I can be reached at gwurster@xxxxxxxxxxxxxxx

The patch has been tested against both systems I own, both x86. One
with a DMA capable IDE controller, the other one (which caused the
oops) without.

Glenn Wurster
Glenn Wurster (gwurster@xxxxxxxxxxxxxxx)
Avoid NULL function pointer reference on IDE controllers without DMA support.
diff -Naur linux-2.4.23/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- linux-2.4.23/drivers/ide/ide-dma.c Mon Aug 25 11:44:41 2003
+++ linux/drivers/ide/ide-dma.c Sun Dec 7 04:21:33 2003
@@ -566,6 +566,20 @@
}

/**
+ * __ide_dma_no_op - Empty DMA function.
+ *
+ * Empty DMA function for controllers that do not support DMA.
+ */
+
+int __ide_dma_no_op (void)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(__ide_dma_no_op);
+
+
+/**
* __ide_dma_host_off - Generic DMA kill
* @drive: drive to control
*
@@ -1214,3 +1228,19 @@
}

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 -Naur linux-2.4.23/drivers/ide/setup-pci.c linux/drivers/ide/setup-pci.c
--- linux-2.4.23/drivers/ide/setup-pci.c Mon Aug 25 11:44:41 2003
+++ linux/drivers/ide/setup-pci.c Fri Dec 5 07:10:50 2003
@@ -507,6 +507,7 @@
} else {
printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
"(BIOS)\n", hwif->name, d->name);
+ ide_setup_no_dma(hwif);
}
}
}
diff -Naur linux-2.4.23/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.4.23/include/linux/ide.h Fri Nov 28 18:26:21 2003
+++ linux/include/linux/ide.h Fri Dec 5 06:43:46 2003
@@ -1692,7 +1692,10 @@
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 void ide_setup_dma_off(ide_hwif_t *);

+extern int __ide_dma_no_op(void);
extern int __ide_dma_host_off(ide_drive_t *);
extern int __ide_dma_off_quietly(ide_drive_t *);
extern int __ide_dma_off(ide_drive_t *);
@@ -1713,6 +1716,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_setup_no_dma(ide_hwif_t *x) {;}
static inline void ide_release_dma(ide_hwif_t *x) {;}
#endif