From 0eb9b18eb108a9d169084ee154155041f413e945 Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Sun, 1 Feb 2004 23:39:32 -0800 Subject: [PATCH] Driver core: add hotplug support for class_simple This is needed by the DRI code. --- include/linux/device.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index 367b21888ad4..c8f5aa7d9f5a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -253,6 +253,8 @@ extern struct class_simple *class_simple_create(struct module *owner, char *name extern void class_simple_destroy(struct class_simple *cs); extern struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...) __attribute__((format(printf,4,5))); +extern int class_simple_set_hotplug(struct class_simple *, + int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size)); extern void class_simple_device_remove(dev_t dev); -- cgit v1.2.3 From 9d6cc8f23f0e0d00a29faabf059e12cdd2c1becb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Feb 2004 21:48:53 -0800 Subject: [PATCH] Driver core: remove device_unregister_wait() as it's a very bad idea. --- drivers/base/core.c | 23 ----------------------- include/linux/device.h | 2 -- 2 files changed, 25 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/core.c b/drivers/base/core.c index 84bc01e0ce59..6c84ff06026b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -76,7 +76,6 @@ static struct sysfs_ops dev_sysfs_ops = { static void device_release(struct kobject * kobj) { struct device * dev = to_dev(kobj); - struct completion * c = dev->complete; if (dev->release) dev->release(dev); @@ -86,8 +85,6 @@ static void device_release(struct kobject * kobj) dev->bus_id); WARN_ON(1); } - if (c) - complete(c); } static struct kobj_type ktype_device = { @@ -354,25 +351,6 @@ void device_unregister(struct device * dev) } -/** - * device_unregister_wait - Unregister device and wait for it to be freed. - * @dev: Device to unregister. - * - * For the cases where the caller needs to wait for all references to - * be dropped from the device before continuing (e.g. modules with - * statically allocated devices), this function uses a completion struct - * to wait, along with a matching complete() in device_release() above. - */ - -void device_unregister_wait(struct device * dev) -{ - struct completion c; - init_completion(&c); - dev->complete = &c; - device_unregister(dev); - wait_for_completion(&c); -} - /** * device_for_each_child - device child iterator. * @dev: parent struct device. @@ -421,7 +399,6 @@ EXPORT_SYMBOL(device_register); EXPORT_SYMBOL(device_del); EXPORT_SYMBOL(device_unregister); -EXPORT_SYMBOL(device_unregister_wait); EXPORT_SYMBOL(get_device); EXPORT_SYMBOL(put_device); EXPORT_SYMBOL(device_find); diff --git a/include/linux/device.h b/include/linux/device.h index c8f5aa7d9f5a..6da63dac06b0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -265,7 +265,6 @@ struct device { struct list_head children; struct device * parent; - struct completion * complete; /* Notification for freeing device. */ struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ @@ -313,7 +312,6 @@ dev_set_drvdata (struct device *dev, void *data) */ extern int device_register(struct device * dev); extern void device_unregister(struct device * dev); -extern void device_unregister_wait(struct device * dev); extern void device_initialize(struct device * dev); extern int device_add(struct device * dev); extern void device_del(struct device * dev); -- cgit v1.2.3 From d4f63c8a506cf37ea05681f824cdd407ea8aeaf8 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 5 Feb 2004 22:07:24 -0800 Subject: [PATCH] Char drivers: cdev_unmap() To recap my argument: the current cdev implementation keeps an uncounted reference to every cdev in cdev_map. Creators of cdevs must know to call cdev_unmap() with the same arguments they passed to cdev_add() before releasing the device, or that reference will remain and will oops the kernel should user space attempt to open the (missing) device. It's an easy mistake to make, and, IMO, entirely unnecessary; the cdev code should be able to do its own bookkeeping. --- drivers/char/tty_io.c | 1 - drivers/ieee1394/amdtp.c | 1 - drivers/ieee1394/dv1394.c | 1 - drivers/ieee1394/raw1394.c | 1 - drivers/ieee1394/video1394.c | 1 - drivers/scsi/sg.c | 1 - drivers/scsi/st.c | 4 ---- fs/char_dev.c | 7 ++++--- include/linux/cdev.h | 4 ++-- 9 files changed, 6 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 963f6fb2b5dd..33a9c5cb4ecd 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2264,7 +2264,6 @@ int tty_unregister_driver(struct tty_driver *driver) if (driver->refcount) return -EBUSY; - cdev_unmap(MKDEV(driver->major, driver->minor_start), driver->num); unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), driver->num); diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 3fc004d47884..94630dcaac2d 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -1308,7 +1308,6 @@ static void __exit amdtp_exit_module (void) hpsb_unregister_highlevel(&amdtp_highlevel); devfs_remove("amdtp"); - cdev_unmap(IEEE1394_AMDTP_DEV, 16); cdev_del(&amdtp_cdev); HPSB_INFO("Unloaded AMDTP driver"); diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index dd16cccc2eb1..881340aa52ac 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2609,7 +2609,6 @@ static void __exit dv1394_exit_module(void) hpsb_unregister_protocol(&dv1394_driver); hpsb_unregister_highlevel(&dv1394_highlevel); - cdev_unmap(IEEE1394_DV1394_DEV, 16); cdev_del(&dv1394_cdev); devfs_remove("ieee1394/dv"); } diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 83e5a7c5149b..405c6d59bcd9 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2682,7 +2682,6 @@ static int __init init_raw1394(void) static void __exit cleanup_raw1394(void) { hpsb_unregister_protocol(&raw1394_driver); - cdev_unmap(IEEE1394_RAW1394_DEV, 1); cdev_del(&raw1394_cdev); devfs_remove(RAW1394_DEVICE_NAME); hpsb_unregister_highlevel(&raw1394_highlevel); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 6353ef25628d..d66d517d0187 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1447,7 +1447,6 @@ static void __exit video1394_exit_module (void) hpsb_unregister_highlevel(&video1394_highlevel); devfs_remove(VIDEO1394_DRIVER_NAME); - cdev_unmap(IEEE1394_VIDEO1394_DEV, 16); cdev_del(&video1394_cdev); PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 6c210f52c5e0..9141152f33ce 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1521,7 +1521,6 @@ sg_remove(struct class_device *cl_dev) if (sdp) { sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); class_simple_device_remove(MKDEV(SCSI_GENERIC_MAJOR, k)); - cdev_unmap(MKDEV(SCSI_GENERIC_MAJOR, k), 1); cdev_del(sdp->cdev); sdp->cdev = NULL; devfs_remove("%s/generic", scsidp->devfs_name); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index fc5b890e6f80..d566897fecbe 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3946,8 +3946,6 @@ out_free_tape: if (cdev == STm->cdevs[j]) cdev = NULL; sysfs_remove_link(&STm->cdevs[j]->kobj, "device"); - cdev_unmap(MKDEV(SCSI_TAPE_MAJOR, - TAPE_MINOR(dev_num, mode, j)), 1); cdev_del(STm->cdevs[j]); } } @@ -3990,8 +3988,6 @@ static int st_remove(struct device *dev) for (j=0; j < 2; j++) { sysfs_remove_link(&tpnt->modes[mode].cdevs[j]->kobj, "device"); - cdev_unmap(MKDEV(SCSI_TAPE_MAJOR, - TAPE_MINOR(i, mode, j)), 1); cdev_del(tpnt->modes[mode].cdevs[j]); tpnt->modes[mode].cdevs[j] = NULL; } diff --git a/fs/char_dev.c b/fs/char_dev.c index 50ab4cf8e8e1..7a1d47c3157a 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -240,7 +240,6 @@ void unregister_chrdev_region(dev_t from, unsigned count) int unregister_chrdev(unsigned int major, const char *name) { struct char_device_struct *cd; - cdev_unmap(MKDEV(major, 0), 256); cd = __unregister_chrdev_region(major, 0, 256); if (cd && cd->cdev) cdev_del(cd->cdev); @@ -347,16 +346,19 @@ int cdev_add(struct cdev *p, dev_t dev, unsigned count) err = kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); if (err) kobject_del(&p->kobj); + p->dev = dev; + p->count = count; return err; } -void cdev_unmap(dev_t dev, unsigned count) +static void cdev_unmap(dev_t dev, unsigned count) { kobj_unmap(cdev_map, dev, count); } void cdev_del(struct cdev *p) { + cdev_unmap(p->dev, p->count); kobject_del(&p->kobj); kobject_put(&p->kobj); } @@ -458,6 +460,5 @@ EXPORT_SYMBOL(cdev_get); EXPORT_SYMBOL(cdev_put); EXPORT_SYMBOL(cdev_del); EXPORT_SYMBOL(cdev_add); -EXPORT_SYMBOL(cdev_unmap); EXPORT_SYMBOL(register_chrdev); EXPORT_SYMBOL(unregister_chrdev); diff --git a/include/linux/cdev.h b/include/linux/cdev.h index 191c800fa127..f1996ec09e96 100644 --- a/include/linux/cdev.h +++ b/include/linux/cdev.h @@ -7,6 +7,8 @@ struct cdev { struct module *owner; struct file_operations *ops; struct list_head list; + dev_t dev; + unsigned int count; }; void cdev_init(struct cdev *, struct file_operations *); @@ -21,8 +23,6 @@ int cdev_add(struct cdev *, dev_t, unsigned); void cdev_del(struct cdev *); -void cdev_unmap(dev_t, unsigned); - void cd_forget(struct inode *); #endif -- cgit v1.2.3