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: (28 commits)
  driver core: device_rename's new_name can be const
  sysfs: Remove owner field from sysfs struct attribute
  powerpc/pci: Remove owner field from attribute initialization in PCI bridge init
  regulator: Remove owner field from attribute initialization in regulator core driver
  leds: Remove owner field from attribute initialization in bd2802 driver
  scsi: Remove owner field from attribute initialization in ARCMSR driver
  scsi: Remove owner field from attribute initialization in LPFC driver
  cgroupfs: create /sys/fs/cgroup to mount cgroupfs on
  Driver core: Add BUS_NOTIFY_BIND_DRIVER
  driver core: fix memory leak on one error path in bus_register()
  debugfs: no longer needs to depend on SYSFS
  sysfs: Fix one more signature discrepancy between sysfs implementation and docs.
  sysfs: fix discrepancies between implementation and documentation
  dcdbas: remove a redundant smi_data_buf_free in dcdbas_exit
  dmi-id: fix a memory leak in dmi_id_init error path
  sysfs: sysfs_chmod_file's attr can be const
  firmware: Update hotplug script
  Driver core: move platform device creation helpers to .init.text (if MODULE=n)
  Driver core: reduce duplicated code for platform_device creation
  Driver core: use kmemdup in platform_device_add_resources
  ...
This commit is contained in:
Linus Torvalds 2010-08-06 11:36:30 -07:00
commit ab69bcd66f
26 changed files with 292 additions and 294 deletions

View file

@ -111,6 +111,7 @@ X!Edrivers/base/attribute_container.c
<!-- <!--
X!Edrivers/base/interface.c X!Edrivers/base/interface.c
--> -->
!Iinclude/linux/platform_device.h
!Edrivers/base/platform.c !Edrivers/base/platform.c
!Edrivers/base/bus.c !Edrivers/base/bus.c
</sect1> </sect1>

View file

@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects.
Patrick Mochel <mochel@osdl.org> Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu> Mike Murphy <mamurph@cs.clemson.edu>
Revised: 22 February 2009 Revised: 15 July 2010
Original: 10 January 2003 Original: 10 January 2003
@ -124,7 +124,7 @@ show and store methods of the attribute owners.
struct sysfs_ops { struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *); ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
}; };
[ Subsystems should have already defined a struct kobj_type as a [ Subsystems should have already defined a struct kobj_type as a
@ -139,18 +139,22 @@ calls the associated methods.
To illustrate: To illustrate:
#define to_dev(obj) container_of(obj, struct device, kobj)
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
#define to_dev(d) container_of(d, struct device, kobj)
static ssize_t static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) char *buf)
{ {
struct device_attribute * dev_attr = to_dev_attr(attr); struct device_attribute *dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj); struct device *dev = to_dev(kobj);
ssize_t ret = 0; ssize_t ret = -EIO;
if (dev_attr->show) if (dev_attr->show)
ret = dev_attr->show(dev, buf); ret = dev_attr->show(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
print_symbol("dev_attr_show: %s returned bad count\n",
(unsigned long)dev_attr->show);
}
return ret; return ret;
} }
@ -163,10 +167,9 @@ To read or write attributes, show() or store() methods must be
specified when declaring the attribute. The method types should be as specified when declaring the attribute. The method types should be as
simple as those defined for device attributes: simple as those defined for device attributes:
ssize_t (*show)(struct device * dev, struct device_attribute * attr, ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
char * buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr,
ssize_t (*store)(struct device * dev, struct device_attribute * attr, const char *buf, size_t count);
const char * buf);
IOW, they should take only an object, an attribute, and a buffer as parameters. IOW, they should take only an object, an attribute, and a buffer as parameters.
@ -209,8 +212,8 @@ Other notes:
- show() should always use snprintf(). - show() should always use snprintf().
- store() should return the number of bytes used from the buffer. This - store() should return the number of bytes used from the buffer. If the
can be done using strlen(). entire buffer has been used, just return the count argument.
- show() or store() can always return errors. If a bad value comes - show() or store() can always return errors. If a bad value comes
through, be sure to return an error. through, be sure to return an error.
@ -223,15 +226,18 @@ Other notes:
A very simple (and naive) implementation of a device attribute is: A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%s\n", dev->name); return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
} }
static ssize_t store_name(struct device * dev, const char * buf) static ssize_t store_name(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{ {
sscanf(buf, "%20s", dev->name); snprintf(dev->name, sizeof(dev->name), "%.*s",
return strnlen(buf, PAGE_SIZE); (int)min(count, sizeof(dev->name) - 1), buf);
return count;
} }
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
@ -327,7 +333,7 @@ Structure:
struct bus_attribute { struct bus_attribute {
struct attribute attr; struct attribute attr;
ssize_t (*show)(struct bus_type *, char * buf); ssize_t (*show)(struct bus_type *, char * buf);
ssize_t (*store)(struct bus_type *, const char * buf); ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
}; };
Declaring: Declaring:

View file

@ -6,11 +6,12 @@
HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
echo 1 > /sys/$DEVPATH/loading if [ "$SUBSYSTEM" == "firmware" -a "$ACTION" == "add" ]; then
cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data if [ -f $HOTPLUG_FW_DIR/$FIRMWARE ]; then
echo 0 > /sys/$DEVPATH/loading echo 1 > /sys/$DEVPATH/loading
cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
# To cancel the load in case of error: echo 0 > /sys/$DEVPATH/loading
# else
# echo -1 > /sys/$DEVPATH/loading echo -1 > /sys/$DEVPATH/loading
# fi
fi

View file

@ -73,7 +73,6 @@ static struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */
.attr = { .attr = {
.name = "hs_reg", .name = "hs_reg",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
}, },
.size = MV64X60_VAL_LEN_MAX, .size = MV64X60_VAL_LEN_MAX,
.read = mv64x60_hs_reg_read, .read = mv64x60_hs_reg_read,

View file

@ -945,8 +945,8 @@ int bus_register(struct bus_type *bus)
bus_remove_file(bus, &bus_attr_uevent); bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail: bus_uevent_fail:
kset_unregister(&bus->p->subsys); kset_unregister(&bus->p->subsys);
kfree(bus->p);
out: out:
kfree(bus->p);
bus->p = NULL; bus->p = NULL;
return retval; return retval;
} }

