diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/base/core.c linux-2.6.32-rc6-driver-core/drivers/base/core.c --- linux-2.6.32-rc6-staging.current/drivers/base/core.c 2009-11-04 15:20:15.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/base/core.c 2009-11-06 20:57:04.000000000 -0800 @@ -987,6 +987,8 @@ device_remove_class_symlinks(dev); SymlinkError: if (MAJOR(dev->devt)) + devtmpfs_delete_node(dev); + if (MAJOR(dev->devt)) device_remove_sys_dev_entry(dev); devtattrError: if (MAJOR(dev->devt)) @@ -1728,8 +1730,5 @@ dev->driver->shutdown(dev); } } - kobject_put(sysfs_dev_char_kobj); - kobject_put(sysfs_dev_block_kobj); - kobject_put(dev_kobj); async_synchronize_full(); } diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/base/devtmpfs.c linux-2.6.32-rc6-driver-core/drivers/base/devtmpfs.c --- linux-2.6.32-rc6-staging.current/drivers/base/devtmpfs.c 2009-11-04 15:20:15.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/base/devtmpfs.c 2009-11-06 20:57:04.000000000 -0800 @@ -32,6 +32,8 @@ static int dev_mount; #endif +static rwlock_t dirlock; + static int __init mount_param(char *str) { dev_mount = simple_strtoul(str, NULL, 0); @@ -74,47 +76,35 @@ dentry = lookup_create(&nd, 1); if (!IS_ERR(dentry)) { err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); + if (!err) + /* mark as kernel-created inode */ + dentry->d_inode->i_private = &dev_mnt; dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; } static int create_path(const char *nodepath) { - char *path; - struct nameidata nd; - int err = 0; - - path = kstrdup(nodepath, GFP_KERNEL); - if (!path) - return -ENOMEM; - - err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, - path, LOOKUP_PARENT, &nd); - if (err == 0) { - struct dentry *dentry; - - /* create directory right away */ - dentry = lookup_create(&nd, 1); - if (!IS_ERR(dentry)) { - err = vfs_mkdir(nd.path.dentry->d_inode, - dentry, 0755); - dput(dentry); - } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + int err; - path_put(&nd.path); - } else if (err == -ENOENT) { + read_lock(&dirlock); + err = dev_mkdir(nodepath, 0755); + if (err == -ENOENT) { + char *path; char *s; /* parent directories do not exist, create them */ + path = kstrdup(nodepath, GFP_KERNEL); + if (!path) + return -ENOMEM; s = path; - while (1) { + for (;;) { s = strchr(s, '/'); if (!s) break; @@ -125,9 +115,9 @@ s[0] = '/'; s++; } + kfree(path); } - - kfree(path); + read_unlock(&dirlock); return err; } @@ -156,34 +146,38 @@ mode |= S_IFCHR; curr_cred = override_creds(&init_cred); + err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err == -ENOENT) { - /* create missing parent directories */ create_path(nodename); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); - if (err) - goto out; } + if (err) + goto out; dentry = lookup_create(&nd, 0); if (!IS_ERR(dentry)) { - int umask; - - umask = sys_umask(0000); err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, dev->devt); - sys_umask(umask); - /* mark as kernel created inode */ - if (!err) + if (!err) { + struct iattr newattrs; + + /* fixup possibly umasked mode */ + newattrs.ia_mode = mode; + newattrs.ia_valid = ATTR_MODE; + notify_change(dentry, &newattrs); + + /* mark as kernel-created inode */ dentry->d_inode->i_private = &dev_mnt; + } dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); out: kfree(tmp); @@ -205,16 +199,21 @@ mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { - if (dentry->d_inode) - err = vfs_rmdir(nd.path.dentry->d_inode, dentry); - else + if (dentry->d_inode) { + if (dentry->d_inode->i_private == &dev_mnt) + err = vfs_rmdir(nd.path.dentry->d_inode, + dentry); + else + err = -EPERM; + } else { err = -ENOENT; + } dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; } @@ -228,7 +227,8 @@ if (!path) return -ENOMEM; - while (1) { + write_lock(&dirlock); + for (;;) { char *base; base = strrchr(path, '/'); @@ -239,6 +239,7 @@ if (err) break; } + write_unlock(&dirlock); kfree(path); return err; @@ -322,9 +323,8 @@ * If configured, or requested by the commandline, devtmpfs will be * auto-mounted after the kernel mounted the root filesystem. */ -int devtmpfs_mount(const char *mountpoint) +int devtmpfs_mount(const char *mntdir) { - struct path path; int err; if (!dev_mount) @@ -333,15 +333,11 @@ if (!dev_mnt) return 0; - err = kern_path(mountpoint, LOOKUP_FOLLOW, &path); - if (err) - return err; - err = do_add_mount(dev_mnt, &path, 0, NULL); + err = sys_mount("none", (char *)mntdir, "devtmpfs", MS_SILENT, NULL); if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else printk(KERN_INFO "devtmpfs: mounted\n"); - path_put(&path); return err; } @@ -354,6 +350,8 @@ int err; struct vfsmount *mnt; + rwlock_init(&dirlock); + err = register_filesystem(&dev_fs_type); if (err) { printk(KERN_ERR "devtmpfs: unable to register devtmpfs " @@ -361,7 +359,7 @@ return err; } - mnt = kern_mount(&dev_fs_type); + mnt = kern_mount_data(&dev_fs_type, "mode=0755"); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/base/firmware_class.c linux-2.6.32-rc6-driver-core/drivers/base/firmware_class.c --- linux-2.6.32-rc6-staging.current/drivers/base/firmware_class.c 2009-10-05 16:45:07.000000000 -0700 +++ linux-2.6.32-rc6-driver-core/drivers/base/firmware_class.c 2009-11-06 20:57:04.000000000 -0800 @@ -601,12 +601,9 @@ } ret = _request_firmware(&fw, fw_work->name, fw_work->device, fw_work->uevent); - if (ret < 0) - fw_work->cont(NULL, fw_work->context); - else { - fw_work->cont(fw, fw_work->context); - release_firmware(fw); - } + + fw_work->cont(fw, fw_work->context); + module_put(fw_work->module); kfree(fw_work); return ret; @@ -619,6 +616,7 @@ * is non-zero else the firmware copy must be done manually. * @name: name of firmware file * @device: device for which firmware is being loaded + * @gfp: allocation flags * @context: will be passed over to @cont, and * @fw may be %NULL if firmware request fails. * @cont: function will be called asynchronously when the firmware @@ -631,12 +629,12 @@ int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { struct task_struct *task; struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), - GFP_ATOMIC); + gfp); if (!fw_work) return -ENOMEM; diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/firmware/dell_rbu.c linux-2.6.32-rc6-driver-core/drivers/firmware/dell_rbu.c --- linux-2.6.32-rc6-staging.current/drivers/firmware/dell_rbu.c 2009-03-23 16:12:14.000000000 -0700 +++ linux-2.6.32-rc6-driver-core/drivers/firmware/dell_rbu.c 2009-11-06 20:57:04.000000000 -0800 @@ -544,9 +544,12 @@ { rbu_data.entry_created = 0; - if (!fw || !fw->size) + if (!fw) return; + if (!fw->size) + goto out; + spin_lock(&rbu_data.lock); if (!strcmp(image_type, "mono")) { if (!img_update_realloc(fw->size)) @@ -568,6 +571,8 @@ } else pr_debug("invalid image type specified.\n"); spin_unlock(&rbu_data.lock); + out: + release_firmware(fw); } static ssize_t read_rbu_image_type(struct kobject *kobj, @@ -615,7 +620,7 @@ spin_unlock(&rbu_data.lock); req_firm_rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, "dell_rbu", - &rbu_device->dev, &context, + &rbu_device->dev, GFP_KERNEL, &context, callbackfn_rbu); if (req_firm_rc) { printk(KERN_ERR diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/misc/hpilo.h linux-2.6.32-rc6-driver-core/drivers/misc/hpilo.h --- linux-2.6.32-rc6-staging.current/drivers/misc/hpilo.h 2009-11-04 15:20:22.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/misc/hpilo.h 2009-11-06 20:57:04.000000000 -0800 @@ -44,9 +44,20 @@ struct pci_dev *ilo_dev; + /* + * open_lock serializes ccb_cnt during open and close + * [ irq disabled ] + * -> alloc_lock used when adding/removing/searching ccb_alloc, + * which represents all ccbs open on the device + * --> fifo_lock controls access to fifo queues shared with hw + * + * Locks must be taken in this order, but open_lock and alloc_lock + * are optional, they do not need to be held in order to take a + * lower level lock. + */ + spinlock_t open_lock; spinlock_t alloc_lock; spinlock_t fifo_lock; - spinlock_t open_lock; struct cdev cdev; }; diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/serial/ucc_uart.c linux-2.6.32-rc6-driver-core/drivers/serial/ucc_uart.c --- linux-2.6.32-rc6-staging.current/drivers/serial/ucc_uart.c 2009-11-04 15:20:32.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/serial/ucc_uart.c 2009-11-06 20:57:04.000000000 -0800 @@ -1179,16 +1179,18 @@ if (firmware->header.length != fw->size) { dev_err(dev, "invalid firmware\n"); - return; + goto out; } ret = qe_upload_firmware(firmware); if (ret) { dev_err(dev, "could not load firmware\n"); - return; + goto out; } firmware_loaded = 1; + out: + release_firmware(fw); } static int ucc_uart_probe(struct of_device *ofdev, @@ -1247,7 +1249,7 @@ */ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, filename, &ofdev->dev, - &ofdev->dev, uart_firmware_cont); + GFP_KERNEL, &ofdev->dev, uart_firmware_cont); if (ret) { dev_err(&ofdev->dev, "could not load firmware %s\n", diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/staging/comedi/drivers/usbdux.c linux-2.6.32-rc6-driver-core/drivers/staging/comedi/drivers/usbdux.c --- linux-2.6.32-rc6-staging.current/drivers/staging/comedi/drivers/usbdux.c 2009-11-04 15:20:36.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/staging/comedi/drivers/usbdux.c 2009-11-06 20:57:04.000000000 -0800 @@ -2327,9 +2327,11 @@ if (ret) { dev_err(&usbdev->dev, "Could not upload firmware (err=%d)\n", ret); - return; + goto out; } comedi_usb_auto_config(usbdev, BOARDNAME); + out: + release_firmware(fw); } /* allocate memory for the urbs and initialise them */ @@ -2580,6 +2582,7 @@ FW_ACTION_HOTPLUG, "usbdux_firmware.bin", &udev->dev, + GFP_KERNEL, usbduxsub + index, usbdux_firmware_request_complete_handler); diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/staging/comedi/drivers/usbduxfast.c linux-2.6.32-rc6-driver-core/drivers/staging/comedi/drivers/usbduxfast.c --- linux-2.6.32-rc6-staging.current/drivers/staging/comedi/drivers/usbduxfast.c 2009-11-04 15:20:36.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/drivers/staging/comedi/drivers/usbduxfast.c 2009-11-06 20:57:04.000000000 -0800 @@ -1451,10 +1451,12 @@ if (ret) { dev_err(&usbdev->dev, "Could not upload firmware (err=%d)\n", ret); - return; + goto out; } comedi_usb_auto_config(usbdev, BOARDNAME); + out: + release_firmware(fw); } /* @@ -1569,6 +1571,7 @@ FW_ACTION_HOTPLUG, "usbduxfast_firmware.bin", &udev->dev, + GFP_KERNEL, usbduxfastsub + index, usbduxfast_firmware_request_complete_handler); diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/drivers/usb/atm/ueagle-atm.c linux-2.6.32-rc6-driver-core/drivers/usb/atm/ueagle-atm.c --- linux-2.6.32-rc6-staging.current/drivers/usb/atm/ueagle-atm.c 2009-10-05 16:45:24.000000000 -0700 +++ linux-2.6.32-rc6-driver-core/drivers/usb/atm/ueagle-atm.c 2009-11-06 20:57:04.000000000 -0800 @@ -667,12 +667,12 @@ else uea_info(usb, "firmware uploaded\n"); - uea_leaves(usb); - return; + goto err; err_fw_corrupted: uea_err(usb, "firmware is corrupted\n"); err: + release_firmware(fw_entry); uea_leaves(usb); } @@ -705,7 +705,8 @@ break; } - ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); + ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, + GFP_KERNEL, usb, uea_upload_pre_firmware); if (ret) uea_err(usb, "firmware %s is not available\n", fw_name); else diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/fs/sysfs/inode.c linux-2.6.32-rc6-driver-core/fs/sysfs/inode.c --- linux-2.6.32-rc6-staging.current/fs/sysfs/inode.c 2009-11-04 15:20:47.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/fs/sysfs/inode.c 2009-11-06 20:57:04.000000000 -0800 @@ -46,7 +46,7 @@ return bdi_init(&sysfs_backing_dev_info); } -struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) +static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) { struct sysfs_inode_attrs *attrs; struct iattr *iattrs; @@ -64,6 +64,7 @@ return attrs; } + int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/include/linux/device.h linux-2.6.32-rc6-driver-core/include/linux/device.h --- linux-2.6.32-rc6-staging.current/include/linux/device.h 2009-11-04 15:20:47.000000000 -0800 +++ linux-2.6.32-rc6-driver-core/include/linux/device.h 2009-11-06 20:57:04.000000000 -0800 @@ -558,7 +558,7 @@ #ifdef CONFIG_DEVTMPFS extern int devtmpfs_create_node(struct device *dev); extern int devtmpfs_delete_node(struct device *dev); -extern int devtmpfs_mount(const char *mountpoint); +extern int devtmpfs_mount(const char *mntdir); #else static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } diff -Naur -X linux-2.6.32-rc6-staging.current/Documentation/dontdiff linux-2.6.32-rc6-staging.current/include/linux/firmware.h linux-2.6.32-rc6-driver-core/include/linux/firmware.h --- linux-2.6.32-rc6-staging.current/include/linux/firmware.h 2009-10-05 16:45:29.000000000 -0700 +++ linux-2.6.32-rc6-driver-core/include/linux/firmware.h 2009-11-06 20:57:04.000000000 -0800 @@ -4,6 +4,7 @@ #include #include #include +#include #define FW_ACTION_NOHOTPLUG 0 #define FW_ACTION_HOTPLUG 1 @@ -38,7 +39,7 @@ struct device *device); int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); @@ -51,7 +52,7 @@ } static inline int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { return -EINVAL;