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:
@@ -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(¶m->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;
|
||||
|
Reference in New Issue
Block a user