Commit 6c7a3c95 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 80d316b7 3fe52eb6
This diff is collapsed.
...@@ -598,7 +598,7 @@ static struct kobj_type ktype_edd = { ...@@ -598,7 +598,7 @@ static struct kobj_type ktype_edd = {
.default_attrs = def_attrs, .default_attrs = def_attrs,
}; };
static decl_subsys(edd,&ktype_edd); static decl_subsys(edd,&ktype_edd,NULL);
/** /**
......
...@@ -676,7 +676,7 @@ acpi_bus_init (void) ...@@ -676,7 +676,7 @@ acpi_bus_init (void)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
decl_subsys(acpi,NULL); decl_subsys(acpi,NULL,NULL);
static int __init acpi_init (void) static int __init acpi_init (void)
{ {
......
...@@ -18,13 +18,8 @@ extern void interface_remove_dev(struct device *); ...@@ -18,13 +18,8 @@ extern void interface_remove_dev(struct device *);
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
extern int dev_hotplug(struct device *dev, const char *action);
extern int class_hotplug(struct device *dev, const char *action); extern int class_hotplug(struct device *dev, const char *action);
#else #else
static inline int dev_hotplug(struct device *dev, const char *action)
{
return 0;
}
static inline int class_hotplug(struct device *dev, const char *action) static inline int class_hotplug(struct device *dev, const char *action)
{ {
return 0; return 0;
......
...@@ -132,7 +132,7 @@ static struct kobj_type ktype_bus = { ...@@ -132,7 +132,7 @@ static struct kobj_type ktype_bus = {
}; };
decl_subsys(bus,&ktype_bus); decl_subsys(bus,&ktype_bus,NULL);
/** /**
* bus_for_each_dev - device iterator. * bus_for_each_dev - device iterator.
......
...@@ -49,7 +49,9 @@ static struct kobj_type ktype_devclass = { ...@@ -49,7 +49,9 @@ static struct kobj_type ktype_devclass = {
.sysfs_ops = &class_sysfs_ops, .sysfs_ops = &class_sysfs_ops,
}; };
static decl_subsys(class,&ktype_devclass); /* Classes can't use the kobject hotplug logic, as
* they do not add new kobjects to the system */
static decl_subsys(class,&ktype_devclass,NULL);
static int devclass_dev_link(struct device_class * cls, struct device * dev) static int devclass_dev_link(struct device_class * cls, struct device * dev)
......
...@@ -23,13 +23,12 @@ int (*platform_notify_remove)(struct device * dev) = NULL; ...@@ -23,13 +23,12 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
DECLARE_MUTEX(device_sem); DECLARE_MUTEX(device_sem);
#define to_dev(obj) container_of(obj,struct device,kobj)
/* /*
* sysfs bindings for devices. * sysfs bindings for devices.
*/ */
#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)
extern struct attribute * dev_default_attrs[]; extern struct attribute * dev_default_attrs[];
...@@ -86,11 +85,55 @@ static struct kobj_type ktype_device = { ...@@ -86,11 +85,55 @@ static struct kobj_type ktype_device = {
.default_attrs = dev_default_attrs, .default_attrs = dev_default_attrs,
}; };
static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
if (ktype == &ktype_device) {
struct device *dev = to_dev(kobj);
if (dev->bus)
return 1;
}
return 0;
}
static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
return dev->bus->name;
}
static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct device *dev = to_dev(kobj);
int retval = 0;
if (dev->bus->hotplug) {
/* have the bus specific function add its stuff */
retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
if (retval) {
pr_debug ("%s - hotplug() returned %d\n",
__FUNCTION__, retval);
}
}
return retval;
}
static struct kset_hotplug_ops device_hotplug_ops = {
.filter = dev_hotplug_filter,
.name = dev_hotplug_name,
.hotplug = dev_hotplug,
};
/** /**
* device_subsys - structure to be registered with kobject core. * device_subsys - structure to be registered with kobject core.
*/ */
decl_subsys(devices,&ktype_device); decl_subsys(devices, &ktype_device, &device_hotplug_ops);
/** /**
...@@ -192,9 +235,6 @@ int device_add(struct device *dev) ...@@ -192,9 +235,6 @@ int device_add(struct device *dev)
if (platform_notify) if (platform_notify)
platform_notify(dev); platform_notify(dev);
/* notify userspace of device entry */
dev_hotplug(dev, "add");
devclass_add_device(dev); devclass_add_device(dev);
register_done: register_done:
if (error && parent) if (error && parent)
...@@ -278,9 +318,6 @@ void device_del(struct device * dev) ...@@ -278,9 +318,6 @@ void device_del(struct device * dev)
if (platform_notify_remove) if (platform_notify_remove)
platform_notify_remove(dev); platform_notify_remove(dev);
/* notify userspace that this device is about to disappear */
dev_hotplug (dev, "remove");
bus_remove_device(dev); bus_remove_device(dev);
kobject_del(&dev->kobj); kobject_del(&dev->kobj);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
static decl_subsys(firmware,NULL); static decl_subsys(firmware,NULL,NULL);
int firmware_register(struct subsystem * s) int firmware_register(struct subsystem * s)
{ {
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* drivers/base/hotplug.c - hotplug call code * drivers/base/hotplug.c - hotplug call code
* *
* Copyright (c) 2000-2001 David Brownell * Copyright (c) 2000-2001 David Brownell
* Copyright (c) 2002 Greg Kroah-Hartman * Copyright (c) 2002-2003 Greg Kroah-Hartman
* Copyright (c) 2002 IBM Corp. * Copyright (c) 2002-2003 IBM Corp.
* *
* Based off of drivers/usb/core/usb.c:call_agent(), which was * Based off of drivers/usb/core/usb.c:call_agent(), which was
* written by David Brownell. * written by David Brownell.
...@@ -53,17 +53,6 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action, ...@@ -53,17 +53,6 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action,
if (!hotplug_path [0]) if (!hotplug_path [0])
return -ENODEV; return -ENODEV;
if (in_interrupt ()) {
pr_debug ("%s - in_interrupt, not allowed!", __FUNCTION__);
return -EIO;
}
if (!current->fs->root) {
/* don't try to do anything unless we have a root partition */
pr_debug ("%s - %s -- no FS yet\n", __FUNCTION__, action);
return -EIO;
}
envp = (char **) kmalloc (NUM_ENVP * sizeof (char *), GFP_KERNEL); envp = (char **) kmalloc (NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp) if (!envp)
return -ENOMEM; return -ENOMEM;
...@@ -128,23 +117,6 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action, ...@@ -128,23 +117,6 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action,
return retval; return retval;
} }
/*
* dev_hotplug - called when any device is added or removed from a bus
*/
int dev_hotplug (struct device *dev, const char *action)
{
pr_debug ("%s\n", __FUNCTION__);
if (!dev)
return -ENODEV;
if (!dev->bus)
return -ENODEV;
return do_hotplug (dev, dev->bus->name, action, dev->bus->hotplug);
}
/* /*
* class_hotplug - called when a class is added or removed from a device * class_hotplug - called when a class is added or removed from a device
*/ */
......
...@@ -525,9 +525,21 @@ static struct kobj_type ktype_block = { ...@@ -525,9 +525,21 @@ static struct kobj_type ktype_block = {
.default_attrs = default_attrs, .default_attrs = default_attrs,
}; };
extern struct kobj_type ktype_part;
static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
return ((ktype == &ktype_block) || (ktype == &ktype_part));
}
static struct kset_hotplug_ops block_hotplug_ops = {
.filter = block_hotplug_filter,
};
/* declare block_subsys. */ /* declare block_subsys. */
static decl_subsys(block,&ktype_block); static decl_subsys(block, &ktype_block, &block_hotplug_ops);
struct gendisk *alloc_disk(int minors) struct gendisk *alloc_disk(int minors)
......
...@@ -100,7 +100,7 @@ static struct kobj_type hotplug_slot_ktype = { ...@@ -100,7 +100,7 @@ static struct kobj_type hotplug_slot_ktype = {
.sysfs_ops = &hotplug_slot_sysfs_ops .sysfs_ops = &hotplug_slot_sysfs_ops
}; };
static decl_subsys(hotplug_slots, &hotplug_slot_ktype); static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL);
/* these strings match up with the values in pci_bus_speed */ /* these strings match up with the values in pci_bus_speed */
......
...@@ -1806,22 +1806,6 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc ...@@ -1806,22 +1806,6 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc
printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
d->descriptor.idVendor, d->descriptor.idProduct, ifnum); d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
for ( i=0 ; i < d->descriptor.bNumConfigurations ; i++ ) {
if ( d->config+i == c ) goto configfound;
}
printk(KERN_INFO "usb-midi: Config not found.\n");
return -EINVAL;
configfound:
/* this may not be necessary. */
if ( usb_set_configuration( d, c->desc.bConfigurationValue ) < 0 ) {
printk(KERN_INFO "usb-midi: Could not set config.\n");
return -EINVAL;
}
ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE );
if ( ret < 0 ) { if ( ret < 0 ) {
printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret);
...@@ -1916,21 +1900,6 @@ static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct ...@@ -1916,21 +1900,6 @@ static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct
printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n", printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n",
d->descriptor.idVendor, d->descriptor.idProduct, ifnum); d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
for ( i=0 ; i < d->descriptor.bNumConfigurations ; i++ ) {
if ( d->config+i == c ) goto configfound;
}
printk(KERN_INFO "usb-midi: Config not found.\n");
return -EINVAL;
configfound:
/* this may not be necessary. */
if ( usb_set_configuration( d, c->desc.bConfigurationValue ) < 0 ) {
printk(KERN_INFO "usb-midi: Could not set config.\n");
return -EINVAL;
}
/* From USB Spec v2.0, Section 9.5. /* From USB Spec v2.0, Section 9.5.
If the class or vendor specific descriptors use the same format If the class or vendor specific descriptors use the same format
......
...@@ -1175,8 +1175,10 @@ void usb_hub_cleanup(void) ...@@ -1175,8 +1175,10 @@ void usb_hub_cleanup(void)
* *
* Take a look at proc_resetdevice in devio.c for some sample code to * Take a look at proc_resetdevice in devio.c for some sample code to
* do this. * do this.
* Use this only from within your probe function, otherwise use
* usb_reset_device() below, which ensure proper locking
*/ */
int usb_reset_device(struct usb_device *dev) int usb_physical_reset_device(struct usb_device *dev)
{ {
struct usb_device *parent = dev->parent; struct usb_device *parent = dev->parent;
struct usb_device_descriptor *descriptor; struct usb_device_descriptor *descriptor;
...@@ -1306,3 +1308,16 @@ int usb_reset_device(struct usb_device *dev) ...@@ -1306,3 +1308,16 @@ int usb_reset_device(struct usb_device *dev)
return 0; return 0;
} }
int usb_reset_device(struct usb_device *udev)
{
struct device *gdev = &udev->dev;
int r;
down_read(&gdev->bus->subsys.rwsem);
r = usb_physical_reset_device(udev);
up_read(&gdev->bus->subsys.rwsem);
return r;
}
...@@ -930,6 +930,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -930,6 +930,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* reset more hc/hcd endpoint state */ /* reset more hc/hcd endpoint state */
dev->toggle[0] = 0; dev->toggle[0] = 0;
dev->toggle[1] = 0; dev->toggle[1] = 0;
dev->halted[0] = 0;
dev->halted[1] = 0;
usb_set_maxpacket(dev); usb_set_maxpacket(dev);
return 0; return 0;
......
...@@ -89,11 +89,6 @@ int usb_device_probe(struct device *dev) ...@@ -89,11 +89,6 @@ int usb_device_probe(struct device *dev)
if (!driver->probe) if (!driver->probe)
return error; return error;
if (!try_module_get(driver->owner)) {
dev_err (dev, "Can't get a module reference for %s\n", driver->name);
return error;
}
id = usb_match_id (intf, driver->id_table); id = usb_match_id (intf, driver->id_table);
if (id) { if (id) {
dev_dbg (dev, "%s - got id\n", __FUNCTION__); dev_dbg (dev, "%s - got id\n", __FUNCTION__);
...@@ -104,8 +99,6 @@ int usb_device_probe(struct device *dev) ...@@ -104,8 +99,6 @@ int usb_device_probe(struct device *dev)
if (!error) if (!error)
intf->driver = driver; intf->driver = driver;
module_put(driver->owner);
return error; return error;
} }
...@@ -117,22 +110,6 @@ int usb_device_remove(struct device *dev) ...@@ -117,22 +110,6 @@ int usb_device_remove(struct device *dev)
intf = list_entry(dev,struct usb_interface,dev); intf = list_entry(dev,struct usb_interface,dev);
driver = to_usb_driver(dev->driver); driver = to_usb_driver(dev->driver);
if (!driver) {
dev_err(dev, "%s does not have a valid driver to work with!",
__FUNCTION__);
return -ENODEV;
}
if (!try_module_get(driver->owner)) {
// FIXME this happens even when we just rmmod
// drivers that aren't in active use...
dev_err(dev, "Dieing driver still bound to device.\n");
return -EIO;
}
/* if we sleep here on an umanaged driver
* the holder of the lock guards against
* module unload */
down(&driver->serialize); down(&driver->serialize);
if (intf->driver && intf->driver->disconnect) if (intf->driver && intf->driver->disconnect)
...@@ -143,7 +120,6 @@ int usb_device_remove(struct device *dev) ...@@ -143,7 +120,6 @@ int usb_device_remove(struct device *dev)
usb_driver_release_interface(driver, intf); usb_driver_release_interface(driver, intf);
up(&driver->serialize); up(&driver->serialize);
module_put(driver->owner);
return 0; return 0;
} }
...@@ -498,9 +474,6 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev) ...@@ -498,9 +474,6 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev)
continue; continue;
intf = to_usb_interface(dev); intf = to_usb_interface(dev);
if (!intf)
continue;
if (kdev_same(intf->kdev,kdev)) { if (kdev_same(intf->kdev,kdev)) {
return intf; return intf;
} }
...@@ -566,12 +539,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -566,12 +539,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
return 0; return 0;
intf = to_usb_interface(dev); intf = to_usb_interface(dev);
if (!intf)
return -ENODEV;
usb_dev = interface_to_usbdev (intf); usb_dev = interface_to_usbdev (intf);
if (!usb_dev)
return -ENODEV;
if (usb_dev->devnum < 0) { if (usb_dev->devnum < 0) {
dbg ("device already deleted ??"); dbg ("device already deleted ??");
...@@ -748,8 +716,6 @@ static void usb_release_dev(struct device *dev) ...@@ -748,8 +716,6 @@ static void usb_release_dev(struct device *dev)
struct usb_device *udev; struct usb_device *udev;
udev = to_usb_device(dev); udev = to_usb_device(dev);
if (!udev)
return;
if (udev->bus && udev->bus->op && udev->bus->op->deallocate) if (udev->bus && udev->bus->op && udev->bus->op->deallocate)
udev->bus->op->deallocate(udev); udev->bus->op->deallocate(udev);
......
...@@ -62,6 +62,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) ...@@ -62,6 +62,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
{ {
memset (qtd, 0, sizeof *qtd); memset (qtd, 0, sizeof *qtd);
qtd->qtd_dma = dma; qtd->qtd_dma = dma;
qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
qtd->hw_next = EHCI_LIST_END; qtd->hw_next = EHCI_LIST_END;
qtd->hw_alt_next = EHCI_LIST_END; qtd->hw_alt_next = EHCI_LIST_END;
INIT_LIST_HEAD (&qtd->qtd_list); INIT_LIST_HEAD (&qtd->qtd_list);
......
...@@ -137,7 +137,10 @@ static void qtd_copy_status ( ...@@ -137,7 +137,10 @@ static void qtd_copy_status (
if (QTD_CERR (token)) if (QTD_CERR (token))
urb->status = -EPIPE; urb->status = -EPIPE;
else { else {
dbg ("3strikes"); ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
urb->dev->devpath,
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out");
urb->status = -EPROTO; urb->status = -EPROTO;
} }
/* CERR nonzero + no errors + halt --> stall */ /* CERR nonzero + no errors + halt --> stall */
...@@ -213,7 +216,6 @@ ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs) ...@@ -213,7 +216,6 @@ ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs)
/* complete() can reenter this HCD */ /* complete() can reenter this HCD */
spin_unlock (&ehci->lock); spin_unlock (&ehci->lock);
usb_hcd_giveback_urb (&ehci->hcd, urb, regs); usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
spin_lock (&ehci->lock); spin_lock (&ehci->lock);
} }
...@@ -827,7 +829,7 @@ static struct ehci_qh *qh_append_tds ( ...@@ -827,7 +829,7 @@ static struct ehci_qh *qh_append_tds (
* HC is allowed to fetch the old dummy (4.10.2). * HC is allowed to fetch the old dummy (4.10.2).
*/ */
token = qtd->hw_token; token = qtd->hw_token;
qtd->hw_token = 0; qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
wmb (); wmb ();
dummy = qh->dummy; dummy = qh->dummy;
...@@ -879,8 +881,7 @@ submit_async ( ...@@ -879,8 +881,7 @@ submit_async (
if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe)) if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe))
epnum |= 0x10; epnum |= 0x10;
vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]", ehci_vdbg (ehci, "submit_async urb %p len %d ep%d%s qtd %p [qh %p]\n",
hcd_to_bus (&ehci->hcd)->bus_name,
urb, urb->transfer_buffer_length, urb, urb->transfer_buffer_length,
epnum & 0x0f, (epnum & 0x10) ? "in" : "out", epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
qtd, dev ? dev->ep [epnum] : (void *)~0); qtd, dev ? dev->ep [epnum] : (void *)~0);
...@@ -916,7 +917,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) ...@@ -916,7 +917,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
del_timer (&ehci->watchdog); del_timer (&ehci->watchdog);
qh->hw_next = cpu_to_le32 (qh->qh_dma); // qh->hw_next = cpu_to_le32 (qh->qh_dma);
qh->qh_state = QH_STATE_IDLE; qh->qh_state = QH_STATE_IDLE;
qh->qh_next.qh = 0; qh->qh_next.qh = 0;
qh_put (ehci, qh); // refcount from reclaim qh_put (ehci, qh); // refcount from reclaim
......
...@@ -429,6 +429,8 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -429,6 +429,8 @@ static int hc_reset (struct ohci_hcd *ohci)
ohci->hc_control = readl (&ohci->regs->control); ohci->hc_control = readl (&ohci->regs->control);
ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
// flush those pci writes
(void) readl (&ohci->regs->control);
wait_ms (50); wait_ms (50);
/* HC Reset requires max 10 us delay */ /* HC Reset requires max 10 us delay */
...@@ -450,6 +452,8 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -450,6 +452,8 @@ static int hc_reset (struct ohci_hcd *ohci)
* this if we write fmInterval after we're OPERATIONAL. * this if we write fmInterval after we're OPERATIONAL.
*/ */
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
// flush those pci writes
(void) readl (&ohci->regs->control);
return 0; return 0;
} }
...@@ -524,6 +528,8 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -524,6 +528,8 @@ static int hc_start (struct ohci_hcd *ohci)
writel (tmp, &ohci->regs->roothub.a); writel (tmp, &ohci->regs->roothub.a);
writel (RH_HS_LPSC, &ohci->regs->roothub.status); writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (0, &ohci->regs->roothub.b); writel (0, &ohci->regs->roothub.b);
// flush those pci writes
(void) readl (&ohci->regs->control);
// POTPGT delay is bits 24-31, in 2 ms units. // POTPGT delay is bits 24-31, in 2 ms units.
mdelay ((roothub_a (ohci) >> 23) & 0x1fe); mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
...@@ -610,6 +616,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -610,6 +616,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
writel (ints, &regs->intrstatus); writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable); writel (OHCI_INTR_MIE, &regs->intrenable);
// flush those pci writes
(void) readl (&ohci->regs->control);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -446,6 +446,8 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -446,6 +446,8 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
if (!ohci->sleeping) { if (!ohci->sleeping) {
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
writel (OHCI_INTR_SF, &ohci->regs->intrenable); writel (OHCI_INTR_SF, &ohci->regs->intrenable);
// flush those pci writes
(void) readl (&ohci->regs->control);
} }
} }
......
...@@ -1664,6 +1664,9 @@ static struct usb_driver hid_driver = { ...@@ -1664,6 +1664,9 @@ static struct usb_driver hid_driver = {
.probe = hid_probe, .probe = hid_probe,
.disconnect = hid_disconnect, .disconnect = hid_disconnect,
.id_table = hid_usb_ids, .id_table = hid_usb_ids,
.driver = {
.devclass = &input_devclass,
},
}; };
static int __init hid_init(void) static int __init hid_init(void)
......
...@@ -91,7 +91,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) ...@@ -91,7 +91,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
} }
struct usb_device_id kbtab_ids[] = { struct usb_device_id kbtab_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), driver_info : 0 }, { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 },
{ } { }
}; };
......
...@@ -359,6 +359,9 @@ static struct usb_driver usb_kbd_driver = { ...@@ -359,6 +359,9 @@ static struct usb_driver usb_kbd_driver = {
.probe = usb_kbd_probe, .probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect, .disconnect = usb_kbd_disconnect,
.id_table = usb_kbd_id_table, .id_table = usb_kbd_id_table,
.driver = {
.devclass = &input_devclass,
},
}; };
static int __init usb_kbd_init(void) static int __init usb_kbd_init(void)
......
...@@ -242,6 +242,9 @@ static struct usb_driver usb_mouse_driver = { ...@@ -242,6 +242,9 @@ static struct usb_driver usb_mouse_driver = {
.probe = usb_mouse_probe, .probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect, .disconnect = usb_mouse_disconnect,
.id_table = usb_mouse_id_table, .id_table = usb_mouse_id_table,
.driver = {
.devclass = &input_devclass,
},
}; };
static int __init usb_mouse_init(void) static int __init usb_mouse_init(void)
......
...@@ -1034,6 +1034,23 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) ...@@ -1034,6 +1034,23 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
** USB ** ** USB **
**********/ **********/
static int udsl_set_alternate (struct udsl_instance_data *instance)
{
down (&instance->serialize); /* vs self */
if (!instance->firmware_loaded) {
int ret;
if ((ret = usb_set_interface (instance->usb_dev, 1, 1)) < 0) {
up (&instance->serialize);
return ret;
}
instance->firmware_loaded = 1;
}
up (&instance->serialize);
udsl_fire_receivers (instance);
return 0;
}
static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data) static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data)
{ {
struct udsl_instance_data *instance = usb_get_intfdata (intf); struct udsl_instance_data *instance = usb_get_intfdata (intf);
...@@ -1048,14 +1065,7 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void * ...@@ -1048,14 +1065,7 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *
switch (code) { switch (code) {
case UDSL_IOCTL_START: case UDSL_IOCTL_START:
instance->atm_dev->signal = ATM_PHY_SIG_FOUND; instance->atm_dev->signal = ATM_PHY_SIG_FOUND;
down (&instance->serialize); /* vs self */ return udsl_set_alternate (instance);
if (!instance->firmware_loaded) {
usb_set_interface (instance->usb_dev, 1, 1);
instance->firmware_loaded = 1;
}
up (&instance->serialize);
udsl_fire_receivers (instance);
return 0;
case UDSL_IOCTL_STOP: case UDSL_IOCTL_STOP:
instance->atm_dev->signal = ATM_PHY_SIG_LOST; instance->atm_dev->signal = ATM_PHY_SIG_LOST;
return 0; return 0;
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v0.5.9 (2002/12/31)" #define DRIVER_VERSION "v0.5.10 (2003/04/01)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
...@@ -121,7 +121,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -121,7 +121,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
char *buffer; char *buffer;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL); buffer = kmalloc(size, GFP_DMA);
if (!buffer) { if (!buffer) {
warn("%s: looks like we're out of memory", __FUNCTION__); warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -170,7 +170,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -170,7 +170,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
char *buffer; char *buffer;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL); buffer = kmalloc(size, GFP_DMA);
if (!buffer) { if (!buffer) {
warn("%s: looks like we're out of memory", __FUNCTION__); warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -218,7 +218,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -218,7 +218,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
char *tmp; char *tmp;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
tmp = kmalloc(1, GFP_KERNEL); tmp = kmalloc(1, GFP_DMA);
if (!tmp) { if (!tmp) {
warn("%s: looks like we're out of memory", __FUNCTION__); warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -233,7 +233,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -233,7 +233,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
pegasus->dr.wValue = cpu_to_le16p(&data); pegasus->dr.wValue = cpu_to_le16(data);
pegasus->dr.wIndex = cpu_to_le16p(&indx); pegasus->dr.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16(1); pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1; pegasus->ctrl_urb->transfer_buffer_length = 1;
...@@ -711,11 +711,11 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) ...@@ -711,11 +711,11 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
pegasus->stats.tx_aborted_errors++; pegasus->stats.tx_aborted_errors++;
if (d[0] & LATE_COL) if (d[0] & LATE_COL)
pegasus->stats.tx_window_errors++; pegasus->stats.tx_window_errors++;
if (d[0] & (NO_CARRIER | LOSS_CARRIER)) { if (d[5] & LINK_STATUS) {
pegasus->stats.tx_carrier_errors++;
netif_carrier_off(net);
} else {
netif_carrier_on(net); netif_carrier_on(net);
} else {
pegasus->stats.tx_carrier_errors++;
netif_carrier_off(net);
} }
} }
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
#define LOSS_CARRIER 0x08 #define LOSS_CARRIER 0x08
#define JABBER_TIMEOUT 0x04 #define JABBER_TIMEOUT 0x04
#define LINK_STATUS 0x01
#define PEGASUS_REQT_READ 0xc0 #define PEGASUS_REQT_READ 0xc0
#define PEGASUS_REQT_WRITE 0x40 #define PEGASUS_REQT_WRITE 0x40
#define PEGASUS_REQ_GET_REGS 0xf0 #define PEGASUS_REQ_GET_REGS 0xf0
......
This diff is collapsed.
...@@ -411,19 +411,19 @@ static const struct keyspan_device_details usa49w_device_details = { ...@@ -411,19 +411,19 @@ static const struct keyspan_device_details usa49w_device_details = {
}; };
static const struct keyspan_device_details usa49wlc_device_details = { static const struct keyspan_device_details usa49wlc_device_details = {
product_id: keyspan_usa49wlc_product_id, .product_id = keyspan_usa49wlc_product_id,
msg_format: msg_usa49, .msg_format = msg_usa49,
num_ports: 4, .num_ports = 4,
indat_endp_flip: 0, .indat_endp_flip = 0,
outdat_endp_flip: 0, .outdat_endp_flip = 0,
indat_endpoints: {0x81, 0x82, 0x83, 0x84}, .indat_endpoints = {0x81, 0x82, 0x83, 0x84},
outdat_endpoints: {0x01, 0x02, 0x03, 0x04}, .outdat_endpoints = {0x01, 0x02, 0x03, 0x04},
inack_endpoints: {-1, -1, -1, -1}, .inack_endpoints = {-1, -1, -1, -1},
outcont_endpoints: {-1, -1, -1, -1}, .outcont_endpoints = {-1, -1, -1, -1},
instat_endpoint: 0x87, .instat_endpoint = 0x87,
glocont_endpoint: 0x07, .glocont_endpoint = 0x07,
calculate_baud_rate: keyspan_usa19w_calc_baud, .calculate_baud_rate = keyspan_usa19w_calc_baud,
baudclk: KEYSPAN_USA19W_BAUDCLK, .baudclk = KEYSPAN_USA19W_BAUDCLK,
}; };
static const struct keyspan_device_details *keyspan_devices[] = { static const struct keyspan_device_details *keyspan_devices[] = {
......
...@@ -141,13 +141,19 @@ static int usb_storage_release(struct Scsi_Host *psh) ...@@ -141,13 +141,19 @@ static int usb_storage_release(struct Scsi_Host *psh)
static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
{ {
struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
int state = atomic_read(&us->sm_state);
US_DEBUGP("queuecommand() called\n"); US_DEBUGP("queuecommand() called\n");
srb->host_scribble = (unsigned char *)us; srb->host_scribble = (unsigned char *)us;
/* enqueue the command */ /* enqueue the command */
BUG_ON(atomic_read(&us->sm_state) != US_STATE_IDLE); if (state != US_STATE_IDLE || us->srb != NULL) {
BUG_ON(us->srb != NULL); printk(KERN_ERR USB_STORAGE "Error in %s: "
"state = %d, us->srb = %p\n",
__FUNCTION__, state, us->srb);
return SCSI_MLQUEUE_HOST_BUSY;
}
srb->scsi_done = done; srb->scsi_done = done;
us->srb = srb; us->srb = srb;
...@@ -175,8 +181,7 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb ) ...@@ -175,8 +181,7 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb )
return FAILED; return FAILED;
} }
usb_stor_abort_transport(us); return usb_stor_abort_transport(us);
return SUCCESS;
} }
/* This invokes the transport reset mechanism to reset the state of the /* This invokes the transport reset mechanism to reset the state of the
...@@ -185,10 +190,15 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb ) ...@@ -185,10 +190,15 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb )
static int usb_storage_device_reset( Scsi_Cmnd *srb ) static int usb_storage_device_reset( Scsi_Cmnd *srb )
{ {
struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
int state = atomic_read(&us->sm_state);
int result; int result;
US_DEBUGP("device_reset() called\n" ); US_DEBUGP("device_reset() called\n" );
BUG_ON(atomic_read(&us->sm_state) != US_STATE_IDLE); if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* set the state and release the lock */ /* set the state and release the lock */
atomic_set(&us->sm_state, US_STATE_RESETTING); atomic_set(&us->sm_state, US_STATE_RESETTING);
...@@ -260,6 +270,7 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset, ...@@ -260,6 +270,7 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset,
struct us_data *us; struct us_data *us;
char *pos = buffer; char *pos = buffer;
struct Scsi_Host *hostptr; struct Scsi_Host *hostptr;
unsigned long f;
/* if someone is sending us data, just throw it away */ /* if someone is sending us data, just throw it away */
if (inout) if (inout)
...@@ -274,6 +285,7 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset, ...@@ -274,6 +285,7 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset,
/* if we couldn't find it, we return an error */ /* if we couldn't find it, we return an error */
if (!us) { if (!us) {
scsi_host_put(hostptr);
return -ESRCH; return -ESRCH;
} }
...@@ -289,6 +301,24 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset, ...@@ -289,6 +301,24 @@ static int usb_storage_proc_info (char *buffer, char **start, off_t offset,
SPRINTF(" Protocol: %s\n", us->protocol_name); SPRINTF(" Protocol: %s\n", us->protocol_name);
SPRINTF(" Transport: %s\n", us->transport_name); SPRINTF(" Transport: %s\n", us->transport_name);
/* show the device flags */
if (pos < buffer + length) {
pos += sprintf(pos, " Quirks:");
f = us->flags;
#define DO_FLAG(a) if (f & US_FL_##a) pos += sprintf(pos, " " #a)
DO_FLAG(SINGLE_LUN);
DO_FLAG(MODE_XLATE);
DO_FLAG(START_STOP);
DO_FLAG(IGNORE_SER);
DO_FLAG(SCM_MULT_TARG);
DO_FLAG(FIX_INQUIRY);
DO_FLAG(FIX_CAPACITY);
#undef DO_FLAG
*(pos++) = '\n';
}
/* release the reference count on this host */ /* release the reference count on this host */
scsi_host_put(hostptr); scsi_host_put(hostptr);
......
...@@ -297,10 +297,11 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe, ...@@ -297,10 +297,11 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
/* stalled */ /* stalled */
case -EPIPE: case -EPIPE:
/* for control endpoints, a stall indicates a protocol error */ /* for control endpoints, (used by CB[I]) a stall indicates
* a failed command */
if (usb_pipecontrol(pipe)) { if (usb_pipecontrol(pipe)) {
US_DEBUGP("-- stall on control pipe\n"); US_DEBUGP("-- stall on control pipe\n");
return USB_STOR_XFER_ERROR; return USB_STOR_XFER_STALLED;
} }
/* for other sorts of endpoint, clear the stall */ /* for other sorts of endpoint, clear the stall */
...@@ -691,7 +692,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -691,7 +692,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Abort the currently running scsi command or device reset. /* Abort the currently running scsi command or device reset.
* This must be called with scsi_lock(us->srb->host) held */ * This must be called with scsi_lock(us->srb->host) held */
void usb_stor_abort_transport(struct us_data *us) int usb_stor_abort_transport(struct us_data *us)
{ {
struct Scsi_Host *host; struct Scsi_Host *host;
int state = atomic_read(&us->sm_state); int state = atomic_read(&us->sm_state);
...@@ -701,7 +702,11 @@ void usb_stor_abort_transport(struct us_data *us) ...@@ -701,7 +702,11 @@ void usb_stor_abort_transport(struct us_data *us)
/* Normally the current state is RUNNING. If the control thread /* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be * hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */ * IDLE. Anything else is a bug. */
BUG_ON((state != US_STATE_RUNNING && state != US_STATE_IDLE)); if (state != US_STATE_RUNNING && state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* set state to abort and release the lock */ /* set state to abort and release the lock */
atomic_set(&us->sm_state, US_STATE_ABORTING); atomic_set(&us->sm_state, US_STATE_ABORTING);
...@@ -730,6 +735,7 @@ void usb_stor_abort_transport(struct us_data *us) ...@@ -730,6 +735,7 @@ void usb_stor_abort_transport(struct us_data *us)
/* Reacquire the lock: note that us->srb is now NULL */ /* Reacquire the lock: note that us->srb is now NULL */
scsi_lock(host); scsi_lock(host);
return SUCCESS;
} }
/* /*
...@@ -750,8 +756,14 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -750,8 +756,14 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check the return code for the command */ /* check the return code for the command */
US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result); US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
/* if we stalled the command, it means command failed */
if (result == USB_STOR_XFER_STALLED) {
return USB_STOR_TRANSPORT_FAILED;
}
/* Uh oh... serious problem here */
if (result != USB_STOR_XFER_GOOD) { if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -834,8 +846,14 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -834,8 +846,14 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check the return code for the command */ /* check the return code for the command */
US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result); US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
/* if we stalled the command, it means command failed */
if (result == USB_STOR_XFER_STALLED) {
return USB_STOR_TRANSPORT_FAILED;
}
/* Uh oh... serious problem here */
if (result != USB_STOR_XFER_GOOD) { if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
......
...@@ -154,7 +154,7 @@ extern int usb_stor_Bulk_max_lun(struct us_data*); ...@@ -154,7 +154,7 @@ extern int usb_stor_Bulk_max_lun(struct us_data*);
extern int usb_stor_Bulk_reset(struct us_data*); extern int usb_stor_Bulk_reset(struct us_data*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*); extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern void usb_stor_abort_transport(struct us_data*); extern int usb_stor_abort_transport(struct us_data*);
extern int usb_stor_bulk_msg(struct us_data *us, void *data, extern int usb_stor_bulk_msg(struct us_data *us, void *data,
unsigned int pipe, unsigned int len, unsigned int *act_len); unsigned int pipe, unsigned int len, unsigned int *act_len);
......
This diff is collapsed.
...@@ -61,7 +61,7 @@ static struct file_system_type **find_filesystem(const char *name) ...@@ -61,7 +61,7 @@ static struct file_system_type **find_filesystem(const char *name)
/* define fs_subsys */ /* define fs_subsys */
static decl_subsys(fs, NULL); static decl_subsys(fs, NULL, NULL);
static int register_fs_subsys(struct file_system_type * fs) static int register_fs_subsys(struct file_system_type * fs)
{ {
......
...@@ -248,7 +248,7 @@ static struct attribute * default_attrs[] = { ...@@ -248,7 +248,7 @@ static struct attribute * default_attrs[] = {
extern struct subsystem block_subsys; extern struct subsystem block_subsys;
static struct kobj_type ktype_part = { struct kobj_type ktype_part = {
.default_attrs = default_attrs, .default_attrs = default_attrs,
.sysfs_ops = &part_sysfs_ops, .sysfs_ops = &part_sysfs_ops,
}; };
......
...@@ -57,12 +57,24 @@ struct kobj_type { ...@@ -57,12 +57,24 @@ struct kobj_type {
* of object; multiple ksets can belong to one subsystem. All * of object; multiple ksets can belong to one subsystem. All
* ksets of a subsystem share the subsystem's lock. * ksets of a subsystem share the subsystem's lock.
* *
* Each kset can support hotplugging; if it does, it will be given
* the opportunity to filter out specific kobjects from being
* reported, as well as to add its own "data" elements to the
* environment being passed to the hotplug helper.
*/ */
struct kset_hotplug_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);
char *(*name)(struct kset *kset, struct kobject *kobj);
int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size);
};
struct kset { struct kset {
struct subsystem * subsys; struct subsystem * subsys;
struct kobj_type * ktype; struct kobj_type * ktype;
struct list_head list; struct list_head list;
struct kobject kobj; struct kobject kobj;
struct kset_hotplug_ops * hotplug_ops;
}; };
...@@ -86,6 +98,13 @@ static inline void kset_put(struct kset * k) ...@@ -86,6 +98,13 @@ static inline void kset_put(struct kset * k)
kobject_put(&k->kobj); kobject_put(&k->kobj);
} }
static inline struct kobj_type * get_ktype(struct kobject * k)
{
if (k->kset && k->kset->ktype)
return k->kset->ktype;
else
return k->ktype;
}
extern struct kobject * kset_find_obj(struct kset *, const char *); extern struct kobject * kset_find_obj(struct kset *, const char *);
...@@ -95,11 +114,12 @@ struct subsystem { ...@@ -95,11 +114,12 @@ struct subsystem {
struct rw_semaphore rwsem; struct rw_semaphore rwsem;
}; };
#define decl_subsys(_name,_type) \ #define decl_subsys(_name,_type,_hotplug_ops) \
struct subsystem _name##_subsys = { \ struct subsystem _name##_subsys = { \
.kset = { \ .kset = { \
.kobj = { .name = __stringify(_name) }, \ .kobj = { .name = __stringify(_name) }, \
.ktype = _type, \ .ktype = _type, \
.hotplug_ops =_hotplug_ops, \
} \ } \
} }
......
...@@ -11,14 +11,6 @@ ...@@ -11,14 +11,6 @@
static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED; static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED;
static inline struct kobj_type * get_ktype(struct kobject * k)
{
if (k->kset && k->kset->ktype)
return k->kset->ktype;
else
return k->ktype;
}
/** /**
* populate_dir - populate directory with attributes. * populate_dir - populate directory with attributes.
* @kobj: object we're working on. * @kobj: object we're working on.
...@@ -67,6 +59,140 @@ static inline struct kobject * to_kobj(struct list_head * entry) ...@@ -67,6 +59,140 @@ static inline struct kobject * to_kobj(struct list_head * entry)
} }
#ifdef CONFIG_HOTPLUG
static int get_kobj_path_length(struct kset *kset, struct kobject *kobj)
{
int length = 1;
struct kobject * parent = kobj;
/* walk up the ancestors until we hit the one pointing to the
* root.
* Add 1 to strlen for leading '/' of each level.
*/
do {
length += strlen (parent->name) + 1;
parent = parent->parent;
} while (parent);
return length;
}
static void fill_kobj_path(struct kset *kset, struct kobject *kobj, char *path, int length)
{
struct kobject * parent;
--length;
for (parent = kobj; parent; parent = parent->parent) {
int cur = strlen (parent->name);
/* back up enough to print this name with '/' */
length -= cur;
strncpy (path + length, parent->name, cur);
*(path + --length) = '/';
}
pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
}
#define BUFFER_SIZE 1024 /* should be enough memory for the env */
#define NUM_ENVP 32 /* number of env pointers */
static void kset_hotplug(const char *action, struct kset *kset,
struct kobject *kobj)
{
char *argv [3];
char **envp;
char *buffer;
char *scratch;
int i = 0;
int retval;
int kobj_path_length;
char *kobj_path;
char *name = NULL;
/* If the kset has a filter operation, call it. If it returns
failure, no hotplug event is required. */
if (kset->hotplug_ops->filter) {
if (!kset->hotplug_ops->filter(kset, kobj))
return;
}
pr_debug ("%s\n", __FUNCTION__);
if (!hotplug_path[0])
return;
envp = (char **)kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp)
return;
memset (envp, 0x00, NUM_ENVP * sizeof (char *));
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!buffer) {
kfree(envp);
return;
}
if (kset->hotplug_ops->name)
name = kset->hotplug_ops->name(kset, kobj);
if (name == NULL)
name = kset->kobj.name;
argv [0] = hotplug_path;
argv [1] = name;
argv [2] = 0;
/* minimal command environment */
envp [i++] = "HOME=/";
envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
scratch = buffer;
envp [i++] = scratch;
scratch += sprintf(scratch, "ACTION=%s", action) + 1;
kobj_path_length = get_kobj_path_length (kset, kobj);
kobj_path = kmalloc (kobj_path_length, GFP_KERNEL);
if (!kobj_path) {
kfree (buffer);
kfree (envp);
return;
}
memset (kobj_path, 0x00, kobj_path_length);
fill_kobj_path (kset, kobj, kobj_path, kobj_path_length);
envp [i++] = scratch;
scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
if (kset->hotplug_ops->hotplug) {
/* have the kset specific function add its stuff */
retval = kset->hotplug_ops->hotplug (kset, kobj,
&envp[i], NUM_ENVP - i, scratch,
BUFFER_SIZE - (scratch - buffer));
if (retval) {
pr_debug ("%s - hotplug() returned %d\n",
__FUNCTION__, retval);
goto exit;
}
}
pr_debug ("%s: %s %s %s %s %s %s\n", __FUNCTION__, argv[0], argv[1],
envp[0], envp[1], envp[2], envp[3]);
retval = call_usermodehelper (argv[0], argv, envp, 0);
if (retval)
pr_debug ("%s - call_usermodehelper returned %d\n",
__FUNCTION__, retval);
exit:
kfree (kobj_path);
kfree (buffer);
return;
}
#else
static void kset_hotplug(const char *action, struct kset *kset,
struct kobject *kobj)
{
return 0;
}
#endif /* CONFIG_HOTPLUG */
/** /**
* kobject_init - initialize object. * kobject_init - initialize object.
* @kobj: object in question. * @kobj: object in question.
...@@ -111,6 +237,7 @@ int kobject_add(struct kobject * kobj) ...@@ -111,6 +237,7 @@ int kobject_add(struct kobject * kobj)
{ {
int error = 0; int error = 0;
struct kobject * parent; struct kobject * parent;
struct kobject * top_kobj;
if (!(kobj = kobject_get(kobj))) if (!(kobj = kobject_get(kobj)))
return -ENOENT; return -ENOENT;
...@@ -134,6 +261,19 @@ int kobject_add(struct kobject * kobj) ...@@ -134,6 +261,19 @@ int kobject_add(struct kobject * kobj)
error = create_dir(kobj); error = create_dir(kobj);
if (error) if (error)
unlink(kobj); unlink(kobj);
else {
/* If this kobj does not belong to a kset,
try to find a parent that does. */
top_kobj = kobj;
if (!top_kobj->kset && top_kobj->parent) {
do {
top_kobj = top_kobj->parent;
} while (!top_kobj->kset && top_kobj->parent);
}
if (top_kobj->kset && top_kobj->kset->hotplug_ops)
kset_hotplug("add", top_kobj->kset, kobj);
}
return error; return error;
} }
...@@ -162,6 +302,20 @@ int kobject_register(struct kobject * kobj) ...@@ -162,6 +302,20 @@ int kobject_register(struct kobject * kobj)
void kobject_del(struct kobject * kobj) void kobject_del(struct kobject * kobj)
{ {
struct kobject * top_kobj;
/* If this kobj does not belong to a kset,
try to find a parent that does. */
top_kobj = kobj;
if (!top_kobj->kset && top_kobj->parent) {
do {
top_kobj = top_kobj->parent;
} while (!top_kobj->kset && top_kobj->parent);
}
if (top_kobj->kset && top_kobj->kset->hotplug_ops)
kset_hotplug("remove", top_kobj->kset, kobj);
sysfs_remove_dir(kobj); sysfs_remove_dir(kobj);
unlink(kobj); unlink(kobj);
} }
......
...@@ -2815,7 +2815,7 @@ extern void ip_auto_config(void); ...@@ -2815,7 +2815,7 @@ extern void ip_auto_config(void);
extern void dv_init(void); extern void dv_init(void);
#endif /* CONFIG_NET_DIVERT */ #endif /* CONFIG_NET_DIVERT */
static decl_subsys(net,NULL); static decl_subsys(net,NULL,NULL);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment