Commit 0083ab86 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 3bdd85a2 ca433637
...@@ -104,8 +104,8 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \ ...@@ -104,8 +104,8 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/sound/sound_firmware.c \ $(TOPDIR)/sound/sound_firmware.c \
$(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/syncppp.c \
$(TOPDIR)/drivers/net/wan/z85230.c \ $(TOPDIR)/drivers/net/wan/z85230.c \
$(TOPDIR)/drivers/usb/hcd.c \ $(TOPDIR)/drivers/usb/core/hcd.c \
$(TOPDIR)/drivers/usb/usb.c \ $(TOPDIR)/drivers/usb/core/usb.c \
$(TOPDIR)/drivers/video/fbmem.c \ $(TOPDIR)/drivers/video/fbmem.c \
$(TOPDIR)/drivers/video/fbcmap.c \ $(TOPDIR)/drivers/video/fbcmap.c \
$(TOPDIR)/drivers/video/fbcon.c \ $(TOPDIR)/drivers/video/fbcon.c \
......
...@@ -282,7 +282,7 @@ ...@@ -282,7 +282,7 @@
</sect1> </sect1>
<sect1><title>USB Core APIs</title> <sect1><title>USB Core APIs</title>
!Edrivers/usb/usb.c !Edrivers/usb/core/usb.c
</sect1> </sect1>
<sect1><title>Host Controller APIs</title> <sect1><title>Host Controller APIs</title>
...@@ -290,7 +290,7 @@ ...@@ -290,7 +290,7 @@
most of which implement standard register interfaces such as most of which implement standard register interfaces such as
EHCI, OHCI, or UHCI. EHCI, OHCI, or UHCI.
</para> </para>
!Edrivers/usb/hcd.c !Edrivers/usb/core/hcd.c
</sect1> </sect1>
</chapter> </chapter>
......
This diff is collapsed.
CONFIG_USB_ACM
This driver supports USB modems and ISDN adapters which support the
Communication Device Class Abstract Control Model interface.
Please read <file:Documentation/usb/acm.txt> for details.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called acm.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUDIO
Say Y here if you want to connect USB audio equipment such as
speakers to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_BLUETOOTH_TTY
Say Y here if you want to connect a USB Bluetooth device to your
computer's USB port. You will need the Bluetooth stack (available
at <http://developer.axis.com/software/index.shtml>) to fully use
the device.
This driver implements a tty inteface to a Bluetooth device. If
you want to use a socket based Bluetooth stack (like the BlueZ
stack), do not use this driver.
If in doubt, say N here.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called bluetty.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PRINTER
Say Y here if you want to connect a USB printer to your computer's
USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called printer.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
# #
comment 'USB Device Class drivers' comment 'USB Device Class drivers'
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB Bluetooth TTY support' CONFIG_USB_BLUETOOTH_TTY $CONFIG_USB
dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
# Turn on CONFIG_USB_CLASS if any of the drivers are compiled into the kernel # Turn on CONFIG_USB_CLASS if any of the drivers are compiled into the kernel
# to make our Makefile logic a bit simpler. # to make our Makefile logic a bit simpler.
if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH" = "y" ]; then if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH_TTY" = "y" ]; then
define_bool CONFIG_USB_CLASS y define_bool CONFIG_USB_CLASS y
fi fi
if [ "$CONFIG_USB_ACM" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then if [ "$CONFIG_USB_ACM" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then
......
...@@ -7,7 +7,7 @@ O_TARGET := usb-class.o ...@@ -7,7 +7,7 @@ O_TARGET := usb-class.o
obj-$(CONFIG_USB_ACM) += cdc-acm.o obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_AUDIO) += audio.o obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o
obj-$(CONFIG_USB_PRINTER) += printer.o obj-$(CONFIG_USB_PRINTER) += printer.o
......
/* /*
* bluetooth.c Version 0.13 * bluetty.c Version 0.13
* *
* Copyright (c) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com> * Copyright (c) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu> * Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
* *
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
* *
* (2001/11/30) Version 0.13 gkh * (2001/11/30) Version 0.13 gkh
* - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com> * - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
...@@ -237,7 +237,7 @@ static struct usb_device_id usb_bluetooth_ids [] = { ...@@ -237,7 +237,7 @@ static struct usb_device_id usb_bluetooth_ids [] = {
MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids); MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
static struct usb_driver usb_bluetooth_driver = { static struct usb_driver usb_bluetooth_driver = {
name: "bluetooth", name: "bluetty",
probe: usb_bluetooth_probe, probe: usb_bluetooth_probe,
disconnect: usb_bluetooth_disconnect, disconnect: usb_bluetooth_disconnect,
id_table: usb_bluetooth_ids, id_table: usb_bluetooth_ids,
......
...@@ -597,33 +597,31 @@ static int proc_bulk(struct dev_state *ps, void *arg) ...@@ -597,33 +597,31 @@ static int proc_bulk(struct dev_state *ps, void *arg)
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
return -EINVAL; return -EINVAL;
len1 = bulk.len; len1 = bulk.len;
if (len1 > PAGE_SIZE) if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
return -EINVAL;
if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
tmo = (bulk.timeout * HZ + 999) / 1000; tmo = (bulk.timeout * HZ + 999) / 1000;
if (bulk.ep & 0x80) { if (bulk.ep & 0x80) {
if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
free_page((unsigned long)tbuf); kfree(tbuf);
return -EINVAL; return -EINVAL;
} }
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
if (!i && len2) { if (!i && len2) {
if (copy_to_user(bulk.data, tbuf, len2)) { if (copy_to_user(bulk.data, tbuf, len2)) {
free_page((unsigned long)tbuf); kfree(tbuf);
return -EFAULT; return -EFAULT;
} }
} }
} else { } else {
if (len1) { if (len1) {
if (copy_from_user(tbuf, bulk.data, len1)) { if (copy_from_user(tbuf, bulk.data, len1)) {
free_page((unsigned long)tbuf); kfree(tbuf);
return -EFAULT; return -EFAULT;
} }
} }
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
} }
free_page((unsigned long)tbuf); kfree(tbuf);
if (i < 0) { if (i < 0) {
printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n",
dev->devnum, bulk.ep, bulk.len, i); dev->devnum, bulk.ep, bulk.len, i);
...@@ -1059,6 +1057,8 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1059,6 +1057,8 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
int size; int size;
void *buf = 0; void *buf = 0;
int retval = 0; int retval = 0;
struct usb_interface *ifp = 0;
struct usb_driver *driver = 0;
/* get input parameters and alloc buffer */ /* get input parameters and alloc buffer */
if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl))) if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
...@@ -1076,33 +1076,41 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1076,33 +1076,41 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
} }
} }
/* ioctl to device */ if (!ps->dev)
if (ctrl.ifno < 0) { retval = -ENODEV;
switch (ctrl.ioctl_code) { else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
/* access/release token for issuing control messages retval = -EINVAL;
* ask a particular driver to bind/unbind, ... etc else switch (ctrl.ioctl_code) {
*/
} /* disconnect kernel driver from interface, leaving it unbound. */
retval = -ENOSYS; case USBDEVFS_DISCONNECT:
driver = ifp->driver;
/* ioctl to the driver which has claimed a given interface */ if (driver) {
} else { down (&driver->serialize);
struct usb_interface *ifp = 0; dbg ("disconnect '%s' from dev %d interface %d",
if (!ps->dev) driver->name, ps->dev->devnum, ctrl.ifno);
retval = -ENODEV; driver->disconnect (ps->dev, ifp->private_data);
else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces) usb_driver_release_interface (driver, ifp);
up (&driver->serialize);
} else
retval = -EINVAL; retval = -EINVAL;
break;
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
usb_find_interface_driver_for_ifnum (ps->dev, ctrl.ifno);
break;
/* talk directly to the interface's driver */
default:
driver = ifp->driver;
if (driver == 0 || driver->ioctl == 0)
retval = -ENOSYS;
else { else {
if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
retval = -EINVAL;
else if (ifp->driver == 0 || ifp->driver->ioctl == 0)
retval = -ENOSYS;
}
if (retval == 0) {
if (ifp->driver->owner) if (ifp->driver->owner)
__MOD_INC_USE_COUNT(ifp->driver->owner); __MOD_INC_USE_COUNT(ifp->driver->owner);
/* ifno might usefully be passed ... */ /* ifno might usefully be passed ... */
retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf); retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
/* size = min_t(int, size, retval)? */ /* size = min_t(int, size, retval)? */
if (ifp->driver->owner) if (ifp->driver->owner)
__MOD_DEC_USE_COUNT(ifp->driver->owner); __MOD_DEC_USE_COUNT(ifp->driver->owner);
......
...@@ -181,6 +181,24 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev); ...@@ -181,6 +181,24 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *);
extern void usb_free_dev(struct usb_device *);
extern int usb_new_device(struct usb_device *dev);
extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
#ifndef _LINUX_HUB_H
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
#endif /* _LINUX_HUB_H */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "hcd.h"
#include "hub.h" #include "hub.h"
/* Wakes up khubd */ /* Wakes up khubd */
......
...@@ -196,6 +196,28 @@ void usb_deregister(struct usb_driver *driver) ...@@ -196,6 +196,28 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special(); usbfs_update_special();
} }
/**
* usb_ifnum_to_ifpos - convert the interface number to the interface position
* @dev: the device to use
* @ifnum: the interface number (bInterfaceNumber); not interface position
*
* This is used to convert the interface _number_ (as in
* interface.bInterfaceNumber) to the interface _position_ (as in
* dev->actconfig->interface + position). Note that the number is the same as
* the position for all interfaces _except_ devices with interfaces not
* sequentially numbered (e.g., 0, 2, 3, etc).
*/
int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum)
{
int i;
for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
return i;
return -EINVAL;
}
/** /**
* usb_ifnum_to_if - get the interface object with a given interface number * usb_ifnum_to_if - get the interface object with a given interface number
* @dev: the device whose current configuration is considered * @dev: the device whose current configuration is considered
...@@ -570,6 +592,24 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum) ...@@ -570,6 +592,24 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
return -1; return -1;
} }
/**
* usb_find_interface_driver_for_ifnum - finds a usb interface driver for the specified ifnum
* @dev: the device to use
* @ifnum: the interface number (bInterfaceNumber); not interface position!
*
* This converts a ifnum to ifpos via a call to usb_ifnum_to_ifpos and then
* calls usb_find_interface_driver() with the found ifpos. Note
* usb_find_interface_driver's ifnum parameter is actually interface position.
*/
int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned ifnum)
{
int ifpos = usb_ifnum_to_ifpos(dev, ifnum);
if (0 > ifpos)
return -EINVAL;
return usb_find_interface_driver(dev, ifpos);
}
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
...@@ -789,50 +829,32 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -789,50 +829,32 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
return dev; return dev;
} }
// usbcore-internal ... /**
// but usb_dec_dev_use() is #defined to this, and that's public!! * usb_free_dev - free a usb device structure (usbcore-internal)
// FIXME the public call should BUG() whenever count goes to zero, * @dev: device that's been disconnected
// the usbcore-internal one should do so _unless_ it does so... * Context: !in_interrupt ()
*
* Used by hub and virtual root hub drivers. The device is completely
* gone, everything is cleaned up, so it's time to get rid of these last
* records of this device.
*/
void usb_free_dev(struct usb_device *dev) void usb_free_dev(struct usb_device *dev)
{ {
if (atomic_dec_and_test(&dev->refcnt)) { if (in_interrupt ())
/* Normally only goes to zero in usb_disconnect(), from BUG ();
* khubd or from roothub shutdown (rmmod/apmd/... thread). if (!atomic_dec_and_test (&dev->refcnt)) {
* Abnormally, roothub init errors can happen, so HCDs /* MUST go to zero here, else someone's hanging on to
* call this directly. * a device that's supposed to have been cleaned up!!
*
* Otherwise this is a nasty device driver bug, often in
* disconnect processing.
*/ */
if (in_interrupt ()) BUG ();
BUG ();
dev->bus->op->deallocate(dev);
usb_destroy_configuration(dev);
usb_bus_put(dev->bus);
kfree(dev);
} }
}
/** dev->bus->op->deallocate (dev);
* usb_inc_dev_use - record another reference to a device usb_destroy_configuration (dev);
* @dev: the device being referenced usb_bus_put (dev->bus);
* kfree (dev);
* Each live reference to a device should be refcounted.
*
* Device drivers should normally record such references in their
* open() methods.
* Drivers should then release them, using usb_dec_dev_use(), in their
* close() methods.
*/
void usb_inc_dev_use(struct usb_device *dev)
{
atomic_inc(&dev->refcnt);
} }
/** /**
* usb_alloc_urb - creates a new urb for a USB driver to use * usb_alloc_urb - creates a new urb for a USB driver to use
* @iso_packets: number of iso packets for this urb * @iso_packets: number of iso packets for this urb
...@@ -2636,6 +2658,7 @@ module_exit(usb_exit); ...@@ -2636,6 +2658,7 @@ module_exit(usb_exit);
* into the kernel, and other device drivers are built as modules, * into the kernel, and other device drivers are built as modules,
* then these symbols need to be exported for the modules to use. * then these symbols need to be exported for the modules to use.
*/ */
EXPORT_SYMBOL(usb_ifnum_to_ifpos);
EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_epnum_to_ep_desc); EXPORT_SYMBOL(usb_epnum_to_ep_desc);
...@@ -2647,6 +2670,7 @@ EXPORT_SYMBOL(usb_alloc_dev); ...@@ -2647,6 +2670,7 @@ EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev); EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_inc_dev_use); EXPORT_SYMBOL(usb_inc_dev_use);
EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum);
EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_interface_claimed); EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface); EXPORT_SYMBOL(usb_driver_release_interface);
......
...@@ -749,7 +749,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb) ...@@ -749,7 +749,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) { if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) {
urbp->fsbr = 1; urbp->fsbr = 1;
if (!uhci->fsbr++) if (!uhci->fsbr++ && !uhci->fsbrtimeout)
uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH; uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
} }
...@@ -1631,8 +1631,7 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) ...@@ -1631,8 +1631,7 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
if (urb->status != -EINPROGRESS) { if (urb->status != -EINPROGRESS) {
info("uhci_transfer_result: called for URB %p not in flight?", urb); info("uhci_transfer_result: called for URB %p not in flight?", urb);
spin_unlock_irqrestore(&urb->lock, flags); goto out;
return;
} }
switch (usb_pipetype(urb->pipe)) { switch (usb_pipetype(urb->pipe)) {
...@@ -1652,10 +1651,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) ...@@ -1652,10 +1651,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
urbp->status = ret; urbp->status = ret;
if (ret == -EINPROGRESS) { if (ret == -EINPROGRESS)
spin_unlock_irqrestore(&urb->lock, flags); goto out;
return;
}
switch (usb_pipetype(urb->pipe)) { switch (usb_pipetype(urb->pipe)) {
case PIPE_CONTROL: case PIPE_CONTROL:
...@@ -1669,11 +1666,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) ...@@ -1669,11 +1666,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
/* Interrupts are an exception */ /* Interrupts are an exception */
if (urb->interval) { if (urb->interval)
uhci_add_complete(urb); goto out_complete;
spin_unlock_irqrestore(&urb->lock, flags);
return; /* <-- note return */
}
/* Release bandwidth for Interrupt or Isoc. transfers */ /* Release bandwidth for Interrupt or Isoc. transfers */
/* Spinlock needed ? */ /* Spinlock needed ? */
...@@ -1689,8 +1683,10 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) ...@@ -1689,8 +1683,10 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
/* Remove it from uhci->urb_list */ /* Remove it from uhci->urb_list */
list_del_init(&urb->urb_list); list_del_init(&urb->urb_list);
out_complete:
uhci_add_complete(urb); uhci_add_complete(urb);
out:
spin_unlock_irqrestore(&urb->lock, flags); spin_unlock_irqrestore(&urb->lock, flags);
} }
...@@ -1820,6 +1816,9 @@ static int uhci_unlink_urb(struct urb *urb) ...@@ -1820,6 +1816,9 @@ static int uhci_unlink_urb(struct urb *urb)
} else { } else {
urb->status = -ENOENT; urb->status = -ENOENT;
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
if (in_interrupt()) { /* wait at least 1 frame */ if (in_interrupt()) { /* wait at least 1 frame */
static int errorcount = 10; static int errorcount = 10;
...@@ -1829,9 +1828,6 @@ static int uhci_unlink_urb(struct urb *urb) ...@@ -1829,9 +1828,6 @@ static int uhci_unlink_urb(struct urb *urb)
} else } else
schedule_timeout(1+1*HZ/1000); schedule_timeout(1+1*HZ/1000);
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
uhci_call_completion(urb); uhci_call_completion(urb);
} }
} }
...@@ -1846,10 +1842,6 @@ static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb) ...@@ -1846,10 +1842,6 @@ static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb)
uhci_dec_fsbr(uhci, urb); uhci_dec_fsbr(uhci, urb);
/* There is a race with updating IOC in here, but it's not worth */
/* trying to fix since this is merely an optimization. The only */
/* time we'd lose is if the status of the packet got updated */
/* and we'd be turning on FSBR next frame anyway, so it's a wash */
urbp->fsbr_timeout = 1; urbp->fsbr_timeout = 1;
head = &urbp->td_list; head = &urbp->td_list;
...@@ -2013,23 +2005,23 @@ static void rh_int_timer_do(unsigned long ptr) ...@@ -2013,23 +2005,23 @@ static void rh_int_timer_do(unsigned long ptr)
tmp = head->next; tmp = head->next;
while (tmp != head) { while (tmp != head) {
struct urb *u = list_entry(tmp, struct urb, urb_list); struct urb *u = list_entry(tmp, struct urb, urb_list);
struct urb_priv *urbp = (struct urb_priv *)u->hcpriv; struct urb_priv *up = (struct urb_priv *)u->hcpriv;
tmp = tmp->next; tmp = tmp->next;
spin_lock(&urb->lock); spin_lock(&u->lock);
/* Check if the FSBR timed out */ /* Check if the FSBR timed out */
if (urbp->fsbr && !urbp->fsbr_timeout && time_after_eq(jiffies, urbp->fsbrtime + IDLE_TIMEOUT)) if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
uhci_fsbr_timeout(uhci, u); uhci_fsbr_timeout(uhci, u);
/* Check if the URB timed out */ /* Check if the URB timed out */
if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) { if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
list_del(&u->urb_list); list_del(&u->urb_list);
list_add_tail(&u->urb_list, &list); list_add_tail(&u->urb_list, &list);
} }
spin_unlock(&urb->lock); spin_unlock(&u->lock);
} }
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
...@@ -2202,12 +2194,12 @@ static int rh_submit_urb(struct urb *urb) ...@@ -2202,12 +2194,12 @@ static int rh_submit_urb(struct urb *urb)
OK(0); OK(0);
case RH_PORT_RESET: case RH_PORT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR); SET_RH_PORTSTAT(USBPORTSC_PR);
wait_ms(50); /* USB v1.1 7.1.7.3 */ mdelay(50); /* USB v1.1 7.1.7.3 */
uhci->rh.c_p_r[wIndex - 1] = 1; uhci->rh.c_p_r[wIndex - 1] = 1;
CLR_RH_PORTSTAT(USBPORTSC_PR); CLR_RH_PORTSTAT(USBPORTSC_PR);
udelay(10); udelay(10);
SET_RH_PORTSTAT(USBPORTSC_PE); SET_RH_PORTSTAT(USBPORTSC_PE);
wait_ms(10); mdelay(10);
SET_RH_PORTSTAT(0xa); SET_RH_PORTSTAT(0xa);
OK(0); OK(0);
case RH_PORT_POWER: case RH_PORT_POWER:
...@@ -2724,6 +2716,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io ...@@ -2724,6 +2716,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
} }
uhci->dev = dev; uhci->dev = dev;
uhci->irq = dev->irq;
uhci->io_addr = io_addr; uhci->io_addr = io_addr;
uhci->io_size = io_size; uhci->io_size = io_size;
pci_set_drvdata(dev, uhci); pci_set_drvdata(dev, uhci);
...@@ -2750,6 +2743,11 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io ...@@ -2750,6 +2743,11 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
/* or broken setup */ /* or broken setup */
reset_hc(uhci); reset_hc(uhci);
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
uhci->is_suspended = 0;
spin_lock_init(&uhci->qh_remove_list_lock); spin_lock_init(&uhci->qh_remove_list_lock);
INIT_LIST_HEAD(&uhci->qh_remove_list); INIT_LIST_HEAD(&uhci->qh_remove_list);
...@@ -2932,8 +2930,6 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io ...@@ -2932,8 +2930,6 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci)) if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci))
goto err_request_irq; goto err_request_irq;
uhci->irq = dev->irq;
/* disable legacy emulation */ /* disable legacy emulation */
pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT); pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT);
......
...@@ -287,17 +287,17 @@ struct virt_root_hub { ...@@ -287,17 +287,17 @@ struct virt_root_hub {
struct uhci { struct uhci {
struct pci_dev *dev; struct pci_dev *dev;
#ifdef CONFIG_PROC_FS
/* procfs */ /* procfs */
int num; int num;
struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_entry;
#endif
/* Grabbed from PCI */ /* Grabbed from PCI */
int irq; int irq;
unsigned int io_addr; unsigned int io_addr;
unsigned int io_size; unsigned int io_size;
struct list_head uhci_list;
struct pci_pool *qh_pool; struct pci_pool *qh_pool;
struct pci_pool *td_pool; struct pci_pool *td_pool;
......
...@@ -11,7 +11,7 @@ static __inline__ void uhci_wait_ms(unsigned int ms) ...@@ -11,7 +11,7 @@ static __inline__ void uhci_wait_ms(unsigned int ms)
{ {
if(!in_interrupt()) if(!in_interrupt())
{ {
current->state = TASK_UNINTERRUPTIBLE; set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1 + ms * HZ / 1000); schedule_timeout(1 + ms * HZ / 1000);
} }
else else
......
CONFIG_USB_DC2XX
Say Y here if you want to connect this type of still camera to your
computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
more information; some non-Kodak cameras may also work with this
driver, given application support (such as <http://www.gphoto.org/>).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dc2xx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_MDC800
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
and higher (look at <http://www.gphoto.org/>).
To use it create a device node with "mknod /dev/mustek c 180 32" and
configure it in your software.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called mdc800.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HPUSBSCSI
Say Y here if you want support for the HP 53xx series of scanners
and the Minolta Scan Dual. This driver is experimental.
The scanner will be accessible as a SCSI device.
This can be compiled as a module, called hpusbscsi.o.
CONFIG_USB_MICROTEK
Say Y here if you want support for the Microtek X6USB and
possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
Support for anything but the X6 is experimental.
Please report failures and successes.
The scanner will appear as a scsi generic device to the rest
of the system. Scsi support is required.
This driver can be compiled as a module, called microtek.o.
CONFIG_USB_SCANNER
Say Y here if you want to connect a USB scanner to your computer's
USB port. Please read <file:Documentation/usb/scanner.txt> and
<file:Documentation/usb/scanner-hp-sane.txt> for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called scanner.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HID
Say Y here if you want full HID support to connect keyboards,
mice, joysticks, graphic tablets, or any other HID based devices
to your computer via USB. You also need to select HID Input layer
support (below) if you want to use keyboards, mice, joysticks and
the like.
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
<file:Documentation/input/input.txt>.
If unsure, say Y.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called hid.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HIDINPUT
Say Y here if you want to use a USB keyboard, mouse or joystick,
or any other HID input device. You also need Input layer support,
(CONFIG_INPUT) which you select under "Input core support".
If unsure, say Y.
CONFIG_USB_HIDDEV
Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface
devices, like monitor controls and Uninterruptable Power Supplies.
This module supports these devices separately using a separate
event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
This driver requires CONFIG_USB_HID.
If unsure, say Y.
CONFIG_USB_KBD
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_MOUSE
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbmouse.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_WACOM
Say Y here if you want to use the USB version of the Wacom Intuos
or Graphire tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called wacom.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DABUSB
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
brought to you by the DAB-Team (<http://dab.in.tum.de/>). This
driver can be taken as an example for URB-based bulk, control, and
isochronous transactions. URB's are explained in
<file:Documentation/usb/URB.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dabusb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DSBR
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
you must connect the line out connector to a sound card or a
set of speakers.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dsbr100.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_IBMCAM
Say Y here if you want to connect a IBM "C-It" camera, also known as
"Xirlink PC Camera" to your computer's USB port. For more
information, read <file:Documentation/usb/ibmcam.txt>.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ibmcam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. This
camera has several configuration options which can be specified when
you load the module. Read <file:Documentation/usb/ibmcam.txt> to
learn more.
CONFIG_USB_KONICAWC
Say Y here if you want support for webcams based on a Konica
chipset. This is known to work with the Intel YC76 webcam.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called konicawc.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_OV511
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/ov511.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ov511.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PWC
Say Y or M here if you want to use one of these Philips USB webcams:
PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
by this driver and never will be.
This driver has an optional plugin, which is distributed as a binary
module only. It contains code that allow you to use higher
resolutions and framerates but may not be distributed as source.
But even without this plugin you can these cams for most
applications.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pwc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SE401
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/se401.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called se401.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_STV680
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
See <file:Documentation/usb/stv680.txt> for more information and for
a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called stv680.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_VICAM
Say Y here if you have 3com homeconnect camera (vicam).
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called vicam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUERSWALD
Say Y here if you want to connect an Auerswald USB ISDN Device
to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called auerswald.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_EMI26
This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface.
After firmware load the device is handled with standard linux
USB Audio driver.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RIO500
Say Y here if you want to connect a USB Rio500 mp3 player to your
computer's USB port. Please read <file:Documentation/usb/rio.txt>
for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rio500.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_TIGL
If you own a Texas Instruments graphing calculator and use a
TI-GRAPH LINK USB cable (aka SilverLink), then you might be
interested in this driver.
If you enable this driver, you will be able to communicate with
your calculator through a set of device nodes under /dev.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called tiglusb.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
If you don't know what the SilverLink cable is or what a Texas
Instruments graphing calculator is, then you probably don't need this
driver.
If unsure, say N.
CONFIG_USB_USS720
This driver is for USB parallel port adapters that use the Lucent
Technologies USS-720 chip. These cables are plugged into your USB
port and provide USB compatibility to peripherals designed with
parallel port interfaces.
The chip has two modes: automatic mode and manual mode. In automatic
mode, it looks to the computer like a standard USB printer. Only
printers may be connected to the USS-720 in this mode. The generic
USB printer driver ("USB Printer support", above) may be used in
that mode, and you can say N here if you want to use the chip only
in this mode.
Manual mode is not limited to printers, any parallel port
device should work. This driver utilizes manual mode.
Note however that some operations are three orders of magnitude
slower than on a PCI/ISA Parallel Port, so timing critical
applications might not work.
Say Y here if you own an USS-720 USB->Parport cable and intend to
connect anything other than a printer to it.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called uss720.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
smartBridges smartNIC
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called catc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CDCETHER
This driver supports devices conforming to the Communication Device
Class Ethernet Control Model. This is used in some cable modems.
For more details on the specification, get the Communication Device
Class specification from <http://www.usb.org/>.
This driver should work with the following devices:
* Ericsson PipeRider (all variants)
* Motorola (DM100 and SB4100)
* Broadcom Cable Modem (reference design)
* Toshiba PCX1100U and possibly other cable modems
The device creates a network device (ethX, where X depends on what
other networking devices you have in use), as for a normal PCI
or ISA based ethernet network card.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cdc-ether.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_KAWETH
Say Y here if you want to use one of the following 10Mbps only
USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
3Com 3C19250
ADS USB-10BT
ATEN USB Ethernet
ASANTE USB To Ethernet Adapter
AOX Endpoints USB Ethernet
Correga K.K.
D-Link DSB-650C and DU-E10
Entrega / Portgear E45
I-O DATA USB-ET/T
Jaton USB Ethernet Device Adapter
Kingston Technology USB Ethernet Adapter
Linksys USB10T
Mobility USB-Ethernet Adapter
NetGear EA-101
Peracom Enet and Enet2
Portsmith Express Ethernet Adapter
Shark Pocket Adapter
SMC 2202USB
Sony Vaio port extender
This driver is likely to work with most 10Mbps only USB Ethernet
adapters, including some "no brand" devices. It does NOT work on
SmartBridges smartNIC or on Belkin F5U111 devices - you should use
the CATC NetMate driver for those. If you are not sure which one
you need, select both, and the correct one should be selected for
you.
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called kaweth.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PEGASUS
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
If in doubt then look at linux/drivers/usb/pegasus.h for the complete
list of supported devices.
If your particular adapter is not in the list and you are _sure_ it
is Pegasus or Pegasus II based then send me (petkan@users.sourceforge.net)
vendor and device IDs.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pegasus.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RTL8150
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me (petkan@users.sourceforge.net) any comments you may have.
You can also check for updates at http://pegasus2.sourceforge.net/
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rtl8150.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_USBNET
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
(GeneLink), NetChip and Prolific. Intelligent USB devices could also
use this approach to provide Internet access, using standard USB
cabling. You can find these chips also on some motherboards with
USB PC2PC support.
These links will have names like "usb0", "usb1", etc. They act
like two-node Ethernets, so you can use 802.1d Ethernet Bridging
(CONFIG_BRIDGE) to simplify your network routing.
This code is also available as a kernel module (code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbnet.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
/* /*
* USB Host-to-Host Links * USB Host-to-Host Links
* Copyright (C) 2000-2001 by David Brownell <dbrownell@users.sourceforge.net> * Copyright (C) 2000-2002 by David Brownell <dbrownell@users.sourceforge.net>
*/ */
/* /*
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
* 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info
* and prolific support, isolate net1080-specific bits, cleanup. * and prolific support, isolate net1080-specific bits, cleanup.
* fix unlink_urbs oops in D3 PM resume code path. * fix unlink_urbs oops in D3 PM resume code path.
*
* 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ... * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ...
* 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it; * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it;
* AnchorChips 2720 support (from spec) for testing; * AnchorChips 2720 support (from spec) for testing;
...@@ -83,6 +84,11 @@ ...@@ -83,6 +84,11 @@
* tie mostly to (sub)driver info. Workaround some PL-2302 * tie mostly to (sub)driver info. Workaround some PL-2302
* chips that seem to reject SET_INTERFACE requests. * chips that seem to reject SET_INTERFACE requests.
* *
* 06-apr-2002 Added ethtool support, based on a patch from Brad Hards.
* Level of diagnostics is more configurable; they use device
* location (usb_device->devpath) instead of address (2.5).
* For tx_fixup, memflags can't be NOIO.
*
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
#include <linux/config.h> #include <linux/config.h>
...@@ -93,6 +99,8 @@ ...@@ -93,6 +99,8 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
// #define DEBUG // error path messages, extra info // #define DEBUG // error path messages, extra info
...@@ -113,6 +121,8 @@ ...@@ -113,6 +121,8 @@
#define CONFIG_USB_PL2301 #define CONFIG_USB_PL2301
#define DRIVER_VERSION "06-Apr-2002"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
...@@ -164,6 +174,7 @@ struct usbnet { ...@@ -164,6 +174,7 @@ struct usbnet {
// protocol/interface state // protocol/interface state
struct net_device net; struct net_device net;
struct net_device_stats stats; struct net_device_stats stats;
int msg_level;
#ifdef CONFIG_USB_NET1080 #ifdef CONFIG_USB_NET1080
u16 packet_id; u16 packet_id;
...@@ -224,6 +235,13 @@ struct skb_data { // skb->cb is one of these ...@@ -224,6 +235,13 @@ struct skb_data { // skb->cb is one of these
size_t length; size_t length;
}; };
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
static int msg_level = 1;
MODULE_PARM (msg_level, "i");
MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
#define mutex_lock(x) down(x) #define mutex_lock(x) down(x)
#define mutex_unlock(x) up(x) #define mutex_unlock(x) up(x)
...@@ -241,7 +259,9 @@ struct skb_data { // skb->cb is one of these ...@@ -241,7 +259,9 @@ struct skb_data { // skb->cb is one of these
#endif #endif
#define devinfo(usbnet, fmt, arg...) \ #define devinfo(usbnet, fmt, arg...) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg) do { if ((usbnet)->msg_level >= 1) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg); \
} while (0)
#ifdef CONFIG_USB_AN2720 #ifdef CONFIG_USB_AN2720
...@@ -948,10 +968,11 @@ static int net1080_reset (struct usbnet *dev) ...@@ -948,10 +968,11 @@ static int net1080_reset (struct usbnet *dev)
MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) ); MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS); dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS);
devdbg (dev, "port %c, peer %sconnected", if (dev->msg_level >= 2)
(status & STATUS_PORT_A) ? 'A' : 'B', devinfo (dev, "port %c, peer %sconnected",
(status & STATUS_CONN_OTHER) ? "" : "dis" (status & STATUS_PORT_A) ? 'A' : 'B',
); (status & STATUS_CONN_OTHER) ? "" : "dis"
);
retval = 0; retval = 0;
done: done:
...@@ -1441,10 +1462,11 @@ static int usbnet_stop (struct net_device *net) ...@@ -1441,10 +1462,11 @@ static int usbnet_stop (struct net_device *net)
mutex_lock (&dev->mutex); mutex_lock (&dev->mutex);
netif_stop_queue (net); netif_stop_queue (net);
devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", if (dev->msg_level >= 2)
dev->stats.rx_packets, dev->stats.tx_packets, devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
dev->stats.rx_errors, dev->stats.tx_errors dev->stats.rx_packets, dev->stats.tx_packets,
); dev->stats.rx_errors, dev->stats.tx_errors
);
// ensure there are no more active urbs // ensure there are no more active urbs
add_wait_queue (&unlink_wakeup, &wait); add_wait_queue (&unlink_wakeup, &wait);
...@@ -1482,9 +1504,10 @@ static int usbnet_open (struct net_device *net) ...@@ -1482,9 +1504,10 @@ static int usbnet_open (struct net_device *net)
// put into "known safe" state // put into "known safe" state
if (info->reset && (retval = info->reset (dev)) < 0) { if (info->reset && (retval = info->reset (dev)) < 0) {
devinfo (dev, "open reset fail (%d) usbnet %03d/%03d, %s", devinfo (dev, "open reset fail (%d) usbnet bus%d%s, %s",
retval, retval,
dev->udev->bus->busnum, dev->udev->devnum, // FIXME busnum is unstable
dev->udev->bus->busnum, dev->udev->devpath,
info->description); info->description);
goto done; goto done;
} }
...@@ -1496,14 +1519,16 @@ static int usbnet_open (struct net_device *net) ...@@ -1496,14 +1519,16 @@ static int usbnet_open (struct net_device *net)
} }
netif_start_queue (net); netif_start_queue (net);
devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing", if (dev->msg_level >= 2)
RX_QLEN, TX_QLEN, dev->net.mtu, devinfo (dev, "open: enable queueing "
(info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL)) "(rx %d, tx %d) mtu %d %s framing",
? ((info->flags & FLAG_FRAMING_NC) RX_QLEN, TX_QLEN, dev->net.mtu,
? "NetChip" (info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
: "GeneSys") ? ((info->flags & FLAG_FRAMING_NC)
: "raw" ? "NetChip"
); : "GeneSys")
: "raw"
);
// delay posting reads until we're fully open // delay posting reads until we're fully open
tasklet_schedule (&dev->bh); tasklet_schedule (&dev->bh);
...@@ -1514,6 +1539,80 @@ static int usbnet_open (struct net_device *net) ...@@ -1514,6 +1539,80 @@ static int usbnet_open (struct net_device *net)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int usbnet_ethtool_ioctl (struct net_device *net, void *useraddr)
{
struct usbnet *dev = (struct usbnet *) net->priv;
u32 cmd;
if (get_user (cmd, (u32 *)useraddr))
return -EFAULT;
switch (cmd) {
case ETHTOOL_GDRVINFO: { /* get driver info */
struct ethtool_drvinfo info;
memset (&info, 0, sizeof info);
info.cmd = ETHTOOL_GDRVINFO;
strncpy (info.driver, driver_name, sizeof info.driver);
strncpy (info.version, DRIVER_VERSION, sizeof info.version);
strncpy (info.fw_version, dev->driver_info->description,
sizeof info.fw_version);
snprintf (info.bus_info, sizeof info.bus_info, "USB bus%d%s",
/* FIXME busnums are bogus/unstable IDs */
dev->udev->bus->busnum, dev->udev->devpath);
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
case ETHTOOL_GLINK: /* get link status */
if (dev->driver_info->check_connect) {
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = dev->driver_info->check_connect (dev);
if (copy_to_user (useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
break;
case ETHTOOL_GMSGLVL: { /* get message-level */
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = dev->msg_level;
if (copy_to_user (useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
case ETHTOOL_SMSGLVL: { /* set message-level */
struct ethtool_value edata;
if (copy_from_user (&edata, useraddr, sizeof (edata)))
return -EFAULT;
dev->msg_level = edata.data;
return 0;
}
/* could also map RINGPARAM to RX/TX QLEN */
}
/* Note that the ethtool user space code requires EOPNOTSUPP */
return -EOPNOTSUPP;
}
static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
return usbnet_ethtool_ioctl (net, (void *)rq->ifr_data);
default:
return -EOPNOTSUPP;
}
}
/*-------------------------------------------------------------------------*/
/* usb_clear_halt cannot be called in interrupt context */ /* usb_clear_halt cannot be called in interrupt context */
static void static void
...@@ -1576,12 +1675,10 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) ...@@ -1576,12 +1675,10 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
struct nc_trailer *trailer = 0; struct nc_trailer *trailer = 0;
#endif /* CONFIG_USB_NET1080 */ #endif /* CONFIG_USB_NET1080 */
flags = in_interrupt () ? GFP_ATOMIC : GFP_NOIO; /* might be used for nfs */
// some devices want funky USB-level framing, for // some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks // win32 driver (usually) and/or hardware quirks
if (info->tx_fixup) { if (info->tx_fixup) {
skb = info->tx_fixup (dev, skb, flags); skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) { if (!skb) {
dbg ("can't tx_fixup skb"); dbg ("can't tx_fixup skb");
goto drop; goto drop;
...@@ -1750,8 +1847,9 @@ static void usbnet_disconnect (struct usb_device *udev, void *ptr) ...@@ -1750,8 +1847,9 @@ static void usbnet_disconnect (struct usb_device *udev, void *ptr)
{ {
struct usbnet *dev = (struct usbnet *) ptr; struct usbnet *dev = (struct usbnet *) ptr;
devinfo (dev, "unregister usbnet %03d/%03d, %s", devinfo (dev, "unregister usbnet bus%d%s, %s",
udev->bus->busnum, udev->devnum, // FIXME busnum is unstable
udev->bus->busnum, udev->devpath,
dev->driver_info->description); dev->driver_info->description);
unregister_netdev (&dev->net); unregister_netdev (&dev->net);
...@@ -1811,6 +1909,7 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum, ...@@ -1811,6 +1909,7 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum,
usb_inc_dev_use (udev); usb_inc_dev_use (udev);
dev->udev = udev; dev->udev = udev;
dev->driver_info = info; dev->driver_info = info;
dev->msg_level = msg_level;
INIT_LIST_HEAD (&dev->dev_list); INIT_LIST_HEAD (&dev->dev_list);
skb_queue_head_init (&dev->rxq); skb_queue_head_init (&dev->rxq);
skb_queue_head_init (&dev->txq); skb_queue_head_init (&dev->txq);
...@@ -1836,10 +1935,12 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum, ...@@ -1836,10 +1935,12 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum,
net->stop = usbnet_stop; net->stop = usbnet_stop;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
net->tx_timeout = usbnet_tx_timeout; net->tx_timeout = usbnet_tx_timeout;
net->do_ioctl = usbnet_ioctl;
register_netdev (&dev->net); register_netdev (&dev->net);
devinfo (dev, "register usbnet %03d/%03d, %s", devinfo (dev, "register usbnet bus%d%s, %s",
udev->bus->busnum, udev->devnum, // FIXME busnum is unstable
udev->bus->busnum, udev->devpath,
dev->driver_info->description); dev->driver_info->description);
// ok, it's ready to go. // ok, it's ready to go.
...@@ -1936,7 +2037,7 @@ static const struct usb_device_id products [] = { ...@@ -1936,7 +2037,7 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE (usb, products); MODULE_DEVICE_TABLE (usb, products);
static struct usb_driver usbnet_driver = { static struct usb_driver usbnet_driver = {
name: "usbnet", name: driver_name,
id_table: products, id_table: products,
probe: usbnet_probe, probe: usbnet_probe,
disconnect: usbnet_disconnect, disconnect: usbnet_disconnect,
......
...@@ -305,6 +305,7 @@ struct usb_qualifier_descriptor { ...@@ -305,6 +305,7 @@ struct usb_qualifier_descriptor {
} __attribute__ ((packed)); } __attribute__ ((packed));
/* helpers for driver access to descriptors */ /* helpers for driver access to descriptors */
extern int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum);
extern struct usb_interface * extern struct usb_interface *
usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
extern struct usb_endpoint_descriptor * extern struct usb_endpoint_descriptor *
...@@ -470,8 +471,10 @@ struct usb_device_id { ...@@ -470,8 +471,10 @@ struct usb_device_id {
/** /**
* struct usb_driver - identifies USB driver to usbcore * struct usb_driver - identifies USB driver to usbcore
* @owner: pointer to the module owner of this driver * @owner: Pointer to the module owner of this driver; initialize
* @name: The driver name should be unique among USB drivers * it using THIS_MODULE.
* @name: The driver name should be unique among USB drivers,
* 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. The probe routine returns a handle that
* will later be provided to disconnect(), or a null pointer to * will later be provided to disconnect(), or a null pointer to
...@@ -506,7 +509,7 @@ struct usb_device_id { ...@@ -506,7 +509,7 @@ struct usb_device_id {
* is used by both user and kernel mode hotplugging support. * is used by both user and kernel mode hotplugging support.
* *
* The probe() and disconnect() methods are called in a context where * The probe() and disconnect() methods are called in a context where
* they can sleep, but they should avoid abusing the privilage. Most * they can sleep, but they should avoid abusing the privilege. Most
* work to connect to a device should be done when the device is opened, * work to connect to a device should be done when the device is opened,
* and undone at the last close. The disconnect code needs to address * and undone at the last close. The disconnect code needs to address
* concurrency issues with respect to open() and close() methods, as * concurrency issues with respect to open() and close() methods, as
...@@ -959,24 +962,6 @@ struct usb_tt { ...@@ -959,24 +962,6 @@ struct usb_tt {
}; };
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *);
extern void usb_free_dev(struct usb_device *);
extern int usb_new_device(struct usb_device *dev);
extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
#ifndef _LINUX_HUB_H
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
#endif /* _LINUX_HUB_H */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* This is arbitrary. /* This is arbitrary.
...@@ -1047,11 +1032,52 @@ extern int usb_reset_device(struct usb_device *dev); ...@@ -1047,11 +1032,52 @@ extern int usb_reset_device(struct usb_device *dev);
/* for drivers using iso endpoints */ /* for drivers using iso endpoints */
extern int usb_get_current_frame_number (struct usb_device *usb_dev); extern int usb_get_current_frame_number (struct usb_device *usb_dev);
/* drivers must track when they bind to a device's interfaces */ /**
extern void usb_inc_dev_use(struct usb_device *); * usb_inc_dev_use - record another reference to a device
#define usb_dec_dev_use usb_free_dev * @dev: the device being referenced
*
* Each live reference to a device should be refcounted.
*
* Drivers for USB interfaces should normally record such references in
* their probe() methods, when they bind to an interface, and release
* them usb_dec_dev_use(), in their disconnect() methods.
*/
static inline void usb_inc_dev_use (struct usb_device *dev)
{
atomic_inc (&dev->refcnt);
}
/**
* usb_dec_dev_use - drop a reference to a device
* @dev: the device no longer being referenced
*
* Each live reference to a device should be refcounted.
*
* Drivers for USB interfaces should normally release such references in
* their disconnect() methods, and record them in probe().
*
* Note that driver disconnect() methods must guarantee that when they
* return, all of their outstanding references to the device (and its
* interfaces) are cleaned up. That means that all pending URBs from
* this driver must have completed, and that no more copies of the device
* handle are saved in driver records (including other kernel threads).
*/
static inline void usb_dec_dev_use (struct usb_device *dev)
{
if (atomic_dec_and_test (&dev->refcnt)) {
/* May only go to zero when usbcore finishes
* usb_disconnect() processing: khubd or HCDs.
*
* If you hit this BUG() it's likely a problem
* with some driver's disconnect() routine.
*/
BUG ();
}
}
/* used these for multi-interface device registration */ /* used these for multi-interface device registration */
extern int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned int ifnum);
extern void usb_driver_claim_interface(struct usb_driver *driver, extern void usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void* priv); struct usb_interface *iface, void* priv);
extern int usb_interface_claimed(struct usb_interface *iface); extern int usb_interface_claimed(struct usb_interface *iface);
......
...@@ -142,6 +142,8 @@ struct usbdevfs_hub_portinfo { ...@@ -142,6 +142,8 @@ struct usbdevfs_hub_portinfo {
#define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo) #define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
#define USBDEVFS_RESET _IO('U', 20) #define USBDEVFS_RESET _IO('U', 20)
#define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int) #define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define USBDEVFS_DISCONNECT _IO('U', 22)
#define USBDEVFS_CONNECT _IO('U', 23)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
......
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