Messages in this thread Patch in this message | | | Date | Thu, 4 Nov 2004 16:45:28 +0900 | From | Tejun Heo <> | Subject | Re: [PATCH 2.6.10-rc1 2/4] driver-model: devparam expanded to accept direct per-device parameters via @args argument |
| |
ma_02_devparam_set_by_args.patch
This patch implements set_devparams_by_args() and expands related functions to accept an const char * @args argument. This enables setting per-device parameters directly from argument string rather than from parameters stored while booting or loading modules.
Signed-off-by: Tejun Heo <tj@home-tj.org>
Index: linux-export/drivers/base/bus.c =================================================================== --- linux-export.orig/drivers/base/bus.c 2004-11-04 14:40:01.000000000 +0900 +++ linux-export/drivers/base/bus.c 2004-11-04 14:40:01.000000000 +0900 @@ -287,7 +287,8 @@ void device_bind_driver(struct device * * If we find a match, we call @drv->probe(@dev) if it exists, and * call device_bind_driver() above. */ -int driver_probe_device(struct device_driver * drv, struct device * dev) +int driver_probe_device(struct device_driver * drv, struct device * dev, + const char *args) { int error; @@ -296,7 +297,7 @@ int driver_probe_device(struct device_dr dev->driver = drv; - if ((error = devparam_set_params(dev)) != 0) + if ((error = devparam_set_params(dev, args)) != 0) goto devparam_fail; if (drv->probe) { @@ -338,7 +339,7 @@ int device_attach(struct device * dev) if (dev_autoattach && bus->match) { list_for_each(entry, &bus->drivers.list) { struct device_driver * drv = to_drv(entry); - error = driver_probe_device(drv, dev); + error = driver_probe_device(drv, dev, NULL); if (!error) /* success, driver matched */ return 1; @@ -378,7 +379,7 @@ void driver_attach(struct device_driver list_for_each(entry, &bus->devices.list) { struct device * dev = container_of(entry, struct device, bus_list); if (!dev->driver) { - error = driver_probe_device(drv, dev); + error = driver_probe_device(drv, dev, NULL); if (error && (error != -ENODEV)) /* driver matched but the probe failed */ printk(KERN_WARNING Index: linux-export/drivers/base/deviceparam.c =================================================================== --- linux-export.orig/drivers/base/deviceparam.c 2004-11-04 14:39:59.000000000 +0900 +++ linux-export/drivers/base/deviceparam.c 2004-11-04 14:40:01.000000000 +0900 @@ -9,6 +9,7 @@ #include <linux/deviceparam.h> #include <linux/device.h> #include <linux/module.h> +#include <linux/ctype.h> #if 0 #define pdebug(fmt, args...) printk("[%-25s] " fmt, __FUNCTION__ , ##args) @@ -800,27 +801,113 @@ static int set_devparams_by_storedparams return 0; } -int devparam_set_params(struct device *dev) +static int set_devparams_by_args(struct device *dev, char *args) { struct device_driver *drv = dev->driver; + int which, i, err; + long **bitmaps; size_t size; - int which, ret; struct device_paramset_def *setdef; + char *param, *val; + + /* Allocate bitmaps */ + err = -ENOMEM; + + size = drv->nr_paramsets * sizeof(bitmaps[0]); + if (!(bitmaps = kmalloc(size, GFP_KERNEL))) + goto out; + memset(bitmaps, 0, size); + + for_each_setdef(which, setdef, drv) { + size = ALIGN(setdef->nr_defs, 8) / 8; + if (!(bitmaps[which] = kmalloc(size, GFP_KERNEL))) + goto out; + memset(bitmaps[which], 0, size); + } + + /* Okay, parse */ + while (*args) { + int ret; + args = param_next_arg(args, ¶m, &val); + pdebug("param=\"%s\" val=\"%s\"\n", param, val); + ret = parse_one_devparam(param, param, val, + drv, NULL, dev, bitmaps); + if (ret == -ENOENT) + printk(KERN_ERR "Device params: Unknown parameter " + "`%s'\n", param); + } + + /* Finalize */ + for_each_setdef(which, setdef, drv) { + for (i = 0; i < setdef->nr_defs; i++) { + struct device_param_def *def = &setdef->defs[i]; + + if (test_bit(i, bitmaps[which]) || def->dfl == NULL) + continue; + + err = call_set(def, NULL, dev->paramsets[which]); + if (err < 0) + goto out; + } + } - pdebug("invoked for %s\n", drv->name); + err = 0; + + out: + if (bitmaps) { + for (i = 0; i < drv->nr_paramsets; i++) + kfree(bitmaps[i]); + kfree(bitmaps); + } + return err; +} + +int devparam_set_params(struct device *dev, const char *args) +{ + struct device_driver *drv = dev->driver; + char *buf; + size_t size, args_len; + int which, ret; + struct device_paramset_def *setdef; + pdebug("invoked for %s args=\"%s\"\n", drv->name, args); dev->paramsets = NULL; dev->bus_paramset = NULL; dev->paramset_idx = -1; - if (drv->nr_paramsets == 0) + /* Trim leading white spaces */ + if (args) { + while (isspace(*args)) + args++; + } + + if (drv->nr_paramsets == 0) { + if (args && *args) + printk(KERN_ERR "Device params: %s does not take any " + "device parameters\n", drv->name); return 0; + } size = drv->nr_paramsets * sizeof(void *); - if ((dev->paramsets = kmalloc(size, GFP_KERNEL)) == NULL) + args_len = args ? strlen(args) + 1 : 0; + + dev->paramsets = kmalloc(size + args_len, GFP_KERNEL); + if (dev->paramsets == NULL) return -ENOMEM; + memset(dev->paramsets, 0, size); + buf = NULL; + if (args) { + char *p; + buf = (char *)dev->paramsets + size; + memcpy(buf, args, args_len); + /* Trim tailing white spaces */ + p = buf + args_len - 2; + while (p >= buf && isspace(*p)) + *p-- = '\0'; + } + for_each_setdef(which, setdef, drv) { void *ps; if ((ps = kmalloc(setdef->size, GFP_KERNEL)) == NULL) { @@ -831,7 +918,12 @@ int devparam_set_params(struct device *d dev->paramsets[which] = ps; } - if ((ret = set_devparams_by_storedparams(dev)) < 0) + if (buf) + ret = set_devparams_by_args(dev, buf); + else + ret = set_devparams_by_storedparams(dev); + + if (ret < 0) goto free_out; if (drv->bus && drv->bus->paramset_def) Index: linux-export/include/linux/device.h =================================================================== --- linux-export.orig/include/linux/device.h 2004-11-04 14:40:01.000000000 +0900 +++ linux-export/include/linux/device.h 2004-11-04 14:40:01.000000000 +0900 @@ -342,7 +342,8 @@ extern int device_for_each_child(struct * Manual binding of a device to driver. See drivers/base/bus.c * for information on use. */ -extern int driver_probe_device(struct device_driver * drv, struct device * dev); +extern int driver_probe_device(struct device_driver * drv, struct device * dev, + const char *args); extern void device_bind_driver(struct device * dev); extern void device_release_driver(struct device * dev); extern int device_attach(struct device * dev); Index: linux-export/include/linux/deviceparam.h =================================================================== --- linux-export.orig/include/linux/deviceparam.h 2004-11-04 14:39:59.000000000 +0900 +++ linux-export/include/linux/deviceparam.h 2004-11-04 14:40:01.000000000 +0900 @@ -220,7 +220,7 @@ int devparam_module_init(struct module * int devparam_unknown_modparam(char *name, char *val, void *arg); void devparam_module_done(struct module *module); -int devparam_set_params(struct device *dev); +int devparam_set_params(struct device *dev, const char *args); void devparam_release_params(struct device *dev); #endif /*__LINUX_DEVICEPARAM_H*/ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |