From patchwork Mon Jul 30 08:04:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548497 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 40F6F13BB for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0180F298DE for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9F18298EE; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 229FB298E2 for ; Mon, 30 Jul 2018 07:07:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726474AbeG3IlJ (ORCPT ); Mon, 30 Jul 2018 04:41:09 -0400 Received: from mr07.mx01.tldhost.de ([62.108.44.247]:51423 "EHLO mr07.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726416AbeG3IlJ (ORCPT ); Mon, 30 Jul 2018 04:41:09 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id D6193120EC5 for ; Mon, 30 Jul 2018 09:07:34 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id C44E1120EC3; Mon, 30 Jul 2018 09:07:34 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id B9AEB120EC3; Mon, 30 Jul 2018 09:07:32 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 01/22] usb: usbtmc: Add ioctl for generic requests on control Date: Mon, 30 Jul 2018 10:04:31 +0200 Message-Id: <20180730080452.15150-2-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070733.16376.62486@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add USBTMC_IOCTL_CTRL_REQUEST to send arbitrary requests on the control pipe. Used by specific applications of IVI Foundation, Inc. to implement VISA API functions: viUsbControlIn/Out. The maximum length of control request is set to 4k. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 77 ++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 15 +++++++ 2 files changed, 92 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 83ffa5a14c3d..f5603c835336 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -5,6 +5,7 @@ * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Greg Kroah-Hartman + * Copyright (C) 2018 IVI Foundation, Inc. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -36,6 +37,9 @@ /* Default USB timeout (in milliseconds) */ #define USBTMC_TIMEOUT 5000 +/* I/O buffer size used in generic read/write functions */ +#define USBTMC_BUFSIZE (4096) + /* * Maximum number of read cycles to empty bulk in endpoint during CLEAR and * ABORT_BULK_IN requests. Ends the loop if (for whatever reason) a short @@ -129,6 +133,14 @@ struct usbtmc_file_data { /* Forward declarations */ static struct usb_driver usbtmc_driver; +static void __user *u64_to_uptr(u64 value) +{ + if (in_compat_syscall()) + return compat_ptr(value); + else + return (void __user *)(unsigned long)value; +} + static void usbtmc_delete(struct kref *kref) { struct usbtmc_device_data *data = to_usbtmc_data(kref); @@ -1250,6 +1262,67 @@ static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) return rv; } +static int usbtmc_ioctl_request(struct usbtmc_device_data *data, + void __user *arg) +{ + struct device *dev = &data->intf->dev; + struct usbtmc_ctrlrequest request; + u8 *buffer = NULL; + int rv; + unsigned long res; + + res = copy_from_user(&request, arg, sizeof(struct usbtmc_ctrlrequest)); + if (res) + return -EFAULT; + + buffer = kmalloc(request.req.wLength, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if (request.req.wLength > USBTMC_BUFSIZE) + return -EMSGSIZE; + + if (request.req.wLength) { + buffer = kmalloc(request.req.wLength, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if ((request.req.bRequestType & USB_DIR_IN) == 0) { + /* Send control data to device */ + res = copy_from_user(buffer, u64_to_uptr(request.data), + request.req.wLength); + if (res) { + rv = -EFAULT; + goto exit; + } + } + } + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + request.req.bRequest, + request.req.bRequestType, + request.req.wValue, + request.req.wIndex, + buffer, request.req.wLength, USB_CTRL_GET_TIMEOUT); + + if (rv < 0) { + dev_err(dev, "%s failed %d\n", __func__, rv); + goto exit; + } + + if (rv && (request.req.bRequestType & USB_DIR_IN)) { + /* Read control data from device */ + res = copy_to_user(u64_to_uptr(request.data), buffer, rv); + if (res) + rv = -EFAULT; + } + + exit: + kfree(buffer); + return rv; +} + /* * Get the usb timeout value */ @@ -1366,6 +1439,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) retval = usbtmc_ioctl_abort_bulk_in(data); break; + case USBTMC_IOCTL_CTRL_REQUEST: + retval = usbtmc_ioctl_request(data, (void __user *)arg); + break; + case USBTMC_IOCTL_GET_TIMEOUT: retval = usbtmc_ioctl_get_timeout(file_data, (void __user *)arg); diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 729af2f861a4..95533118ac34 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -4,6 +4,7 @@ * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Greg Kroah-Hartman * Copyright (C) 2015 Dave Penkler + * Copyright (C) 2018 IVI Foundation, Inc. * * This file holds USB constants defined by the USB Device Class * and USB488 Subclass Definitions for Test and Measurement devices @@ -40,6 +41,19 @@ #define USBTMC488_REQUEST_GOTO_LOCAL 161 #define USBTMC488_REQUEST_LOCAL_LOCKOUT 162 +struct usbtmc_request { + __u8 bRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; +} __attribute__ ((packed)); + +struct usbtmc_ctrlrequest { + struct usbtmc_request req; + __u64 data; /* pointer to user space */ +} __attribute__ ((packed)); + struct usbtmc_termchar { __u8 term_char; __u8 term_char_enabled; @@ -53,6 +67,7 @@ struct usbtmc_termchar { #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4) #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6) #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) +#define USBTMC_IOCTL_CTRL_REQUEST _IOWR(USBTMC_IOC_NR, 8, struct usbtmc_ctrlrequest) #define USBTMC_IOCTL_GET_TIMEOUT _IOR(USBTMC_IOC_NR, 9, __u32) #define USBTMC_IOCTL_SET_TIMEOUT _IOW(USBTMC_IOC_NR, 10, __u32) #define USBTMC_IOCTL_EOM_ENABLE _IOW(USBTMC_IOC_NR, 11, __u8) From patchwork Mon Jul 30 08:04:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548489 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5152614BC for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 399A5298F1 for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2E072298FE; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B68F298EE for ; Mon, 30 Jul 2018 07:07:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726520AbeG3IlL (ORCPT ); Mon, 30 Jul 2018 04:41:11 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:46726 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726399AbeG3IlL (ORCPT ); Mon, 30 Jul 2018 04:41:11 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id A58E6120ED2 for ; Mon, 30 Jul 2018 09:07:35 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 907A8120EDE; Mon, 30 Jul 2018 09:07:35 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 7F150120ED6; Mon, 30 Jul 2018 09:07:33 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 02/22] usb: usbtmc: Add ioctl for vendor specific write Date: Mon, 30 Jul 2018 10:04:32 +0200 Message-Id: <20180730080452.15150-3-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070733.16393.76722@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The new ioctl USBTMC_IOCTL_WRITE sends a generic message to bulk OUT. This ioctl is used for vendor specific or asynchronous I/O as well. The message is split into chunks of 4k (page size). Message size is aligned to 32 bit boundaries. With flag USBTMC_FLAG_ASYNC the ioctl is non blocking. With flag USBTMC_FLAG_APPEND additional urbs are queued and out_status/out_transfer_size is not reset. EPOLLOUT | EPOLLWRNORM is signaled when all submitted urbs are completed. Flush flying urbs when file handle is closed or device is suspended or reset. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 376 ++++++++++++++++++++++++++++++++++- include/uapi/linux/usb/tmc.h | 14 ++ 2 files changed, 388 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index f5603c835336..b30935d8af6b 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -37,6 +37,8 @@ /* Default USB timeout (in milliseconds) */ #define USBTMC_TIMEOUT 5000 +/* Max number of urbs used in write transfers */ +#define MAX_URBS_IN_FLIGHT 16 /* I/O buffer size used in generic read/write functions */ #define USBTMC_BUFSIZE (4096) @@ -125,13 +127,24 @@ struct usbtmc_file_data { u32 timeout; u8 srq_byte; atomic_t srq_asserted; + u8 eom_val; u8 term_char; bool term_char_enabled; + + spinlock_t err_lock; /* lock for errors */ + + struct usb_anchor submitted; + + /* data for generic_write */ + struct semaphore limit_write_sem; + u32 out_transfer_size; + int out_status; }; /* Forward declarations */ static struct usb_driver usbtmc_driver; +static void usbtmc_draw_down(struct usbtmc_file_data *file_data); static void __user *u64_to_uptr(u64 value) { @@ -165,6 +178,10 @@ static int usbtmc_open(struct inode *inode, struct file *filp) if (!file_data) return -ENOMEM; + spin_lock_init(&file_data->err_lock); + sema_init(&file_data->limit_write_sem, MAX_URBS_IN_FLIGHT); + init_usb_anchor(&file_data->submitted); + data = usb_get_intfdata(intf); /* Protect reference to data from file structure until release */ kref_get(&data->kref); @@ -190,6 +207,36 @@ static int usbtmc_open(struct inode *inode, struct file *filp) return 0; } +/* + * usbtmc_flush - called before file handle is closed + */ +static int usbtmc_flush(struct file *file, fl_owner_t id) +{ + struct usbtmc_file_data *file_data; + struct usbtmc_device_data *data; + + file_data = file->private_data; + if (file_data == NULL) + return -ENODEV; + + data = file_data->data; + + /* wait for io to stop */ + mutex_lock(&data->io_mutex); + + usbtmc_draw_down(file_data); + + spin_lock_irq(&file_data->err_lock); + file_data->out_status = 0; + file_data->out_transfer_size = 0; + spin_unlock_irq(&file_data->err_lock); + + wake_up_interruptible_all(&data->waitq); + mutex_unlock(&data->io_mutex); + + return 0; +} + static int usbtmc_release(struct inode *inode, struct file *file) { struct usbtmc_file_data *file_data = file->private_data; @@ -622,6 +669,238 @@ static int usbtmc488_ioctl_trigger(struct usbtmc_file_data *file_data) return 0; } +static struct urb *usbtmc_create_urb(void) +{ + const size_t bufsize = USBTMC_BUFSIZE; + u8 *dmabuf = NULL; + struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!urb) + return NULL; + + dmabuf = kmalloc(bufsize, GFP_KERNEL); + if (!dmabuf) { + usb_free_urb(urb); + return NULL; + } + + urb->transfer_buffer = dmabuf; + urb->transfer_buffer_length = bufsize; + urb->transfer_flags |= URB_FREE_BUFFER; + return urb; +} + +static void usbtmc_write_bulk_cb(struct urb *urb) +{ + struct usbtmc_file_data *file_data = urb->context; + int wakeup = 0; + unsigned long flags; + + spin_lock_irqsave(&file_data->err_lock, flags); + file_data->out_transfer_size += urb->actual_length; + + /* sync/async unlink faults aren't errors */ + if (urb->status) { + if (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) + dev_err(&file_data->data->intf->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, urb->status); + + if (!file_data->out_status) { + file_data->out_status = urb->status; + wakeup = 1; + } + } + spin_unlock_irqrestore(&file_data->err_lock, flags); + + dev_dbg(&file_data->data->intf->dev, + "%s - write bulk total size: %u\n", + __func__, file_data->out_transfer_size); + + up(&file_data->limit_write_sem); + if (usb_anchor_empty(&file_data->submitted) || wakeup) + wake_up_interruptible(&file_data->data->waitq); +} + +static ssize_t usbtmc_generic_write(struct usbtmc_file_data *file_data, + const void __user *user_buffer, + u32 transfer_size, + u32 *transferred, + u32 flags) +{ + struct usbtmc_device_data *data = file_data->data; + struct device *dev; + u32 done = 0; + u32 remaining; + unsigned long expire; + const u32 bufsize = USBTMC_BUFSIZE; + struct urb *urb = NULL; + int retval = 0; + u32 timeout; + + *transferred = 0; + + /* Get pointer to private data structure */ + dev = &data->intf->dev; + + dev_dbg(dev, "%s: size=%u flags=0x%X sema=%u\n", + __func__, transfer_size, flags, + file_data->limit_write_sem.count); + + if (flags & USBTMC_FLAG_APPEND) { + spin_lock_irq(&file_data->err_lock); + retval = file_data->out_status; + spin_unlock_irq(&file_data->err_lock); + if (retval < 0) + return retval; + } else { + spin_lock_irq(&file_data->err_lock); + file_data->out_transfer_size = 0; + file_data->out_status = 0; + spin_unlock_irq(&file_data->err_lock); + } + + remaining = transfer_size; + if (remaining > INT_MAX) + remaining = INT_MAX; + + timeout = file_data->timeout; + expire = msecs_to_jiffies(timeout); + + while (remaining > 0) { + u32 this_part, aligned; + u8 *buffer = NULL; + + if (flags & USBTMC_FLAG_ASYNC) { + if (down_trylock(&file_data->limit_write_sem)) { + retval = (done)?(0):(-EAGAIN); + goto exit; + } + } else { + retval = down_timeout(&file_data->limit_write_sem, + expire); + if (retval < 0) { + retval = -ETIMEDOUT; + goto error; + } + } + + spin_lock_irq(&file_data->err_lock); + retval = file_data->out_status; + spin_unlock_irq(&file_data->err_lock); + if (retval < 0) { + up(&file_data->limit_write_sem); + goto error; + } + + /* prepare next urb to send */ + urb = usbtmc_create_urb(); + if (!urb) { + retval = -ENOMEM; + up(&file_data->limit_write_sem); + goto error; + } + buffer = urb->transfer_buffer; + + if (remaining > bufsize) + this_part = bufsize; + else + this_part = remaining; + + if (copy_from_user(buffer, user_buffer + done, this_part)) { + retval = -EFAULT; + up(&file_data->limit_write_sem); + goto error; + } + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, + 16, 1, buffer, this_part, true); + + /* fill bulk with 32 bit alignment to meet USBTMC specification + * (size + 3 & ~3) rounds up and simplifies user code + */ + aligned = (this_part + 3) & ~3; + dev_dbg(dev, "write(size:%u align:%u done:%u)\n", + (unsigned int)this_part, + (unsigned int)aligned, + (unsigned int)done); + + usb_fill_bulk_urb(urb, data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out), + urb->transfer_buffer, aligned, + usbtmc_write_bulk_cb, file_data); + + usb_anchor_urb(urb, &file_data->submitted); + retval = usb_submit_urb(urb, GFP_KERNEL); + if (unlikely(retval)) { + usb_unanchor_urb(urb); + up(&file_data->limit_write_sem); + goto error; + } + + usb_free_urb(urb); + urb = NULL; /* urb will be finally released by usb driver */ + + remaining -= this_part; + done += this_part; + } + + /* All urbs are on the fly */ + if (!(flags & USBTMC_FLAG_ASYNC)) { + if (!usb_wait_anchor_empty_timeout(&file_data->submitted, + timeout)) { + retval = -ETIMEDOUT; + goto error; + } + } + + retval = 0; + goto exit; + +error: + usb_kill_anchored_urbs(&file_data->submitted); +exit: + usb_free_urb(urb); + + spin_lock_irq(&file_data->err_lock); + if (!(flags & USBTMC_FLAG_ASYNC)) + done = file_data->out_transfer_size; + if (!retval && file_data->out_status) + retval = file_data->out_status; + spin_unlock_irq(&file_data->err_lock); + + *transferred = done; + + dev_dbg(dev, "%s: done=%u, retval=%d, urbstat=%d\n", + __func__, done, retval, file_data->out_status); + + return retval; +} + +static ssize_t usbtmc_ioctl_generic_write(struct usbtmc_file_data *file_data, + void __user *arg) +{ + struct usbtmc_message msg; + ssize_t retval = 0; + + /* mutex already locked */ + + if (copy_from_user(&msg, arg, sizeof(struct usbtmc_message))) + return -EFAULT; + + retval = usbtmc_generic_write(file_data, u64_to_uptr(msg.message), + msg.transfer_size, &msg.transferred, + msg.flags); + + if (put_user(msg.transferred, + &((struct usbtmc_message __user *)arg)->transferred)) + return -EFAULT; + + return retval; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint. * @transfer_size: number of bytes to request from the device. @@ -1089,6 +1368,15 @@ static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) return 0; } +static int usbtmc_ioctl_cancel_io(struct usbtmc_file_data *file_data) +{ + spin_lock_irq(&file_data->err_lock); + file_data->out_status = -ECANCELED; + spin_unlock_irq(&file_data->err_lock); + usb_kill_anchored_urbs(&file_data->submitted); + return 0; +} + static int get_capabilities(struct usbtmc_device_data *data) { struct device *dev = &data->usb_dev->dev; @@ -1463,6 +1751,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void __user *)arg); break; + case USBTMC_IOCTL_WRITE: + retval = usbtmc_ioctl_generic_write(file_data, + (void __user *)arg); + break; + case USBTMC488_IOCTL_GET_CAPS: retval = copy_to_user((void __user *)arg, &data->usb488_caps, @@ -1523,7 +1816,19 @@ static __poll_t usbtmc_poll(struct file *file, poll_table *wait) poll_wait(file, &data->waitq, wait); - mask = (atomic_read(&file_data->srq_asserted)) ? EPOLLPRI : 0; + mask = 0; + if (atomic_read(&file_data->srq_asserted)) + mask |= EPOLLPRI; + + if (usb_anchor_empty(&file_data->submitted)) + mask |= (EPOLLOUT | EPOLLWRNORM); + + spin_lock_irq(&file_data->err_lock); + if (file_data->out_status) + mask |= EPOLLERR; + spin_unlock_irq(&file_data->err_lock); + + dev_dbg(&data->intf->dev, "poll mask = %x\n", mask); no_poll: mutex_unlock(&data->io_mutex); @@ -1536,6 +1841,7 @@ static const struct file_operations fops = { .write = usbtmc_write, .open = usbtmc_open, .release = usbtmc_release, + .flush = usbtmc_flush, .unlocked_ioctl = usbtmc_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = usbtmc_ioctl, @@ -1761,6 +2067,7 @@ static int usbtmc_probe(struct usb_interface *intf, static void usbtmc_disconnect(struct usb_interface *intf) { struct usbtmc_device_data *data = usb_get_intfdata(intf); + struct list_head *elem; usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); @@ -1768,14 +2075,46 @@ static void usbtmc_disconnect(struct usb_interface *intf) mutex_lock(&data->io_mutex); data->zombie = 1; wake_up_interruptible_all(&data->waitq); + list_for_each(elem, &data->file_list) { + struct usbtmc_file_data *file_data; + + file_data = list_entry(elem, + struct usbtmc_file_data, + file_elem); + usb_kill_anchored_urbs(&file_data->submitted); + } mutex_unlock(&data->io_mutex); usbtmc_free_int(data); kref_put(&data->kref, usbtmc_delete); } +static void usbtmc_draw_down(struct usbtmc_file_data *file_data) +{ + int time; + + time = usb_wait_anchor_empty_timeout(&file_data->submitted, 1000); + if (!time) + usb_kill_anchored_urbs(&file_data->submitted); +} + static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) { - /* this driver does not have pending URBs */ + struct usbtmc_device_data *data = usb_get_intfdata(intf); + struct list_head *elem; + + if (!data) + return 0; + + mutex_lock(&data->io_mutex); + list_for_each(elem, &data->file_list) { + struct usbtmc_file_data *file_data; + + file_data = list_entry(elem, + struct usbtmc_file_data, + file_elem); + usbtmc_draw_down(file_data); + } + mutex_unlock(&data->io_mutex); return 0; } @@ -1784,6 +2123,37 @@ static int usbtmc_resume(struct usb_interface *intf) return 0; } +static int usbtmc_pre_reset(struct usb_interface *intf) +{ + struct usbtmc_device_data *data = usb_get_intfdata(intf); + struct list_head *elem; + + if (!data) + return 0; + + mutex_lock(&data->io_mutex); + + list_for_each(elem, &data->file_list) { + struct usbtmc_file_data *file_data; + + file_data = list_entry(elem, + struct usbtmc_file_data, + file_elem); + usbtmc_ioctl_cancel_io(file_data); + } + + return 0; +} + +static int usbtmc_post_reset(struct usb_interface *intf) +{ + struct usbtmc_device_data *data = usb_get_intfdata(intf); + + mutex_unlock(&data->io_mutex); + + return 0; +} + static struct usb_driver usbtmc_driver = { .name = "usbtmc", .id_table = usbtmc_devices, @@ -1791,6 +2161,8 @@ static struct usb_driver usbtmc_driver = { .disconnect = usbtmc_disconnect, .suspend = usbtmc_suspend, .resume = usbtmc_resume, + .pre_reset = usbtmc_pre_reset, + .post_reset = usbtmc_post_reset, }; module_usb_driver(usbtmc_driver); diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 95533118ac34..56faeb3b5f0f 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -59,6 +59,19 @@ struct usbtmc_termchar { __u8 term_char_enabled; } __attribute__ ((packed)); +/* + * usbtmc_message->flags: + */ +#define USBTMC_FLAG_ASYNC 0x0001 +#define USBTMC_FLAG_APPEND 0x0002 + +struct usbtmc_message { + __u32 transfer_size; /* size of bytes to transfer */ + __u32 transferred; /* size of received/written bytes */ + __u32 flags; /* bit 0: 0 = synchronous; 1 = asynchronous */ + __u64 message; /* pointer to header and data in user space */ +} __attribute__ ((packed)); + /* Request values for USBTMC driver's ioctl entry point */ #define USBTMC_IOC_NR 91 #define USBTMC_IOCTL_INDICATOR_PULSE _IO(USBTMC_IOC_NR, 1) @@ -72,6 +85,7 @@ struct usbtmc_termchar { #define USBTMC_IOCTL_SET_TIMEOUT _IOW(USBTMC_IOC_NR, 10, __u32) #define USBTMC_IOCTL_EOM_ENABLE _IOW(USBTMC_IOC_NR, 11, __u8) #define USBTMC_IOCTL_CONFIG_TERMCHAR _IOW(USBTMC_IOC_NR, 12, struct usbtmc_termchar) +#define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct usbtmc_message) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) From patchwork Mon Jul 30 08:04:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548501 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BD907A7F9 for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A9FA02851E for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A3CB28508; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BCC62298E7 for ; Mon, 30 Jul 2018 07:07:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726510AbeG3IlK (ORCPT ); Mon, 30 Jul 2018 04:41:10 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:43665 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726416AbeG3IlK (ORCPT ); Mon, 30 Jul 2018 04:41:10 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 6958F120E58 for ; Mon, 30 Jul 2018 09:07:36 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 515CC120EBE; Mon, 30 Jul 2018 09:07:36 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 495BE120E58; Mon, 30 Jul 2018 09:07:34 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 03/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_WRITE_RESULT Date: Mon, 30 Jul 2018 10:04:33 +0200 Message-Id: <20180730080452.15150-4-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070734.16410.77209@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ioctl USBTMC_IOCTL_WRITE_RESULT copies current out_transfer_size to given __u32 pointer and returns current out_status of the last (asnynchronous) USBTMC_IOCTL_WRITE call. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 25 +++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 1 + 2 files changed, 26 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index b30935d8af6b..32aef9e53bc5 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -901,6 +901,26 @@ static ssize_t usbtmc_ioctl_generic_write(struct usbtmc_file_data *file_data, return retval; } +/* + * Get the generic write result + */ +static ssize_t usbtmc_ioctl_write_result(struct usbtmc_file_data *file_data, + void __user *arg) +{ + u32 transferred; + int retval; + + spin_lock_irq(&file_data->err_lock); + transferred = file_data->out_transfer_size; + retval = file_data->out_status; + spin_unlock_irq(&file_data->err_lock); + + if (put_user(transferred, (__u32 __user *)arg)) + return -EFAULT; + + return retval; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint. * @transfer_size: number of bytes to request from the device. @@ -1756,6 +1776,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void __user *)arg); break; + case USBTMC_IOCTL_WRITE_RESULT: + retval = usbtmc_ioctl_write_result(file_data, + (void __user *)arg); + break; + case USBTMC488_IOCTL_GET_CAPS: retval = copy_to_user((void __user *)arg, &data->usb488_caps, diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 56faeb3b5f0f..4a47b11e4a7e 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -86,6 +86,7 @@ struct usbtmc_message { #define USBTMC_IOCTL_EOM_ENABLE _IOW(USBTMC_IOC_NR, 11, __u8) #define USBTMC_IOCTL_CONFIG_TERMCHAR _IOW(USBTMC_IOC_NR, 12, struct usbtmc_termchar) #define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct usbtmc_message) +#define USBTMC_IOCTL_WRITE_RESULT _IOWR(USBTMC_IOC_NR, 15, __u32) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) From patchwork Mon Jul 30 08:04:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548485 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A465513BB for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 95871298F1 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8A68029900; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8326E298F1 for ; Mon, 30 Jul 2018 07:07:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726532AbeG3IlM (ORCPT ); Mon, 30 Jul 2018 04:41:12 -0400 Received: from mr03.mx01.tldhost.de ([62.108.44.115]:33051 "EHLO mr03.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726476AbeG3IlL (ORCPT ); Mon, 30 Jul 2018 04:41:11 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 19B10120EC6 for ; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 0F3D5120EE2; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 0ADA0120EC0; Mon, 30 Jul 2018 09:07:35 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 04/22] usb: usbtmc: Add ioctl for vendor specific read Date: Mon, 30 Jul 2018 10:04:34 +0200 Message-Id: <20180730080452.15150-5-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> MIME-Version: 1.0 X-PPP-Message-ID: <20180730070735.16430.97962@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The USBTMC_IOCTL_READ call provides for generic synchronous and asynchronous reads on bulk IN to implement vendor specific library routines. Depending on transfer_size the function submits one or more urbs (up to 16) each with a size of up to 4kB. The flag USBTMC_FLAG_IGNORE_TRAILER can be used when the transmission size is already known. Then the function does not truncate the transfer_size to a multiple of 4 kB, but does reserve extra space to receive the final short or zero length packet. Note that the instrument is allowed to send up to wMaxPacketSize - 1 bytes at the end of a message to avoid sending a zero length packet. With flag USBTMC_FLAG_ASYNC the ioctl is non blocking. When no received data is available, the read function submits as many urbs as needed to receive transfer_size bytes. However the number of flying urbs (=4kB) is limited to 16 even with subsequent calls of this ioctl. Returns -EAGAIN when non blocking and no data is received. Signals EPOLLIN | EPOLLRDNORM when asynchronous urbs are ready to be read. In non blocking mode the usbtmc_message.message pointer may be NULL and the ioctl just submits urbs to initiate receiving data. However if data is already available due to a previous non blocking call the ioctl will return -EINVAL when the message pointer is NULL. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 336 ++++++++++++++++++++++++++++++++++- include/uapi/linux/usb/tmc.h | 2 + 2 files changed, 337 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 32aef9e53bc5..5edb548d9122 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -85,6 +85,9 @@ struct usbtmc_device_data { u8 bTag_last_write; /* needed for abort */ u8 bTag_last_read; /* needed for abort */ + /* packet size of IN bulk */ + u16 wMaxPacketSize; + /* data for interrupt in endpoint handling */ u8 bNotify1; u8 bNotify2; @@ -140,6 +143,13 @@ struct usbtmc_file_data { struct semaphore limit_write_sem; u32 out_transfer_size; int out_status; + + /* data for generic_read */ + u32 in_transfer_size; + int in_status; + int in_urbs_used; + struct usb_anchor in_anchor; + wait_queue_head_t wait_bulk_in; }; /* Forward declarations */ @@ -181,6 +191,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp) spin_lock_init(&file_data->err_lock); sema_init(&file_data->limit_write_sem, MAX_URBS_IN_FLIGHT); init_usb_anchor(&file_data->submitted); + init_usb_anchor(&file_data->in_anchor); + init_waitqueue_head(&file_data->wait_bulk_in); data = usb_get_intfdata(intf); /* Protect reference to data from file structure until release */ @@ -227,6 +239,9 @@ static int usbtmc_flush(struct file *file, fl_owner_t id) usbtmc_draw_down(file_data); spin_lock_irq(&file_data->err_lock); + file_data->in_status = 0; + file_data->in_transfer_size = 0; + file_data->in_urbs_used = 0; file_data->out_status = 0; file_data->out_transfer_size = 0; spin_unlock_irq(&file_data->err_lock); @@ -690,6 +705,307 @@ static struct urb *usbtmc_create_urb(void) return urb; } +static void usbtmc_read_bulk_cb(struct urb *urb) +{ + struct usbtmc_file_data *file_data = urb->context; + int status = urb->status; + unsigned long flags; + + /* sync/async unlink faults aren't errors */ + if (status) { + if (!(/* status == -ENOENT || */ + status == -ECONNRESET || + status == -EREMOTEIO || /* Short packet */ + status == -ESHUTDOWN)) + dev_err(&file_data->data->intf->dev, + "%s - nonzero read bulk status received: %d\n", + __func__, status); + + spin_lock_irqsave(&file_data->err_lock, flags); + if (!file_data->in_status) + file_data->in_status = status; + spin_unlock_irqrestore(&file_data->err_lock, flags); + } + + spin_lock_irqsave(&file_data->err_lock, flags); + file_data->in_transfer_size += urb->actual_length; + dev_dbg(&file_data->data->intf->dev, + "%s - total size: %u current: %d status: %d\n", + __func__, file_data->in_transfer_size, + urb->actual_length, status); + spin_unlock_irqrestore(&file_data->err_lock, flags); + usb_anchor_urb(urb, &file_data->in_anchor); + + wake_up_interruptible(&file_data->wait_bulk_in); + wake_up_interruptible(&file_data->data->waitq); +} + +static inline bool usbtmc_do_transfer(struct usbtmc_file_data *file_data) +{ + bool data_or_error; + + spin_lock_irq(&file_data->err_lock); + data_or_error = !usb_anchor_empty(&file_data->in_anchor) + || file_data->in_status; + spin_unlock_irq(&file_data->err_lock); + dev_dbg(&file_data->data->intf->dev, "%s: returns %d\n", __func__, + data_or_error); + return data_or_error; +} + +static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data, + void __user *user_buffer, + u32 transfer_size, + u32 *transferred, + u32 flags) +{ + struct usbtmc_device_data *data = file_data->data; + struct device *dev = &data->intf->dev; + u32 done = 0; + u32 remaining; + const u32 bufsize = USBTMC_BUFSIZE; + int retval = 0; + u32 max_transfer_size; + unsigned long expire; + int bufcount = 1; + int again = 0; + + /* mutex already locked */ + + *transferred = done; + + max_transfer_size = transfer_size; + + if (flags & USBTMC_FLAG_IGNORE_TRAILER) { + /* The device may send extra alignment bytes (up to + * wMaxPacketSize – 1) to avoid sending a zero-length + * packet + */ + remaining = transfer_size; + if ((max_transfer_size % data->wMaxPacketSize) == 0) + max_transfer_size += (data->wMaxPacketSize - 1); + } else { + /* round down to bufsize to avoid truncated data left */ + if (max_transfer_size > bufsize) { + max_transfer_size = + roundup(max_transfer_size + 1 - bufsize, + bufsize); + } + remaining = max_transfer_size; + } + + spin_lock_irq(&file_data->err_lock); + + if (file_data->in_status) { + /* return the very first error */ + retval = file_data->in_status; + spin_unlock_irq(&file_data->err_lock); + goto error; + } + + if (flags & USBTMC_FLAG_ASYNC) { + if (usb_anchor_empty(&file_data->in_anchor)) + again = 1; + + if (file_data->in_urbs_used == 0) { + file_data->in_transfer_size = 0; + file_data->in_status = 0; + } + } else { + file_data->in_transfer_size = 0; + file_data->in_status = 0; + } + + if (max_transfer_size == 0) { + bufcount = 0; + } else { + bufcount = roundup(max_transfer_size, bufsize) / bufsize; + if (bufcount > file_data->in_urbs_used) + bufcount -= file_data->in_urbs_used; + else + bufcount = 0; + + if (bufcount + file_data->in_urbs_used > MAX_URBS_IN_FLIGHT) { + bufcount = MAX_URBS_IN_FLIGHT - + file_data->in_urbs_used; + } + } + spin_unlock_irq(&file_data->err_lock); + + dev_dbg(dev, "%s: requested=%u flags=0x%X size=%u bufs=%d used=%d\n", + __func__, transfer_size, flags, + max_transfer_size, bufcount, file_data->in_urbs_used); + + while (bufcount > 0) { + u8 *dmabuf = NULL; + struct urb *urb = usbtmc_create_urb(); + + if (!urb) { + retval = -ENOMEM; + goto error; + } + + dmabuf = urb->transfer_buffer; + + usb_fill_bulk_urb(urb, data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, data->bulk_in), + dmabuf, bufsize, + usbtmc_read_bulk_cb, file_data); + + usb_anchor_urb(urb, &file_data->submitted); + retval = usb_submit_urb(urb, GFP_KERNEL); + /* urb is anchored. We can release our reference. */ + usb_free_urb(urb); + if (unlikely(retval)) { + usb_unanchor_urb(urb); + goto error; + } + file_data->in_urbs_used++; + bufcount--; + } + + if (again) { + dev_dbg(dev, "%s: ret=again\n", __func__); + return -EAGAIN; + } + + if (user_buffer == NULL) + return -EINVAL; + + expire = msecs_to_jiffies(file_data->timeout); + + while (max_transfer_size > 0) { + u32 this_part; + struct urb *urb = NULL; + + if (!(flags & USBTMC_FLAG_ASYNC)) { + dev_dbg(dev, "%s: before wait time %lu\n", + __func__, expire); + retval = wait_event_interruptible_timeout( + file_data->wait_bulk_in, + usbtmc_do_transfer(file_data), + expire); + + dev_dbg(dev, "%s: wait returned %d\n", + __func__, retval); + + if (retval <= 0) { + if (retval == 0) + retval = -ETIMEDOUT; + goto error; + } + } + + urb = usb_get_from_anchor(&file_data->in_anchor); + if (!urb) { + if (!(flags & USBTMC_FLAG_ASYNC)) { + /* synchronous case: must not happen */ + retval = -EFAULT; + goto error; + } + + /* asynchronous case: ready, do not block or wait */ + *transferred = done; + dev_dbg(dev, "%s: (async) done=%u ret=0\n", + __func__, done); + return 0; + } + + file_data->in_urbs_used--; + + if (max_transfer_size > urb->actual_length) + max_transfer_size -= urb->actual_length; + else + max_transfer_size = 0; + + if (remaining > urb->actual_length) + this_part = urb->actual_length; + else + this_part = remaining; + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, 16, 1, + urb->transfer_buffer, urb->actual_length, true); + + if (copy_to_user(user_buffer + done, + urb->transfer_buffer, this_part)) { + usb_free_urb(urb); + retval = -EFAULT; + goto error; + } + + remaining -= this_part; + done += this_part; + + spin_lock_irq(&file_data->err_lock); + if (urb->status) { + /* return the very first error */ + retval = file_data->in_status; + spin_unlock_irq(&file_data->err_lock); + usb_free_urb(urb); + goto error; + } + spin_unlock_irq(&file_data->err_lock); + + if (urb->actual_length < bufsize) { + /* short packet or ZLP received => ready */ + usb_free_urb(urb); + retval = 1; + break; + } + + if (!(flags & USBTMC_FLAG_ASYNC) && + max_transfer_size > (bufsize * file_data->in_urbs_used)) { + /* resubmit, since other buffers still not enough */ + usb_anchor_urb(urb, &file_data->submitted); + retval = usb_submit_urb(urb, GFP_KERNEL); + if (unlikely(retval)) { + usb_unanchor_urb(urb); + usb_free_urb(urb); + goto error; + } + file_data->in_urbs_used++; + } + usb_free_urb(urb); + retval = 0; + } + +error: + *transferred = done; + + dev_dbg(dev, "%s: before kill\n", __func__); + /* Attention: killing urbs can take long time (2 ms) */ + usb_kill_anchored_urbs(&file_data->submitted); + dev_dbg(dev, "%s: after kill\n", __func__); + usb_scuttle_anchored_urbs(&file_data->in_anchor); + file_data->in_urbs_used = 0; + file_data->in_status = 0; /* no spinlock needed here */ + dev_dbg(dev, "%s: done=%u ret=%d\n", __func__, done, retval); + + return retval; +} + +static ssize_t usbtmc_ioctl_generic_read(struct usbtmc_file_data *file_data, + void __user *arg) +{ + struct usbtmc_message msg; + ssize_t retval = 0; + + /* mutex already locked */ + + if (copy_from_user(&msg, arg, sizeof(struct usbtmc_message))) + return -EFAULT; + + retval = usbtmc_generic_read(file_data, u64_to_uptr(msg.message), + msg.transfer_size, &msg.transferred, + msg.flags); + + if (put_user(msg.transferred, + &((struct usbtmc_message __user *)arg)->transferred)) + return -EFAULT; + + return retval; +} + static void usbtmc_write_bulk_cb(struct urb *urb) { struct usbtmc_file_data *file_data = urb->context; @@ -1391,6 +1707,7 @@ static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) static int usbtmc_ioctl_cancel_io(struct usbtmc_file_data *file_data) { spin_lock_irq(&file_data->err_lock); + file_data->in_status = -ECANCELED; file_data->out_status = -ECANCELED; spin_unlock_irq(&file_data->err_lock); usb_kill_anchored_urbs(&file_data->submitted); @@ -1776,6 +2093,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void __user *)arg); break; + case USBTMC_IOCTL_READ: + retval = usbtmc_ioctl_generic_read(file_data, + (void __user *)arg); + break; + case USBTMC_IOCTL_WRITE_RESULT: retval = usbtmc_ioctl_write_result(file_data, (void __user *)arg); @@ -1841,15 +2163,24 @@ static __poll_t usbtmc_poll(struct file *file, poll_table *wait) poll_wait(file, &data->waitq, wait); + /* Note that EPOLLPRI is now assigned to SRQ, and + * EPOLLIN|EPOLLRDNORM to normal read data. + */ mask = 0; if (atomic_read(&file_data->srq_asserted)) mask |= EPOLLPRI; + /* Note that the anchor submitted includes all urbs for BULK IN + * and OUT. So EPOLLOUT is signaled when BULK OUT is empty and + * all BULK IN urbs are completed and moved to in_anchor. + */ if (usb_anchor_empty(&file_data->submitted)) mask |= (EPOLLOUT | EPOLLWRNORM); + if (!usb_anchor_empty(&file_data->in_anchor)) + mask |= (EPOLLIN | EPOLLRDNORM); spin_lock_irq(&file_data->err_lock); - if (file_data->out_status) + if (file_data->in_status || file_data->out_status) mask |= EPOLLERR; spin_unlock_irq(&file_data->err_lock); @@ -2011,6 +2342,7 @@ static int usbtmc_probe(struct usb_interface *intf, } data->bulk_in = bulk_in->bEndpointAddress; + data->wMaxPacketSize = usb_endpoint_maxp(bulk_in); dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in); data->bulk_out = bulk_out->bEndpointAddress; @@ -2107,6 +2439,7 @@ static void usbtmc_disconnect(struct usb_interface *intf) struct usbtmc_file_data, file_elem); usb_kill_anchored_urbs(&file_data->submitted); + usb_scuttle_anchored_urbs(&file_data->in_anchor); } mutex_unlock(&data->io_mutex); usbtmc_free_int(data); @@ -2120,6 +2453,7 @@ static void usbtmc_draw_down(struct usbtmc_file_data *file_data) time = usb_wait_anchor_empty_timeout(&file_data->submitted, 1000); if (!time) usb_kill_anchored_urbs(&file_data->submitted); + usb_scuttle_anchored_urbs(&file_data->in_anchor); } static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 4a47b11e4a7e..c75354dfd592 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -64,6 +64,7 @@ struct usbtmc_termchar { */ #define USBTMC_FLAG_ASYNC 0x0001 #define USBTMC_FLAG_APPEND 0x0002 +#define USBTMC_FLAG_IGNORE_TRAILER 0x0004 struct usbtmc_message { __u32 transfer_size; /* size of bytes to transfer */ @@ -86,6 +87,7 @@ struct usbtmc_message { #define USBTMC_IOCTL_EOM_ENABLE _IOW(USBTMC_IOC_NR, 11, __u8) #define USBTMC_IOCTL_CONFIG_TERMCHAR _IOW(USBTMC_IOC_NR, 12, struct usbtmc_termchar) #define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct usbtmc_message) +#define USBTMC_IOCTL_READ _IOWR(USBTMC_IOC_NR, 14, struct usbtmc_message) #define USBTMC_IOCTL_WRITE_RESULT _IOWR(USBTMC_IOC_NR, 15, __u32) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) From patchwork Mon Jul 30 08:04:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548483 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4B2A8A7F6 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3DA19298F3 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 32934298FD; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61C31298F3 for ; Mon, 30 Jul 2018 07:07:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726543AbeG3IlN (ORCPT ); Mon, 30 Jul 2018 04:41:13 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:43530 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726416AbeG3IlM (ORCPT ); Mon, 30 Jul 2018 04:41:12 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id C18EF120EE3 for ; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id B40A7120EC7; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id AB064120ED8; Mon, 30 Jul 2018 09:07:35 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 05/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_CANCEL_IO Date: Mon, 30 Jul 2018 10:04:35 +0200 Message-Id: <20180730080452.15150-6-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070736.16444.82336@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ioctl USBTMC_IOCTL_CANCEL_IO stops and kills all flying urbs of last USBTMC_IOCTL_READ and USBTMC_IOCTL_WRITE function calls. A subsequent call to USBTMC_IOCTL_READ or USBTMC_IOCTL_WRITE_RESULT returns -ECANCELED with information about current transferred data. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 4 ++++ include/uapi/linux/usb/tmc.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 5edb548d9122..e78176ef0e42 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2134,6 +2134,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC488_IOCTL_TRIGGER: retval = usbtmc488_ioctl_trigger(file_data); break; + + case USBTMC_IOCTL_CANCEL_IO: + retval = usbtmc_ioctl_cancel_io(file_data); + break; } skip_io_on_zombie: diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index c75354dfd592..934991624a28 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -97,6 +97,9 @@ struct usbtmc_message { #define USBTMC488_IOCTL_LOCAL_LOCKOUT _IO(USBTMC_IOC_NR, 21) #define USBTMC488_IOCTL_TRIGGER _IO(USBTMC_IOC_NR, 22) +/* Cancel and cleanup asynchronous calls */ +#define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35) + /* Driver encoded usb488 capabilities */ #define USBTMC488_CAPABILITY_TRIGGER 1 #define USBTMC488_CAPABILITY_SIMPLE 2 From patchwork Mon Jul 30 08:04:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548493 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7A7C913BB for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B8CC298E1 for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5834E298FE; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C502298E1 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726544AbeG3IlN (ORCPT ); Mon, 30 Jul 2018 04:41:13 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:46690 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726399AbeG3IlM (ORCPT ); Mon, 30 Jul 2018 04:41:12 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 68C7F120EF0 for ; Mon, 30 Jul 2018 09:07:38 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 5DB79120EE2; Mon, 30 Jul 2018 09:07:38 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 570F0120EDD; Mon, 30 Jul 2018 09:07:36 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 06/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_CLEANUP_IO Date: Mon, 30 Jul 2018 10:04:36 +0200 Message-Id: <20180730080452.15150-7-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070736.16464.41423@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The ioctl USBTMC_IOCTL_CLEANUP_IO kills all submitted urbs to OUT and IN bulk, and clears all received data from IN bulk. Internal transfer counters and error states are reset. An application should use this ioctl after an asnychronous transfer was canceled and/or error handling has finished. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 19 +++++++++++++++++++ include/uapi/linux/usb/tmc.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index e78176ef0e42..b8a4140bd161 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1714,6 +1714,21 @@ static int usbtmc_ioctl_cancel_io(struct usbtmc_file_data *file_data) return 0; } +static int usbtmc_ioctl_cleanup_io(struct usbtmc_file_data *file_data) +{ + usb_kill_anchored_urbs(&file_data->submitted); + usb_scuttle_anchored_urbs(&file_data->in_anchor); + spin_lock_irq(&file_data->err_lock); + file_data->in_status = 0; + file_data->in_transfer_size = 0; + file_data->out_status = 0; + file_data->out_transfer_size = 0; + spin_unlock_irq(&file_data->err_lock); + + file_data->in_urbs_used = 0; + return 0; +} + static int get_capabilities(struct usbtmc_device_data *data) { struct device *dev = &data->usb_dev->dev; @@ -2138,6 +2153,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC_IOCTL_CANCEL_IO: retval = usbtmc_ioctl_cancel_io(file_data); break; + + case USBTMC_IOCTL_CLEANUP_IO: + retval = usbtmc_ioctl_cleanup_io(file_data); + break; } skip_io_on_zombie: diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 934991624a28..d638c198c7a8 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -99,6 +99,7 @@ struct usbtmc_message { /* Cancel and cleanup asynchronous calls */ #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35) +#define USBTMC_IOCTL_CLEANUP_IO _IO(USBTMC_IOC_NR, 36) /* Driver encoded usb488 capabilities */ #define USBTMC488_CAPABILITY_TRIGGER 1 From patchwork Mon Jul 30 08:04:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548487 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CDDF5A7F9 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C07FB298F1 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B5237298F3; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53473298F3 for ; Mon, 30 Jul 2018 07:07:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726566AbeG3IlO (ORCPT ); Mon, 30 Jul 2018 04:41:14 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:60765 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726529AbeG3IlN (ORCPT ); Mon, 30 Jul 2018 04:41:13 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 1E45F120EB8 for ; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 0BC3E120ED6; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 030D3120EAA; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 07/22] usb: usbtmc: Fix suspend/resume Date: Mon, 30 Jul 2018 10:04:37 +0200 Message-Id: <20180730080452.15150-8-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070737.16481.96306@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Submitted urbs are not allowed when system is suspended. Thus the submitted urb waiting at interrupt pipe is killed during suspend callback and submitted again when system resumes. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index b8a4140bd161..9953b62b7db4 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2314,7 +2314,9 @@ static void usbtmc_free_int(struct usbtmc_device_data *data) return; usb_kill_urb(data->iin_urb); kfree(data->iin_buffer); + data->iin_buffer = NULL; usb_free_urb(data->iin_urb); + data->iin_urb = NULL; kref_put(&data->kref, usbtmc_delete); } @@ -2496,13 +2498,25 @@ static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) file_elem); usbtmc_draw_down(file_data); } + + if (data->iin_ep_present && data->iin_urb) + usb_kill_urb(data->iin_urb); + mutex_unlock(&data->io_mutex); return 0; } static int usbtmc_resume(struct usb_interface *intf) { - return 0; + struct usbtmc_device_data *data = usb_get_intfdata(intf); + int retcode = 0; + + if (data->iin_ep_present && data->iin_urb) + retcode = usb_submit_urb(data->iin_urb, GFP_KERNEL); + if (retcode) + dev_err(&intf->dev, "Failed to submit iin_urb\n"); + + return retcode; } static int usbtmc_pre_reset(struct usb_interface *intf) From patchwork Mon Jul 30 08:04:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548495 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D10C5A7FA for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BDE46298DE for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A995A298E1; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 081A8298F3 for ; Mon, 30 Jul 2018 07:07:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726573AbeG3IlO (ORCPT ); Mon, 30 Jul 2018 04:41:14 -0400 Received: from mr07.mx01.tldhost.de ([62.108.44.247]:34777 "EHLO mr07.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726534AbeG3IlO (ORCPT ); Mon, 30 Jul 2018 04:41:14 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E92ED120EFD for ; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id DC41F120ED4; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id CD944120EEE; Mon, 30 Jul 2018 09:07:37 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 08/22] usb: usbtmc: Add ioctl USBTMC488_IOCTL_WAIT_SRQ Date: Mon, 30 Jul 2018 10:04:38 +0200 Message-Id: <20180730080452.15150-9-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070737.16498.62061@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Wait until an SRQ (service request) is received on the interrupt pipe or until the given period of time is expired. In contrast to the poll() function this ioctl does not return when other (a)synchronous I/O operations fail with EPOLLERR. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 57 ++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 1 + 2 files changed, 58 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 9953b62b7db4..15421aa71eef 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -130,6 +130,7 @@ struct usbtmc_file_data { u32 timeout; u8 srq_byte; atomic_t srq_asserted; + atomic_t closing; u8 eom_val; u8 term_char; @@ -201,6 +202,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp) mutex_lock(&data->io_mutex); file_data->data = data; + atomic_set(&file_data->closing, 0); + /* copy default values from device settings */ file_data->timeout = USBTMC_TIMEOUT; file_data->term_char = data->TermChar; @@ -231,6 +234,7 @@ static int usbtmc_flush(struct file *file, fl_owner_t id) if (file_data == NULL) return -ENODEV; + atomic_set(&file_data->closing, 1); data = file_data->data; /* wait for io to stop */ @@ -584,6 +588,54 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, return rv; } +static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data, + __u32 __user *arg) +{ + struct usbtmc_device_data *data = file_data->data; + struct device *dev = &data->intf->dev; + int rv; + u32 timeout; + unsigned long expire; + + if (!data->iin_ep_present) { + dev_dbg(dev, "no interrupt endpoint present\n"); + return -EFAULT; + } + + if (get_user(timeout, arg)) + return -EFAULT; + + expire = msecs_to_jiffies(timeout); + + mutex_unlock(&data->io_mutex); + + rv = wait_event_interruptible_timeout( + data->waitq, + atomic_read(&file_data->srq_asserted) != 0 || + atomic_read(&file_data->closing), + expire); + + mutex_lock(&data->io_mutex); + + /* Note! disconnect or close could be called in the meantime */ + if (atomic_read(&file_data->closing) || data->zombie) + rv = -ENODEV; + + if (rv < 0) { + /* dev can be invalid now! */ + pr_debug("%s - wait interrupted %d\n", __func__, rv); + return rv; + } + + if (rv == 0) { + dev_dbg(dev, "%s - wait timed out\n", __func__); + return -ETIMEDOUT; + } + + dev_dbg(dev, "%s - srq asserted\n", __func__); + return 0; +} + static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data, void __user *arg, unsigned int cmd) { @@ -2150,6 +2202,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) retval = usbtmc488_ioctl_trigger(file_data); break; + case USBTMC488_IOCTL_WAIT_SRQ: + retval = usbtmc488_ioctl_wait_srq(file_data, + (__u32 __user *)arg); + break; + case USBTMC_IOCTL_CANCEL_IO: retval = usbtmc_ioctl_cancel_io(file_data); break; diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index d638c198c7a8..56c76a9680e5 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -96,6 +96,7 @@ struct usbtmc_message { #define USBTMC488_IOCTL_GOTO_LOCAL _IO(USBTMC_IOC_NR, 20) #define USBTMC488_IOCTL_LOCAL_LOCKOUT _IO(USBTMC_IOC_NR, 21) #define USBTMC488_IOCTL_TRIGGER _IO(USBTMC_IOC_NR, 22) +#define USBTMC488_IOCTL_WAIT_SRQ _IOW(USBTMC_IOC_NR, 23, __u32) /* Cancel and cleanup asynchronous calls */ #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35) From patchwork Mon Jul 30 08:04:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548491 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 65C85A7F6 for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57E8A298F1 for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 45AF329901; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D8F1629906 for ; Mon, 30 Jul 2018 07:07:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726562AbeG3IlO (ORCPT ); Mon, 30 Jul 2018 04:41:14 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:58749 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726399AbeG3IlO (ORCPT ); Mon, 30 Jul 2018 04:41:14 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 92949120EE2 for ; Mon, 30 Jul 2018 09:07:40 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 8853C120EC5; Mon, 30 Jul 2018 09:07:40 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 83F21120EDC; Mon, 30 Jul 2018 09:07:38 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 09/22] usb: usbtmc: add ioctl USBTMC_IOCTL_MSG_IN_ATTR Date: Mon, 30 Jul 2018 10:04:39 +0200 Message-Id: <20180730080452.15150-10-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070738.16515.55145@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP add ioctl USBTMC_IOCTL_MSG_IN_ATTR that returns the specific bmTransferAttributes field of the last DEV_DEP_MSG_IN Bulk-IN header. This header is received by the read() function. The meaning of the (u8) bitmap bmTransferAttributes is: Bit 0 = EOM flag is set when the last transfer of a USBTMC message is received. Bit 1 = is set when the last byte is a termchar (e.g. '\n'). Note that this bit is always zero when the device does not support the termchar feature or when termchar detection is not enabled (see ioctl USBTMC_IOCTL_CONFIG_TERMCHAR). Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 8 ++++++++ include/uapi/linux/usb/tmc.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 15421aa71eef..1e7a1dcfcec7 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -131,6 +131,7 @@ struct usbtmc_file_data { u8 srq_byte; atomic_t srq_asserted; atomic_t closing; + u8 bmTransferAttributes; /* member of DEV_DEP_MSG_IN */ u8 eom_val; u8 term_char; @@ -1443,6 +1444,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, (buffer[6] << 16) + (buffer[7] << 24); + file_data->bmTransferAttributes = buffer[8]; + if (n_characters > this_part) { dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count); if (data->auto_abort) @@ -2207,6 +2210,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (__u32 __user *)arg); break; + case USBTMC_IOCTL_MSG_IN_ATTR: + retval = put_user(file_data->bmTransferAttributes, + (__u8 __user *)arg); + break; + case USBTMC_IOCTL_CANCEL_IO: retval = usbtmc_ioctl_cancel_io(file_data); break; diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 56c76a9680e5..d2ed6a20de6b 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -98,6 +98,8 @@ struct usbtmc_message { #define USBTMC488_IOCTL_TRIGGER _IO(USBTMC_IOC_NR, 22) #define USBTMC488_IOCTL_WAIT_SRQ _IOW(USBTMC_IOC_NR, 23, __u32) +#define USBTMC_IOCTL_MSG_IN_ATTR _IOR(USBTMC_IOC_NR, 24, __u8) + /* Cancel and cleanup asynchronous calls */ #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35) #define USBTMC_IOCTL_CLEANUP_IO _IO(USBTMC_IOC_NR, 36) From patchwork Mon Jul 30 08:04:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548499 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A72D6A7F6 for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 76D9727F97 for ; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 69415294AB; Mon, 30 Jul 2018 07:07:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D3D33298E1 for ; Mon, 30 Jul 2018 07:07:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726584AbeG3IlQ (ORCPT ); Mon, 30 Jul 2018 04:41:16 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:44528 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726529AbeG3IlP (ORCPT ); Mon, 30 Jul 2018 04:41:15 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 4E36A120EE0 for ; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 440D6120EB2; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 34E29120EB2; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 10/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_AUTO_ABORT Date: Mon, 30 Jul 2018 10:04:40 +0200 Message-Id: <20180730080452.15150-11-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070739.16530.94833@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add ioctl USBTMC_IOCTL_AUTO_ABORT to configure auto_abort for each specific file handle. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 23 ++++++++++++++++------- include/uapi/linux/usb/tmc.h | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 1e7a1dcfcec7..42989c7902a8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -136,6 +136,7 @@ struct usbtmc_file_data { u8 eom_val; u8 term_char; bool term_char_enabled; + bool auto_abort; spinlock_t err_lock; /* lock for errors */ @@ -209,6 +210,7 @@ static int usbtmc_open(struct inode *inode, struct file *filp) file_data->timeout = USBTMC_TIMEOUT; file_data->term_char = data->TermChar; file_data->term_char_enabled = data->TermCharEnabled; + file_data->auto_abort = data->auto_abort; file_data->eom_val = 1; INIT_LIST_HEAD(&file_data->file_elem); @@ -1384,7 +1386,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, retval = send_request_dev_dep_msg_in(file_data, count); if (retval < 0) { - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_out(data); goto exit; } @@ -1409,7 +1411,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, if (retval < 0) { dev_dbg(dev, "Unable to read data, error %d\n", retval); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } @@ -1419,21 +1421,21 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, /* Sanity checks for the header */ if (actual < USBTMC_HEADER_SIZE) { dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } if (buffer[0] != 2) { dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } if (buffer[1] != data->bTag_last_write) { dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } @@ -1448,7 +1450,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, if (n_characters > this_part) { dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } @@ -1590,7 +1592,7 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, if (retval < 0) { dev_err(&data->intf->dev, "Unable to send data, error %d\n", retval); - if (data->auto_abort) + if (file_data->auto_abort) usbtmc_ioctl_abort_bulk_out(data); goto exit; } @@ -2099,6 +2101,7 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct usbtmc_file_data *file_data; struct usbtmc_device_data *data; int retval = -EBADRQC; + __u8 tmp_byte; file_data = file->private_data; data = file_data->data; @@ -2215,6 +2218,12 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (__u8 __user *)arg); break; + case USBTMC_IOCTL_AUTO_ABORT: + retval = get_user(tmp_byte, (unsigned char __user *)arg); + if (retval == 0) + file_data->auto_abort = !!tmp_byte; + break; + case USBTMC_IOCTL_CANCEL_IO: retval = usbtmc_ioctl_cancel_io(file_data); break; diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index d2ed6a20de6b..2435694d3ba5 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -99,6 +99,7 @@ struct usbtmc_message { #define USBTMC488_IOCTL_WAIT_SRQ _IOW(USBTMC_IOC_NR, 23, __u32) #define USBTMC_IOCTL_MSG_IN_ATTR _IOR(USBTMC_IOC_NR, 24, __u8) +#define USBTMC_IOCTL_AUTO_ABORT _IOW(USBTMC_IOC_NR, 25, __u8) /* Cancel and cleanup asynchronous calls */ #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35) From patchwork Mon Jul 30 08:04:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548525 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3688EA7F6 for ; Mon, 30 Jul 2018 07:07:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C43652910F for ; Mon, 30 Jul 2018 07:07:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B8A8A29601; Mon, 30 Jul 2018 07:07:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E0F52910F for ; Mon, 30 Jul 2018 07:07:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726581AbeG3IlR (ORCPT ); Mon, 30 Jul 2018 04:41:17 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:35784 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726399AbeG3IlQ (ORCPT ); Mon, 30 Jul 2018 04:41:16 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E9978120EE8 for ; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id DF091120EDA; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id D6016120EAA; Mon, 30 Jul 2018 09:07:39 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 11/22] usb: usbtmc: Optimize usbtmc_write Date: Mon, 30 Jul 2018 10:04:41 +0200 Message-Id: <20180730080452.15150-12-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070740.16550.6910@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use new usbtmc_generic_write function to maximize bandwidth during long data transfer. The maximum output transfer size is limited to INT_MAX (=2GB). Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 176 +++++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 67 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 42989c7902a8..6d5f514b3081 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1517,94 +1517,136 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, { struct usbtmc_file_data *file_data; struct usbtmc_device_data *data; + struct urb *urb = NULL; + ssize_t retval = 0; u8 *buffer; - int retval; - int actual; - unsigned long int n_bytes; - int remaining; - int done; - int this_part; + u32 remaining, done; + u32 transfersize, aligned, buflen; file_data = filp->private_data; data = file_data->data; - buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - mutex_lock(&data->io_mutex); + if (data->zombie) { retval = -ENODEV; goto exit; } - remaining = count; done = 0; - while (remaining > 0) { - if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE) { - this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE; - buffer[8] = 0; - } else { - this_part = remaining; - buffer[8] = file_data->eom_val; - } - - /* Setup IO buffer for DEV_DEP_MSG_OUT message */ - buffer[0] = 1; - buffer[1] = data->bTag; - buffer[2] = ~data->bTag; - buffer[3] = 0; /* Reserved */ - buffer[4] = this_part >> 0; - buffer[5] = this_part >> 8; - buffer[6] = this_part >> 16; - buffer[7] = this_part >> 24; - /* buffer[8] is set above... */ - buffer[9] = 0; /* Reserved */ - buffer[10] = 0; /* Reserved */ - buffer[11] = 0; /* Reserved */ - - if (copy_from_user(&buffer[USBTMC_HEADER_SIZE], buf + done, this_part)) { - retval = -EFAULT; - goto exit; - } - - n_bytes = roundup(USBTMC_HEADER_SIZE + this_part, 4); - memset(buffer + USBTMC_HEADER_SIZE + this_part, 0, n_bytes - (USBTMC_HEADER_SIZE + this_part)); - - do { - retval = usb_bulk_msg(data->usb_dev, - usb_sndbulkpipe(data->usb_dev, - data->bulk_out), - buffer, n_bytes, - &actual, file_data->timeout); - if (retval != 0) - break; - n_bytes -= actual; - } while (n_bytes); - - data->bTag_last_write = data->bTag; + spin_lock_irq(&file_data->err_lock); + file_data->out_transfer_size = 0; + file_data->out_status = 0; + spin_unlock_irq(&file_data->err_lock); + + if (!count) + goto exit; + + if (down_trylock(&file_data->limit_write_sem)) { + /* previous calls were async */ + retval = -EBUSY; + goto exit; + } + + urb = usbtmc_create_urb(); + if (!urb) { + retval = -ENOMEM; + up(&file_data->limit_write_sem); + goto exit; + } + + buffer = urb->transfer_buffer; + buflen = urb->transfer_buffer_length; + + if (count > INT_MAX) { + transfersize = INT_MAX; + buffer[8] = 0; + } else { + transfersize = count; + buffer[8] = file_data->eom_val; + } + + /* Setup IO buffer for DEV_DEP_MSG_OUT message */ + buffer[0] = 1; + buffer[1] = data->bTag; + buffer[2] = ~data->bTag; + buffer[3] = 0; /* Reserved */ + buffer[4] = transfersize >> 0; + buffer[5] = transfersize >> 8; + buffer[6] = transfersize >> 16; + buffer[7] = transfersize >> 24; + /* buffer[8] is set above... */ + buffer[9] = 0; /* Reserved */ + buffer[10] = 0; /* Reserved */ + buffer[11] = 0; /* Reserved */ + + remaining = transfersize; + + if (transfersize + USBTMC_HEADER_SIZE > buflen) { + transfersize = buflen - USBTMC_HEADER_SIZE; + aligned = buflen; + } else { + aligned = (transfersize + (USBTMC_HEADER_SIZE + 3)) & ~3; + } + + if (copy_from_user(&buffer[USBTMC_HEADER_SIZE], buf, transfersize)) { + retval = -EFAULT; + up(&file_data->limit_write_sem); + goto exit; + } + + dev_dbg(&data->intf->dev, "%s(size:%u align:%u)\n", __func__, + (unsigned int)transfersize, (unsigned int)aligned); + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, + 16, 1, buffer, aligned, true); + + usb_fill_bulk_urb(urb, data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out), + urb->transfer_buffer, aligned, + usbtmc_write_bulk_cb, file_data); + + usb_anchor_urb(urb, &file_data->submitted); + retval = usb_submit_urb(urb, GFP_KERNEL); + if (unlikely(retval)) { + usb_unanchor_urb(urb); + up(&file_data->limit_write_sem); + goto exit; + } + + remaining -= transfersize; + + data->bTag_last_write = data->bTag; + data->bTag++; + + if (!data->bTag) data->bTag++; - if (!data->bTag) - data->bTag++; + /* call generic_write even when remaining = 0 */ + retval = usbtmc_generic_write(file_data, buf + transfersize, remaining, + &done, USBTMC_FLAG_APPEND); + /* truncate alignment bytes */ + if (done > remaining) + done = remaining; - if (retval < 0) { - dev_err(&data->intf->dev, - "Unable to send data, error %d\n", retval); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_out(data); - goto exit; - } + /*add size of first urb*/ + done += transfersize; - remaining -= this_part; - done += this_part; + if (retval < 0) { + usb_kill_anchored_urbs(&file_data->submitted); + + dev_err(&data->intf->dev, + "Unable to send data, error %d\n", (int)retval); + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_out(data); + goto exit; } - retval = count; + retval = done; exit: + usb_free_urb(urb); mutex_unlock(&data->io_mutex); - kfree(buffer); return retval; } From patchwork Mon Jul 30 08:04:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548503 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3E8E014BC for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C7572910F for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1E9F7295AF; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6D01C2910F for ; Mon, 30 Jul 2018 07:07:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726450AbeG3IlR (ORCPT ); Mon, 30 Jul 2018 04:41:17 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:48902 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726568AbeG3IlR (ORCPT ); Mon, 30 Jul 2018 04:41:17 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 9FB89120EF8 for ; Mon, 30 Jul 2018 09:07:42 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 943F5120EE4; Mon, 30 Jul 2018 09:07:42 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 84EBD120EC0; Mon, 30 Jul 2018 09:07:40 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 12/22] usb: usbtmc: Optimize usbtmc_read Date: Mon, 30 Jul 2018 10:04:42 +0200 Message-Id: <20180730080452.15150-13-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070740.16567.52086@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use new usbtmc_generic_read function to maximize bandwidth during long data transfer. Also fix reading of zero length packet (ZLP) or trailing short packet. The maximum input transfer size is limited to INT_MAX (=2GB). Also remove redundant return in send_request_dev_dep_msg_in(). Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 222 ++++++++++++++++++------------------- 1 file changed, 105 insertions(+), 117 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6d5f514b3081..11225c6d6c69 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1301,7 +1301,7 @@ static ssize_t usbtmc_ioctl_write_result(struct usbtmc_file_data *file_data, * Also updates bTag_last_write. */ static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data, - size_t transfer_size) + u32 transfer_size) { struct usbtmc_device_data *data = file_data->data; int retval; @@ -1344,12 +1344,11 @@ static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data, data->bTag++; kfree(buffer); - if (retval < 0) { - dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval); - return retval; - } + if (retval < 0) + dev_err(&data->intf->dev, "%s returned %d\n", + __func__, retval); - return 0; + return retval; } static ssize_t usbtmc_read(struct file *filp, char __user *buf, @@ -1358,20 +1357,20 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, struct usbtmc_file_data *file_data; struct usbtmc_device_data *data; struct device *dev; + const u32 bufsize = USBTMC_BUFSIZE; u32 n_characters; u8 *buffer; int actual; - size_t done; - size_t remaining; + u32 done = 0; + u32 remaining; int retval; - size_t this_part; /* Get pointer to private data structure */ file_data = filp->private_data; data = file_data->data; dev = &data->intf->dev; - buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + buffer = kmalloc(bufsize, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -1381,7 +1380,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, goto exit; } - dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count); + if (count > INT_MAX) + count = INT_MAX; + + dev_dbg(dev, "%s(count:%zu)\n", __func__, count); retval = send_request_dev_dep_msg_in(file_data, count); @@ -1393,114 +1395,100 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, /* Loop until we have fetched everything we requested */ remaining = count; - this_part = remaining; - done = 0; - - while (remaining > 0) { - /* Send bulk URB */ - retval = usb_bulk_msg(data->usb_dev, - usb_rcvbulkpipe(data->usb_dev, - data->bulk_in), - buffer, USBTMC_SIZE_IOBUFFER, &actual, - file_data->timeout); - - dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual); - - /* Store bTag (in case we need to abort) */ - data->bTag_last_read = data->bTag; - - if (retval < 0) { - dev_dbg(dev, "Unable to read data, error %d\n", retval); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_in(data); + + /* Send bulk URB */ + retval = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, bufsize, &actual, + file_data->timeout); + + dev_dbg(dev, "%s: bulk_msg retval(%u), actual(%d)\n", + __func__, retval, actual); + + /* Store bTag (in case we need to abort) */ + data->bTag_last_read = data->bTag; + + if (retval < 0) { + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + /* Sanity checks for the header */ + if (actual < USBTMC_HEADER_SIZE) { + dev_err(dev, "Device sent too small first packet: %u < %u\n", + actual, USBTMC_HEADER_SIZE); + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + if (buffer[0] != 2) { + dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", + buffer[0]); + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + if (buffer[1] != data->bTag_last_write) { + dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", + buffer[1], data->bTag_last_write); + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + /* How many characters did the instrument send? */ + n_characters = buffer[4] + + (buffer[5] << 8) + + (buffer[6] << 16) + + (buffer[7] << 24); + + file_data->bmTransferAttributes = buffer[8]; + + dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", + n_characters, buffer[8]); + + if (n_characters > remaining) { + dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", + n_characters, count); + if (file_data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, + 16, 1, buffer, actual, true); + + remaining = n_characters; + + /* Remove the USBTMC header */ + actual -= USBTMC_HEADER_SIZE; + + /* Remove padding if it exists */ + if (actual > remaining) + actual = remaining; + + remaining -= actual; + + /* Copy buffer to user space */ + if (copy_to_user(buf, &buffer[USBTMC_HEADER_SIZE], actual)) { + /* There must have been an addressing problem */ + retval = -EFAULT; + goto exit; + } + + if ((actual + USBTMC_HEADER_SIZE) == bufsize) { + retval = usbtmc_generic_read(file_data, buf + actual, + remaining, + &done, + USBTMC_FLAG_IGNORE_TRAILER); + if (retval < 0) goto exit; - } - - /* Parse header in first packet */ - if (done == 0) { - /* Sanity checks for the header */ - if (actual < USBTMC_HEADER_SIZE) { - dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_in(data); - goto exit; - } - - if (buffer[0] != 2) { - dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_in(data); - goto exit; - } - - if (buffer[1] != data->bTag_last_write) { - dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_in(data); - goto exit; - } - - /* How many characters did the instrument send? */ - n_characters = buffer[4] + - (buffer[5] << 8) + - (buffer[6] << 16) + - (buffer[7] << 24); - - file_data->bmTransferAttributes = buffer[8]; - - if (n_characters > this_part) { - dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count); - if (file_data->auto_abort) - usbtmc_ioctl_abort_bulk_in(data); - goto exit; - } - - /* Remove the USBTMC header */ - actual -= USBTMC_HEADER_SIZE; - - /* Check if the message is smaller than requested */ - if (remaining > n_characters) - remaining = n_characters; - /* Remove padding if it exists */ - if (actual > remaining) - actual = remaining; - - dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]); - - remaining -= actual; - - /* Terminate if end-of-message bit received from device */ - if ((buffer[8] & 0x01) && (actual >= n_characters)) - remaining = 0; - - dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done); - - - /* Copy buffer to user space */ - if (copy_to_user(buf + done, &buffer[USBTMC_HEADER_SIZE], actual)) { - /* There must have been an addressing problem */ - retval = -EFAULT; - goto exit; - } - done += actual; - } - else { - if (actual > remaining) - actual = remaining; - - remaining -= actual; - - dev_dbg(dev, "Bulk-IN header cont: actual(%u), done(%zu), remaining(%zu), buf(%p), buffer(%p)\n", actual, done, remaining,buf,buffer); - - /* Copy buffer to user space */ - if (copy_to_user(buf + done, buffer, actual)) { - /* There must have been an addressing problem */ - retval = -EFAULT; - goto exit; - } - done += actual; - } } + done += actual; /* Update file position value */ *f_pos = *f_pos + done; From patchwork Mon Jul 30 08:04:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7AAFA7F6 for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C80002910F for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BC2FF295B0; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48D242910F for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726576AbeG3IlS (ORCPT ); Mon, 30 Jul 2018 04:41:18 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:45272 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726583AbeG3IlR (ORCPT ); Mon, 30 Jul 2018 04:41:17 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 409F7120EF7 for ; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 361CF120ED4; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 31F26120E58; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 13/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_CLEAR Date: Mon, 30 Jul 2018 10:04:43 +0200 Message-Id: <20180730080452.15150-14-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070741.16584.34140@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Remove calculation of max_size (=wMaxPacketSize) and wrong condition (actual == max_size) in while loop. A device clear should always flush the complete Bulk-IN FIFO. Insert a sleep of 50 ms between subsequent CHECK_CLEAR_STATUS control requests to avoid stressing the instrument with repeated requests. Some instruments need time to cleanup internal I/O buffers. Polling and nonbraked requests slow down the response time of devices. Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k). Using USBTMC_SIZE_IOBUFFER is deprecated. Check only bit 0 (field bmClear) of the CHECK_CLEAR_STATUS response, since other bits are reserved and can change in future versions. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 46 +++++++++++++++----------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 11225c6d6c69..1903d98f5a18 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1640,20 +1640,17 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) { - struct usb_host_interface *current_setting; - struct usb_endpoint_descriptor *desc; struct device *dev; u8 *buffer; int rv; int n; int actual = 0; - int max_size; dev = &data->intf->dev; dev_dbg(dev, "Sending INITIATE_CLEAR request\n"); - buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -1661,7 +1658,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_INITIATE_CLEAR, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, 0, buffer, 1, USBTMC_TIMEOUT); + 0, 0, buffer, 1, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; @@ -1675,22 +1672,6 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) goto exit; } - max_size = 0; - current_setting = data->intf->cur_altsetting; - for (n = 0; n < current_setting->desc.bNumEndpoints; n++) { - desc = ¤t_setting->endpoint[n].desc; - if (desc->bEndpointAddress == data->bulk_in) - max_size = usb_endpoint_maxp(desc); - } - - if (max_size == 0) { - dev_err(dev, "Couldn't get wMaxPacketSize\n"); - rv = -EPERM; - goto exit; - } - - dev_dbg(dev, "wMaxPacketSize is %d\n", max_size); - n = 0; usbtmc_clear_check_status: @@ -1701,7 +1682,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_CHECK_CLEAR_STATUS, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, 0, buffer, 2, USBTMC_TIMEOUT); + 0, 0, buffer, 2, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; @@ -1718,15 +1699,19 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) goto exit; } - if (buffer[1] == 1) + if ((buffer[1] & 1) != 0) { do { dev_dbg(dev, "Reading from bulk in EP\n"); rv = usb_bulk_msg(data->usb_dev, usb_rcvbulkpipe(data->usb_dev, data->bulk_in), - buffer, USBTMC_SIZE_IOBUFFER, - &actual, USBTMC_TIMEOUT); + buffer, USBTMC_BUFSIZE, + &actual, USB_CTRL_GET_TIMEOUT); + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, + 16, 1, buffer, actual, true); + n++; if (rv < 0) { @@ -1734,10 +1719,15 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) rv); goto exit; } - } while ((actual == max_size) && + } while ((actual == USBTMC_BUFSIZE) && (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); + } else { + /* do not stress device with subsequent requests */ + msleep(50); + n++; + } - if (actual == max_size) { + if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) { dev_err(dev, "Couldn't clear device buffer within %d cycles\n", USBTMC_MAX_READS_TO_CLEAR_BULK_IN); rv = -EPERM; @@ -1751,7 +1741,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) rv = usb_clear_halt(data->usb_dev, usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { - dev_err(dev, "usb_control_msg returned %d\n", rv); + dev_err(dev, "usb_clear_halt returned %d\n", rv); goto exit; } rv = 0; From patchwork Mon Jul 30 08:04:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548507 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5A1C513BB for ; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48A072959B for ; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3CF8D295B0; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9AF1C2959B for ; Mon, 30 Jul 2018 07:07:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726593AbeG3IlT (ORCPT ); Mon, 30 Jul 2018 04:41:19 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:37887 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726529AbeG3IlS (ORCPT ); Mon, 30 Jul 2018 04:41:18 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E9A60120EFD for ; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id DF077120EE3; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id D8EAC120EBA; Mon, 30 Jul 2018 09:07:41 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 14/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN Date: Mon, 30 Jul 2018 10:04:44 +0200 Message-Id: <20180730080452.15150-15-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070742.16602.42810@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 139 ++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 78 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 1903d98f5a18..c197d8c629f2 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -278,18 +278,17 @@ static int usbtmc_release(struct inode *inode, struct file *file) return 0; } -static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) +static int usbtmc_ioctl_abort_bulk_in_tag(struct usbtmc_device_data *data, + u8 tag) { u8 *buffer; struct device *dev; int rv; int n; int actual; - struct usb_host_interface *current_setting; - int max_size; dev = &data->intf->dev; - buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL); + buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -297,21 +296,34 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_INITIATE_ABORT_BULK_IN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, - data->bTag_last_read, data->bulk_in, - buffer, 2, USBTMC_TIMEOUT); + tag, data->bulk_in, + buffer, 2, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; } - dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x with tag %02x\n", + buffer[0], buffer[1]); if (buffer[0] == USBTMC_STATUS_FAILED) { + /* No transfer in progress and the Bulk-OUT FIFO is empty. */ rv = 0; goto exit; } + if (buffer[0] == USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS) { + /* The device returns this status if either: + * - There is a transfer in progress, but the specified bTag + * does not match. + * - There is no transfer in progress, but the Bulk-OUT FIFO + * is not empty. + */ + rv = -ENOMSG; + goto exit; + } + if (buffer[0] != USBTMC_STATUS_SUCCESS) { dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); @@ -319,64 +331,52 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) goto exit; } - max_size = 0; - current_setting = data->intf->cur_altsetting; - for (n = 0; n < current_setting->desc.bNumEndpoints; n++) - if (current_setting->endpoint[n].desc.bEndpointAddress == - data->bulk_in) - max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc); - - if (max_size == 0) { - dev_err(dev, "Couldn't get wMaxPacketSize\n"); - rv = -EPERM; - goto exit; - } - - dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size); - - n = 0; - - do { - dev_dbg(dev, "Reading from bulk in EP\n"); - - rv = usb_bulk_msg(data->usb_dev, - usb_rcvbulkpipe(data->usb_dev, - data->bulk_in), - buffer, USBTMC_SIZE_IOBUFFER, - &actual, USBTMC_TIMEOUT); - - n++; - - if (rv < 0) { - dev_err(dev, "usb_bulk_msg returned %d\n", rv); - goto exit; - } - } while ((actual == max_size) && - (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); - - if (actual == max_size) { - dev_err(dev, "Couldn't clear device buffer within %d cycles\n", - USBTMC_MAX_READS_TO_CLEAR_BULK_IN); - rv = -EPERM; - goto exit; - } - n = 0; usbtmc_abort_bulk_in_status: + dev_dbg(dev, "Reading from bulk in EP\n"); + + /* Data must be present. So use low timeout 300 ms */ + rv = usb_bulk_msg(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, USBTMC_BUFSIZE, + &actual, 300); + + print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, 16, 1, + buffer, actual, true); + + n++; + + if (rv < 0) { + dev_err(dev, "usb_bulk_msg returned %d\n", rv); + if (rv != -ETIMEDOUT) + goto exit; + } + + if (actual == USBTMC_BUFSIZE) + goto usbtmc_abort_bulk_in_status; + + if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) { + dev_err(dev, "Couldn't clear device buffer within %d cycles\n", + USBTMC_MAX_READS_TO_CLEAR_BULK_IN); + rv = -EPERM; + goto exit; + } + rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, 0, data->bulk_in, buffer, 0x08, - USBTMC_TIMEOUT); + USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; } - dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + dev_dbg(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]); if (buffer[0] == USBTMC_STATUS_SUCCESS) { rv = 0; @@ -384,43 +384,26 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) } if (buffer[0] != USBTMC_STATUS_PENDING) { - dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]); + dev_err(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]); rv = -EPERM; goto exit; } - if (buffer[1] == 1) - do { - dev_dbg(dev, "Reading from bulk in EP\n"); - - rv = usb_bulk_msg(data->usb_dev, - usb_rcvbulkpipe(data->usb_dev, - data->bulk_in), - buffer, USBTMC_SIZE_IOBUFFER, - &actual, USBTMC_TIMEOUT); - - n++; - - if (rv < 0) { - dev_err(dev, "usb_bulk_msg returned %d\n", rv); - goto exit; - } - } while ((actual == max_size) && - (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); - - if (actual == max_size) { - dev_err(dev, "Couldn't clear device buffer within %d cycles\n", - USBTMC_MAX_READS_TO_CLEAR_BULK_IN); - rv = -EPERM; - goto exit; + if ((buffer[1] & 1) > 0) { + /* The device has 1 or more queued packets the Host can read */ + goto usbtmc_abort_bulk_in_status; } - goto usbtmc_abort_bulk_in_status; - + /* The Host must send CHECK_ABORT_BULK_IN_STATUS at a later time. */ + rv = -EAGAIN; exit: kfree(buffer); return rv; +} +static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) +{ + return usbtmc_ioctl_abort_bulk_in_tag(data, data->bTag_last_read); } static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) From patchwork Mon Jul 30 08:04:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548509 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89D59A7F6 for ; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7A8F42910F for ; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6EC2B295AF; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 105CF2910F for ; Mon, 30 Jul 2018 07:07:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726583AbeG3IlT (ORCPT ); Mon, 30 Jul 2018 04:41:19 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:36788 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726477AbeG3IlS (ORCPT ); Mon, 30 Jul 2018 04:41:18 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 977F9120EF1 for ; Mon, 30 Jul 2018 09:07:44 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 8D181120EDE; Mon, 30 Jul 2018 09:07:44 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 86E7D120EBE; Mon, 30 Jul 2018 09:07:42 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 15/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_OUT Date: Mon, 30 Jul 2018 10:04:45 +0200 Message-Id: <20180730080452.15150-16-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070742.16619.11931@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add parameter 'tag' to function usbtmc_ioctl_abort_bulk_out_tag() for future versions. Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k). Using USBTMC_SIZE_IOBUFFER is deprecated. Insert a sleep of 50 ms between subsequent CHECK_ABORT_BULK_OUT_STATUS control requests to avoid stressing the instrument with repeated requests. Use common macro USB_CTRL_GET_TIMEOUT instead of USBTMC_TIMEOUT. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index c197d8c629f2..4609dc0db8a8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -406,7 +406,8 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) return usbtmc_ioctl_abort_bulk_in_tag(data, data->bTag_last_read); } -static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) +static int usbtmc_ioctl_abort_bulk_out_tag(struct usbtmc_device_data *data, + u8 tag) { struct device *dev; u8 *buffer; @@ -423,8 +424,8 @@ static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, - data->bTag_last_write, data->bulk_out, - buffer, 2, USBTMC_TIMEOUT); + tag, data->bulk_out, + buffer, 2, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); @@ -443,12 +444,14 @@ static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) n = 0; usbtmc_abort_bulk_out_check_status: + /* do not stress device with subsequent requests */ + msleep(50); rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, 0, data->bulk_out, buffer, 0x08, - USBTMC_TIMEOUT); + USB_CTRL_GET_TIMEOUT); n++; if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); @@ -482,6 +485,11 @@ static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) return rv; } +static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data) +{ + return usbtmc_ioctl_abort_bulk_out_tag(data, data->bTag_last_write); +} + static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, void __user *arg) { From patchwork Mon Jul 30 08:04:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548517 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1827B14BC for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DDF142910F for ; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D27D4295AF; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7CC3E2910F for ; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726589AbeG3IlT (ORCPT ); Mon, 30 Jul 2018 04:41:19 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:46572 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726582AbeG3IlS (ORCPT ); Mon, 30 Jul 2018 04:41:18 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 3DA4D120EF3 for ; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 3314C120EE9; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 2D0AA120EC0; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 16/22] usb: usbtmc: Replace USBTMC_TIMEOUT macros for control messages Date: Mon, 30 Jul 2018 10:04:46 +0200 Message-Id: <20180730080452.15150-17-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070743.16636.29818@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use common timeout macro USB_CTRL_GET_TIMEOUT (=5s) for all usb_control_msg() function calls. The macro USBTMC_TIMEOUT should only be used as default value for Bulk IN/OUT transfers. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 4609dc0db8a8..91fb2fbf1aeb 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -529,7 +529,7 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, data->iin_bTag, data->ifnum, - buffer, 0x03, USBTMC_TIMEOUT); + buffer, 0x03, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "stb usb_control_msg returned %d\n", rv); goto exit; @@ -663,7 +663,7 @@ static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, wValue, data->ifnum, - buffer, 0x01, USBTMC_TIMEOUT); + buffer, 0x01, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "simple usb_control_msg failed %d\n", rv); goto exit; @@ -1810,7 +1810,7 @@ static int get_capabilities(struct usbtmc_device_data *data) rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_GET_CAPABILITIES, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, 0, buffer, 0x18, USBTMC_TIMEOUT); + 0, 0, buffer, 0x18, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto err_out; @@ -1949,7 +1949,7 @@ static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) usb_rcvctrlpipe(data->usb_dev, 0), USBTMC_REQUEST_INDICATOR_PULSE, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, 0, buffer, 0x01, USBTMC_TIMEOUT); + 0, 0, buffer, 0x01, USB_CTRL_GET_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); From patchwork Mon Jul 30 08:04:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548511 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BDDE713BB for ; Mon, 30 Jul 2018 07:07:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADD502910F for ; Mon, 30 Jul 2018 07:07:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A2638295AF; Mon, 30 Jul 2018 07:07:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48CF82910F for ; Mon, 30 Jul 2018 07:07:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbeG3IlU (ORCPT ); Mon, 30 Jul 2018 04:41:20 -0400 Received: from mr03.mx01.tldhost.de ([62.108.44.115]:40832 "EHLO mr03.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726548AbeG3IlU (ORCPT ); Mon, 30 Jul 2018 04:41:20 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E74D0120E58 for ; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id D4436120EC7; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id CE335120EB8; Mon, 30 Jul 2018 09:07:43 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 17/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_API_VERSION Date: Mon, 30 Jul 2018 10:04:47 +0200 Message-Id: <20180730080452.15150-18-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070744.16653.49100@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add ioctl USBTMC_IOCTL_API_VERSION to get current API version of usbtmc driver. This is to allow an instrument library to determine whether the driver API is compatible with the implementation. The API may change in future versions. Therefore the macro USBTMC_API_VERSION should be incremented when changing tmc.h with new flags, ioctls or when changing a significant behavior of the driver. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 9 +++++++++ include/uapi/linux/usb/tmc.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 91fb2fbf1aeb..fb49a737ea61 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -22,6 +22,10 @@ #include #include +/* Increment API VERSION when changing tmc.h with new flags or ioctls + * or when changing a significant behavior of the driver. + */ +#define USBTMC_API_VERSION (2) #define USBTMC_HEADER_SIZE 12 #define USBTMC_MINOR_BASE 176 @@ -2187,6 +2191,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void __user *)arg); break; + case USBTMC_IOCTL_API_VERSION: + retval = put_user(USBTMC_API_VERSION, + (__u32 __user *)arg); + break; + case USBTMC488_IOCTL_GET_CAPS: retval = copy_to_user((void __user *)arg, &data->usb488_caps, diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 2435694d3ba5..1d3373922e5e 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -89,6 +89,7 @@ struct usbtmc_message { #define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct usbtmc_message) #define USBTMC_IOCTL_READ _IOWR(USBTMC_IOC_NR, 14, struct usbtmc_message) #define USBTMC_IOCTL_WRITE_RESULT _IOWR(USBTMC_IOC_NR, 15, __u32) +#define USBTMC_IOCTL_API_VERSION _IOR(USBTMC_IOC_NR, 16, __u32) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) From patchwork Mon Jul 30 08:04:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548519 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2BF6213BB for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0814E2959B for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F0C2B295B0; Mon, 30 Jul 2018 07:07:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F8682959B for ; Mon, 30 Jul 2018 07:07:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726622AbeG3IlX (ORCPT ); Mon, 30 Jul 2018 04:41:23 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:51912 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726594AbeG3IlU (ORCPT ); Mon, 30 Jul 2018 04:41:20 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 7F0E7120EED for ; Mon, 30 Jul 2018 09:07:46 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 74B24120EBA; Mon, 30 Jul 2018 09:07:46 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 6F7F2120EAA; Mon, 30 Jul 2018 09:07:44 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 18/22] usb: usbtmc: Update ioctl-number.txt Date: Mon, 30 Jul 2018 10:04:48 +0200 Message-Id: <20180730080452.15150-19-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070744.16670.76945@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Reserve a suitable range of ioctl numbers for USBTMC driver. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- Documentation/ioctl/ioctl-number.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 480c8609dc58..810dd6c30296 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -200,7 +200,7 @@ Code Seq#(hex) Include File Comments 'X' 01 linux/pktcdvd.h conflict! 'Y' all linux/cyclades.h 'Z' 14-15 drivers/message/fusion/mptctl.h -'[' 00-07 linux/usb/tmc.h USB Test and Measurement Devices +'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices 'a' all linux/atm*.h, linux/sonet.h ATM on linux From patchwork Mon Jul 30 08:04:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548513 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6840EA7F6 for ; Mon, 30 Jul 2018 07:07:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 562862910F for ; Mon, 30 Jul 2018 07:07:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4AC6C295AF; Mon, 30 Jul 2018 07:07:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E7EAA2910F for ; Mon, 30 Jul 2018 07:07:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726608AbeG3IlV (ORCPT ); Mon, 30 Jul 2018 04:41:21 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:53292 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726476AbeG3IlV (ORCPT ); Mon, 30 Jul 2018 04:41:21 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 2A2F9120EFB for ; Mon, 30 Jul 2018 09:07:47 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 1FD06120EBE; Mon, 30 Jul 2018 09:07:47 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 17965120EBE; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 19/22] usb: usbtmc: Remove redundant code Date: Mon, 30 Jul 2018 10:04:49 +0200 Message-Id: <20180730080452.15150-20-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070745.16689.65337@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Remove redundant code and fix debug messages. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index fb49a737ea61..81144c0c4772 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1753,12 +1753,9 @@ static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data) rv = usb_clear_halt(data->usb_dev, usb_sndbulkpipe(data->usb_dev, data->bulk_out)); - if (rv < 0) { - dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", - rv); - return rv; - } - return 0; + if (rv < 0) + dev_err(&data->usb_dev->dev, "%s returned %d\n", __func__, rv); + return rv; } static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) @@ -1768,12 +1765,9 @@ static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) rv = usb_clear_halt(data->usb_dev, usb_rcvbulkpipe(data->usb_dev, data->bulk_in)); - if (rv < 0) { - dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", - rv); - return rv; - } - return 0; + if (rv < 0) + dev_err(&data->usb_dev->dev, "%s returned %d\n", __func__, rv); + return rv; } static int usbtmc_ioctl_cancel_io(struct usbtmc_file_data *file_data) @@ -2197,11 +2191,8 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case USBTMC488_IOCTL_GET_CAPS: - retval = copy_to_user((void __user *)arg, - &data->usb488_caps, - sizeof(data->usb488_caps)); - if (retval) - retval = -EFAULT; + retval = put_user(data->usb488_caps, + (unsigned char __user *)arg); break; case USBTMC488_IOCTL_READ_STB: From patchwork Mon Jul 30 08:04:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548515 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 20D2714BC for ; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 125202910F for ; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 06DBF295AF; Mon, 30 Jul 2018 07:07:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AF8872910F for ; Mon, 30 Jul 2018 07:07:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726604AbeG3IlV (ORCPT ); Mon, 30 Jul 2018 04:41:21 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:60168 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726598AbeG3IlV (ORCPT ); Mon, 30 Jul 2018 04:41:21 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id C1551120EEA for ; Mon, 30 Jul 2018 09:07:47 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id B62A2120ED2; Mon, 30 Jul 2018 09:07:47 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id AEF37120EC0; Mon, 30 Jul 2018 09:07:45 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 20/22] usb: usbtmc: Remove redundant macro USBTMC_SIZE_IOBUFFER Date: Mon, 30 Jul 2018 10:04:50 +0200 Message-Id: <20180730080452.15150-21-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070746.16708.43713@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 81144c0c4772..785eee3a6b89 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -30,12 +30,6 @@ #define USBTMC_HEADER_SIZE 12 #define USBTMC_MINOR_BASE 176 -/* - * Size of driver internal IO buffer. Must be multiple of 4 and at least as - * large as wMaxPacketSize (which is usually 512 bytes). - */ -#define USBTMC_SIZE_IOBUFFER 2048 - /* Minimum USB timeout (in milliseconds) */ #define USBTMC_MIN_TIMEOUT 100 /* Default USB timeout (in milliseconds) */ From patchwork Mon Jul 30 08:04:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548523 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D436413BB for ; Mon, 30 Jul 2018 07:07:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D00D295AF for ; Mon, 30 Jul 2018 07:07:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3194F29601; Mon, 30 Jul 2018 07:07:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DD11D295AF for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726620AbeG3IlX (ORCPT ); Mon, 30 Jul 2018 04:41:23 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:34832 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726599AbeG3IlW (ORCPT ); Mon, 30 Jul 2018 04:41:22 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 6969D120ED2 for ; Mon, 30 Jul 2018 09:07:48 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 5D0B1120EC0; Mon, 30 Jul 2018 09:07:48 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 541B1120EB8; Mon, 30 Jul 2018 09:07:46 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 21/22] usb: usbtmc: Fix split quoted string in debug message Date: Mon, 30 Jul 2018 10:04:51 +0200 Message-Id: <20180730080452.15150-22-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070746.16726.12997@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 785eee3a6b89..6aef3447adcc 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2507,8 +2507,8 @@ static int usbtmc_probe(struct usb_interface *intf, retcode = usb_register_dev(intf, &usbtmc_class); if (retcode) { - dev_err(&intf->dev, "Not able to get a minor" - " (base %u, slice default): %d\n", USBTMC_MINOR_BASE, + dev_err(&intf->dev, "Not able to get a minor (base %u, slice default): %d\n", + USBTMC_MINOR_BASE, retcode); goto error_register; } From patchwork Mon Jul 30 08:04:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10548521 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F2BA14BC for ; Mon, 30 Jul 2018 07:07:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C254C2910F for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6B49295B0; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 180C7295AF for ; Mon, 30 Jul 2018 07:07:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726611AbeG3IlY (ORCPT ); Mon, 30 Jul 2018 04:41:24 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:50092 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726476AbeG3IlX (ORCPT ); Mon, 30 Jul 2018 04:41:23 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 2456C120EB8 for ; Mon, 30 Jul 2018 09:07:49 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 0FE6C120EBA; Mon, 30 Jul 2018 09:07:49 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 01235120EAA; Mon, 30 Jul 2018 09:07:47 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, pankaj.adhikari@ni.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v4 22/22] usb: usbtmc: Remove sysfs group TermChar and auto_abort Date: Mon, 30 Jul 2018 10:04:52 +0200 Message-Id: <20180730080452.15150-23-guido@kiener-muenchen.de> In-Reply-To: <20180730080452.15150-1-guido@kiener-muenchen.de> References: <20180730080452.15150-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180730070747.16743.41436@server12.tldhost.de> X-PPP-Vhost: kiener-muenchen.de X-POWERED-BY: TLDHost.de - AV:CLEAN SPAM:OK Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP As all the properties of the usbtmc driver can now be controlled on a per file descriptor basis by ioctl functions the sysfs interface is of limited use. We are not aware about applications that are using the sysfs parameter TermChar, TermCharEnabled or auto_abort. Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- .../ABI/stable/sysfs-driver-usb-usbtmc | 35 -------- drivers/usb/class/usbtmc.c | 84 +------------------ 2 files changed, 3 insertions(+), 116 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc index e960cd027e1e..a9e123ba32cd 100644 --- a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc +++ b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc @@ -25,38 +25,3 @@ Description: 4.2.2. The files are read only. - - -What: /sys/bus/usb/drivers/usbtmc/*/TermChar -Date: August 2008 -Contact: Greg Kroah-Hartman -Description: - This file is the TermChar value to be sent to the USB TMC - device as described by the document, "Universal Serial Bus Test - and Measurement Class Specification - (USBTMC) Revision 1.0" as published by the USB-IF. - - Note that the TermCharEnabled file determines if this value is - sent to the device or not. - - -What: /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled -Date: August 2008 -Contact: Greg Kroah-Hartman -Description: - This file determines if the TermChar is to be sent to the - device on every transaction or not. For more details about - this, please see the document, "Universal Serial Bus Test and - Measurement Class Specification (USBTMC) Revision 1.0" as - published by the USB-IF. - - -What: /sys/bus/usb/drivers/usbtmc/*/auto_abort -Date: August 2008 -Contact: Greg Kroah-Hartman -Description: - This file determines if the transaction of the USB TMC - device is to be automatically aborted if there is any error. - For more details about this, please see the document, - "Universal Serial Bus Test and Measurement Class Specification - (USBTMC) Revision 1.0" as published by the USB-IF. diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6aef3447adcc..f8391d41b13d 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -102,11 +102,6 @@ struct usbtmc_device_data { /* coalesced usb488_caps from usbtmc_dev_capabilities */ __u8 usb488_caps; - /* attributes from the USB TMC spec for this device */ - u8 TermChar; - bool TermCharEnabled; - bool auto_abort; - bool zombie; /* fd of disconnected device */ struct usbtmc_dev_capabilities capabilities; @@ -204,11 +199,10 @@ static int usbtmc_open(struct inode *inode, struct file *filp) atomic_set(&file_data->closing, 0); - /* copy default values from device settings */ file_data->timeout = USBTMC_TIMEOUT; - file_data->term_char = data->TermChar; - file_data->term_char_enabled = data->TermCharEnabled; - file_data->auto_abort = data->auto_abort; + file_data->term_char = '\n'; + file_data->term_char_enabled = 0; + file_data->auto_abort = 0; file_data->eom_val = 1; INIT_LIST_HEAD(&file_data->file_elem); @@ -1859,72 +1853,6 @@ static const struct attribute_group capability_attr_grp = { .attrs = capability_attrs, }; -static ssize_t TermChar_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usbtmc_device_data *data = usb_get_intfdata(intf); - - return sprintf(buf, "%c\n", data->TermChar); -} - -static ssize_t TermChar_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usbtmc_device_data *data = usb_get_intfdata(intf); - - if (count < 1) - return -EINVAL; - data->TermChar = buf[0]; - return count; -} -static DEVICE_ATTR_RW(TermChar); - -#define data_attribute(name) \ -static ssize_t name##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usbtmc_device_data *data = usb_get_intfdata(intf); \ - \ - return sprintf(buf, "%d\n", data->name); \ -} \ -static ssize_t name##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usbtmc_device_data *data = usb_get_intfdata(intf); \ - ssize_t result; \ - unsigned val; \ - \ - result = sscanf(buf, "%u\n", &val); \ - if (result != 1) \ - result = -EINVAL; \ - data->name = val; \ - if (result < 0) \ - return result; \ - else \ - return count; \ -} \ -static DEVICE_ATTR_RW(name) - -data_attribute(TermCharEnabled); -data_attribute(auto_abort); - -static struct attribute *data_attrs[] = { - &dev_attr_TermChar.attr, - &dev_attr_TermCharEnabled.attr, - &dev_attr_auto_abort.attr, - NULL, -}; - -static const struct attribute_group data_attr_grp = { - .attrs = data_attrs, -}; - static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) { struct device *dev; @@ -2428,8 +2356,6 @@ static int usbtmc_probe(struct usb_interface *intf, /* Initialize USBTMC bTag and other fields */ data->bTag = 1; - data->TermCharEnabled = 0; - data->TermChar = '\n'; /* 2 <= bTag <= 127 USBTMC-USB488 subclass specification 4.3.1 */ data->iin_bTag = 2; @@ -2503,8 +2429,6 @@ static int usbtmc_probe(struct usb_interface *intf, } } - retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp); - retcode = usb_register_dev(intf, &usbtmc_class); if (retcode) { dev_err(&intf->dev, "Not able to get a minor (base %u, slice default): %d\n", @@ -2518,7 +2442,6 @@ static int usbtmc_probe(struct usb_interface *intf, error_register: sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); - sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); usbtmc_free_int(data); err_put: kref_put(&data->kref, usbtmc_delete); @@ -2532,7 +2455,6 @@ static void usbtmc_disconnect(struct usb_interface *intf) usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); - sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); mutex_lock(&data->io_mutex); data->zombie = 1; wake_up_interruptible_all(&data->waitq);