Commit 36644e22 authored by Linus Torvalds's avatar Linus Torvalds

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

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents f6b765c0 8e791974
......@@ -19,9 +19,9 @@ your system. This library is available from
auerswald and shipped as part of the java software.
You may create the devices with:
mknod -m 666 /dev/usb/auer0 c 180 80
mknod -m 666 /dev/usb/auer0 c 180 112
...
mknod -m 666 /dev/usb/auer15 c 180 95
mknod -m 666 /dev/usb/auer15 c 180 127
Future plans
============
......
......@@ -95,12 +95,13 @@ HandSpring Visor, Palm USB, and Cli
Kroah-Hartman at greg@kroah.com
Compaq iPAQ driver
Compaq iPAQ and HP Jornada driver
This driver can be used to connect to Compaq iPAQ PDAs running
Windows CE 3.0 using a USB autosync cable. It has been tested only on
the Compaq H3135. It should work with the H3600 and later models too.
It may work with other CE based handhelds as well.
This driver can be used to connect to Compaq iPAQ and HP Jornada PDAs
running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. It
has been tested only on the Compaq H3135, but is rumoured to work on
with the H3600 and later models as well as the Jornada 548 and 568.
With minor modifications, it may work for other CE based handhelds too.
The driver presents a serial interface (usually on /dev/ttyUSB0) over
which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
......@@ -109,11 +110,14 @@ Compaq iPAQ driver
kbytes/sec for download/upload to the iPAQ.
The driver works intermittently with the usb-uhci driver but quite
reliably with the uhci driver. Make sure you have the right driver
loaded - usb-uhci is often the default.
reliably with the uhci driver. However, performance is much better
with usb-uhci. It does not seem to work with ohci at all.
You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
A ppp script like the one below may be used:
A ppp script like the one below should be kept in the file
/etc/hotplug/usb/ipaq Remember to chmod +x. Make sure there are no
options in /etc/ppp/options or ~/.ppprc which conflict with the ones
given below.
#!/bin/bash
......@@ -133,7 +137,7 @@ Compaq iPAQ driver
On connecting the cable, you should see the usual "Device Connected",
"User Authenticated" messages flash by on your iPAQ. Once connected,
you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
and other synce utilities from the Linux side. Remember to enable IP
and xcerdisp, synce utilities from the Linux side. Remember to enable IP
forwarding.
To use Pocket IE, follow the instructions given at
......
......@@ -124,9 +124,7 @@
* conversions. We never do sample rate conversion; these are too
* expensive to be performed in the kernel.
*
* Current status:
* - Pretty stable on UHCI-Acher/Fliegl/Sailer
* - Does not work on OHCI due to lack of OHCI driver supporting URB's
* Current status: no known HCD-specific issues.
*
* Generally: Due to the brokenness of the Audio Class spec
* it seems generally impossible to write a generic Audio Class driver,
......@@ -298,12 +296,10 @@ struct usb_audio_state;
struct my_data_urb {
struct urb *urb;
struct usb_iso_packet_descriptor isoframe[DESCFRAMES];
};
struct my_sync_urb {
struct urb *urb;
struct usb_iso_packet_descriptor isoframe[SYNCFRAMES];
};
......@@ -2829,14 +2825,14 @@ static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *b
init_waitqueue_head(&as->usbin.dma.wait);
init_waitqueue_head(&as->usbout.dma.wait);
spin_lock_init(&as->lock);
as->usbin.durb[0].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbin.durb[1].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbin.surb[0].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbin.surb[1].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbout.durb[0].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbout.durb[1].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbout.surb[0].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbout.surb[1].urb = usb_alloc_urb(0, GFP_KERNEL);
as->usbin.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
as->usbin.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
as->usbin.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
as->usbin.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
as->usbout.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
as->usbout.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
as->usbout.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
as->usbout.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
if ((!as->usbin.durb[0].urb) ||
(!as->usbin.durb[1].urb) ||
(!as->usbin.surb[0].urb) ||
......
......@@ -61,7 +61,7 @@ do { \
#define ID_AUERSWALD 0x09BF
#ifndef AUER_MINOR_BASE /* allow external override */
#define AUER_MINOR_BASE 80 /* auerswald driver minor number */
#define AUER_MINOR_BASE 112 /* auerswald driver minor number */
#endif
/* we can have up to this number of device plugged in at once */
......
......@@ -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__ */
......@@ -44,6 +44,7 @@
#include <linux/usb.h>
#include "../hcd.h"
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
......
......@@ -18,8 +18,6 @@
/* this file is part of ehci-hcd.c */
#include <asm/byteorder.h>
/*-------------------------------------------------------------------------*/
/*
......
......@@ -18,8 +18,6 @@
/* this file is part of ehci-hcd.c */
#include <asm/byteorder.h>
/*-------------------------------------------------------------------------*/
/*
......
......@@ -18,8 +18,6 @@
/* this file is part of ehci-hcd.c */
#include <asm/byteorder.h>
/*-------------------------------------------------------------------------*/
/*
......
......@@ -20,8 +20,6 @@
/*-------------------------------------------------------------------------*/
#include "ehci.h"
/*
* EHCI scheduled transaction support: interrupt, iso, split iso
* These are called "periodic" transactions in the EHCI spec.
......@@ -395,6 +393,9 @@ static int intr_submit (
frame += period;
} while (frame < ehci->periodic_size);
/* update bandwidth utilization records (for usbfs) */
usb_claim_bandwidth (urb->dev, urb, usecs, 0);
/* maybe enable periodic schedule processing */
if (!ehci->periodic_urbs++) {
u32 cmd;
......
......@@ -8,8 +8,6 @@
* $Id: ohci-q.c,v 1.6 2002/01/19 00:23:15 dbrownell Exp $
*/
#include <asm/byteorder.h>
static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
{
int last = urb_priv->length - 1;
......
......@@ -1452,7 +1452,8 @@ static void hid_disconnect(struct usb_device *dev, void *ptr)
}
static struct usb_device_id hid_usb_ids [] = {
{ bInterfaceClass: USB_INTERFACE_CLASS_HID },
{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
bInterfaceClass: USB_INTERFACE_CLASS_HID },
{ } /* Terminating entry */
};
......
......@@ -40,9 +40,10 @@ CONFIG_USB_SERIAL_VISOR
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SERIAL_IPAQ
Say Y here if you want to connect to your Compaq iPAQ running
Windows CE 3.0 using a USB autosync cable. For information on using
the driver, read <file:Documentation/usb/usb-serial.txt>.
Say Y here if you want to connect to your Compaq iPAQ or HP Jornada
548/568 running Windows CE 3.0 or PocketPC 2002 using a USB
cradle/cable. For information on using the driver,
read <file:Documentation/usb/usb-serial.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
......
......@@ -15,7 +15,7 @@ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_
dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
dep_tristate ' USB Compaq iPAQ Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
dep_tristate ' USB Compaq iPAQ / HP Jornada Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
......
......@@ -207,8 +207,6 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__" port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -230,8 +228,6 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
}
exit:
up (&port->sem);
return retval;
} /* belkin_sa_open */
......@@ -249,8 +245,6 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__" port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -262,8 +256,6 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
}
port->open_count = 0;
}
up (&port->sem);
} /* belkin_sa_close */
......
......@@ -151,8 +151,6 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -179,8 +177,6 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__ " - usb_submit_urb(int urb)");
}
up (&port->sem);
return result;
}
......@@ -188,8 +184,6 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
{
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -201,8 +195,6 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
}
port->open_count = 0;
}
up (&port->sem);
}
static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
......@@ -225,8 +217,6 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
return (0);
}
down (&port->sem);
if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
/* To much data for buffer. Reset buffer. */
priv->wrfilled=0;
......@@ -235,8 +225,9 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
/* Copy data */
if (from_user) {
if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count))
if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) {
return -EFAULT;
}
} else {
memcpy (priv->wrbuf+priv->wrfilled, buf, count);
}
......@@ -277,7 +268,6 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
/* Throw away data. No better idea what to do with it. */
priv->wrfilled=0;
priv->wrsent=0;
up (&port->sem);
return 0;
}
......@@ -292,7 +282,6 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
}
}
up (&port->sem);
return (count);
}
......@@ -432,8 +421,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - transmitting data (frame n)");
length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
......@@ -459,7 +446,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
/* Throw away data. No better idea what to do with it. */
priv->wrfilled=0;
priv->wrsent=0;
up (&port->sem);
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
......@@ -477,7 +463,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
priv->wrsent=0;
}
up (&port->sem);
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
......
......@@ -157,8 +157,6 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -189,8 +187,6 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
}
up (&port->sem);
return result;
}
......@@ -208,8 +204,6 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -220,8 +214,6 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp)
port->open_count = 0;
}
up (&port->sem);
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
}
......@@ -462,15 +454,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
static void empeg_throttle (struct usb_serial_port *port)
{
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
usb_unlink_urb (port->read_urb);
up (&port->sem);
return;
}
......@@ -480,8 +464,6 @@ static void empeg_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
......@@ -489,10 +471,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
up (&port->sem);
return;
}
......
......@@ -319,8 +319,6 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__);
down (&port->sem);
++port->open_count;
if (port->open_count == 1){
......@@ -361,7 +359,6 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
up (&port->sem);
return result;
} /* ftdi_sio_open */
......@@ -374,7 +371,6 @@ static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
dbg( __FUNCTION__);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -411,9 +407,6 @@ static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
tty_hangup(port->tty);
}
}
up (&port->sem);
} /* ftdi_sio_close */
......@@ -447,8 +440,6 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
return (0);
}
down(&port->sem);
count += data_offset;
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
......@@ -456,7 +447,6 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
if (from_user) {
if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
buf, count - data_offset )){
up (&port->sem);
return -EFAULT;
}
} else {
......@@ -482,14 +472,11 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
up (&port->sem);
return 0;
}
up (&port->sem);
dbg(__FUNCTION__ " write returning: %d", count - data_offset);
return (count - data_offset);
} /* ftdi_sio_write */
static void ftdi_sio_write_bulk_callback (struct urb *urb)
......
/*
* USB Compaq iPAQ driver
*
* Copyright (C) 2001
* Copyright (C) 2001 - 2002
* Ganesh Varadarajan <ganesh@veritas.com>
*
* This program is free software; you can redistribute it and/or modify
......@@ -9,6 +9,9 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* (25/2/2002) ganesh
* Added support for the HP Jornada 548 and 568. Completely untested.
* Thanks to info from Heath Robinson and Arieh Davidoff.
*/
#include <linux/config.h>
......@@ -39,9 +42,9 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.1"
#define DRIVER_VERSION "v0.2"
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
#define DRIVER_DESC "USB Compaq iPAQ driver"
#define DRIVER_DESC "USB Compaq iPAQ, HP Jornada driver"
/* Function prototypes for an ipaq */
static int ipaq_open (struct usb_serial_port *port, struct file *filp);
......@@ -61,7 +64,9 @@ static void ipaq_destroy_lists(struct usb_serial_port *port);
static __devinitdata struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(IPAQ_VENDOR_ID, IPAQ_PRODUCT_ID) },
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
{ } /* Terminating entry */
};
......@@ -72,7 +77,7 @@ struct usb_serial_device_type ipaq_device = {
owner: THIS_MODULE,
name: "Compaq iPAQ",
id_table: ipaq_id_table,
num_interrupt_in: 0,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
......@@ -104,8 +109,6 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__ " - port %d", port->number);
down(&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -193,8 +196,6 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
}
}
up(&port->sem);
return result;
enomem:
......@@ -219,8 +220,6 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
serial = get_usb_serial(port, __FUNCTION__);
if (!serial)
return;
down (&port->sem);
--port->open_count;
......@@ -238,8 +237,6 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
port->open_count = 0;
}
up (&port->sem);
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
}
......
/*
* USB Compaq iPAQ driver
*
* Copyright (C) 2001
* Copyright (C) 2001 - 2002
* Ganesh Varadarajan <ganesh@veritas.com>
*
* This program is free software; you can redistribute it and/or modify
......@@ -16,8 +16,12 @@
#define __LINUX_USB_SERIAL_IPAQ_H
#define IPAQ_VENDOR_ID 0x049f
#define IPAQ_PRODUCT_ID 0x0003
#define COMPAQ_VENDOR_ID 0x049f
#define COMPAQ_IPAQ_ID 0x0003
#define HP_VENDOR_ID 0x003f
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
/*
* Since we can't queue our bulk write urbs (don't know why - it just
......
......@@ -252,8 +252,6 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -293,9 +291,6 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
if (result)
err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
}
up (&port->sem);
return result;
}
......@@ -312,8 +307,6 @@ static void ir_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -324,7 +317,6 @@ static void ir_close (struct usb_serial_port *port, struct file * filp)
port->open_count = 0;
}
up (&port->sem);
}
static int ir_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
......
......@@ -861,10 +861,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
dbg("keyspan_open called for port%d.\n", port->number);
down (&port->sem);
already_active = port->open_count;
++port->open_count;
up (&port->sem);
if (already_active)
return 0;
......@@ -926,8 +924,6 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
p_priv->out_flip = 0;
p_priv->in_flip = 0;
down (&port->sem);
if (--port->open_count <= 0) {
if (serial->dev) {
/* Stop reading/writing urbs */
......@@ -941,7 +937,6 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
port->open_count = 0;
port->tty = 0;
}
up (&port->sem);
}
......
......@@ -662,8 +662,6 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
int rc = 0;
struct keyspan_pda_private *priv;
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -707,12 +705,9 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
}
up (&port->sem);
return rc;
error:
--port->open_count;
up (&port->sem);
return rc;
}
......@@ -721,8 +716,6 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -737,8 +730,6 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
}
port->open_count = 0;
}
up (&port->sem);
}
......
......@@ -358,8 +358,6 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__" port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -437,8 +435,6 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
}
exit:
up (&port->sem);
return retval;
} /* klsi_105_open */
......@@ -455,8 +451,6 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
if(!serial)
return;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -482,8 +476,6 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
port->open_count = 0;
info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
}
up (&port->sem);
} /* klsi_105_close */
......@@ -505,9 +497,6 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem); /* to lock against someone else trying to
take an URB we just selected from the pool */
while (count > 0) {
/* try to find a free urb (write 0 bytes if none) */
struct urb *urb = NULL;
......@@ -543,7 +532,6 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
if (from_user) {
if (copy_from_user(urb->transfer_buffer
+ KLSI_105_DATA_OFFSET, buf, size)) {
up (&port->sem);
return -EFAULT;
}
} else {
......@@ -578,7 +566,6 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
count -= size;
}
exit:
up (&port->sem);
priv->bytes_out+=bytes_sent;
return bytes_sent; /* that's how much we wrote */
......@@ -1021,34 +1008,21 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
static void klsi_105_throttle (struct usb_serial_port *port)
{
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
usb_unlink_urb (port->read_urb);
up (&port->sem);
return;
}
static void klsi_105_unthrottle (struct usb_serial_port *port)
{
int result;
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
up (&port->sem);
return;
}
......
......@@ -341,8 +341,6 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__" port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -398,8 +396,6 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
}
exit:
up (&port->sem);
return 0;
} /* mct_u232_open */
......@@ -408,8 +404,6 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
{
dbg(__FUNCTION__" port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -421,8 +415,6 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
}
port->open_count = 0;
}
up (&port->sem);
} /* mct_u232_close */
......@@ -454,16 +446,12 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
bytes_sent = 0;
while (count > 0) {
down (&port->sem);
size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
if (from_user) {
if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {
up (&port->sem);
return -EFAULT;
}
}
......@@ -486,12 +474,9 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
up (&port->sem);
return result;
}
up (&port->sem);
bytes_sent += size;
if (write_blocking)
interruptible_sleep_on(&port->write_wait);
......
......@@ -157,8 +157,6 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
if (!serial)
return -ENODEV;
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -166,7 +164,6 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
if( !od ) {
err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
port->open_count = 0;
up (&port->sem);
return -ENOMEM;
}
......@@ -184,8 +181,6 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
up (&port->sem);
return result;
}
......@@ -204,8 +199,6 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -220,8 +213,6 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
if (od)
kfree(od);
}
up (&port->sem);
}
......
......@@ -367,8 +367,6 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
dbg (__FUNCTION__ " - port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -407,7 +405,6 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb (port->read_urb, GFP_KERNEL);
if (result) {
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
up (&port->sem);
pl2303_close (port, NULL);
return -EPROTO;
}
......@@ -417,12 +414,10 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
if (result) {
err(__FUNCTION__ " - failed submitting interrupt urb, error %d", result);
up (&port->sem);
pl2303_close (port, NULL);
return -EPROTO;
}
}
up (&port->sem);
return 0;
}
......@@ -442,8 +437,6 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
dbg (__FUNCTION__ " - port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
if (serial->dev) {
......@@ -478,8 +471,6 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
}
port->open_count = 0;
}
up (&port->sem);
}
static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
......
/*
* USB Serial Converter driver
*
* Copyright (C) 1999 - 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2000 Peter Berger (pberger@brimson.com)
* Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com)
*
......@@ -15,6 +15,13 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (02/26/2002) gkh
* Moved all locking into the main serial_* functions, instead of having
* the individual drivers have to grab the port semaphore. This should
* reduce races.
* Reworked the MOD_INC logic a bit to always increment and decrement, even
* if the generic driver is being used.
*
* (10/10/2001) gkh
* usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
* help prevent child drivers from accessing the device since it is now
......@@ -337,6 +344,7 @@ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
/* All of the device info needed for the Generic Serial Converter */
static struct usb_serial_device_type generic_device = {
owner: THIS_MODULE,
name: "Generic",
id_table: generic_device_ids,
num_interrupt_in: NUM_DONT_CARE,
......@@ -345,13 +353,6 @@ static struct usb_serial_device_type generic_device = {
num_ports: 1,
shutdown: generic_shutdown,
};
#define if_generic_do(x) \
if ((serial->vendor == vendor) && \
(serial->product == product)) \
x
#else
#define if_generic_do(x)
#endif
......@@ -384,7 +385,7 @@ static struct usb_driver usb_serial_driver = {
via modprobe, and modprobe will load usbserial because the serial
drivers depend on it.
*/
static int serial_refcount;
static struct tty_driver serial_tty_driver;
......@@ -392,8 +393,6 @@ static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
static struct termios * serial_termios[SERIAL_TTY_MINORS];
static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static LIST_HEAD(usb_serial_driver_list);
......@@ -402,7 +401,6 @@ static struct usb_serial *get_serial_by_minor (unsigned int minor)
return serial_table[minor];
}
static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
{
struct usb_serial *serial = NULL;
......@@ -439,7 +437,6 @@ static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
return NULL;
}
static void return_serial (struct usb_serial *serial)
{
int i;
......@@ -456,7 +453,6 @@ static void return_serial (struct usb_serial *serial)
return;
}
#ifdef USES_EZUSB_FUNCTIONS
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
......@@ -483,7 +479,6 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
return result;
}
int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
{
int response;
......@@ -497,7 +492,6 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
#endif /* USES_EZUSB_FUNCTIONS */
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
......@@ -516,266 +510,293 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
/* get the serial object associated with this tty pointer */
serial = get_serial_by_minor (minor(tty->device));
if (serial_paranoia_check (serial, __FUNCTION__)) {
if (serial_paranoia_check (serial, __FUNCTION__))
return -ENODEV;
}
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = minor(tty->device) - serial->minor;
port = &serial->port[portNumber];
tty->driver_data = port;
down (&port->sem);
port->tty = tty;
/* lock this module before we call it */
if (serial->type->owner)
__MOD_INC_USE_COUNT(serial->type->owner);
/* pass on to the driver specific version of this function if it is available */
if (serial->type->open) {
if (serial->type->owner)
__MOD_INC_USE_COUNT(serial->type->owner);
if (serial->type->open)
retval = serial->type->open(port, filp);
if (retval)
__MOD_DEC_USE_COUNT(serial->type->owner);
} else {
else
retval = generic_open(port, filp);
}
if (retval)
__MOD_DEC_USE_COUNT(serial->type->owner);
up (&port->sem);
return retval;
}
static void serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
if (!serial)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (tty->driver_data == NULL) {
/* disconnect beat us to the punch here, so handle it gracefully */
goto exit;
}
if (!port->open_count) {
dbg (__FUNCTION__ " - port not opened");
return;
goto exit_no_mod_dec;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->close) {
if (serial->type->close)
serial->type->close(port, filp);
if (serial->type->owner)
__MOD_DEC_USE_COUNT(serial->type->owner);
} else {
else
generic_close(port, filp);
}
}
exit:
if (serial->type->owner)
__MOD_DEC_USE_COUNT(serial->type->owner);
exit_no_mod_dec:
up (&port->sem);
}
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
int retval = -EINVAL;
if (!serial)
return -ENODEV;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not opened");
return -EINVAL;
goto exit;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->write) {
return (serial->type->write(port, from_user, buf, count));
} else {
return (generic_write(port, from_user, buf, count));
}
}
if (serial->type->write)
retval = serial->type->write(port, from_user, buf, count);
else
retval = generic_write(port, from_user, buf, count);
exit:
up (&port->sem);
return retval;
}
static int serial_write_room (struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
int retval = -EINVAL;
if (!serial) {
if (!serial)
return -ENODEV;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -EINVAL;
goto exit;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->write_room) {
return (serial->type->write_room(port));
} else {
return (generic_write_room(port));
}
}
if (serial->type->write_room)
retval = serial->type->write_room(port);
else
retval = generic_write_room(port);
exit:
up (&port->sem);
return retval;
}
static int serial_chars_in_buffer (struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
int retval = -EINVAL;
if (!serial) {
if (!serial)
return -ENODEV;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -EINVAL;
goto exit;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->chars_in_buffer) {
return (serial->type->chars_in_buffer(port));
} else {
return (generic_chars_in_buffer(port));
}
}
if (serial->type->chars_in_buffer)
retval = serial->type->chars_in_buffer(port);
else
retval = generic_chars_in_buffer(port);
exit:
up (&port->sem);
return retval;
}
static void serial_throttle (struct tty_struct * tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
if (!serial)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
goto exit;
}
/* pass on to the driver specific version of this function */
if (serial->type->throttle) {
if (serial->type->throttle)
serial->type->throttle(port);
}
return;
exit:
up (&port->sem);
}
static void serial_unthrottle (struct tty_struct * tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
if (!serial)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
goto exit;
}
/* pass on to the driver specific version of this function */
if (serial->type->unthrottle) {
if (serial->type->unthrottle)
serial->type->unthrottle(port);
}
return;
exit:
up (&port->sem);
}
static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
int retval = -ENODEV;
if (!serial) {
if (!serial)
return -ENODEV;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -ENODEV;
goto exit;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->ioctl) {
return (serial->type->ioctl(port, file, cmd, arg));
} else {
return -ENOIOCTLCMD;
}
}
if (serial->type->ioctl)
retval = serial->type->ioctl(port, file, cmd, arg);
else
retval = -ENOIOCTLCMD;
exit:
up (&port->sem);
return retval;
}
static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
if (!serial)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
goto exit;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->set_termios) {
if (serial->type->set_termios)
serial->type->set_termios(port, old);
}
return;
}
exit:
up (&port->sem);
}
static void serial_break (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
if (!serial)
return;
}
down (&port->sem);
dbg(__FUNCTION__ " - port %d", port->number);
if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
goto exit;
}
/* pass on to the driver specific version of this function if it is
available */
if (serial->type->break_ctl) {
/* pass on to the driver specific version of this function if it is available */
if (serial->type->break_ctl)
serial->type->break_ctl(port, break_state);
}
}
exit:
up (&port->sem);
}
static void serial_shutdown (struct usb_serial *serial)
{
if (serial->type->shutdown) {
if (serial->type->shutdown)
serial->type->shutdown(serial);
} else {
else
generic_shutdown(serial);
}
}
/*****************************************************************************
* generic devices specific driver functions
*****************************************************************************/
......@@ -787,21 +808,16 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
/* only increment our usage count, if this device is _really_ a generic device */
if_generic_do(MOD_INC_USE_COUNT);
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates (like with OHCI) data
can get lost. */
port->tty->low_latency = 1;
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
......@@ -818,21 +834,16 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
}
up (&port->sem);
return result;
}
static void generic_close (struct usb_serial_port *port, struct file * filp)
{
struct usb_serial *serial = port->serial;
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -845,14 +856,8 @@ static void generic_close (struct usb_serial_port *port, struct file * filp)
}
port->open_count = 0;
}
up (&port->sem);
/* only decrement our usage count, if this device is _really_ a generic device */
if_generic_do(MOD_DEC_USE_COUNT);
}
static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
......@@ -880,14 +885,14 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
}
else {
memcpy (port->write_urb->transfer_buffer, buf, count);
}
}
usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
/* set up our urb */
usb_fill_bulk_urb (port->write_urb, serial->dev,
usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress),
port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
((serial->type->write_bulk_callback) ?
serial->type->write_bulk_callback :
......@@ -902,11 +907,10 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
return result;
}
/* no bulk out, so return 0 bytes written */
return (0);
}
}
static int generic_write_room (struct usb_serial_port *port)
{
......@@ -919,19 +923,18 @@ static int generic_write_room (struct usb_serial_port *port)
if (port->write_urb->status != -EINPROGRESS)
room = port->bulk_out_size;
}
dbg(__FUNCTION__ " - returns %d", room);
return (room);
}
static int generic_chars_in_buffer (struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
int chars = 0;
dbg(__FUNCTION__ " - port %d", port->number);
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS)
chars = port->write_urb->transfer_buffer_length;
......@@ -941,7 +944,6 @@ static int generic_chars_in_buffer (struct usb_serial_port *port)
return (chars);
}
static void generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
......@@ -952,7 +954,7 @@ static void generic_read_bulk_callback (struct urb *urb)
int result;
dbg(__FUNCTION__ " - port %d", port->number);
if (!serial) {
dbg(__FUNCTION__ " - bad serial pointer, exiting");
return;
......@@ -992,14 +994,13 @@ static void generic_read_bulk_callback (struct urb *urb)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
static void generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg(__FUNCTION__ " - port %d", port->number);
if (!serial) {
dbg(__FUNCTION__ " - bad serial pointer, exiting");
return;
......@@ -1012,11 +1013,10 @@ static void generic_write_bulk_callback (struct urb *urb)
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
}
static void generic_shutdown (struct usb_serial *serial)
{
int i;
......@@ -1025,13 +1025,13 @@ static void generic_shutdown (struct usb_serial *serial)
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
while (serial->port[i].open_count > 0) {
down (&serial->port[i].sem);
while (serial->port[i].open_count > 0)
generic_close (&serial->port[i], NULL);
}
up (&serial->port[i].sem);
}
}
static void port_softint(void *private)
{
struct usb_serial_port *port = (struct usb_serial_port *)private;
......@@ -1043,7 +1043,7 @@ static void port_softint(void *private)
if (!serial) {
return;
}
tty = port->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
dbg(__FUNCTION__ " - write wakeup call.");
......@@ -1053,8 +1053,6 @@ static void port_softint(void *private)
wake_up_interruptible(&tty->write_wait);
}
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
......@@ -1080,7 +1078,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
int max_endpoints;
const struct usb_device_id *id_pattern = NULL;
/* loop through our list of known serial converters, and see if this
device matches. */
found = 0;
......@@ -1130,7 +1127,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
++num_interrupt_in;
}
}
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
......@@ -1156,7 +1153,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
}
/* END HORRIBLE HACK FOR PL2303 */
#endif
/* found all that we need */
info("%s converter detected", type->name);
......@@ -1176,7 +1173,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
err("No more free serial devices");
return NULL;
}
serial->dev = dev;
serial->type = type;
serial->interface = interface;
......@@ -1289,14 +1286,14 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
port->tqueue.data = port;
init_MUTEX (&port->sem);
}
/* initialize the devfs nodes for this device and let the user know what ports we are bound to */
for (i = 0; i < serial->num_ports; ++i) {
tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number);
info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)",
type->name, serial->port[i].number, serial->port[i].number);
}
return serial; /* success */
......@@ -1322,7 +1319,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
if (port->interrupt_in_buffer)
kfree (port->interrupt_in_buffer);
}
/* return the minor range that this device had */
return_serial (serial);
......@@ -1331,7 +1328,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
return NULL;
}
static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_serial *serial = (struct usb_serial *) ptr;
......@@ -1341,8 +1337,10 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
if (serial) {
/* fail all future close/read/write/ioctl/etc calls */
for (i = 0; i < serial->num_ports; ++i) {
down (&serial->port[i].sem);
if (serial->port[i].tty != NULL)
serial->port[i].tty->driver_data = NULL;
up (&serial->port[i].sem);
}
serial->dev = NULL;
......@@ -1393,7 +1391,7 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
} else {
info("device disconnected");
}
}
......@@ -1407,12 +1405,12 @@ static struct tty_driver serial_tty_driver = {
type: TTY_DRIVER_TYPE_SERIAL,
subtype: SERIAL_TYPE_NORMAL,
flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
refcount: &serial_refcount,
table: serial_tty,
termios: serial_termios,
termios_locked: serial_termios_locked,
open: serial_open,
close: serial_close,
write: serial_write,
......
......@@ -12,6 +12,15 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (02/27/2002) gkh
* Reworked the urb handling logic. We have no more pool, but dynamically
* allocate the urb and the transfer buffer on the fly. In testing this
* does not incure any measurable overhead. This also relies on the fact
* that we have proper reference counting logic for urbs.
*
* (02/21/2002) SilaS
* Added initial support for the Palm m515 devices.
*
* (02/14/2002) gkh
* Added support for the Clie S-360 device.
*
......@@ -134,7 +143,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.9"
#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
......@@ -158,6 +167,7 @@ static int clie_3_5_startup (struct usb_serial *serial);
static __devinitdata struct usb_device_id combined_id_table [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
......@@ -174,6 +184,7 @@ static __devinitdata struct usb_device_id id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
......@@ -233,12 +244,8 @@ static struct usb_serial_device_type clie_3_5_device = {
};
#define NUM_URBS 24
#define URB_TRANSFER_BUFFER_SIZE 768
static struct urb *write_urb_pool[NUM_URBS];
static spinlock_t write_urb_pool_lock;
static int bytes_in;
static int bytes_out;
static int bytes_in;
static int bytes_out;
/******************************************************************************
......@@ -259,8 +266,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
return -ENODEV;
}
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -284,8 +289,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
up (&port->sem);
return result;
}
......@@ -304,8 +307,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -329,8 +330,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
}
port->open_count = 0;
}
up (&port->sem);
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
}
......@@ -340,120 +339,84 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
{
struct usb_serial *serial = port->serial;
struct urb *urb;
const unsigned char *current_position = buf;
unsigned long flags;
unsigned char *buffer;
int status;
int i;
int bytes_sent = 0;
int transfer_size;
dbg(__FUNCTION__ " - port %d", port->number);
while (count > 0) {
/* try to find a free urb in our list of them */
urb = NULL;
spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status != -EINPROGRESS) {
urb = write_urb_pool[i];
break;
}
}
spin_unlock_irqrestore (&write_urb_pool_lock, flags);
if (urb == NULL) {
dbg (__FUNCTION__ " - no more free urbs");
goto exit;
}
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__" no more kernel memory...");
goto exit;
}
}
transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
if (from_user) {
if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) {
bytes_sent = -EFAULT;
break;
}
} else {
memcpy (urb->transfer_buffer, current_position, transfer_size);
}
buffer = kmalloc (count, GFP_KERNEL);
if (!buffer) {
err ("out of memory");
return -ENOMEM;
}
usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, urb->transfer_buffer);
/* build up our urb */
usb_fill_bulk_urb (urb, serial->dev,
usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress),
urb->transfer_buffer, transfer_size,
visor_write_bulk_callback, port);
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
bytes_sent = status;
break;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
err ("no more free urbs");
kfree (buffer);
return -ENOMEM;
}
if (from_user) {
if (copy_from_user (buffer, buf, count)) {
kfree (buffer);
usb_free_urb (urb);
return -EFAULT;
}
} else {
memcpy (buffer, buf, count);
}
usb_serial_debug_data (__FILE__, __FUNCTION__, count, buffer);
current_position += transfer_size;
bytes_sent += transfer_size;
count -= transfer_size;
bytes_out += transfer_size;
usb_fill_bulk_urb (urb, serial->dev,
usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress),
buffer, count,
visor_write_bulk_callback, port);
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
count = status;
} else {
bytes_out += count;
}
exit:
return bytes_sent;
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
usb_free_urb (urb);
return count;
}
static int visor_write_room (struct usb_serial_port *port)
{
unsigned long flags;
int i;
int room = 0;
dbg(__FUNCTION__ " - port %d", port->number);
spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status != -EINPROGRESS) {
room += URB_TRANSFER_BUFFER_SIZE;
}
}
spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg(__FUNCTION__ " - returns %d", room);
return (room);
/*
* We really can take anything the user throws at us
* but let's pick a nice big number to tell the tty
* layer that we have lots of free space
*/
return 2048;
}
static int visor_chars_in_buffer (struct usb_serial_port *port)
{
unsigned long flags;
int i;
int chars = 0;
dbg(__FUNCTION__ " - port %d", port->number);
spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status == -EINPROGRESS) {
chars += URB_TRANSFER_BUFFER_SIZE;
}
}
spin_unlock_irqrestore (&write_urb_pool_lock, flags);
dbg (__FUNCTION__ " - returns %d", chars);
return (chars);
/*
* We can't really account for how much data we
* have sent out, but hasn't made it through to the
* device, so just tell the tty layer that everything
* is flushed.
*/
return 0;
}
......@@ -471,9 +434,12 @@ static void visor_write_bulk_callback (struct urb *urb)
return;
}
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
}
......@@ -534,16 +500,8 @@ static void visor_read_bulk_callback (struct urb *urb)
static void visor_throttle (struct usb_serial_port *port)
{
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
usb_unlink_urb (port->read_urb);
up (&port->sem);
return;
}
......@@ -553,16 +511,10 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
up (&port->sem);
return;
}
......@@ -783,30 +735,8 @@ static void visor_set_termios (struct usb_serial_port *port, struct termios *old
static int __init visor_init (void)
{
struct urb *urb;
int i;
usb_serial_register (&handspring_device);
usb_serial_register (&clie_3_5_device);
/* create our write urb pool and transfer buffers */
spin_lock_init (&write_urb_pool_lock);
for (i = 0; i < NUM_URBS; ++i) {
urb = usb_alloc_urb(0, GFP_KERNEL);
write_urb_pool[i] = urb;
if (urb == NULL) {
err("No more urbs???");
continue;
}
urb->transfer_buffer = NULL;
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (!urb->transfer_buffer) {
err (__FUNCTION__ " - out of memory for urb buffers.");
continue;
}
}
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
......@@ -815,27 +745,8 @@ static int __init visor_init (void)
static void __exit visor_exit (void)
{
int i;
unsigned long flags;
usb_serial_deregister (&handspring_device);
usb_serial_deregister (&clie_3_5_device);
spin_lock_irqsave (&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]) {
/* FIXME - uncomment the following usb_unlink_urb call when
* the host controllers get fixed to set urb->dev = NULL after
* the urb is finished. Otherwise this call oopses. */
/* usb_unlink_urb(write_urb_pool[i]); */
if (write_urb_pool[i]->transfer_buffer)
kfree(write_urb_pool[i]->transfer_buffer);
usb_free_urb (write_urb_pool[i]);
}
}
spin_unlock_irqrestore (&write_urb_pool_lock, flags);
}
......
......@@ -23,6 +23,7 @@
#define PALM_VENDOR_ID 0x0830
#define PALM_M500_ID 0x0001
#define PALM_M505_ID 0x0002
#define PALM_M515_ID 0x0003
#define PALM_M125_ID 0x0040
#define SONY_VENDOR_ID 0x054C
......
......@@ -306,8 +306,6 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__" - port %d", port->number);
down (&port->sem);
++port->open_count;
if (port->open_count == 1) {
......@@ -354,16 +352,12 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
}
dbg(__FUNCTION__ " - exit");
up (&port->sem);
return retval;
error_exit:
--port->open_count;
dbg(__FUNCTION__ " - error_exit");
up (&port->sem);
return retval;
}
......@@ -374,7 +368,6 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
dbg(__FUNCTION__ " - port %d", port->number);
down (&port->sem);
--port->open_count;
if (port->open_count <= 0) {
......@@ -391,7 +384,6 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
usb_unlink_urb (port->read_urb);
port->open_count = 0;
}
up (&port->sem);
}
......@@ -410,8 +402,6 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct termios
dbg(__FUNCTION__ " -port %d", port->number);
down (&port->sem);
if ((!port->tty) || (!port->tty->termios)) {
dbg(__FUNCTION__" - no tty structures");
goto exit;
......@@ -492,7 +482,6 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct termios
whiteheat_send_cmd (port->serial, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings));
exit:
up (&port->sem);
return;
}
......
......@@ -53,11 +53,11 @@
#include <asm/irq.h>
#include <asm/system.h>
#include "hcd.h"
#include "uhci.h"
#include <linux/pm.h>
/*
* Version Information
*/
......@@ -65,7 +65,6 @@
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URB's except for stalls
......@@ -100,6 +99,7 @@ static void wakeup_hc(struct uhci *uhci);
/* If a transfer is still active after this much time, turn off FSBR */
#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */
#define FSBR_DELAY (HZ / 20) /* 50 ms */
#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */
......@@ -766,7 +766,7 @@ static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
if ((!(urb->transfer_flags & USB_NO_FSBR)) && urbp->fsbr) {
urbp->fsbr = 0;
if (!--uhci->fsbr)
uhci->skel_term_qh->link = UHCI_PTR_TERM;
uhci->fsbrtimeout = jiffies + FSBR_DELAY;
}
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
......@@ -2031,6 +2031,12 @@ static void rh_int_timer_do(unsigned long ptr)
uhci_unlink_urb(u);
}
/* Really disable FSBR */
if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
uhci->fsbrtimeout = 0;
uhci->skel_term_qh->link = UHCI_PTR_TERM;
}
/* enter global suspend if nothing connected */
if (!uhci->is_suspended && !ports_active(uhci))
suspend_hc(uhci);
......
......@@ -309,6 +309,7 @@ struct uhci {
spinlock_t frame_list_lock;
struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */
int fsbr; /* Full speed bandwidth reclamation */
unsigned long fsbrtimeout; /* FSBR delay */
int is_suspended;
/* Main list of URB's currently controlled by this HC */
......
......@@ -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