View file

@ -1599,7 +1599,7 @@ EXPORT_SYMBOL_GPL(device_destroy);
* on the same device to ensure that new_name is valid and * on the same device to ensure that new_name is valid and
* won't conflict with other devices. * won't conflict with other devices.
*/ */
int device_rename(struct device *dev, char *new_name) int device_rename(struct device *dev, const char *new_name)
{ {
char *old_class_name = NULL; char *old_class_name = NULL;
char *new_class_name = NULL; char *new_class_name = NULL;

View file

@ -51,6 +51,10 @@ static int driver_sysfs_add(struct device *dev)
{ {
int ret; int ret;
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BIND_DRIVER, dev);
ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
kobject_name(&dev->kobj)); kobject_name(&dev->kobj));
if (ret == 0) { if (ret == 0) {

View file

@ -8,7 +8,7 @@
struct dma_coherent_mem { struct dma_coherent_mem {
void *virt_base; void *virt_base;
u32 device_base; dma_addr_t device_base;
int size; int size;
int flags; int flags;
unsigned long *bitmap; unsigned long *bitmap;

View file

@ -87,29 +87,32 @@ static DEFINE_MUTEX(fw_lock);
struct firmware_priv { struct firmware_priv {
struct completion completion; struct completion completion;
struct bin_attribute attr_data;
struct firmware *fw; struct firmware *fw;
unsigned long status; unsigned long status;
struct page **pages; struct page **pages;
int nr_pages; int nr_pages;
int page_array_size; int page_array_size;
struct timer_list timeout; struct timer_list timeout;
struct device dev;
bool nowait; bool nowait;
char fw_id[]; char fw_id[];
}; };
static void static struct firmware_priv *to_firmware_priv(struct device *dev)
fw_load_abort(struct firmware_priv *fw_priv) {
return container_of(dev, struct firmware_priv, dev);
}
static void fw_load_abort(struct firmware_priv *fw_priv)
{ {
set_bit(FW_STATUS_ABORT, &fw_priv->status); set_bit(FW_STATUS_ABORT, &fw_priv->status);
wmb(); wmb();
complete(&fw_priv->completion); complete(&fw_priv->completion);
} }
static ssize_t static ssize_t firmware_timeout_show(struct class *class,
firmware_timeout_show(struct class *class, struct class_attribute *attr,
struct class_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", loading_timeout); return sprintf(buf, "%d\n", loading_timeout);
} }
@ -127,14 +130,14 @@ firmware_timeout_show(struct class *class,
* *
* Note: zero means 'wait forever'. * Note: zero means 'wait forever'.
**/ **/
static ssize_t static ssize_t firmware_timeout_store(struct class *class,
firmware_timeout_store(struct class *class, struct class_attribute *attr,
struct class_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
loading_timeout = simple_strtol(buf, NULL, 10); loading_timeout = simple_strtol(buf, NULL, 10);
if (loading_timeout < 0) if (loading_timeout < 0)
loading_timeout = 0; loading_timeout = 0;
return count; return count;
} }
@ -146,21 +149,20 @@ static struct class_attribute firmware_class_attrs[] = {
static void fw_dev_release(struct device *dev) static void fw_dev_release(struct device *dev)
{ {
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
int i; int i;
for (i = 0; i < fw_priv->nr_pages; i++) for (i = 0; i < fw_priv->nr_pages; i++)
__free_page(fw_priv->pages[i]); __free_page(fw_priv->pages[i]);
kfree(fw_priv->pages); kfree(fw_priv->pages);
kfree(fw_priv); kfree(fw_priv);
kfree(dev);
module_put(THIS_MODULE); module_put(THIS_MODULE);
} }
static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
return -ENOMEM; return -ENOMEM;
@ -182,8 +184,9 @@ static struct class firmware_class = {
static ssize_t firmware_loading_show(struct device *dev, static ssize_t firmware_loading_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
return sprintf(buf, "%d\n", loading); return sprintf(buf, "%d\n", loading);
} }
@ -219,7 +222,7 @@ static ssize_t firmware_loading_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
int loading = simple_strtol(buf, NULL, 10); int loading = simple_strtol(buf, NULL, 10);
int i; int i;
@ -277,13 +280,12 @@ static ssize_t firmware_loading_store(struct device *dev,
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
static ssize_t static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
firmware_data_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr,
struct bin_attribute *bin_attr, char *buffer, loff_t offset, char *buffer, loff_t offset, size_t count)
size_t count)
{ {
struct device *dev = to_dev(kobj); struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
struct firmware *fw; struct firmware *fw;
ssize_t ret_count; ssize_t ret_count;
@ -322,8 +324,7 @@ firmware_data_read(struct file *filp, struct kobject *kobj,
return ret_count; return ret_count;
} }
static int static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
{ {
int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
@ -373,13 +374,12 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
* Data written to the 'data' attribute will be later handed to * Data written to the 'data' attribute will be later handed to
* the driver as a firmware image. * the driver as a firmware image.
**/ **/
static ssize_t static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj,
firmware_data_write(struct file* filp, struct kobject *kobj, struct bin_attribute *bin_attr,
struct bin_attribute *bin_attr, char *buffer, char *buffer, loff_t offset, size_t count)
loff_t offset, size_t count)
{ {
struct device *dev = to_dev(kobj); struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware_priv *fw_priv = to_firmware_priv(dev);
struct firmware *fw; struct firmware *fw;
ssize_t retval; ssize_t retval;
@ -420,116 +420,103 @@ firmware_data_write(struct file* filp, struct kobject *kobj,
return retval; return retval;
} }
static struct bin_attribute firmware_attr_data_tmpl = { static struct bin_attribute firmware_attr_data = {
.attr = {.name = "data", .mode = 0644}, .attr = { .name = "data", .mode = 0644 },
.size = 0, .size = 0,
.read = firmware_data_read, .read = firmware_data_read,
.write = firmware_data_write, .write = firmware_data_write,
}; };
static void static void firmware_class_timeout(u_long data)
firmware_class_timeout(u_long data)
{ {
struct firmware_priv *fw_priv = (struct firmware_priv *) data; struct firmware_priv *fw_priv = (struct firmware_priv *) data;
fw_load_abort(fw_priv); fw_load_abort(fw_priv);
} }
static int fw_register_device(struct device **dev_p, const char *fw_name, static struct firmware_priv *
struct device *device) fw_create_instance(struct firmware *firmware, const char *fw_name,
struct device *device, bool uevent, bool nowait)
{ {
int retval; struct firmware_priv *fw_priv;
struct firmware_priv *fw_priv = struct device *f_dev;
kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); int error;
struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL);
*dev_p = NULL; fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL);
if (!fw_priv) {
if (!fw_priv || !f_dev) {
dev_err(device, "%s: kmalloc failed\n", __func__); dev_err(device, "%s: kmalloc failed\n", __func__);
retval = -ENOMEM; error = -ENOMEM;
goto error_kfree; goto err_out;
} }
fw_priv->fw = firmware;
fw_priv->nowait = nowait;
strcpy(fw_priv->fw_id, fw_name); strcpy(fw_priv->fw_id, fw_name);
init_completion(&fw_priv->completion); init_completion(&fw_priv->completion);
fw_priv->attr_data = firmware_attr_data_tmpl; setup_timer(&fw_priv->timeout,
fw_priv->timeout.function = firmware_class_timeout; firmware_class_timeout, (u_long) fw_priv);
fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout);
f_dev = &fw_priv->dev;
device_initialize(f_dev);
dev_set_name(f_dev, "%s", dev_name(device)); dev_set_name(f_dev, "%s", dev_name(device));
f_dev->parent = device; f_dev->parent = device;
f_dev->class = &firmware_class; f_dev->class = &firmware_class;
dev_set_drvdata(f_dev, fw_priv);
dev_set_uevent_suppress(f_dev, 1);
retval = device_register(f_dev);
if (retval) {
dev_err(device, "%s: device_register failed\n", __func__);
put_device(f_dev);
return retval;
}
*dev_p = f_dev;
return 0;
error_kfree: dev_set_uevent_suppress(f_dev, true);
kfree(f_dev);
kfree(fw_priv);
return retval;
}
static int fw_setup_device(struct firmware *fw, struct device **dev_p,
const char *fw_name, struct device *device,
int uevent, bool nowait)
{
struct device *f_dev;
struct firmware_priv *fw_priv;
int retval;
*dev_p = NULL;
retval = fw_register_device(&f_dev, fw_name, device);
if (retval)
goto out;
/* Need to pin this module until class device is destroyed */ /* Need to pin this module until class device is destroyed */
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
fw_priv = dev_get_drvdata(f_dev); error = device_add(f_dev);
if (error) {
fw_priv->nowait = nowait; dev_err(device, "%s: device_register failed\n", __func__);
goto err_put_dev;
fw_priv->fw = fw;
sysfs_bin_attr_init(&fw_priv->attr_data);
retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
if (retval) {
dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
goto error_unreg;
} }
retval = device_create_file(f_dev, &dev_attr_loading); error = device_create_bin_file(f_dev, &firmware_attr_data);
if (retval) { if (error) {
dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
goto err_del_dev;
}
error = device_create_file(f_dev, &dev_attr_loading);
if (error) {
dev_err(device, "%s: device_create_file failed\n", __func__); dev_err(device, "%s: device_create_file failed\n", __func__);
goto error_unreg; goto err_del_bin_attr;
} }
if (uevent) if (uevent)
dev_set_uevent_suppress(f_dev, 0); dev_set_uevent_suppress(f_dev, false);
*dev_p = f_dev;
goto out;
error_unreg: return fw_priv;
device_unregister(f_dev);
out: err_del_bin_attr:
return retval; device_remove_bin_file(f_dev, &firmware_attr_data);
err_del_dev:
device_del(f_dev);
err_put_dev:
put_device(f_dev);
err_out:
return ERR_PTR(error);
} }
static int static void fw_destroy_instance(struct firmware_priv *fw_priv)
_request_firmware(const struct firmware **firmware_p, const char *name, {
struct device *device, int uevent, bool nowait) struct device *f_dev = &fw_priv->dev;
device_remove_file(f_dev, &dev_attr_loading);
device_remove_bin_file(f_dev, &firmware_attr_data);
device_unregister(f_dev);
}
static int _request_firmware(const struct firmware **firmware_p,
const char *name, struct device *device,
bool uevent, bool nowait)
{ {
struct device *f_dev;
struct firmware_priv *fw_priv; struct firmware_priv *fw_priv;
struct firmware *firmware; struct firmware *firmware;
int retval; int retval = 0;
if (!firmware_p) if (!firmware_p)
return -EINVAL; return -EINVAL;
@ -550,41 +537,40 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (uevent) if (uevent)
dev_dbg(device, "firmware: requesting %s\n", name); dev_dbg(device, "firmware: requesting %s\n", name);
retval = fw_setup_device(firmware, &f_dev, name, device, fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
uevent, nowait); if (IS_ERR(fw_priv)) {
if (retval) retval = PTR_ERR(fw_priv);
goto error_kfree_fw; goto out;
}
fw_priv = dev_get_drvdata(f_dev);
if (uevent) { if (uevent) {
if (loading_timeout > 0) { if (loading_timeout > 0)
fw_priv->timeout.expires = jiffies + loading_timeout * HZ; mod_timer(&fw_priv->timeout,
add_timer(&fw_priv->timeout); round_jiffies_up(jiffies +
} loading_timeout * HZ));
kobject_uevent(&f_dev->kobj, KOBJ_ADD); kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
wait_for_completion(&fw_priv->completion); }
set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout); wait_for_completion(&fw_priv->completion);
} else
wait_for_completion(&fw_priv->completion); set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout);
mutex_lock(&fw_lock); mutex_lock(&fw_lock);
if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status))
retval = -ENOENT; retval = -ENOENT;
release_firmware(fw_priv->fw);
*firmware_p = NULL;
}
fw_priv->fw = NULL; fw_priv->fw = NULL;
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
device_unregister(f_dev);
goto out;
error_kfree_fw: fw_destroy_instance(fw_priv);
kfree(firmware);
*firmware_p = NULL;
out: out:
if (retval) {
release_firmware(firmware);
firmware_p = NULL;
}
return retval; return retval;
} }
@ -635,23 +621,24 @@ struct firmware_work {
int uevent; int uevent;
}; };
static int static int request_firmware_work_func(void *arg)
request_firmware_work_func(void *arg)
{ {
struct firmware_work *fw_work = arg; struct firmware_work *fw_work = arg;
const struct firmware *fw; const struct firmware *fw;
int ret; int ret;
if (!arg) { if (!arg) {
WARN_ON(1); WARN_ON(1);
return 0; return 0;
} }
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
fw_work->uevent, true);
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
fw_work->uevent, true);
fw_work->cont(fw, fw_work->context); fw_work->cont(fw, fw_work->context);
module_put(fw_work->module); module_put(fw_work->module);
kfree(fw_work); kfree(fw_work);
return ret; return ret;
} }
@ -679,34 +666,33 @@ request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context)) void (*cont)(const struct firmware *fw, void *context))
{ {
struct task_struct *task; struct task_struct *task;
struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), struct firmware_work *fw_work;
gfp);
fw_work = kzalloc(sizeof (struct firmware_work), gfp);
if (!fw_work) if (!fw_work)
return -ENOMEM; return -ENOMEM;
fw_work->module = module;
fw_work->name = name;
fw_work->device = device;
fw_work->context = context;
fw_work->cont = cont;
fw_work->uevent = uevent;
if (!try_module_get(module)) { if (!try_module_get(module)) {
kfree(fw_work); kfree(fw_work);
return -EFAULT; return -EFAULT;
} }
*fw_work = (struct firmware_work) {
.module = module,
.name = name,
.device = device,
.context = context,
.cont = cont,
.uevent = uevent,
};
task = kthread_run(request_firmware_work_func, fw_work, task = kthread_run(request_firmware_work_func, fw_work,
"firmware/%s", name); "firmware/%s", name);
if (IS_ERR(task)) { if (IS_ERR(task)) {
fw_work->cont(NULL, fw_work->context); fw_work->cont(NULL, fw_work->context);
module_put(fw_work->module); module_put(fw_work->module);
kfree(fw_work); kfree(fw_work);
return PTR_ERR(task); return PTR_ERR(task);
} }
return 0; return 0;
} }

