Commit 89f0f973 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 2c0889e4 bbed5f2f
......@@ -8,13 +8,8 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI) += host/
obj-$(CONFIG_USB_OHCI_SA1111) += host/
obj-$(CONFIG_USB_SL811HS) += host/
obj-$(CONFIG_USB_UHCI_ALT) += host/
obj-$(CONFIG_USB_UHCI_HCD_ALT) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI) += host/
obj-$(CONFIG_USB_SL811HS) += host/
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_AUDIO) += class/
......
......@@ -20,14 +20,16 @@ config USB_BLUETOOTH_TTY
tristate "USB Bluetooth TTY support"
depends on USB
---help---
Say Y here if you want to connect a USB Bluetooth device to your
computer's USB port. You will need the Bluetooth stack (available
at <http://developer.axis.com/software/index.shtml>) to fully use
the device.
This driver implements a tty inteface to a Bluetooth device. If
you want to use a socket based Bluetooth stack (like the BlueZ
stack), do not use this driver.
This driver implements a nonstandard tty interface to a Bluetooth
device that can be used only by specialized Bluetooth HCI software.
Say Y here if you want to use OpenBT Bluetooth stack (available
at <http://developer.axis.com/software/index.shtml>), or other TTY
based Bluetooth stacks, and want to connect a USB Bluetooth device
to your computer's USB port.
Do *not* enable this driver if you want to use generic Linux
Bluetooth support.
If in doubt, say N here.
......
/*
* usblp.c Version 0.12
* usblp.c Version 0.13
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
* Copyright (c) 2000 Randy Dunlap <rddunlap@osdl.org>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
......@@ -25,6 +25,8 @@
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
* v0.11 - add proto_bias option (Pete Zaitcev)
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
* v0.13 - alloc space for statusbuf (<status> not on stack);
* use usb_buffer_alloc() for read buf & write buf;
*/
/*
......@@ -59,7 +61,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.12"
#define DRIVER_VERSION "v0.13"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
......@@ -120,11 +122,19 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
#define USBLP_LAST_PROTOCOL 3
#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
/*
* some arbitrary status buffer size;
* need a status buffer that is allocated via kmalloc(), not on stack
*/
#define STATUS_BUF_SIZE 8
struct usblp {
struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */
char *buf; /* writeurb->transfer_buffer */
char *writebuf; /* write transfer_buffer */
char *readbuf; /* read transfer_buffer */
char *statusbuf; /* status transfer_buffer */
struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */
......@@ -289,13 +299,14 @@ static int usblp_check_status(struct usblp *usblp, int err)
unsigned char status, newerr = 0;
int error;
error = usblp_read_status (usblp, &status);
error = usblp_read_status (usblp, usblp->statusbuf);
if (error < 0) {
err("usblp%d: error %d reading printer status",
usblp->minor, error);
return 0;
}
status = *usblp->statusbuf;
if (~status & LP_PERRORP) {
newerr = 3;
if (status & LP_POUTPA) newerr = 1;
......@@ -375,8 +386,12 @@ static void usblp_cleanup (struct usblp *usblp)
usb_deregister_dev (1, usblp->minor);
info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->writebuf, usblp->writeurb->transfer_dma);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->writeurb->transfer_dma);
kfree (usblp->device_id_string);
kfree (usblp->statusbuf);
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
kfree (usblp);
......@@ -841,11 +856,27 @@ static int usblp_probe(struct usb_interface *intf,
goto abort_minor;
}
/* Malloc write/read buffers in one chunk. We somewhat wastefully
usblp->writebuf = usblp->readbuf = NULL;
usblp->writeurb->transfer_flags = URB_NO_DMA_MAP;
usblp->readurb->transfer_flags = URB_NO_DMA_MAP;
/* Malloc write & read buffers. We somewhat wastefully
* malloc both regardless of bidirectionality, because the
* alternate setting can be changed later via an ioctl. */
if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
err("out of memory for buf");
if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
err("out of memory for write buf");
goto abort_minor;
}
if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->readurb->transfer_dma))) {
err("out of memory for read buf");
goto abort_minor;
}
/* Allocate buffer for printer status */
usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
if (!usblp->statusbuf) {
err("out of memory for statusbuf");
goto abort_minor;
}
......@@ -900,10 +931,16 @@ static int usblp_probe(struct usb_interface *intf,
usb_deregister_dev (1, usblp->minor);
abort:
if (usblp) {
if (usblp->writebuf)
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->writebuf, usblp->writeurb->transfer_dma);
if (usblp->readbuf)
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->writeurb->transfer_dma);
if (usblp->statusbuf) kfree(usblp->statusbuf);
if (usblp->device_id_string) kfree(usblp->device_id_string);
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
if (usblp->buf) kfree(usblp->buf);
if (usblp->device_id_string) kfree(usblp->device_id_string);
kfree(usblp);
}
return -EIO;
......@@ -1021,7 +1058,7 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
usb_sndbulkpipe(usblp->dev,
usblp->protocol[protocol].epwrite->bEndpointAddress),
usblp->buf, 0,
usblp->writebuf, 0,
usblp_bulk_write, usblp);
usblp->bidir = (usblp->protocol[protocol].epread != 0);
......@@ -1029,7 +1066,7 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
usb_fill_bulk_urb(usblp->readurb, usblp->dev,
usb_rcvbulkpipe(usblp->dev,
usblp->protocol[protocol].epread->bEndpointAddress),
usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
usblp->readbuf, USBLP_BUF_SIZE,
usblp_bulk_read, usblp);
usblp->current_protocol = protocol;
......
......@@ -148,23 +148,31 @@ usb_descriptor_attr (bcdDevice, "%04x\n")
usb_descriptor_attr (bDeviceClass, "%02x\n")
usb_descriptor_attr (bDeviceSubClass, "%02x\n")
usb_descriptor_attr (bDeviceProtocol, "%02x\n")
usb_descriptor_attr (bNumConfigurations, "%d\n")
void usb_create_driverfs_dev_files (struct usb_device *udev)
{
struct device *dev = &udev->dev;
/* current configuration's attributes */
device_create_file (dev, &dev_attr_bNumInterfaces);
device_create_file (dev, &dev_attr_bConfigurationValue);
device_create_file (dev, &dev_attr_bmAttributes);
device_create_file (dev, &dev_attr_bMaxPower);
/* device attributes */
device_create_file (dev, &dev_attr_idVendor);
device_create_file (dev, &dev_attr_idProduct);
device_create_file (dev, &dev_attr_bcdDevice);
device_create_file (dev, &dev_attr_bDeviceClass);
device_create_file (dev, &dev_attr_bDeviceSubClass);
device_create_file (dev, &dev_attr_bDeviceProtocol);
device_create_file (dev, &dev_attr_bNumConfigurations);
/* speed varies depending on how you connect the device */
device_create_file (dev, &dev_attr_speed);
// FIXME iff there are other speed configs, show how many
if (udev->descriptor.iManufacturer)
device_create_file (dev, &dev_attr_manufacturer);
......
......@@ -23,6 +23,11 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
......@@ -32,13 +37,6 @@
#include <linux/pci.h> /* for hcd->pdev and dma addressing */
#include <asm/byteorder.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
#include "hcd.h"
......@@ -1090,6 +1088,7 @@ static int hcd_unlink_urb (struct urb *urb)
{
struct hcd_dev *dev;
struct usb_hcd *hcd = 0;
struct device *sys = 0;
unsigned long flags;
struct completion_splice splice;
int retval;
......@@ -1110,38 +1109,31 @@ static int hcd_unlink_urb (struct urb *urb)
*/
spin_lock_irqsave (&urb->lock, flags);
spin_lock (&hcd_data_lock);
if (!urb->hcpriv || urb->transfer_flags & URB_TIMEOUT_KILLED) {
retval = -EINVAL;
goto done;
}
if (!urb->dev || !urb->dev->bus) {
retval = -ENODEV;
goto done;
}
/* giveback clears dev; non-null means it's linked at this level */
dev = urb->dev->hcpriv;
sys = &urb->dev->dev;
hcd = urb->dev->bus->hcpriv;
if (!dev || !hcd) {
retval = -ENODEV;
goto done;
}
/* Except for interrupt transfers, any status except -EINPROGRESS
* means the HCD already started to unlink this URB from the hardware.
* So there's no more work to do.
*
* For interrupt transfers, this is the only way to trigger unlinking
* from the hardware. Since we (currently) overload urb->status to
* tell the driver to unlink, error status might get clobbered ...
* unless that transfer hasn't yet restarted. One such case is when
* the URB gets unlinked from its completion handler.
if (!urb->hcpriv) {
retval = -EINVAL;
goto done;
}
/* Any status except -EINPROGRESS means something already started to
* unlink this URB from the hardware. So there's no more work to do.
*
* FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
* FIXME use better explicit urb state
*/
if (urb->status != -EINPROGRESS
&& usb_pipetype (urb->pipe) != PIPE_INTERRUPT) {
if (urb->status != -EINPROGRESS) {
retval = -EINVAL;
goto done;
}
......@@ -1150,9 +1142,7 @@ static int hcd_unlink_urb (struct urb *urb)
* lower level hcd code is always async, locking on urb->status
* updates; an intercepted completion unblocks us.
*/
if ((urb->transfer_flags & URB_TIMEOUT_KILLED))
urb->status = -ETIMEDOUT;
else if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
if (in_interrupt ()) {
dbg ("non-async unlink in_interrupt");
retval = -EWOULDBLOCK;
......@@ -1177,29 +1167,34 @@ static int hcd_unlink_urb (struct urb *urb)
retval = 0;
} else {
retval = hcd->driver->urb_dequeue (hcd, urb);
// FIXME: if retval and we tried to splice, whoa!!
if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
/* hcds shouldn't really fail these calls, but... */
if (retval) {
dev_dbg (*sys, "dequeue %p --> %d\n", urb, retval);
if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
spin_lock_irqsave (&urb->lock, flags);
urb->complete = splice.complete;
urb->context = splice.context;
spin_unlock_irqrestore (&urb->lock, flags);
}
goto bye;
}
}
/* block till giveback, if needed */
if (!(urb->transfer_flags & (URB_ASYNC_UNLINK|URB_TIMEOUT_KILLED))
&& HCD_IS_RUNNING (hcd->state)
&& !retval) {
dbg ("%s: wait for giveback urb %p",
hcd->self.bus_name, urb);
wait_for_completion (&splice.done);
} else if ((urb->transfer_flags & URB_ASYNC_UNLINK) && retval == 0) {
if (urb->transfer_flags & URB_ASYNC_UNLINK)
return -EINPROGRESS;
}
goto bye;
dev_dbg (*sys, "wait for giveback urb %p\n", urb);
wait_for_completion (&splice.done);
return 0;
done:
spin_unlock (&hcd_data_lock);
spin_unlock_irqrestore (&urb->lock, flags);
bye:
if (retval)
dbg ("%s: hcd_unlink_urb fail %d",
hcd ? hcd->self.bus_name : "(no bus?)",
retval);
if (retval && sys)
dev_dbg (*sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
return retval;
}
......
......@@ -67,7 +67,7 @@ static void generic_release (struct device_driver * drv)
}
static struct device_driver usb_generic_driver = {
.name = "generic",
.name = "usb",
.bus = &usb_bus_type,
.probe = generic_probe,
.remove = generic_remove,
......@@ -514,17 +514,10 @@ static int usb_device_match (struct device *dev, struct device_driver *drv)
* or other modules, configure the device, and more. Drivers can provide
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
*
* Some synchronization is important: removes can't start processing
* before the add-device processing completes, and vice versa. That keeps
* a stack of USB-related identifiers stable while they're in use. If we
* know that agents won't complete after they return (such as by forking
* a process that completes later), it's enough to just waitpid() for the
* agent -- as is currently done.
*
* The reason: we know we're called either from khubd (the typical case)
* or from root hub initialization (init, kapmd, modprobe, etc). In both
* cases, we know no other thread can recycle our address, since we must
* already have been serialized enough to prevent that.
* We're called either from khubd (the typical case) or from root hub
* (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
* device (and this configuration!) are still present.
*/
static int usb_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
......@@ -579,7 +572,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
scratch += length;
#endif
/* per-device configuration hacks are common */
/* per-device configurations are common */
envp [i++] = scratch;
length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x",
usb_dev->descriptor.idVendor,
......@@ -604,10 +597,9 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
if (usb_dev->descriptor.bDeviceClass == 0) {
int alt = intf->act_altsetting;
/* a simple/common case: one config, one interface, one driver
* with current altsetting being a reasonable setting.
* everything needs a smart agent and usbfs; or can rely on
* device-specific binding policies.
/* 2.4 only exposed interface zero. in 2.5, hotplug
* agents are called for all interfaces, and can use
* $DEVPATH/bInterfaceNumber if necessary.
*/
envp [i++] = scratch;
length += snprintf (scratch, buffer_size - length,
......@@ -949,6 +941,24 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
int i;
int j;
/*
* Set the driver for the usb device to point to the "generic" driver.
* This prevents the main usb device from being sent to the usb bus
* probe function. Yes, it's a hack, but a nice one :)
*
* Do it asap, so more driver model stuff (like the device.h message
* utilities) can be used in hcd submit/unlink code paths.
*/
usb_generic_driver.bus = &usb_bus_type;
dev->dev.parent = parent;
dev->dev.driver = &usb_generic_driver;
dev->dev.bus = &usb_bus_type;
if (dev->dev.bus_id[0] == 0)
sprintf (&dev->dev.bus_id[0], "%d-%s",
dev->bus->busnum, dev->devpath);
/* USB device state == default ... it's not usable yet */
/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
* it's fixed size except for full speed devices.
*/
......@@ -1010,6 +1020,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
}
/* USB device state == addressed ... still not usable */
err = usb_get_device_descriptor(dev);
if (err < (signed)sizeof(dev->descriptor)) {
if (err < 0)
......@@ -1042,6 +1054,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
return 1;
}
/* USB device state == configured ... tell the world! */
dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",
dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
set_device_description (dev);
......@@ -1051,23 +1065,10 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
#endif
/*
* Set the driver for the usb device to point to the "generic" driver.
* This prevents the main usb device from being sent to the usb bus
* probe function. Yes, it's a hack, but a nice one :)
*/
usb_generic_driver.bus = &usb_bus_type;
dev->dev.parent = parent;
dev->dev.driver = &usb_generic_driver;
dev->dev.bus = &usb_bus_type;
if (dev->dev.bus_id[0] == 0)
sprintf (&dev->dev.bus_id[0], "%d-%s",
dev->bus->busnum, dev->devpath);
/* put into sysfs, with device and config specific files */
err = device_register (&dev->dev);
if (err)
return err;
/* add the USB device specific driverfs files */
usb_create_driverfs_dev_files (dev);
/* Register all of the interfaces for this device with the driver core.
......
......@@ -49,7 +49,7 @@ config USB_OHCI_HCD
The module will be called ohci-hcd.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
config USB_UHCI_HCD_ALT
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
depends on USB
---help---
......
......@@ -5,7 +5,7 @@
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD_ALT) += uhci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
......
......@@ -272,6 +272,7 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
{
u32 scratch;
u32 hw_curr;
struct list_head *entry;
struct ehci_qtd *td;
unsigned temp;
......@@ -279,20 +280,22 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
char *next = *nextp;
scratch = cpu_to_le32p (&qh->hw_info1);
temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x",
hw_curr = cpu_to_le32p (&qh->hw_current);
temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x %08x)",
qh, scratch & 0x007f,
speed_char (scratch),
(scratch >> 8) & 0x000f,
scratch, cpu_to_le32p (&qh->hw_info2));
scratch, cpu_to_le32p (&qh->hw_info2),
hw_curr, cpu_to_le32p (&qh->hw_token));
size -= temp;
next += temp;
list_for_each (entry, &qh->qtd_list) {
td = list_entry (entry, struct ehci_qtd,
qtd_list);
td = list_entry (entry, struct ehci_qtd, qtd_list);
scratch = cpu_to_le32p (&td->hw_token);
temp = snprintf (next, size,
"\n\ttd/%p %s len=%d %08x urb %p",
"\n\t%std/%p %s len=%d %08x urb %p",
(hw_curr == td->qtd_dma) ? "*" : "",
td, ({ char *tmp;
switch ((scratch>>8)&0x03) {
case 0: tmp = "out"; break;
......@@ -552,8 +555,8 @@ show_registers (struct device *dev, char *buf, size_t count, loff_t off)
size -= temp;
next += temp;
temp = snprintf (next, size, "complete %ld unlink %ld qpatch %ld\n",
ehci->stats.complete, ehci->stats.unlink, ehci->stats.qpatch);
temp = snprintf (next, size, "complete %ld unlink %ld\n",
ehci->stats.complete, ehci->stats.unlink);
size -= temp;
next += temp;
#endif
......
......@@ -494,8 +494,8 @@ static void ehci_stop (struct usb_hcd *hcd)
#ifdef EHCI_STATS
dbg ("irq normal %ld err %ld reclaim %ld",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
dbg ("complete %ld unlink %ld qpatch %ld",
ehci->stats.complete, ehci->stats.unlink, ehci->stats.qpatch);
dbg ("complete %ld unlink %ld",
ehci->stats.complete, ehci->stats.unlink);
#endif
dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
......
......@@ -58,19 +58,23 @@ static void ehci_hcd_free (struct usb_hcd *hcd)
/* Allocate the key transfer structures from the previously allocated pool */
static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
static void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
{
struct ehci_qtd *qtd;
dma_addr_t dma;
qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
if (qtd != 0) {
memset (qtd, 0, sizeof *qtd);
qtd->qtd_dma = dma;
qtd->hw_next = EHCI_LIST_END;
qtd->hw_alt_next = EHCI_LIST_END;
INIT_LIST_HEAD (&qtd->qtd_list);
}
}
static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
{
struct ehci_qtd *qtd;
dma_addr_t dma;
qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
if (qtd != 0)
ehci_qtd_init (qtd, dma);
return qtd;
}
......@@ -87,12 +91,21 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
qh = (struct ehci_qh *)
pci_pool_alloc (ehci->qh_pool, flags, &dma);
if (qh) {
if (!qh)
return qh;
memset (qh, 0, sizeof *qh);
atomic_set (&qh->refcount, 1);
qh->qh_dma = dma;
// INIT_LIST_HEAD (&qh->qh_list);
INIT_LIST_HEAD (&qh->qtd_list);
/* dummy td enables safe urb queuing */
qh->dummy = ehci_qtd_alloc (ehci, flags);
if (qh->dummy == 0) {
dbg ("no dummy td");
pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
qh = 0;
}
return qh;
}
......@@ -115,6 +128,8 @@ static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh)
dbg ("unused qh not empty!");
BUG ();
}
if (qh->dummy)
ehci_qtd_free (ehci, qh->dummy);
pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
}
......
......@@ -85,7 +85,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
/* update halted (but potentially linked) qh */
static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
static void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
{
qh->hw_current = 0;
qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
......@@ -221,17 +221,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
struct urb *urb = qtd->urb;
u32 token = 0;
/* hc's on-chip qh overlay cache can overwrite our idea of
* next qtd ptrs, if we appended a qtd while the queue was
* advancing. (because we don't use dummy qtds.)
*/
if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current
&& qtd->hw_next != qh->hw_qtd_next) {
qh->hw_alt_next = qtd->hw_alt_next;
qh->hw_qtd_next = qtd->hw_next;
COUNT (ehci->stats.qpatch);
}
/* clean up any state from previous QTD ...*/
if (last) {
if (likely (last->urb != urb)) {
......@@ -495,8 +484,7 @@ qh_urb_transaction (
}
/* by default, enable interrupt on urb completion */
// ... do it always, unless we switch over to dummy qtds
// if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
return head;
......@@ -661,8 +649,15 @@ ehci_qh_make (
/* initialize sw and hw queues with these qtds */
if (!list_empty (qtd_list)) {
struct ehci_qtd *qtd;
/* hc's list view ends with dummy td; we might update it */
qtd = list_entry (qtd_list->prev, struct ehci_qtd, qtd_list);
qtd->hw_next = QTD_NEXT (qh->dummy->qtd_dma);
list_splice (qtd_list, &qh->qtd_list);
qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list));
qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
qh_update (qh, qtd);
} else {
qh->hw_qtd_next = qh->hw_alt_next = EHCI_LIST_END;
}
......@@ -767,39 +762,48 @@ static struct ehci_qh *qh_append_tds (
/* append to tds already queued to this qh? */
if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
struct ehci_qtd *last_qtd;
u32 hw_next;
struct ehci_qtd *dummy;
dma_addr_t dma;
u32 token;
/* update the last qtd's "next" pointer */
// dbg_qh ("non-empty qh", ehci, qh);
last_qtd = list_entry (qh->qtd_list.prev,
/* to avoid racing the HC, use the dummy td instead of
* the first td of our list (becomes new dummy). both
* tds stay deactivated until we're done, when the
* HC is allowed to fetch the old dummy (4.10.2).
*/
token = qtd->hw_token;
qtd->hw_token = 0;
dummy = qh->dummy;
// dbg ("swap td %p with dummy %p", qtd, dummy);
dma = dummy->qtd_dma;
*dummy = *qtd;
dummy->qtd_dma = dma;
list_del (&qtd->qtd_list);
list_add (&dummy->qtd_list, qtd_list);
ehci_qtd_init (qtd, qtd->qtd_dma);
qh->dummy = qtd;
/* hc must see the new dummy at list end */
qtd = list_entry (qh->qtd_list.prev,
struct ehci_qtd, qtd_list);
hw_next = QTD_NEXT (qtd->qtd_dma);
last_qtd->hw_next = hw_next;
/* previous urb allows short rx? maybe optimize. */
if (!(last_qtd->urb->transfer_flags & URB_SHORT_NOT_OK)
&& (epnum & 0x10)) {
// only the last QTD for now
last_qtd->hw_alt_next = hw_next;
}
qtd->hw_next = QTD_NEXT (dma);
/* qh_completions() may need to patch the qh overlay if
* the hc was advancing this queue while we appended.
* we know it can: last_qtd->hw_token has IOC set.
*
* or: use a dummy td (so the overlay gets the next td
* only when we set its active bit); fewer irqs.
*/
/* let the hc process these next qtds */
wmb ();
dummy->hw_token = token;
/* no URB queued */
} else {
// dbg_qh ("empty qh", ehci, qh);
struct ehci_qtd *last_qtd;
/* NOTE: we already canceled any queued URBs
* when the endpoint halted.
*/
/* make sure hc sees current dummy at the end */
last_qtd = list_entry (qtd_list->prev,
struct ehci_qtd, qtd_list);
last_qtd->hw_next = QTD_NEXT (qh->dummy->qtd_dma);
// dbg_qh ("empty qh", ehci, qh);
/* usb_clear_halt() means qh data toggle gets reset */
if (unlikely (!usb_gettoggle (urb->dev,
......
......@@ -31,11 +31,6 @@ struct ehci_stats {
/* termination of urbs from core */
unsigned long complete;
unsigned long unlink;
/* qhs patched to recover from td queueing race
* (can avoid by using 'dummy td', allowing fewer irqs)
*/
unsigned long qpatch;
};
/* ehci_hcd->lock guards shared data against other CPUs:
......@@ -311,6 +306,7 @@ struct ehci_qh {
dma_addr_t qh_dma; /* address of qh */
union ehci_shadow qh_next; /* ptr to qh; or periodic */
struct list_head qtd_list; /* sw qtd list */
struct ehci_qtd *dummy;
atomic_t refcount;
......
......@@ -840,7 +840,7 @@ probe_scanner(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev (intf);
struct scn_usb_data *scn;
struct usb_host_interface *interface;
struct usb_host_endpoint *endpoint;
struct usb_endpoint_descriptor *endpoint;
int ep_cnt;
int ix;
......@@ -911,7 +911,6 @@ probe_scanner(struct usb_interface *intf,
}
interface = intf->altsetting;
endpoint = &interface->endpoint[0];
/*
* Start checking for two bulk endpoints OR two bulk endpoints *and* one
......@@ -929,22 +928,23 @@ probe_scanner(struct usb_interface *intf,
ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0;
while (ep_cnt < interface->desc.bNumEndpoints) {
endpoint = &interface->endpoint[ep_cnt].desc;
if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
if (!have_bulk_in && IS_EP_BULK_IN(endpoint)) {
ep_cnt++;
have_bulk_in = ep_cnt;
dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
continue;
}
if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
if (!have_bulk_out && IS_EP_BULK_OUT(endpoint)) {
ep_cnt++;
have_bulk_out = ep_cnt;
dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
continue;
}
if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) {
if (!have_intr && IS_EP_INTR(endpoint)) {
ep_cnt++;
have_intr = ep_cnt;
dbg("probe_scanner: intr_ep:%d", have_intr);
......
......@@ -211,10 +211,10 @@ static struct usb_device_id scanner_device_ids [] = {
MODULE_DEVICE_TABLE (usb, scanner_device_ids);
#define IS_EP_BULK(ep) ((ep).desc.bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep).desc.bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
#define IS_EP_BULK(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
......
......@@ -1214,7 +1214,6 @@ static struct video_device vicam_template = {
.type = VID_TYPE_CAPTURE,
.hardware = VID_HARDWARE_VICAM,
.fops = &vicam_fops,
// .initialize = vicam_video_init,
.minor = -1,
};
......
......@@ -550,6 +550,74 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/*-------------------------------------------------------------------------*/
static void unlink1_callback (struct urb *urb)
{
int status = urb->status;
// we "know" -EPIPE (stall) never happens
if (!status)
status = usb_submit_urb (urb, SLAB_ATOMIC);
if (status) {
if (status == -ECONNRESET || status == -ENOENT)
status = 0;
urb->status = status;
complete ((struct completion *) urb->context);
}
}
static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
{
struct urb *urb;
struct completion completion;
int retval = 0;
init_completion (&completion);
urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
if (async)
urb->transfer_flags |= URB_ASYNC_UNLINK;
urb->context = &completion;
urb->complete = unlink1_callback;
/* keep the endpoint busy. there are lots of hc/hcd-internal
* states, and testing should get to all of them over time.
*
* FIXME want additional tests for when endpoint is STALLing
* due to errors, or is just NAKing requests.
*/
if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) {
dbg ("submit/unlink fail %d", retval);
return retval;
}
/* unlinking that should always work. variable delay tests more
* hcd states and code paths, even with little other system load.
*/
wait_ms (jiffies % (2 * INTERRUPT_RATE));
retval = usb_unlink_urb (urb);
if (!(retval == 0 || retval == -EINPROGRESS)) {
dbg ("submit/unlink fail %d", retval);
return retval;
}
wait_for_completion (&completion);
retval = urb->status;
simple_free_urb (urb);
return retval;
}
static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
{
int retval = 0;
/* test sync and async paths */
retval = unlink1 (dev, pipe, len, 1);
if (!retval)
retval = unlink1 (dev, pipe, len, 0);
return retval;
}
/*-------------------------------------------------------------------------*/
/* We only have this one interface to user space, through usbfs.
* User mode code can scan usbfs to find N different devices (maybe on
* different busses) to use when testing, and allocate one thread per
......@@ -560,7 +628,8 @@ static int ch9_postconfig (struct usbtest_dev *dev)
* video capture, and so on. Run different tests at different times, in
* different sequences. Nothing here should interact with other devices,
* except indirectly by consuming USB bandwidth and CPU resources for test
* threads and request completion.
* threads and request completion. But the only way to know that for sure
* is to test when HC queues are in use by many devices.
*/
static int
......@@ -761,13 +830,35 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
dbg ("ch9 subset failed, iterations left %d", i);
break;
/* test cases for the unlink/cancel codepaths need a thread to
* usb_unlink_urb() or usg_sg_cancel(), and a way to check if
* the urb/sg_request was properly canceled.
*
* for the unlink-queued cases, the usb_sg_*() code uses/tests
* the "streamed" cleanup mode, not the "packet" one
*/
// case 10: queued control
/* simple non-queued unlinks (ring with one urb) */
case 11:
if (dev->in_pipe == 0 || !param->length)
break;
retval = 0;
dbg ("%s TEST 11: unlink %d reads of %d",
dev->id, param->iterations, param->length);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = unlink_simple (dev, dev->in_pipe, param->length);
if (retval)
dbg ("unlink reads failed, iterations left %d", i);
break;
case 12:
if (dev->out_pipe == 0 || !param->length)
break;
retval = 0;
dbg ("%s TEST 12: unlink %d writes of %d",
dev->id, param->iterations, param->length);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = unlink_simple (dev, dev->out_pipe, param->length);
if (retval)
dbg ("unlink writes failed, iterations left %d", i);
break;
// FIXME unlink from queue (ring with N urbs)
// FIXME scatterlist cancel (needs helper thread)
}
do_gettimeofday (&param->duration);
......
......@@ -124,20 +124,23 @@ config USB_RTL8150
module, say M here and read <file:Documentation/modules.txt>.
config USB_USBNET
tristate "USB-to-USB Networking cable device support"
tristate "USB-to-USB Networking for cables, PDAs and other devices"
depends on USB && NET
---help---
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
(GeneLink), NetChip and Prolific. Intelligent USB devices could also
use this approach to provide Internet access, using standard USB
cabling. You can find these chips also on some motherboards with
USB PC2PC support.
(GeneLink), NetChip and Prolific. Some motherboards with USB PC2PC
support include such chips.
Intelligent USB devices, such as PDAs running Linux (like Yopy
and Zaurus, or iPaqs after upgrading to Linux) can use the same
approach to provide Internet access.
These links will have names like "usb0", "usb1", etc. They act
like two-node Ethernets, so you can use 802.1d Ethernet Bridging
(CONFIG_BRIDGE) to simplify your network routing.
(CONFIG_BRIDGE) to simplify your network routing. For more
information see <http://www.linux-usb.org/usbnet/>.
This code is also available as a kernel module (code which can be
inserted in and removed from the running kernel whenever you want).
......
......@@ -128,15 +128,8 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
result = usb_stor_bulk_msg (us, fxfr, opipe,
FCM_PACKET_LENGTH, &partial);
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n",
US_DEBUGP ("Freecom readdata xport failure: r=%d, p=%d\n",
result, partial);
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_readdata(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("Done issuing read request: %d %d\n", result, partial);
......@@ -171,15 +164,8 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
result = usb_stor_bulk_msg (us, fxfr, opipe,
FCM_PACKET_LENGTH, &partial);
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n",
US_DEBUGP ("Freecom writedata xport failure: r=%d, p=%d\n",
result, partial);
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_writedata(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("Done issuing write request: %d %d\n",
......@@ -238,13 +224,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
return USB_STOR_TRANSPORT_ERROR;
}
......@@ -253,12 +232,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
US_DEBUGP("foo Status result %d %d\n", result, partial);
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -293,13 +266,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
return USB_STOR_TRANSPORT_ERROR;
}
......@@ -308,12 +274,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
FCM_PACKET_LENGTH, &partial);
US_DEBUGP("bar Status result %d %d\n", result, partial);
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
......@@ -372,10 +332,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
FCM_PACKET_LENGTH, &partial);
US_DEBUG(pdump ((void *) fst, partial));
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP ("freecom_transport: transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
......@@ -401,10 +357,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP ("freecom_transport: transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
......
......@@ -130,8 +130,6 @@
#define ISD200_TRANSPORT_GOOD 0 /* Transport good, command good */
#define ISD200_TRANSPORT_FAILED 1 /* Transport good, command failed */
#define ISD200_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
#define ISD200_TRANSPORT_ABORTED 3 /* Transport aborted */
#define ISD200_TRANSPORT_SHORT 4 /* Transport short */
/* driver action codes */
#define ACTION_READ_STATUS 0
......@@ -394,138 +392,6 @@ void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
***********************************************************************/
/**************************************************************************
* ISD200 Bulk Transport
*
* Note: This routine was copied from the usb_stor_Bulk_transport routine
* located in the transport.c source file. The scsi command is limited to
* only 12 bytes while the CDB for the ISD200 must be 16 bytes.
*/
int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
union ata_cdb *AtaCdb, unsigned char AtaCdbLength )
{
struct bulk_cb_wrap bcb;
struct bulk_cs_wrap bcs;
int result;
unsigned int transfer_length;
int dir = srb->sc_data_direction;
srb->sc_data_direction = SCSI_DATA_WRITE;
transfer_length = usb_stor_transfer_length(srb);
srb->sc_data_direction = dir;
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->target << 4;
bcb.Length = AtaCdbLength;
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, AtaCdb, bcb.Length);
/* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
le32_to_cpu(bcb.Signature), bcb.Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD)
return ISD200_TRANSPORT_ERROR;
/* if the command transfered well, then we go to the data stage */
if (transfer_length) {
unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("Bulk data transfer result 0x%x\n", result);
/* if it was aborted, we need to indicate that */
if (result == USB_STOR_XFER_ABORTED)
return ISD200_TRANSPORT_ABORTED;
if (result == USB_STOR_XFER_ERROR)
return ISD200_TRANSPORT_ERROR;
}
/* See flow chart on pg 15 of the Bulk Only Transport spec for
* an explanation of how this code works.
*/
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
/* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) {
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
/* if the command was aborted, indicate that */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
}
}
/* if we still have a failure at this point, we're in trouble */
US_DEBUGP("Bulk status result = %d\n", result);
if (result != USB_STOR_XFER_GOOD)
return ISD200_TRANSPORT_ERROR;
/* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag,
bcs.Residue, bcs.Status);
if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) ||
bcs.Tag != bcb.Tag ||
bcs.Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return ISD200_TRANSPORT_ERROR;
}
/* based on the status code, we report good or bad */
switch (bcs.Status) {
case US_BULK_STAT_OK:
/* command good -- note that we could be short on data */
if (srb->resid > 0)
return ISD200_TRANSPORT_SHORT;
return ISD200_TRANSPORT_GOOD;
case US_BULK_STAT_FAIL:
/* command failed */
return ISD200_TRANSPORT_FAILED;
case US_BULK_STAT_PHASE:
/* phase error */
usb_stor_Bulk_reset(us);
return ISD200_TRANSPORT_ERROR;
}
/* we should never get here, but if we do, we're in trouble */
return ISD200_TRANSPORT_ERROR;
}
/**************************************************************************
* isd200_action
*
......@@ -612,9 +478,11 @@ static int isd200_action( struct us_data *us, int action,
break;
}
status = isd200_Bulk_transport(us, &srb, &ata, sizeof(ata.generic));
if (status != ISD200_TRANSPORT_GOOD &&
status != ISD200_TRANSPORT_SHORT) {
memcpy(srb.cmnd, &ata, sizeof(ata.generic));
status = usb_stor_Bulk_transport(&srb, us);
if (status == USB_STOR_TRANSPORT_GOOD)
status = ISD200_GOOD;
else {
US_DEBUGP(" isd200_action(0x%02x) error: %d\n",action,status);
status = ISD200_ERROR;
/* need to reset device here */
......@@ -669,8 +537,8 @@ void isd200_invoke_transport( struct us_data *us,
/* send the command to the transport layer */
srb->resid = 0;
transferStatus = isd200_Bulk_transport(us, srb, ataCdb,
sizeof(ataCdb->generic));
memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic));
transferStatus = usb_stor_Bulk_transport(srb, us);
/* if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
......@@ -683,32 +551,31 @@ void isd200_invoke_transport( struct us_data *us,
switch (transferStatus) {
case ISD200_TRANSPORT_GOOD:
case USB_STOR_TRANSPORT_GOOD:
/* Indicate a good result */
srb->result = GOOD << 1;
break;
case ISD200_TRANSPORT_ABORTED:
/* if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
*/
US_DEBUGP("-- transport indicates command was aborted\n");
srb->result = DID_ABORT << 16;
break;
case ISD200_TRANSPORT_FAILED:
case USB_STOR_TRANSPORT_FAILED:
US_DEBUGP("-- transport indicates command failure\n");
need_auto_sense = 1;
break;
case ISD200_TRANSPORT_ERROR:
US_DEBUGP("-- transport indicates transport failure\n");
case USB_STOR_TRANSPORT_ERROR:
US_DEBUGP("-- transport indicates transport error\n");
srb->result = DID_ERROR << 16;
break;
/* Need reset here */
return;
case ISD200_TRANSPORT_SHORT:
srb->result = GOOD << 1;
if (!((srb->cmnd[0] == REQUEST_SENSE) ||
default:
US_DEBUGP("-- transport indicates unknown error\n");
srb->result = DID_ERROR << 16;
/* Need reset here */
return;
}
if ((srb->resid > 0) &&
!((srb->cmnd[0] == REQUEST_SENSE) ||
(srb->cmnd[0] == INQUIRY) ||
(srb->cmnd[0] == MODE_SENSE) ||
(srb->cmnd[0] == LOG_SENSE) ||
......@@ -716,27 +583,29 @@ void isd200_invoke_transport( struct us_data *us,
US_DEBUGP("-- unexpectedly short transfer\n");
need_auto_sense = 1;
}
break;
default:
US_DEBUGP("-- transport indicates unknown failure\n");
srb->result = DID_ERROR << 16;
}
if (need_auto_sense) {
result = isd200_read_regs(us);
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("-- auto-sense aborted\n");
srb->result = DID_ABORT << 16;
} else if (result == ISD200_GOOD)
return;
}
if (result == ISD200_GOOD) {
isd200_build_sense(us, srb);
srb->result = CHECK_CONDITION << 1;
/* If things are really okay, then let's show that */
if ((srb->sense_buffer[2] & 0xf) == 0x0)
srb->result = GOOD << 1;
} else
srb->result = DID_ERROR << 16;
}
/* Regardless of auto-sense, if we _know_ we have an error
* condition, show that in the result code
*/
if (transferStatus == ISD200_TRANSPORT_FAILED)
if (transferStatus == USB_STOR_TRANSPORT_FAILED)
srb->result = CHECK_CONDITION << 1;
}
......
/*
* Common routines for a handful of drivers.
* Unrelated to CF/SM - just USB stuff.
*
* This is mostly a thin layer on top of transport.c.
* It converts routines that return values like -EPIPE
* into routines that return USB_STOR_TRANSPORT_ABORTED etc.
*
* There is also some debug printing here.
* Unrelated to CF/SM - just scatter-gather stuff.
*/
#include "debug.h"
#include "transport.h"
#include "usb.h"
#include "raw_bulk.h"
/*
......
......@@ -103,7 +103,7 @@ static int detect(struct SHT *sht)
*
* NOTE: There is no contention here, because we're already deregistered
* the driver and we're doing each virtual host in turn, not in parallel
* Synchronization: BLK, no spinlock.
* Synchronization: BKL, no spinlock.
*/
static int release(struct Scsi_Host *psh)
{
......
......@@ -562,12 +562,6 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
value, index, data, size);
US_DEBUGP("usb_stor_control_msg returned %d\n", result);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("-- transfer aborted\n");
return USB_STOR_XFER_ABORTED;
}
/* a stall indicates a protocol error */
if (result == -EPIPE) {
US_DEBUGP("-- stall on control pipe\n");
......@@ -624,12 +618,6 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
return USB_STOR_XFER_STALLED;
}
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("-- transfer aborted\n");
return USB_STOR_XFER_ABORTED;
}
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
......@@ -669,7 +657,7 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* initialize the scatter-gather request block */
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %d bytes, "
"%d entires\n", length, num_sg);
"%d entries\n", length, num_sg);
result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, SLAB_NOIO);
if (result) {
......@@ -691,26 +679,27 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
}
}
/* wait for the completion of the transfer */
usb_sg_wait(us->current_sg);
clear_bit(US_FLIDX_CANCEL_SG, &us->flags);
result = us->current_sg->status;
partial = us->current_sg->bytes;
US_DEBUGP("usb_sg_wait() returned %d xferrerd %d/%d\n",
US_DEBUGP("usb_sg_wait() returned %d xferred %d/%d\n",
result, partial, length);
if (act_len)
*act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
US_DEBUGP("clearing endpoint halt for pipe 0x%x, "
"stalled at %d bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've tried this a few times already */
/* NAK - that means we've retried this a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
......@@ -738,10 +727,10 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
*
* Nore that this uses the usb_stor_bulk_transfer_buf() and
* Nore that this uses usb_stor_bulk_transfer_buf() and
* usb_stor_bulk_transfer_sglist() to achieve its goals --
* this function simply determines whether we're going to use
* scatter-gather or not, and acts apropriately.
* scatter-gather or not, and acts appropriately.
*/
int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
char *buf, unsigned int length_left, int use_sg, int *residual)
......@@ -1116,15 +1105,6 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
if (result != USB_STOR_XFER_GOOD) {
/* Reset flag for status notification */
clear_bit(US_FLIDX_IP_WANTED, &us->flags);
}
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_control_msg(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR;
}
......@@ -1137,12 +1117,6 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("CBI data stage result is 0x%x\n", result);
/* report any errors */
if (result == USB_STOR_XFER_ABORTED) {
clear_bit(US_FLIDX_IP_WANTED, &us->flags);
return USB_STOR_TRANSPORT_ABORTED;
}
if (result == USB_STOR_XFER_ERROR) {
clear_bit(US_FLIDX_IP_WANTED, &us->flags);
return USB_STOR_TRANSPORT_ERROR;
......@@ -1157,7 +1131,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("CBI interrupt aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
......@@ -1222,13 +1196,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check the return code for the command */
US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR;
......@@ -1242,15 +1209,9 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("CB data stage result is 0x%x\n", result);
/* report any errors */
if (result == USB_STOR_XFER_ABORTED) {
return USB_STOR_TRANSPORT_ABORTED;
}
if (result == USB_STOR_XFER_ERROR) {
if (result == USB_STOR_XFER_ERROR)
return USB_STOR_TRANSPORT_ERROR;
}
}
/* STATUS STAGE */
/* NOTE: CB does not have a status stage. Silly, I know. So
......@@ -1319,12 +1280,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -1336,10 +1291,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("Bulk data transfer result 0x%x\n", result);
/* if it was aborted, we need to indicate that */
if (result == USB_STOR_XFER_ABORTED)
return USB_STOR_TRANSPORT_ABORTED;
if (result == USB_STOR_XFER_ERROR)
return USB_STOR_TRANSPORT_ERROR;
}
......@@ -1353,12 +1304,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
/* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) {
......@@ -1366,12 +1311,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
}
/* if we still have a failure at this point, we're in trouble */
......
......@@ -121,7 +121,6 @@ struct bulk_cs_wrap {
#define USB_STOR_XFER_SHORT 1 /* transfered less than expected */
#define USB_STOR_XFER_STALLED 2 /* endpoint stalled */
#define USB_STOR_XFER_ERROR 3 /* transfer died in the middle */
#define USB_STOR_XFER_ABORTED 4 /* transfer canceled */
/*
* Transport return codes
......
......@@ -437,41 +437,6 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = GOOD << 1;
}
/* Most USB devices can't handle START_STOP. But we
* need something for media-change, so we'll use TUR
* instead.
*
* We specifically allow this command through if either:
* (a) it's a load/eject command (cmnd[4] & 2)
* (b) it's a multi-target unit (i.e. legacy SCSI adaptor)
*/
else if (us->srb->cmnd[0] == START_STOP &&
!(us->srb->cmnd[4] & 2) &&
!(us->flags & US_FL_SCM_MULT_TARG)) {
unsigned char saved_cdb[16]; /* largest SCSI-III cmd */
__u8 old_cmd_len;
US_DEBUGP("Converting START_STOP to TUR\n");
/* save old command */
memcpy(saved_cdb, us->srb->cmnd, us->srb->cmd_len);
old_cmd_len = us->srb->cmd_len;
/* set up new command -- preserve LUN */
us->srb->cmd_len = 6;
memset(us->srb->cmnd, 0, us->srb->cmd_len);
us->srb->cmnd[0] = TEST_UNIT_READY;
us->srb->cmnd[1] = saved_cdb[1] & 0xE0;
/* do command */
US_DEBUG(usb_stor_show_command(us->srb));
us->proto_handler(us->srb, us);
/* restore original command */
us->srb->cmd_len = old_cmd_len;
memcpy(us->srb->cmnd, saved_cdb, us->srb->cmd_len);
}
/* we've got a command, let's do it! */
else {
US_DEBUG(usb_stor_show_command(us->srb));
......
......@@ -443,19 +443,19 @@ extern void firmware_uregister(struct subsystem *);
#ifdef DEBUG
#define dev_dbg(dev, format, arg...) \
printk (KERN_DEBUG "%s %s: " format , \
dev.driver->name , dev.bus_id , ## arg)
(dev).driver->name , (dev).bus_id , ## arg)
#else
#define dev_dbg(dev, format, arg...) do {} while (0)
#endif
#define dev_err(dev, format, arg...) \
printk (KERN_ERR "%s %s: " format , \
dev.driver->name , dev.bus_id , ## arg)
(dev).driver->name , (dev).bus_id , ## arg)
#define dev_info(dev, format, arg...) \
printk (KERN_INFO "%s %s: " format , \
dev.driver->name , dev.bus_id , ## arg)
(dev).driver->name , (dev).bus_id , ## arg)
#define dev_warn(dev, format, arg...) \
printk (KERN_WARN "%s %s: " format , \
dev.driver->name , dev.bus_id , ## arg)
printk (KERN_WARNING "%s %s: " format , \
(dev).driver->name , (dev).bus_id , ## arg)
#endif /* _DEVICE_H_ */
......@@ -105,7 +105,7 @@ extern const char *print_tainted(void);
extern void dump_stack(void);
#if DEBUG
#ifdef DEBUG
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
#else
......
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