mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
This commit is contained in:
commit
f65e77693a
10 changed files with 178 additions and 70 deletions
|
@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
|
||||||
|
|
||||||
It also defines this helper for defining device attributes:
|
It also defines this helper for defining device attributes:
|
||||||
|
|
||||||
#define DEVICE_ATTR(_name,_mode,_show,_store) \
|
#define DEVICE_ATTR(_name, _mode, _show, _store) \
|
||||||
struct device_attribute dev_attr_##_name = { \
|
struct device_attribute dev_attr_##_name = { \
|
||||||
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
||||||
.show = _show, \
|
.show = _show, \
|
||||||
|
@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
|
||||||
|
|
||||||
For example, declaring
|
For example, declaring
|
||||||
|
|
||||||
static DEVICE_ATTR(foo,0644,show_foo,store_foo);
|
static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
|
||||||
|
|
||||||
is equivalent to doing:
|
is equivalent to doing:
|
||||||
|
|
||||||
static struct device_attribute dev_attr_foo = {
|
static struct device_attribute dev_attr_foo = {
|
||||||
.attr = {
|
.attr = {
|
||||||
.name = "foo",
|
.name = "foo",
|
||||||
.mode = 0644,
|
.mode = S_IWUSR | S_IRUGO,
|
||||||
},
|
},
|
||||||
.show = show_foo,
|
.show = show_foo,
|
||||||
.store = store_foo,
|
.store = store_foo,
|
||||||
|
@ -121,8 +121,8 @@ set of sysfs operations for forwarding read and write calls to the
|
||||||
show and store methods of the attribute owners.
|
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 *);
|
||||||
};
|
};
|
||||||
|
|
||||||
[ Subsystems should have already defined a struct kobj_type as a
|
[ Subsystems should have already defined a struct kobj_type as a
|
||||||
|
@ -137,7 +137,7 @@ calls the associated methods.
|
||||||
|
|
||||||
To illustrate:
|
To illustrate:
|
||||||
|
|
||||||
#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)
|
#define to_dev(d) container_of(d, struct device, kobj)
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
|
@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
|
||||||
if (dev_attr->show)
|
if (dev_attr->show)
|
||||||
ret = dev_attr->show(dev,buf);
|
ret = dev_attr->show(dev, buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,16 +216,16 @@ 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 sprintf(buf,"%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, const char * buf)
|
||||||
{
|
{
|
||||||
sscanf(buf,"%20s",dev->name);
|
sscanf(buf, "%20s", dev->name);
|
||||||
return strlen(buf);
|
return strnlen(buf, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
|
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
|
||||||
|
|
||||||
|
|
||||||
(Note that the real implementation doesn't allow userspace to set the
|
(Note that the real implementation doesn't allow userspace to set the
|
||||||
|
@ -290,7 +290,7 @@ struct device_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DEVICE_ATTR(_name,_str,_mode,_show,_store);
|
DEVICE_ATTR(_name, _str, _mode, _show, _store);
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ struct bus_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
BUS_ATTR(_name,_mode,_show,_store)
|
BUS_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ struct driver_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DRIVER_ATTR(_name,_mode,_show,_store)
|
DRIVER_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,9 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
||||||
device_release_driver(dev);
|
device_release_driver(dev);
|
||||||
err = count;
|
err = count;
|
||||||
}
|
}
|
||||||
return err;
|
if (err)
|
||||||
|
return err;
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
||||||
|
|
||||||
|
@ -358,7 +360,7 @@ int bus_add_device(struct device * dev)
|
||||||
if (bus) {
|
if (bus) {
|
||||||
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
|
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
|
||||||
device_attach(dev);
|
device_attach(dev);
|
||||||
klist_add_tail(&bus->klist_devices, &dev->knode_bus);
|
klist_add_tail(&dev->knode_bus, &bus->klist_devices);
|
||||||
error = device_add_attrs(bus, dev);
|
error = device_add_attrs(bus, dev);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
|
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
|
||||||
|
@ -446,7 +448,7 @@ int bus_add_driver(struct device_driver * drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_attach(drv);
|
driver_attach(drv);
|
||||||
klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
|
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
|
||||||
module_add_driver(drv->owner, drv);
|
module_add_driver(drv->owner, drv);
|
||||||
|
|
||||||
driver_add_attrs(bus, drv);
|
driver_add_attrs(bus, drv);
|
||||||
|
|
|
@ -299,10 +299,8 @@ static void class_dev_release(struct kobject * kobj)
|
||||||
|
|
||||||
pr_debug("device class '%s': release.\n", cd->class_id);
|
pr_debug("device class '%s': release.\n", cd->class_id);
|
||||||
|
|
||||||
if (cd->devt_attr) {
|
kfree(cd->devt_attr);
|
||||||
kfree(cd->devt_attr);
|
cd->devt_attr = NULL;
|
||||||
cd->devt_attr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cls->release)
|
if (cls->release)
|
||||||
cls->release(cd);
|
cls->release(cd);
|
||||||
|
@ -452,10 +450,29 @@ void class_device_initialize(struct class_device *class_dev)
|
||||||
INIT_LIST_HEAD(&class_dev->node);
|
INIT_LIST_HEAD(&class_dev->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *make_class_name(struct class_device *class_dev)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = strlen(class_dev->class->name) +
|
||||||
|
strlen(kobject_name(&class_dev->kobj)) + 2;
|
||||||
|
|
||||||
|
name = kmalloc(size, GFP_KERNEL);
|
||||||
|
if (!name)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
strcpy(name, class_dev->class->name);
|
||||||
|
strcat(name, ":");
|
||||||
|
strcat(name, kobject_name(&class_dev->kobj));
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
int class_device_add(struct class_device *class_dev)
|
int class_device_add(struct class_device *class_dev)
|
||||||
{
|
{
|
||||||
struct class * parent = NULL;
|
struct class * parent = NULL;
|
||||||
struct class_interface * class_intf;
|
struct class_interface * class_intf;
|
||||||
|
char *class_name = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
class_dev = class_device_get(class_dev);
|
class_dev = class_device_get(class_dev);
|
||||||
|
@ -500,9 +517,13 @@ int class_device_add(struct class_device *class_dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
class_device_add_attrs(class_dev);
|
class_device_add_attrs(class_dev);
|
||||||
if (class_dev->dev)
|
if (class_dev->dev) {
|
||||||
|
class_name = make_class_name(class_dev);
|
||||||
sysfs_create_link(&class_dev->kobj,
|
sysfs_create_link(&class_dev->kobj,
|
||||||
&class_dev->dev->kobj, "device");
|
&class_dev->dev->kobj, "device");
|
||||||
|
sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
|
||||||
|
class_name);
|
||||||
|
}
|
||||||
|
|
||||||
/* notify any interfaces this device is now here */
|
/* notify any interfaces this device is now here */
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
@ -519,6 +540,7 @@ int class_device_add(struct class_device *class_dev)
|
||||||
if (error && parent)
|
if (error && parent)
|
||||||
class_put(parent);
|
class_put(parent);
|
||||||
class_device_put(class_dev);
|
class_device_put(class_dev);
|
||||||
|
kfree(class_name);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,6 +606,7 @@ void class_device_del(struct class_device *class_dev)
|
||||||
{
|
{
|
||||||
struct class * parent = class_dev->class;
|
struct class * parent = class_dev->class;
|
||||||
struct class_interface * class_intf;
|
struct class_interface * class_intf;
|
||||||
|
char *class_name = NULL;
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
down(&parent->sem);
|
down(&parent->sem);
|
||||||
|
@ -594,8 +617,11 @@ void class_device_del(struct class_device *class_dev)
|
||||||
up(&parent->sem);
|
up(&parent->sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (class_dev->dev)
|
if (class_dev->dev) {
|
||||||
|
class_name = make_class_name(class_dev);
|
||||||
sysfs_remove_link(&class_dev->kobj, "device");
|
sysfs_remove_link(&class_dev->kobj, "device");
|
||||||
|
sysfs_remove_link(&class_dev->dev->kobj, class_name);
|
||||||
|
}
|
||||||
if (class_dev->devt_attr)
|
if (class_dev->devt_attr)
|
||||||
class_device_remove_file(class_dev, class_dev->devt_attr);
|
class_device_remove_file(class_dev, class_dev->devt_attr);
|
||||||
class_device_remove_attrs(class_dev);
|
class_device_remove_attrs(class_dev);
|
||||||
|
@ -605,6 +631,7 @@ void class_device_del(struct class_device *class_dev)
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
class_put(parent);
|
class_put(parent);
|
||||||
|
kfree(class_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_device_unregister(struct class_device *class_dev)
|
void class_device_unregister(struct class_device *class_dev)
|
||||||
|
|
|
@ -249,7 +249,7 @@ int device_add(struct device *dev)
|
||||||
if ((error = bus_add_device(dev)))
|
if ((error = bus_add_device(dev)))
|
||||||
goto BusError;
|
goto BusError;
|
||||||
if (parent)
|
if (parent)
|
||||||
klist_add_tail(&parent->klist_children, &dev->knode_parent);
|
klist_add_tail(&dev->knode_parent, &parent->klist_children);
|
||||||
|
|
||||||
/* notify platform of device entry */
|
/* notify platform of device entry */
|
||||||
if (platform_notify)
|
if (platform_notify)
|
||||||
|
|
|
@ -42,7 +42,7 @@ void device_bind_driver(struct device * dev)
|
||||||
{
|
{
|
||||||
pr_debug("bound device '%s' to driver '%s'\n",
|
pr_debug("bound device '%s' to driver '%s'\n",
|
||||||
dev->bus_id, dev->driver->name);
|
dev->bus_id, dev->driver->name);
|
||||||
klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
|
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
|
||||||
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
|
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
|
||||||
kobject_name(&dev->kobj));
|
kobject_name(&dev->kobj));
|
||||||
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
|
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
|
||||||
|
|
|
@ -288,6 +288,27 @@ void sysdev_shutdown(void)
|
||||||
up(&sysdev_drivers_lock);
|
up(&sysdev_drivers_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __sysdev_resume(struct sys_device *dev)
|
||||||
|
{
|
||||||
|
struct sysdev_class *cls = dev->cls;
|
||||||
|
struct sysdev_driver *drv;
|
||||||
|
|
||||||
|
/* First, call the class-specific one */
|
||||||
|
if (cls->resume)
|
||||||
|
cls->resume(dev);
|
||||||
|
|
||||||
|
/* Call auxillary drivers next. */
|
||||||
|
list_for_each_entry(drv, &cls->drivers, entry) {
|
||||||
|
if (drv->resume)
|
||||||
|
drv->resume(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call global drivers. */
|
||||||
|
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
||||||
|
if (drv->resume)
|
||||||
|
drv->resume(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysdev_suspend - Suspend all system devices.
|
* sysdev_suspend - Suspend all system devices.
|
||||||
|
@ -305,38 +326,93 @@ void sysdev_shutdown(void)
|
||||||
int sysdev_suspend(pm_message_t state)
|
int sysdev_suspend(pm_message_t state)
|
||||||
{
|
{
|
||||||
struct sysdev_class * cls;
|
struct sysdev_class * cls;
|
||||||
|
struct sys_device *sysdev, *err_dev;
|
||||||
|
struct sysdev_driver *drv, *err_drv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pr_debug("Suspending System Devices\n");
|
pr_debug("Suspending System Devices\n");
|
||||||
|
|
||||||
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
|
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
|
||||||
kset.kobj.entry) {
|
kset.kobj.entry) {
|
||||||
struct sys_device * sysdev;
|
|
||||||
|
|
||||||
pr_debug("Suspending type '%s':\n",
|
pr_debug("Suspending type '%s':\n",
|
||||||
kobject_name(&cls->kset.kobj));
|
kobject_name(&cls->kset.kobj));
|
||||||
|
|
||||||
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
||||||
struct sysdev_driver * drv;
|
|
||||||
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
||||||
|
|
||||||
/* Call global drivers first. */
|
/* Call global drivers first. */
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
||||||
if (drv->suspend)
|
if (drv->suspend) {
|
||||||
drv->suspend(sysdev, state);
|
ret = drv->suspend(sysdev, state);
|
||||||
|
if (ret)
|
||||||
|
goto gbl_driver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call auxillary drivers next. */
|
/* Call auxillary drivers next. */
|
||||||
list_for_each_entry(drv, &cls->drivers, entry) {
|
list_for_each_entry(drv, &cls->drivers, entry) {
|
||||||
if (drv->suspend)
|
if (drv->suspend) {
|
||||||
drv->suspend(sysdev, state);
|
ret = drv->suspend(sysdev, state);
|
||||||
|
if (ret)
|
||||||
|
goto aux_driver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now call the generic one */
|
/* Now call the generic one */
|
||||||
if (cls->suspend)
|
if (cls->suspend) {
|
||||||
cls->suspend(sysdev, state);
|
ret = cls->suspend(sysdev, state);
|
||||||
|
if (ret)
|
||||||
|
goto cls_driver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
/* resume current sysdev */
|
||||||
|
cls_driver:
|
||||||
|
drv = NULL;
|
||||||
|
printk(KERN_ERR "Class suspend failed for %s\n",
|
||||||
|
kobject_name(&sysdev->kobj));
|
||||||
|
|
||||||
|
aux_driver:
|
||||||
|
if (drv)
|
||||||
|
printk(KERN_ERR "Class driver suspend failed for %s\n",
|
||||||
|
kobject_name(&sysdev->kobj));
|
||||||
|
list_for_each_entry(err_drv, &cls->drivers, entry) {
|
||||||
|
if (err_drv == drv)
|
||||||
|
break;
|
||||||
|
if (err_drv->resume)
|
||||||
|
err_drv->resume(sysdev);
|
||||||
|
}
|
||||||
|
drv = NULL;
|
||||||
|
|
||||||
|
gbl_driver:
|
||||||
|
if (drv)
|
||||||
|
printk(KERN_ERR "sysdev driver suspend failed for %s\n",
|
||||||
|
kobject_name(&sysdev->kobj));
|
||||||
|
list_for_each_entry(err_drv, &sysdev_drivers, entry) {
|
||||||
|
if (err_drv == drv)
|
||||||
|
break;
|
||||||
|
if (err_drv->resume)
|
||||||
|
err_drv->resume(sysdev);
|
||||||
|
}
|
||||||
|
/* resume other sysdevs in current class */
|
||||||
|
list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
|
||||||
|
if (err_dev == sysdev)
|
||||||
|
break;
|
||||||
|
pr_debug(" %s\n", kobject_name(&err_dev->kobj));
|
||||||
|
__sysdev_resume(err_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resume other classes */
|
||||||
|
list_for_each_entry_continue(cls, &system_subsys.kset.list,
|
||||||
|
kset.kobj.entry) {
|
||||||
|
list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
|
||||||
|
pr_debug(" %s\n", kobject_name(&err_dev->kobj));
|
||||||
|
__sysdev_resume(err_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,25 +438,9 @@ int sysdev_resume(void)
|
||||||
kobject_name(&cls->kset.kobj));
|
kobject_name(&cls->kset.kobj));
|
||||||
|
|
||||||
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
||||||
struct sysdev_driver * drv;
|
|
||||||
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
||||||
|
|
||||||
/* First, call the class-specific one */
|
__sysdev_resume(sysdev);
|
||||||
if (cls->resume)
|
|
||||||
cls->resume(sysdev);
|
|
||||||
|
|
||||||
/* Call auxillary drivers next. */
|
|
||||||
list_for_each_entry(drv, &cls->drivers, entry) {
|
|
||||||
if (drv->resume)
|
|
||||||
drv->resume(sysdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call global drivers. */
|
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->resume)
|
|
||||||
drv->resume(sysdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -493,6 +493,8 @@ static struct floppy_struct user_params[N_DRIVE];
|
||||||
|
|
||||||
static sector_t floppy_sizes[256];
|
static sector_t floppy_sizes[256];
|
||||||
|
|
||||||
|
static char floppy_device_name[] = "floppy";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The driver is trying to determine the correct media format
|
* The driver is trying to determine the correct media format
|
||||||
* while probing is set. rw_interrupt() clears it after a
|
* while probing is set. rw_interrupt() clears it after a
|
||||||
|
@ -4191,18 +4193,24 @@ static int __init floppy_setup(char *str)
|
||||||
|
|
||||||
static int have_no_fdc = -ENODEV;
|
static int have_no_fdc = -ENODEV;
|
||||||
|
|
||||||
|
static ssize_t floppy_cmos_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct platform_device *p;
|
||||||
|
int drive;
|
||||||
|
|
||||||
|
p = container_of(dev, struct platform_device,dev);
|
||||||
|
drive = p->id;
|
||||||
|
return sprintf(buf, "%X\n", UDP->cmos);
|
||||||
|
}
|
||||||
|
DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
|
||||||
|
|
||||||
static void floppy_device_release(struct device *dev)
|
static void floppy_device_release(struct device *dev)
|
||||||
{
|
{
|
||||||
complete(&device_release);
|
complete(&device_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_device floppy_device = {
|
static struct platform_device floppy_device[N_DRIVE];
|
||||||
.name = "floppy",
|
|
||||||
.id = 0,
|
|
||||||
.dev = {
|
|
||||||
.release = floppy_device_release,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||||
{
|
{
|
||||||
|
@ -4370,20 +4378,26 @@ static int __init floppy_init(void)
|
||||||
goto out_flush_work;
|
goto out_flush_work;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_register(&floppy_device);
|
|
||||||
if (err)
|
|
||||||
goto out_flush_work;
|
|
||||||
|
|
||||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||||
if (!(allowed_drive_mask & (1 << drive)))
|
if (!(allowed_drive_mask & (1 << drive)))
|
||||||
continue;
|
continue;
|
||||||
if (fdc_state[FDC(drive)].version == FDC_NONE)
|
if (fdc_state[FDC(drive)].version == FDC_NONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
floppy_device[drive].name = floppy_device_name;
|
||||||
|
floppy_device[drive].id = drive;
|
||||||
|
floppy_device[drive].dev.release = floppy_device_release;
|
||||||
|
|
||||||
|
err = platform_device_register(&floppy_device[drive]);
|
||||||
|
if (err)
|
||||||
|
goto out_flush_work;
|
||||||
|
|
||||||
|
device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
|
||||||
/* to be cleaned up... */
|
/* to be cleaned up... */
|
||||||
disks[drive]->private_data = (void *)(long)drive;
|
disks[drive]->private_data = (void *)(long)drive;
|
||||||
disks[drive]->queue = floppy_queue;
|
disks[drive]->queue = floppy_queue;
|
||||||
disks[drive]->flags |= GENHD_FL_REMOVABLE;
|
disks[drive]->flags |= GENHD_FL_REMOVABLE;
|
||||||
disks[drive]->driverfs_dev = &floppy_device.dev;
|
disks[drive]->driverfs_dev = &floppy_device[drive].dev;
|
||||||
add_disk(disks[drive]);
|
add_disk(disks[drive]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4603,10 +4617,11 @@ void cleanup_module(void)
|
||||||
fdc_state[FDC(drive)].version != FDC_NONE) {
|
fdc_state[FDC(drive)].version != FDC_NONE) {
|
||||||
del_gendisk(disks[drive]);
|
del_gendisk(disks[drive]);
|
||||||
unregister_devfs_entries(drive);
|
unregister_devfs_entries(drive);
|
||||||
|
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
|
||||||
|
platform_device_unregister(&floppy_device[drive]);
|
||||||
}
|
}
|
||||||
put_disk(disks[drive]);
|
put_disk(disks[drive]);
|
||||||
}
|
}
|
||||||
platform_device_unregister(&floppy_device);
|
|
||||||
devfs_remove("floppy");
|
devfs_remove("floppy");
|
||||||
|
|
||||||
del_timer_sync(&fd_timeout);
|
del_timer_sync(&fd_timeout);
|
||||||
|
|
|
@ -782,7 +782,7 @@ static int usb_register_bus(struct usb_bus *bus)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
|
bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
|
||||||
if (IS_ERR(bus->class_dev)) {
|
if (IS_ERR(bus->class_dev)) {
|
||||||
clear_bit(busnum, busmap.busmap);
|
clear_bit(busnum, busmap.busmap);
|
||||||
up(&usb_bus_list_lock);
|
up(&usb_bus_list_lock);
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
* This file is rleased under the GPL v2.
|
* This file is rleased under the GPL v2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _LINUX_KLIST_H
|
||||||
|
#define _LINUX_KLIST_H
|
||||||
|
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
|
@ -31,8 +34,8 @@ struct klist_node {
|
||||||
struct completion n_removed;
|
struct completion n_removed;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void klist_add_tail(struct klist * k, struct klist_node * n);
|
extern void klist_add_tail(struct klist_node * n, struct klist * k);
|
||||||
extern void klist_add_head(struct klist * k, struct klist_node * n);
|
extern void klist_add_head(struct klist_node * n, struct klist * k);
|
||||||
|
|
||||||
extern void klist_del(struct klist_node * n);
|
extern void klist_del(struct klist_node * n);
|
||||||
extern void klist_remove(struct klist_node * n);
|
extern void klist_remove(struct klist_node * n);
|
||||||
|
@ -53,3 +56,4 @@ extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
|
||||||
extern void klist_iter_exit(struct klist_iter * i);
|
extern void klist_iter_exit(struct klist_iter * i);
|
||||||
extern struct klist_node * klist_next(struct klist_iter * i);
|
extern struct klist_node * klist_next(struct klist_iter * i);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -79,11 +79,11 @@ static void klist_node_init(struct klist * k, struct klist_node * n)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* klist_add_head - Initialize a klist_node and add it to front.
|
* klist_add_head - Initialize a klist_node and add it to front.
|
||||||
* @k: klist it's going on.
|
|
||||||
* @n: node we're adding.
|
* @n: node we're adding.
|
||||||
|
* @k: klist it's going on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void klist_add_head(struct klist * k, struct klist_node * n)
|
void klist_add_head(struct klist_node * n, struct klist * k)
|
||||||
{
|
{
|
||||||
klist_node_init(k, n);
|
klist_node_init(k, n);
|
||||||
add_head(k, n);
|
add_head(k, n);
|
||||||
|
@ -94,11 +94,11 @@ EXPORT_SYMBOL_GPL(klist_add_head);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* klist_add_tail - Initialize a klist_node and add it to back.
|
* klist_add_tail - Initialize a klist_node and add it to back.
|
||||||
* @k: klist it's going on.
|
|
||||||
* @n: node we're adding.
|
* @n: node we're adding.
|
||||||
|
* @k: klist it's going on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void klist_add_tail(struct klist * k, struct klist_node * n)
|
void klist_add_tail(struct klist_node * n, struct klist * k)
|
||||||
{
|
{
|
||||||
klist_node_init(k, n);
|
klist_node_init(k, n);
|
||||||
add_tail(k, n);
|
add_tail(k, n);
|
||||||
|
|
Loading…
Add table
Reference in a new issue