View file

@ -192,13 +192,13 @@ int platform_device_add_resources(struct platform_device *pdev,
{ {
struct resource *r; struct resource *r;
r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
if (r) { if (r) {
memcpy(r, res, sizeof(struct resource) * num);
pdev->resource = r; pdev->resource = r;
pdev->num_resources = num; pdev->num_resources = num;
return 0;
} }
return r ? 0 : -ENOMEM; return -ENOMEM;
} }
EXPORT_SYMBOL_GPL(platform_device_add_resources); EXPORT_SYMBOL_GPL(platform_device_add_resources);
@ -345,108 +345,56 @@ void platform_device_unregister(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(platform_device_unregister); EXPORT_SYMBOL_GPL(platform_device_unregister);
/** /**
* platform_device_register_simple - add a platform-level device and its resources * platform_device_register_resndata - add a platform-level device with
* resources and platform-specific data
*
* @parent: parent device for the device we're adding
* @name: base name of the device we're adding * @name: base name of the device we're adding
* @id: instance id * @id: instance id
* @res: set of resources that needs to be allocated for the device * @res: set of resources that needs to be allocated for the device
* @num: number of resources * @num: number of resources
*
* This function creates a simple platform device that requires minimal
* resource and memory management. Canned release function freeing memory
* allocated for the device allows drivers using such devices to be
* unloaded without waiting for the last reference to the device to be
* dropped.
*
* This interface is primarily intended for use with legacy drivers which
* probe hardware directly. Because such drivers create sysfs device nodes
* themselves, rather than letting system infrastructure handle such device
* enumeration tasks, they don't fully conform to the Linux driver model.
* In particular, when such drivers are built as modules, they can't be
* "hotplugged".
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
struct platform_device *platform_device_register_simple(const char *name,
int id,
const struct resource *res,
unsigned int num)
{
struct platform_device *pdev;
int retval;
pdev = platform_device_alloc(name, id);
if (!pdev) {
retval = -ENOMEM;
goto error;
}
if (num) {
retval = platform_device_add_resources(pdev, res, num);
if (retval)
goto error;
}
retval = platform_device_add(pdev);
if (retval)
goto error;
return pdev;
error:
platform_device_put(pdev);
return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(platform_device_register_simple);
/**
* platform_device_register_data - add a platform-level device with platform-specific data
* @parent: parent device for the device we're adding
* @name: base name of the device we're adding
* @id: instance id
* @data: platform specific data for this platform device * @data: platform specific data for this platform device
* @size: size of platform specific data * @size: size of platform specific data
* *
* This function creates a simple platform device that requires minimal
* resource and memory management. Canned release function freeing memory
* allocated for the device allows drivers using such devices to be
* unloaded without waiting for the last reference to the device to be
* dropped.
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error. * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/ */
struct platform_device *platform_device_register_data( struct platform_device *__init_or_module platform_device_register_resndata(
struct device *parent, struct device *parent,
const char *name, int id, const char *name, int id,
const struct resource *res, unsigned int num,
const void *data, size_t size) const void *data, size_t size)
{ {
int ret = -ENOMEM;
struct platform_device *pdev; struct platform_device *pdev;
int retval;
pdev = platform_device_alloc(name, id); pdev = platform_device_alloc(name, id);
if (!pdev) { if (!pdev)
retval = -ENOMEM; goto err;
goto error;
}
pdev->dev.parent = parent; pdev->dev.parent = parent;
if (size) { if (res) {
retval = platform_device_add_data(pdev, data, size); ret = platform_device_add_resources(pdev, res, num);
if (retval) if (ret)
goto error; goto err;
} }
retval = platform_device_add(pdev); if (data) {
if (retval) ret = platform_device_add_data(pdev, data, size);
goto error; if (ret)
goto err;
}
ret = platform_device_add(pdev);
if (ret) {
err:
platform_device_put(pdev);
return ERR_PTR(ret);
}
return pdev; return pdev;
error:
platform_device_put(pdev);
return ERR_PTR(retval);
} }
EXPORT_SYMBOL_GPL(platform_device_register_data); EXPORT_SYMBOL_GPL(platform_device_register_resndata);
static int platform_drv_probe(struct device *_dev) static int platform_drv_probe(struct device *_dev)
{ {

View file

@ -634,9 +634,6 @@ static void __exit dcdbas_exit(void)
* before platform_device_unregister * before platform_device_unregister
*/ */
unregister_reboot_notifier(&dcdbas_reboot_nb); unregister_reboot_notifier(&dcdbas_reboot_nb);
smi_data_buf_free();
platform_device_unregister(dcdbas_pdev);
platform_driver_unregister(&dcdbas_driver);
/* /*
* We have to free the buffer here instead of dcdbas_remove * We have to free the buffer here instead of dcdbas_remove
@ -645,6 +642,8 @@ static void __exit dcdbas_exit(void)
* released. * released.
*/ */
smi_data_buf_free(); smi_data_buf_free();
platform_device_unregister(dcdbas_pdev);
platform_driver_unregister(&dcdbas_driver);
} }
module_init(dcdbas_init); module_init(dcdbas_init);

View file

@ -229,10 +229,12 @@ static int __init dmi_id_init(void)
ret = device_register(dmi_dev); ret = device_register(dmi_dev);
if (ret) if (ret)
goto fail_class_unregister; goto fail_free_dmi_dev;
return 0; return 0;
fail_free_dmi_dev:
kfree(dmi_dev);
fail_class_unregister: fail_class_unregister:
class_unregister(&dmi_class); class_unregister(&dmi_class);

View file

@ -351,7 +351,7 @@ static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \
return count; \ return count; \
} \ } \
static struct device_attribute bd2802_reg##reg_addr##_attr = { \ static struct device_attribute bd2802_reg##reg_addr##_attr = { \
.attr = {.name = reg_name, .mode = 0644, .owner = THIS_MODULE}, \ .attr = {.name = reg_name, .mode = 0644}, \
.store = bd2802_store_reg##reg_addr, \ .store = bd2802_store_reg##reg_addr, \
}; };
@ -482,7 +482,6 @@ static struct device_attribute bd2802_adv_conf_attr = {
.attr = { .attr = {
.name = "advanced_configuration", .name = "advanced_configuration",
.mode = 0644, .mode = 0644,
.owner = THIS_MODULE
}, },
.show = bd2802_show_adv_conf, .show = bd2802_show_adv_conf,
.store = bd2802_store_adv_conf, .store = bd2802_store_adv_conf,
@ -519,7 +518,6 @@ static struct device_attribute bd2802_##attr_name##_attr = { \
.attr = { \ .attr = { \
.name = name_str, \ .name = name_str, \
.mode = 0644, \ .mode = 0644, \
.owner = THIS_MODULE \
}, \ }, \
.show = bd2802_show_##attr_name, \ .show = bd2802_show_##attr_name, \
.store = bd2802_store_##attr_name, \ .store = bd2802_store_##attr_name, \

View file

@ -1025,7 +1025,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
if (regulator->dev_attr.attr.name == NULL) if (regulator->dev_attr.attr.name == NULL)
goto attr_name_err; goto attr_name_err;
regulator->dev_attr.attr.owner = THIS_MODULE;
regulator->dev_attr.attr.mode = 0444; regulator->dev_attr.attr.mode = 0444;
regulator->dev_attr.show = device_requested_uA_show; regulator->dev_attr.show = device_requested_uA_show;
err = device_create_file(dev, &regulator->dev_attr); err = device_create_file(dev, &regulator->dev_attr);

View file

@ -192,7 +192,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
.attr = { .attr = {
.name = "mu_read", .name = "mu_read",
.mode = S_IRUSR , .mode = S_IRUSR ,
.owner = THIS_MODULE,
}, },
.size = 1032, .size = 1032,
.read = arcmsr_sysfs_iop_message_read, .read = arcmsr_sysfs_iop_message_read,
@ -202,7 +201,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
.attr = { .attr = {
.name = "mu_write", .name = "mu_write",
.mode = S_IWUSR, .mode = S_IWUSR,
.owner = THIS_MODULE,
}, },
.size = 1032, .size = 1032,
.write = arcmsr_sysfs_iop_message_write, .write = arcmsr_sysfs_iop_message_write,
@ -212,7 +210,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
.attr = { .attr = {
.name = "mu_clear", .name = "mu_clear",
.mode = S_IWUSR, .mode = S_IWUSR,
.owner = THIS_MODULE,
}, },
.size = 1, .size = 1,
.write = arcmsr_sysfs_iop_message_clear, .write = arcmsr_sysfs_iop_message_clear,

View file

@ -2778,7 +2778,6 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
.attr = { .attr = {
.name = "lpfc_drvr_stat_data", .name = "lpfc_drvr_stat_data",
.mode = S_IRUSR, .mode = S_IRUSR,
.owner = THIS_MODULE,
}, },
.size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET, .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
.read = sysfs_drvr_stat_data_read, .read = sysfs_drvr_stat_data_read,

View file

@ -79,7 +79,7 @@ static int __devinit hilscher_pci_probe(struct pci_dev *dev,
} }
info->version = "0.0.1"; info->version = "0.0.1";
info->irq = dev->irq; info->irq = dev->irq;
info->irq_flags = IRQF_DISABLED | IRQF_SHARED; info->irq_flags = IRQF_SHARED;
info->handler = hilscher_handler; info->handler = hilscher_handler;
if (uio_register_device(&dev->dev, info)) if (uio_register_device(&dev->dev, info))

View file

@ -155,7 +155,6 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
* Interrupt sharing is not supported. * Interrupt sharing is not supported.
*/ */
uioinfo->irq_flags |= IRQF_DISABLED;
uioinfo->handler = uio_pdrv_genirq_handler; uioinfo->handler = uio_pdrv_genirq_handler;
uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol;
uioinfo->open = uio_pdrv_genirq_open; uioinfo->open = uio_pdrv_genirq_open;

View file

@ -154,7 +154,7 @@ static int __devinit sercos3_pci_probe(struct pci_dev *dev,
info->name = "Sercos_III_PCI"; info->name = "Sercos_III_PCI";
info->version = "0.0.1"; info->version = "0.0.1";
info->irq = dev->irq; info->irq = dev->irq;
info->irq_flags = IRQF_DISABLED | IRQF_SHARED; info->irq_flags = IRQF_SHARED;
info->handler = sercos3_handler; info->handler = sercos3_handler;
info->irqcontrol = sercos3_irqcontrol; info->irqcontrol = sercos3_irqcontrol;

View file

@ -593,7 +593,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
* @mode: file permissions. * @mode: file permissions.
* *
*/ */
int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
mode_t mode)
{ {
struct sysfs_dirent *sd; struct sysfs_dirent *sd;
struct iattr newattrs; struct iattr newattrs;

View file

@ -84,9 +84,8 @@ struct device *bus_find_device_by_name(struct bus_type *bus,
struct device *start, struct device *start,
const char *name); const char *name);
int __must_check bus_for_each_drv(struct bus_type *bus, int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
struct device_driver *start, void *data, void *data, int (*fn)(struct device_driver *, void *));
int (*fn)(struct device_driver *, void *));
void bus_sort_breadthfirst(struct bus_type *bus, void bus_sort_breadthfirst(struct bus_type *bus,
int (*compare)(const struct device *a, int (*compare)(const struct device *a,
@ -110,10 +109,12 @@ extern int bus_unregister_notifier(struct bus_type *bus,
*/ */
#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ #define BUS_NOTIFY_BIND_DRIVER 0x00000003 /* driver about to be
#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be bound */
#define BUS_NOTIFY_BOUND_DRIVER 0x00000004 /* driver bound to device */
#define BUS_NOTIFY_UNBIND_DRIVER 0x00000005 /* driver about to be
unbound */ unbound */
#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000005 /* driver is unbound #define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound
from the device */ from the device */
extern struct kset *bus_get_kset(struct bus_type *bus); extern struct kset *bus_get_kset(struct bus_type *bus);
@ -551,7 +552,7 @@ extern int device_for_each_child(struct device *dev, void *data,
int (*fn)(struct device *dev, void *data)); int (*fn)(struct device *dev, void *data));
extern struct device *device_find_child(struct device *dev, void *data, extern struct device *device_find_child(struct device *dev, void *data,
int (*match)(struct device *dev, void *data)); int (*match)(struct device *dev, void *data));
extern int device_rename(struct device *dev, char *new_name); extern int device_rename(struct device *dev, const char *new_name);
extern int device_move(struct device *dev, struct device *new_parent, extern int device_move(struct device *dev, struct device *new_parent,
enum dpm_order dpm_order); enum dpm_order dpm_order);
extern const char *device_get_devnode(struct device *dev, extern const char *device_get_devnode(struct device *dev,

View file

@ -43,10 +43,64 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u
extern int platform_get_irq_byname(struct platform_device *, const char *); extern int platform_get_irq_byname(struct platform_device *, const char *);
extern int platform_add_devices(struct platform_device **, int); extern int platform_add_devices(struct platform_device **, int);
extern struct platform_device *platform_device_register_simple(const char *, int id, extern struct platform_device *platform_device_register_resndata(
const struct resource *, unsigned int); struct device *parent, const char *name, int id,
extern struct platform_device *platform_device_register_data(struct device *, const struct resource *res, unsigned int num,
const char *, int, const void *, size_t); const void *data, size_t size);
/**
* platform_device_register_simple - add a platform-level device and its resources
* @name: base name of the device we're adding
* @id: instance id
* @res: set of resources that needs to be allocated for the device
* @num: number of resources
*
* This function creates a simple platform device that requires minimal
* resource and memory management. Canned release function freeing memory
* allocated for the device allows drivers using such devices to be
* unloaded without waiting for the last reference to the device to be
* dropped.
*
* This interface is primarily intended for use with legacy drivers which
* probe hardware directly. Because such drivers create sysfs device nodes
* themselves, rather than letting system infrastructure handle such device
* enumeration tasks, they don't fully conform to the Linux driver model.
* In particular, when such drivers are built as modules, they can't be
* "hotplugged".
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
static inline struct platform_device *platform_device_register_simple(
const char *name, int id,
const struct resource *res, unsigned int num)
{
return platform_device_register_resndata(NULL, name, id,
res, num, NULL, 0);
}
/**
* platform_device_register_data - add a platform-level device with platform-specific data
* @parent: parent device for the device we're adding
* @name: base name of the device we're adding
* @id: instance id
* @data: platform specific data for this platform device
* @size: size of platform specific data
*
* This function creates a simple platform device that requires minimal
* resource and memory management. Canned release function freeing memory
* allocated for the device allows drivers using such devices to be
* unloaded without waiting for the last reference to the device to be
* dropped.
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
static inline struct platform_device *platform_device_register_data(
struct device *parent, const char *name, int id,
const void *data, size_t size)
{
return platform_device_register_resndata(parent, name, id,
NULL, 0, data, size);
}
extern struct platform_device *platform_device_alloc(const char *name, int id); extern struct platform_device *platform_device_alloc(const char *name, int id);
extern int platform_device_add_resources(struct platform_device *pdev, extern int platform_device_add_resources(struct platform_device *pdev,

View file

@ -22,14 +22,8 @@ struct kobject;
struct module; struct module;
enum kobj_ns_type; enum kobj_ns_type;
/* FIXME
* The *owner field is no longer used.
* x86 tree has been cleaned up. The owner
* attribute is still left for other arches.
*/
struct attribute { struct attribute {
const char *name; const char *name;
struct module *owner;
mode_t mode; mode_t mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC #ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lock_class_key *key; struct lock_class_key *key;
@ -136,8 +130,8 @@ int __must_check sysfs_create_file(struct kobject *kobj,
const struct attribute *attr); const struct attribute *attr);
int __must_check sysfs_create_files(struct kobject *kobj, int __must_check sysfs_create_files(struct kobject *kobj,
const struct attribute **attr); const struct attribute **attr);
int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, int __must_check sysfs_chmod_file(struct kobject *kobj,
mode_t mode); const struct attribute *attr, mode_t mode);
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
@ -225,7 +219,7 @@ static inline int sysfs_create_files(struct kobject *kobj,
} }
static inline int sysfs_chmod_file(struct kobject *kobj, static inline int sysfs_chmod_file(struct kobject *kobj,
struct attribute *attr, mode_t mode) const struct attribute *attr, mode_t mode)
{ {
return 0; return 0;
} }

View file

@ -1623,6 +1623,8 @@ static struct file_system_type cgroup_fs_type = {
.kill_sb = cgroup_kill_sb, .kill_sb = cgroup_kill_sb,
}; };
static struct kobject *cgroup_kobj;
static inline struct cgroup *__d_cgrp(struct dentry *dentry) static inline struct cgroup *__d_cgrp(struct dentry *dentry)
{ {
return dentry->d_fsdata; return dentry->d_fsdata;
@ -3894,9 +3896,18 @@ int __init cgroup_init(void)
hhead = css_set_hash(init_css_set.subsys); hhead = css_set_hash(init_css_set.subsys);
hlist_add_head(&init_css_set.hlist, hhead); hlist_add_head(&init_css_set.hlist, hhead);
BUG_ON(!init_root_id(&rootnode)); BUG_ON(!init_root_id(&rootnode));
err = register_filesystem(&cgroup_fs_type);
if (err < 0) cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
if (!cgroup_kobj) {
err = -ENOMEM;
goto out; goto out;
}
err = register_filesystem(&cgroup_fs_type);
if (err < 0) {
kobject_put(cgroup_kobj);
goto out;
}
proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations); proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);

View file

@ -566,7 +566,7 @@ static struct ctl_table kern_table[] = {
.extra2 = &one, .extra2 = &one,
}, },
#endif #endif
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) #ifdef CONFIG_HOTPLUG
{ {
.procname = "hotplug", .procname = "hotplug",
.data = &uevent_helper, .data = &uevent_helper,

View file

@ -76,7 +76,6 @@ config UNUSED_SYMBOLS
config DEBUG_FS config DEBUG_FS
bool "Debug Filesystem" bool "Debug Filesystem"
depends on SYSFS
help help
debugfs is a virtual file system that kernel developers use to put debugfs is a virtual file system that kernel developers use to put
debugging files into. Enable this option to be able to read and debugging files into. Enable this option to be able to read and