Patch from abbotti@mev.co.uk (Ian Abbott):
authorFrank Mori Hess <fmhess@speakeasy.net>
Mon, 12 Jun 2006 01:10:38 +0000 (01:10 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Mon, 12 Jun 2006 01:10:38 +0000 (01:10 +0000)
The (few) module parameters used by comedi (for debugging and for specifying
irq_mask or irq_list for some PCMCIA drivers) haven't worked since kernel
2.6.11. If you try and specify a module parameter when loading a module, the
module fails to load due to missing symbols.

I have implemented a linux/moduleparam.h compatibility header using code
borrowed from the 2.4.25 kernel with some additions, and a patch to use it.

The module_param() macro has been implemented for 2.4 kernels.  Unfortunately,
it is not possible to implement module_param_array() for 2.4 kernels, so I
implemented a similar MODULE_PARAM_ARRAY() macro instead.  The third parameter
is different, being the length of the array rather than a (optionally null)
pointer to a variable set to the number of elements of the array that have been
filled in (that information is not available in 2.4 so I thought it best to omit
it entirely).  There is one restriction on the "length of array" parameter; it
has to be a decimal number (or a macro that expands to a decimal number), not a
fancy C expression, otherwise insmod won't parse it properly (if at all!).

comedi/comedi_fops.c
comedi/drivers/cb_das16_cs.c
comedi/drivers/comedi_bond.c
comedi/drivers/das08_cs.c
comedi/drivers/ni_daq_dio24.c
comedi/drivers/ni_labpc_cs.c
comedi/drivers/quatech_daqp_cs.c
include/linux/module.h
include/linux/moduleparam.h [new file with mode: 0644]

index 0d392995c75391cca10600a6924f1051a5de8be6..79a09883cc07ca0ca1ab51d1bac69de1a8d98c50 100644 (file)
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_COMEDI_DEBUG
 int comedi_debug;
-MODULE_PARM(comedi_debug, "i");
+module_param(comedi_debug, int, 0644);
 #endif
 
 comedi_device *comedi_devices;
index 6ef4bfcb8e3a97acaead6a5c86ae8a507b61e454..883b95bb10dd4ac4bbc1af77a5ba82102be9f2cc 100644 (file)
@@ -620,7 +620,7 @@ static int das16cs_timer_insn_config(comedi_device *dev,comedi_subdevice *s,
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0644);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
index 57c601ce198cf1e56b1bb680a058df0bdb625254..d8be8f95694f69e39646b2b49ce0c844a0f95331 100644 (file)
@@ -103,7 +103,7 @@ Configuration Options:
 #endif
 
 int debug = 0;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful only to developers probably.");
 
 #define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
index b3da02357df0c9924098ab6ac60f37ece225fab9..ec5e34bc2dfa00ae32d13620870f2a6e852384f7 100644 (file)
@@ -129,7 +129,7 @@ static int das08_cs_attach(comedi_device *dev,comedi_devconfig *it)
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0644);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
index ee816342f9fa98a2a8e962c5fd1f0ddc61fadc9a..f8baf8384b082774871fab0075cac51a8003e1ce 100644 (file)
@@ -210,7 +210,7 @@ static int dio24_detach(comedi_device *dev)
 */
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0644);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "ni_daq_dio24.c, based on dummy_cs.c";
index 31dc5a33e6285ebf9956dcfb2ec47eb94c12acab..e9d70787a1761dabab412a63c9f60d6cbe4b8a32 100644 (file)
@@ -144,7 +144,7 @@ static int labpc_attach(comedi_device *dev, comedi_devconfig *it)
 */
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0644);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "ni_labpc.c, based on dummy_cs.c 1.31 2001/08/24 12:13:13";
index 9cbbb325ed1bb8d6c74739d5c9ca5a01d0fe87f2..ebf09573e538b62d48defa951730097dddb8ef51 100644 (file)
@@ -67,7 +67,7 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0644);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "quatech_daqp_cs.c 1.10 2003/04/21 (Brent Baccala)";
@@ -154,10 +154,11 @@ static local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */ };
 /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
 static u_int irq_mask = 0xdeb8;
 /* Newer, simpler way of listing specific interrupts */
-static int irq_list[4] = { -1 };
+#define IRQ_LIST_LEN   4
+static int irq_list[IRQ_LIST_LEN] = { -1 };
 
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
+module_param(irq_mask, uint, 0444);
+MODULE_PARAM_ARRAY(irq_list, int, IRQ_LIST_LEN, 0444);
 
 /*====================================================================*/
 
index 661f34ee3f609678bd75b00767071eda231596a9..d692a17b507d2d3ba02069942f5f04dc8cad98d5 100644 (file)
@@ -34,6 +34,10 @@ static inline void module_put(struct module *module)
 #define MOD_IN_USE (0)
 #endif
 
+#ifndef module_param
+#include <linux/moduleparam.h>
+#endif
+
 #endif /* _COMPAT_MODULE_H */
 
 
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
new file mode 100644 (file)
index 0000000..4fbbdb7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * moduleparam.h compatibility header
+ */
+
+#ifndef _COMPAT_MODULEPARAM_H
+#define _COMPAT_MODULEPARAM_H
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25)
+/* We should have <linux/moduleparam.h> so include it. */
+/* (We don't care about 2.5 kernels.) */
+#include_next <linux/moduleparam.h>
+#else
+/* Need to fake contents of <linux/moduleparam.h> */
+#include <linux/module.h>
+
+#define module_param(name, type, perm) \
+       static inline void *__check_existence_##name(void) { return &name; } \
+       MODULE_PARM(name, _MODULE_PARM_STRING_##type)
+
+#define _MODULE_PARM_STRING_byte       "b"
+#define _MODULE_PARM_STRING_short      "h"
+#define _MODULE_PARM_STRING_ushort     "h"
+#define _MODULE_PARM_STRING_int                "i"
+#define _MODULE_PARM_STRING_uint       "i"
+#define _MODULE_PARM_STRING_long       "l"
+#define _MODULE_PARM_STRING_ulong      "l"
+#define _MODULE_PARM_STRING_bool       "i"
+
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+/*
+ * Extend <linux/moduleparam.h> support for 2.4.
+ *
+ * Additionally supported:
+ *     'charp' parameters
+ * Not supported:
+ *     'invbool' parameters
+ *     module_param_named()
+ *     module_param_array()
+ *     module_param_array_named()
+ */
+
+/* Support charp parameters */
+#define _MODULE_PARM_STRING_charp      "s"
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && \
+                          (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+/*
+ * 2.6 kernels before 2.6.10 use an unsigned int lvalue for third parameter of
+ * module_param_array() instead of the pointer to unsigned int used in
+ * 2.6.10 onwards.  Comedi code goes with 2.6.10, so cope with the change here.
+ * To make things more difficult, the pointer can be null and we need to
+ * substitute that with a pointer to a unique lvalue.
+ */
+
+#undef module_param_array_named
+#define module_param_array_named(name, array, type, nump, perm)                \
+       static unsigned int __missing_num_##name;                       \
+       static struct kparam_array __param_arr_##name                   \
+       = { ARRAY_SIZE(array), nump ?: &__missing_num_##name,           \
+           param_set_##type, param_get_##type,                         \
+           sizeof(array[0]), array };                                  \
+       module_param_call(name, param_array_set, param_array_get,       \
+               &__param_arr_##name, perm)
+
+#undef module_param_array
+#define module_param_array(name, type, nump, perm)             \
+       module_param_array_named(name, name, type, nump, perm)
+
+#endif /* (L_V_C >= K_V(2,6,0)) && (L_V_C < K_V(2,6,10)) */
+
+/*
+ * Define a Comedi-specific macro MODULE_PARAM_ARRAY(name,type,len,perm)
+ * supported on 2.4 and 2.6 kernels, because
+ * module_param_array(name,type,nump,perm) * is only available for 2.6.
+ *
+ * name - Name of module parameter and array variable.
+ * type - Module parameter type: byte, short, ushort, int, uint, long, ulong,
+ *        bool, charp.  Note that invbool is not supported.
+ * len  - Length of array variable; needed for 2.4 kernel; ignored for 2.6
+ *        kernel.  Note that this must be specified as a sequence of decimal
+ *        digits or a macro that expands to a sequence of decimal digits.
+ *        Using ARRAY_SIZE() or sizeof() is not allowed.
+ * perm - Permissions for module parameter in sysfs, e.g. 0444.  Only used
+ *        for 2.6 kernels.
+ */
+#ifdef module_param_array
+#define MODULE_PARAM_ARRAY(name,type,len,perm) \
+       module_param_array(name,type,0,perm)
+#else
+#define MODULE_PARAM_ARRAY(name,type,len,perm) \
+       static inline void *__check_existence_##name(void) \
+               { return &name[0]; } \
+       MODULE_PARM(name, "1-" __MODULE_STRING(len) _MODULE_PARM_STRING_##type)
+#endif /* module_param_array */
+
+#endif /* _COMPAT_MODULEPARAM_H */
+