Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (27 commits) Driver core: fix race in dev_driver_string Driver Core: Early platform driver buffer sysfs: sysfs_setattr remove unnecessary permission check. sysfs: Factor out sysfs_rename from sysfs_rename_dir and sysfs_move_dir sysfs: Propagate renames to the vfs on demand sysfs: Gut sysfs_addrm_start and sysfs_addrm_finish sysfs: In sysfs_chmod_file lazily propagate the mode change. sysfs: Implement sysfs_getattr & sysfs_permission sysfs: Nicely indent sysfs_symlink_inode_operations sysfs: Update s_iattr on link and unlink. sysfs: Fix locking and factor out sysfs_sd_setattr sysfs: Simplify iattr time assignments sysfs: Simplify sysfs_chmod_file semantics sysfs: Use dentry_ops instead of directly playing with the dcache sysfs: Rename sysfs_d_iput to sysfs_dentry_iput sysfs: Update sysfs_setxattr so it updates secdata under the sysfs_mutex debugfs: fix create mutex racy fops and private data Driver core: Don't remove kobjects in device_shutdown. firmware_class: make request_firmware_nowait more useful Driver-Core: devtmpfs - set root directory mode to 0755 ...
This commit is contained in:
@@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev)
|
||||
*/
|
||||
const char *dev_driver_string(const struct device *dev)
|
||||
{
|
||||
return dev->driver ? dev->driver->name :
|
||||
struct device_driver *drv;
|
||||
|
||||
/* dev->driver can change to NULL underneath us because of unbinding,
|
||||
* so be careful about accessing it. dev->bus and dev->class should
|
||||
* never change once they are set, so they don't need special care.
|
||||
*/
|
||||
drv = ACCESS_ONCE(dev->driver);
|
||||
return drv ? drv->name :
|
||||
(dev->bus ? dev->bus->name :
|
||||
(dev->class ? dev->class->name : ""));
|
||||
}
|
||||
@@ -986,6 +993,8 @@ done:
|
||||
AttrsError:
|
||||
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:
|
||||
@@ -1728,8 +1737,5 @@ void device_shutdown(void)
|
||||
dev->driver->shutdown(dev);
|
||||
}
|
||||
}
|
||||
kobject_put(sysfs_dev_char_kobj);
|
||||
kobject_put(sysfs_dev_block_kobj);
|
||||
kobject_put(dev_kobj);
|
||||
async_synchronize_full();
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@ static int dev_mount = 1;
|
||||
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 @@ static int dev_mkdir(const char *name, mode_t mode)
|
||||
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;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
||||
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 @@ static int create_path(const char *nodepath)
|
||||
s[0] = '/';
|
||||
s++;
|
||||
}
|
||||
kfree(path);
|
||||
}
|
||||
|
||||
kfree(path);
|
||||
read_unlock(&dirlock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -156,34 +146,40 @@ int devtmpfs_create_node(struct device *dev)
|
||||
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;
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
notify_change(dentry, &newattrs);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
|
||||
/* 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 +201,21 @@ static int dev_rmdir(const char *name)
|
||||
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 +229,8 @@ static int delete_path(const char *nodepath)
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
while (1) {
|
||||
write_lock(&dirlock);
|
||||
for (;;) {
|
||||
char *base;
|
||||
|
||||
base = strrchr(path, '/');
|
||||
@@ -239,6 +241,7 @@ static int delete_path(const char *nodepath)
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
write_unlock(&dirlock);
|
||||
|
||||
kfree(path);
|
||||
return err;
|
||||
@@ -322,9 +325,8 @@ out:
|
||||
* 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 +335,11 @@ int devtmpfs_mount(const char *mountpoint)
|
||||
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("devtmpfs", (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 +352,8 @@ int __init devtmpfs_init(void)
|
||||
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 +361,7 @@ int __init devtmpfs_init(void)
|
||||
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);
|
||||
|
@@ -601,12 +601,9 @@ request_firmware_work_func(void *arg)
|
||||
}
|
||||
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 @@ request_firmware_work_func(void *arg)
|
||||
* 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 @@ request_firmware_work_func(void *arg)
|
||||
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;
|
||||
|
@@ -1000,7 +1000,7 @@ static __initdata LIST_HEAD(early_platform_device_list);
|
||||
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||
char *buf)
|
||||
{
|
||||
unsigned long index;
|
||||
char *tmp;
|
||||
int n;
|
||||
|
||||
/* Simply add the driver to the end of the global list.
|
||||
@@ -1019,13 +1019,28 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||
if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
|
||||
list_move(&epdrv->list, &early_platform_driver_list);
|
||||
|
||||
if (!strcmp(buf, epdrv->pdrv->driver.name))
|
||||
/* Allow passing parameters after device name */
|
||||
if (buf[n] == '\0' || buf[n] == ',')
|
||||
epdrv->requested_id = -1;
|
||||
else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
|
||||
&index) == 0)
|
||||
epdrv->requested_id = index;
|
||||
else
|
||||
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
|
||||
else {
|
||||
epdrv->requested_id = simple_strtoul(&buf[n + 1],
|
||||
&tmp, 10);
|
||||
|
||||
if (buf[n] != '.' || (tmp == &buf[n + 1])) {
|
||||
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
|
||||
n = 0;
|
||||
} else
|
||||
n += strcspn(&buf[n + 1], ",") + 1;
|
||||
}
|
||||
|
||||
if (buf[n] == ',')
|
||||
n++;
|
||||
|
||||
if (epdrv->bufsize) {
|
||||
memcpy(epdrv->buffer, &buf[n],
|
||||
min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
|
||||
epdrv->buffer[epdrv->bufsize - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -544,9 +544,12 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
|
||||
{
|
||||
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 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
|
||||
} 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 @@ static ssize_t write_rbu_image_type(struct kobject *kobj,
|
||||
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
|
||||
|
@@ -44,9 +44,20 @@ struct ilo_hwinfo {
|
||||
|
||||
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;
|
||||
};
|
||||
|
@@ -1179,16 +1179,18 @@ static void uart_firmware_cont(const struct firmware *fw, void *context)
|
||||
|
||||
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 @@ static int ucc_uart_probe(struct of_device *ofdev,
|
||||
*/
|
||||
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",
|
||||
|
@@ -2327,9 +2327,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
|
||||
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 @@ static int usbduxsub_probe(struct usb_interface *uinterf,
|
||||
FW_ACTION_HOTPLUG,
|
||||
"usbdux_firmware.bin",
|
||||
&udev->dev,
|
||||
GFP_KERNEL,
|
||||
usbduxsub + index,
|
||||
usbdux_firmware_request_complete_handler);
|
||||
|
||||
|
@@ -1451,10 +1451,12 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware
|
||||
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 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf,
|
||||
FW_ACTION_HOTPLUG,
|
||||
"usbduxfast_firmware.bin",
|
||||
&udev->dev,
|
||||
GFP_KERNEL,
|
||||
usbduxfastsub + index,
|
||||
usbduxfast_firmware_request_complete_handler);
|
||||
|
||||
|
@@ -667,12 +667,12 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
|
||||
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 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
|
||||
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
|
||||
|
Reference in New Issue
Block a user