From e105b8bfc769b0545b6f0f395179d1e43cbee822 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2008 10:51:07 -0700 Subject: sysfs: add /sys/dev/{char,block} to lookup sysfs path by major:minor Why?: There are occasions where userspace would like to access sysfs attributes for a device but it may not know how sysfs has named the device or the path. For example what is the sysfs path for /dev/disk/by-id/ata-ST3160827AS_5MT004CK? With this change a call to stat(2) returns the major:minor then userspace can see that /sys/dev/block/8:32 links to /sys/block/sdc. What are the alternatives?: 1/ Add an ioctl to return the path: Doable, but sysfs is meant to reduce the need to proliferate ioctl interfaces into the kernel, so this seems counter productive. 2/ Use udev to create these symlinks: Also doable, but it adds a udev dependency to utilities that might be running in a limited environment like an initramfs. 3/ Do a full-tree search of sysfs. [kay.sievers@vrfy.org: fix duplicate registrations] [kay.sievers@vrfy.org: cleanup suggestions] Cc: Neil Brown Cc: Tejun Heo Acked-by: Kay Sievers Reviewed-by: SL Baur Acked-by: Kay Sievers Acked-by: Mark Lord Acked-by: H. Peter Anvin Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-dev b/Documentation/ABI/testing/sysfs-dev new file mode 100644 index 0000000..a9f2b8b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-dev @@ -0,0 +1,20 @@ +What: /sys/dev +Date: April 2008 +KernelVersion: 2.6.26 +Contact: Dan Williams +Description: The /sys/dev tree provides a method to look up the sysfs + path for a device using the information returned from + stat(2). There are two directories, 'block' and 'char', + beneath /sys/dev containing symbolic links with names of + the form ":". These links point to the + corresponding sysfs path for the given device. + + Example: + $ readlink /sys/dev/block/8:32 + ../../block/sdc + + Entries in /sys/dev/char and /sys/dev/block will be + dynamically created and destroyed as devices enter and + leave the system. + +Users: mdadm diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 7f27b8f..9e9c348 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -248,6 +248,7 @@ The top level sysfs directory looks like: block/ bus/ class/ +dev/ devices/ firmware/ net/ @@ -274,6 +275,11 @@ fs/ contains a directory for some filesystems. Currently each filesystem wanting to export attributes must create its own hierarchy below fs/ (see ./fuse.txt for an example). +dev/ contains two directories char/ and block/. Inside these two +directories there are symlinks named :. These symlinks +point to the sysfs directory for the given device. /sys/dev provides a +quick way to lookup the sysfs interface for a device from the result of +a stat(2) operation. More information can driver-model specific features can be found in Documentation/driver-model/. diff --git a/block/genhd.c b/block/genhd.c index 9074f38..24e3fc9 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -370,7 +370,10 @@ static struct kobject *base_probe(dev_t devt, int *part, void *data) static int __init genhd_device_init(void) { - int error = class_register(&block_class); + int error; + + block_class.dev_kobj = sysfs_dev_block_kobj; + error = class_register(&block_class); if (unlikely(error)) return error; bdev_map = kobj_map_init(base_probe, &block_class_lock); diff --git a/drivers/base/class.c b/drivers/base/class.c index e085af0..71ce3ff 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -148,6 +148,10 @@ int class_register(struct class *cls) if (error) return error; + /* set the default /sys/dev directory for devices of this class */ + if (!cls->dev_kobj) + cls->dev_kobj = sysfs_dev_char_kobj; + #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) /* let the block class directory show up in the root of sysfs */ if (cls != &block_class) diff --git a/drivers/base/core.c b/drivers/base/core.c index ee0a51a..be9aba4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -27,6 +27,9 @@ int (*platform_notify)(struct device *dev) = NULL; int (*platform_notify_remove)(struct device *dev) = NULL; +static struct kobject *dev_kobj; +struct kobject *sysfs_dev_char_kobj; +struct kobject *sysfs_dev_block_kobj; #ifdef CONFIG_BLOCK static inline int device_is_not_partition(struct device *dev) @@ -776,6 +779,54 @@ int dev_set_name(struct device *dev, const char *fmt, ...) EXPORT_SYMBOL_GPL(dev_set_name); /** + * device_to_dev_kobj - select a /sys/dev/ directory for the device + * @dev: device + * + * By default we select char/ for new entries. Setting class->dev_obj + * to NULL prevents an entry from being created. class->dev_kobj must + * be set (or cleared) before any devices are registered to the class + * otherwise device_create_sys_dev_entry() and + * device_remove_sys_dev_entry() will disagree about the the presence + * of the link. + */ +static struct kobject *device_to_dev_kobj(struct device *dev) +{ + struct kobject *kobj; + + if (dev->class) + kobj = dev->class->dev_kobj; + else + kobj = sysfs_dev_char_kobj; + + return kobj; +} + +static int device_create_sys_dev_entry(struct device *dev) +{ + struct kobject *kobj = device_to_dev_kobj(dev); + int error = 0; + char devt_str[15]; + + if (kobj) { + format_dev_t(devt_str, dev->devt); + error = sysfs_create_link(kobj, &dev->kobj, devt_str); + } + + return error; +} + +static void device_remove_sys_dev_entry(struct device *dev) +{ + struct kobject *kobj = device_to_dev_kobj(dev); + char devt_str[15]; + + if (kobj) { + format_dev_t(devt_str, dev->devt); + sysfs_remove_link(kobj, devt_str); + } +} + +/** * device_add - add device to device hierarchy. * @dev: device. * @@ -829,6 +880,10 @@ int device_add(struct device *dev) error = device_create_file(dev, &devt_attr); if (error) goto ueventattrError; + + error = device_create_sys_dev_entry(dev); + if (error) + goto devtattrError; } error = device_add_class_symlinks(dev); @@ -873,6 +928,9 @@ int device_add(struct device *dev) device_remove_class_symlinks(dev); SymlinkError: if (MAJOR(dev->devt)) + device_remove_sys_dev_entry(dev); + devtattrError: + if (MAJOR(dev->devt)) device_remove_file(dev, &devt_attr); ueventattrError: device_remove_file(dev, &uevent_attr); @@ -948,8 +1006,10 @@ void device_del(struct device *dev) device_pm_remove(dev); if (parent) klist_del(&dev->knode_parent); - if (MAJOR(dev->devt)) + if (MAJOR(dev->devt)) { + device_remove_sys_dev_entry(dev); device_remove_file(dev, &devt_attr); + } if (dev->class) { device_remove_class_symlinks(dev); @@ -1074,7 +1134,25 @@ int __init devices_init(void) devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); if (!devices_kset) return -ENOMEM; + dev_kobj = kobject_create_and_add("dev", NULL); + if (!dev_kobj) + goto dev_kobj_err; + sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); + if (!sysfs_dev_block_kobj) + goto block_kobj_err; + sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); + if (!sysfs_dev_char_kobj) + goto char_kobj_err; + return 0; + + char_kobj_err: + kobject_put(sysfs_dev_block_kobj); + block_kobj_err: + kobject_put(dev_kobj); + dev_kobj_err: + kset_unregister(devices_kset); + return -ENOMEM; } EXPORT_SYMBOL_GPL(device_for_each_child); @@ -1447,4 +1525,7 @@ void device_shutdown(void) dev->driver->shutdown(dev); } } + kobject_put(sysfs_dev_char_kobj); + kobject_put(sysfs_dev_block_kobj); + kobject_put(dev_kobj); } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 54a350c..6fbc8f5 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1792,6 +1792,11 @@ int __init usb_devio_init(void) usb_classdev_class = NULL; goto out; } + /* devices of this class shadow the major:minor of their parent + * device, so clear ->dev_kobj to prevent adding duplicate entries + * to /sys/dev + */ + usb_classdev_class->dev_kobj = NULL; usb_register_notify(&usbdev_nb); #endif diff --git a/include/linux/device.h b/include/linux/device.h index f71a78d..e49aa74 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -193,6 +193,7 @@ struct class { struct semaphore sem; /* locks children, devices, interfaces */ struct class_attribute *class_attrs; struct device_attribute *dev_attrs; + struct kobject *dev_kobj; int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); @@ -205,6 +206,8 @@ struct class { struct pm_ops *pm; }; +extern struct kobject *sysfs_dev_block_kobj; +extern struct kobject *sysfs_dev_char_kobj; extern int __must_check class_register(struct class *class); extern void class_unregister(struct class *class); extern int class_for_each_device(struct class *class, void *data, -- cgit v0.10.2 From 9f255651fb41c111ee35a2ae632df8ce9bd61def Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 6 May 2008 22:24:04 +0200 Subject: kobject: replace '/' with '!' in name Some (block) devices have a '/' in the name, and need special handling. Let's have that rule to the core, so we can remove it from the block class. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/lib/kobject.c b/lib/kobject.c index dcade05..7444015 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -216,13 +216,19 @@ static int kobject_add_internal(struct kobject *kobj) static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, va_list vargs) { - /* Free the old name, if necessary. */ - kfree(kobj->name); + const char *old_name = kobj->name; + char *s; kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs); if (!kobj->name) return -ENOMEM; + /* ewww... some of these buggers have '/' in the name ... */ + s = strchr(kobj->name, '/'); + if (s) + s[0] = '!'; + + kfree(old_name); return 0; } -- cgit v0.10.2 From ff543332ec5d23833994fca9e7789f067fb51221 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Tue, 20 May 2008 00:06:00 +0200 Subject: debugfs: Add a reference to the debugfs API documentation. Signed-off-by: Robert P. J. Day Cc: Jesper Juhl Signed-off-by: Greg Kroah-Hartman diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index df27132..ba106db 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -74,6 +74,9 @@ config DEBUG_FS debugging files into. Enable this option to be able to read and write to these files. + For detailed documentation on the debugfs API, see + Documentation/DocBook/filesystems. + If unsure, say N. config HEADERS_CHECK -- cgit v0.10.2 From 09857e35cdccf2457bb03c6d7595adc210a517cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 18:21:38 -0400 Subject: Firmware: fix typo in example code It's not like this stuff even builds right now, but this will make Randy's scripts happy :) Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c index 9392116..e6cf7a4 100644 --- a/samples/firmware_class/firmware_sample_firmware_class.c +++ b/samples/firmware_class/firmware_sample_firmware_class.c @@ -124,7 +124,7 @@ static int fw_setup_class_device(struct class_device *class_dev, class_dev->class_id[BUS_ID_SIZE-1] = '\0'; class_dev->dev = device; - class_dev->class = &firmware_class, + class_dev->class = &firmware_class; class_set_devdata(class_dev, fw_priv); retval = class_device_register(class_dev); if (retval) { -- cgit v0.10.2 From f79f060561d04a38d41e773ade9baafce3c96179 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: block: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/block/bsg.c b/block/bsg.c index 5fb9b0b..5a68b09 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -1044,7 +1044,8 @@ int bsg_register_queue(struct request_queue *q, struct device *parent, bcd->release = release; kref_init(&bcd->ref); dev = MKDEV(bsg_major, bcd->minor); - class_dev = device_create(bsg_class, parent, dev, "%s", devname); + class_dev = device_create_drvdata(bsg_class, parent, dev, NULL, + "%s", devname); if (IS_ERR(class_dev)) { ret = PTR_ERR(class_dev); goto put_dev; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index d1de68a..c04440c 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -277,8 +277,9 @@ aoechr_init(void) return PTR_ERR(aoe_class); } for (i = 0; i < ARRAY_SIZE(chardevs); ++i) - device_create(aoe_class, NULL, - MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name); + device_create_drvdata(aoe_class, NULL, + MKDEV(AOE_MAJOR, chardevs[i].minor), + NULL, chardevs[i].name); return 0; } diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 9d92636..d731ca4 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -686,8 +686,9 @@ static int __init pg_init(void) for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; if (dev->present) - device_create(pg_class, NULL, MKDEV(major, unit), - "pg%u", unit); + device_create_drvdata(pg_class, NULL, + MKDEV(major, unit), NULL, + "pg%u", unit); } err = 0; goto out; diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 5c74c35..673b8b2 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -979,10 +979,12 @@ static int __init pt_init(void) for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) { - device_create(pt_class, NULL, MKDEV(major, unit), - "pt%d", unit); - device_create(pt_class, NULL, MKDEV(major, unit + 128), - "pt%dn", unit); + device_create_drvdata(pt_class, NULL, + MKDEV(major, unit), NULL, + "pt%d", unit); + device_create_drvdata(pt_class, NULL, + MKDEV(major, unit + 128), NULL, + "pt%dn", unit); } goto out; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 45bee91..158eed4 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -303,7 +303,9 @@ static struct kobj_type kobj_pkt_type_wqueue = { static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) { if (class_pktcdvd) { - pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name); + pd->dev = device_create_drvdata(class_pktcdvd, NULL, + pd->pkt_dev, NULL, + "%s", pd->name); if (IS_ERR(pd->dev)) pd->dev = NULL; } -- cgit v0.10.2 From 47aa5793f78c274d51711f6a621fa6b02d4e6402 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: char: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index b9a30c3..33c466a 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -500,7 +500,8 @@ static int __init dsp56k_init_driver(void) err = PTR_ERR(dsp56k_class); goto out_chrdev; } - device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k"); + device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), + NULL, "dsp56k"); printk(banner); goto out; diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 5dc7440..9cb48fc 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp) } if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i), - "ipl%d", i); - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i + 1), - "stat%d", i); + device_create_drvdata(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i), + NULL, "ipl%d", i); + device_create_drvdata(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + NULL, "stat%d", i); for ( box = 0; box < ABS_MAX_BOXES; ++box ) { diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index c11a404..64e1c16 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device) entry->dev = dev; mutex_lock(®_list_mutex); - device_create(ipmi_class, device, dev, "ipmi%d", if_num); + device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num); list_add(&entry->link, ®_list); mutex_unlock(®_list_mutex); } diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7930fba..24637bb 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -4599,8 +4599,9 @@ static int __init istallion_module_init(void) istallion_class = class_create(THIS_MODULE, "staliomem"); for (i = 0; i < 4; i++) - device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - "staliomem%d", i); + device_create_drvdata(istallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); return 0; err_deinit: diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 71abb4c..3f2719b 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -813,7 +813,8 @@ static int lp_register(int nr, struct parport *port) if (reset) lp_reset(nr); - device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr); + device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, + "lp%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index b6772d6..c2dba82 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -989,9 +989,9 @@ static int __init chr_dev_init(void) mem_class = class_create(THIS_MODULE, "mem"); for (i = 0; i < ARRAY_SIZE(devlist); i++) - device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), - devlist[i].name); + device_create_drvdata(mem_class, NULL, + MKDEV(MEM_MAJOR, devlist[i].minor), + NULL, devlist[i].name); return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 6e1563c..999aa77 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); - misc->this_device = device_create(misc_class, misc->parent, dev, - "%s", misc->name); + misc->this_device = device_create_drvdata(misc_class, misc->parent, + dev, NULL, "%s", misc->name); if (IS_ERR(misc->this_device)) { err = PTR_ERR(misc->this_device); goto out; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e4a4fbd..f070ae7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1896,7 +1896,7 @@ static int cm4000_probe(struct pcmcia_device *link) return ret; } - device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i); + device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); return 0; } diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 6181f8a..0b5934b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -653,7 +653,8 @@ static int reader_probe(struct pcmcia_device *link) return ret; } - device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i); + device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL, + "cmx%d", i); return 0; } diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index f6e6aca..7af7a7e 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -752,8 +752,9 @@ static const struct file_operations pp_fops = { static void pp_attach(struct parport *port) { - device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), - "parport%d", port->number); + device_create_drvdata(ppdev_class, port->dev, + MKDEV(PP_MAJOR, port->number), + NULL, "parport%d", port->number); } static void pp_detach(struct parport *port) diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 505fcbe..47b8cf2 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp, static void bind_device(struct raw_config_request *rq) { device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), - "raw%d", rq->raw_minor); + device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), + NULL, "raw%d", rq->raw_minor); } /* @@ -283,7 +283,8 @@ static int __init raw_init(void) ret = PTR_ERR(raw_class); goto error_region; } - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl"); + device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, + "rawctl"); return 0; diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 0b799ac..3ce60df 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -444,7 +444,8 @@ scdrv_init(void) continue; } - device_create(snsc_class, NULL, dev, "%s", devname); + device_create_drvdata(snsc_class, NULL, dev, NULL, + "%s", devname); ia64_sn_irtr_intr_enable(scd->scd_nasid, 0 /*ignored */ , diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0243efb..45aeeea 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -4753,8 +4753,8 @@ static int __init stallion_module_init(void) if (IS_ERR(stallion_class)) printk("STALLION: failed to create class\n"); for (i = 0; i < 4; i++) - device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - "staliomem%d", i); + device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); return 0; err_unrtty: diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 82f6a8c..dc9202d 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -4045,7 +4045,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, else tty_line_name(driver, index, name); - return device_create(tty_class, device, dev, name); + return device_create_drvdata(tty_class, device, dev, NULL, name); } /** @@ -4323,20 +4323,22 @@ static int __init tty_init(void) if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) panic("Couldn't register /dev/tty driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, + "tty"); cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, + "console"); #ifdef CONFIG_UNIX98_PTYS cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); #endif #ifdef CONFIG_VT @@ -4344,7 +4346,7 @@ static int __init tty_init(void) if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) panic("Couldn't register /dev/tty0 driver\n"); - device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0"); + device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); vty_init(); #endif diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index eebfad2..c2ae52d 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -481,10 +481,10 @@ static struct class *vc_class; void vcs_make_sysfs(struct tty_struct *tty) { - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), - "vcs%u", tty->index + 1); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), - "vcsa%u", tty->index + 1); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), + NULL, "vcs%u", tty->index + 1); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), + NULL, "vcsa%u", tty->index + 1); } void vcs_remove_sysfs(struct tty_struct *tty) @@ -499,7 +499,7 @@ int __init vcs_init(void) panic("unable to get major %d for vcs device", VCS_MAJOR); vc_class = class_create(THIS_MODULE, "vc"); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs"); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa"); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); return 0; } diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index e5da98d..7a70a40 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) state[i].cur_part = 0; for (j = 0; j < MAX_PARTITIONS; ++j) state[i].part_stat_rwi[j] = VIOT_IDLE; - device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), - "iseries!vt%d", i); - device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), - "iseries!nvt%d", i); + device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), + NULL, "iseries!vt%d", i); + device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), + NULL, "iseries!nvt%d", i); printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " "resource %10.10s type %4.4s, model %3.3s\n", i, viotape_unitinfo[i].rsrcname, diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 935f1c2..e32a076 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -3425,9 +3425,10 @@ int register_con_driver(const struct consw *csw, int first, int last) if (retval) goto err; - con_driver->dev = device_create(vtconsole_class, NULL, - MKDEV(0, con_driver->node), - "vtcon%i", con_driver->node); + con_driver->dev = device_create_drvdata(vtconsole_class, NULL, + MKDEV(0, con_driver->node), + NULL, "vtcon%i", + con_driver->node); if (IS_ERR(con_driver->dev)) { printk(KERN_WARNING "Unable to create device for %s; " @@ -3535,9 +3536,10 @@ static int __init vtconsole_class_init(void) struct con_driver *con = ®istered_con_driver[i]; if (con->con && !con->dev) { - con->dev = device_create(vtconsole_class, NULL, - MKDEV(0, con->node), - "vtcon%i", con->node); + con->dev = device_create_drvdata(vtconsole_class, NULL, + MKDEV(0, con->node), + NULL, "vtcon%i", + con->node); if (IS_ERR(con->dev)) { printk(KERN_WARNING "Unable to create " diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 1e1b81e..51966cc 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -658,8 +658,9 @@ static int __devinit hwicap_setup(struct device *dev, int id, dev_err(dev, "cdev_add() failed\n"); goto failed3; } - /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ - device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id); + + device_create_drvdata(icap_class, dev, devt, NULL, + "%s%d", DRIVER_NAME, id); return 0; /* success */ failed3: -- cgit v0.10.2 From 6143b599700f7d6d7961e2de88f1486b2b19b1f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: coda: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Jan Harkes Signed-off-by: Greg Kroah-Hartman diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index e3eb355..40c36f7 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -362,8 +362,9 @@ static int init_coda_psdev(void) goto out_chrdev; } for (i = 0; i < MAX_CODADEVS; i++) - device_create(coda_psdev_class, NULL, - MKDEV(CODA_PSDEV_MAJOR,i), "cfs%d", i); + device_create_drvdata(coda_psdev_class, NULL, + MKDEV(CODA_PSDEV_MAJOR, i), + NULL, "cfs%d", i); coda_sysctl_init(); goto out; -- cgit v0.10.2 From 275e64decc01acf4d2f6b6ad1b83f1c4bd9033e5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: dca: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c index 011328f..9a70377 100644 --- a/drivers/dca/dca-sysfs.c +++ b/drivers/dca/dca-sysfs.c @@ -14,8 +14,9 @@ int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot) { struct device *cd; - cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1), - "requester%d", slot); + cd = device_create_drvdata(dca_class, dca->cd, + MKDEV(0, slot + 1), NULL, + "requester%d", slot); if (IS_ERR(cd)) return PTR_ERR(cd); return 0; @@ -46,7 +47,8 @@ idr_try_again: return err; } - cd = device_create(dca_class, dev, MKDEV(0, 0), "dca%d", dca->id); + cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL, + "dca%d", dca->id); if (IS_ERR(cd)) { spin_lock(&dca_idr_lock); idr_remove(&dca_idr, dca->id); -- cgit v0.10.2 From e282959ef3ebae0d72ac0b24242c376fa34da585 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: dvb: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index e208a60..e713277 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -233,9 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, mutex_unlock(&dvbdev_register_lock); - clsdev = device_create(dvb_class, adap->device, + clsdev = device_create_drvdata(dvb_class, adap->device, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), - "dvb%d.%s%d", adap->num, dnames[type], id); + NULL, "dvb%d.%s%d", adap->num, dnames[type], id); if (IS_ERR(clsdev)) { printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); -- cgit v0.10.2 From 1e2744011ff3cd195aba9f7a15dd71b332812a5c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: framebuffer: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Antonino Daplas Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 97aff8d..4be3b46 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3586,7 +3586,8 @@ static int __init fb_console_init(void) acquire_console_sem(); fb_register_client(&fbcon_event_notifier); - fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon"); + fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0), + NULL, "fbcon"); if (IS_ERR(fbcon_device)) { printk(KERN_WARNING "Unable to create device " diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 33ebdb1..1cd5071 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1439,8 +1439,9 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = i; - fb_info->dev = device_create(fb_class, fb_info->device, - MKDEV(FB_MAJOR, i), "fb%d", i); + fb_info->dev = device_create_drvdata(fb_class, fb_info->device, + MKDEV(FB_MAJOR, i), NULL, + "fb%d", i); if (IS_ERR(fb_info->dev)) { /* Not fatal */ printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); -- cgit v0.10.2 From 0fd15a18d876a9571cc5b88a5d1716dfccb8e493 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: hid: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 2fde6c6..0c6b4d4 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -322,8 +322,9 @@ int hidraw_connect(struct hid_device *hid) goto out; } - dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor), - "%s%d", "hidraw", minor); + dev->dev = device_create_drvdata(hidraw_class, NULL, + MKDEV(hidraw_major, minor), NULL, + "%s%d", "hidraw", minor); if (IS_ERR(dev->dev)) { spin_lock(&minors_lock); -- cgit v0.10.2 From 2871f55237e2aaa00fd724ce45b47e567974045f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: hwmon: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Mark M. Hoffman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 3db2845..7321a88 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -55,7 +55,8 @@ again: return ERR_PTR(err); id = id & MAX_ID_MASK; - hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id); + hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL, + HWMON_ID_FORMAT, id); if (IS_ERR(hwdev)) { spin_lock(&idr_lock); -- cgit v0.10.2 From 1cc4376c259d1950817aaa6221aad7c2058df4a8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: i2c: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Jean Delvare Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 86727fa..9d55c63 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) return PTR_ERR(i2c_dev); /* register this i2c device with the driver core */ - i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, - MKDEV(I2C_MAJOR, adap->nr), - "i2c-%d", adap->nr); + i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev, + MKDEV(I2C_MAJOR, adap->nr), + NULL, "i2c-%d", adap->nr); if (IS_ERR(i2c_dev->dev)) { res = PTR_ERR(i2c_dev->dev); goto error; -- cgit v0.10.2 From 6ecaaf94b831827405613ee9110d8fb8eff92482 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: ide: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b711ab9..353dd11 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2697,10 +2697,12 @@ static int ide_tape_probe(ide_drive_t *drive) idetape_setup(drive, tape, minor); - device_create(idetape_sysfs_class, &drive->gendev, - MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name); - device_create(idetape_sysfs_class, &drive->gendev, - MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name); + device_create_drvdata(idetape_sysfs_class, &drive->gendev, + MKDEV(IDETAPE_MAJOR, minor), NULL, + "%s", tape->name); + device_create_drvdata(idetape_sysfs_class, &drive->gendev, + MKDEV(IDETAPE_MAJOR, minor + 128), NULL, + "n%s", tape->name); g->fops = &idetape_block_ops; ide_register_region(g); -- cgit v0.10.2 From f71674a09f374bb0b5371b3e7b943029867477c5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: ieee1394: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Ben Collins Acked-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9d19aec..b6eb2cf 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2296,9 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host) ohci = (struct ti_ohci *)host->hostdata; - device_create(hpsb_protocol_class, NULL, MKDEV( - IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), - "dv1394-%d", id); + device_create_drvdata(hpsb_protocol_class, NULL, + MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL, + "dv1394-%d", id); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 96f2847..6fa9e4a 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -3010,10 +3010,10 @@ static int __init init_raw1394(void) hpsb_register_highlevel(&raw1394_highlevel); if (IS_ERR - (device_create( + (device_create_drvdata( hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), - RAW1394_DEVICE_NAME))) { + NULL, RAW1394_DEVICE_NAME))) { ret = -EFAULT; goto out_unreg; } diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 069b9f6..25db6e6 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1341,9 +1341,9 @@ static void video1394_add_host (struct hpsb_host *host) hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; - device_create(hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, minor), - "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); + device_create_drvdata(hpsb_protocol_class, NULL, + MKDEV(IEEE1394_MAJOR, minor), NULL, + "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); } -- cgit v0.10.2 From c76d3d28c31a68f45d6b5acaa4813138dd7883b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: infiniband: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Roland Dreier Cc: Sean Hefty Cc: Hal Rosenstock Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 35f301c..56c0eda 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops, goto err_cdev; } - device = device_create(ipath_class, NULL, dev, name); + device = device_create_drvdata(ipath_class, NULL, dev, NULL, name); if (IS_ERR(device)) { ret = PTR_ERR(device); -- cgit v0.10.2 From 24d0b416f988fcdfa2615a25c7c33c21cc2a65a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: isdn: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 8a35029..0dcfbfb 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1552,7 +1552,8 @@ static int __init capi_init(void) return PTR_ERR(capi_class); } - device_create(capi_class, NULL, MKDEV(capi_major, 0), "capi"); + device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL, + "capi"); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { -- cgit v0.10.2 From 97cd790e3a9cf2855676a461ac5c448f5843017d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: macintosh: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index e5d4468..cae5248 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -862,7 +862,8 @@ adbdev_init(void) adb_dev_class = class_create(THIS_MODULE, "adb"); if (IS_ERR(adb_dev_class)) return; - device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb"); + device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, + "adb"); platform_device_register(&adb_pfdev); platform_driver_probe(&adb_pfdrv, adb_dummy_probe); -- cgit v0.10.2 From 43f98747d48195d92c4102c17d7175bf24df1801 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: mips: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index b556419..dfd868b 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -522,8 +522,8 @@ static int __init rtlx_module_init(void) atomic_set(&channel_wqs[i].in_open, 0); mutex_init(&channel_wqs[i].mutex); - dev = device_create(mt_class, NULL, MKDEV(major, i), - "%s%d", module_name, i); + dev = device_create_drvdata(mt_class, NULL, MKDEV(major, i), + NULL, "%s%d", module_name, i); if (IS_ERR(dev)) { err = PTR_ERR(dev); goto out_chrdev; diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c index 28b012a..66e3e3f 100644 --- a/arch/mips/sibyte/common/sb_tbprof.c +++ b/arch/mips/sibyte/common/sb_tbprof.c @@ -576,7 +576,8 @@ static int __init sbprof_tb_init(void) tb_class = tbc; - dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), "tb"); + dev = device_create_drvdata(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), + NULL, "tb"); if (IS_ERR(dev)) { err = PTR_ERR(dev); goto out_class; -- cgit v0.10.2 From 7da5a05dd7b95315af49f724f623bbfdab0f5e4d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: misc: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 1861624..4ce3bdc 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c @@ -399,8 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev, goto err_irq; } - if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major, - minor), "phantom%u", minor))) + if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev, + MKDEV(phantom_major, minor), + NULL, "phantom%u", minor))) dev_err(&pdev->dev, "can't create device\n"); pci_set_drvdata(pdev, pht); -- cgit v0.10.2 From daea34bc6f67cf3872d1b52ba5ccf249f3ceb176 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: mtd: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: David Woodhouse Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 129d429..aef9f4b 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -28,10 +28,13 @@ static void mtd_notify_add(struct mtd_info* mtd) if (!mtd) return; - device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index); + device_create_drvdata(mtd_class, NULL, + MKDEV(MTD_CHAR_MAJOR, mtd->index*2), + NULL, "mtd%d", mtd->index); - device_create(mtd_class, NULL, - MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index); + device_create_drvdata(mtd_class, NULL, + MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), + NULL, "mtd%dro", mtd->index); } static void mtd_notify_remove(struct mtd_info* mtd) -- cgit v0.10.2 From e17da9c4c5fc19e16ddcb0ae020ee4425ca0c96f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: net: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Jeff Garzik Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6b1d7a8..739b3ab 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -866,7 +866,8 @@ static int __init ppp_init(void) err = PTR_ERR(ppp_class); goto out_chrdev; } - device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp"); + device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), + NULL, "ppp"); } out: diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 5827324..f7d3349 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -397,9 +397,9 @@ static int __init cosa_init(void) err = PTR_ERR(cosa_class); goto out_chrdev; } - for (i=0; i Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: s390: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 81a96e0..c3dee90 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -1168,17 +1168,19 @@ static int raw3270_create_attributes(struct raw3270 *rp) if (rc) goto out; - rp->clttydev = device_create(class3270, &rp->cdev->dev, - MKDEV(IBM_TTY3270_MAJOR, rp->minor), - "tty%s", rp->cdev->dev.bus_id); + rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev, + MKDEV(IBM_TTY3270_MAJOR, rp->minor), + NULL, + "tty%s", rp->cdev->dev.bus_id); if (IS_ERR(rp->clttydev)) { rc = PTR_ERR(rp->clttydev); goto out_ttydev; } - rp->cltubdev = device_create(class3270, &rp->cdev->dev, - MKDEV(IBM_FS3270_MAJOR, rp->minor), - "tub%s", rp->cdev->dev.bus_id); + rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev, + MKDEV(IBM_FS3270_MAJOR, rp->minor), + NULL, + "tub%s", rp->cdev->dev.bus_id); if (!IS_ERR(rp->cltubdev)) goto out; diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index 6dfdb7c..12c2a5a 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c @@ -69,10 +69,9 @@ struct tape_class_device *register_tape_dev( if (rc) goto fail_with_cdev; - tcd->class_device = device_create(tape_class, device, - tcd->char_device->dev, - "%s", tcd->device_name - ); + tcd->class_device = device_create_drvdata(tape_class, device, + tcd->char_device->dev, + NULL, "%s", tcd->device_name); rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0; if (rc) goto fail_with_cdev; diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index b0ac44b..c1f352b 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -896,8 +896,9 @@ static int ur_set_online(struct ccw_device *cdev) goto fail_free_cdev; } - urd->device = device_create(vmur_class, NULL, urd->char_device->dev, - "%s", node_id); + urd->device = device_create_drvdata(vmur_class, NULL, + urd->char_device->dev, NULL, + "%s", node_id); if (IS_ERR(urd->device)) { rc = PTR_ERR(urd->device); TRACE("ur_set_online: device_create rc=%d\n", rc); -- cgit v0.10.2 From 9def0b9761ee096c3c539b427dfb1e52b373cdad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: scsi: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: James E.J. Bottomley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 2bc30e3..1fe0901 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -271,8 +271,8 @@ rebuild_sys_tab: pHba->initialized = TRUE; pHba->state &= ~DPTI_STATE_RESET; if (adpt_sysfs_class) { - struct device *dev = device_create(adpt_sysfs_class, - NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), + struct device *dev = device_create_drvdata(adpt_sysfs_class, + NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL, "dpti%d", pHba->unit); if (IS_ERR(dev)) { printk(KERN_WARNING"dpti%d: unable to " -- cgit v0.10.2 From 89409211ff97bf82295d1fb98ab18302a03e9199 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: sound: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman diff --git a/sound/core/init.c b/sound/core/init.c index 5c254d4..df46bbc 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -548,8 +548,9 @@ int snd_card_register(struct snd_card *card) snd_assert(card != NULL, return -EINVAL); #ifndef CONFIG_SYSFS_DEPRECATED if (!card->card_dev) { - card->card_dev = device_create(sound_class, card->dev, 0, - "card%i", card->number); + card->card_dev = device_create_drvdata(sound_class, card->dev, + MKDEV(0, 0), NULL, + "card%i", card->number); if (IS_ERR(card->card_dev)) card->card_dev = NULL; } diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index a9c23b2..7d89c08 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -560,17 +560,19 @@ static int __init oss_init(void) sound_dmap_flag = (dmabuf > 0 ? 1 : 0); for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - device_create(sound_class, NULL, - MKDEV(SOUND_MAJOR, dev_list[i].minor), - "%s", dev_list[i].name); + device_create_drvdata(sound_class, NULL, + MKDEV(SOUND_MAJOR, dev_list[i].minor), + NULL, "%s", dev_list[i].name); if (!dev_list[i].num) continue; for (j = 1; j < *dev_list[i].num; j++) - device_create(sound_class, NULL, - MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), - "%s%d", dev_list[i].name, j); + device_create_drvdata(sound_class, NULL, + MKDEV(SOUND_MAJOR, + dev_list[i].minor + (j*0x10)), + NULL, + "%s%d", dev_list[i].name, j); } if (sound_nblocks >= 1024) diff --git a/sound/sound_core.c b/sound/sound_core.c index dcfc1d5..1b04259 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -171,8 +171,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); - device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), - s->name+6); + device_create_drvdata(sound_class, dev, + MKDEV(SOUND_MAJOR, s->unit_minor), + NULL, s->name+6); return r; fail: -- cgit v0.10.2 From 3d81252ddb10f63ae4db713d9b32faabe641b850 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 6 Jun 2008 15:48:07 -0500 Subject: device create: spi: convert device_create to device_create_drvdata Switch over to use the shiny new device_create_drvdata() call instead of the original device_create() calls, so this continues to work after device_create() is removed. Note that this driver never had the race which motivated removing the original call; it locked correctly. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index ddbe1a5..2833fd7 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -576,7 +576,8 @@ static int spidev_probe(struct spi_device *spi) struct device *dev; spidev->devt = MKDEV(SPIDEV_MAJOR, minor); - dev = device_create(spidev_class, &spi->dev, spidev->devt, + dev = device_create_drvdata(spidev_class, &spi->dev, + spidev->devt, spidev, "spidev%d.%d", spi->master->bus_num, spi->chip_select); status = IS_ERR(dev) ? PTR_ERR(dev) : 0; @@ -586,7 +587,6 @@ static int spidev_probe(struct spi_device *spi) } if (status == 0) { set_bit(minor, minors); - spi_set_drvdata(spi, spidev); list_add(&spidev->device_entry, &device_list); } mutex_unlock(&device_list_lock); -- cgit v0.10.2 From bc00bc924295f02295fe5eeeba3618ba0d0db1ef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: usb: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6fbc8f5..20290c5 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1729,9 +1729,9 @@ static int usb_classdev_add(struct usb_device *dev) { struct device *cldev; - cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, - "usbdev%d.%d", dev->bus->busnum, - dev->devnum); + cldev = device_create_drvdata(usb_classdev_class, &dev->dev, + dev->dev.devt, NULL, "usbdev%d.%d", + dev->bus->busnum, dev->devnum); if (IS_ERR(cldev)) return PTR_ERR(cldev); dev->usb_classdev = cldev; diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 913fb86..6b1b229 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -196,8 +196,9 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), "%s", temp); + intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev, + MKDEV(USB_MAJOR, minor), NULL, + "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 9caaec3..49cd9e1 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1360,8 +1360,8 @@ printer_bind(struct usb_gadget *gadget) /* Setup the sysfs files for the printer gadget. */ - dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, - "g_printer"); + dev->pdev = device_create_drvdata(usb_gadget_class, NULL, + g_printer_devno, NULL, "g_printer"); if (IS_ERR(dev->pdev)) { ERROR(dev, "Failed to create device: g_printer\n"); goto fail; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 293a462..6566fc0 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1162,8 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) if (minor >= MON_BIN_MAX_MINOR) return 0; - dev = device_create(mon_bin_class, ubus? ubus->controller: NULL, - MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor); + dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL, + MKDEV(MAJOR(mon_bin_dev0), minor), NULL, + "usbmon%d", minor); if (IS_ERR(dev)) return 0; -- cgit v0.10.2 From 3bfd49c8ab1859ae0f5fa1df2b3781c99115f442 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: x86: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 2de5fa2..14b11b3 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -141,8 +141,8 @@ static __cpuinit int cpuid_device_create(int cpu) { struct device *dev; - dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), - "cpu%d", cpu); + dev = device_create_drvdata(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), + NULL, "cpu%d", cpu); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index a153b39..9fd80955 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -149,8 +149,8 @@ static int __cpuinit msr_device_create(int cpu) { struct device *dev; - dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu), - "msr%d", cpu); + dev = device_create_drvdata(msr_class, NULL, MKDEV(MSR_MAJOR, cpu), + NULL, "msr%d", cpu); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } -- cgit v0.10.2 From ccea44fadca396b0f89aed5bdeb60e4abb212566 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: driver core: remove device_create() There are no more users of this, and it is racy. Use device_create_drvdata() or device_create_vargs() instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/core.c b/drivers/base/core.c index be9aba4..4dc0d27 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1273,40 +1273,6 @@ struct device *device_create_drvdata(struct class *class, } EXPORT_SYMBOL_GPL(device_create_drvdata); -/** - * device_create - creates a device and registers it with sysfs - * @class: pointer to the struct class that this device should be registered to - * @parent: pointer to the parent struct device of this new device, if any - * @devt: the dev_t for the char device to be added - * @fmt: string for the device's name - * - * This function can be used by char device classes. A struct device - * will be created in sysfs, registered to the specified class. - * - * A "dev" file will be created, showing the dev_t for the device, if - * the dev_t is not 0,0. - * If a pointer to a parent struct device is passed in, the newly created - * struct device will be a child of that device in sysfs. - * The pointer to the struct device will be returned from the call. - * Any further sysfs files that might be required can be created using this - * pointer. - * - * Note: the struct class passed to this function must have previously - * been created with a call to class_create(). - */ -struct device *device_create(struct class *class, struct device *parent, - dev_t devt, const char *fmt, ...) -{ - va_list vargs; - struct device *dev; - - va_start(vargs, fmt); - dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs); - va_end(vargs); - return dev; -} -EXPORT_SYMBOL_GPL(device_create); - static int __match_devt(struct device *dev, void *data) { dev_t *devt = data; diff --git a/include/linux/device.h b/include/linux/device.h index e49aa74..a3ef5a2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -470,9 +470,6 @@ extern struct device *device_create_vargs(struct class *cls, void *drvdata, const char *fmt, va_list vargs); -extern struct device *device_create(struct class *cls, struct device *parent, - dev_t devt, const char *fmt, ...) - __attribute__((format(printf, 4, 5))); extern struct device *device_create_drvdata(struct class *cls, struct device *parent, dev_t devt, -- cgit v0.10.2 From 4e10673944a5c386378ff9d692ae37e19993f9d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 21 Jul 2008 20:03:34 -0700 Subject: device create: convert device_create_drvdata to device_create Now that device_create() has been audited, rename things back to the original call to be sane. Keep the device_create_drvdata macro around to make merges easier. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/core.c b/drivers/base/core.c index 4dc0d27..9ae28aa 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1236,7 +1236,7 @@ error: EXPORT_SYMBOL_GPL(device_create_vargs); /** - * device_create_drvdata - creates a device and registers it with sysfs + * device_create - creates a device and registers it with sysfs * @class: pointer to the struct class that this device should be registered to * @parent: pointer to the parent struct device of this new device, if any * @devt: the dev_t for the char device to be added @@ -1257,11 +1257,8 @@ EXPORT_SYMBOL_GPL(device_create_vargs); * Note: the struct class passed to this function must have previously * been created with a call to class_create(). */ -struct device *device_create_drvdata(struct class *class, - struct device *parent, - dev_t devt, - void *drvdata, - const char *fmt, ...) +struct device *device_create(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const char *fmt, ...) { va_list vargs; struct device *dev; @@ -1271,7 +1268,7 @@ struct device *device_create_drvdata(struct class *class, va_end(vargs); return dev; } -EXPORT_SYMBOL_GPL(device_create_drvdata); +EXPORT_SYMBOL_GPL(device_create); static int __match_devt(struct device *dev, void *data) { diff --git a/include/linux/device.h b/include/linux/device.h index a3ef5a2..de17871 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -470,12 +470,11 @@ extern struct device *device_create_vargs(struct class *cls, void *drvdata, const char *fmt, va_list vargs); -extern struct device *device_create_drvdata(struct class *cls, - struct device *parent, - dev_t devt, - void *drvdata, - const char *fmt, ...) +extern struct device *device_create(struct class *cls, struct device *parent, + dev_t devt, void *drvdata, + const char *fmt, ...) __attribute__((format(printf, 5, 6))); +#define device_create_drvdata device_create extern void device_destroy(struct class *cls, dev_t devt); /* -- cgit v0.10.2 From 93562b537659fc0f63920fd4d9d24f54e434f4c4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: Driver Core: add ability for class_for_each_device to start in middle of list This mirrors the functionality that driver_for_each_device has as well. We add a start variable, and all callers of the function are fixed up at the same time. The block layer will be using this new functionality in a follow-on patch. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/class.c b/drivers/base/class.c index 71ce3ff..2eb7048 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -256,11 +256,14 @@ char *make_class_name(const char *name, struct kobject *kobj) /** * class_for_each_device - device iterator * @class: the class we're iterating + * @start: the device to start with in the list, if any. * @data: data for the callback * @fn: function to be called for each device * * Iterate over @class's list of devices, and call @fn for each, - * passing it @data. + * passing it @data. If @start is set, the list iteration will start + * there, otherwise if it is NULL, the iteration starts at the + * beginning of the list. * * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. @@ -269,8 +272,8 @@ char *make_class_name(const char *name, struct kobject *kobj) * re-acquired in @fn, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ -int class_for_each_device(struct class *class, void *data, - int (*fn)(struct device *, void *)) +int class_for_each_device(struct class *class, struct device *start, + void *data, int (*fn)(struct device *, void *)) { struct device *dev; int error = 0; @@ -279,12 +282,14 @@ int class_for_each_device(struct class *class, void *data, return -EINVAL; down(&class->sem); list_for_each_entry(dev, &class->devices, node) { + if (start) { + if (start == dev) + start = NULL; + continue; + } dev = get_device(dev); - if (dev) { - error = fn(dev, data); - put_device(dev); - } else - error = -ENODEV; + error = fn(dev, data); + put_device(dev); if (error) break; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 7608df8..7bf38c4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -722,7 +722,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ - class_for_each_device(&i2c_adapter_class, driver, __attach_adapter); + class_for_each_device(&i2c_adapter_class, NULL, driver, + __attach_adapter); mutex_unlock(&core_lock); return 0; @@ -782,7 +783,8 @@ void i2c_del_driver(struct i2c_driver *driver) { mutex_lock(&core_lock); - class_for_each_device(&i2c_adapter_class, driver, __detach_adapter); + class_for_each_device(&i2c_adapter_class, NULL, driver, + __detach_adapter); driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 05710c7..47c0d85 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1453,7 +1453,8 @@ static void nodemgr_suspend_ne(struct node_entry *ne) ne->in_limbo = 1; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); - class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend); + class_for_each_device(&nodemgr_ud_class, NULL, ne, + __nodemgr_driver_suspend); } @@ -1462,7 +1463,8 @@ static void nodemgr_resume_ne(struct node_entry *ne) ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); - class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume); + class_for_each_device(&nodemgr_ud_class, NULL, ne, + __nodemgr_driver_resume); HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); } @@ -1498,7 +1500,8 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data) static void nodemgr_update_pdrv(struct node_entry *ne) { - class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv); + class_for_each_device(&nodemgr_ud_class, NULL, ne, + __nodemgr_update_pdrv); } @@ -1591,7 +1594,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * while probes are time-consuming. (Well, those probes need some * improvement...) */ - class_for_each_device(&nodemgr_ne_class, ¶m, __nodemgr_node_probe); + class_for_each_device(&nodemgr_ne_class, NULL, ¶m, + __nodemgr_node_probe); /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we @@ -1826,7 +1830,7 @@ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) hip.cb = cb; hip.data = data; - error = class_for_each_device(&hpsb_host_class, &hip, + error = class_for_each_device(&hpsb_host_class, NULL, &hip, __nodemgr_for_each_host); return error; diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index a489227..936bae5 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -78,7 +78,7 @@ static void find_main_battery(void) main_battery = NULL; bp.main = main_battery; - error = class_for_each_device(power_supply_class, &bp, + error = class_for_each_device(power_supply_class, NULL, &bp, __find_main_battery); if (error) { main_battery = bp.main; diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index af1633e..cb1ccb4 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -41,7 +41,7 @@ static void power_supply_changed_work(struct work_struct *work) dev_dbg(psy->dev, "%s\n", __func__); - class_for_each_device(power_supply_class, psy, + class_for_each_device(power_supply_class, NULL, psy, __power_supply_changed_work); power_supply_update_leds(psy); @@ -79,7 +79,7 @@ int power_supply_am_i_supplied(struct power_supply *psy) { int error; - error = class_for_each_device(power_supply_class, psy, + error = class_for_each_device(power_supply_class, NULL, psy, __power_supply_am_i_supplied); dev_dbg(psy->dev, "%s %d\n", __func__, error); diff --git a/include/linux/device.h b/include/linux/device.h index de17871..6d5b351 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -210,7 +210,8 @@ extern struct kobject *sysfs_dev_block_kobj; extern struct kobject *sysfs_dev_char_kobj; extern int __must_check class_register(struct class *class); extern void class_unregister(struct class *class); -extern int class_for_each_device(struct class *class, void *data, +extern int class_for_each_device(struct class *class, struct device *start, + void *data, int (*fn)(struct device *dev, void *data)); extern struct device *class_find_device(struct class *class, void *data, int (*match)(struct device *, void *)); -- cgit v0.10.2 From 695794ae0c5bdd9bd06e35b118801e2e9be04f9e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: Driver Core: add ability for class_find_device to start in middle of list This mirrors the functionality that driver_find_device has as well. We add a start variable, and all callers of the function are fixed up at the same time. The block layer will be using this new functionality in a follow-on patch. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/class.c b/drivers/base/class.c index 2eb7048..3918d0e 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -302,6 +302,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device); /** * class_find_device - device iterator for locating a particular device * @class: the class we're iterating + * @start: Device to begin with * @data: data for the match function * @match: function to check device * @@ -319,8 +320,9 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * re-acquired in @match, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ -struct device *class_find_device(struct class *class, void *data, - int (*match)(struct device *, void *)) +struct device *class_find_device(struct class *class, struct device *start, + void *data, + int (*match)(struct device *, void *)) { struct device *dev; int found = 0; @@ -330,15 +332,17 @@ struct device *class_find_device(struct class *class, void *data, down(&class->sem); list_for_each_entry(dev, &class->devices, node) { + if (start) { + if (start == dev) + start = NULL; + continue; + } dev = get_device(dev); - if (dev) { - if (match(dev, data)) { - found = 1; - break; - } else - put_device(dev); - } else + if (match(dev, data)) { + found = 1; break; + } else + put_device(dev); } up(&class->sem); diff --git a/drivers/base/core.c b/drivers/base/core.c index 9ae28aa..9f05de6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1289,7 +1289,7 @@ void device_destroy(struct class *class, dev_t devt) { struct device *dev; - dev = class_find_device(class, &devt, __match_devt); + dev = class_find_device(class, NULL, &devt, __match_devt); if (dev) { put_device(dev); device_unregister(dev); diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 47c0d85..994a21e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -754,7 +754,8 @@ static void nodemgr_remove_uds(struct node_entry *ne) */ mutex_lock(&nodemgr_serialize_remove_uds); for (;;) { - dev = class_find_device(&nodemgr_ud_class, ne, __match_ne); + dev = class_find_device(&nodemgr_ud_class, NULL, ne, + __match_ne); if (!dev) break; ud = container_of(dev, struct unit_directory, unit_dev); @@ -901,7 +902,8 @@ static struct node_entry *find_entry_by_guid(u64 guid) struct device *dev; struct node_entry *ne; - dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid); + dev = class_find_device(&nodemgr_ne_class, NULL, &guid, + __match_ne_guid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); @@ -940,7 +942,8 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, param.host = host; param.nodeid = nodeid; - dev = class_find_device(&nodemgr_ne_class, ¶m, __match_ne_nodeid); + dev = class_find_device(&nodemgr_ne_class, NULL, ¶m, + __match_ne_nodeid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 58b7336..d397fa5 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -345,7 +345,7 @@ struct rtc_device *rtc_class_open(char *name) struct device *dev; struct rtc_device *rtc = NULL; - dev = class_find_device(rtc_class, name, __rtc_match); + dev = class_find_device(rtc_class, NULL, name, __rtc_match); if (dev) rtc = to_rtc_device(dev); diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 35cd892..78dad28 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -466,7 +466,8 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) struct device *cdev; struct Scsi_Host *shost = ERR_PTR(-ENXIO); - cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match); + cdev = class_find_device(&shost_class, NULL, &hostnum, + __scsi_host_match); if (cdev) { shost = scsi_host_get(class_to_shost(cdev)); put_device(cdev); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 3af7cbc..06748f3 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -170,7 +170,7 @@ iscsi_create_endpoint(int dd_size) int err; for (id = 1; id < ISCSI_MAX_EPID; id++) { - dev = class_find_device(&iscsi_endpoint_class, &id, + dev = class_find_device(&iscsi_endpoint_class, NULL, &id, iscsi_match_epid); if (!dev) break; @@ -222,7 +222,7 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle) struct iscsi_endpoint *ep; struct device *dev; - dev = class_find_device(&iscsi_endpoint_class, &handle, + dev = class_find_device(&iscsi_endpoint_class, NULL, &handle, iscsi_match_epid); if (!dev) return NULL; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1ad12af..1771b24 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -502,7 +502,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num) struct device *dev; struct spi_master *master = NULL; - dev = class_find_device(&spi_master_class, &bus_num, + dev = class_find_device(&spi_master_class, NULL, &bus_num, __spi_master_match); if (dev) master = container_of(dev, struct spi_master, dev); diff --git a/include/linux/device.h b/include/linux/device.h index 6d5b351..c1f7298 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -213,7 +213,8 @@ extern void class_unregister(struct class *class); extern int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); -extern struct device *class_find_device(struct class *class, void *data, +extern struct device *class_find_device(struct class *class, + struct device *start, void *data, int (*match)(struct device *, void *)); struct class_attribute { -- cgit v0.10.2 From 6ffeea77ff014f1456fcd0564eac84b34e9535ca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: fix compiler warning in genhd.c Warn if something really bad happens if we can't create this link. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index 24e3fc9..3ccf5c0 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -183,6 +183,7 @@ static int exact_lock(dev_t devt, void *data) void add_disk(struct gendisk *disk) { struct backing_dev_info *bdi; + int retval; disk->flags |= GENHD_FL_UP; blk_register_region(MKDEV(disk->major, disk->first_minor), @@ -193,7 +194,8 @@ void add_disk(struct gendisk *disk) bdi = &disk->queue->backing_dev_info; bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); - sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + WARN_ON(retval); } EXPORT_SYMBOL(add_disk); -- cgit v0.10.2 From 5c6f35c5ece8f130cd8ec9ba0d71dc146b46a0f1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make printk_partition use the class iterator function Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index 3ccf5c0..10b9ac4 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -227,58 +227,65 @@ struct gendisk *get_gendisk(dev_t devt, int *part) } /* - * print a full list of all partitions - intended for places where the root - * filesystem can't be mounted and thus to give the victim some idea of what - * went wrong + * print a partitions - intended for places where the root filesystem can't be + * mounted and thus to give the victim some idea of what went wrong */ -void __init printk_all_partitions(void) +static int printk_partition(struct device *dev, void *data) { - struct device *dev; struct gendisk *sgp; char buf[BDEVNAME_SIZE]; int n; - mutex_lock(&block_class_lock); - /* For each block device... */ - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - sgp = dev_to_disk(dev); - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - continue; + if (dev->type != &disk_type) + goto exit; - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } + sgp = dev_to_disk(dev); + /* + * Don't show empty devices or things that have been surpressed + */ + if (get_capacity(sgp) == 0 || + (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) + goto exit; + + /* + * Note, unlike /proc/partitions, I am showing the numbers in + * hex - the same format as the root= option takes. + */ + printk("%02x%02x %10llu %s", + sgp->major, sgp->first_minor, + (unsigned long long)get_capacity(sgp) >> 1, + disk_name(sgp, 0, buf)); + if (sgp->driverfs_dev != NULL && + sgp->driverfs_dev->driver != NULL) + printk(" driver: %s\n", + sgp->driverfs_dev->driver->name); + else + printk(" (driver?)\n"); + + /* now show the partitions */ + for (n = 0; n < sgp->minors - 1; ++n) { + if (sgp->part[n] == NULL) + goto exit; + if (sgp->part[n]->nr_sects == 0) + goto exit; + printk(" %02x%02x %10llu %s\n", + sgp->major, n + 1 + sgp->first_minor, + (unsigned long long)sgp->part[n]->nr_sects >> 1, + disk_name(sgp, n + 1, buf)); } +exit: + return 0; +} +/* + * print a full list of all partitions - intended for places where the root + * filesystem can't be mounted and thus to give the victim some idea of what + * went wrong + */ +void __init printk_all_partitions(void) +{ + mutex_lock(&block_class_lock); + class_for_each_device(&block_class, NULL, NULL, printk_partition); mutex_unlock(&block_class_lock); } -- cgit v0.10.2 From a142be856f060ae8106512c0e81a8d6f8746ab0b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make blk_lookup_devt use the class iterator function Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index 10b9ac4..e8c42bf 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -677,24 +677,38 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ +struct find_block { + const char *name; + int part; +}; + +static int match_id(struct device *dev, void *data) +{ + struct find_block *find = data; + + if (dev->type != &disk_type) + return 0; + if (strcmp(dev->bus_id, find->name) == 0) { + struct gendisk *disk = dev_to_disk(dev); + if (find->part < disk->minors) + return 1; + } + return 0; +} + dev_t blk_lookup_devt(const char *name, int part) { struct device *dev; dev_t devt = MKDEV(0, 0); + struct find_block find; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (strcmp(dev->bus_id, name) == 0) { - struct gendisk *disk = dev_to_disk(dev); - - if (part < disk->minors) - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + part); - break; - } - } + find.name = name; + find.part = part; + dev = class_find_device(&block_class, NULL, (void *)&find, match_id); + if (dev) + devt = MKDEV(MAJOR(dev->devt), + MINOR(dev->devt) + part); mutex_unlock(&block_class_lock); return devt; -- cgit v0.10.2 From a6e2ba88774bc5870ab3d9664cb86d70415f7402 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 23 May 2008 09:44:11 -0700 Subject: block: make /proc/diskstats only build if CONFIG_PROC_FS is enabled These functions are only needed if CONFIG_PROC_FS is enabled, so save the space when it is not. This also makes it easier for a patch later in this series to work properly if CONFIG_PROC_FS is not enabled. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index e8c42bf..68a5f28 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -544,6 +544,7 @@ static struct device_type disk_type = { .release = disk_release, }; +#ifdef CONFIG_PROC_FS /* * aggregate disk stat collector. Uses the same stats that the sysfs * entries do, above, but makes them available through one seq_file. @@ -653,6 +654,7 @@ const struct seq_operations diskstats_op = { .stop = diskstats_stop, .show = diskstats_show }; +#endif /* CONFIG_PROC_FS */ static void media_change_notify_thread(struct work_struct *work) { -- cgit v0.10.2 From 68c4d4a7875c59f2e4b72901ab11ba978e75bde0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make proc files seq_start use the class_find_device() Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index 68a5f28..f03bdad 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -291,18 +291,25 @@ void __init printk_all_partitions(void) #ifdef CONFIG_PROC_FS /* iterator */ +static int find_start(struct device *dev, void *data) +{ + loff_t k = *(loff_t *)data; + + if (dev->type != &disk_type) + return 0; + if (!k--) + return 1; + return 0; +} + static void *part_start(struct seq_file *part, loff_t *pos) { - loff_t k = *pos; struct device *dev; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (!k--) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, NULL, (void *)pos, find_start); + if (dev) + return dev_to_disk(dev); return NULL; } @@ -555,16 +562,12 @@ static struct device_type disk_type = { static void *diskstats_start(struct seq_file *part, loff_t *pos) { - loff_t k = *pos; struct device *dev; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (!k--) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, NULL, (void *)pos, find_start); + if (dev) + return dev_to_disk(dev); return NULL; } -- cgit v0.10.2 From 66c64afec16a7b46212ecb2fa99998923bbeea3f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: move header for /proc/partitions to seq_start The seq_start call is the better place for the header for the file, that way we don't have to be mucking in the class structure to try to figure out if this is the first partition or not. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index f03bdad..70f1d70 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -305,6 +305,10 @@ static int find_start(struct device *dev, void *data) static void *part_start(struct seq_file *part, loff_t *pos) { struct device *dev; + loff_t n = *pos; + + if (!n) + seq_puts(part, "major minor #blocks name\n\n"); mutex_lock(&block_class_lock); dev = class_find_device(&block_class, NULL, (void *)pos, find_start); @@ -338,9 +342,6 @@ static int show_partition(struct seq_file *part, void *v) int n; char buf[BDEVNAME_SIZE]; - if (&sgp->dev.node == block_class.devices.next) - seq_puts(part, "major minor #blocks name\n\n"); - /* Don't show non-partitionable removeable devices or empty devices */ if (!get_capacity(sgp) || (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) -- cgit v0.10.2 From 27f302519148f311307637d4c9a6d0fd87d07e4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make /proc/partitions and /proc/diskstats use class_find_device() Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/block/genhd.c b/block/genhd.c index 70f1d70..c13cc77 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -317,17 +317,21 @@ static void *part_start(struct seq_file *part, loff_t *pos) return NULL; } +static int find_next(struct device *dev, void *data) +{ + if (dev->type == &disk_type) + return 1; + return 0; +} + static void *part_next(struct seq_file *part, void *v, loff_t *pos) { struct gendisk *gp = v; struct device *dev; ++*pos; - list_for_each_entry(dev, &gp->dev.node, node) { - if (&dev->node == &block_class.devices) - return NULL; - if (dev->type == &disk_type) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, &gp->dev, NULL, find_next); + if (dev) + return dev_to_disk(dev); return NULL; } @@ -578,12 +582,9 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) struct device *dev; ++*pos; - list_for_each_entry(dev, &gp->dev.node, node) { - if (&dev->node == &block_class.devices) - return NULL; - if (dev->type == &disk_type) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, &gp->dev, NULL, find_next); + if (dev) + return dev_to_disk(dev); return NULL; } -- cgit v0.10.2 From d4c4196f24ade5f336882587480652efde2c739c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 May 2008 10:17:53 +0300 Subject: infiniband: rename "device" to "ib_device" in cm_device This pointer really is a struct ib_device, not a struct device, so name it properly to help prevent confusion. This makes the followon patch in this series much smaller and easier to understand as well. Cc: Kay Sievers Cc: Roland Dreier Cc: Hal Rosenstock Acked-by: Sean Hefty Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 55738ee..8dc4429 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -162,7 +162,7 @@ struct cm_port { struct cm_device { struct list_head list; - struct ib_device *device; + struct ib_device *ib_device; struct kobject dev_obj; u8 ack_delay; struct cm_port *port[0]; @@ -339,7 +339,7 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc, { av->port = port; av->pkey_index = wc->pkey_index; - ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc, + ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc, grh, &av->ah_attr); } @@ -353,7 +353,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) read_lock_irqsave(&cm.device_lock, flags); list_for_each_entry(cm_dev, &cm.device_list, list) { - if (!ib_find_cached_gid(cm_dev->device, &path->sgid, + if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid, &p, NULL)) { port = cm_dev->port[p-1]; break; @@ -364,13 +364,13 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) if (!port) return -EINVAL; - ret = ib_find_cached_pkey(cm_dev->device, port->port_num, + ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num, be16_to_cpu(path->pkey), &av->pkey_index); if (ret) return ret; av->port = port; - ib_init_ah_from_path(cm_dev->device, port->port_num, path, + ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path, &av->ah_attr); av->timeout = path->packet_life_time + 1; return 0; @@ -1515,7 +1515,7 @@ static int cm_req_handler(struct cm_work *work) req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad; - cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL); + cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); @@ -1550,7 +1550,7 @@ static int cm_req_handler(struct cm_work *work) cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av); if (ret) { - ib_get_cached_gid(work->port->cm_dev->device, + ib_get_cached_gid(work->port->cm_dev->ib_device, work->port->port_num, 0, &work->path[0].sgid); ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID, &work->path[0].sgid, sizeof work->path[0].sgid, @@ -2950,7 +2950,7 @@ static int cm_sidr_req_handler(struct cm_work *work) struct cm_sidr_req_msg *sidr_req_msg; struct ib_wc *wc; - cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL); + cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); cm_id_priv = container_of(cm_id, struct cm_id_private, id); @@ -3578,7 +3578,7 @@ static void cm_get_ack_delay(struct cm_device *cm_dev) { struct ib_device_attr attr; - if (ib_query_device(cm_dev->device, &attr)) + if (ib_query_device(cm_dev->ib_device, &attr)) cm_dev->ack_delay = 0; /* acks will rely on packet life time */ else cm_dev->ack_delay = attr.local_ca_ack_delay; @@ -3676,7 +3676,7 @@ static void cm_remove_port_fs(struct cm_port *port) kobject_put(&port->port_obj); } -static void cm_add_one(struct ib_device *device) +static void cm_add_one(struct ib_device *ib_device) { struct cm_device *cm_dev; struct cm_port *port; @@ -3691,26 +3691,27 @@ static void cm_add_one(struct ib_device *device) int ret; u8 i; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) + if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB) return; cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) * - device->phys_port_cnt, GFP_KERNEL); + ib_device->phys_port_cnt, GFP_KERNEL); if (!cm_dev) return; - cm_dev->device = device; + cm_dev->ib_device = ib_device; cm_get_ack_delay(cm_dev); ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type, - &cm_class.subsys.kobj, "%s", device->name); + &cm_class.subsys.kobj, "%s", + ib_device->name); if (ret) { kfree(cm_dev); return; } set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); - for (i = 1; i <= device->phys_port_cnt; i++) { + for (i = 1; i <= ib_device->phys_port_cnt; i++) { port = kzalloc(sizeof *port, GFP_KERNEL); if (!port) goto error1; @@ -3723,7 +3724,7 @@ static void cm_add_one(struct ib_device *device) if (ret) goto error1; - port->mad_agent = ib_register_mad_agent(device, i, + port->mad_agent = ib_register_mad_agent(ib_device, i, IB_QPT_GSI, ®_req, 0, @@ -3733,11 +3734,11 @@ static void cm_add_one(struct ib_device *device) if (IS_ERR(port->mad_agent)) goto error2; - ret = ib_modify_port(device, i, 0, &port_modify); + ret = ib_modify_port(ib_device, i, 0, &port_modify); if (ret) goto error3; } - ib_set_client_data(device, &cm_client, cm_dev); + ib_set_client_data(ib_device, &cm_client, cm_dev); write_lock_irqsave(&cm.device_lock, flags); list_add_tail(&cm_dev->list, &cm.device_list); @@ -3753,14 +3754,14 @@ error1: port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; while (--i) { port = cm_dev->port[i-1]; - ib_modify_port(device, port->port_num, 0, &port_modify); + ib_modify_port(ib_device, port->port_num, 0, &port_modify); ib_unregister_mad_agent(port->mad_agent); cm_remove_port_fs(port); } kobject_put(&cm_dev->dev_obj); } -static void cm_remove_one(struct ib_device *device) +static void cm_remove_one(struct ib_device *ib_device) { struct cm_device *cm_dev; struct cm_port *port; @@ -3770,7 +3771,7 @@ static void cm_remove_one(struct ib_device *device) unsigned long flags; int i; - cm_dev = ib_get_client_data(device, &cm_client); + cm_dev = ib_get_client_data(ib_device, &cm_client); if (!cm_dev) return; @@ -3778,9 +3779,9 @@ static void cm_remove_one(struct ib_device *device) list_del(&cm_dev->list); write_unlock_irqrestore(&cm.device_lock, flags); - for (i = 1; i <= device->phys_port_cnt; i++) { + for (i = 1; i <= ib_device->phys_port_cnt; i++) { port = cm_dev->port[i-1]; - ib_modify_port(device, port->port_num, 0, &port_modify); + ib_modify_port(ib_device, port->port_num, 0, &port_modify); ib_unregister_mad_agent(port->mad_agent); flush_workqueue(cm.wq); cm_remove_port_fs(port); -- cgit v0.10.2 From 110cf374a809817d5c080c0ac82d65d029820a66 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 May 2008 10:17:53 +0300 Subject: infiniband: make cm_device use a struct device and not a kobject. This object really should be a struct device, or at least contain a pointer to a struct device, as it is trying to create a separate device tree outside of the main device tree. This patch fixes this problem. It is needed for the class core rework that is being done in the driver core. Cc: Kay Sievers Cc: Roland Dreier Cc: Sean Hefty Cc: Hal Rosenstock Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 8dc4429..922d35f 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -163,7 +164,7 @@ struct cm_port { struct cm_device { struct list_head list; struct ib_device *ib_device; - struct kobject dev_obj; + struct device *device; u8 ack_delay; struct cm_port *port[0]; }; @@ -3618,18 +3619,6 @@ static struct kobj_type cm_port_obj_type = { .release = cm_release_port_obj }; -static void cm_release_dev_obj(struct kobject *obj) -{ - struct cm_device *cm_dev; - - cm_dev = container_of(obj, struct cm_device, dev_obj); - kfree(cm_dev); -} - -static struct kobj_type cm_dev_obj_type = { - .release = cm_release_dev_obj -}; - struct class cm_class = { .name = "infiniband_cm", }; @@ -3640,7 +3629,7 @@ static int cm_create_port_fs(struct cm_port *port) int i, ret; ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type, - &port->cm_dev->dev_obj, + &port->cm_dev->device->kobj, "%d", port->port_num); if (ret) { kfree(port); @@ -3702,10 +3691,10 @@ static void cm_add_one(struct ib_device *ib_device) cm_dev->ib_device = ib_device; cm_get_ack_delay(cm_dev); - ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type, - &cm_class.subsys.kobj, "%s", - ib_device->name); - if (ret) { + cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev, + MKDEV(0, 0), NULL, + "%s", ib_device->name); + if (!cm_dev->device) { kfree(cm_dev); return; } @@ -3758,7 +3747,7 @@ error1: ib_unregister_mad_agent(port->mad_agent); cm_remove_port_fs(port); } - kobject_put(&cm_dev->dev_obj); + device_unregister(cm_dev->device); } static void cm_remove_one(struct ib_device *ib_device) @@ -3786,7 +3775,7 @@ static void cm_remove_one(struct ib_device *ib_device) flush_workqueue(cm.wq); cm_remove_port_fs(port); } - kobject_put(&cm_dev->dev_obj); + device_unregister(cm_dev->device); } static int __init ib_cm_init(void) -- cgit v0.10.2 From 16be63fd1670000b96b76cb55b6f1bead21b4c4b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 May 2008 11:50:16 -0700 Subject: bluetooth: remove improper bluetooth class symlinks. Don't create symlinks in a class to a device that is not owned by the class. If the bluetooth subsystem really wants to point to all of the devices it controls, it needs to create real devices, not fake symlinks. Cc: Maxim Krasnyansky Cc: Kay Sievers Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 844ca5f..c85bf8f 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -398,10 +398,6 @@ int hci_register_sysfs(struct hci_dev *hdev) if (device_create_file(dev, bt_attrs[i]) < 0) BT_ERR("Failed to create device attribute"); - if (sysfs_create_link(&bt_class->subsys.kobj, - &dev->kobj, kobject_name(&dev->kobj)) < 0) - BT_ERR("Failed to create class symlink"); - return 0; } @@ -409,9 +405,6 @@ void hci_unregister_sysfs(struct hci_dev *hdev) { BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); - sysfs_remove_link(&bt_class->subsys.kobj, - kobject_name(&hdev->dev.kobj)); - device_del(&hdev->dev); } -- cgit v0.10.2 From 7c71448b8aa80123fc521563d5f7c63a099d97ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2008 18:17:41 -0500 Subject: class: move driver core specific parts to a private structure This moves the portions of struct class that are dynamic (kobject and lock and lists) out of the main structure and into a dynamic, private, structure. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index 2c9ae43..0ec372a 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -36,6 +36,33 @@ struct driver_private { }; #define to_driver(obj) container_of(obj, struct driver_private, kobj) + +/** + * struct class_private - structure to hold the private to the driver core portions of the class structure. + * + * @subsys - the struct kset that defines this class. This is the main kobject + * @children - list of class_devices associated with this class + * @devices - list of devices associated with this class + * @interfaces - list of class_interfaces associated with this class + * @class_dirs - + * @sem - semaphore to protect the children, devices, and interfaces lists. + * @class - pointer back to the struct class that this structure is associated + * with. + * + * This structure is the one that is the actual kobject allowing struct + * class to be statically allocated safely. Nothing outside of the driver + * core should ever touch these fields. + */ +struct class_private { + struct kset subsys; + struct list_head devices; + struct list_head interfaces; + struct kset class_dirs; + struct semaphore sem; + struct class *class; +}; +#define to_class(obj) container_of(obj, struct class_private, subsys.kobj) + /* initialisation functions */ extern int devices_init(void); extern int buses_init(void); diff --git a/drivers/base/class.c b/drivers/base/class.c index 3918d0e..06f09c9 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -21,17 +21,16 @@ #include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) -#define to_class(obj) container_of(obj, struct class, subsys.kobj) static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct class_attribute *class_attr = to_class_attr(attr); - struct class *dc = to_class(kobj); + struct class_private *cp = to_class(kobj); ssize_t ret = -EIO; if (class_attr->show) - ret = class_attr->show(dc, buf); + ret = class_attr->show(cp->class, buf); return ret; } @@ -39,17 +38,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { struct class_attribute *class_attr = to_class_attr(attr); - struct class *dc = to_class(kobj); + struct class_private *cp = to_class(kobj); ssize_t ret = -EIO; if (class_attr->store) - ret = class_attr->store(dc, buf, count); + ret = class_attr->store(cp->class, buf, count); return ret; } static void class_release(struct kobject *kobj) { - struct class *class = to_class(kobj); + struct class_private *cp = to_class(kobj); + struct class *class = cp->class; pr_debug("class '%s': release.\n", class->name); @@ -78,7 +78,7 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) { int error; if (cls) - error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); + error = sysfs_create_file(&cls->p->subsys.kobj, &attr->attr); else error = -EINVAL; return error; @@ -87,21 +87,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) void class_remove_file(struct class *cls, const struct class_attribute *attr) { if (cls) - sysfs_remove_file(&cls->subsys.kobj, &attr->attr); + sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr); } static struct class *class_get(struct class *cls) { if (cls) - return container_of(kset_get(&cls->subsys), - struct class, subsys); - return NULL; + kset_get(&cls->p->subsys); + return cls; } static void class_put(struct class *cls) { if (cls) - kset_put(&cls->subsys); + kset_put(&cls->p->subsys); } static int add_class_attrs(struct class *cls) @@ -136,17 +135,23 @@ static void remove_class_attrs(struct class *cls) int class_register(struct class *cls) { + struct class_private *cp; int error; pr_debug("device class '%s': registering\n", cls->name); - INIT_LIST_HEAD(&cls->devices); - INIT_LIST_HEAD(&cls->interfaces); - kset_init(&cls->class_dirs); - init_MUTEX(&cls->sem); - error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name); - if (error) + cp = kzalloc(sizeof(*cp), GFP_KERNEL); + if (!cp) + return -ENOMEM; + INIT_LIST_HEAD(&cp->devices); + INIT_LIST_HEAD(&cp->interfaces); + kset_init(&cp->class_dirs); + init_MUTEX(&cp->sem); + error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); + if (error) { + kfree(cp); return error; + } /* set the default /sys/dev directory for devices of this class */ if (!cls->dev_kobj) @@ -155,17 +160,21 @@ int class_register(struct class *cls) #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) /* let the block class directory show up in the root of sysfs */ if (cls != &block_class) - cls->subsys.kobj.kset = class_kset; + cp->subsys.kobj.kset = class_kset; #else - cls->subsys.kobj.kset = class_kset; + cp->subsys.kobj.kset = class_kset; #endif - cls->subsys.kobj.ktype = &class_ktype; + cp->subsys.kobj.ktype = &class_ktype; + cp->class = cls; + cls->p = cp; - error = kset_register(&cls->subsys); - if (!error) { - error = add_class_attrs(class_get(cls)); - class_put(cls); + error = kset_register(&cp->subsys); + if (error) { + kfree(cp); + return error; } + error = add_class_attrs(class_get(cls)); + class_put(cls); return error; } @@ -173,7 +182,7 @@ void class_unregister(struct class *cls) { pr_debug("device class '%s': unregistering\n", cls->name); remove_class_attrs(cls); - kset_unregister(&cls->subsys); + kset_unregister(&cls->p->subsys); } static void class_create_release(struct class *cls) @@ -280,8 +289,8 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; - down(&class->sem); - list_for_each_entry(dev, &class->devices, node) { + down(&class->p->sem); + list_for_each_entry(dev, &class->p->devices, node) { if (start) { if (start == dev) start = NULL; @@ -293,7 +302,7 @@ int class_for_each_device(struct class *class, struct device *start, if (error) break; } - up(&class->sem); + up(&class->p->sem); return error; } @@ -330,8 +339,8 @@ struct device *class_find_device(struct class *class, struct device *start, if (!class) return NULL; - down(&class->sem); - list_for_each_entry(dev, &class->devices, node) { + down(&class->p->sem); + list_for_each_entry(dev, &class->p->devices, node) { if (start) { if (start == dev) start = NULL; @@ -344,7 +353,7 @@ struct device *class_find_device(struct class *class, struct device *start, } else put_device(dev); } - up(&class->sem); + up(&class->p->sem); return found ? dev : NULL; } @@ -362,13 +371,13 @@ int class_interface_register(struct class_interface *class_intf) if (!parent) return -EINVAL; - down(&parent->sem); - list_add_tail(&class_intf->node, &parent->interfaces); + down(&parent->p->sem); + list_add_tail(&class_intf->node, &parent->p->interfaces); if (class_intf->add_dev) { - list_for_each_entry(dev, &parent->devices, node) + list_for_each_entry(dev, &parent->p->devices, node) class_intf->add_dev(dev, class_intf); } - up(&parent->sem); + up(&parent->p->sem); return 0; } @@ -381,13 +390,13 @@ void class_interface_unregister(struct class_interface *class_intf) if (!parent) return; - down(&parent->sem); + down(&parent->p->sem); list_del_init(&class_intf->node); if (class_intf->remove_dev) { - list_for_each_entry(dev, &parent->devices, node) + list_for_each_entry(dev, &parent->p->devices, node) class_intf->remove_dev(dev, class_intf); } - up(&parent->sem); + up(&parent->p->sem); class_put(parent); } diff --git a/drivers/base/core.c b/drivers/base/core.c index 9f05de6..64c150b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -551,7 +551,7 @@ static struct kobject *get_device_parent(struct device *dev, { /* class devices without a parent live in /sys/class// */ if (dev->class && (!parent || parent->class != dev->class)) - return &dev->class->subsys.kobj; + return &dev->class->p->subsys.kobj; /* all other devices keep their parent */ else if (parent) return &parent->kobj; @@ -597,13 +597,13 @@ static struct kobject *get_device_parent(struct device *dev, parent_kobj = &parent->kobj; /* find our class-directory at the parent and reference it */ - spin_lock(&dev->class->class_dirs.list_lock); - list_for_each_entry(k, &dev->class->class_dirs.list, entry) + spin_lock(&dev->class->p->class_dirs.list_lock); + list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) if (k->parent == parent_kobj) { kobj = kobject_get(k); break; } - spin_unlock(&dev->class->class_dirs.list_lock); + spin_unlock(&dev->class->p->class_dirs.list_lock); if (kobj) return kobj; @@ -611,7 +611,7 @@ static struct kobject *get_device_parent(struct device *dev, k = kobject_create(); if (!k) return NULL; - k->kset = &dev->class->class_dirs; + k->kset = &dev->class->p->class_dirs; retval = kobject_add(k, parent_kobj, "%s", dev->class->name); if (retval < 0) { kobject_put(k); @@ -630,7 +630,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) { /* see if we live in a "glue" directory */ if (!glue_dir || !dev->class || - glue_dir->kset != &dev->class->class_dirs) + glue_dir->kset != &dev->class->p->class_dirs) return; kobject_put(glue_dir); @@ -657,17 +657,17 @@ static int device_add_class_symlinks(struct device *dev) if (!dev->class) return 0; - error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, + error = sysfs_create_link(&dev->kobj, &dev->class->p->subsys.kobj, "subsystem"); if (error) goto out; #ifdef CONFIG_SYSFS_DEPRECATED /* stacked class devices need a symlink in the class directory */ - if (dev->kobj.parent != &dev->class->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->subsys.kobj && device_is_not_partition(dev)) { - error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, - dev->bus_id); + error = sysfs_create_link(&dev->class->p->subsys.kobj, + &dev->kobj, dev->bus_id); if (error) goto out_subsys; } @@ -704,12 +704,12 @@ out_device: if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); out_busid: - if (dev->kobj.parent != &dev->class->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); #else /* link in the class directory pointing to the device */ - error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, + error = sysfs_create_link(&dev->class->p->subsys.kobj, &dev->kobj, dev->bus_id); if (error) goto out_subsys; @@ -723,7 +723,7 @@ out_busid: return 0; out_busid: - sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); #endif out_subsys: @@ -749,14 +749,14 @@ static void device_remove_class_symlinks(struct device *dev) sysfs_remove_link(&dev->kobj, "device"); } - if (dev->kobj.parent != &dev->class->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); #else if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); - sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); #endif sysfs_remove_link(&dev->kobj, "subsystem"); @@ -904,15 +904,16 @@ int device_add(struct device *dev) klist_add_tail(&dev->knode_parent, &parent->klist_children); if (dev->class) { - down(&dev->class->sem); + down(&dev->class->p->sem); /* tie the class to the device */ - list_add_tail(&dev->node, &dev->class->devices); + list_add_tail(&dev->node, &dev->class->p->devices); /* notify any interfaces that the device is here */ - list_for_each_entry(class_intf, &dev->class->interfaces, node) + list_for_each_entry(class_intf, &dev->class->p->interfaces, + node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); - up(&dev->class->sem); + up(&dev->class->p->sem); } Done: put_device(dev); @@ -1013,14 +1014,15 @@ void device_del(struct device *dev) if (dev->class) { device_remove_class_symlinks(dev); - down(&dev->class->sem); + down(&dev->class->p->sem); /* notify any interfaces that the device is now gone */ - list_for_each_entry(class_intf, &dev->class->interfaces, node) + list_for_each_entry(class_intf, &dev->class->p->interfaces, + node) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ list_del_init(&dev->node); - up(&dev->class->sem); + up(&dev->class->p->sem); } device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); @@ -1348,11 +1350,12 @@ int device_rename(struct device *dev, char *new_name) } #else if (dev->class) { - error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, - dev->bus_id); + error = sysfs_create_link(&dev->class->p->subsys.kobj, + &dev->kobj, dev->bus_id); if (error) goto out; - sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); + sysfs_remove_link(&dev->class->p->subsys.kobj, + old_device_name); } #endif diff --git a/include/linux/device.h b/include/linux/device.h index c1f7298..b055608 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -35,6 +35,7 @@ struct device; struct device_driver; struct driver_private; struct class; +struct class_private; struct bus_type; struct bus_type_private; @@ -186,11 +187,6 @@ struct class { const char *name; struct module *owner; - struct kset subsys; - struct list_head devices; - struct list_head interfaces; - struct kset class_dirs; - struct semaphore sem; /* locks children, devices, interfaces */ struct class_attribute *class_attrs; struct device_attribute *dev_attrs; struct kobject *dev_kobj; @@ -204,6 +200,7 @@ struct class { int (*resume)(struct device *dev); struct pm_ops *pm; + struct class_private *p; }; extern struct kobject *sysfs_dev_block_kobj; -- cgit v0.10.2 From 97ae69fdbaa71a8f7dbc20bf10fb349d1759152f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: rename "devices" to "class_devices" in internal class structure This renames the struct class "devices" field to be "class_devices" to make things easier when struct bus_type and struct class merge in the future. It also makes grepping for fields easier as well. Based on an idea from Kay. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index 0ec372a..586c4ca 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -42,7 +42,7 @@ struct driver_private { * * @subsys - the struct kset that defines this class. This is the main kobject * @children - list of class_devices associated with this class - * @devices - list of devices associated with this class + * @class_devices - list of devices associated with this class * @interfaces - list of class_interfaces associated with this class * @class_dirs - * @sem - semaphore to protect the children, devices, and interfaces lists. @@ -55,7 +55,7 @@ struct driver_private { */ struct class_private { struct kset subsys; - struct list_head devices; + struct list_head class_devices; struct list_head interfaces; struct kset class_dirs; struct semaphore sem; diff --git a/drivers/base/class.c b/drivers/base/class.c index 06f09c9..9947560 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -143,7 +143,7 @@ int class_register(struct class *cls) cp = kzalloc(sizeof(*cp), GFP_KERNEL); if (!cp) return -ENOMEM; - INIT_LIST_HEAD(&cp->devices); + INIT_LIST_HEAD(&cp->class_devices); INIT_LIST_HEAD(&cp->interfaces); kset_init(&cp->class_dirs); init_MUTEX(&cp->sem); @@ -290,7 +290,7 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; down(&class->p->sem); - list_for_each_entry(dev, &class->p->devices, node) { + list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) start = NULL; @@ -340,7 +340,7 @@ struct device *class_find_device(struct class *class, struct device *start, return NULL; down(&class->p->sem); - list_for_each_entry(dev, &class->p->devices, node) { + list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) start = NULL; @@ -374,7 +374,7 @@ int class_interface_register(struct class_interface *class_intf) down(&parent->p->sem); list_add_tail(&class_intf->node, &parent->p->interfaces); if (class_intf->add_dev) { - list_for_each_entry(dev, &parent->p->devices, node) + list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->add_dev(dev, class_intf); } up(&parent->p->sem); @@ -393,7 +393,7 @@ void class_interface_unregister(struct class_interface *class_intf) down(&parent->p->sem); list_del_init(&class_intf->node); if (class_intf->remove_dev) { - list_for_each_entry(dev, &parent->p->devices, node) + list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->remove_dev(dev, class_intf); } up(&parent->p->sem); diff --git a/drivers/base/core.c b/drivers/base/core.c index 64c150b..52d1e71 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -906,7 +906,7 @@ int device_add(struct device *dev) if (dev->class) { down(&dev->class->p->sem); /* tie the class to the device */ - list_add_tail(&dev->node, &dev->class->p->devices); + list_add_tail(&dev->node, &dev->class->p->class_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, &dev->class->p->interfaces, -- cgit v0.10.2 From 184f1f779d5a2e62de4a0b34842ddf8546beca8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: rename "interfaces" to "class_interfaces" in internal class structure This renames the struct class "interfaces" field to be "class_interfaces" to make things easier when struct bus_type and struct class merge in the future. It also makes grepping for fields easier as well. Based on an idea from Kay. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index 586c4ca..670b95a 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -43,7 +43,7 @@ struct driver_private { * @subsys - the struct kset that defines this class. This is the main kobject * @children - list of class_devices associated with this class * @class_devices - list of devices associated with this class - * @interfaces - list of class_interfaces associated with this class + * @class_interfaces - list of class_interfaces associated with this class * @class_dirs - * @sem - semaphore to protect the children, devices, and interfaces lists. * @class - pointer back to the struct class that this structure is associated @@ -56,7 +56,7 @@ struct driver_private { struct class_private { struct kset subsys; struct list_head class_devices; - struct list_head interfaces; + struct list_head class_interfaces; struct kset class_dirs; struct semaphore sem; struct class *class; diff --git a/drivers/base/class.c b/drivers/base/class.c index 9947560..48b518e 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -144,7 +144,7 @@ int class_register(struct class *cls) if (!cp) return -ENOMEM; INIT_LIST_HEAD(&cp->class_devices); - INIT_LIST_HEAD(&cp->interfaces); + INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); init_MUTEX(&cp->sem); error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); @@ -372,7 +372,7 @@ int class_interface_register(struct class_interface *class_intf) return -EINVAL; down(&parent->p->sem); - list_add_tail(&class_intf->node, &parent->p->interfaces); + list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->add_dev(dev, class_intf); diff --git a/drivers/base/core.c b/drivers/base/core.c index 52d1e71..76fdd41 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -909,8 +909,8 @@ int device_add(struct device *dev) list_add_tail(&dev->node, &dev->class->p->class_devices); /* notify any interfaces that the device is here */ - list_for_each_entry(class_intf, &dev->class->p->interfaces, - node) + list_for_each_entry(class_intf, + &dev->class->p->class_interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); up(&dev->class->p->sem); @@ -1016,8 +1016,8 @@ void device_del(struct device *dev) down(&dev->class->p->sem); /* notify any interfaces that the device is now gone */ - list_for_each_entry(class_intf, &dev->class->p->interfaces, - node) + list_for_each_entry(class_intf, + &dev->class->p->class_interfaces, node) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ -- cgit v0.10.2 From 1fbfee6c6dc0f4a4c587b6b163ee79643fc9aaa7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: rename "subsys" to "class_subsys" in internal class structure This renames the struct class "subsys" field to be "class_subsys" to make things easier when struct bus_type and struct class merge in the future. It also makes grepping for fields easier as well. Based on an idea from Kay. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index 670b95a..a77d4bd 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -40,7 +40,7 @@ struct driver_private { /** * struct class_private - structure to hold the private to the driver core portions of the class structure. * - * @subsys - the struct kset that defines this class. This is the main kobject + * @class_subsys - the struct kset that defines this class. This is the main kobject * @children - list of class_devices associated with this class * @class_devices - list of devices associated with this class * @class_interfaces - list of class_interfaces associated with this class @@ -54,14 +54,15 @@ struct driver_private { * core should ever touch these fields. */ struct class_private { - struct kset subsys; + struct kset class_subsys; struct list_head class_devices; struct list_head class_interfaces; struct kset class_dirs; struct semaphore sem; struct class *class; }; -#define to_class(obj) container_of(obj, struct class_private, subsys.kobj) +#define to_class(obj) \ + container_of(obj, struct class_private, class_subsys.kobj) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/class.c b/drivers/base/class.c index 48b518e..86778b8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -70,7 +70,7 @@ static struct kobj_type class_ktype = { .release = class_release, }; -/* Hotplug events for classes go to the class_obj subsys */ +/* Hotplug events for classes go to the class class_subsys */ static struct kset *class_kset; @@ -78,7 +78,8 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) { int error; if (cls) - error = sysfs_create_file(&cls->p->subsys.kobj, &attr->attr); + error = sysfs_create_file(&cls->p->class_subsys.kobj, + &attr->attr); else error = -EINVAL; return error; @@ -87,20 +88,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) void class_remove_file(struct class *cls, const struct class_attribute *attr) { if (cls) - sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr); + sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr); } static struct class *class_get(struct class *cls) { if (cls) - kset_get(&cls->p->subsys); + kset_get(&cls->p->class_subsys); return cls; } static void class_put(struct class *cls) { if (cls) - kset_put(&cls->p->subsys); + kset_put(&cls->p->class_subsys); } static int add_class_attrs(struct class *cls) @@ -147,7 +148,7 @@ int class_register(struct class *cls) INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); init_MUTEX(&cp->sem); - error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); + error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name); if (error) { kfree(cp); return error; @@ -160,15 +161,15 @@ int class_register(struct class *cls) #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) /* let the block class directory show up in the root of sysfs */ if (cls != &block_class) - cp->subsys.kobj.kset = class_kset; + cp->class_subsys.kobj.kset = class_kset; #else - cp->subsys.kobj.kset = class_kset; + cp->class_subsys.kobj.kset = class_kset; #endif - cp->subsys.kobj.ktype = &class_ktype; + cp->class_subsys.kobj.ktype = &class_ktype; cp->class = cls; cls->p = cp; - error = kset_register(&cp->subsys); + error = kset_register(&cp->class_subsys); if (error) { kfree(cp); return error; @@ -182,7 +183,7 @@ void class_unregister(struct class *cls) { pr_debug("device class '%s': unregistering\n", cls->name); remove_class_attrs(cls); - kset_unregister(&cls->p->subsys); + kset_unregister(&cls->p->class_subsys); } static void class_create_release(struct class *cls) diff --git a/drivers/base/core.c b/drivers/base/core.c index 76fdd41..6e1cff2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -551,7 +551,7 @@ static struct kobject *get_device_parent(struct device *dev, { /* class devices without a parent live in /sys/class// */ if (dev->class && (!parent || parent->class != dev->class)) - return &dev->class->p->subsys.kobj; + return &dev->class->p->class_subsys.kobj; /* all other devices keep their parent */ else if (parent) return &parent->kobj; @@ -657,16 +657,17 @@ static int device_add_class_symlinks(struct device *dev) if (!dev->class) return 0; - error = sysfs_create_link(&dev->kobj, &dev->class->p->subsys.kobj, + error = sysfs_create_link(&dev->kobj, + &dev->class->p->class_subsys.kobj, "subsystem"); if (error) goto out; #ifdef CONFIG_SYSFS_DEPRECATED /* stacked class devices need a symlink in the class directory */ - if (dev->kobj.parent != &dev->class->p->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) { - error = sysfs_create_link(&dev->class->p->subsys.kobj, + error = sysfs_create_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); if (error) goto out_subsys; @@ -704,13 +705,14 @@ out_device: if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); out_busid: - if (dev->kobj.parent != &dev->class->p->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->class_subsys.kobj, + dev->bus_id); #else /* link in the class directory pointing to the device */ - error = sysfs_create_link(&dev->class->p->subsys.kobj, &dev->kobj, - dev->bus_id); + error = sysfs_create_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, dev->bus_id); if (error) goto out_subsys; @@ -723,7 +725,7 @@ out_busid: return 0; out_busid: - sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); #endif out_subsys: @@ -749,14 +751,15 @@ static void device_remove_class_symlinks(struct device *dev) sysfs_remove_link(&dev->kobj, "device"); } - if (dev->kobj.parent != &dev->class->p->subsys.kobj && + if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->class_subsys.kobj, + dev->bus_id); #else if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); - sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); #endif sysfs_remove_link(&dev->kobj, "subsystem"); @@ -1350,11 +1353,11 @@ int device_rename(struct device *dev, char *new_name) } #else if (dev->class) { - error = sysfs_create_link(&dev->class->p->subsys.kobj, + error = sysfs_create_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); if (error) goto out; - sysfs_remove_link(&dev->class->p->subsys.kobj, + sysfs_remove_link(&dev->class->p->class_subsys.kobj, old_device_name); } #endif -- cgit v0.10.2 From d9a0157328507c5f563e16a583cd0a063854aebb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: rename "sem" to "class_sem" in internal class structure This renames the struct class "sem" field to be "class_sem" to make things easier when struct bus_type and struct class merge in the future. It also makes grepping for fields easier as well. Based on an idea from Kay. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index a77d4bd..4435732 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -45,7 +45,7 @@ struct driver_private { * @class_devices - list of devices associated with this class * @class_interfaces - list of class_interfaces associated with this class * @class_dirs - - * @sem - semaphore to protect the children, devices, and interfaces lists. + * @class_sem - semaphore to protect the children, devices, and interfaces lists. * @class - pointer back to the struct class that this structure is associated * with. * @@ -58,7 +58,7 @@ struct class_private { struct list_head class_devices; struct list_head class_interfaces; struct kset class_dirs; - struct semaphore sem; + struct semaphore class_sem; struct class *class; }; #define to_class(obj) \ diff --git a/drivers/base/class.c b/drivers/base/class.c index 86778b8..d24d211 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -147,7 +147,7 @@ int class_register(struct class *cls) INIT_LIST_HEAD(&cp->class_devices); INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); - init_MUTEX(&cp->sem); + init_MUTEX(&cp->class_sem); error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name); if (error) { kfree(cp); @@ -278,7 +278,7 @@ char *make_class_name(const char *name, struct kobject *kobj) * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * - * Note, we hold class->sem in this function, so it can not be + * Note, we hold class->class_sem in this function, so it can not be * re-acquired in @fn, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ @@ -290,7 +290,7 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; - down(&class->p->sem); + down(&class->p->class_sem); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) @@ -303,7 +303,7 @@ int class_for_each_device(struct class *class, struct device *start, if (error) break; } - up(&class->p->sem); + up(&class->p->class_sem); return error; } @@ -326,7 +326,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * We hold class->sem in this function, so it can not be + * We hold class->class_sem in this function, so it can not be * re-acquired in @match, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ @@ -340,7 +340,7 @@ struct device *class_find_device(struct class *class, struct device *start, if (!class) return NULL; - down(&class->p->sem); + down(&class->p->class_sem); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) @@ -354,7 +354,7 @@ struct device *class_find_device(struct class *class, struct device *start, } else put_device(dev); } - up(&class->p->sem); + up(&class->p->class_sem); return found ? dev : NULL; } @@ -372,13 +372,13 @@ int class_interface_register(struct class_interface *class_intf) if (!parent) return -EINVAL; - down(&parent->p->sem); + down(&parent->p->class_sem); list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->add_dev(dev, class_intf); } - up(&parent->p->sem); + up(&parent->p->class_sem); return 0; } @@ -391,13 +391,13 @@ void class_interface_unregister(struct class_interface *class_intf) if (!parent) return; - down(&parent->p->sem); + down(&parent->p->class_sem); list_del_init(&class_intf->node); if (class_intf->remove_dev) { list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->remove_dev(dev, class_intf); } - up(&parent->p->sem); + up(&parent->p->class_sem); class_put(parent); } diff --git a/drivers/base/core.c b/drivers/base/core.c index 6e1cff2..b90ae6f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -907,7 +907,7 @@ int device_add(struct device *dev) klist_add_tail(&dev->knode_parent, &parent->klist_children); if (dev->class) { - down(&dev->class->p->sem); + down(&dev->class->p->class_sem); /* tie the class to the device */ list_add_tail(&dev->node, &dev->class->p->class_devices); @@ -916,7 +916,7 @@ int device_add(struct device *dev) &dev->class->p->class_interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); - up(&dev->class->p->sem); + up(&dev->class->p->class_sem); } Done: put_device(dev); @@ -1017,7 +1017,7 @@ void device_del(struct device *dev) if (dev->class) { device_remove_class_symlinks(dev); - down(&dev->class->p->sem); + down(&dev->class->p->class_sem); /* notify any interfaces that the device is now gone */ list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node) @@ -1025,7 +1025,7 @@ void device_del(struct device *dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ list_del_init(&dev->node); - up(&dev->class->p->sem); + up(&dev->class->p->class_sem); } device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); -- cgit v0.10.2 From 1e41250863cd4de5ffa0678c405d001ca5b62796 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: fix docbook comments for class_private structure Removes a field that has been deleted, and adds a description fo the class_dirs field which was previously undocumented. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index 4435732..c035dc2 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -41,10 +41,9 @@ struct driver_private { * struct class_private - structure to hold the private to the driver core portions of the class structure. * * @class_subsys - the struct kset that defines this class. This is the main kobject - * @children - list of class_devices associated with this class * @class_devices - list of devices associated with this class * @class_interfaces - list of class_interfaces associated with this class - * @class_dirs - + * @class_dirs - "glue" directory for virtual devices associated with this class * @class_sem - semaphore to protect the children, devices, and interfaces lists. * @class - pointer back to the struct class that this structure is associated * with. -- cgit v0.10.2 From d2a3b9146e4f40c2e872d7567c996ef95083d802 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: add lockdep infrastructure This adds the infrastructure to properly handle lockdep issues when the internal class semaphore is changed to a mutex. Matthew wrote the original patch, and Greg fixed it up to work properly with the class_create() function. From: Matthew Wilcox Cc: Kay Sievers Cc: Dave Young Cc: Andrew Morton Cc: James Bottomley Cc: Peter Zijlstra Cc: Ingo Molnar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/class.c b/drivers/base/class.c index d24d211..8900056 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -134,7 +134,7 @@ static void remove_class_attrs(struct class *cls) } } -int class_register(struct class *cls) +int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; int error; @@ -178,6 +178,7 @@ int class_register(struct class *cls) class_put(cls); return error; } +EXPORT_SYMBOL_GPL(__class_register); void class_unregister(struct class *cls) { @@ -203,7 +204,8 @@ static void class_create_release(struct class *cls) * Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy(). */ -struct class *class_create(struct module *owner, const char *name) +struct class *__class_create(struct module *owner, const char *name, + struct lock_class_key *key) { struct class *cls; int retval; @@ -218,7 +220,7 @@ struct class *class_create(struct module *owner, const char *name) cls->owner = owner; cls->class_release = class_create_release; - retval = class_register(cls); + retval = __class_register(cls, key); if (retval) goto error; @@ -228,6 +230,7 @@ error: kfree(cls); return ERR_PTR(retval); } +EXPORT_SYMBOL_GPL(__class_create); /** * class_destroy - destroys a struct class structure @@ -412,9 +415,7 @@ int __init classes_init(void) EXPORT_SYMBOL_GPL(class_create_file); EXPORT_SYMBOL_GPL(class_remove_file); -EXPORT_SYMBOL_GPL(class_register); EXPORT_SYMBOL_GPL(class_unregister); -EXPORT_SYMBOL_GPL(class_create); EXPORT_SYMBOL_GPL(class_destroy); EXPORT_SYMBOL_GPL(class_interface_register); diff --git a/include/linux/device.h b/include/linux/device.h index b055608..0e1d24c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -205,8 +206,18 @@ struct class { extern struct kobject *sysfs_dev_block_kobj; extern struct kobject *sysfs_dev_char_kobj; -extern int __must_check class_register(struct class *class); +extern int __must_check __class_register(struct class *class, + struct lock_class_key *key); extern void class_unregister(struct class *class); + +/* This is a #define to keep the compiler from merging different + * instances of the __key variable */ +#define class_register(class) \ +({ \ + static struct lock_class_key __key; \ + __class_register(class, &__key); \ +}) + extern int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -239,9 +250,19 @@ struct class_interface { extern int __must_check class_interface_register(struct class_interface *); extern void class_interface_unregister(struct class_interface *); -extern struct class *class_create(struct module *owner, const char *name); +extern struct class * __must_check __class_create(struct module *owner, + const char *name, + struct lock_class_key *key); extern void class_destroy(struct class *cls); +/* This is a #define to keep the compiler from merging different + * instances of the __key variable */ +#define class_create(owner, name) \ +({ \ + static struct lock_class_key __key; \ + __class_create(owner, name, &__key); \ +}) + /* * The type of device, "struct device" is embedded in. A class * or bus can contain devices of different types -- cgit v0.10.2 From f75b1c60fc1e53c4004a79ea0be071aa3318cdcc Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 28 May 2008 09:28:39 -0700 Subject: class: change internal semaphore to a mutex Now that the lockdep infrastructure in the class core is in place, we should be able to properly change the internal class semaphore to be a mutex. David wrote the original patch, and Greg fixed it up to apply properly due to all of the recent changes in this area. From: Dave Young Cc: Matthew Wilcox Cc: Kay Sievers Cc: Andrew Morton Cc: James Bottomley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/base.h b/drivers/base/base.h index c035dc2..31dc0cd 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -44,7 +44,7 @@ struct driver_private { * @class_devices - list of devices associated with this class * @class_interfaces - list of class_interfaces associated with this class * @class_dirs - "glue" directory for virtual devices associated with this class - * @class_sem - semaphore to protect the children, devices, and interfaces lists. + * @class_mutex - mutex to protect the children, devices, and interfaces lists. * @class - pointer back to the struct class that this structure is associated * with. * @@ -57,7 +57,7 @@ struct class_private { struct list_head class_devices; struct list_head class_interfaces; struct kset class_dirs; - struct semaphore class_sem; + struct mutex class_mutex; struct class *class; }; #define to_class(obj) \ diff --git a/drivers/base/class.c b/drivers/base/class.c index 8900056..839d27c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) @@ -147,7 +148,7 @@ int __class_register(struct class *cls, struct lock_class_key *key) INIT_LIST_HEAD(&cp->class_devices); INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); - init_MUTEX(&cp->class_sem); + __mutex_init(&cp->class_mutex, "struct class mutex", key); error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name); if (error) { kfree(cp); @@ -281,7 +282,7 @@ char *make_class_name(const char *name, struct kobject *kobj) * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * - * Note, we hold class->class_sem in this function, so it can not be + * Note, we hold class->class_mutex in this function, so it can not be * re-acquired in @fn, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ @@ -293,7 +294,7 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; - down(&class->p->class_sem); + mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) @@ -306,7 +307,7 @@ int class_for_each_device(struct class *class, struct device *start, if (error) break; } - up(&class->p->class_sem); + mutex_unlock(&class->p->class_mutex); return error; } @@ -329,7 +330,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * We hold class->class_sem in this function, so it can not be + * We hold class->class_mutex in this function, so it can not be * re-acquired in @match, otherwise it will self-deadlocking. For * example, calls to add or remove class members would be verboten. */ @@ -343,7 +344,7 @@ struct device *class_find_device(struct class *class, struct device *start, if (!class) return NULL; - down(&class->p->class_sem); + mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { if (start == dev) @@ -357,7 +358,7 @@ struct device *class_find_device(struct class *class, struct device *start, } else put_device(dev); } - up(&class->p->class_sem); + mutex_unlock(&class->p->class_mutex); return found ? dev : NULL; } @@ -375,13 +376,13 @@ int class_interface_register(struct class_interface *class_intf) if (!parent) return -EINVAL; - down(&parent->p->class_sem); + mutex_lock(&parent->p->class_mutex); list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->add_dev(dev, class_intf); } - up(&parent->p->class_sem); + mutex_unlock(&parent->p->class_mutex); return 0; } @@ -394,13 +395,13 @@ void class_interface_unregister(struct class_interface *class_intf) if (!parent) return; - down(&parent->p->class_sem); + mutex_lock(&parent->p->class_mutex); list_del_init(&class_intf->node); if (class_intf->remove_dev) { list_for_each_entry(dev, &parent->p->class_devices, node) class_intf->remove_dev(dev, class_intf); } - up(&parent->p->class_sem); + mutex_unlock(&parent->p->class_mutex); class_put(parent); } diff --git a/drivers/base/core.c b/drivers/base/core.c index b90ae6f..c05b115 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -907,7 +908,7 @@ int device_add(struct device *dev) klist_add_tail(&dev->knode_parent, &parent->klist_children); if (dev->class) { - down(&dev->class->p->class_sem); + mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ list_add_tail(&dev->node, &dev->class->p->class_devices); @@ -916,7 +917,7 @@ int device_add(struct device *dev) &dev->class->p->class_interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); - up(&dev->class->p->class_sem); + mutex_unlock(&dev->class->p->class_mutex); } Done: put_device(dev); @@ -1017,7 +1018,7 @@ void device_del(struct device *dev) if (dev->class) { device_remove_class_symlinks(dev); - down(&dev->class->p->class_sem); + mutex_lock(&dev->class->p->class_mutex); /* notify any interfaces that the device is now gone */ list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node) @@ -1025,7 +1026,7 @@ void device_del(struct device *dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ list_del_init(&dev->node); - up(&dev->class->p->class_sem); + mutex_unlock(&dev->class->p->class_mutex); } device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); -- cgit v0.10.2 From aab0de245150c09e61c30962feb16aacde508dc3 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 2 May 2008 06:02:41 +0200 Subject: driver core: remove KOBJ_NAME_LEN define Kobjects do not have a limit in name size since a while, so stop pretending that they do. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 6f33f58..848fdca 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -334,7 +334,7 @@ static int omap_mbox_init(struct omap_mbox *mbox) } mbox->dev.class = &omap_mbox_class; - strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); + strlcpy(mbox->dev.bus_id, mbox->name, BUS_ID_SIZE); dev_set_drvdata(&mbox->dev, mbox); ret = device_register(&mbox->dev); diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index e78b351..ecbb8b6 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -224,7 +224,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, if (!strcmp(type, "domain-services-port")) bus_id_name = "ds"; - if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) { + if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) { printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n", bus_id_name); return NULL; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 75e599b..34402c4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1670,7 +1670,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); spin_lock_init(&ioc->fault_reset_work_lock); - snprintf(ioc->reset_work_q_name, KOBJ_NAME_LEN, "mpt_poll_%d", ioc->id); + snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name), + "mpt_poll_%d", ioc->id); ioc->reset_work_q = create_singlethread_workqueue(ioc->reset_work_q_name); if (!ioc->reset_work_q) { diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6adab64..dff048c 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -707,12 +707,12 @@ typedef struct _MPT_ADAPTER u8 fc_link_speed[2]; spinlock_t fc_rescan_work_lock; struct work_struct fc_rescan_work; - char fc_rescan_work_q_name[KOBJ_NAME_LEN]; + char fc_rescan_work_q_name[20]; struct workqueue_struct *fc_rescan_work_q; struct scsi_cmnd **ScsiLookup; spinlock_t scsi_lookup_lock; - char reset_work_q_name[KOBJ_NAME_LEN]; + char reset_work_q_name[20]; struct workqueue_struct *reset_work_q; struct delayed_work fault_reset_work; spinlock_t fault_reset_work_lock; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index fc31ca6..b36cae9 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1326,8 +1326,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* initialize workqueue */ - snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d", - sh->host_no); + snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), + "mptfc_wq_%d", sh->host_no); ioc->fc_rescan_work_q = create_singlethread_workqueue(ioc->fc_rescan_work_q_name); if (!ioc->fc_rescan_work_q) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index eecf7cb..5a58b07 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -36,7 +36,7 @@ #define _ACPIPHP_H #include -#include /* for KOBJ_NAME_LEN */ +#include #include #include @@ -51,7 +51,7 @@ #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) /* name size which is used for entries in pcihpfs */ -#define SLOT_NAME_SIZE KOBJ_NAME_LEN /* {_SUN} */ +#define SLOT_NAME_SIZE 20 /* {_SUN} */ struct acpiphp_bridge; struct acpiphp_slot; diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 78dad28..fed0b02 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -232,8 +232,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) } if (shost->transportt->create_work_queue) { - snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d", - shost->host_no); + snprintf(shost->work_q_name, sizeof(shost->work_q_name), + "scsi_wq_%d", shost->host_no); shost->work_q = create_singlethread_workqueue( shost->work_q_name); if (!shost->work_q) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5fd64e7..a272b9a 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -417,15 +417,16 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, fc_host->next_vport_number = 0; fc_host->npiv_vports_inuse = 0; - snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d", - shost->host_no); + snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name), + "fc_wq_%d", shost->host_no); fc_host->work_q = create_singlethread_workqueue( fc_host->work_q_name); if (!fc_host->work_q) return -ENOMEM; - snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d", - shost->host_no); + snprintf(fc_host->devloss_work_q_name, + sizeof(fc_host->devloss_work_q_name), + "fc_dl_%d", shost->host_no); fc_host->devloss_work_q = create_singlethread_workqueue( fc_host->devloss_work_q_name); if (!fc_host->devloss_work_q) { diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 06748f3..043c392 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -247,8 +247,8 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); - snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", - shost->host_no); + snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name), + "iscsi_scan_%d", shost->host_no); ihost->scan_workq = create_singlethread_workqueue( ihost->scan_workq_name); if (!ihost->scan_workq) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 6149e4b..efef715 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -401,7 +401,7 @@ void register_disk(struct gendisk *disk) disk->dev.parent = disk->driverfs_dev; disk->dev.devt = MKDEV(disk->major, disk->first_minor); - strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN); + strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); /* ewww... some of these buggers have / in the name... */ s = strchr(disk->dev.bus_id, '/'); if (s) diff --git a/include/linux/device.h b/include/linux/device.h index 0e1d24c..fba1bb0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -29,8 +29,7 @@ /* DEVICE_NAME_HALF is really less than half to accommodate slop */ #define DEVICE_NAME_HALF __stringify(20) #define DEVICE_ID_SIZE 32 -#define BUS_ID_SIZE KOBJ_NAME_LEN - +#define BUS_ID_SIZE 20 struct device; struct device_driver; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 39e709f..d542faa 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -26,7 +26,6 @@ #include #include -#define KOBJ_NAME_LEN 20 #define UEVENT_HELPER_PATH_LEN 256 #define UEVENT_NUM_ENVP 32 /* number of env pointers */ #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 387e428..b9a76c9 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -733,7 +733,7 @@ struct spi_board_info { * controller_data goes to spi_device.controller_data, * irq is copied too */ - char modalias[KOBJ_NAME_LEN]; + char modalias[32]; const void *platform_data; void *controller_data; int irq; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 1834fdf..a594bac 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -623,7 +623,7 @@ struct Scsi_Host { /* * Optional work queue to be utilized by the transport */ - char work_q_name[KOBJ_NAME_LEN]; + char work_q_name[20]; struct workqueue_struct *work_q; /* diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 06f72ba..878373c 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -489,9 +489,9 @@ struct fc_host_attrs { u16 npiv_vports_inuse; /* work queues for rport state manipulation */ - char work_q_name[KOBJ_NAME_LEN]; + char work_q_name[20]; struct workqueue_struct *work_q; - char devloss_work_q_name[KOBJ_NAME_LEN]; + char devloss_work_q_name[20]; struct workqueue_struct *devloss_work_q; }; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index f5444e0..8b6c91d 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -198,7 +198,7 @@ struct iscsi_cls_host { atomic_t nr_scans; struct mutex mutex; struct workqueue_struct *scan_workq; - char scan_workq_name[KOBJ_NAME_LEN]; + char scan_workq_name[20]; }; extern void iscsi_host_for_each_session(struct Scsi_Host *shost, -- cgit v0.10.2 From ca52a49846f1451163c0dc14c40cd06ff808df3e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 2 May 2008 06:02:41 +0200 Subject: driver core: remove DEVICE_NAME_SIZE define There is no such thing as a "device name size" in the driver core, so remove the define and fix up any users of this odd define in the rest of the kernel. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/eisa/Makefile b/drivers/eisa/Makefile index 70abf93f..5369ce9 100644 --- a/drivers/eisa/Makefile +++ b/drivers/eisa/Makefile @@ -9,7 +9,7 @@ obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o # Ugly hack to get DEVICE_NAME_SIZE value... -DEVICE_NAME_SIZE =$(shell awk '$$1=="\#define" && $$2=="DEVICE_NAME_SIZE" {print $$3-1}' $(srctree)/include/linux/device.h) +DEVICE_NAME_SIZE = 50 $(obj)/eisa-bus.o: $(obj)/devlist.h diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 65dcf04..c950bf8 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -22,7 +22,7 @@ struct eisa_device_info { struct eisa_device_id id; - char name[DEVICE_NAME_SIZE]; + char name[50]; }; #ifdef CONFIG_EISA_NAMES @@ -63,7 +63,7 @@ static void __init eisa_name_device (struct eisa_device *edev) if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) { strlcpy (edev->pretty_name, eisa_table[i].name, - DEVICE_NAME_SIZE); + sizeof(edev->pretty_name)); return; } } diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c index 67b8e94..ef2dbfe 100644 --- a/drivers/mca/mca-bus.c +++ b/drivers/mca/mca-bus.c @@ -40,7 +40,7 @@ static struct mca_bus *mca_root_busses[MAX_MCA_BUSSES]; struct mca_device_info { short pos_id; /* the 2 byte pos id for this card */ - char name[DEVICE_NAME_SIZE]; + char name[50]; }; static int mca_bus_match (struct device *dev, struct device_driver *drv) diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 24ee96c..07b6add 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1872,7 +1872,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; struct fb_var_screeninfo var; - char video_card[DEVICE_NAME_SIZE]; + char video_card[50]; u8 chip_rev; u32 dac; diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index c347e38..ccbfffd 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -289,7 +289,7 @@ struct radeonfb_info { struct radeon_regs state; struct radeon_regs init_state; - char name[DEVICE_NAME_SIZE]; + char name[50]; unsigned long mmio_base_phys; unsigned long fb_base_phys; diff --git a/include/linux/device.h b/include/linux/device.h index fba1bb0..894fdb2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -25,9 +25,6 @@ #include #include -#define DEVICE_NAME_SIZE 50 -/* DEVICE_NAME_HALF is really less than half to accommodate slop */ -#define DEVICE_NAME_HALF __stringify(20) #define DEVICE_ID_SIZE 32 #define BUS_ID_SIZE 20 diff --git a/include/linux/eisa.h b/include/linux/eisa.h index fe806b6..e61c0be 100644 --- a/include/linux/eisa.h +++ b/include/linux/eisa.h @@ -40,7 +40,7 @@ struct eisa_device { u64 dma_mask; struct device dev; /* generic device */ #ifdef CONFIG_EISA_NAMES - char pretty_name[DEVICE_NAME_SIZE]; + char pretty_name[50]; #endif }; -- cgit v0.10.2 From b98cb4b7fe0e83238501b48489e46b3e0dce9aaf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 May 2008 06:02:41 +0200 Subject: driver core: remove DEVICE_ID_SIZE define There is no such thing as a "device id size" in the driver core, so remove the define and fix up any users of this odd define in the rest of the kernel. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index a054668..4e3bfbc 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -51,7 +51,7 @@ struct jmb38x_ms_host { void __iomem *addr; spinlock_t lock; int id; - char host_id[DEVICE_ID_SIZE]; + char host_id[32]; int irq; unsigned int block_pos; unsigned long timeout_jiffies; @@ -781,7 +781,7 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) spin_lock_init(&host->lock); host->id = cnt; - snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", + snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d", host->id); host->irq = jm->pdev->irq; host->timeout_jiffies = msecs_to_jiffies(1000); diff --git a/include/linux/device.h b/include/linux/device.h index 894fdb2..d24a47f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -25,7 +25,6 @@ #include #include -#define DEVICE_ID_SIZE 32 #define BUS_ID_SIZE 20 struct device; -- cgit v0.10.2 From fc3a8828b139c24aade3f9d608775e36c248f8f5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 May 2008 06:02:41 +0200 Subject: driver core: fix a lot of printk usages of bus_id We have the dev_printk() variants for this kind of thing, use them instead of directly trying to access the bus_id field of struct device. This is done in order to remove bus_id entirely. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 2744673..dd29473 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -554,9 +554,8 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC); if (!device_info) { - printk(KERN_ERR - "Could not allocated dmabounce_device_info for %s", - dev->bus_id); + dev_err(dev, + "Could not allocated dmabounce_device_info\n"); return -ENOMEM; } @@ -594,8 +593,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, dev->archdata.dmabounce = device_info; - printk(KERN_INFO "dmabounce: registered device %s on %s bus\n", - dev->bus_id, dev->bus->name); + dev_info(dev, "dmabounce: registered device\n"); return 0; @@ -614,16 +612,15 @@ dmabounce_unregister_dev(struct device *dev) dev->archdata.dmabounce = NULL; if (!device_info) { - printk(KERN_WARNING - "%s: Never registered with dmabounce but attempting" \ - "to unregister!\n", dev->bus_id); + dev_warn(dev, + "Never registered with dmabounce but attempting" + "to unregister!\n"); return; } if (!list_empty(&device_info->safe_buffers)) { - printk(KERN_ERR - "%s: Removing from dmabounce with pending buffers!\n", - dev->bus_id); + dev_err(dev, + "Removing from dmabounce with pending buffers!\n"); BUG(); } @@ -639,8 +636,7 @@ dmabounce_unregister_dev(struct device *dev) kfree(device_info); - printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n", - dev->bus_id, dev->bus->name); + dev_info(dev, "dmabounce: device unregistered\n"); } diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index eb06d0b..2048ae0 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -593,7 +593,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, if (dev->dma_mask != 0xffffffffUL) { ret = dmabounce_register_dev(&dev->dev, 1024, 4096); if (ret) { - printk("SA1111: Failed to register %s with dmabounce", dev->dev.bus_id); + dev_err(&dev->dev, "SA1111: Failed to register" + " with dmabounce\n"); device_unregister(&dev->dev); } } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 8bfd299..2de425f 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -853,8 +853,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot) for (i = 0; i < ECARD_NUM_RESOURCES; i++) { if (ec->resource[i].flags && request_resource(&iomem_resource, &ec->resource[i])) { - printk(KERN_ERR "%s: resource(s) not available\n", - ec->dev.bus_id); + dev_err(&ec->dev, "resource(s) not available\n"); ec->resource[i].end -= ec->resource[i].start; ec->resource[i].start = 0; ec->resource[i].flags = 0; diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 62e653a3..619d05e 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -407,8 +407,7 @@ static int impd1_probe(struct lm_device *dev) ret = amba_device_register(d, &dev->resource); if (ret) { - printk("unable to register device %s: %d\n", - d->dev.bus_id, ret); + dev_err(&d->dev, "unable to register device: %d\n"); kfree(d); } } diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 609c46d..768c262 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -367,7 +367,7 @@ static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) viaisa = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL); if (!viaisa) return; - printk("Fixing VIA IDE, force legacy mode on '%s'\n", viaide->dev.bus_id); + dev_info(&viaide->dev, "Fixing VIA IDE, force legacy mode on\n"); pci_read_config_byte(viaide, PCI_CLASS_PROG, &progif); pci_write_config_byte(viaide, PCI_CLASS_PROG, progif & ~0x5); diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a4213c0..cbecb05 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -314,8 +314,7 @@ int dma_supported(struct device *dev, u64 mask) { #ifdef CONFIG_PCI if (mask > 0xffffffff && forbid_dac > 0) { - printk(KERN_INFO "PCI: Disallowing DAC for device %s\n", - dev->bus_id); + dev_info(dev, "PCI: Disallowing DAC for device\n"); return 0; } #endif @@ -342,8 +341,7 @@ int dma_supported(struct device *dev, u64 mask) type. Normally this doesn't make any difference, but gives more gentle handling of IOMMU overflow. */ if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) { - printk(KERN_INFO "%s: Force SAC with mask %Lx\n", - dev->bus_id, mask); + dev_info(dev, "Force SAC with mask %Lx\n", mask); return 0; } diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index be60961..df5f142 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -198,9 +198,7 @@ static void iommu_full(struct device *dev, size_t size, int dir) * out. Hopefully no network devices use single mappings that big. */ - printk(KERN_ERR - "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", - size, dev->bus_id); + dev_err(dev, "PCI-DMA: Out of IOMMU space for %lu bytes\n", size); if (size > PAGE_SIZE*EMERGENCY_PAGES) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 55c17af..2655bc1 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -263,22 +263,22 @@ static int acpi_fan_add(struct acpi_device *device) goto end; } - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, cdev->id); + dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); acpi_driver_data(device) = cdev; result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, "thermal_cooling"); if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); + dev_err(&device->dev, "Failed to create sysfs link " + "'thermal_cooling'\n"); result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj, "device"); if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); + dev_err(&device->dev, "Failed to create sysfs link " + "'device'\n"); result = acpi_fan_add_fs(device); if (result) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 2f173e8..0841095 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -146,8 +146,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) acpi_status status; if (dev->archdata.acpi_handle) { - printk(KERN_WARNING PREFIX - "Drivers changed 'acpi_handle' for %s\n", dev->bus_id); + dev_warn(dev, "Drivers changed 'acpi_handle'\n"); return -EINVAL; } get_device(dev); @@ -195,8 +194,7 @@ static int acpi_unbind_one(struct device *dev) /* acpi_bind_one increase refcnt by one */ put_device(dev); } else { - printk(KERN_ERR PREFIX - "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id); + dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); } return 0; } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ec0f2d5..e36422a 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -714,9 +714,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) goto end; } - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, pr->cdev->id); + dev_info(&device->dev, "registered as cooling_device%d\n", + pr->cdev->id); result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f3132aa..f6f52c1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -471,7 +471,7 @@ static int acpi_device_register(struct acpi_device *device, device->dev.release = &acpi_device_release; result = device_add(&device->dev); if(result) { - printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id); + dev_err(&device->dev, "Error adding device\n"); goto end; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 84c795f..30a3413 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1179,8 +1179,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) tz->tz_enabled = 1; - printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n", - tz->device->dev.bus_id, tz->thermal_zone->id); + dev_info(&tz->device->dev, "registered as thermal_zone%d\n", + tz->thermal_zone->id); return 0; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 64c8893..37b9e16 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -762,9 +762,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (IS_ERR(device->cdev)) return; - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev->dev.bus_id, device->cdev->id); + dev_info(&device->dev->dev, "registered as cooling_device%d\n", + device->cdev->id); result = sysfs_create_link(&device->dev->dev.kobj, &device->cdev->device.kobj, "thermal_cooling"); diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index 9b1b20b..2aa6e8f 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c @@ -194,7 +194,7 @@ static int show_dev_hash(unsigned int value) struct device * dev = to_device(entry); unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); if (hash == value) { - printk(" hash matches device %s\n", dev->bus_id); + dev_info(dev, "hash matches\n"); match++; } entry = entry->prev; -- cgit v0.10.2 From 22454cb99fc39f2629ad06a7eccb3df312f8830e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 28 May 2008 23:06:47 +0200 Subject: pnp: add acpi:* modalias entries Along with the non-modalias conformant "pnp:*" aliases, we add "acpi:*" entries to PNP drivers, to allow module autoloading by ACPI PNP device entries, which export proper modalias information, without any specific userspace modprobe mangling. Cc: Adam Belay Cc: Thomas Renninger Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 37d5c36..1fcaf32 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -340,11 +340,18 @@ static int do_acpi_entry(const char *filename, } /* looks like: "pnp:dD" */ -static int do_pnp_entry(const char *filename, - struct pnp_device_id *id, char *alias) +static void do_pnp_device_entry(void *symval, unsigned long size, + struct module *mod) { - sprintf(alias, "pnp:d%s*", id->id); - return 1; + const unsigned long id_size = sizeof(struct pnp_device_id); + const struct pnp_device_id *id = symval; + + device_id_check(mod->name, "pnp", size, id_size, symval); + + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"pnp:d%s*\");\n", id->id); + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"acpi*:%s:*\");\n", id->id); } /* looks like: "pnp:dD" for every device of the card */ @@ -388,9 +395,12 @@ static void do_pnp_card_entries(void *symval, unsigned long size, } /* add an individual alias for every device entry */ - if (!dup) + if (!dup) { buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"pnp:d%s*\");\n", id); + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"acpi*:%s:*\");\n", id); + } } } } @@ -701,9 +711,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, sizeof(struct acpi_device_id), "acpi", do_acpi_entry, mod); else if (sym_is(symname, "__mod_pnp_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pnp_device_id), "pnp", - do_pnp_entry, mod); + do_pnp_device_entry(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_pnp_card_device_table")) do_pnp_card_entries(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_pcmcia_device_table")) -- cgit v0.10.2 From 934da4766e5f72797118f7c014efaef567a812fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 May 2008 11:37:27 +0200 Subject: UIO: fix UIO Kconfig dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ae210f188614bb3d1ee3f19c64e28e3cdd44877c introduced a big "if UIO"/"endif" where all uio drivers are defined. So know there is no need for them to depend explicitly on UIO. Signed-off-by: Uwe Kleine-König Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index a4aaab9..78e139c 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -15,7 +15,7 @@ if UIO config UIO_CIF tristate "generic Hilscher CIF Card driver" - depends on UIO && PCI + depends on PCI default n help Driver for Hilscher CIF DeviceNet and Profibus cards. This @@ -28,7 +28,6 @@ config UIO_CIF config UIO_SMX tristate "SMX cryptengine UIO interface" - depends on UIO default n help Userspace IO interface to the Cryptography engine found on the -- cgit v0.10.2 From 328a14e70e7f46997cb50d4258dd93d5377f98c6 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Fri, 23 May 2008 13:50:14 +0200 Subject: UIO: Add write function to allow irq masking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes it is necessary to enable/disable the interrupt of a UIO device from the userspace part of the driver. With this patch, the UIO kernel driver can implement an "irqcontrol()" function that does this. Userspace can write an s32 value to /dev/uioX (usually 0 or 1 to turn the irq off or on). The UIO core will then call the driver's irqcontrol function. Signed-off-by: Hans J. Koch Acked-by: Uwe Kleine-König Acked-by: Magnus Damm Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index fdd7f4f..c4d1873 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -30,6 +30,12 @@ + 0.5 + 2008-05-22 + hjk + Added description of write() function. + + 0.4 2007-11-26 hjk @@ -64,7 +70,7 @@ Copyright and License - Copyright (c) 2006 by Hans-Jürgen Koch. + Copyright (c) 2006-2008 by Hans-Jürgen Koch. This documentation is Free Software licensed under the terms of the GPL version 2. @@ -189,6 +195,30 @@ interested in translating it, please email me represents the total interrupt count. You can use this number to figure out if you missed some interrupts. + + For some hardware that has more than one interrupt source internally, + but not separate IRQ mask and status registers, there might be + situations where userspace cannot determine what the interrupt source + was if the kernel handler disables them by writing to the chip's IRQ + register. In such a case, the kernel has to disable the IRQ completely + to leave the chip's register untouched. Now the userspace part can + determine the cause of the interrupt, but it cannot re-enable + interrupts. Another cornercase is chips where re-enabling interrupts + is a read-modify-write operation to a combined IRQ status/acknowledge + register. This would be racy if a new interrupt occurred + simultaneously. + + + To address these problems, UIO also implements a write() function. It + is normally not used and can be ignored for hardware that has only a + single interrupt source or has separate IRQ mask and status registers. + If you need it, however, a write to /dev/uioX + will call the irqcontrol() function implemented + by the driver. You have to write a 32-bit value that is usually either + 0 or 1 to disable or enable interrupts. If a driver does not implement + irqcontrol(), write() will + return with -ENOSYS. + To handle interrupts properly, your custom kernel module can @@ -362,6 +392,14 @@ device is actually used. open(), you will probably also want a custom release() function. + + +int (*irqcontrol)(struct uio_info *info, s32 irq_on) +: Optional. If you need to be able to enable or disable +interrupts from userspace by writing to /dev/uioX, +you can implement this function. The parameter irq_on +will be 0 to disable interrupts and 1 to enable them. + diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 5a7ca2e..3a6934b 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -427,6 +427,31 @@ static ssize_t uio_read(struct file *filep, char __user *buf, return retval; } +static ssize_t uio_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct uio_listener *listener = filep->private_data; + struct uio_device *idev = listener->dev; + ssize_t retval; + s32 irq_on; + + if (idev->info->irq == UIO_IRQ_NONE) + return -EIO; + + if (count != sizeof(s32)) + return -EINVAL; + + if (!idev->info->irqcontrol) + return -ENOSYS; + + if (copy_from_user(&irq_on, buf, count)) + return -EFAULT; + + retval = idev->info->irqcontrol(idev->info, irq_on); + + return retval ? retval : sizeof(s32); +} + static int uio_find_mem_index(struct vm_area_struct *vma) { int mi; @@ -546,6 +571,7 @@ static const struct file_operations uio_fops = { .open = uio_open, .release = uio_release, .read = uio_read, + .write = uio_write, .mmap = uio_mmap, .poll = uio_poll, .fasync = uio_fasync, diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index 973386d..cf65e96 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -53,6 +53,7 @@ struct uio_device; * @mmap: mmap operation for this uio device * @open: open operation for this uio device * @release: release operation for this uio device + * @irqcontrol: disable/enable irqs when 0/1 is written to /dev/uioX */ struct uio_info { struct uio_device *uio_dev; @@ -66,6 +67,7 @@ struct uio_info { int (*mmap)(struct uio_info *info, struct vm_area_struct *vma); int (*open)(struct uio_info *info, struct inode *inode); int (*release)(struct uio_info *info, struct inode *inode); + int (*irqcontrol)(struct uio_info *info, s32 irq_on); }; extern int __must_check -- cgit v0.10.2 From 4d80d59437247075029534adec8d69fce2cfb87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 May 2008 11:37:27 +0200 Subject: UIO: add generic UIO platform driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a generic UIO platform driver. It eliminates the need for a dedicated kernel module for simple platform devices. Users only need to implement their irq handler in platform code and fill a struct uio_info there. This helps avoiding code duplication as UIO platform drivers often share a lot of common code. Signed-off-by: Uwe Kleine-König Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 78e139c..2e9079d 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -26,6 +26,13 @@ config UIO_CIF To compile this driver as a module, choose M here: the module will be called uio_cif. +config UIO_PDRV + tristate "Userspace I/O platform driver" + help + Generic platform driver for Userspace I/O devices. + + If you don't know what to do here, say N. + config UIO_SMX tristate "SMX cryptengine UIO interface" default n diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index 18c4566..e00ce0d 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_UIO) += uio.o obj-$(CONFIG_UIO_CIF) += uio_cif.o +obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o obj-$(CONFIG_UIO_SMX) += uio_smx.o diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c new file mode 100644 index 0000000..5d0d2e8 --- /dev/null +++ b/drivers/uio/uio_pdrv.c @@ -0,0 +1,118 @@ +/* + * drivers/uio/uio_pdrv.c + * + * Copyright (C) 2008 by Digi International Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include + +#define DRIVER_NAME "uio" + +struct uio_platdata { + struct uio_info *uioinfo; +}; + +static int uio_pdrv_probe(struct platform_device *pdev) +{ + struct uio_info *uioinfo = pdev->dev.platform_data; + struct uio_platdata *pdata; + struct uio_mem *uiomem; + int ret = -ENODEV; + int i; + + if (!uioinfo || !uioinfo->name || !uioinfo->version) { + dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__); + goto err_uioinfo; + } + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__); + goto err_alloc_pdata; + } + + pdata->uioinfo = uioinfo; + + uiomem = &uioinfo->mem[0]; + + for (i = 0; i < pdev->num_resources; ++i) { + struct resource *r = &pdev->resource[i]; + + if (r->flags != IORESOURCE_MEM) + continue; + + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { + dev_warn(&pdev->dev, "device has more than " + __stringify(MAX_UIO_MAPS) + " I/O memory resources.\n"); + break; + } + + uiomem->memtype = UIO_MEM_PHYS; + uiomem->addr = r->start; + uiomem->size = r->end - r->start + 1; + ++uiomem; + } + + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { + uiomem->size = 0; + ++uiomem; + } + + pdata->uioinfo->priv = pdata; + + ret = uio_register_device(&pdev->dev, pdata->uioinfo); + + if (ret) { + kfree(pdata); +err_alloc_pdata: +err_uioinfo: + return ret; + } + + platform_set_drvdata(pdev, pdata); + + return 0; +} + +static int uio_pdrv_remove(struct platform_device *pdev) +{ + struct uio_platdata *pdata = platform_get_drvdata(pdev); + + uio_unregister_device(pdata->uioinfo); + + return 0; +} + +static struct platform_driver uio_pdrv = { + .probe = uio_pdrv_probe, + .remove = uio_pdrv_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init uio_pdrv_init(void) +{ + return platform_driver_register(&uio_pdrv); +} + +static void __exit uio_pdrv_exit(void) +{ + platform_driver_unregister(&uio_pdrv); +} +module_init(uio_pdrv_init); +module_exit(uio_pdrv_exit); + +MODULE_AUTHOR("Uwe Kleine-Koenig"); +MODULE_DESCRIPTION("Userspace I/O platform driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v0.10.2 From 6d8333c24d41637f0f847f6e17032189dae08c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Jun 2008 09:14:48 +0200 Subject: UIO: minor style and comment fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Hans J. Koch diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index cf65e96..cdf338d 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -36,7 +36,7 @@ struct uio_mem { struct uio_map *map; }; -#define MAX_UIO_MAPS 5 +#define MAX_UIO_MAPS 5 struct uio_device; @@ -82,11 +82,11 @@ static inline int __must_check extern void uio_unregister_device(struct uio_info *info); extern void uio_event_notify(struct uio_info *info); -/* defines for uio_device->irq */ +/* defines for uio_info->irq */ #define UIO_IRQ_CUSTOM -1 #define UIO_IRQ_NONE -2 -/* defines for uio_device->memtype */ +/* defines for uio_mem->memtype */ #define UIO_MEM_NONE 0 #define UIO_MEM_PHYS 1 #define UIO_MEM_LOGICAL 2 -- cgit v0.10.2 From a231934bdf086a4fefc0df06e669499125a9db6f Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Mon, 2 Jun 2008 11:07:25 +0100 Subject: kobject: reorder kobject to save space on 64 bit builds reorder kobject to save space on 64 bit builds. shrinks from 72 to 64 bytes & moves allocated kobject to a smaller slab. Signed-off-by: Richard Kennedy Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/kobject.h b/include/linux/kobject.h index d542faa..60f0d41 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -58,12 +58,12 @@ enum kobject_action { struct kobject { const char *name; - struct kref kref; struct list_head entry; struct kobject *parent; struct kset *kset; struct kobj_type *ktype; struct sysfs_dirent *sd; + struct kref kref; unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; -- cgit v0.10.2 From 185000fc556372b7fb7f26516c325f212030dbd3 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 13 Jun 2008 11:09:16 +0800 Subject: kobject: should use kobject_put() in kset-example We should call kobject_put() instead of kfree() if kobject_init_and_add() returns an error, shouldn't we? Don't set up a bad example ;) Signed-off-by: Li Zefan Signed-off-by: Greg Kroah-Hartman diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index b0a1b4f..7395c0b 100644 --- a/samples/kobject/kset-example.c +++ b/samples/kobject/kset-example.c @@ -211,7 +211,7 @@ static struct foo_obj *create_foo_obj(const char *name) */ retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name); if (retval) { - kfree(foo); + kobject_put(&foo->kobj); return NULL; } -- cgit v0.10.2 From 838ea8e8dbfc8d907c7a55bbad507a44c1b81d57 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Jun 2008 19:00:34 +0100 Subject: sysdev: fix debugging statements in registration code. The systdev_class_register() and sysdev_register() functions have pr_debug() statements which are enabled when the user selects the driver core debug. Both of these routines do not produce the correct output, as they make assumptions about data which has not been initialised. In sysdev_class_register() the code uses the kobject_name(&cls->kset.kobj) at the start of the function, but this is not setup until later in the same call. Change this to use cls->name which is passed in from the caller. The sysdev_register() function tries to get the name of the sysdev by kobject_name(&sysdev->kobj), but that isn't setup until later in the same function so change this message to use the name of the sysdev's class and add another message once the name is initialised. Signed-off-by: Ben Dooks Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 358bb0b..50690d9 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -130,8 +130,8 @@ static struct kset *system_kset; int sysdev_class_register(struct sysdev_class * cls) { - pr_debug("Registering sysdev class '%s'\n", - kobject_name(&cls->kset.kobj)); + pr_debug("Registering sysdev class '%s'\n", cls->name); + INIT_LIST_HEAD(&cls->drivers); memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); cls->kset.kobj.parent = &system_kset->kobj; @@ -241,7 +241,8 @@ int sysdev_register(struct sys_device * sysdev) if (!cls) return -EINVAL; - pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); + pr_debug("Registering sys device of class '%s'\n", + kobject_name(&cls->kset.kobj)); /* initialize the kobject to 0, in case it had previously been used */ memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); @@ -257,6 +258,9 @@ int sysdev_register(struct sys_device * sysdev) if (!error) { struct sysdev_driver * drv; + pr_debug("Registering sys device '%s'\n", + kobject_name(&sysdev->kobj)); + mutex_lock(&sysdev_drivers_lock); /* Generic notification is implicit, because it's that * code that should have called us. @@ -269,6 +273,7 @@ int sysdev_register(struct sys_device * sysdev) } mutex_unlock(&sysdev_drivers_lock); } + kobject_uevent(&sysdev->kobj, KOBJ_ADD); return error; } -- cgit v0.10.2 From 93265d13ea5c3ec5f61a8009407fbe046ce6b7c0 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jun 2008 13:46:47 +0200 Subject: sysfs: don't call notify_change sysfs_chmod_file() calls notify_change() to change the permission bits on a sysfs file. Replace with explicit call to sysfs_setattr() and fsnotify_change(). This is equivalent, except that security_inode_setattr() is not called. This function is called by drivers, so the security checks do not make any sense. Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e7735f6..3f07893 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -585,9 +586,11 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - rc = notify_change(victim, &newattrs); + newattrs.ia_ctime = current_fs_time(inode->i_sb); + rc = sysfs_setattr(victim, &newattrs); if (rc == 0) { + fsnotify_change(victim, newattrs.ia_valid); mutex_lock(&sysfs_mutex); victim_sd->s_mode = newattrs.ia_mode; mutex_unlock(&sysfs_mutex); -- cgit v0.10.2 From 17149d9fff18c4811349140934dc541f70c617df Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 24 Jun 2008 14:24:57 -0700 Subject: uio-howto.tmpl: use standard copyright/legal markings The Userspace I/O HOWTO document uses straight tags and plain text to describe copyright/legal information. It should instead use the and tags like all other documents in the kernel. Signed-off-by: Mike Frysinger Acked-by: Hans J. Koch Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index c4d1873..d799a26 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -21,6 +21,18 @@ + + 2006-2008 + Hans-Jürgen Koch. + + + + +This documentation is Free Software licensed under the terms of the +GPL version 2. + + + 2006-12-11 @@ -66,17 +78,6 @@ About this document - - -Copyright and License - - Copyright (c) 2006-2008 by Hans-Jürgen Koch. - -This documentation is Free Software licensed under the terms of the -GPL version 2. - - - Translations -- cgit v0.10.2 From 4f7e53096c93f0bdf2205134dfc541d0c3cc6e41 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 24 Jun 2008 14:25:00 -0700 Subject: uio-howto.tmpl: use unique output names The Userspace I/O HOWTO template sets two different sections with the same html output name (about.html). This clearly won't work, so change the first one to a unique "aboutthis.html" to prevent clobbering. Signed-off-by: Mike Frysinger Acked-by: Hans J. Koch Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index d799a26..df87d1b 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -75,7 +75,7 @@ GPL version 2. - + About this document -- cgit v0.10.2 From d9b19199e4894089456aaad295023263b5225c1a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 10 Jun 2008 19:04:08 +0300 Subject: always enable FW_LOADER unless EMBEDDED=y James Bottomley recently discovered that we have {request,release}_firmware() dummies for the case of the actual functions not being available and has a fix for the bug that was actually causing build errors for built-in users with CONFIG_FW_LOADER=m. But now missing selects on FW_LOADER are no longer visible at compile-time at all and can become runtime problems. FW_LOADER is infrastructure with relatively small codesize we can safely enable for everyone, and only for people who really need small kernels (and can be expected to know what they are doing) it matters being able to disable it. This patch therefore always sets FW_LOADER=y and allows users only to disable it with EMBEDDED=y. As a bonus, we can then get rid of all "select FW_LOADER" plus the due to it required "depends on HOTPLUG" which removes some complexity from our Kconfig files. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d47482f..6318f6b 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -27,8 +27,9 @@ config PREVENT_FIRMWARE_BUILD If unsure say Y here. config FW_LOADER - tristate "Userspace firmware loading support" + tristate "Userspace firmware loading support" if EMBEDDED depends on HOTPLUG + default y ---help--- This option is provided for the case where no in-kernel-tree modules require userspace firmware loading support, but a module built outside -- cgit v0.10.2 From 43166141f73f969794bd7c850c89913631df99e4 Mon Sep 17 00:00:00 2001 From: Tsugikazu Shibata Date: Fri, 20 Jun 2008 10:59:52 +0900 Subject: HOWTO: change email addresses of James in HOWTO Signed-off-by: Tsugikazu Shibata Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 619e8ca..c2371c5 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -358,7 +358,7 @@ Here is a list of some of the different kernel trees available: - pcmcia, Dominik Brodowski git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git - - SCSI, James Bottomley + - SCSI, James Bottomley git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git - x86, Ingo Molnar -- cgit v0.10.2 From 9505e6375640fc61d92d36c8e9f25a6a218f3f57 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 1 Jul 2008 15:14:51 +0200 Subject: debugfs: Implement debugfs_remove_recursive() debugfs_remove_recursive() will remove a dentry and all its children. Drivers can use this to zap their whole debugfs tree so that they don't need to keep track of every single debugfs dentry they created. It may fail to remove the whole tree in certain cases: sh-3.2# rmmod atmel-mci < /sys/kernel/debug/mmc0/ios/clock mmc0: card b368 removed atmel_mci atmel_mci.0: Lost dma0chan1, falling back to PIO sh-3.2# ls /sys/kernel/debug/mmc0/ ios But I'm not sure if that case can be handled in any sane manner. Signed-off-by: Haavard Skinnemoen Cc: Pierre Ossman Signed-off-by: Greg Kroah-Hartman diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e9602d8..08e28c9 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -309,6 +309,31 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, } EXPORT_SYMBOL_GPL(debugfs_create_symlink); +static void __debugfs_remove(struct dentry *dentry, struct dentry *parent) +{ + int ret = 0; + + if (debugfs_positive(dentry)) { + if (dentry->d_inode) { + dget(dentry); + switch (dentry->d_inode->i_mode & S_IFMT) { + case S_IFDIR: + ret = simple_rmdir(parent->d_inode, dentry); + break; + case S_IFLNK: + kfree(dentry->d_inode->i_private); + /* fall through */ + default: + simple_unlink(parent->d_inode, dentry); + break; + } + if (!ret) + d_delete(dentry); + dput(dentry); + } + } +} + /** * debugfs_remove - removes a file or directory from the debugfs filesystem * @dentry: a pointer to a the dentry of the file or directory to be @@ -325,7 +350,6 @@ EXPORT_SYMBOL_GPL(debugfs_create_symlink); void debugfs_remove(struct dentry *dentry) { struct dentry *parent; - int ret = 0; if (!dentry) return; @@ -335,29 +359,83 @@ void debugfs_remove(struct dentry *dentry) return; mutex_lock(&parent->d_inode->i_mutex); - if (debugfs_positive(dentry)) { - if (dentry->d_inode) { - dget(dentry); - switch (dentry->d_inode->i_mode & S_IFMT) { - case S_IFDIR: - ret = simple_rmdir(parent->d_inode, dentry); - break; - case S_IFLNK: - kfree(dentry->d_inode->i_private); - /* fall through */ - default: - simple_unlink(parent->d_inode, dentry); + __debugfs_remove(dentry, parent); + mutex_unlock(&parent->d_inode->i_mutex); + simple_release_fs(&debugfs_mount, &debugfs_mount_count); +} +EXPORT_SYMBOL_GPL(debugfs_remove); + +/** + * debugfs_remove_recursive - recursively removes a directory + * @dentry: a pointer to a the dentry of the directory to be removed. + * + * This function recursively removes a directory tree in debugfs that + * was previously created with a call to another debugfs function + * (like debugfs_create_file() or variants thereof.) + * + * This function is required to be called in order for the file to be + * removed, no automatic cleanup of files will happen when a module is + * removed, you are responsible here. + */ +void debugfs_remove_recursive(struct dentry *dentry) +{ + struct dentry *child; + struct dentry *parent; + + if (!dentry) + return; + + parent = dentry->d_parent; + if (!parent || !parent->d_inode) + return; + + parent = dentry; + mutex_lock(&parent->d_inode->i_mutex); + + while (1) { + /* + * When all dentries under "parent" has been removed, + * walk up the tree until we reach our starting point. + */ + if (list_empty(&parent->d_subdirs)) { + mutex_unlock(&parent->d_inode->i_mutex); + if (parent == dentry) break; - } - if (!ret) - d_delete(dentry); - dput(dentry); + parent = parent->d_parent; + mutex_lock(&parent->d_inode->i_mutex); + } + child = list_entry(parent->d_subdirs.next, struct dentry, + d_u.d_child); + + /* + * If "child" isn't empty, walk down the tree and + * remove all its descendants first. + */ + if (!list_empty(&child->d_subdirs)) { + mutex_unlock(&parent->d_inode->i_mutex); + parent = child; + mutex_lock(&parent->d_inode->i_mutex); + continue; } + __debugfs_remove(child, parent); + if (parent->d_subdirs.next == &child->d_u.d_child) { + /* + * Avoid infinite loop if we fail to remove + * one dentry. + */ + mutex_unlock(&parent->d_inode->i_mutex); + break; + } + simple_release_fs(&debugfs_mount, &debugfs_mount_count); } + + parent = dentry->d_parent; + mutex_lock(&parent->d_inode->i_mutex); + __debugfs_remove(dentry, parent); mutex_unlock(&parent->d_inode->i_mutex); simple_release_fs(&debugfs_mount, &debugfs_mount_count); } -EXPORT_SYMBOL_GPL(debugfs_remove); +EXPORT_SYMBOL_GPL(debugfs_remove_recursive); /** * debugfs_rename - rename a file/directory in the debugfs filesystem diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 32755cd..e1a6c04 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -44,6 +44,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, const char *dest); void debugfs_remove(struct dentry *dentry); +void debugfs_remove_recursive(struct dentry *dentry); struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, const char *new_name); @@ -101,6 +102,9 @@ static inline struct dentry *debugfs_create_symlink(const char *name, static inline void debugfs_remove(struct dentry *dentry) { } +static inline void debugfs_remove_recursive(struct dentry *dentry) +{ } + static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, char *new_name) { -- cgit v0.10.2 From 83c79b55f0d929a0dcf2b0d347cd1875afc06f21 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Wed, 2 Jul 2008 10:21:30 -0700 Subject: sysfs-rules.txt: reword API stability statement The first paragraph of this document implies that user space developers shouldn't use sysfs at all, but then it goes on to describe rules that developers should follow when accessing sysfs. Not only is this somewhat self-contradictory, it has been shown to discourage developers from using established sysfs interfaces. A note of caution is more appropriate than a blanket "sysfs will never be stable" assertion. Signed-off-by: Nathan Lynch Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt index 80ef562..6049a2a 100644 --- a/Documentation/sysfs-rules.txt +++ b/Documentation/sysfs-rules.txt @@ -3,9 +3,8 @@ Rules on how to access information in the Linux kernel sysfs The kernel-exported sysfs exports internal kernel implementation details and depends on internal kernel structures and layout. It is agreed upon by the kernel developers that the Linux kernel does not provide a stable -internal API. As sysfs is a direct export of kernel internal -structures, the sysfs interface cannot provide a stable interface either; -it may always change along with internal kernel changes. +internal API. Therefore, there are aspects of the sysfs interface that +may not be stable across kernel releases. To minimize the risk of breaking users of sysfs, which are in most cases low-level userspace applications, with a new kernel release, the users -- cgit v0.10.2 From 0ad1d6f37cc3bb234c6e7ae30e40d1d40b9aa258 Mon Sep 17 00:00:00 2001 From: Wang Chen Date: Tue, 24 Jun 2008 16:59:02 +0800 Subject: kobject: Transmit return value of call_usermodehelper() to caller kobject_uevent_env() drops the return value of call_usermodehelper(). It will make upper caller, such as dm_send_uevents(), to lose error information. BTW, Previously kobject_uevent_env() transmitted return of call_usermodehelper() to callers, but commit 5f123fbd80f4f788554636f02bf73e40f914e0d6 "[PATCH] merge kobject_uevent and kobject_hotplug" removed it. Signed-off-by: Wang Chen Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 2fa545a..9f8d599 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -245,7 +245,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, if (retval) goto exit; - call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC); + retval = call_usermodehelper(argv[0], argv, + env->envp, UMH_WAIT_EXEC); } exit: -- cgit v0.10.2 From 36ce6dad6e3cb3f050ed41e0beac0070d2062b25 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 10 Jun 2008 11:09:08 +0200 Subject: driver core: Suppress sysfs warnings for device_rename(). driver core: Suppress sysfs warnings for device_rename(). Renaming network devices to an already existing name is not something we want sysfs to print a scary warning for, since the callers can deal with this correctly. So let's introduce sysfs_create_link_nowarn() which gets rid of the common warning. Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/core.c b/drivers/base/core.c index c05b115..7d5c63c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1345,8 +1345,9 @@ int device_rename(struct device *dev, char *new_name) if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); if (new_class_name) { - error = sysfs_create_link(&dev->parent->kobj, - &dev->kobj, new_class_name); + error = sysfs_create_link_nowarn(&dev->parent->kobj, + &dev->kobj, + new_class_name); if (error) goto out; sysfs_remove_link(&dev->parent->kobj, old_class_name); @@ -1354,8 +1355,8 @@ int device_rename(struct device *dev, char *new_name) } #else if (dev->class) { - error = sysfs_create_link(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev->bus_id); + error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, + &dev->kobj, dev->bus_id); if (error) goto out; sysfs_remove_link(&dev->class->p->class_subsys.kobj, diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 8c0e4b9..c1a7efb 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -398,7 +398,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, } /** - * sysfs_add_one - add sysfs_dirent to parent + * __sysfs_add_one - add sysfs_dirent to parent without warning * @acxt: addrm context to use * @sd: sysfs_dirent to be added * @@ -417,7 +417,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, * 0 on success, -EEXIST if entry with the given name already * exists. */ -int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) +int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) return -EEXIST; @@ -435,6 +435,39 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) } /** + * sysfs_add_one - add sysfs_dirent to parent + * @acxt: addrm context to use + * @sd: sysfs_dirent to be added + * + * Get @acxt->parent_sd and set sd->s_parent to it and increment + * nlink of parent inode if @sd is a directory and link into the + * children list of the parent. + * + * This function should be called between calls to + * sysfs_addrm_start() and sysfs_addrm_finish() and should be + * passed the same @acxt as passed to sysfs_addrm_start(). + * + * LOCKING: + * Determined by sysfs_addrm_start(). + * + * RETURNS: + * 0 on success, -EEXIST if entry with the given name already + * exists. + */ +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) +{ + int ret; + + ret = __sysfs_add_one(acxt, sd); + if (ret == -EEXIST) { + printk(KERN_WARNING "sysfs: duplicate filename '%s' " + "can not be created\n", sd->s_name); + WARN_ON(1); + } + return ret; +} + +/** * sysfs_remove_one - remove sysfs_dirent from parent * @acxt: addrm context to use * @sd: sysfs_dirent to be removed diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 817f596..a3ba217 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -19,13 +19,8 @@ #include "sysfs.h" -/** - * sysfs_create_link - create symlink between two objects. - * @kobj: object whose directory we're creating the link in. - * @target: object we're pointing to. - * @name: name of the symlink. - */ -int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) +static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, + const char *name, int warn) { struct sysfs_dirent *parent_sd = NULL; struct sysfs_dirent *target_sd = NULL; @@ -65,7 +60,10 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char target_sd = NULL; /* reference is now owned by the symlink */ sysfs_addrm_start(&acxt, parent_sd); - error = sysfs_add_one(&acxt, sd); + if (warn) + error = sysfs_add_one(&acxt, sd); + else + error = __sysfs_add_one(&acxt, sd); sysfs_addrm_finish(&acxt); if (error) @@ -80,6 +78,33 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char } /** + * sysfs_create_link - create symlink between two objects. + * @kobj: object whose directory we're creating the link in. + * @target: object we're pointing to. + * @name: name of the symlink. + */ +int sysfs_create_link(struct kobject *kobj, struct kobject *target, + const char *name) +{ + return sysfs_do_create_link(kobj, target, name, 1); +} + +/** + * sysfs_create_link_nowarn - create symlink between two objects. + * @kobj: object whose directory we're creating the link in. + * @target: object we're pointing to. + * @name: name of the symlink. + * + * This function does the same as sysf_create_link(), but it + * doesn't warn if the link already exists. + */ +int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, + const char *name) +{ + return sysfs_do_create_link(kobj, target, name, 0); +} + +/** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. * @name: name of the symlink to remove. diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index ce4e15f8..a5db496 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -107,6 +107,7 @@ struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); void sysfs_put_active_two(struct sysfs_dirent *sd); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *parent_sd); +int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7858eac..37fa241 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -101,6 +101,9 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name); +int __must_check sysfs_create_link_nowarn(struct kobject *kobj, + struct kobject *target, + const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); int __must_check sysfs_create_group(struct kobject *kobj, @@ -180,6 +183,13 @@ static inline int sysfs_create_link(struct kobject *kobj, return 0; } +static inline int sysfs_create_link_nowarn(struct kobject *kobj, + struct kobject *target, + const char *name) +{ + return 0; +} + static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } -- cgit v0.10.2 From 4a0b2b4dbe1335b8b9886ba3dc85a145d5d938ed Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 1 Jul 2008 18:48:41 +0200 Subject: sysdev: Pass the attribute to the low level sysdev show/store function This allow to dynamically generate attributes and share show/store functions between attributes. Right now most attributes are generated by special macros and lots of duplicated code. With the attribute passed it's instead possible to attach some data to the attribute and then use that in shared low level functions to do different things. I need this for the dynamically generated bank attributes in the x86 machine check code, but it'll allow some further cleanups. I converted all users in tree to the new show/store prototype. It's a single huge patch to avoid unbisectable sections. Runtime tested: x86-32, x86-64 Compiled only: ia64, powerpc Not compile tested/only grep converted: sh, arm, avr32 Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index cc5145b..368d171 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -130,7 +130,9 @@ static const struct leds_evt_name evt_names[] = { { "red", led_red_on, led_red_off }, }; -static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size) +static ssize_t leds_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t size) { int ret = -EINVAL, len = strcspn(buf, " "); diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c index b8409ca..e84faff 100644 --- a/arch/avr32/kernel/cpu.c +++ b/arch/avr32/kernel/cpu.c @@ -26,14 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); * XXX: If/when a SMP-capable implementation of AVR32 will ever be * made, we must make sure that the code executes on the correct CPU. */ -static ssize_t show_pc0event(struct sys_device *dev, char *buf) +static ssize_t show_pc0event(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); } -static ssize_t store_pc0event(struct sys_device *dev, const char *buf, +static ssize_t store_pc0event(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { unsigned long val; @@ -46,15 +48,17 @@ static ssize_t store_pc0event(struct sys_device *dev, const char *buf, sysreg_write(PCCR, val); return count; } -static ssize_t show_pc0count(struct sys_device *dev, char *buf) +static ssize_t show_pc0count(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pcnt0; pcnt0 = sysreg_read(PCNT0); return sprintf(buf, "%lu\n", pcnt0); } -static ssize_t store_pc0count(struct sys_device *dev, const char *buf, - size_t count) +static ssize_t store_pc0count(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t count) { unsigned long val; char *endp; @@ -67,14 +71,16 @@ static ssize_t store_pc0count(struct sys_device *dev, const char *buf, return count; } -static ssize_t show_pc1event(struct sys_device *dev, char *buf) +static ssize_t show_pc1event(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); } -static ssize_t store_pc1event(struct sys_device *dev, const char *buf, +static ssize_t store_pc1event(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { unsigned long val; @@ -87,14 +93,16 @@ static ssize_t store_pc1event(struct sys_device *dev, const char *buf, sysreg_write(PCCR, val); return count; } -static ssize_t show_pc1count(struct sys_device *dev, char *buf) +static ssize_t show_pc1count(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pcnt1; pcnt1 = sysreg_read(PCNT1); return sprintf(buf, "%lu\n", pcnt1); } -static ssize_t store_pc1count(struct sys_device *dev, const char *buf, +static ssize_t store_pc1count(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { unsigned long val; @@ -108,14 +116,16 @@ static ssize_t store_pc1count(struct sys_device *dev, const char *buf, return count; } -static ssize_t show_pccycles(struct sys_device *dev, char *buf) +static ssize_t show_pccycles(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pccnt; pccnt = sysreg_read(PCCNT); return sprintf(buf, "%lu\n", pccnt); } -static ssize_t store_pccycles(struct sys_device *dev, const char *buf, +static ssize_t store_pccycles(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { unsigned long val; @@ -129,14 +139,16 @@ static ssize_t store_pccycles(struct sys_device *dev, const char *buf, return count; } -static ssize_t show_pcenable(struct sys_device *dev, char *buf) +static ssize_t show_pcenable(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); } -static ssize_t store_pcenable(struct sys_device *dev, const char *buf, +static ssize_t store_pcenable(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { unsigned long pccr, val; diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c index b642648..c539c68 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -55,7 +55,8 @@ static u64 resources[NR_CPUS]; #define show(name) \ static ssize_t \ -show_##name(struct sys_device *dev, char *buf) \ +show_##name(struct sys_device *dev, struct sysdev_attribute *attr, \ + char *buf) \ { \ u32 cpu=dev->id; \ return sprintf(buf, "%lx\n", name[cpu]); \ @@ -63,7 +64,8 @@ show_##name(struct sys_device *dev, char *buf) \ #define store(name) \ static ssize_t \ -store_##name(struct sys_device *dev, const char *buf, size_t size) \ +store_##name(struct sys_device *dev, struct sysdev_attribute *attr, \ + const char *buf, size_t size) \ { \ unsigned int cpu=dev->id; \ name[cpu] = simple_strtoull(buf, NULL, 16); \ @@ -76,7 +78,8 @@ show(call_start) * processor. The cpu number in driver is only used for storing data. */ static ssize_t -store_call_start(struct sys_device *dev, const char *buf, size_t size) +store_call_start(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t size) { unsigned int cpu=dev->id; unsigned long call_start = simple_strtoull(buf, NULL, 16); @@ -124,14 +127,16 @@ show(err_type_info) store(err_type_info) static ssize_t -show_virtual_to_phys(struct sys_device *dev, char *buf) +show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) { unsigned int cpu=dev->id; return sprintf(buf, "%lx\n", phys_addr[cpu]); } static ssize_t -store_virtual_to_phys(struct sys_device *dev, const char *buf, size_t size) +store_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t size) { unsigned int cpu=dev->id; u64 virt_addr=simple_strtoull(buf, NULL, 16); @@ -154,7 +159,8 @@ show(err_struct_info) store(err_struct_info) static ssize_t -show_err_data_buffer(struct sys_device *dev, char *buf) +show_err_data_buffer(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned int cpu=dev->id; @@ -165,7 +171,9 @@ show_err_data_buffer(struct sys_device *dev, char *buf) } static ssize_t -store_err_data_buffer(struct sys_device *dev, const char *buf, size_t size) +store_err_data_buffer(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t size) { unsigned int cpu=dev->id; int ret; diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index c8127f8..aba0ba9 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -28,7 +28,9 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); /* Time in microseconds we delay before sleeping in the idle loop */ DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 }; -static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf, +static ssize_t store_smt_snooze_delay(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t count) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); @@ -44,7 +46,9 @@ static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf, return count; } -static ssize_t show_smt_snooze_delay(struct sys_device *dev, char *buf) +static ssize_t show_smt_snooze_delay(struct sys_device *dev, + struct sysdev_attribute *attr, + char *buf) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); @@ -152,14 +156,17 @@ static unsigned long write_##NAME(unsigned long val) \ mtspr(ADDRESS, val); \ return 0; \ } \ -static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ +static ssize_t show_##NAME(struct sys_device *dev, \ + struct sysdev_attribute *attr, \ + char *buf) \ { \ struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ return sprintf(buf, "%lx\n", val); \ } \ static ssize_t __used \ - store_##NAME(struct sys_device *dev, const char *buf, size_t count) \ + store_##NAME(struct sys_device *dev, struct sysdev_attribute *attr, \ + const char *buf, size_t count) \ { \ struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ unsigned long val; \ diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index 4852bf3..4d4c8c1 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -97,7 +97,8 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom return value.spe[spu->spe_id]; } -static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) +static ssize_t spu_show_temp(struct sys_device *sysdev, struct sysdev_attribute *attr, + char *buf) { u8 value; struct cbe_pmd_regs __iomem *pmd_regs; @@ -146,32 +147,38 @@ static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char return size; } -static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf) +static ssize_t spu_show_throttle_end(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(get_pmd_regs(sysdev), buf, 0); } -static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf) +static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(get_pmd_regs(sysdev), buf, 8); } -static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(get_pmd_regs(sysdev), buf, 16); } -static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t spu_store_throttle_end(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(get_pmd_regs(sysdev), buf, size, 0); } -static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(get_pmd_regs(sysdev), buf, size, 8); } -static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(get_pmd_regs(sysdev), buf, size, 16); } @@ -192,43 +199,51 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) /* shows the temperature of the DTS on the PPE, * located near the linear thermal sensor */ -static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf) +static ssize_t ppe_show_temp0(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return ppe_show_temp(sysdev, buf, 32); } /* shows the temperature of the second DTS on the PPE */ -static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) +static ssize_t ppe_show_temp1(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return ppe_show_temp(sysdev, buf, 0); } -static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf) +static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); } -static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf) +static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); } -static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); } -static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); } -static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); } -static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, + struct sysdev_attribute *attr, const char *buf, size_t size) { return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 78f905b..a5bdb89 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -703,7 +703,8 @@ static unsigned long long spu_acct_time(struct spu *spu, } -static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf) +static ssize_t spu_stat_show(struct sys_device *sysdev, + struct sysdev_attribute *attr, char *buf) { struct spu *spu = container_of(sysdev, struct spu, sysdev); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b678103..b795b3e 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -864,7 +864,8 @@ int setup_profiling_timer(unsigned int multiplier) } #ifdef CONFIG_HOTPLUG_CPU -static ssize_t cpu_configure_show(struct sys_device *dev, char *buf) +static ssize_t cpu_configure_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t count; @@ -874,8 +875,9 @@ static ssize_t cpu_configure_show(struct sys_device *dev, char *buf) return count; } -static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf, - size_t count) +static ssize_t cpu_configure_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t count) { int cpu = dev->id; int val, rc; @@ -922,7 +924,8 @@ out: static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); #endif /* CONFIG_HOTPLUG_CPU */ -static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf) +static ssize_t cpu_polarization_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { int cpu = dev->id; ssize_t count; @@ -950,7 +953,8 @@ static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf) } static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL); -static ssize_t show_cpu_address(struct sys_device *dev, char *buf) +static ssize_t show_cpu_address(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]); } @@ -970,7 +974,8 @@ static struct attribute_group cpu_common_attr_group = { .attrs = cpu_common_attrs, }; -static ssize_t show_capability(struct sys_device *dev, char *buf) +static ssize_t show_capability(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { unsigned int capability; int rc; @@ -982,7 +987,8 @@ static ssize_t show_capability(struct sys_device *dev, char *buf) } static SYSDEV_ATTR(capability, 0444, show_capability, NULL); -static ssize_t show_idle_count(struct sys_device *dev, char *buf) +static ssize_t show_idle_count(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct s390_idle_data *idle; unsigned long long idle_count; @@ -995,7 +1001,8 @@ static ssize_t show_idle_count(struct sys_device *dev, char *buf) } static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); -static ssize_t show_idle_time(struct sys_device *dev, char *buf) +static ssize_t show_idle_time(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct s390_idle_data *idle; unsigned long long new_time; @@ -1112,7 +1119,9 @@ out: return rc; } -static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf, +static ssize_t __ref rescan_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t count) { int rc; @@ -1123,7 +1132,9 @@ static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf, static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); #endif /* CONFIG_HOTPLUG_CPU */ -static ssize_t dispatching_show(struct sys_device *dev, char *buf) +static ssize_t dispatching_show(struct sys_device *dev, + struct sysdev_attribute *attr, + char *buf) { ssize_t count; @@ -1133,8 +1144,9 @@ static ssize_t dispatching_show(struct sys_device *dev, char *buf) return count; } -static ssize_t dispatching_store(struct sys_device *dev, const char *buf, - size_t count) +static ssize_t dispatching_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t count) { int val, rc; char delim; diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index f2cede3..ab70d9b 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -1100,7 +1100,9 @@ static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev) return etr_port1_online ? &etr_port1 : NULL; } -static ssize_t etr_online_show(struct sys_device *dev, char *buf) +static ssize_t etr_online_show(struct sys_device *dev, + struct sysdev_attribute *attr, + char *buf) { unsigned int online; @@ -1109,7 +1111,8 @@ static ssize_t etr_online_show(struct sys_device *dev, char *buf) } static ssize_t etr_online_store(struct sys_device *dev, - const char *buf, size_t count) + struct sysdev_attribute *attr, + const char *buf, size_t count) { unsigned int value; @@ -1136,7 +1139,9 @@ static ssize_t etr_online_store(struct sys_device *dev, static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store); -static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf) +static ssize_t etr_stepping_control_show(struct sys_device *dev, + struct sysdev_attribute *attr, + char *buf) { return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ? etr_eacr.e0 : etr_eacr.e1); @@ -1144,7 +1149,8 @@ static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL); -static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf) +static ssize_t etr_mode_code_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { if (!etr_port0_online && !etr_port1_online) /* Status word is not uptodate if both ports are offline. */ @@ -1155,7 +1161,8 @@ static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL); -static ssize_t etr_untuned_show(struct sys_device *dev, char *buf) +static ssize_t etr_untuned_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1166,7 +1173,8 @@ static ssize_t etr_untuned_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL); -static ssize_t etr_network_id_show(struct sys_device *dev, char *buf) +static ssize_t etr_network_id_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1177,7 +1185,8 @@ static ssize_t etr_network_id_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL); -static ssize_t etr_id_show(struct sys_device *dev, char *buf) +static ssize_t etr_id_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1188,7 +1197,8 @@ static ssize_t etr_id_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(id, 0400, etr_id_show, NULL); -static ssize_t etr_port_number_show(struct sys_device *dev, char *buf) +static ssize_t etr_port_number_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1199,7 +1209,8 @@ static ssize_t etr_port_number_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL); -static ssize_t etr_coupled_show(struct sys_device *dev, char *buf) +static ssize_t etr_coupled_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1210,7 +1221,8 @@ static ssize_t etr_coupled_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL); -static ssize_t etr_local_time_show(struct sys_device *dev, char *buf) +static ssize_t etr_local_time_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); @@ -1221,7 +1233,8 @@ static ssize_t etr_local_time_show(struct sys_device *dev, char *buf) static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL); -static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf) +static ssize_t etr_utc_offset_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct etr_aib *aib = etr_aib_from_dev(dev); diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 51b57c0..347ee11 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -23,7 +23,8 @@ static struct sysdev_class dma_sysclass = { }; EXPORT_SYMBOL(dma_sysclass); -static ssize_t dma_show_devices(struct sys_device *dev, char *buf) +static ssize_t dma_show_devices(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t len = 0; int i; @@ -57,13 +58,15 @@ static int __init dma_sysclass_init(void) } postcore_initcall(dma_sysclass_init); -static ssize_t dma_show_dev_id(struct sys_device *dev, char *buf) +static ssize_t dma_show_dev_id(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct dma_channel *channel = to_dma_channel(dev); return sprintf(buf, "%s\n", channel->dev_id); } static ssize_t dma_store_dev_id(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { struct dma_channel *channel = to_dma_channel(dev); @@ -74,6 +77,7 @@ static ssize_t dma_store_dev_id(struct sys_device *dev, static SYSDEV_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id); static ssize_t dma_store_config(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { struct dma_channel *channel = to_dma_channel(dev); @@ -87,13 +91,15 @@ static ssize_t dma_store_config(struct sys_device *dev, static SYSDEV_ATTR(config, S_IWUSR, NULL, dma_store_config); -static ssize_t dma_show_mode(struct sys_device *dev, char *buf) +static ssize_t dma_show_mode(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct dma_channel *channel = to_dma_channel(dev); return sprintf(buf, "0x%08x\n", channel->mode); } static ssize_t dma_store_mode(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { struct dma_channel *channel = to_dma_channel(dev); @@ -104,7 +110,8 @@ static ssize_t dma_store_mode(struct sys_device *dev, static SYSDEV_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode); #define dma_ro_attr(field, fmt) \ -static ssize_t dma_show_##field(struct sys_device *dev, char *buf) \ +static ssize_t dma_show_##field(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf)\ { \ struct dma_channel *channel = to_dma_channel(dev); \ return sprintf(buf, fmt, channel->field); \ diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c index e885034..84e5ce1 100644 --- a/arch/sparc64/kernel/sysfs.c +++ b/arch/sparc64/kernel/sysfs.c @@ -14,7 +14,8 @@ static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64))); #define SHOW_MMUSTAT_ULONG(NAME) \ -static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ +static ssize_t show_##NAME(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \ return sprintf(buf, "%lu\n", p->NAME); \ @@ -135,13 +136,16 @@ static unsigned long write_mmustat_enable(unsigned long val) return sun4v_mmustat_conf(ra, &orig_ra); } -static ssize_t show_mmustat_enable(struct sys_device *s, char *buf) +static ssize_t show_mmustat_enable(struct sys_device *s, + struct sysdev_attribute *attr, char *buf) { unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0); return sprintf(buf, "%lx\n", val); } -static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count) +static ssize_t store_mmustat_enable(struct sys_device *s, + struct sysdev_attribute *attr, const char *buf, + size_t count) { unsigned long val, err; int ret = sscanf(buf, "%ld", &val); @@ -179,14 +183,16 @@ static void unregister_mmu_stats(struct sys_device *s) #endif #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \ -static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ +static ssize_t show_##NAME(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ cpuinfo_sparc *c = &cpu_data(dev->id); \ return sprintf(buf, "%lu\n", c->MEMBER); \ } #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \ -static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ +static ssize_t show_##NAME(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ cpuinfo_sparc *c = &cpu_data(dev->id); \ return sprintf(buf, "%u\n", c->MEMBER); \ diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index c4a7ec3..e6a4d5f 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -762,10 +762,14 @@ DEFINE_PER_CPU(struct sys_device, device_mce); /* Why are there no generic functions for this? */ #define ACCESSOR(name, var, start) \ - static ssize_t show_ ## name(struct sys_device *s, char *buf) { \ + static ssize_t show_ ## name(struct sys_device *s, \ + struct sysdev_attribute *attr, \ + char *buf) { \ return sprintf(buf, "%lx\n", (unsigned long)var); \ } \ - static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \ + static ssize_t set_ ## name(struct sys_device *s, \ + struct sysdev_attribute *attr, \ + const char *buf, size_t siz) { \ char *end; \ unsigned long new = simple_strtoul(buf, &end, 0); \ if (end == buf) return -EINVAL; \ @@ -786,14 +790,16 @@ ACCESSOR(bank3ctl,bank[3],mce_restart()) ACCESSOR(bank4ctl,bank[4],mce_restart()) ACCESSOR(bank5ctl,bank[5],mce_restart()) -static ssize_t show_trigger(struct sys_device *s, char *buf) +static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr, + char *buf) { strcpy(buf, trigger); strcat(buf, "\n"); return strlen(trigger) + 1; } -static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz) +static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, + const char *buf,size_t siz) { char *p; int len; diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 1f4cc48..d5ae224 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -35,6 +35,7 @@ atomic_t therm_throt_en = ATOMIC_INIT(0); #define define_therm_throt_sysdev_show_func(name) \ static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ + struct sysdev_attribute *attr, \ char *buf) \ { \ unsigned int cpu = dev->id; \ diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 56b9331..fc47906 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -644,7 +644,9 @@ static void microcode_fini_cpu(int cpu) mutex_unlock(µcode_mutex); } -static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz) +static ssize_t reload_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t sz) { struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; char *end; @@ -674,14 +676,16 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz) return sz; } -static ssize_t version_show(struct sys_device *dev, char *buf) +static ssize_t version_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; return sprintf(buf, "0x%x\n", uci->rev); } -static ssize_t pf_show(struct sys_device *dev, char *buf) +static ssize_t pf_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index e38dfed..20537d5 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -21,15 +21,16 @@ EXPORT_SYMBOL(cpu_sysdev_class); static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); #ifdef CONFIG_HOTPLUG_CPU -static ssize_t show_online(struct sys_device *dev, char *buf) +static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); } -static ssize_t __ref store_online(struct sys_device *dev, const char *buf, - size_t count) +static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t count) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); ssize_t ret; @@ -80,7 +81,8 @@ static inline void register_cpu_control(struct cpu *cpu) #ifdef CONFIG_KEXEC #include -static ssize_t show_crash_notes(struct sys_device *dev, char *buf) +static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); ssize_t rc; diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 937e825..4d4e0e7 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -92,7 +92,8 @@ unregister_memory(struct memory_block *memory, struct mem_section *section) * uses. */ -static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf) +static ssize_t show_mem_phys_index(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct memory_block *mem = container_of(dev, struct memory_block, sysdev); @@ -102,7 +103,8 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf) /* * online, offline, going offline, etc. */ -static ssize_t show_mem_state(struct sys_device *dev, char *buf) +static ssize_t show_mem_state(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct memory_block *mem = container_of(dev, struct memory_block, sysdev); @@ -217,7 +219,8 @@ out: } static ssize_t -store_mem_state(struct sys_device *dev, const char *buf, size_t count) +store_mem_state(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { struct memory_block *mem; unsigned int phys_section_nr; @@ -248,7 +251,8 @@ out: * s.t. if I offline all of these sections I can then * remove the physical device? */ -static ssize_t show_phys_device(struct sys_device *dev, char *buf) +static ssize_t show_phys_device(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { struct memory_block *mem = container_of(dev, struct memory_block, sysdev); diff --git a/drivers/base/node.c b/drivers/base/node.c index 0f867a0..5116b78 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -36,11 +36,13 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf) return len; } -static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf) +static inline ssize_t node_read_cpumask(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { return node_read_cpumap(dev, 0, buf); } -static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf) +static inline ssize_t node_read_cpulist(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { return node_read_cpumap(dev, 1, buf); } @@ -49,7 +51,8 @@ static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL); static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); #define K(x) ((x) << (PAGE_SHIFT - 10)) -static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) +static ssize_t node_read_meminfo(struct sys_device * dev, + struct sysdev_attribute *attr, char * buf) { int n; int nid = dev->id; @@ -112,7 +115,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) #undef K static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); -static ssize_t node_read_numastat(struct sys_device * dev, char * buf) +static ssize_t node_read_numastat(struct sys_device * dev, + struct sysdev_attribute *attr, char * buf) { return sprintf(buf, "numa_hit %lu\n" @@ -130,7 +134,8 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) } static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); -static ssize_t node_read_distance(struct sys_device * dev, char * buf) +static ssize_t node_read_distance(struct sys_device * dev, + struct sysdev_attribute *attr, char * buf) { int nid = dev->id; int len = 0; diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 50690d9..dc7dace 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -36,7 +36,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->show) - return sysdev_attr->show(sysdev, buffer); + return sysdev_attr->show(sysdev, sysdev_attr, buffer); return -EIO; } @@ -49,7 +49,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr, struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->store) - return sysdev_attr->store(sysdev, buffer, count); + return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); return -EIO; } diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3f6d9b0..199cd97 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -34,7 +34,8 @@ static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) #define define_id_show_func(name) \ -static ssize_t show_##name(struct sys_device *dev, char *buf) \ +static ssize_t show_##name(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ unsigned int cpu = dev->id; \ return sprintf(buf, "%d\n", topology_##name(cpu)); \ @@ -59,14 +60,17 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) #ifdef arch_provides_topology_pointers #define define_siblings_show_map(name) \ -static ssize_t show_##name(struct sys_device *dev, char *buf) \ +static ssize_t show_##name(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ unsigned int cpu = dev->id; \ return show_cpumap(0, &(topology_##name(cpu)), buf); \ } #define define_siblings_show_list(name) \ -static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ +static ssize_t show_##name##_list(struct sys_device *dev, \ + struct sysdev_attribute *attr, \ + char *buf) \ { \ unsigned int cpu = dev->id; \ return show_cpumap(1, &(topology_##name(cpu)), buf); \ @@ -74,7 +78,8 @@ static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ #else #define define_siblings_show_map(name) \ -static ssize_t show_##name(struct sys_device *dev, char *buf) \ +static ssize_t show_##name(struct sys_device *dev, \ + struct sysdev_attribute *attr, char *buf) \ { \ unsigned int cpu = dev->id; \ cpumask_t mask = topology_##name(cpu); \ @@ -82,7 +87,9 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \ } #define define_siblings_show_list(name) \ -static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ +static ssize_t show_##name##_list(struct sys_device *dev, \ + struct sysdev_attribute *attr, \ + char *buf) \ { \ unsigned int cpu = dev->id; \ cpumask_t mask = topology_##name(cpu); \ diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index e949618..31a0e0b 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -21,7 +21,8 @@ static int __init cpuidle_sysfs_setup(char *unused) } __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); -static ssize_t show_available_governors(struct sys_device *dev, char *buf) +static ssize_t show_available_governors(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t i = 0; struct cpuidle_governor *tmp; @@ -39,7 +40,8 @@ out: return i; } -static ssize_t show_current_driver(struct sys_device *dev, char *buf) +static ssize_t show_current_driver(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t ret; @@ -53,7 +55,8 @@ static ssize_t show_current_driver(struct sys_device *dev, char *buf) return ret; } -static ssize_t show_current_governor(struct sys_device *dev, char *buf) +static ssize_t show_current_governor(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t ret; @@ -68,6 +71,7 @@ static ssize_t show_current_governor(struct sys_device *dev, char *buf) } static ssize_t store_current_governor(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { char gov_name[CPUIDLE_NAME_LEN]; diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 591bc29..d4427cb 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -610,6 +610,7 @@ static ssize_t show_target_kb(struct sys_device *dev, char *buf) } static ssize_t store_target_kb(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index f2767bc..8dcf316 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -99,8 +99,9 @@ extern void sysdev_unregister(struct sys_device *); struct sysdev_attribute { struct attribute attr; - ssize_t (*show)(struct sys_device *, char *); - ssize_t (*store)(struct sys_device *, const char *, size_t); + ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *); + ssize_t (*store)(struct sys_device *, struct sysdev_attribute *, + const char *, size_t); }; diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c index 092e4c6..a56f629 100644 --- a/kernel/rtmutex-tester.c +++ b/kernel/rtmutex-tester.c @@ -297,8 +297,8 @@ static int test_func(void *data) * * opcode:data */ -static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf, - size_t count) +static ssize_t sysfs_test_command(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t count) { struct sched_param schedpar; struct test_thread_data *td; @@ -360,7 +360,8 @@ static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf, * @dev: thread to query * @buf: char buffer to be filled with thread status info */ -static ssize_t sysfs_test_status(struct sys_device *dev, char *buf) +static ssize_t sysfs_test_status(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) { struct test_thread_data *td; struct task_struct *tsk; diff --git a/kernel/sched.c b/kernel/sched.c index 99e6d85..b1104ea 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -7737,11 +7737,13 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt) } #ifdef CONFIG_SCHED_MC -static ssize_t sched_mc_power_savings_show(struct sys_device *dev, char *page) +static ssize_t sched_mc_power_savings_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *page) { return sprintf(page, "%u\n", sched_mc_power_savings); } static ssize_t sched_mc_power_savings_store(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { return sched_power_savings_store(buf, count, 0); @@ -7751,11 +7753,13 @@ static SYSDEV_ATTR(sched_mc_power_savings, 0644, sched_mc_power_savings_show, #endif #ifdef CONFIG_SCHED_SMT -static ssize_t sched_smt_power_savings_show(struct sys_device *dev, char *page) +static ssize_t sched_smt_power_savings_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *page) { return sprintf(page, "%u\n", sched_smt_power_savings); } static ssize_t sched_smt_power_savings_store(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { return sched_power_savings_store(buf, count, 1); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index dadde53..b1c2da8 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -376,7 +376,8 @@ void clocksource_unregister(struct clocksource *cs) * Provides sysfs interface for listing current clocksource. */ static ssize_t -sysfs_show_current_clocksources(struct sys_device *dev, char *buf) +sysfs_show_current_clocksources(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) { ssize_t count = 0; @@ -397,6 +398,7 @@ sysfs_show_current_clocksources(struct sys_device *dev, char *buf) * clocksource selction. */ static ssize_t sysfs_override_clocksource(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { struct clocksource *ovr = NULL; @@ -449,7 +451,9 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev, * Provides sysfs interface for listing registered clocksources */ static ssize_t -sysfs_show_available_clocksources(struct sys_device *dev, char *buf) +sysfs_show_available_clocksources(struct sys_device *dev, + struct sysdev_attribute *attr, + char *buf) { struct clocksource *src; ssize_t count = 0; -- cgit v0.10.2 From 9800794ac11d4646384b3a310dfd1fe2eed577bf Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 1 Jul 2008 18:48:42 +0200 Subject: sysdev: Add utility functions for simple int/ulong variable sysdev attributes This adds a new sysdev_ext_attribute that stores a pointer to the variable it manages and some utility functions/macro to easily use them. Previously all users wrote custom macros to generate show/store functions for each variable, with this it is possible to avoid that in many cases. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/sys.c b/drivers/base/sys.c index dc7dace..40fc14f 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -479,3 +479,52 @@ int __init system_bus_init(void) EXPORT_SYMBOL_GPL(sysdev_register); EXPORT_SYMBOL_GPL(sysdev_unregister); + +#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) + +ssize_t sysdev_store_ulong(struct sys_device *sysdev, + struct sysdev_attribute *attr, + const char *buf, size_t size) +{ + struct sysdev_ext_attribute *ea = to_ext_attr(attr); + char *end; + unsigned long new = simple_strtoul(buf, &end, 0); + if (end == buf) + return -EINVAL; + *(unsigned long *)(ea->var) = new; + return end - buf; +} +EXPORT_SYMBOL_GPL(sysdev_store_ulong); + +ssize_t sysdev_show_ulong(struct sys_device *sysdev, + struct sysdev_attribute *attr, + char *buf) +{ + struct sysdev_ext_attribute *ea = to_ext_attr(attr); + return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); +} +EXPORT_SYMBOL_GPL(sysdev_show_ulong); + +ssize_t sysdev_store_int(struct sys_device *sysdev, + struct sysdev_attribute *attr, + const char *buf, size_t size) +{ + struct sysdev_ext_attribute *ea = to_ext_attr(attr); + char *end; + long new = simple_strtol(buf, &end, 0); + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + *(int *)(ea->var) = new; + return end - buf; +} +EXPORT_SYMBOL_GPL(sysdev_store_int); + +ssize_t sysdev_show_int(struct sys_device *sysdev, + struct sysdev_attribute *attr, + char *buf) +{ + struct sysdev_ext_attribute *ea = to_ext_attr(attr); + return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); +} +EXPORT_SYMBOL_GPL(sysdev_show_int); + diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index 8dcf316..f395bb3 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -119,4 +119,38 @@ struct sysdev_attribute { extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); +struct sysdev_ext_attribute { + struct sysdev_attribute attr; + void *var; +}; + +/* + * Support for simple variable sysdev attributes. + * The pointer to the variable is stored in a sysdev_ext_attribute + */ + +/* Add more types as needed */ + +extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *, + char *); +extern ssize_t sysdev_store_ulong(struct sys_device *, + struct sysdev_attribute *, const char *, size_t); +extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *, + char *); +extern ssize_t sysdev_store_int(struct sys_device *, + struct sysdev_attribute *, const char *, size_t); + +#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \ + { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \ + &(_var) } +#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \ + struct sysdev_ext_attribute attr_##_name = \ + _SYSDEV_ULONG_ATTR(_name, _mode, _var); +#define _SYSDEV_INT_ATTR(_name, _mode, _var) \ + { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \ + &(_var) } +#define SYSDEV_INT_ATTR(_name, _mode, _var) \ + struct sysdev_ext_attribute attr_##_name = \ + _SYSDEV_INT_ATTR(_name, _mode, _var); + #endif /* _SYSDEV_H_ */ -- cgit v0.10.2 From d95d62c018209355c0dc998682ff792432aa870c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 1 Jul 2008 18:48:43 +0200 Subject: sysdev: Convert the x86 mce tolerant sysdev attribute to generic attribute Use the new generic int attribute accessors for the x86 mce tolerant attribute. Simple example to illustrate the new macros. There are much more places all over the tree that could be converted like this. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index e6a4d5f..9ab65be 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -812,12 +812,12 @@ static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, } static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger); -ACCESSOR(tolerant,tolerant,) +static SYSDEV_INT_ATTR(tolerant, 0644, tolerant); ACCESSOR(check_interval,check_interval,mce_restart()) static struct sysdev_attribute *mce_attributes[] = { &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl, &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl, - &attr_tolerant, &attr_check_interval, &attr_trigger, + &attr_tolerant.attr, &attr_check_interval, &attr_trigger, NULL }; -- cgit v0.10.2 From 89bcb05d9bbf8bd559988bca4f2579defd28d008 Mon Sep 17 00:00:00 2001 From: David Altobelli Date: Wed, 2 Jul 2008 09:38:53 -0600 Subject: HP iLO driver A driver for the HP iLO/iLO2 management processor, which allows userspace programs to query the management processor. Programs can open a channel to the device (/dev/hpilo/dXccbN), and use this to send/receive queries. The O_EXCL open flag is used to indicate that a particular channel cannot be shared between processes. This driver will replace various packages HP has shipped, including hprsm and hp-ilo. Signed-off-by: David Altobelli Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1921b8d..ce67d97 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -420,4 +420,17 @@ config SGI_XP this feature will allow for direct communication between SSIs based on a network adapter and DMA messaging. +config HP_ILO + tristate "Channel interface driver for HP iLO/iLO2 processor" + default n + help + The channel interface driver allows applications to communicate + with iLO/iLO2 management processors present on HP ProLiant + servers. Upon loading, the driver creates /dev/hpilo/dXccbN files, + which can be used to gather data from the management processor, + via read and write system calls. + + To compile this driver as a module, choose M here: the + module will be called hpilo. + endif # MISC_DEVICES diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index a6dac6a..688fe76 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o obj-$(CONFIG_KGDB_TESTS) += kgdbts.o obj-$(CONFIG_SGI_XP) += sgi-xp/ +obj-$(CONFIG_HP_ILO) += hpilo.o diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c new file mode 100644 index 0000000..05e2982 --- /dev/null +++ b/drivers/misc/hpilo.c @@ -0,0 +1,768 @@ +/* + * Driver for HP iLO/iLO2 management processor. + * + * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. + * David Altobelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hpilo.h" + +static struct class *ilo_class; +static unsigned int ilo_major; +static char ilo_hwdev[MAX_ILO_DEV]; + +static inline int get_entry_id(int entry) +{ + return (entry & ENTRY_MASK_DESCRIPTOR) >> ENTRY_BITPOS_DESCRIPTOR; +} + +static inline int get_entry_len(int entry) +{ + return ((entry & ENTRY_MASK_QWORDS) >> ENTRY_BITPOS_QWORDS) << 3; +} + +static inline int mk_entry(int id, int len) +{ + int qlen = len & 7 ? (len >> 3) + 1 : len >> 3; + return id << ENTRY_BITPOS_DESCRIPTOR | qlen << ENTRY_BITPOS_QWORDS; +} + +static inline int desc_mem_sz(int nr_entry) +{ + return nr_entry << L2_QENTRY_SZ; +} + +/* + * FIFO queues, shared with hardware. + * + * If a queue has empty slots, an entry is added to the queue tail, + * and that entry is marked as occupied. + * Entries can be dequeued from the head of the list, when the device + * has marked the entry as consumed. + * + * Returns true on successful queue/dequeue, false on failure. + */ +static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry) +{ + struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); + int ret = 0; + + spin_lock(&hw->fifo_lock); + if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask] + & ENTRY_MASK_O)) { + fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |= + (entry & ENTRY_MASK_NOSTATE) | fifo_q->merge; + fifo_q->tail += 1; + ret = 1; + } + spin_unlock(&hw->fifo_lock); + + return ret; +} + +static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry) +{ + struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); + int ret = 0; + u64 c; + + spin_lock(&hw->fifo_lock); + c = fifo_q->fifobar[fifo_q->head & fifo_q->imask]; + if (c & ENTRY_MASK_C) { + if (entry) + *entry = c & ENTRY_MASK_NOSTATE; + + fifo_q->fifobar[fifo_q->head & fifo_q->imask] = + (c | ENTRY_MASK) + 1; + fifo_q->head += 1; + ret = 1; + } + spin_unlock(&hw->fifo_lock); + + return ret; +} + +static int ilo_pkt_enqueue(struct ilo_hwinfo *hw, struct ccb *ccb, + int dir, int id, int len) +{ + char *fifobar; + int entry; + + if (dir == SENDQ) + fifobar = ccb->ccb_u1.send_fifobar; + else + fifobar = ccb->ccb_u3.recv_fifobar; + + entry = mk_entry(id, len); + return fifo_enqueue(hw, fifobar, entry); +} + +static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb, + int dir, int *id, int *len, void **pkt) +{ + char *fifobar, *desc; + int entry = 0, pkt_id = 0; + int ret; + + if (dir == SENDQ) { + fifobar = ccb->ccb_u1.send_fifobar; + desc = ccb->ccb_u2.send_desc; + } else { + fifobar = ccb->ccb_u3.recv_fifobar; + desc = ccb->ccb_u4.recv_desc; + } + + ret = fifo_dequeue(hw, fifobar, &entry); + if (ret) { + pkt_id = get_entry_id(entry); + if (id) + *id = pkt_id; + if (len) + *len = get_entry_len(entry); + if (pkt) + *pkt = (void *)(desc + desc_mem_sz(pkt_id)); + } + + return ret; +} + +static inline void doorbell_set(struct ccb *ccb) +{ + iowrite8(1, ccb->ccb_u5.db_base); +} + +static inline void doorbell_clr(struct ccb *ccb) +{ + iowrite8(2, ccb->ccb_u5.db_base); +} +static inline int ctrl_set(int l2sz, int idxmask, int desclim) +{ + int active = 0, go = 1; + return l2sz << CTRL_BITPOS_L2SZ | + idxmask << CTRL_BITPOS_FIFOINDEXMASK | + desclim << CTRL_BITPOS_DESCLIMIT | + active << CTRL_BITPOS_A | + go << CTRL_BITPOS_G; +} +static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz) +{ + /* for simplicity, use the same parameters for send and recv ctrls */ + ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1); + ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1); +} + +static inline int fifo_sz(int nr_entry) +{ + /* size of a fifo is determined by the number of entries it contains */ + return (nr_entry * sizeof(u64)) + FIFOHANDLESIZE; +} + +static void fifo_setup(void *base_addr, int nr_entry) +{ + struct fifo *fifo_q = base_addr; + int i; + + /* set up an empty fifo */ + fifo_q->head = 0; + fifo_q->tail = 0; + fifo_q->reset = 0; + fifo_q->nrents = nr_entry; + fifo_q->imask = nr_entry - 1; + fifo_q->merge = ENTRY_MASK_O; + + for (i = 0; i < nr_entry; i++) + fifo_q->fifobar[i] = 0; +} + +static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) +{ + struct ccb *driver_ccb; + struct ccb __iomem *device_ccb; + int retries; + + driver_ccb = &data->driver_ccb; + device_ccb = data->mapped_ccb; + + /* complicated dance to tell the hw we are stopping */ + doorbell_clr(driver_ccb); + iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), + &device_ccb->send_ctrl); + iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G), + &device_ccb->recv_ctrl); + + /* give iLO some time to process stop request */ + for (retries = 1000; retries > 0; retries--) { + doorbell_set(driver_ccb); + udelay(1); + if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) + && + !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) + break; + } + if (retries == 0) + dev_err(&pdev->dev, "Closing, but controller still active\n"); + + /* clear the hw ccb */ + memset_io(device_ccb, 0, sizeof(struct ccb)); + + /* free resources used to back send/recv queues */ + pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); +} + +static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) +{ + char *dma_va, *dma_pa; + int pkt_id, pkt_sz, i, error; + struct ccb *driver_ccb, *ilo_ccb; + struct pci_dev *pdev; + + driver_ccb = &data->driver_ccb; + ilo_ccb = &data->ilo_ccb; + pdev = hw->ilo_dev; + + data->dma_size = 2 * fifo_sz(NR_QENTRY) + + 2 * desc_mem_sz(NR_QENTRY) + + ILO_START_ALIGN + ILO_CACHE_SZ; + + error = -ENOMEM; + data->dma_va = pci_alloc_consistent(pdev, data->dma_size, + &data->dma_pa); + if (!data->dma_va) + goto out; + + dma_va = (char *)data->dma_va; + dma_pa = (char *)data->dma_pa; + + memset(dma_va, 0, data->dma_size); + + dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN); + dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_START_ALIGN); + + /* + * Create two ccb's, one with virt addrs, one with phys addrs. + * Copy the phys addr ccb to device shared mem. + */ + ctrl_setup(driver_ccb, NR_QENTRY, L2_QENTRY_SZ); + ctrl_setup(ilo_ccb, NR_QENTRY, L2_QENTRY_SZ); + + fifo_setup(dma_va, NR_QENTRY); + driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE; + ilo_ccb->ccb_u1.send_fifobar = dma_pa + FIFOHANDLESIZE; + dma_va += fifo_sz(NR_QENTRY); + dma_pa += fifo_sz(NR_QENTRY); + + dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ); + dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_CACHE_SZ); + + fifo_setup(dma_va, NR_QENTRY); + driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE; + ilo_ccb->ccb_u3.recv_fifobar = dma_pa + FIFOHANDLESIZE; + dma_va += fifo_sz(NR_QENTRY); + dma_pa += fifo_sz(NR_QENTRY); + + driver_ccb->ccb_u2.send_desc = dma_va; + ilo_ccb->ccb_u2.send_desc = dma_pa; + dma_pa += desc_mem_sz(NR_QENTRY); + dma_va += desc_mem_sz(NR_QENTRY); + + driver_ccb->ccb_u4.recv_desc = dma_va; + ilo_ccb->ccb_u4.recv_desc = dma_pa; + + driver_ccb->channel = slot; + ilo_ccb->channel = slot; + + driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE); + ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */ + + /* copy the ccb with physical addrs to device memory */ + data->mapped_ccb = (struct ccb __iomem *) + (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); + memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb)); + + /* put packets on the send and receive queues */ + pkt_sz = 0; + for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) { + ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz); + doorbell_set(driver_ccb); + } + + pkt_sz = desc_mem_sz(1); + for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) + ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz); + + doorbell_clr(driver_ccb); + + /* make sure iLO is really handling requests */ + for (i = 1000; i > 0; i--) { + if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) + break; + udelay(1); + } + + if (i) { + ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0); + doorbell_set(driver_ccb); + } else { + dev_err(&pdev->dev, "Open could not dequeue a packet\n"); + error = -EBUSY; + goto free; + } + + return 0; +free: + pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); +out: + return error; +} + +static inline int is_channel_reset(struct ccb *ccb) +{ + /* check for this particular channel needing a reset */ + return FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset; +} + +static inline void set_channel_reset(struct ccb *ccb) +{ + /* set a flag indicating this channel needs a reset */ + FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1; +} + +static inline int is_device_reset(struct ilo_hwinfo *hw) +{ + /* check for global reset condition */ + return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET); +} + +static inline void clear_device(struct ilo_hwinfo *hw) +{ + /* clear the device (reset bits, pending channel entries) */ + iowrite32(-1, &hw->mmio_vaddr[DB_OUT]); +} + +static void ilo_locked_reset(struct ilo_hwinfo *hw) +{ + int slot; + + /* + * Mapped memory is zeroed on ilo reset, so set a per ccb flag + * to indicate that this ccb needs to be closed and reopened. + */ + for (slot = 0; slot < MAX_CCB; slot++) { + if (!hw->ccb_alloc[slot]) + continue; + set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb); + } + + clear_device(hw); +} + +static void ilo_reset(struct ilo_hwinfo *hw) +{ + spin_lock(&hw->alloc_lock); + + /* reset might have been handled after lock was taken */ + if (is_device_reset(hw)) + ilo_locked_reset(hw); + + spin_unlock(&hw->alloc_lock); +} + +static ssize_t ilo_read(struct file *fp, char __user *buf, + size_t len, loff_t *off) +{ + int err, found, cnt, pkt_id, pkt_len; + struct ccb_data *data; + struct ccb *driver_ccb; + struct ilo_hwinfo *hw; + void *pkt; + + data = fp->private_data; + driver_ccb = &data->driver_ccb; + hw = data->ilo_hw; + + if (is_device_reset(hw) || is_channel_reset(driver_ccb)) { + /* + * If the device has been reset, applications + * need to close and reopen all ccbs. + */ + ilo_reset(hw); + return -ENODEV; + } + + /* + * This function is to be called when data is expected + * in the channel, and will return an error if no packet is found + * during the loop below. The sleep/retry logic is to allow + * applications to call read() immediately post write(), + * and give iLO some time to process the sent packet. + */ + cnt = 20; + do { + /* look for a received packet */ + found = ilo_pkt_dequeue(hw, driver_ccb, RECVQ, &pkt_id, + &pkt_len, &pkt); + if (found) + break; + cnt--; + msleep(100); + } while (!found && cnt); + + if (!found) + return -EAGAIN; + + /* only copy the length of the received packet */ + if (pkt_len < len) + len = pkt_len; + + err = copy_to_user(buf, pkt, len); + + /* return the received packet to the queue */ + ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, desc_mem_sz(1)); + + return err ? -EFAULT : len; +} + +static ssize_t ilo_write(struct file *fp, const char __user *buf, + size_t len, loff_t *off) +{ + int err, pkt_id, pkt_len; + struct ccb_data *data; + struct ccb *driver_ccb; + struct ilo_hwinfo *hw; + void *pkt; + + data = fp->private_data; + driver_ccb = &data->driver_ccb; + hw = data->ilo_hw; + + if (is_device_reset(hw) || is_channel_reset(driver_ccb)) { + /* + * If the device has been reset, applications + * need to close and reopen all ccbs. + */ + ilo_reset(hw); + return -ENODEV; + } + + /* get a packet to send the user command */ + if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt)) + return -EBUSY; + + /* limit the length to the length of the packet */ + if (pkt_len < len) + len = pkt_len; + + /* on failure, set the len to 0 to return empty packet to the device */ + err = copy_from_user(pkt, buf, len); + if (err) + len = 0; + + /* send the packet */ + ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len); + doorbell_set(driver_ccb); + + return err ? -EFAULT : len; +} + +static int ilo_close(struct inode *ip, struct file *fp) +{ + int slot; + struct ccb_data *data; + struct ilo_hwinfo *hw; + + slot = iminor(ip) % MAX_CCB; + hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); + + spin_lock(&hw->alloc_lock); + + if (is_device_reset(hw)) + ilo_locked_reset(hw); + + if (hw->ccb_alloc[slot]->ccb_cnt == 1) { + + data = fp->private_data; + + ilo_ccb_close(hw->ilo_dev, data); + + kfree(data); + hw->ccb_alloc[slot] = NULL; + } else + hw->ccb_alloc[slot]->ccb_cnt--; + + spin_unlock(&hw->alloc_lock); + + return 0; +} + +static int ilo_open(struct inode *ip, struct file *fp) +{ + int slot, error; + struct ccb_data *data; + struct ilo_hwinfo *hw; + + slot = iminor(ip) % MAX_CCB; + hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); + + /* new ccb allocation */ + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock(&hw->alloc_lock); + + if (is_device_reset(hw)) + ilo_locked_reset(hw); + + /* each fd private_data holds sw/hw view of ccb */ + if (hw->ccb_alloc[slot] == NULL) { + /* create a channel control block for this minor */ + error = ilo_ccb_open(hw, data, slot); + if (!error) { + hw->ccb_alloc[slot] = data; + hw->ccb_alloc[slot]->ccb_cnt = 1; + hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL; + hw->ccb_alloc[slot]->ilo_hw = hw; + } else + kfree(data); + } else { + kfree(data); + if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) { + /* + * The channel exists, and either this open + * or a previous open of this channel wants + * exclusive access. + */ + error = -EBUSY; + } else { + hw->ccb_alloc[slot]->ccb_cnt++; + error = 0; + } + } + spin_unlock(&hw->alloc_lock); + + if (!error) + fp->private_data = hw->ccb_alloc[slot]; + + return error; +} + +static const struct file_operations ilo_fops = { + .owner = THIS_MODULE, + .read = ilo_read, + .write = ilo_write, + .open = ilo_open, + .release = ilo_close, +}; + +static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) +{ + pci_iounmap(pdev, hw->db_vaddr); + pci_iounmap(pdev, hw->ram_vaddr); + pci_iounmap(pdev, hw->mmio_vaddr); +} + +static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) +{ + int error = -ENOMEM; + + /* map the memory mapped i/o registers */ + hw->mmio_vaddr = pci_iomap(pdev, 1, 0); + if (hw->mmio_vaddr == NULL) { + dev_err(&pdev->dev, "Error mapping mmio\n"); + goto out; + } + + /* map the adapter shared memory region */ + hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ); + if (hw->ram_vaddr == NULL) { + dev_err(&pdev->dev, "Error mapping shared mem\n"); + goto mmio_free; + } + + /* map the doorbell aperture */ + hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE); + if (hw->db_vaddr == NULL) { + dev_err(&pdev->dev, "Error mapping doorbell\n"); + goto ram_free; + } + + return 0; +ram_free: + pci_iounmap(pdev, hw->ram_vaddr); +mmio_free: + pci_iounmap(pdev, hw->mmio_vaddr); +out: + return error; +} + +static void ilo_remove(struct pci_dev *pdev) +{ + int i, minor; + struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev); + + clear_device(ilo_hw); + + minor = MINOR(ilo_hw->cdev.dev); + for (i = minor; i < minor + MAX_CCB; i++) + device_destroy(ilo_class, MKDEV(ilo_major, i)); + + cdev_del(&ilo_hw->cdev); + ilo_unmap_device(pdev, ilo_hw); + pci_release_regions(pdev); + pci_disable_device(pdev); + kfree(ilo_hw); + ilo_hwdev[(minor / MAX_CCB)] = 0; +} + +static int __devinit ilo_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int devnum, minor, start, error; + struct ilo_hwinfo *ilo_hw; + + /* find a free range for device files */ + for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) { + if (ilo_hwdev[devnum] == 0) { + ilo_hwdev[devnum] = 1; + break; + } + } + + if (devnum == MAX_ILO_DEV) { + dev_err(&pdev->dev, "Error finding free device\n"); + return -ENODEV; + } + + /* track global allocations for this device */ + error = -ENOMEM; + ilo_hw = kzalloc(sizeof(*ilo_hw), GFP_KERNEL); + if (!ilo_hw) + goto out; + + ilo_hw->ilo_dev = pdev; + spin_lock_init(&ilo_hw->alloc_lock); + spin_lock_init(&ilo_hw->fifo_lock); + + error = pci_enable_device(pdev); + if (error) + goto free; + + pci_set_master(pdev); + + error = pci_request_regions(pdev, ILO_NAME); + if (error) + goto disable; + + error = ilo_map_device(pdev, ilo_hw); + if (error) + goto free_regions; + + pci_set_drvdata(pdev, ilo_hw); + clear_device(ilo_hw); + + cdev_init(&ilo_hw->cdev, &ilo_fops); + ilo_hw->cdev.owner = THIS_MODULE; + start = devnum * MAX_CCB; + error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB); + if (error) { + dev_err(&pdev->dev, "Could not add cdev\n"); + goto unmap; + } + + for (minor = 0 ; minor < MAX_CCB; minor++) { + struct device *dev; + dev = device_create(ilo_class, &pdev->dev, + MKDEV(ilo_major, minor), NULL, + "hpilo!d%dccb%d", devnum, minor); + if (IS_ERR(dev)) + dev_err(&pdev->dev, "Could not create files\n"); + } + + return 0; +unmap: + ilo_unmap_device(pdev, ilo_hw); +free_regions: + pci_release_regions(pdev); +disable: + pci_disable_device(pdev); +free: + kfree(ilo_hw); +out: + ilo_hwdev[devnum] = 0; + return error; +} + +static struct pci_device_id ilo_devices[] = { + { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) }, + { } +}; +MODULE_DEVICE_TABLE(pci, ilo_devices); + +static struct pci_driver ilo_driver = { + .name = ILO_NAME, + .id_table = ilo_devices, + .probe = ilo_probe, + .remove = __devexit_p(ilo_remove), +}; + +static int __init ilo_init(void) +{ + int error; + dev_t dev; + + ilo_class = class_create(THIS_MODULE, "iLO"); + if (IS_ERR(ilo_class)) { + error = PTR_ERR(ilo_class); + goto out; + } + + error = alloc_chrdev_region(&dev, 0, MAX_OPEN, ILO_NAME); + if (error) + goto class_destroy; + + ilo_major = MAJOR(dev); + + error = pci_register_driver(&ilo_driver); + if (error) + goto chr_remove; + + return 0; +chr_remove: + unregister_chrdev_region(dev, MAX_OPEN); +class_destroy: + class_destroy(ilo_class); +out: + return error; +} + +static void __exit ilo_exit(void) +{ + pci_unregister_driver(&ilo_driver); + unregister_chrdev_region(MKDEV(ilo_major, 0), MAX_OPEN); + class_destroy(ilo_class); +} + +MODULE_VERSION("0.05"); +MODULE_ALIAS(ILO_NAME); +MODULE_DESCRIPTION(ILO_NAME); +MODULE_AUTHOR("David Altobelli "); +MODULE_LICENSE("GPL v2"); + +module_init(ilo_init); +module_exit(ilo_exit); diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h new file mode 100644 index 0000000..a281207 --- /dev/null +++ b/drivers/misc/hpilo.h @@ -0,0 +1,189 @@ +/* + * linux/drivers/char/hpilo.h + * + * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. + * David Altobelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __HPILO_H +#define __HPILO_H + +#define ILO_NAME "hpilo" + +/* max number of open channel control blocks per device, hw limited to 32 */ +#define MAX_CCB 8 +/* max number of supported devices */ +#define MAX_ILO_DEV 1 +/* max number of files */ +#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) + +/* + * Per device, used to track global memory allocations. + */ +struct ilo_hwinfo { + /* mmio registers on device */ + char __iomem *mmio_vaddr; + + /* doorbell registers on device */ + char __iomem *db_vaddr; + + /* shared memory on device used for channel control blocks */ + char __iomem *ram_vaddr; + + /* files corresponding to this device */ + struct ccb_data *ccb_alloc[MAX_CCB]; + + struct pci_dev *ilo_dev; + + spinlock_t alloc_lock; + spinlock_t fifo_lock; + + struct cdev cdev; +}; + +/* offset from mmio_vaddr */ +#define DB_OUT 0xD4 +/* DB_OUT reset bit */ +#define DB_RESET 26 + +/* + * Channel control block. Used to manage hardware queues. + * The format must match hw's version. The hw ccb is 128 bytes, + * but the context area shouldn't be touched by the driver. + */ +#define ILOSW_CCB_SZ 64 +#define ILOHW_CCB_SZ 128 +struct ccb { + union { + char *send_fifobar; + u64 padding1; + } ccb_u1; + union { + char *send_desc; + u64 padding2; + } ccb_u2; + u64 send_ctrl; + + union { + char *recv_fifobar; + u64 padding3; + } ccb_u3; + union { + char *recv_desc; + u64 padding4; + } ccb_u4; + u64 recv_ctrl; + + union { + char __iomem *db_base; + u64 padding5; + } ccb_u5; + + u64 channel; + + /* unused context area (64 bytes) */ +}; + +/* ccb queue parameters */ +#define SENDQ 1 +#define RECVQ 2 +#define NR_QENTRY 4 +#define L2_QENTRY_SZ 12 + +/* ccb ctrl bitfields */ +#define CTRL_BITPOS_L2SZ 0 +#define CTRL_BITPOS_FIFOINDEXMASK 4 +#define CTRL_BITPOS_DESCLIMIT 18 +#define CTRL_BITPOS_A 30 +#define CTRL_BITPOS_G 31 + +/* ccb doorbell macros */ +#define L2_DB_SIZE 14 +#define ONE_DB_SIZE (1 << L2_DB_SIZE) + +/* + * Per fd structure used to track the ccb allocated to that dev file. + */ +struct ccb_data { + /* software version of ccb, using virtual addrs */ + struct ccb driver_ccb; + + /* hardware version of ccb, using physical addrs */ + struct ccb ilo_ccb; + + /* hardware ccb is written to this shared mapped device memory */ + struct ccb __iomem *mapped_ccb; + + /* dma'able memory used for send/recv queues */ + void *dma_va; + dma_addr_t dma_pa; + size_t dma_size; + + /* pointer to hardware device info */ + struct ilo_hwinfo *ilo_hw; + + /* usage count, to allow for shared ccb's */ + int ccb_cnt; + + /* open wanted exclusive access to this ccb */ + int ccb_excl; +}; + +/* + * FIFO queue structure, shared with hw. + */ +#define ILO_START_ALIGN 4096 +#define ILO_CACHE_SZ 128 +struct fifo { + u64 nrents; /* user requested number of fifo entries */ + u64 imask; /* mask to extract valid fifo index */ + u64 merge; /* O/C bits to merge in during enqueue operation */ + u64 reset; /* set to non-zero when the target device resets */ + u8 pad_0[ILO_CACHE_SZ - (sizeof(u64) * 4)]; + + u64 head; + u8 pad_1[ILO_CACHE_SZ - (sizeof(u64))]; + + u64 tail; + u8 pad_2[ILO_CACHE_SZ - (sizeof(u64))]; + + u64 fifobar[1]; +}; + +/* convert between struct fifo, and the fifobar, which is saved in the ccb */ +#define FIFOHANDLESIZE (sizeof(struct fifo) - sizeof(u64)) +#define FIFOBARTOHANDLE(_fifo) \ + ((struct fifo *)(((char *)(_fifo)) - FIFOHANDLESIZE)) + +/* the number of qwords to consume from the entry descriptor */ +#define ENTRY_BITPOS_QWORDS 0 +/* descriptor index number (within a specified queue) */ +#define ENTRY_BITPOS_DESCRIPTOR 10 +/* state bit, fifo entry consumed by consumer */ +#define ENTRY_BITPOS_C 22 +/* state bit, fifo entry is occupied */ +#define ENTRY_BITPOS_O 23 + +#define ENTRY_BITS_QWORDS 10 +#define ENTRY_BITS_DESCRIPTOR 12 +#define ENTRY_BITS_C 1 +#define ENTRY_BITS_O 1 +#define ENTRY_BITS_TOTAL \ + (ENTRY_BITS_C + ENTRY_BITS_O + \ + ENTRY_BITS_QWORDS + ENTRY_BITS_DESCRIPTOR) + +/* extract various entry fields */ +#define ENTRY_MASK ((1 << ENTRY_BITS_TOTAL) - 1) +#define ENTRY_MASK_C (((1 << ENTRY_BITS_C) - 1) << ENTRY_BITPOS_C) +#define ENTRY_MASK_O (((1 << ENTRY_BITS_O) - 1) << ENTRY_BITPOS_O) +#define ENTRY_MASK_QWORDS \ + (((1 << ENTRY_BITS_QWORDS) - 1) << ENTRY_BITPOS_QWORDS) +#define ENTRY_MASK_DESCRIPTOR \ + (((1 << ENTRY_BITS_DESCRIPTOR) - 1) << ENTRY_BITPOS_DESCRIPTOR) + +#define ENTRY_MASK_NOSTATE (ENTRY_MASK >> (ENTRY_BITS_C + ENTRY_BITS_O)) + +#endif /* __HPILO_H */ -- cgit v0.10.2 From eadcf0d704a46979c29984fa05f1fc413c775bcb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Jul 2008 12:46:22 -0700 Subject: MTD: handle pci_name() being const This changes the MTD core to handle pci_name() now returning a constant string. Cc: David Woodhouse Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 519d942..7b72a1b 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -241,6 +241,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) { struct block_device *bdev; struct block2mtd_dev *dev; + char *name; if (!devname) return NULL; @@ -279,12 +280,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Setup the MTD structure */ /* make the name contain the block device in */ - dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname), + name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1, GFP_KERNEL); - if (!dev->mtd.name) + if (!name) goto devinit_err; - sprintf(dev->mtd.name, "block2mtd: %s", devname); + sprintf(name, "block2mtd: %s", devname); + dev->mtd.name = name; dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; dev->mtd.erasesize = erase_size; diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index a9fae03..9c1d954 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -189,7 +189,7 @@ typedef union { */ struct map_info { - char *name; + const char *name; unsigned long size; resource_size_t phys; #define NO_XIP (-1UL) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 245f909..8b5d491 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -121,7 +121,7 @@ struct mtd_info { u_int32_t oobavail; // Available OOB bytes per block // Kernel-only stuff starts here. - char *name; + const char *name; int index; /* ecc layout structure pointer - read only ! */ -- cgit v0.10.2 From 361d5ee3c04c43c8fa0e277545ac5258dc310a5e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Jul 2008 12:46:22 -0700 Subject: 3c59x: handle pci_name() being const This changes vortex_prob1() to handle pci_name() now returning a constant string. Cc: Steffen Klassert Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index aabad8c..8db4e6b 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1010,7 +1010,7 @@ static int __devinit vortex_probe1(struct device *gendev, static int printed_version; int retval, print_info; struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; - char *print_name = "3c59x"; + const char *print_name = "3c59x"; struct pci_dev *pdev = NULL; struct eisa_device *edev = NULL; DECLARE_MAC_BUF(mac); -- cgit v0.10.2 From 2222c313e9371b6476787594bc5804c72cee2597 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 May 2008 06:02:41 +0200 Subject: sparc64: fix up bus_id changes in sparc core code This converts all instances of bus_id in the sparc core kernel to use either dev_set_name(), or dev_name() depending on the need. This is done in anticipation of removing the bus_id field from struct driver. Cc: Kay Sievers Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index c49d038..4d58d7c 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -401,7 +401,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; - sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); + dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) @@ -501,7 +501,7 @@ void __init ebus_init(void) ebus->ofdev.node = dp; ebus->ofdev.dev.parent = &pdev->dev; ebus->ofdev.dev.bus = &ebus_bus_type; - sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); + dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); /* Register with core */ if (of_device_register(&ebus->ofdev) != 0) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index d569f60..4fd48ab 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -797,9 +797,9 @@ static struct of_device * __init scan_one_device(struct device_node *dp, op->dev.parent = parent; op->dev.bus = &of_platform_bus_type; if (!parent) - strcpy(op->dev.bus_id, "root"); + dev_set_name(&op->dev, "root"); else - sprintf(op->dev.bus_id, "%08x", dp->node); + dev_set_name(&op->dev, "%08x", dp->node); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index d00a365..5509619 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->class = class >> 8; dev->revision = class & 0xff; - sprintf(dev->dev.bus_id, "%04x:%02x:%02x.%d", pci_domain_nr(bus), + dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(bus), dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); if (ofpci_verbose) diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index ecbb8b6..a490077 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -260,16 +260,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, vio_fill_channel_info(hp, mp, vdev); if (!id) { - snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", - bus_id_name); + dev_set_name(&vdev->dev, "%s", bus_id_name); vdev->dev_no = ~(u64)0; } else if (!cfg_handle) { - snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", - bus_id_name, *id); + dev_set_name(&vdev->dev, "%s-%lu", bus_id_name, *id); vdev->dev_no = *id; } else { - snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu", - bus_id_name, *cfg_handle, *id); + dev_set_name(&vdev->dev, "%s-%lu-%lu", bus_id_name, + *cfg_handle, *id); vdev->dev_no = *cfg_handle; } @@ -292,12 +290,12 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, } vdev->dp = dp; - printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id); + printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev)); err = device_register(&vdev->dev); if (err) { printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", - vdev->dev.bus_id, err); + dev_name(&vdev->dev), err); kfree(vdev); return NULL; } @@ -330,7 +328,7 @@ static void vio_remove(struct mdesc_handle *hp, u64 node) dev = device_find_child(&root_vdev->dev, (void *) node, vio_md_node_match); if (dev) { - printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id); + printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev)); device_unregister(dev); } diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index c37d7c2..73a86d0 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -78,7 +78,7 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde else sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; sdev->ofdev.dev.bus = &sbus_bus_type; - sprintf(sdev->ofdev.dev.bus_id, "sbus[%08x]", dp->node); + dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node); if (of_device_register(&sdev->ofdev) != 0) printk(KERN_DEBUG "sbus: device registration error for %s!\n", @@ -257,11 +257,11 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus) sbus->ofdev.node = dp; sbus->ofdev.dev.parent = NULL; sbus->ofdev.dev.bus = &sbus_bus_type; - sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus); + dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus); if (of_device_register(&sbus->ofdev) != 0) printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sbus->ofdev.dev.bus_id); + dev_name(&sbus->ofdev.dev)); dev_dp = dp->child; while (dev_dp) { -- cgit v0.10.2 From 3f9787046ea37a26170dc4439efa21f8d23a9978 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 30 May 2008 17:42:11 +0200 Subject: arm: bus_id -> dev_name() and dev_set_name() conversions Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index d973c98..c3c3a33 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -543,7 +543,6 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) goto out; } - strncpy(dev->dev.bus_id, info->name, sizeof(dev->dev.bus_id)); /* * If the parent device has a DMA mask associated with it, * propagate it down to the children. @@ -553,6 +552,7 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) dev->dev.dma_mask = &dev->dma_mask; } + dev_set_name(&dev->dev, "%s", info->name); dev->devid = info->devid; dev->dev.parent = lchip->dev; dev->dev.bus = &locomo_bus_type; diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 2048ae0..c8e8f0e 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -550,9 +550,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, goto out; } - snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), - "%4.4lx", info->offset); - + dev_set_name(&dev->dev, "%4.4lx", info->offset); dev->devid = info->devid; dev->dev.parent = sachip->dev; dev->dev.bus = &sa1111_bus_type; @@ -560,7 +558,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask; dev->res.start = sachip->phys + info->offset; dev->res.end = dev->res.start + 511; - dev->res.name = dev->dev.bus_id; + dev->res.name = dev_name(&dev->dev); dev->res.flags = IORESOURCE_MEM; dev->mapbase = sachip->base + info->offset; dev->skpcr_mask = info->skpcr_mask; @@ -570,6 +568,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, if (ret) { printk("SA1111: failed to allocate resource for %s\n", dev->res.name); + dev_set_name(&dev->dev, NULL); kfree(dev); goto out; } diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index bc299b0..ae39553 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -247,7 +247,7 @@ static int __devinit scoop_probe(struct platform_device *pdev) devptr->gpio.base = -1; if (inf->gpio_base != 0) { - devptr->gpio.label = pdev->dev.bus_id; + devptr->gpio.label = dev_name(&pdev->dev); devptr->gpio.base = inf->gpio_base; devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */ devptr->gpio.set = scoop_gpio_set; diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 2de425f..f5cfdab 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -783,7 +783,7 @@ static void ecard_proc_init(void) #define ec_set_resource(ec,nr,st,sz) \ do { \ - (ec)->resource[nr].name = ec->dev.bus_id; \ + (ec)->resource[nr].name = dev_name(&ec->dev); \ (ec)->resource[nr].start = st; \ (ec)->resource[nr].end = (st) + (sz) - 1; \ (ec)->resource[nr].flags = IORESOURCE_MEM; \ diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 619d05e..5a1588c 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -393,9 +393,7 @@ static int impd1_probe(struct lm_device *dev) if (!d) continue; - snprintf(d->dev.bus_id, sizeof(d->dev.bus_id), - "lm%x:%5.5lx", dev->id, idev->offset >> 12); - + dev_set_name(&d->dev, "lm%x:%5.5lx", dev->id, idev->offset >> 12); d->dev.parent = &dev->dev; d->res.start = dev->resource.start + idev->offset; d->res.end = d->res.start + SZ_4K - 1; diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c index 622cdc4..f939c50 100644 --- a/arch/arm/mach-integrator/lm.c +++ b/arch/arm/mach-integrator/lm.c @@ -81,8 +81,10 @@ int lm_device_register(struct lm_device *dev) dev->dev.release = lm_device_release; dev->dev.bus = &lm_bustype; - snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "lm%d", dev->id); - dev->resource.name = dev->dev.bus_id; + ret = dev_set_name(&dev->dev, "lm%d", dev->id); + if (ret) + return ret; + dev->resource.name = dev_name(&dev->dev); ret = request_resource(&iomem_resource, &dev->resource); if (ret == 0) { diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 848fdca..ff1413e 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -334,7 +334,7 @@ static int omap_mbox_init(struct omap_mbox *mbox) } mbox->dev.class = &omap_mbox_class; - strlcpy(mbox->dev.bus_id, mbox->name, BUS_ID_SIZE); + dev_set_name(&mbox->dev, "%s", mbox->name); dev_set_drvdata(&mbox->dev, mbox); ret = device_register(&mbox->dev); diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 1e39e78..71f7cec 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -677,7 +677,7 @@ static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo { strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static const struct ethtool_ops at91ether_ethtool_ops = { diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index ecd8fc6..7a14980 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -848,7 +848,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev) ep->res = request_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1, - pdev->dev.bus_id); + dev_name(&pdev->dev)); if (ep->res == NULL) { dev_err(&pdev->dev, "Could not reserve memory region\n"); err = -ENOMEM; diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index e9d15ec..5c5f1e4 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -535,7 +535,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec) if (!ecard_readchunk(&cd, ec, 0xf5, 0)) { printk(KERN_ERR "%s: unable to read podule description string\n", - ec->dev.bus_id); + dev_name(&ec->dev)); goto no_addr; } @@ -554,7 +554,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec) } printk(KERN_ERR "%s: unable to parse MAC address: %s\n", - ec->dev.bus_id, cd.d.string); + dev_name(&ec->dev), cd.d.string); no_addr: return -ENODEV; @@ -585,7 +585,7 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i { strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } -- cgit v0.10.2