Wednesday, June 13, 2012

module_params with callback

module_param() creates a subdirectory under sys/module/.
module_param(name, type, perm);

This creates
/sys/module/module name/parameters/name

You can change the name from cmdline by
echo 1 >  /sys/module/module name/parameters/name

This will update the name variable. But there is no way to notify your module that “name” has changed.
Now you will be thinking why we want to know when it has changed, if I have the changed value in name variable.

But there are certain rare instance. I say it rare because there are only 6 instance of the maro used in drivers/ folder in linux kerne 3.0.15.

grep -nr module_param_cb drivers/
drivers/acpi/sysfs.c:162:module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644);
drivers/acpi/sysfs.c:163:module_param_cb(debug_level, &param_ops_debug_level, &acpi_dbg_level, 0644);
drivers/char/ipmi/ipmi_watchdog.c:304:module_param_cb(action, &param_ops_str, action_op, 0644);
drivers/char/ipmi/ipmi_watchdog.c:308:module_param_cb(preaction, &param_ops_str, preaction_op, 0644);
drivers/char/ipmi/ipmi_watchdog.c:312:module_param_cb(preop, &param_ops_str, preop_op, 0644);
drivers/usb/otg/otg-wakelock.c:134:module_param_cb(enabled, &enabled_param_ops, &enabled, 0644);

One example scenario can be as follows
Whenever name is set to 1, you have to write a particular value in to a hardware register. How can you do this if the change of name variable is not notified to you?

For that you have macro module_param_cb in kernel,

+/* Returns 0, or -errno.  arg is in kp->arg. */
+static int param_set_ramdump_enable(const char *val,
+                               const struct kernel_param *kp)
+{
+
+       int ret = param_set_bool(val, kp);
+       printk(KERN_INFO, "%s ramdump_enable = %d\n", __func__, ramdump_enable);
+
+       if (ramdump_enable)
+               cdebugger_set_upload_magic(0xDEAFABCD);
+       else
+               cdebugger_set_upload_magic(0);
+
+       return ret;
+}
+
+static struct kernel_param_ops params_ops_ramdump_enable = {
+       .set = param_set_ramdump_enable,
+       .get = param_get_uint,
+};
+module_param_cb(enable, &params_ops_ramdump_enable, &ramdump_enable, 0644);