Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (205 commits)
  USB: EHCI: Remove SPARC_LEON {read,write}_be definitions from ehci.h
  USB: UHCI: Support big endian GRUSBHC HC
  sparc: add {read,write}*_be routines
  USB: UHCI: Add support for big endian descriptors
  USB: UHCI: Use ACCESS_ONCE rather than using a full compiler barrier
  USB: UHCI: Add support for big endian mmio
  usb-storage: Correct adjust_quirks to include latest flags
  usb/isp1760: Fix possible unlink problems
  usb/isp1760: Move function isp1760_endpoint_disable() within file.
  USB: remove remaining usages of hcd->state from usbcore and fix regression
  usb: musb: ux500: add configuration and build options for ux500 dma
  usb: musb: ux500: add dma glue layer for ux500
  usb: musb: ux500: add dma name for ux500
  usb: musb: ux500: add ux500 specific code for gadget side
  usb: musb: fix compile error
  usb-storage: fix up the unusual_realtek device list
  USB: gadget: f_audio: Fix invalid dereference of initdata
  EHCI: don't rescan interrupt QHs needlessly
  OHCI: fix regression caused by nVidia shutdown workaround
  USB: OTG: msm: Free VCCCX regulator even if we can't set the voltage
  ...
This commit is contained in:
Linus Torvalds
2011-05-23 12:33:02 -07:00
184 changed files with 14777 additions and 3506 deletions

View File

@@ -268,9 +268,9 @@ static inline void simple_fill_buf(struct urb *urb)
}
}
static inline unsigned buffer_offset(void *buf)
static inline unsigned long buffer_offset(void *buf)
{
return (unsigned)buf & (ARCH_KMALLOC_MINALIGN - 1);
return (unsigned long)buf & (ARCH_KMALLOC_MINALIGN - 1);
}
static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb)
@@ -329,7 +329,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
static void simple_free_urb(struct urb *urb)
{
unsigned offset = buffer_offset(urb->transfer_buffer);
unsigned long offset = buffer_offset(urb->transfer_buffer);
if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
usb_free_coherent(
@@ -1030,6 +1030,8 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0);
/* device descriptor size == 18 bytes */
len = udev->descriptor.bMaxPacketSize0;
if (udev->speed == USB_SPEED_SUPER)
len = 512;
switch (len) {
case 8:
len = 24;
@@ -1195,6 +1197,104 @@ static int unlink_simple(struct usbtest_dev *dev, int pipe, int len)
/*-------------------------------------------------------------------------*/
struct queued_ctx {
struct completion complete;
atomic_t pending;
unsigned num;
int status;
struct urb **urbs;
};
static void unlink_queued_callback(struct urb *urb)
{
int status = urb->status;
struct queued_ctx *ctx = urb->context;
if (ctx->status)
goto done;
if (urb == ctx->urbs[ctx->num - 4] || urb == ctx->urbs[ctx->num - 2]) {
if (status == -ECONNRESET)
goto done;
/* What error should we report if the URB completed normally? */
}
if (status != 0)
ctx->status = status;
done:
if (atomic_dec_and_test(&ctx->pending))
complete(&ctx->complete);
}
static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num,
unsigned size)
{
struct queued_ctx ctx;
struct usb_device *udev = testdev_to_usbdev(dev);
void *buf;
dma_addr_t buf_dma;
int i;
int retval = -ENOMEM;
init_completion(&ctx.complete);
atomic_set(&ctx.pending, 1); /* One more than the actual value */
ctx.num = num;
ctx.status = 0;
buf = usb_alloc_coherent(udev, size, GFP_KERNEL, &buf_dma);
if (!buf)
return retval;
memset(buf, 0, size);
/* Allocate and init the urbs we'll queue */
ctx.urbs = kcalloc(num, sizeof(struct urb *), GFP_KERNEL);
if (!ctx.urbs)
goto free_buf;
for (i = 0; i < num; i++) {
ctx.urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!ctx.urbs[i])
goto free_urbs;
usb_fill_bulk_urb(ctx.urbs[i], udev, pipe, buf, size,
unlink_queued_callback, &ctx);
ctx.urbs[i]->transfer_dma = buf_dma;
ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
}
/* Submit all the URBs and then unlink URBs num - 4 and num - 2. */
for (i = 0; i < num; i++) {
atomic_inc(&ctx.pending);
retval = usb_submit_urb(ctx.urbs[i], GFP_KERNEL);
if (retval != 0) {
dev_err(&dev->intf->dev, "submit urbs[%d] fail %d\n",
i, retval);
atomic_dec(&ctx.pending);
ctx.status = retval;
break;
}
}
if (i == num) {
usb_unlink_urb(ctx.urbs[num - 4]);
usb_unlink_urb(ctx.urbs[num - 2]);
} else {
while (--i >= 0)
usb_unlink_urb(ctx.urbs[i]);
}
if (atomic_dec_and_test(&ctx.pending)) /* The extra count */
complete(&ctx.complete);
wait_for_completion(&ctx.complete);
retval = ctx.status;
free_urbs:
for (i = 0; i < num; i++)
usb_free_urb(ctx.urbs[i]);
kfree(ctx.urbs);
free_buf:
usb_free_coherent(udev, size, buf, buf_dma);
return retval;
}
/*-------------------------------------------------------------------------*/
static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
{
int retval;
@@ -1970,8 +2070,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
dev->in_iso_pipe, dev->iso_in, 0);
break;
/* FIXME unlink from queue (ring with N urbs) */
/* FIXME scatterlist cancel (needs helper thread) */
/* Tests for bulk I/O using DMA mapping by core and odd address */
@@ -2064,6 +2162,26 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
dev->in_iso_pipe, dev->iso_in, 1);
break;
/* unlink URBs from a bulk-OUT queue */
case 24:
if (dev->out_pipe == 0 || !param->length || param->sglen < 4)
break;
retval = 0;
dev_info(&intf->dev, "TEST 17: unlink from %d queues of "
"%d %d-byte writes\n",
param->iterations, param->sglen, param->length);
for (i = param->iterations; retval == 0 && i > 0; --i) {
retval = unlink_queued(dev, dev->out_pipe,
param->sglen, param->length);
if (retval) {
dev_err(&intf->dev,
"unlink queued writes failed %d, "
"iterations left %d\n", retval, i);
break;
}
}
break;
}
do_gettimeofday(&param->duration);
param->duration.tv_sec -= start.tv_sec;
@@ -2192,6 +2310,9 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
case USB_SPEED_HIGH:
tmp = "high";
break;
case USB_SPEED_SUPER:
tmp = "super";
break;
default:
tmp = "unknown";
break;