Commit 29b78b5a authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

This is another USB API cleanup patch. It's against 2.5.5:

  
    - Moves 8 functions from usb.[hc] to hcd.[hc]
    - Also moves some data structures and types
    - Now usbdevfs and "old" HCDs #include "hcd.h"
    - Minor tweaks to the "hcd" layer (one less FIXME)
    - Minor kernel doc and comment cleanups
  
Basically this continues moving the HCD-only functionality
out of the way of normal USB device drivers.  Converging
"usb_bus" and "usb_hcd" (later!) will be a bit easier too.

I did basic sanity tests, there's little to break ... :)
  
There are still a few functions in usb.c that aren't for
general driver use.  They're mostly for enumeration,
in areas where the hub driver and HCD root hubs
need to do various kinds of magic.  It wasn't clear
how to decouple those, they can certainly wait.
parent 6d3d01de
......@@ -4,8 +4,6 @@
* (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
* (C) Copyright 1999 Deti Fliegl (new USB architecture)
*
* $id$
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
......@@ -61,6 +59,8 @@
#include <linux/usbdevice_fs.h>
#include <asm/uaccess.h>
#include "hcd.h"
#define MAX_TOPO_LEVEL 6
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
......@@ -429,6 +429,10 @@ static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes
* count = device count at this level
*/
/* If this is the root hub, display the bandwidth information */
/* FIXME high speed reserves 20% frametime for non-periodic,
* while full/low speed reserves only 10% ... so this is wrong
* for high speed busses. also, change how bandwidth is recorded.
*/
if (level == 0)
data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
FRAME_TIME_MAX_USECS_ALLOC,
......
/*
* Copyright (c) 2001 by David Brownell
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2002
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
......@@ -33,9 +39,6 @@
#include <linux/interrupt.h>
#include <linux/uts.h> /* for UTS_SYSNAME */
#ifndef CONFIG_USB_DEBUG
#define CONFIG_USB_DEBUG /* this is experimental! */
#endif
#ifdef CONFIG_USB_DEBUG
#define DEBUG
......@@ -53,6 +56,8 @@
#include <asm/byteorder.h>
// #define USB_BANDWIDTH_MESSAGES
/*-------------------------------------------------------------------------*/
/*
......@@ -78,19 +83,28 @@
* usb client device drivers.
*
* Contributors of ideas or unattributed patches include: David Brownell,
* Roman Weissgaerber, Rory Bolt, ...
* Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ...
*
* HISTORY:
* 2002-02-21 Pull in most of the usb_bus support from usb.c; some
* associated cleanup. "usb_hcd" still != "usb_bus".
* 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
*/
/*-------------------------------------------------------------------------*/
/* host controllers we manage */
static LIST_HEAD (hcd_list);
LIST_HEAD (usb_bus_list);
/* used when allocating bus numbers */
#define USB_MAXBUS 64
struct usb_busmap {
unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
};
static struct usb_busmap busmap;
/* used when updating list of hcds */
static DECLARE_MUTEX (hcd_list_lock);
DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
/* used when updating hcd data */
static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
......@@ -105,6 +119,9 @@ static struct usb_operations hcd_operations;
/*-------------------------------------------------------------------------*/
#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff)
#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff)
/* usb 2.0 root hub device descriptor */
static const u8 usb2_rh_dev_descriptor [18] = {
0x12, /* __u8 bLength; */
......@@ -118,7 +135,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
0x00, 0x00, /* __u16 idVendor; */
0x00, 0x00, /* __u16 idProduct; */
0x40, 0x02, /* __u16 bcdDevice; (v2.4) */
KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */
0x03, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
......@@ -141,7 +158,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {
0x00, 0x00, /* __u16 idVendor; */
0x00, 0x00, /* __u16 idProduct; */
0x40, 0x02, /* __u16 bcdDevice; (v2.4) */
KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */
0x03, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
......@@ -504,6 +521,346 @@ static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
usb_hcd_giveback_urb (hcd, urb);
}
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
void usb_bus_get (struct usb_bus *bus)
{
atomic_inc (&bus->refcnt);
}
/* exported only within usbcore */
void usb_bus_put (struct usb_bus *bus)
{
if (atomic_dec_and_test (&bus->refcnt))
kfree (bus);
}
/*-------------------------------------------------------------------------*/
/* shared initialization code */
static void usb_init_bus (struct usb_bus *bus)
{
memset (&bus->devmap, 0, sizeof(struct usb_devmap));
#ifdef DEVNUM_ROUND_ROBIN
bus->devnum_next = 1;
#endif /* DEVNUM_ROUND_ROBIN */
bus->root_hub = NULL;
bus->hcpriv = NULL;
bus->busnum = -1;
bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list);
atomic_set (&bus->refcnt, 1);
}
/**
* usb_alloc_bus - creates a new USB host controller structure
* @op: pointer to a struct usb_operations that this bus structure should use
* Context: !in_interrupt()
*
* Creates a USB host controller bus structure with the specified
* usb_operations and initializes all the necessary internal objects.
*
* If no memory is available, NULL is returned.
*
* The caller should call usb_free_bus() when it is finished with the structure.
*/
struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{
struct usb_bus *bus;
bus = kmalloc (sizeof *bus, GFP_KERNEL);
if (!bus)
return NULL;
usb_init_bus (bus);
bus->op = op;
return bus;
}
EXPORT_SYMBOL (usb_alloc_bus);
/**
* usb_free_bus - frees the memory used by a bus structure
* @bus: pointer to the bus to free
*
* To be invoked by a HCD, only as the last step of decoupling from
* hardware. It is an error to call this if the reference count is
* anything but one. That would indicate that some system component
* did not correctly shut down, and thought the hardware was still
* accessible.
*/
void usb_free_bus (struct usb_bus *bus)
{
if (!bus)
return;
if (atomic_read (&bus->refcnt) != 1)
err ("usb_free_bus #%d, count != 1", bus->busnum);
usb_bus_put (bus);
}
EXPORT_SYMBOL (usb_free_bus);
/*-------------------------------------------------------------------------*/
/**
* usb_register_bus - registers the USB host controller with the usb core
* @bus: pointer to the bus to register
* Context: !in_interrupt()
*
* Assigns a bus number, and links the controller into usbcore data
* structures so that it can be seen by scanning the bus list.
*/
void usb_register_bus(struct usb_bus *bus)
{
int busnum;
down (&usb_bus_list_lock);
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
if (busnum < USB_MAXBUS) {
set_bit (busnum, busmap.busmap);
bus->busnum = busnum;
} else
warn ("too many buses");
usb_bus_get (bus);
/* Add it to the list of buses */
list_add (&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock);
usbfs_add_bus (bus);
info ("new USB bus registered, assigned bus number %d", bus->busnum);
}
EXPORT_SYMBOL (usb_register_bus);
/**
* usb_deregister_bus - deregisters the USB host controller
* @bus: pointer to the bus to deregister
* Context: !in_interrupt()
*
* Recycles the bus number, and unlinks the controller from usbcore data
* structures so that it won't be seen by scanning the bus list.
*/
void usb_deregister_bus (struct usb_bus *bus)
{
info ("USB bus %d deregistered", bus->busnum);
/*
* NOTE: make sure that all the devices are removed by the
* controller code, as well as having it call this when cleaning
* itself up
*/
down (&usb_bus_list_lock);
list_del (&bus->bus_list);
up (&usb_bus_list_lock);
usbfs_remove_bus (bus);
clear_bit (bus->busnum, busmap.busmap);
usb_bus_put (bus);
}
EXPORT_SYMBOL (usb_deregister_bus);
/**
* usb_register_root_hub - called by HCD to register its root hub
* @usb_dev: the usb root hub device to be registered.
* @parent_dev: the parent device of this root hub.
*
* The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in
* the driverfs tree, and then calls usb_new_device() to register the
* usb device.
*/
int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
{
int retval;
usb_dev->dev.parent = parent_dev;
strcpy (&usb_dev->dev.name[0], "usb_name");
strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
retval = usb_new_device (usb_dev);
if (retval)
put_device (&usb_dev->dev);
return retval;
}
EXPORT_SYMBOL (usb_register_root_hub);
/*-------------------------------------------------------------------------*/
/*
* usb_calc_bus_time:
* Returns approximate bus time in nanoseconds for a periodic transaction.
* See USB 2.0 spec section 5.11.3
*/
static long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)
{
unsigned long tmp;
switch (speed) {
case USB_SPEED_LOW: /* INTR only */
if (is_input) {
tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
} else {
tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
}
case USB_SPEED_FULL: /* ISOC or INTR */
if (isoc) {
tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
} else {
tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (9107L + BW_HOST_DELAY + tmp);
}
case USB_SPEED_HIGH: /* ISOC or INTR */
// FIXME merge from EHCI code; caller will need to handle
// each part of a split separately.
return 0;
default:
dbg ("bogus device speed!");
return -1;
}
}
/*
* usb_check_bandwidth():
*
* old_alloc is from host_controller->bandwidth_allocated in microseconds;
* bustime is from calc_bus_time(), but converted to microseconds.
*
* returns <bustime in us> if successful,
* or -ENOSPC if bandwidth request fails.
*
* FIXME:
* This initial implementation does not use Endpoint.bInterval
* in managing bandwidth allocation.
* It probably needs to be expanded to use Endpoint.bInterval.
* This can be done as a later enhancement (correction).
*
* This will also probably require some kind of
* frame allocation tracking...meaning, for example,
* that if multiple drivers request interrupts every 10 USB frames,
* they don't all have to be allocated at
* frame numbers N, N+10, N+20, etc. Some of them could be at
* N+11, N+21, N+31, etc., and others at
* N+12, N+22, N+32, etc.
*
* Similarly for isochronous transfers...
*
* Individual HCDs can schedule more directly ... this logic
* is not correct for high speed transfers.
*/
int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
{
unsigned int pipe = urb->pipe;
long bustime;
int is_in = usb_pipein (pipe);
int is_iso = usb_pipeisoc (pipe);
int old_alloc = dev->bus->bandwidth_allocated;
int new_alloc;
bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso,
usb_maxpacket (dev, pipe, !is_in)));
if (is_iso)
bustime /= urb->number_of_packets;
new_alloc = old_alloc + (int) bustime;
if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) {
#ifdef DEBUG
char *mode =
#ifdef CONFIG_USB_BANDWIDTH
"";
#else
"would have ";
#endif
dbg ("usb_check_bandwidth %sFAILED: %d + %ld = %d usec",
mode, old_alloc, bustime, new_alloc);
#endif
#ifdef CONFIG_USB_BANDWIDTH
bustime = -ENOSPC; /* report error */
#endif
}
return bustime;
}
EXPORT_SYMBOL (usb_check_bandwidth);
/**
* usb_claim_bandwidth - records bandwidth for a periodic transfer
* @dev: source/target of request
* @urb: request (urb->dev == dev)
* @bustime: bandwidth consumed, in (average) microseconds per frame
* @isoc: true iff the request is isochronous
*
* Bus bandwidth reservations are recorded purely for diagnostic purposes.
* HCDs are expected not to overcommit periodic bandwidth, and to record such
* reservations whenever endpoints are added to the periodic schedule.
*
* FIXME averaging per-frame is suboptimal. Better to sum over the HCD's
* entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable
* for EHCI (256/512/1024 frames, default 1024) and have the bus expose how
* large its periodic schedule is.
*/
void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
{
dev->bus->bandwidth_allocated += bustime;
if (isoc)
dev->bus->bandwidth_isoc_reqs++;
else
dev->bus->bandwidth_int_reqs++;
urb->bandwidth = bustime;
#ifdef USB_BANDWIDTH_MESSAGES
dbg ("bandwidth alloc increased by %d (%s) to %d for %d requesters",
bustime,
isoc ? "ISOC" : "INTR",
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
#endif
}
EXPORT_SYMBOL (usb_claim_bandwidth);
/**
* usb_release_bandwidth - reverses effect of usb_claim_bandwidth()
* @dev: source/target of request
* @urb: request (urb->dev == dev)
* @isoc: true iff the request is isochronous
*
* This records that previously allocated bandwidth has been released.
* Bandwidth is released when endpoints are removed from the host controller's
* periodic schedule.
*/
void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc)
{
dev->bus->bandwidth_allocated -= urb->bandwidth;
if (isoc)
dev->bus->bandwidth_isoc_reqs--;
else
dev->bus->bandwidth_int_reqs--;
#ifdef USB_BANDWIDTH_MESSAGES
dbg ("bandwidth alloc reduced by %d (%s) to %d for %d requesters",
urb->bandwidth,
isoc ? "ISOC" : "INTR",
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
#endif
urb->bandwidth = 0;
}
EXPORT_SYMBOL (usb_release_bandwidth);
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PCI
......@@ -522,6 +879,7 @@ static void hc_died (struct usb_hcd *hcd);
* usb_hcd_pci_probe - initialize PCI-based HCDs
* @dev: USB Host Controller being probed
* @id: pci hotplug id connecting controller to HCD framework
* Context: !in_interrupt()
*
* Allocates basic PCI resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
......@@ -535,7 +893,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
unsigned long resource, len;
void *base;
u8 latency, limit;
struct usb_bus *bus;
struct usb_hcd *hcd;
int retval, region;
char buf [8], *bufp = buf;
......@@ -631,7 +988,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
!= 0) {
err ("request interrupt %s failed", bufp);
retval = -EBUSY;
clean_3:
driver->hcd_free (hcd);
goto clean_2;
}
......@@ -643,26 +999,15 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
base);
// FIXME simpler: make "bus" be that data, not pointer to it.
bus = usb_alloc_bus (&hcd_operations);
if (bus == NULL) {
dbg ("usb_alloc_bus fail");
retval = -ENOMEM;
free_irq (dev->irq, hcd);
goto clean_3;
}
hcd->bus = bus;
usb_init_bus (&hcd->self);
hcd->self.op = &hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->bus = &hcd->self;
hcd->bus_name = dev->slot_name;
bus->hcpriv = (void *) hcd;
INIT_LIST_HEAD (&hcd->dev_list);
INIT_LIST_HEAD (&hcd->hcd_list);
down (&hcd_list_lock);
list_add (&hcd->hcd_list, &hcd_list);
up (&hcd_list_lock);
usb_register_bus (bus);
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
usb_hcd_pci_remove (dev);
......@@ -678,6 +1023,7 @@ EXPORT_SYMBOL (usb_hcd_pci_probe);
/**
* usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
* @dev: USB Host Controller being removed
* Context: !in_interrupt()
*
* Reverses the effect of usb_hcd_pci_probe(), first invoking
* the HCD's stop() method. It is always called from a thread
......@@ -717,12 +1063,9 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
pci_resource_len (dev, hcd->region));
}
down (&hcd_list_lock);
list_del (&hcd->hcd_list);
up (&hcd_list_lock);
usb_deregister_bus (hcd->bus);
usb_free_bus (hcd->bus);
if (atomic_read (&hcd->self.refcnt) != 1)
err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name);
hcd->bus = NULL;
hcd->driver->hcd_free (hcd);
......@@ -1257,6 +1600,7 @@ static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
* usb_hcd_giveback_urb - return URB from HCD to device driver
* @hcd: host controller returning the URB
* @urb: urb being returned to the USB device driver.
* Context: in_interrupt()
*
* This hands the URB from HCD to its USB device driver, using its
* completion function. The HCD has freed all per-urb resources
......@@ -1279,16 +1623,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
struct usb_device *dev;
/* Release periodic transfer bandwidth */
if (urb->bandwidth) {
switch (usb_pipetype (urb->pipe)) {
case PIPE_INTERRUPT:
usb_release_bandwidth (urb->dev, urb, 0);
break;
case PIPE_ISOCHRONOUS:
usb_release_bandwidth (urb->dev, urb, 1);
break;
}
}
if (urb->bandwidth)
usb_release_bandwidth (urb->dev, urb,
usb_pipeisoc (urb->pipe));
/* clear all state linking urb to this dev (and hcd) */
......
/*
* Copyright (c) 2001 by David Brownell
*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
......@@ -17,6 +17,8 @@
*/
#ifdef __KERNEL__
/*-------------------------------------------------------------------------*/
/*
......@@ -33,8 +35,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
/*
* housekeeping
*/
struct usb_bus *bus; /* hcd is-a bus */
struct list_head hcd_list;
struct usb_bus *bus; /* FIXME only use "self" */
struct usb_bus self; /* hcd is-a bus */
const char *bus_name;
......@@ -98,6 +100,19 @@ struct hcd_timeout { /* timeouts we allocate */
/*-------------------------------------------------------------------------*/
/*
* FIXME usb_operations should vanish or become hc_driver,
* when usb_bus and usb_hcd become the same thing.
*/
struct usb_operations {
int (*allocate)(struct usb_device *);
int (*deallocate)(struct usb_device *);
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, int mem_flags);
int (*unlink_urb) (struct urb *urb);
};
/* each driver provides one of these, and hardware init support */
struct hc_driver {
......@@ -126,8 +141,6 @@ struct hc_driver {
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
// FIXME: rework generic-to-specific HCD linkage (specific contains generic)
/* memory lifecycle */
struct usb_hcd *(*hcd_alloc) (void);
void (*hcd_free) (struct usb_hcd *hcd);
......@@ -152,7 +165,8 @@ struct hc_driver {
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
extern int usb_hcd_pci_probe (struct pci_dev *dev,
const struct pci_device_id *id);
extern void usb_hcd_pci_remove (struct pci_dev *dev);
......@@ -204,6 +218,59 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev);
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
/*-------------------------------------------------------------------------*/
/*
* Generic bandwidth allocation constants/support
*/
#define FRAME_TIME_USECS 1000L
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
/* Trying not to use worst-case bit-stuffing
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
/* bytecount = data payload byte count */
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
/* convert & round nanoseconds to microseconds */
extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
int bustime, int isoc);
extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
int isoc);
/*
* Full/low speed bandwidth allocation constants/support.
*/
#define BW_HOST_DELAY 1000L /* nanoseconds */
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
/* 4 full-speed bit times (est.) */
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
/*-------------------------------------------------------------------------*/
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
extern void usb_free_bus (struct usb_bus *);
extern void usb_register_bus (struct usb_bus *);
extern void usb_deregister_bus (struct usb_bus *);
extern int usb_register_root_hub (struct usb_device *usb_dev,
struct device *parent_dev);
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock;
extern void usb_bus_get (struct usb_bus *bus);
extern void usb_bus_put (struct usb_bus *bus);
/*-------------------------------------------------------------------------*/
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
......@@ -217,3 +284,7 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev);
#define RUN_CONTEXT (in_irq () ? "in_irq" \
: (in_interrupt () ? "in_interrupt" : "can sleep"))
#endif /* __KERNEL__ */
......@@ -73,6 +73,7 @@
#define OHCI_USE_NPS // force NoPowerSwitching mode
// #define OHCI_VERBOSE_DEBUG /* not always helpful */
#include "hcd.h"
#include "usb-ohci.h"
......
......@@ -57,6 +57,7 @@
#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "hcd.h"
#include "usb-uhci.h"
#include "usb-uhci-debug.h"
......
......@@ -40,12 +40,7 @@
#endif
#include <linux/usb.h>
static const int usb_bandwidth_option =
#ifdef CONFIG_USB_BANDWIDTH
1;
#else
0;
#endif
#include "hcd.h"
extern int usb_hub_init(void);
extern void usb_hub_cleanup(void);
......@@ -61,13 +56,9 @@ static void usb_check_support(struct usb_device *);
* We have a per-interface "registered driver" list.
*/
LIST_HEAD(usb_driver_list);
LIST_HEAD(usb_bus_list);
struct semaphore usb_bus_list_lock;
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usb_busmap busmap;
static struct usb_driver *usb_minors[16];
/**
......@@ -105,6 +96,7 @@ int usb_register(struct usb_driver *new_driver)
/**
* usb_scan_devices - scans all unclaimed USB interfaces
* Context: !in_interrupt ()
*
* Goes through all unclaimed USB interfaces, and offers them to all
* registered USB drivers through the 'probe' function.
......@@ -173,6 +165,7 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
/**
* usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister
* Context: !in_interrupt ()
*
* Unlinks the specified driver from the internal USB driver list.
*/
......@@ -257,259 +250,6 @@ struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, uns
return NULL;
}
/*
* usb_calc_bus_time:
*
* returns (approximate) USB bus time in nanoseconds for a USB transaction.
*/
static long usb_calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount)
{
unsigned long tmp;
if (low_speed) /* no isoc. here */
{
if (input_dir)
{
tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
}
else
{
tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
}
}
/* for full-speed: */
if (!isoc) /* Input or Output */
{
tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (9107L + BW_HOST_DELAY + tmp);
} /* end not Isoc */
/* for isoc: */
tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
}
/*
* usb_check_bandwidth():
*
* old_alloc is from host_controller->bandwidth_allocated in microseconds;
* bustime is from calc_bus_time(), but converted to microseconds.
*
* returns <bustime in us> if successful,
* or -ENOSPC if bandwidth request fails.
*
* FIXME:
* This initial implementation does not use Endpoint.bInterval
* in managing bandwidth allocation.
* It probably needs to be expanded to use Endpoint.bInterval.
* This can be done as a later enhancement (correction).
* This will also probably require some kind of
* frame allocation tracking...meaning, for example,
* that if multiple drivers request interrupts every 10 USB frames,
* they don't all have to be allocated at
* frame numbers N, N+10, N+20, etc. Some of them could be at
* N+11, N+21, N+31, etc., and others at
* N+12, N+22, N+32, etc.
* However, this first cut at USB bandwidth allocation does not
* contain any frame allocation tracking.
*/
int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
{
int new_alloc;
int old_alloc = dev->bus->bandwidth_allocated;
unsigned int pipe = urb->pipe;
long bustime;
bustime = usb_calc_bus_time (dev->speed == USB_SPEED_LOW,
usb_pipein(pipe), usb_pipeisoc(pipe),
usb_maxpacket(dev, pipe, usb_pipeout(pipe)));
if (usb_pipeisoc(pipe))
bustime = NS_TO_US(bustime) / urb->number_of_packets;
else
bustime = NS_TO_US(bustime);
new_alloc = old_alloc + (int)bustime;
/* what new total allocated bus time would be */
if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC)
dbg("usb-check-bandwidth %sFAILED: was %u, would be %u, bustime = %ld us",
usb_bandwidth_option ? "" : "would have ",
old_alloc, new_alloc, bustime);
if (!usb_bandwidth_option) /* don't enforce it */
return (bustime);
return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : -ENOSPC;
}
void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
{
dev->bus->bandwidth_allocated += bustime;
if (isoc)
dev->bus->bandwidth_isoc_reqs++;
else
dev->bus->bandwidth_int_reqs++;
urb->bandwidth = bustime;
#ifdef USB_BANDWIDTH_MESSAGES
dbg("bandwidth alloc increased by %d to %d for %d requesters",
bustime,
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
#endif
}
/*
* usb_release_bandwidth():
*
* called to release a pipe's bandwidth (in microseconds)
*/
void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc)
{
dev->bus->bandwidth_allocated -= urb->bandwidth;
if (isoc)
dev->bus->bandwidth_isoc_reqs--;
else
dev->bus->bandwidth_int_reqs--;
#ifdef USB_BANDWIDTH_MESSAGES
dbg("bandwidth alloc reduced by %d to %d for %d requesters",
urb->bandwidth,
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
#endif
urb->bandwidth = 0;
}
static void usb_bus_get(struct usb_bus *bus)
{
atomic_inc(&bus->refcnt);
}
static void usb_bus_put(struct usb_bus *bus)
{
if (atomic_dec_and_test(&bus->refcnt))
kfree(bus);
}
/**
* usb_alloc_bus - creates a new USB host controller structure (usbcore-internal)
* @op: pointer to a struct usb_operations that this bus structure should use
*
* Creates a USB host controller bus structure with the specified
* usb_operations and initializes all the necessary internal objects.
* (For use only by USB Host Controller Drivers.)
*
* If no memory is available, NULL is returned.
*
* The caller should call usb_free_bus() when it is finished with the structure.
*/
struct usb_bus *usb_alloc_bus(struct usb_operations *op)
{
struct usb_bus *bus;
bus = kmalloc(sizeof(*bus), GFP_KERNEL);
if (!bus)
return NULL;
memset(&bus->devmap, 0, sizeof(struct usb_devmap));
#ifdef DEVNUM_ROUND_ROBIN
bus->devnum_next = 1;
#endif /* DEVNUM_ROUND_ROBIN */
bus->op = op;
bus->root_hub = NULL;
bus->hcpriv = NULL;
bus->busnum = -1;
bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD(&bus->bus_list);
atomic_set(&bus->refcnt, 1);
return bus;
}
/**
* usb_free_bus - frees the memory used by a bus structure (usbcore-internal)
* @bus: pointer to the bus to free
*
* (For use only by USB Host Controller Drivers.)
*/
void usb_free_bus(struct usb_bus *bus)
{
if (!bus)
return;
usb_bus_put(bus);
}
/**
* usb_register_bus - registers the USB host controller with the usb core (usbcore-internal)
* @bus: pointer to the bus to register
*
* (For use only by USB Host Controller Drivers.)
*
* This call is synchronous, and may not be used in an interrupt context.
*/
void usb_register_bus(struct usb_bus *bus)
{
int busnum;
down (&usb_bus_list_lock);
busnum = find_next_zero_bit(busmap.busmap, USB_MAXBUS, 1);
if (busnum < USB_MAXBUS) {
set_bit(busnum, busmap.busmap);
bus->busnum = busnum;
} else
warn("too many buses");
usb_bus_get(bus);
/* Add it to the list of buses */
list_add(&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock);
usbfs_add_bus(bus);
info("new USB bus registered, assigned bus number %d", bus->busnum);
}
/**
* usb_deregister_bus - deregisters the USB host controller (usbcore-internal)
* @bus: pointer to the bus to deregister
*
* (For use only by USB Host Controller Drivers.)
*
* This call is synchronous, and may not be used in an interrupt context.
*/
void usb_deregister_bus(struct usb_bus *bus)
{
info("USB bus %d deregistered", bus->busnum);
/*
* NOTE: make sure that all the devices are removed by the
* controller code, as well as having it call this when cleaning
* itself up
*/
down (&usb_bus_list_lock);
list_del(&bus->bus_list);
up (&usb_bus_list_lock);
usbfs_remove_bus(bus);
clear_bit(bus->busnum, busmap.busmap);
usb_bus_put(bus);
}
/*
* This function is for doing a depth-first search for devices which
* have support, for dynamic loading of driver modules.
......@@ -1016,6 +756,7 @@ static void usb_find_drivers(struct usb_device *dev)
* usb_alloc_dev - allocate a usb device structure (usbcore-internal)
* @parent: hub to which device is connected
* @bus: bus used to access the device
* Context: !in_interrupt ()
*
* Only hub drivers (including virtual root hub drivers for host
* controllers) should ever call this.
......@@ -1078,14 +819,12 @@ void usb_inc_dev_use(struct usb_device *dev)
atomic_inc(&dev->refcnt);
}
/* ----------------------------------------------------------------------
* New USB Core Functions
* ----------------------------------------------------------------------*/
/**
* usb_alloc_urb - creates a new urb for a USB driver to use
* @iso_packets: number of iso packets for this urb
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this.
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of
* valid options for this.
*
* Creates an urb for the USB driver to use, initializes a few internal
* structures, incrementes the usage counter, and returns a pointer to it.
......@@ -1129,8 +868,10 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
void usb_free_urb(struct urb *urb)
{
if (urb)
if (atomic_dec_and_test(&urb->count))
if (atomic_dec_and_test(&urb->count)) {
info ("really freeing urb");
kfree(urb);
}
}
/**
......@@ -1158,7 +899,8 @@ struct urb * usb_get_urb(struct urb *urb)
/**
* usb_submit_urb - asynchronously issue a transfer request for an endpoint
* @urb: pointer to the urb describing the request
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this.
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
* of valid options for this.
*
* This submits a transfer request, and transfers control of the URB
* describing that request to the USB subsystem. Request completion will
......@@ -1393,7 +1135,9 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
* @index: USB message index value
* @data: pointer to the data to send
* @size: length in bytes of the data to send
* @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple control message to a specified endpoint
* and waits for the message to complete, or timeout.
......@@ -1401,7 +1145,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
* If successful, it returns 0, otherwise a negative error number.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need a asyncronous message, or need to send
* bottom half handler. If you need an asynchronous message, or need to send
* a message from within interrupt context, use usb_submit_urb()
*/
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
......@@ -1436,7 +1180,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
* @data: pointer to the data to send
* @len: length in bytes of the data to send
* @actual_length: pointer to a location to put the actual length transferred in bytes
* @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple bulk message to a specified endpoint
* and waits for the message to complete, or timeout.
......@@ -1446,7 +1192,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
* actual_length paramater.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need a asyncronous message, or need to
* bottom half handler. If you need an asynchronous message, or need to
* send a message from within interrupt context, use usb_submit_urb()
*/
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
......@@ -1474,6 +1220,11 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
* Returns the current frame number for the USB host controller
* used with the given USB device. This can be used when scheduling
* isochronous requests.
*
* Note that different kinds of host controller have different
* "scheduling horizons". While one type might support scheduling only
* 32 frames into the future, others could support scheduling up to
* 1024 frames into the future.
*/
int usb_get_current_frame_number(struct usb_device *dev)
{
......@@ -1946,6 +1697,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type,
/**
* usb_disconnect - disconnect a device (usbcore-internal)
* @pdev: pointer to device being disconnected
* Context: !in_interrupt ()
*
* Something got disconnected. Get rid of it, and all of its children.
*
......@@ -2069,6 +1821,7 @@ int usb_set_address(struct usb_device *dev)
* @index: the number of the descriptor
* @buf: where to put the descriptor
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Gets a USB descriptor. Convenience functions exist to simplify
* getting some types of descriptors. Use
......@@ -2110,6 +1863,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
* in little-endian byte order).
......@@ -2135,6 +1889,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
/**
* usb_get_device_descriptor - (re)reads the device descriptor
* @dev: the device whose device descriptor is being updated
* Context: !in_interrupt ()
*
* Updates the copy of the device descriptor stored in the device structure,
* which dedicates space for this purpose. Note that several fields are
......@@ -2169,6 +1924,7 @@ int usb_get_device_descriptor(struct usb_device *dev)
* @type: USB_RECIP_*; for device, interface, or endpoint
* @target: zero (for device), else interface or endpoint number
* @data: pointer to two bytes of bitmap data
* Context: !in_interrupt ()
*
* Returns device, interface, or endpoint status. Normally only of
* interest to see if the device is self powered, or has enabled the
......@@ -2227,6 +1983,7 @@ void usb_set_maxpacket(struct usb_device *dev)
* usb_clear_halt - tells device to clear endpoint halt/stall condition
* @dev: device whose endpoint is halted
* @pipe: endpoint "pipe" being cleared
* Context: !in_interrupt ()
*
* This is used to clear halt conditions for bulk and interrupt endpoints,
* as reported by URB completion status. Endpoints that are halted are
......@@ -2298,6 +2055,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
* @dev: the device whose interface is being updated
* @interface: the interface being updated
* @alternate: the setting being chosen.
* Context: !in_interrupt ()
*
* This is used to enable data transfers on interfaces that may not
* be enabled by default. Not all devices support such configurability.
......@@ -2378,6 +2136,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated
* @configuration: the configuration being chosen.
* Context: !in_interrupt ()
*
* This is used to enable non-default device modes. Not all devices
* support this kind of configurability. By default, configuration
......@@ -2540,6 +2299,7 @@ int usb_get_configuration(struct usb_device *dev)
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
......@@ -2619,8 +2379,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
* @dev: the device whose path is being constructed
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Returns length of the string (>= 0) or out of memory status (< 0).
*
* NOTE: prefer to use use dev->devpath directly.
*/
int usb_make_path(struct usb_device *dev, char *buf, size_t size)
{
......@@ -2768,29 +2531,6 @@ int usb_new_device(struct usb_device *dev)
return 0;
}
/**
* usb_register_root_hub - called by a usb host controller to register the root hub device in the system
* @usb_dev: the usb root hub device to be registered.
* @parent_dev: the parent device of this root hub.
*
* The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in
* the driverfs tree, and then calls usb_new_device() to register the
* usb device.
*/
int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
{
int retval;
usb_dev->dev.parent = parent_dev;
strcpy (&usb_dev->dev.name[0], "usb_name");
strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
retval = usb_new_device (usb_dev);
if (retval)
put_device (&usb_dev->dev);
return retval;
}
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
......@@ -2859,7 +2599,6 @@ struct list_head *usb_bus_get_list(void)
*/
static int __init usb_init(void)
{
init_MUTEX(&usb_bus_list_lock);
usb_major_init();
usbfs_init();
usb_hub_init();
......@@ -2892,11 +2631,7 @@ EXPORT_SYMBOL(usb_epnum_to_ep_desc);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_scan_devices);
EXPORT_SYMBOL(usb_alloc_bus);
EXPORT_SYMBOL(usb_free_bus);
EXPORT_SYMBOL(usb_register_bus);
EXPORT_SYMBOL(usb_deregister_bus);
EXPORT_SYMBOL(usb_register_root_hub);
EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_inc_dev_use);
......@@ -2912,10 +2647,6 @@ EXPORT_SYMBOL(usb_reset_device);
EXPORT_SYMBOL(usb_connect);
EXPORT_SYMBOL(usb_disconnect);
EXPORT_SYMBOL(usb_check_bandwidth);
EXPORT_SYMBOL(usb_claim_bandwidth);
EXPORT_SYMBOL(usb_release_bandwidth);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number);
......
......@@ -44,8 +44,8 @@
/*
* USB directions
*/
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
/*
* Endpoints
......@@ -148,12 +148,6 @@ struct usb_devmap {
unsigned long devicemap[128 / (8*sizeof(unsigned long))];
};
#define USB_MAXBUS 64
struct usb_busmap {
unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
};
struct usb_device;
/*-------------------------------------------------------------------------*/
......@@ -516,7 +510,8 @@ struct usb_device_id {
* 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
* concurrency issues with respect to open() and close() methods, as
* well as cancel any I/O requests that are still pending.
* well as forcing all pending I/O requests to complete (by unlinking
* them as necessary, and blocking until the unlinks complete).
*/
struct usb_driver {
struct module *owner;
......@@ -905,13 +900,7 @@ extern int usb_make_path(struct usb_device *dev, char *buf, size_t size);
/* Host Controller Driver (HCD) support */
struct usb_operations {
int (*allocate)(struct usb_device *);
int (*deallocate)(struct usb_device *);
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, int mem_flags);
int (*unlink_urb) (struct urb *urb);
};
struct usb_operations;
#define DEVNUM_ROUND_ROBIN /***** OPTION *****/
......@@ -944,40 +933,11 @@ struct usb_bus {
atomic_t refcnt;
};
extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
extern void usb_free_bus(struct usb_bus *);
extern void usb_register_bus(struct usb_bus *);
extern void usb_deregister_bus(struct usb_bus *);
extern int usb_register_root_hub(struct usb_device *usb_dev, struct device *parent_dev);
extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
int bustime, int isoc);
extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb,
int isoc);
// FIXME: root_hub_string vanishes when "usb_hcd" conversion is done,
// along with pre-hcd versions of the OHCI and UHCI drivers.
extern int usb_root_hub_string(int id, int serial,
char *type, __u8 *data, int len);
/*
* Some USB 1.1 bandwidth allocation constants.
*/
#define BW_HOST_DELAY 1000L /* nanoseconds */
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
/* 4 full-speed bit times (est.) */
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
#define FRAME_TIME_USECS 1000L
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
/* Trying not to use worst-case bit-stuffing
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
/* bytecount = data payload byte count */
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
/* convert & round nanoseconds to microseconds */
/*
* As of USB 2.0, full/low speed devices are segregated into trees.
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
......@@ -1209,13 +1169,11 @@ void usb_show_string(struct usb_device *dev, char *id, int index);
/* -------------------------------------------------------------------------- */
/*
* bus and driver list
* driver list
* exported only for usbfs (not visible outside usbcore)
*/
extern struct list_head usb_driver_list;
extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock;
/*
* USB device fs stuff
......
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