Commit 1a008d0e authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 2fbc109c 5c1c6931
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include "base.h" #include "base.h"
#include "fs/fs.h"
/* /*
* hotplugging invokes what /proc/sys/kernel/hotplug says (normally * hotplugging invokes what /proc/sys/kernel/hotplug says (normally
...@@ -32,14 +33,16 @@ ...@@ -32,14 +33,16 @@
int dev_hotplug (struct device *dev, const char *action) int dev_hotplug (struct device *dev, const char *action)
{ {
char *argv [3], **envp, *buffer, *scratch; char *argv [3], **envp, *buffer, *scratch;
char *dev_path;
int retval; int retval;
int i = 0; int i = 0;
int dev_length;
pr_debug ("%s\n", __FUNCTION__); pr_debug ("%s\n", __FUNCTION__);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!dev->bus || !dev->bus->hotplug) if (!dev->bus)
return -ENODEV; return -ENODEV;
if (!hotplug_path [0]) if (!hotplug_path [0])
...@@ -66,6 +69,18 @@ int dev_hotplug (struct device *dev, const char *action) ...@@ -66,6 +69,18 @@ int dev_hotplug (struct device *dev, const char *action)
return -ENOMEM; return -ENOMEM;
} }
dev_length = get_devpath_length (dev);
dev_length += strlen("root");
dev_path = kmalloc (dev_length, GFP_KERNEL);
if (!dev_path) {
kfree (buffer);
kfree (envp);
return -ENOMEM;
}
memset (dev_path, 0x00, dev_length);
strcpy (dev_path, "root");
fill_devpath (dev, dev_path, dev_length);
/* only one standardized param to hotplug command: the bus name */ /* only one standardized param to hotplug command: the bus name */
argv [0] = hotplug_path; argv [0] = hotplug_path;
argv [1] = dev->bus->name; argv [1] = dev->bus->name;
...@@ -77,26 +92,33 @@ int dev_hotplug (struct device *dev, const char *action) ...@@ -77,26 +92,33 @@ int dev_hotplug (struct device *dev, const char *action)
scratch = buffer; scratch = buffer;
/* action: add, remove */
envp [i++] = scratch; envp [i++] = scratch;
scratch += sprintf (scratch, "ACTION=%s", action) + 1; scratch += sprintf (scratch, "ACTION=%s", action) + 1;
/* have the bus specific function set up the rest of the environment */ envp [i++] = scratch;
retval = dev->bus->hotplug (dev, &envp[i], NUM_ENVP - i, scratch += sprintf (scratch, "DEVICE=%s", dev_path) + 1;
scratch, BUFFER_SIZE - (scratch - buffer));
if (retval) { if (dev->bus->hotplug) {
pr_debug ("%s - hotplug() returned %d\n", __FUNCTION__, retval); /* have the bus specific function add its stuff */
goto exit; retval = dev->bus->hotplug (dev, &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], pr_debug ("%s: %s %s %s %s %s %s\n", __FUNCTION__, argv [0], argv[1],
action, envp[0], envp[1], envp[2]); envp[0], envp[1], envp[2], envp[3]);
retval = call_usermodehelper (argv [0], argv, envp); retval = call_usermodehelper (argv [0], argv, envp);
if (retval) if (retval)
pr_debug ("%s - call_usermodehelper returned %d\n", pr_debug ("%s - call_usermodehelper returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
exit: exit:
kfree (dev_path);
kfree (buffer); kfree (buffer);
kfree (envp); kfree (envp);
return retval; return retval;
......
...@@ -1006,9 +1006,7 @@ static void bluetooth_write_bulk_callback (struct urb *urb) ...@@ -1006,9 +1006,7 @@ static void bluetooth_write_bulk_callback (struct urb *urb)
} }
/* wake up our little function to let the tty layer know that something happened */ /* wake up our little function to let the tty layer know that something happened */
queue_task(&bluetooth->tqueue, &tq_immediate); schedule_task(&bluetooth->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
......
...@@ -272,8 +272,7 @@ static void acm_write_bulk(struct urb *urb) ...@@ -272,8 +272,7 @@ static void acm_write_bulk(struct urb *urb)
if (urb->status) if (urb->status)
dbg("nonzero write bulk status received: %d", urb->status); dbg("nonzero write bulk status received: %d", urb->status);
queue_task(&acm->tqueue, &tq_immediate); schedule_task(&acm->tqueue);
mark_bh(IMMEDIATE_BH);
} }
static void acm_softint(void *private) static void acm_softint(void *private)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o buffer.o export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o buffer.o
usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \ usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
config.o file.o buffer.o config.o file.o buffer.o driverfs.o
ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o usbcore-objs += hcd-pci.o
......
...@@ -1067,6 +1067,10 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1067,6 +1067,10 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
/* disconnect kernel driver from interface, leaving it unbound. */ /* disconnect kernel driver from interface, leaving it unbound. */
case USBDEVFS_DISCONNECT: case USBDEVFS_DISCONNECT:
/* this function is voodoo. */ /* this function is voodoo. */
/* which function ... usb_device_remove()?
* FIXME either the module lock (BKL) should be involved
* here too, or the 'default' case below is broken
*/
driver = ifp->driver; driver = ifp->driver;
if (driver) { if (driver) {
dbg ("disconnect '%s' from dev %d interface %d", dbg ("disconnect '%s' from dev %d interface %d",
...@@ -1081,26 +1085,28 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1081,26 +1085,28 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
retval = usb_device_probe (&ifp->dev); retval = usb_device_probe (&ifp->dev);
break; break;
/* talk directly to the interface's driver */ /* talk directly to the interface's driver */
default: default:
lock_kernel(); /* against module unload */ /* BKL used here to protect against changing the binding
driver = ifp->driver; * of this driver to this device, as well as unloading its
if (driver == 0 || driver->ioctl == 0) { * driver module.
*/
lock_kernel ();
driver = ifp->driver;
if (driver == 0 || driver->ioctl == 0) {
unlock_kernel(); unlock_kernel();
retval = -ENOSYS; retval = -ENOSYS;
} else { } else {
if (ifp->driver->owner) { if (driver->owner
__MOD_INC_USE_COUNT(ifp->driver->owner); && !try_inc_mod_count (driver->owner)) {
unlock_kernel();
}
/* ifno might usefully be passed ... */
retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
/* size = min_t(int, size, retval)? */
if (ifp->driver->owner) {
__MOD_DEC_USE_COUNT(ifp->driver->owner);
} else {
unlock_kernel(); unlock_kernel();
retval = -ENOSYS;
break;
} }
unlock_kernel ();
retval = driver->ioctl (ifp, ctrl.ioctl_code, buf);
if (driver->owner)
__MOD_DEC_USE_COUNT (driver->owner);
} }
if (retval == -ENOIOCTLCMD) if (retval == -ENOIOCTLCMD)
......
/*
* drivers/usb/core/driverfs.c
*
* (C) Copyright 2002 David Brownell
* (C) Copyright 2002 Greg Kroah-Hartman
* (C) Copyright 2002 IBM Corp.
*
* All of the driverfs file attributes for usb devices and interfaces.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
#include "usb.h"
/* Active configuration fields */
#define usb_actconfig_attr(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
{ \
struct usb_device *udev; \
\
if (off) \
return 0; \
\
udev = to_usb_device (dev); \
return sprintf (buf, format_string, udev->actconfig->field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_actconfig_attr (bNumInterfaces, "%2d\n")
usb_actconfig_attr (bConfigurationValue, "%2d\n")
usb_actconfig_attr (bmAttributes, "%2x\n")
usb_actconfig_attr (MaxPower, "%3dmA\n")
/* String fields */
static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
static ssize_t
show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
static ssize_t
show_serial (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
/* Descriptor fields */
#define usb_descriptor_attr(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
{ \
struct usb_device *udev; \
\
if (off) \
return 0; \
\
udev = to_usb_device (dev); \
return sprintf (buf, format_string, udev->descriptor.field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_descriptor_attr (idVendor, "%04x\n")
usb_descriptor_attr (idProduct, "%04x\n")
usb_descriptor_attr (bcdDevice, "%04x\n")
usb_descriptor_attr (bDeviceClass, "%02x\n")
usb_descriptor_attr (bDeviceSubClass, "%02x\n")
usb_descriptor_attr (bDeviceProtocol, "%02x\n")
void usb_create_driverfs_dev_files (struct usb_device *udev)
{
struct device *dev = &udev->dev;
device_create_file (dev, &dev_attr_bNumInterfaces);
device_create_file (dev, &dev_attr_bConfigurationValue);
device_create_file (dev, &dev_attr_bmAttributes);
device_create_file (dev, &dev_attr_MaxPower);
device_create_file (dev, &dev_attr_idVendor);
device_create_file (dev, &dev_attr_idProduct);
device_create_file (dev, &dev_attr_bcdDevice);
device_create_file (dev, &dev_attr_bDeviceClass);
device_create_file (dev, &dev_attr_bDeviceSubClass);
device_create_file (dev, &dev_attr_bDeviceProtocol);
if (udev->descriptor.iManufacturer)
device_create_file (dev, &dev_attr_manufacturer);
if (udev->descriptor.iProduct)
device_create_file (dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber)
device_create_file (dev, &dev_attr_serial);
}
/* Interface fields */
#define usb_intf_attr(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
{ \
struct usb_interface *intf; \
int alt; \
\
if (off) \
return 0; \
\
intf = to_usb_interface (dev); \
alt = intf->act_altsetting; \
\
return sprintf (buf, format_string, intf->altsetting[alt].field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_intf_attr (bAlternateSetting, "%2d\n")
usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
void usb_create_driverfs_intf_files (struct usb_interface *intf)
{
device_create_file (&intf->dev, &dev_attr_bAlternateSetting);
device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol);
}
...@@ -1024,6 +1024,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1024,6 +1024,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
*/ */
urb = usb_get_urb (urb); urb = usb_get_urb (urb);
if (urb->dev == hcd->self.root_hub) { if (urb->dev == hcd->self.root_hub) {
/* NOTE: requirement on hub callers (usbfs and the hub
* driver, for now) that URBs' urb->transfer_buffer be
* valid and usb_buffer_{sync,unmap}() not be needed, since
* they could clobber root hub response data.
*/
urb->transfer_flags |= URB_NO_DMA_MAP; urb->transfer_flags |= URB_NO_DMA_MAP;
return rh_urb_enqueue (hcd, urb); return rh_urb_enqueue (hcd, urb);
} }
...@@ -1132,11 +1137,11 @@ static int hcd_unlink_urb (struct urb *urb) ...@@ -1132,11 +1137,11 @@ static int hcd_unlink_urb (struct urb *urb)
goto done; goto done;
} }
/* For non-periodic transfers, any status except -EINPROGRESS means /* Except for interrupt transfers, any status except -EINPROGRESS
* the HCD has already started to unlink this URB from the hardware. * means the HCD already started to unlink this URB from the hardware.
* In that case, there's no more work to do. * So there's no more work to do.
* *
* For periodic transfers, this is the only way to trigger unlinking * For interrupt transfers, this is the only way to trigger unlinking
* from the hardware. Since we (currently) overload urb->status to * from the hardware. Since we (currently) overload urb->status to
* tell the driver to unlink, error status might get clobbered ... * tell the driver to unlink, error status might get clobbered ...
* unless that transfer hasn't yet restarted. One such case is when * unless that transfer hasn't yet restarted. One such case is when
...@@ -1144,13 +1149,10 @@ static int hcd_unlink_urb (struct urb *urb) ...@@ -1144,13 +1149,10 @@ static int hcd_unlink_urb (struct urb *urb)
* *
* FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
*/ */
switch (usb_pipetype (urb->pipe)) { if (urb->status != -EINPROGRESS
case PIPE_CONTROL: && usb_pipetype (urb->pipe) != PIPE_INTERRUPT) {
case PIPE_BULK: retval = -EINVAL;
if (urb->status != -EINPROGRESS) { goto done;
retval = -EINVAL;
goto done;
}
} }
/* maybe set up to block on completion notification */ /* maybe set up to block on completion notification */
......
...@@ -537,7 +537,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -537,7 +537,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
dev_set_drvdata (&intf->dev, hub); dev_set_drvdata (&intf->dev, hub);
if (usb_hub_configure(hub, endpoint) >= 0) { if (usb_hub_configure(hub, endpoint) >= 0) {
strcpy (intf->dev.name, "Hub/Port Status Changes"); strcpy (intf->dev.name, "Hub");
return 0; return 0;
} }
...@@ -547,8 +547,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -547,8 +547,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV; return -ENODEV;
} }
static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data) static int
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{ {
struct usb_device *hub = interface_to_usbdev (intf);
/* assert ifno == 0 (part of hub spec) */ /* assert ifno == 0 (part of hub spec) */
switch (code) { switch (code) {
case USBDEVFS_HUB_PORTINFO: { case USBDEVFS_HUB_PORTINFO: {
......
This diff is collapsed.
...@@ -232,22 +232,19 @@ int usb_submit_urb(struct urb *urb, int mem_flags) ...@@ -232,22 +232,19 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
return -EMSGSIZE; return -EMSGSIZE;
} }
/* "high bandwidth" mode, 1-3 packets/uframe? */ /* periodic transfers limit size per frame/uframe,
if (dev->speed == USB_SPEED_HIGH) { * but drivers only control those sizes for ISO.
int mult; * while we're checking, initialize return status.
switch (temp) { */
case PIPE_ISOCHRONOUS: if (temp == PIPE_ISOCHRONOUS) {
case PIPE_INTERRUPT: int n, len;
mult = 1 + ((max >> 11) & 0x03);
/* "high bandwidth" mode, 1-3 packets/uframe? */
if (dev->speed == USB_SPEED_HIGH) {
int mult = 1 + ((max >> 11) & 0x03);
max &= 0x03ff; max &= 0x03ff;
max *= mult; max *= mult;
} }
}
/* periodic transfers limit size per frame/uframe */
switch (temp) {
case PIPE_ISOCHRONOUS: {
int n, len;
if (urb->number_of_packets <= 0) if (urb->number_of_packets <= 0)
return -EINVAL; return -EINVAL;
...@@ -255,13 +252,9 @@ int usb_submit_urb(struct urb *urb, int mem_flags) ...@@ -255,13 +252,9 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
len = urb->iso_frame_desc [n].length; len = urb->iso_frame_desc [n].length;
if (len < 0 || len > max) if (len < 0 || len > max)
return -EMSGSIZE; return -EMSGSIZE;
urb->iso_frame_desc [n].status = -EXDEV;
urb->iso_frame_desc [n].actual_length = 0;
} }
}
break;
case PIPE_INTERRUPT:
if (urb->transfer_buffer_length > max)
return -EMSGSIZE;
} }
/* the I/O buffer must be mapped/unmapped, except when length=0 */ /* the I/O buffer must be mapped/unmapped, except when length=0 */
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/usb.h> #include <linux/usb.h>
#include "hcd.h" #include "hcd.h"
#include "usb.h"
extern int usb_hub_init(void); extern int usb_hub_init(void);
extern void usb_hub_cleanup(void); extern void usb_hub_cleanup(void);
...@@ -123,6 +124,8 @@ int usb_device_remove(struct device *dev) ...@@ -123,6 +124,8 @@ int usb_device_remove(struct device *dev)
if (driver->owner) { if (driver->owner) {
m = try_inc_mod_count(driver->owner); m = try_inc_mod_count(driver->owner);
if (m == 0) { if (m == 0) {
// FIXME this happens even when we just rmmod
// drivers that aren't in active use...
err("Dieing driver still bound to device.\n"); err("Dieing driver still bound to device.\n");
return -EIO; return -EIO;
} }
...@@ -524,9 +527,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -524,9 +527,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
/* check for generic driver, we do not call do hotplug calls for it */
if (dev->driver == &usb_generic_driver) if (dev->driver == &usb_generic_driver)
return -ENODEV; return 0;
intf = to_usb_interface(dev); intf = to_usb_interface(dev);
if (!intf) if (!intf)
...@@ -629,98 +631,6 @@ static int usb_hotplug (struct device *dev, char **envp, ...@@ -629,98 +631,6 @@ static int usb_hotplug (struct device *dev, char **envp,
#endif /* CONFIG_HOTPLUG */ #endif /* CONFIG_HOTPLUG */
/* driverfs files */
/* devices have one current configuration, with one
* or more interfaces that are used concurrently
*/
static ssize_t
show_config (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
if (off)
return 0;
udev = to_usb_device (dev);
return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue);
}
static DEVICE_ATTR(configuration,S_IRUGO,show_config,NULL);
/* interfaces have one current setting; alternates
* can have different endpoints and class info.
*/
static ssize_t
show_altsetting (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_interface *interface;
if (off)
return 0;
interface = to_usb_interface (dev);
return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting);
}
static DEVICE_ATTR(altsetting,S_IRUGO,show_altsetting,NULL);
/* product driverfs file */
static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
/* manufacturer driverfs file */
static ssize_t
show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
/* serial number driverfs file */
static ssize_t
show_serial (struct device *dev, char *buf, size_t count, loff_t off)
{
struct usb_device *udev;
int len;
if (off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
/** /**
* usb_alloc_dev - allocate a usb device structure (usbcore-internal) * usb_alloc_dev - allocate a usb device structure (usbcore-internal)
* @parent: hub to which device is connected * @parent: hub to which device is connected
...@@ -1133,13 +1043,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1133,13 +1043,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
return err; return err;
/* add the USB device specific driverfs files */ /* add the USB device specific driverfs files */
device_create_file (&dev->dev, &dev_attr_configuration); usb_create_driverfs_dev_files (dev);
if (dev->descriptor.iManufacturer)
device_create_file (&dev->dev, &dev_attr_manufacturer);
if (dev->descriptor.iProduct)
device_create_file (&dev->dev, &dev_attr_product);
if (dev->descriptor.iSerialNumber)
device_create_file (&dev->dev, &dev_attr_serial);
/* Register all of the interfaces for this device with the driver core. /* Register all of the interfaces for this device with the driver core.
* Remember, interfaces get bound to drivers, not devices. */ * Remember, interfaces get bound to drivers, not devices. */
...@@ -1169,7 +1073,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1169,7 +1073,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
} }
dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id); dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
device_register (&interface->dev); device_register (&interface->dev);
device_create_file (&interface->dev, &dev_attr_altsetting); usb_create_driverfs_intf_files (interface);
} }
/* add a /proc/bus/usb entry */ /* add a /proc/bus/usb entry */
...@@ -1194,6 +1098,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1194,6 +1098,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
* avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping * avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping
* hardware for long idle periods. The implementation varies between * hardware for long idle periods. The implementation varies between
* platforms, depending on details of how DMA will work to this device. * platforms, depending on details of how DMA will work to this device.
* Using these buffers also helps prevent cacheline sharing problems on
* architectures where CPU caches are not DMA-coherent.
* *
* When the buffer is no longer used, free it with usb_buffer_free(). * When the buffer is no longer used, free it with usb_buffer_free().
*/ */
......
/* Functions local to drivers/usb/core/ */
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
...@@ -749,7 +749,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -749,7 +749,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
default: default:
spin_lock_irqsave (&ehci->lock, flags); spin_lock_irqsave (&ehci->lock, flags);
if (ehci->reclaim) { if (ehci->reclaim) {
dbg ("dq %p: reclaim = %p, %s", vdbg ("dq %p: reclaim = %p, %s",
qh, ehci->reclaim, RUN_CONTEXT); qh, ehci->reclaim, RUN_CONTEXT);
if (qh == ehci->reclaim) { if (qh == ehci->reclaim) {
/* unlinking qh for another queued urb? */ /* unlinking qh for another queued urb? */
......
...@@ -255,23 +255,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) ...@@ -255,23 +255,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
struct urb *urb = qtd->urb; struct urb *urb = qtd->urb;
u32 token = 0; u32 token = 0;
/* hc's on-chip qh overlay cache can overwrite our idea of
* next qtd ptrs, if we appended a qtd while the queue was
* advancing. (because we don't use dummy qtds.)
*/
if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current
&& qtd->hw_next != qh->hw_qtd_next) {
qh->hw_alt_next = qtd->hw_alt_next;
qh->hw_qtd_next = qtd->hw_next;
COUNT (ehci->stats.qpatch);
}
/* clean up any state from previous QTD ...*/ /* clean up any state from previous QTD ...*/
if (last) { if (last) {
if (likely (last->urb != urb)) { if (likely (last->urb != urb)) {
ehci_urb_done (ehci, last->urb); ehci_urb_done (ehci, last->urb);
count++; count++;
} }
/* qh overlays can have HC's old cached copies of
* next qtd ptrs, if an URB was queued afterwards.
*/
if (cpu_to_le32 (last->qtd_dma) == qh->hw_current
&& last->hw_next != qh->hw_qtd_next) {
qh->hw_alt_next = last->hw_alt_next;
qh->hw_qtd_next = last->hw_next;
COUNT (ehci->stats.qpatch);
}
ehci_qtd_free (ehci, last); ehci_qtd_free (ehci, last);
last = 0; last = 0;
} }
...@@ -529,7 +529,8 @@ qh_urb_transaction ( ...@@ -529,7 +529,8 @@ qh_urb_transaction (
} }
/* by default, enable interrupt on urb completion */ /* by default, enable interrupt on urb completion */
if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) // ... do it always, unless we switch over to dummy qtds
// if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC); qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
return head; return head;
...@@ -785,7 +786,6 @@ static struct ehci_qh *qh_append_tds ( ...@@ -785,7 +786,6 @@ static struct ehci_qh *qh_append_tds (
/* append to tds already queued to this qh? */ /* append to tds already queued to this qh? */
if (unlikely (!list_empty (&qh->qtd_list) && qtd)) { if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
struct ehci_qtd *last_qtd; struct ehci_qtd *last_qtd;
int short_rx = 0;
u32 hw_next; u32 hw_next;
/* update the last qtd's "next" pointer */ /* update the last qtd's "next" pointer */
...@@ -800,23 +800,16 @@ static struct ehci_qh *qh_append_tds ( ...@@ -800,23 +800,16 @@ static struct ehci_qh *qh_append_tds (
&& (epnum & 0x10)) { && (epnum & 0x10)) {
// only the last QTD for now // only the last QTD for now
last_qtd->hw_alt_next = hw_next; last_qtd->hw_alt_next = hw_next;
short_rx = 1;
} }
/* Adjust any old copies in qh overlay too. /* qh_completions() may need to patch the qh overlay if
* Interrupt code must cope with case of HC having it * the hc was advancing this queue while we appended.
* cached, and clobbering these updates. * we know it can: last_qtd->hw_token has IOC set.
* ... complicates getting rid of extra interrupts! *
* (Or: use dummy td, so cache always stays valid.) * or: use a dummy td (so the overlay gets the next td
* only when we set its active bit); fewer irqs.
*/ */
if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) { wmb ();
wmb ();
qh->hw_qtd_next = hw_next;
if (short_rx)
qh->hw_alt_next = hw_next
| (qh->hw_alt_next & 0x1e);
vdbg ("queue to qh %p, patch", qh);
}
/* no URB queued */ /* no URB queued */
} else { } else {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/malloc.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
...@@ -1158,6 +1158,7 @@ static hci_t *__devinit hc_alloc_hci (void) ...@@ -1158,6 +1158,7 @@ static hci_t *__devinit hc_alloc_hci (void)
bus = usb_alloc_bus (&hci_device_operations); bus = usb_alloc_bus (&hci_device_operations);
if (!bus) { if (!bus) {
kfree (hci); kfree (hci);
kfree (ps);
return NULL; return NULL;
} }
......
...@@ -193,12 +193,6 @@ static int ohci_urb_enqueue ( ...@@ -193,12 +193,6 @@ static int ohci_urb_enqueue (
break; break;
case PIPE_ISOCHRONOUS: /* number of packets from URB */ case PIPE_ISOCHRONOUS: /* number of packets from URB */
size = urb->number_of_packets; size = urb->number_of_packets;
if (size <= 0)
return -EINVAL;
for (i = 0; i < urb->number_of_packets; i++) {
urb->iso_frame_desc [i].actual_length = 0;
urb->iso_frame_desc [i].status = -EXDEV;
}
break; break;
} }
......
...@@ -48,10 +48,10 @@ dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) ...@@ -48,10 +48,10 @@ dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
struct hash_t * scan = entry->head; struct hash_t * scan = entry->head;
while (scan && scan->dma != dma) while (scan && scan->dma != dma)
scan = scan->next; scan = scan->next;
return scan->virt; return scan ? scan->virt : 0;
} }
static struct td * static inline struct td *
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
{ {
td_dma &= TD_MASK; td_dma &= TD_MASK;
...@@ -62,7 +62,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) ...@@ -62,7 +62,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
// FIXME: when updating the hashtables this way, mem_flags is unusable... // FIXME: when updating the hashtables this way, mem_flags is unusable...
/* Add a hash entry for a TD/ED; return true on success */ /* Add a hash entry for a TD/ED; return true on success */
static int static inline int
hash_add_ed_td ( hash_add_ed_td (
struct hash_list_t *entry, struct hash_list_t *entry,
void *virt, void *virt,
...@@ -97,7 +97,7 @@ hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags) ...@@ -97,7 +97,7 @@ hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
} }
static void static inline void
hash_free_ed_td (struct hash_list_t *entry, void *virt) hash_free_ed_td (struct hash_list_t *entry, void *virt)
{ {
struct hash_t *scan, *prev; struct hash_t *scan, *prev;
......
...@@ -854,6 +854,11 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -854,6 +854,11 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
int cc; int cc;
td = dma_to_td (ohci, td_dma); td = dma_to_td (ohci, td_dma);
if (!td) {
err ("%s bad entry %8x",
ohci->hcd.self.bus_name, td_dma);
break;
}
td->hwINFO |= cpu_to_le32 (TD_DONE); td->hwINFO |= cpu_to_le32 (TD_DONE);
cc = TD_CC_GET (le32_to_cpup (&td->hwINFO)); cc = TD_CC_GET (le32_to_cpup (&td->hwINFO));
......
...@@ -437,9 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb) ...@@ -437,9 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
/* Throw away data. No better idea what to do with it. */ /* Throw away data. No better idea what to do with it. */
priv->wrfilled=0; priv->wrfilled=0;
priv->wrsent=0; priv->wrsent=0;
queue_task(&port->tqueue, &tq_immediate); goto exit;
mark_bh(IMMEDIATE_BH);
return;
} }
dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent); dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
...@@ -453,16 +451,10 @@ static void cyberjack_write_bulk_callback (struct urb *urb) ...@@ -453,16 +451,10 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
priv->wrfilled=0; priv->wrfilled=0;
priv->wrsent=0; priv->wrsent=0;
} }
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
} }
queue_task(&port->tqueue, &tq_immediate); exit:
mark_bh(IMMEDIATE_BH); schedule_task(&port->tqueue);
return;
} }
static int __init cyberjack_init (void) static int __init cyberjack_init (void)
......
...@@ -362,11 +362,7 @@ static void empeg_write_bulk_callback (struct urb *urb) ...@@ -362,11 +362,7 @@ static void empeg_write_bulk_callback (struct urb *urb)
return; return;
} }
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
......
...@@ -484,10 +484,8 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb) ...@@ -484,10 +484,8 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb)
dbg("nonzero write bulk status received: %d", urb->status); dbg("nonzero write bulk status received: %d", urb->status);
return; return;
} }
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return; schedule_task(&port->tqueue);
} /* ftdi_sio_write_bulk_callback */ } /* ftdi_sio_write_bulk_callback */
......
...@@ -465,10 +465,8 @@ static void ipaq_write_bulk_callback(struct urb *urb) ...@@ -465,10 +465,8 @@ static void ipaq_write_bulk_callback(struct urb *urb)
priv->active = 0; priv->active = 0;
spin_unlock_irqrestore(&write_list_lock, flags); spin_unlock_irqrestore(&write_list_lock, flags);
} }
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH); schedule_task(&port->tqueue);
return;
} }
static int ipaq_write_room(struct usb_serial_port *port) static int ipaq_write_room(struct usb_serial_port *port)
......
...@@ -426,10 +426,7 @@ static void ir_write_bulk_callback (struct urb *urb) ...@@ -426,10 +426,7 @@ static void ir_write_bulk_callback (struct urb *urb)
urb->actual_length, urb->actual_length,
urb->transfer_buffer); urb->transfer_buffer);
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
static void ir_read_bulk_callback (struct urb *urb) static void ir_read_bulk_callback (struct urb *urb)
......
...@@ -447,10 +447,8 @@ static void usa2x_outdat_callback(struct urb *urb) ...@@ -447,10 +447,8 @@ static void usa2x_outdat_callback(struct urb *urb)
p_priv = (struct keyspan_port_private *)(port->private); p_priv = (struct keyspan_port_private *)(port->private);
dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]);
if (port->open_count) { if (port->open_count)
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
}
} }
static void usa26_inack_callback(struct urb *urb) static void usa26_inack_callback(struct urb *urb)
......
...@@ -577,10 +577,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb) ...@@ -577,10 +577,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb)
} }
/* from generic_write_bulk_callback */ /* from generic_write_bulk_callback */
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} /* klsi_105_write_bulk_completion_callback */ } /* klsi_105_write_bulk_completion_callback */
......
...@@ -507,8 +507,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb) ...@@ -507,8 +507,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb)
} else { } else {
/* from generic_write_bulk_callback */ /* from generic_write_bulk_callback */
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
} }
return; return;
......
...@@ -359,12 +359,9 @@ static void omninet_write_bulk_callback (struct urb *urb) ...@@ -359,12 +359,9 @@ static void omninet_write_bulk_callback (struct urb *urb)
return; return;
} }
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
// dbg("omninet_write_bulk_callback, tty %0x\n", tty); // dbg("omninet_write_bulk_callback, tty %0x\n", tty);
return;
} }
......
...@@ -705,10 +705,7 @@ static void pl2303_write_bulk_callback (struct urb *urb) ...@@ -705,10 +705,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
return; return;
} }
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
......
...@@ -1092,10 +1092,7 @@ static void generic_write_bulk_callback (struct urb *urb) ...@@ -1092,10 +1092,7 @@ static void generic_write_bulk_callback (struct urb *urb)
usb_serial_port_softint((void *)port); usb_serial_port_softint((void *)port);
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
static void generic_shutdown (struct usb_serial *serial) static void generic_shutdown (struct usb_serial *serial)
......
...@@ -182,9 +182,10 @@ static struct usb_device_id id_table [] = { ...@@ -182,9 +182,10 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
...@@ -202,9 +203,10 @@ static struct usb_device_id id_table_combined [] = { ...@@ -202,9 +203,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
...@@ -458,10 +460,7 @@ static void visor_write_bulk_callback (struct urb *urb) ...@@ -458,10 +460,7 @@ static void visor_write_bulk_callback (struct urb *urb)
/* free up the transfer buffer, as usb_free_urb() does not do this */ /* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer); kfree (urb->transfer_buffer);
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define PALM_I705_ID 0x0020 #define PALM_I705_ID 0x0020
#define PALM_M125_ID 0x0040 #define PALM_M125_ID 0x0040
#define PALM_M130_ID 0x0050 #define PALM_M130_ID 0x0050
#define PALM_ZIRE_ID 0x0070
#define SONY_VENDOR_ID 0x054C #define SONY_VENDOR_ID 0x054C
#define SONY_CLIE_3_5_ID 0x0038 #define SONY_CLIE_3_5_ID 0x0038
......
...@@ -918,10 +918,7 @@ static void whiteheat_write_callback(struct urb *urb) ...@@ -918,10 +918,7 @@ static void whiteheat_write_callback(struct urb *urb)
usb_serial_port_softint((void *)port); usb_serial_port_softint((void *)port);
queue_task(&port->tqueue, &tq_immediate); schedule_task(&port->tqueue);
mark_bh(IMMEDIATE_BH);
return;
} }
......
...@@ -530,6 +530,8 @@ int usb_stor_clear_halt(struct us_data *us, int pipe) ...@@ -530,6 +530,8 @@ int usb_stor_clear_halt(struct us_data *us, int pipe)
if (result < 0) if (result < 0)
return result; return result;
printk(KERN_ERR "usb_stor_clear_halt() WORKED!\n");
/* reset the toggles and endpoint flags */ /* reset the toggles and endpoint flags */
usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
usb_pipeout(pipe)); usb_pipeout(pipe));
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#include <linux/list.h> /* for struct list_head */ #include <linux/list.h> /* for struct list_head */
#include <linux/device.h> /* for struct device */ #include <linux/device.h> /* for struct device */
#include <linux/fs.h> /* for struct file_operations */ #include <linux/fs.h> /* for struct file_operations */
#include <linux/completion.h> /* for struct completion */
static __inline__ void wait_ms(unsigned int ms) static __inline__ void wait_ms(unsigned int ms)
...@@ -452,9 +453,9 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) ...@@ -452,9 +453,9 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
* User mode code can read these tables to choose which modules to load. * User mode code can read these tables to choose which modules to load.
* Declare the table as a MODULE_DEVICE_TABLE. * Declare the table as a MODULE_DEVICE_TABLE.
* *
* The third probe() parameter will point to a matching entry from this * A probe() parameter will point to a matching entry from this table.
* table. (Null value reserved.) Use the driver_data field for each * Use the driver_info field for each match to hold information tied
* match to hold information tied to that match: device quirks, etc. * to that match: device quirks, etc.
* *
* Terminate the driver's table with an all-zeroes entry. * Terminate the driver's table with an all-zeroes entry.
* Use the flag values to control which fields are compared. * Use the flag values to control which fields are compared.
...@@ -604,17 +605,14 @@ struct usb_device_id { ...@@ -604,17 +605,14 @@ struct usb_device_id {
* @name: The driver name should be unique among USB drivers, * @name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name. * and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular * @probe: Called to see if the driver is willing to manage a particular
* interface on a device. The probe routine returns a handle that * interface on a device. If it is, probe returns zero and uses
* will later be provided to disconnect(), or a null pointer to * dev_set_drvdata() to associate driver-specific data with the
* indicate that the driver will not handle the interface. * interface. It may also use usb_set_interface() to specify the
* The handle is normally a pointer to driver-specific data. * appropriate altsetting. If unwilling to manage the interface,
* If the probe() routine needs to access the interface * return a negative errno value.
* structure itself, use usb_ifnum_to_if() to make sure it's using
* the right one.
* @disconnect: Called when the interface is no longer accessible, usually * @disconnect: Called when the interface is no longer accessible, usually
* because its device has been (or is being) disconnected. The * because its device has been (or is being) disconnected or the
* handle passed is what was returned by probe(), or was provided * driver module is being unloaded.
* to usb_driver_claim_interface().
* @ioctl: Used for drivers that want to talk to userspace through * @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to * the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they * expose information to user space regardless of where they
...@@ -648,7 +646,7 @@ struct usb_driver { ...@@ -648,7 +646,7 @@ struct usb_driver {
void (*disconnect) (struct usb_interface *intf); void (*disconnect) (struct usb_interface *intf);
int (*ioctl) (struct usb_device *dev, unsigned int code, void *buf); int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
const struct usb_device_id *id_table; const struct usb_device_id *id_table;
...@@ -1074,6 +1072,57 @@ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); ...@@ -1074,6 +1072,57 @@ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
#define USB_CTRL_SET_TIMEOUT 3 #define USB_CTRL_SET_TIMEOUT 3
/**
* struct usb_sg_request - support for scatter/gather I/O
* @status: zero indicates success, else negative errno
* @bytes: counts bytes transferred.
*
* These requests are initialized using usb_sg_init(), and then are used
* as request handles passed to usb_sg_wait() or usb_sg_cancel(). Most
* members of the request object aren't for driver access.
*
* The status and bytecount values are valid only after usb_sg_wait()
* returns. If the status is zero, then the bytecount matches the total
* from the request.
*
* After an error completion, drivers may need to clear a halt condition
* on the endpoint.
*/
struct usb_sg_request {
int status;
size_t bytes;
// members not documented above are private to usbcore,
// and are not provided for driver access!
spinlock_t lock;
struct usb_device *dev;
int pipe;
struct scatterlist *sg;
int nents;
int entries;
struct urb **urbs;
int count;
struct completion complete;
};
int usb_sg_init (
struct usb_sg_request *io,
struct usb_device *dev,
unsigned pipe,
unsigned period,
struct scatterlist *sg,
int nents,
size_t length,
int mem_flags
);
void usb_sg_cancel (struct usb_sg_request *io);
void usb_sg_wait (struct usb_sg_request *io);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* /*
......
...@@ -108,7 +108,7 @@ struct usbdevfs_urb { ...@@ -108,7 +108,7 @@ struct usbdevfs_urb {
struct usbdevfs_iso_packet_desc iso_frame_desc[0]; struct usbdevfs_iso_packet_desc iso_frame_desc[0];
}; };
/* ioctls for talking to drivers in the usbcore module: */ /* ioctls for talking directly to drivers */
struct usbdevfs_ioctl { struct usbdevfs_ioctl {
int ifno; /* interface 0..N ; negative numbers reserved */ int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the int ioctl_code; /* MUST encode size + direction of data so the
......
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