aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorGuido Kiener <guido@kiener-muenchen.de>2018-09-12 04:51:04 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-20 07:04:02 -0400
commitcbe743f1333b23040d1312afd58224dbd58fcc25 (patch)
treee38a1e08ba740125b7191e14b6fff349a7e9bece /drivers/usb/class
parentdfee02ac4bce6374c9769fe31f20794309341fa0 (diff)
usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN
Add parameter 'tag' to function usbtmc_ioctl_abort_bulk_in_tag() for future versions. Remove calculation of max_size (=wMaxPacketSize) and wrong condition (actual == max_size) in while loop. An abort operation should always flush the complete Bulk-IN until a short packet is received. Return error code ENOMSG when transfer (specified by given tag) is not in progress and device returns code USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS. Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k). Using USBTMC_SIZE_IOBUFFER is deprecated. Use common macro USB_CTRL_GET_TIMEOUT instead of USBTMC_TIMEOUT. Check only bit 0 (field bmAbortBulkIn) of the CHECK_ABORT_BULK_IN_STATUS response, since other bits are reserved and can change in future versions. Signed-off-by: Guido Kiener <guido.kiener@rohde-schwarz.com> Reviewed-by: Steve Bayless <steve_bayless@keysight.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/usbtmc.c119
1 files changed, 51 insertions, 68 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 11b2c8632d91..0b05aaa0247c 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -270,18 +270,17 @@ static int usbtmc_release(struct inode *inode, struct file *file)
270 return 0; 270 return 0;
271} 271}
272 272
273static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) 273static int usbtmc_ioctl_abort_bulk_in_tag(struct usbtmc_device_data *data,
274 u8 tag)
274{ 275{
275 u8 *buffer; 276 u8 *buffer;
276 struct device *dev; 277 struct device *dev;
277 int rv; 278 int rv;
278 int n; 279 int n;
279 int actual; 280 int actual;
280 struct usb_host_interface *current_setting;
281 int max_size;
282 281
283 dev = &data->intf->dev; 282 dev = &data->intf->dev;
284 buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); 283 buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL);
285 if (!buffer) 284 if (!buffer)
286 return -ENOMEM; 285 return -ENOMEM;
287 286
@@ -289,86 +288,87 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
289 usb_rcvctrlpipe(data->usb_dev, 0), 288 usb_rcvctrlpipe(data->usb_dev, 0),
290 USBTMC_REQUEST_INITIATE_ABORT_BULK_IN, 289 USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
291 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, 290 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
292 data->bTag_last_read, data->bulk_in, 291 tag, data->bulk_in,
293 buffer, 2, USBTMC_TIMEOUT); 292 buffer, 2, USB_CTRL_GET_TIMEOUT);
294 293
295 if (rv < 0) { 294 if (rv < 0) {
296 dev_err(dev, "usb_control_msg returned %d\n", rv); 295 dev_err(dev, "usb_control_msg returned %d\n", rv);
297 goto exit; 296 goto exit;
298 } 297 }
299 298
300 dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); 299 dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x with tag %02x\n",
300 buffer[0], buffer[1]);
301 301
302 if (buffer[0] == USBTMC_STATUS_FAILED) { 302 if (buffer[0] == USBTMC_STATUS_FAILED) {
303 /* No transfer in progress and the Bulk-OUT FIFO is empty. */
303 rv = 0; 304 rv = 0;
304 goto exit; 305 goto exit;
305 } 306 }
306 307
307 if (buffer[0] != USBTMC_STATUS_SUCCESS) { 308 if (buffer[0] == USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS) {
308 dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", 309 /* The device returns this status if either:
309 buffer[0]); 310 * - There is a transfer in progress, but the specified bTag
310 rv = -EPERM; 311 * does not match.
312 * - There is no transfer in progress, but the Bulk-OUT FIFO
313 * is not empty.
314 */
315 rv = -ENOMSG;
311 goto exit; 316 goto exit;
312 } 317 }
313 318
314 max_size = 0; 319 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
315 current_setting = data->intf->cur_altsetting; 320 dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
316 for (n = 0; n < current_setting->desc.bNumEndpoints; n++) 321 buffer[0]);
317 if (current_setting->endpoint[n].desc.bEndpointAddress ==
318 data->bulk_in)
319 max_size = usb_endpoint_maxp(&current_setting->endpoint[n].desc);
320
321 if (max_size == 0) {
322 dev_err(dev, "Couldn't get wMaxPacketSize\n");
323 rv = -EPERM; 322 rv = -EPERM;
324 goto exit; 323 goto exit;
325 } 324 }
326 325
327 dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size);
328
329 n = 0; 326 n = 0;
330 327
331 do { 328usbtmc_abort_bulk_in_status:
332 dev_dbg(dev, "Reading from bulk in EP\n"); 329 dev_dbg(dev, "Reading from bulk in EP\n");
333 330
334 rv = usb_bulk_msg(data->usb_dev, 331 /* Data must be present. So use low timeout 300 ms */
335 usb_rcvbulkpipe(data->usb_dev, 332 rv = usb_bulk_msg(data->usb_dev,
336 data->bulk_in), 333 usb_rcvbulkpipe(data->usb_dev,
337 buffer, USBTMC_SIZE_IOBUFFER, 334 data->bulk_in),
338 &actual, USBTMC_TIMEOUT); 335 buffer, USBTMC_BUFSIZE,
336 &actual, 300);
339 337
340 n++; 338 print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, 16, 1,
339 buffer, actual, true);
341 340
342 if (rv < 0) { 341 n++;
343 dev_err(dev, "usb_bulk_msg returned %d\n", rv); 342
343 if (rv < 0) {
344 dev_err(dev, "usb_bulk_msg returned %d\n", rv);
345 if (rv != -ETIMEDOUT)
344 goto exit; 346 goto exit;
345 } 347 }
346 } while ((actual == max_size) &&
347 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
348 348
349 if (actual == max_size) { 349 if (actual == USBTMC_BUFSIZE)
350 goto usbtmc_abort_bulk_in_status;
351
352 if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) {
350 dev_err(dev, "Couldn't clear device buffer within %d cycles\n", 353 dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
351 USBTMC_MAX_READS_TO_CLEAR_BULK_IN); 354 USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
352 rv = -EPERM; 355 rv = -EPERM;
353 goto exit; 356 goto exit;
354 } 357 }
355 358
356 n = 0;
357
358usbtmc_abort_bulk_in_status:
359 rv = usb_control_msg(data->usb_dev, 359 rv = usb_control_msg(data->usb_dev,
360 usb_rcvctrlpipe(data->usb_dev, 0), 360 usb_rcvctrlpipe(data->usb_dev, 0),
361 USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS, 361 USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
362 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, 362 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
363 0, data->bulk_in, buffer, 0x08, 363 0, data->bulk_in, buffer, 0x08,
364 USBTMC_TIMEOUT); 364 USB_CTRL_GET_TIMEOUT);
365 365
366 if (rv < 0) { 366 if (rv < 0) {
367 dev_err(dev, "usb_control_msg returned %d\n", rv); 367 dev_err(dev, "usb_control_msg returned %d\n", rv);
368 goto exit; 368 goto exit;
369 } 369 }
370 370
371 dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); 371 dev_dbg(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
372 372
373 if (buffer[0] == USBTMC_STATUS_SUCCESS) { 373 if (buffer[0] == USBTMC_STATUS_SUCCESS) {
374 rv = 0; 374 rv = 0;
@@ -376,43 +376,26 @@ usbtmc_abort_bulk_in_status:
376 } 376 }
377 377
378 if (buffer[0] != USBTMC_STATUS_PENDING) { 378 if (buffer[0] != USBTMC_STATUS_PENDING) {
379 dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); 379 dev_err(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
380 rv = -EPERM; 380 rv = -EPERM;
381 goto exit; 381 goto exit;
382 } 382 }
383 383
384 if (buffer[1] == 1) 384 if ((buffer[1] & 1) > 0) {
385 do { 385 /* The device has 1 or more queued packets the Host can read */
386 dev_dbg(dev, "Reading from bulk in EP\n"); 386 goto usbtmc_abort_bulk_in_status;
387
388 rv = usb_bulk_msg(data->usb_dev,
389 usb_rcvbulkpipe(data->usb_dev,
390 data->bulk_in),
391 buffer, USBTMC_SIZE_IOBUFFER,
392 &actual, USBTMC_TIMEOUT);
393
394 n++;
395
396 if (rv < 0) {
397 dev_err(dev, "usb_bulk_msg returned %d\n", rv);
398 goto exit;
399 }
400 } while ((actual == max_size) &&
401 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
402
403 if (actual == max_size) {
404 dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
405 USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
406 rv = -EPERM;
407 goto exit;
408 } 387 }
409 388
410 goto usbtmc_abort_bulk_in_status; 389 /* The Host must send CHECK_ABORT_BULK_IN_STATUS at a later time. */
411 390 rv = -EAGAIN;
412exit: 391exit:
413 kfree(buffer); 392 kfree(buffer);
414 return rv; 393 return rv;
394}
415 395
396static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
397{
398 return usbtmc_ioctl_abort_bulk_in_tag(data, data->bTag_last_read);
416} 399}
417 400
418static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) 401static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)