diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-23 15:33:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-23 15:33:02 -0400 |
commit | c44dead70a841d90ddc01968012f323c33217c9e (patch) | |
tree | 85489ebe9b9a3413cd8ee197ffb40c8aa8d97e63 /drivers/usb/misc/usbtest.c | |
parent | 99dff5856220a02b8711f2e8746413ea6e53ccf6 (diff) | |
parent | d5f6db9e1aff6ccf1876224f152c0268b0c8a992 (diff) |
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
...
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 131 |
1 files changed, 126 insertions, 5 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ff9a01f8d40..bb10846affc 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -268,9 +268,9 @@ static inline void simple_fill_buf(struct urb *urb) | |||
268 | } | 268 | } |
269 | } | 269 | } |
270 | 270 | ||
271 | static inline unsigned buffer_offset(void *buf) | 271 | static inline unsigned long buffer_offset(void *buf) |
272 | { | 272 | { |
273 | return (unsigned)buf & (ARCH_KMALLOC_MINALIGN - 1); | 273 | return (unsigned long)buf & (ARCH_KMALLOC_MINALIGN - 1); |
274 | } | 274 | } |
275 | 275 | ||
276 | static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb) | 276 | 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) | |||
329 | 329 | ||
330 | static void simple_free_urb(struct urb *urb) | 330 | static void simple_free_urb(struct urb *urb) |
331 | { | 331 | { |
332 | unsigned offset = buffer_offset(urb->transfer_buffer); | 332 | unsigned long offset = buffer_offset(urb->transfer_buffer); |
333 | 333 | ||
334 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 334 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
335 | usb_free_coherent( | 335 | usb_free_coherent( |
@@ -1030,6 +1030,8 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) | |||
1030 | req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0); | 1030 | req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0); |
1031 | /* device descriptor size == 18 bytes */ | 1031 | /* device descriptor size == 18 bytes */ |
1032 | len = udev->descriptor.bMaxPacketSize0; | 1032 | len = udev->descriptor.bMaxPacketSize0; |
1033 | if (udev->speed == USB_SPEED_SUPER) | ||
1034 | len = 512; | ||
1033 | switch (len) { | 1035 | switch (len) { |
1034 | case 8: | 1036 | case 8: |
1035 | len = 24; | 1037 | len = 24; |
@@ -1195,6 +1197,104 @@ static int unlink_simple(struct usbtest_dev *dev, int pipe, int len) | |||
1195 | 1197 | ||
1196 | /*-------------------------------------------------------------------------*/ | 1198 | /*-------------------------------------------------------------------------*/ |
1197 | 1199 | ||
1200 | struct queued_ctx { | ||
1201 | struct completion complete; | ||
1202 | atomic_t pending; | ||
1203 | unsigned num; | ||
1204 | int status; | ||
1205 | struct urb **urbs; | ||
1206 | }; | ||
1207 | |||
1208 | static void unlink_queued_callback(struct urb *urb) | ||
1209 | { | ||
1210 | int status = urb->status; | ||
1211 | struct queued_ctx *ctx = urb->context; | ||
1212 | |||
1213 | if (ctx->status) | ||
1214 | goto done; | ||
1215 | if (urb == ctx->urbs[ctx->num - 4] || urb == ctx->urbs[ctx->num - 2]) { | ||
1216 | if (status == -ECONNRESET) | ||
1217 | goto done; | ||
1218 | /* What error should we report if the URB completed normally? */ | ||
1219 | } | ||
1220 | if (status != 0) | ||
1221 | ctx->status = status; | ||
1222 | |||
1223 | done: | ||
1224 | if (atomic_dec_and_test(&ctx->pending)) | ||
1225 | complete(&ctx->complete); | ||
1226 | } | ||
1227 | |||
1228 | static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num, | ||
1229 | unsigned size) | ||
1230 | { | ||
1231 | struct queued_ctx ctx; | ||
1232 | struct usb_device *udev = testdev_to_usbdev(dev); | ||
1233 | void *buf; | ||
1234 | dma_addr_t buf_dma; | ||
1235 | int i; | ||
1236 | int retval = -ENOMEM; | ||
1237 | |||
1238 | init_completion(&ctx.complete); | ||
1239 | atomic_set(&ctx.pending, 1); /* One more than the actual value */ | ||
1240 | ctx.num = num; | ||
1241 | ctx.status = 0; | ||
1242 | |||
1243 | buf = usb_alloc_coherent(udev, size, GFP_KERNEL, &buf_dma); | ||
1244 | if (!buf) | ||
1245 | return retval; | ||
1246 | memset(buf, 0, size); | ||
1247 | |||
1248 | /* Allocate and init the urbs we'll queue */ | ||
1249 | ctx.urbs = kcalloc(num, sizeof(struct urb *), GFP_KERNEL); | ||
1250 | if (!ctx.urbs) | ||
1251 | goto free_buf; | ||
1252 | for (i = 0; i < num; i++) { | ||
1253 | ctx.urbs[i] = usb_alloc_urb(0, GFP_KERNEL); | ||
1254 | if (!ctx.urbs[i]) | ||
1255 | goto free_urbs; | ||
1256 | usb_fill_bulk_urb(ctx.urbs[i], udev, pipe, buf, size, | ||
1257 | unlink_queued_callback, &ctx); | ||
1258 | ctx.urbs[i]->transfer_dma = buf_dma; | ||
1259 | ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
1260 | } | ||
1261 | |||
1262 | /* Submit all the URBs and then unlink URBs num - 4 and num - 2. */ | ||
1263 | for (i = 0; i < num; i++) { | ||
1264 | atomic_inc(&ctx.pending); | ||
1265 | retval = usb_submit_urb(ctx.urbs[i], GFP_KERNEL); | ||
1266 | if (retval != 0) { | ||
1267 | dev_err(&dev->intf->dev, "submit urbs[%d] fail %d\n", | ||
1268 | i, retval); | ||
1269 | atomic_dec(&ctx.pending); | ||
1270 | ctx.status = retval; | ||
1271 | break; | ||
1272 | } | ||
1273 | } | ||
1274 | if (i == num) { | ||
1275 | usb_unlink_urb(ctx.urbs[num - 4]); | ||
1276 | usb_unlink_urb(ctx.urbs[num - 2]); | ||
1277 | } else { | ||
1278 | while (--i >= 0) | ||
1279 | usb_unlink_urb(ctx.urbs[i]); | ||
1280 | } | ||
1281 | |||
1282 | if (atomic_dec_and_test(&ctx.pending)) /* The extra count */ | ||
1283 | complete(&ctx.complete); | ||
1284 | wait_for_completion(&ctx.complete); | ||
1285 | retval = ctx.status; | ||
1286 | |||
1287 | free_urbs: | ||
1288 | for (i = 0; i < num; i++) | ||
1289 | usb_free_urb(ctx.urbs[i]); | ||
1290 | kfree(ctx.urbs); | ||
1291 | free_buf: | ||
1292 | usb_free_coherent(udev, size, buf, buf_dma); | ||
1293 | return retval; | ||
1294 | } | ||
1295 | |||
1296 | /*-------------------------------------------------------------------------*/ | ||
1297 | |||
1198 | static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) | 1298 | static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) |
1199 | { | 1299 | { |
1200 | int retval; | 1300 | int retval; |
@@ -1970,8 +2070,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
1970 | dev->in_iso_pipe, dev->iso_in, 0); | 2070 | dev->in_iso_pipe, dev->iso_in, 0); |
1971 | break; | 2071 | break; |
1972 | 2072 | ||
1973 | /* FIXME unlink from queue (ring with N urbs) */ | ||
1974 | |||
1975 | /* FIXME scatterlist cancel (needs helper thread) */ | 2073 | /* FIXME scatterlist cancel (needs helper thread) */ |
1976 | 2074 | ||
1977 | /* Tests for bulk I/O using DMA mapping by core and odd address */ | 2075 | /* 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) | |||
2064 | dev->in_iso_pipe, dev->iso_in, 1); | 2162 | dev->in_iso_pipe, dev->iso_in, 1); |
2065 | break; | 2163 | break; |
2066 | 2164 | ||
2165 | /* unlink URBs from a bulk-OUT queue */ | ||
2166 | case 24: | ||
2167 | if (dev->out_pipe == 0 || !param->length || param->sglen < 4) | ||
2168 | break; | ||
2169 | retval = 0; | ||
2170 | dev_info(&intf->dev, "TEST 17: unlink from %d queues of " | ||
2171 | "%d %d-byte writes\n", | ||
2172 | param->iterations, param->sglen, param->length); | ||
2173 | for (i = param->iterations; retval == 0 && i > 0; --i) { | ||
2174 | retval = unlink_queued(dev, dev->out_pipe, | ||
2175 | param->sglen, param->length); | ||
2176 | if (retval) { | ||
2177 | dev_err(&intf->dev, | ||
2178 | "unlink queued writes failed %d, " | ||
2179 | "iterations left %d\n", retval, i); | ||
2180 | break; | ||
2181 | } | ||
2182 | } | ||
2183 | break; | ||
2184 | |||
2067 | } | 2185 | } |
2068 | do_gettimeofday(¶m->duration); | 2186 | do_gettimeofday(¶m->duration); |
2069 | param->duration.tv_sec -= start.tv_sec; | 2187 | param->duration.tv_sec -= start.tv_sec; |
@@ -2192,6 +2310,9 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2192 | case USB_SPEED_HIGH: | 2310 | case USB_SPEED_HIGH: |
2193 | tmp = "high"; | 2311 | tmp = "high"; |
2194 | break; | 2312 | break; |
2313 | case USB_SPEED_SUPER: | ||
2314 | tmp = "super"; | ||
2315 | break; | ||
2195 | default: | 2316 | default: |
2196 | tmp = "unknown"; | 2317 | tmp = "unknown"; |
2197 | break; | 2318 | break; |