From patchwork Tue Jul 24 09:05:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10541517 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 1FE9D14BC for ; Tue, 24 Jul 2018 08:08:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 08CC128692 for ; Tue, 24 Jul 2018 08:08:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F10DD28704; Tue, 24 Jul 2018 08:08:28 +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 69A1728692 for ; Tue, 24 Jul 2018 08:08:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388449AbeGXJNm (ORCPT ); Tue, 24 Jul 2018 05:13:42 -0400 Received: from mr05.mx01.tldhost.de ([62.108.36.228]:54520 "EHLO mr05.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388400AbeGXJNm (ORCPT ); Tue, 24 Jul 2018 05:13:42 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 757DF120EA4 for ; Tue, 24 Jul 2018 10:08:26 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 6AE4F120EA0; Tue, 24 Jul 2018 10:08:26 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 67ABE120D0D; Tue, 24 Jul 2018 10:08:24 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 01/23] usb: usbtmc: Add support for 32 bit compat applications Date: Tue, 24 Jul 2018 11:05:28 +0200 Message-Id: <20180724090550.29201-2-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080824.5459.41233@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 32 bit applications can only call ioctl functions on 64 bit systems when the field .compat_ioctl is defined for file operations. Tested-by: Dave Penkler Signed-off-by: Guido Kiener Reviewed-by: Steve Bayless --- drivers/usb/class/usbtmc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 1b7b2e402adb..83ffa5a14c3d 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -1459,6 +1460,9 @@ static const struct file_operations fops = { .open = usbtmc_open, .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = usbtmc_ioctl, +#endif .fasync = usbtmc_fasync, .poll = usbtmc_poll, .llseek = default_llseek, From patchwork Tue Jul 24 09:05:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10541519 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 A7AC91822 for ; Tue, 24 Jul 2018 08:08:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 96E8228692 for ; Tue, 24 Jul 2018 08:08:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8B63028704; Tue, 24 Jul 2018 08:08:30 +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 E9F8328692 for ; Tue, 24 Jul 2018 08:08:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388487AbeGXJNn (ORCPT ); Tue, 24 Jul 2018 05:13:43 -0400 Received: from mr05.mx01.tldhost.de ([62.108.36.228]:44697 "EHLO mr05.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388439AbeGXJNn (ORCPT ); Tue, 24 Jul 2018 05:13:43 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 35074120E84 for ; Tue, 24 Jul 2018 10:08:27 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 29980120E61; Tue, 24 Jul 2018 10:08:27 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 1C779120E76; Tue, 24 Jul 2018 10:08:25 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 02/23] usb: usbtmc: Add ioctl for generic requests on control Date: Tue, 24 Jul 2018 11:05:29 +0200 Message-Id: <20180724090550.29201-3-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080825.5472.6850@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 | 84 ++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 15 +++++++ 2 files changed, 99 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 83ffa5a14c3d..3b3b4284d04e 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,21 @@ struct usbtmc_file_data { /* Forward declarations */ static struct usb_driver usbtmc_driver; +#ifdef CONFIG_COMPAT +static void __user *u64_to_uptr(u64 value) +{ + if (in_compat_syscall()) + return compat_ptr(value); + else + return (void __user *)(unsigned long)value; +} +#else +static inline void __user *u64_to_uptr(u64 value) +{ + return (void __user *)(unsigned long)value; +} +#endif /* CONFIG_COMPAT */ + static void usbtmc_delete(struct kref *kref) { struct usbtmc_device_data *data = to_usbtmc_data(kref); @@ -1250,6 +1269,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 +1446,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 Tue Jul 24 09:05:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10541523 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 D3E9014BC for ; Tue, 24 Jul 2018 08:08:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C626628692 for ; Tue, 24 Jul 2018 08:08:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA8DE28707; Tue, 24 Jul 2018 08:08:32 +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 BA40228692 for ; Tue, 24 Jul 2018 08:08:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388500AbeGXJNp (ORCPT ); Tue, 24 Jul 2018 05:13:45 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:56996 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388400AbeGXJNp (ORCPT ); Tue, 24 Jul 2018 05:13:45 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E0658120E8E for ; Tue, 24 Jul 2018 10:08:27 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id D270D120E65; Tue, 24 Jul 2018 10:08:27 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id C8597120E87; Tue, 24 Jul 2018 10:08:25 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 03/23] usb: usbtmc: Add ioctl for vendor specific write Date: Tue, 24 Jul 2018 11:05:30 +0200 Message-Id: <20180724090550.29201-4-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080826.5487.67007@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 3b3b4284d04e..0328f1beb32d 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); #ifdef CONFIG_COMPAT static void __user *u64_to_uptr(u64 value) @@ -172,6 +185,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); @@ -197,6 +214,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; @@ -629,6 +676,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. @@ -1096,6 +1375,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; @@ -1470,6 +1758,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, @@ -1530,7 +1823,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); @@ -1543,6 +1848,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, @@ -1768,6 +2074,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); @@ -1775,14 +2082,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; } @@ -1791,6 +2130,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, @@ -1798,6 +2168,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 Tue Jul 24 09:05: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: 10541521 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 F11A114BC for ; Tue, 24 Jul 2018 08:08:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E409C28702 for ; Tue, 24 Jul 2018 08:08:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D86B728707; Tue, 24 Jul 2018 08:08:31 +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 AE29328702 for ; Tue, 24 Jul 2018 08:08:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388498AbeGXJNo (ORCPT ); Tue, 24 Jul 2018 05:13:44 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:55070 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNn (ORCPT ); Tue, 24 Jul 2018 05:13:43 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 8112A120EA5 for ; Tue, 24 Jul 2018 10:08:28 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 72D00120E80; Tue, 24 Jul 2018 10:08:28 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 66AF7120E9F; Tue, 24 Jul 2018 10:08:26 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 04/23] usb: usbtmc: Add ioctl USBTMC_IOCTL_WRITE_RESULT Date: Tue, 24 Jul 2018 11:05:31 +0200 Message-Id: <20180724090550.29201-5-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080826.5501.22147@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 0328f1beb32d..ea4e6f033c26 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -908,6 +908,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. @@ -1763,6 +1783,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 Tue Jul 24 09:05:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10541525 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 77D501822 for ; Tue, 24 Jul 2018 08:08:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A72728692 for ; Tue, 24 Jul 2018 08:08:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5E4C028704; Tue, 24 Jul 2018 08:08:33 +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 5FD2F28702 for ; Tue, 24 Jul 2018 08:08:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388514AbeGXJNp (ORCPT ); Tue, 24 Jul 2018 05:13:45 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:50042 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388439AbeGXJNp (ORCPT ); Tue, 24 Jul 2018 05:13:45 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 4981E120ECB for ; Tue, 24 Jul 2018 10:08:29 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 3DE47120EA1; Tue, 24 Jul 2018 10:08:29 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 38A17120ECA; Tue, 24 Jul 2018 10:08:27 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 05/23] usb: usbtmc: Add ioctl for vendor specific read Date: Tue, 24 Jul 2018 11:05:32 +0200 Message-Id: <20180724090550.29201-6-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> MIME-Version: 1.0 X-PPP-Message-ID: <20180724080827.5515.47815@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 ea4e6f033c26..32b588eb0304 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 */ @@ -188,6 +198,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 */ @@ -234,6 +246,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); @@ -697,6 +712,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; @@ -1398,6 +1714,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); @@ -1783,6 +2100,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); @@ -1848,15 +2170,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); @@ -2018,6 +2349,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; @@ -2114,6 +2446,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); @@ -2127,6 +2460,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 Tue Jul 24 09:05: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: 10541527 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 E2BFA184F for ; Tue, 24 Jul 2018 08:08:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D335528692 for ; Tue, 24 Jul 2018 08:08:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7C1E28702; Tue, 24 Jul 2018 08:08:33 +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 71E6D28707 for ; Tue, 24 Jul 2018 08:08:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388527AbeGXJNq (ORCPT ); Tue, 24 Jul 2018 05:13:46 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:45663 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNq (ORCPT ); Tue, 24 Jul 2018 05:13:46 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 1F58C120ECC for ; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 14377120E61; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 04890120D0D; Tue, 24 Jul 2018 10:08:28 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 06/23] usb: usbtmc: Add ioctl USBTMC_IOCTL_CANCEL_IO Date: Tue, 24 Jul 2018 11:05:33 +0200 Message-Id: <20180724090550.29201-7-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080828.5529.20234@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 32b588eb0304..67cdf5df90d7 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2141,6 +2141,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 Tue Jul 24 09:05:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guido Kiener X-Patchwork-Id: 10541529 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 884841822 for ; Tue, 24 Jul 2018 08:08:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AD6728704 for ; Tue, 24 Jul 2018 08:08:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F56B28707; Tue, 24 Jul 2018 08:08:34 +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 1004C28692 for ; Tue, 24 Jul 2018 08:08:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388526AbeGXJNq (ORCPT ); Tue, 24 Jul 2018 05:13:46 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:41148 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388439AbeGXJNq (ORCPT ); Tue, 24 Jul 2018 05:13:46 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id D813C120ED5 for ; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id CDB14120D36; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id C577E120D36; Tue, 24 Jul 2018 10:08:28 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 07/23] usb: usbtmc: Add ioctl USBTMC_IOCTL_CLEANUP_IO Date: Tue, 24 Jul 2018 11:05:34 +0200 Message-Id: <20180724090550.29201-8-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080829.5552.57082@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 67cdf5df90d7..fe140d400e1d 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1721,6 +1721,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; @@ -2145,6 +2160,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 Tue Jul 24 09:05: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: 10541531 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 3D71E14BC for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 30B0628702 for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1C5932870F; Tue, 24 Jul 2018 08:08:36 +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 E266728702 for ; Tue, 24 Jul 2018 08:08:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388536AbeGXJNs (ORCPT ); Tue, 24 Jul 2018 05:13:48 -0400 Received: from mr07.mx01.tldhost.de ([62.108.44.247]:35348 "EHLO mr07.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388515AbeGXJNr (ORCPT ); Tue, 24 Jul 2018 05:13:47 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 9D601120EA1 for ; Tue, 24 Jul 2018 10:08:31 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 8E9CD120E78; Tue, 24 Jul 2018 10:08:31 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 88F09120E84; Tue, 24 Jul 2018 10:08:29 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 08/23] usb: usbtmc: Fix suspend/resume Date: Tue, 24 Jul 2018 11:05:35 +0200 Message-Id: <20180724090550.29201-9-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080829.5574.90217@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 fe140d400e1d..3babca045c02 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2321,7 +2321,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); } @@ -2503,13 +2505,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 Tue Jul 24 09:05: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: 10541535 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 90BE21822 for ; Tue, 24 Jul 2018 08:08:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8401028702 for ; Tue, 24 Jul 2018 08:08:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 78B5428707; Tue, 24 Jul 2018 08:08:37 +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 4DB9628702 for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388558AbeGXJNt (ORCPT ); Tue, 24 Jul 2018 05:13:49 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:52442 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNs (ORCPT ); Tue, 24 Jul 2018 05:13:48 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 5C400120ED4 for ; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 508D2120E76; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 39B94120D0D; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 09/23] usb: usbtmc: Add ioctl USBTMC488_IOCTL_WAIT_SRQ Date: Tue, 24 Jul 2018 11:05:36 +0200 Message-Id: <20180724090550.29201-10-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080830.5599.97126@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 3babca045c02..edce0a753623 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; @@ -208,6 +209,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; @@ -238,6 +241,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 */ @@ -591,6 +595,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) { @@ -2157,6 +2209,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 Tue Jul 24 09:05: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: 10541533 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 96357184F for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8685F28692 for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B12728704; Tue, 24 Jul 2018 08:08:36 +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 1C0B828707 for ; Tue, 24 Jul 2018 08:08:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388554AbeGXJNs (ORCPT ); Tue, 24 Jul 2018 05:13:48 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:54091 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388531AbeGXJNs (ORCPT ); Tue, 24 Jul 2018 05:13:48 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id DFE48120ECC for ; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id D4B93120E76; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id CF335120E87; Tue, 24 Jul 2018 10:08:30 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 10/23] usb: usbtmc: add ioctl USBTMC_IOCTL_MSG_IN_ATTR Date: Tue, 24 Jul 2018 11:05:37 +0200 Message-Id: <20180724090550.29201-11-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080831.5615.39788@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 edce0a753623..d659c083a19b 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; @@ -1450,6 +1451,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) @@ -2214,6 +2217,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 Tue Jul 24 09:05: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: 10541537 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 607B01822 for ; Tue, 24 Jul 2018 08:08:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5400128692 for ; Tue, 24 Jul 2018 08:08:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 489D828716; Tue, 24 Jul 2018 08:08:38 +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 C895B28702 for ; Tue, 24 Jul 2018 08:08:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388560AbeGXJNu (ORCPT ); Tue, 24 Jul 2018 05:13:50 -0400 Received: from mr05.mx01.tldhost.de ([62.108.36.228]:37744 "EHLO mr05.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388515AbeGXJNt (ORCPT ); Tue, 24 Jul 2018 05:13:49 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 9F7F5120ED6 for ; Tue, 24 Jul 2018 10:08:33 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 94993120EA6; Tue, 24 Jul 2018 10:08:33 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 7E207120D36; Tue, 24 Jul 2018 10:08:31 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 11/23] usb: usbtmc: Add ioctl USBTMC_IOCTL_AUTO_ABORT Date: Tue, 24 Jul 2018 11:05:38 +0200 Message-Id: <20180724090550.29201-12-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080831.5631.1651@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 d659c083a19b..caadd2df13a9 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 */ @@ -216,6 +217,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); @@ -1391,7 +1393,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; } @@ -1416,7 +1418,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; } @@ -1426,21 +1428,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; } @@ -1455,7 +1457,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; } @@ -1597,7 +1599,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; } @@ -2106,6 +2108,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; @@ -2222,6 +2225,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 Tue Jul 24 09:05: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: 10541539 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 14B4414BC for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 080C928692 for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F0C4928707; Tue, 24 Jul 2018 08:08:38 +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 7264228692 for ; Tue, 24 Jul 2018 08:08:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388566AbeGXJNv (ORCPT ); Tue, 24 Jul 2018 05:13:51 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:36479 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388531AbeGXJNu (ORCPT ); Tue, 24 Jul 2018 05:13:50 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 4B0D5120ECF for ; Tue, 24 Jul 2018 10:08:34 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 3F48C120E9D; Tue, 24 Jul 2018 10:08:34 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 37CF4120E89; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 12/23] usb: usbtmc: Optimize usbtmc_write Date: Tue, 24 Jul 2018 11:05:39 +0200 Message-Id: <20180724090550.29201-13-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080832.5661.75831@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 caadd2df13a9..26d5af413009 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1524,94 +1524,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 Tue Jul 24 09:05: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: 10541541 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 9BA721822 for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8ED4528704 for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 82E6028707; Tue, 24 Jul 2018 08:08:39 +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 D4F7928702 for ; Tue, 24 Jul 2018 08:08:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388576AbeGXJNw (ORCPT ); Tue, 24 Jul 2018 05:13:52 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:45356 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNv (ORCPT ); Tue, 24 Jul 2018 05:13:51 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 0CC07120ED5 for ; Tue, 24 Jul 2018 10:08:35 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id F3707120E76; Tue, 24 Jul 2018 10:08:34 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id DEE1A120EA5; Tue, 24 Jul 2018 10:08:32 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 13/23] usb: usbtmc: Optimize usbtmc_read Date: Tue, 24 Jul 2018 11:05:40 +0200 Message-Id: <20180724090550.29201-14-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080833.5676.82239@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 26d5af413009..e5ea2d822ae3 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1308,7 +1308,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; @@ -1351,12 +1351,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, @@ -1365,20 +1364,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; @@ -1388,7 +1387,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); @@ -1400,114 +1402,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 Tue Jul 24 09:05: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: 10541559 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 8B9EB14BC for ; Tue, 24 Jul 2018 08:08:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7C7F828692 for ; Tue, 24 Jul 2018 08:08:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 709282870F; Tue, 24 Jul 2018 08:08:46 +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 00E8B28704 for ; Tue, 24 Jul 2018 08:08:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388599AbeGXJN6 (ORCPT ); Tue, 24 Jul 2018 05:13:58 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:60882 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388515AbeGXJNw (ORCPT ); Tue, 24 Jul 2018 05:13:52 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id A13D3120ED2 for ; Tue, 24 Jul 2018 10:08:35 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 97648120EA0; Tue, 24 Jul 2018 10:08:35 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 8CCB9120E65; Tue, 24 Jul 2018 10:08:33 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 14/23] usb: usbtmc: Fix ioctl USBTMC_IOCTL_CLEAR Date: Tue, 24 Jul 2018 11:05:41 +0200 Message-Id: <20180724090550.29201-15-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080833.5690.92444@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 e5ea2d822ae3..a7fa9e287477 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1647,20 +1647,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; @@ -1668,7 +1665,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; @@ -1682,22 +1679,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: @@ -1708,7 +1689,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; @@ -1725,15 +1706,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) { @@ -1741,10 +1726,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; @@ -1758,7 +1748,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 Tue Jul 24 09:05: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: 10541557 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 32AFB1822 for ; Tue, 24 Jul 2018 08:08:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2712028692 for ; Tue, 24 Jul 2018 08:08:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B8F428716; Tue, 24 Jul 2018 08:08:46 +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 7C00E28692 for ; Tue, 24 Jul 2018 08:08:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388598AbeGXJN6 (ORCPT ); Tue, 24 Jul 2018 05:13:58 -0400 Received: from mr06.mx01.tldhost.de ([62.108.41.213]:46608 "EHLO mr06.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388563AbeGXJNw (ORCPT ); Tue, 24 Jul 2018 05:13:52 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 4982E120ED6 for ; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 3EAE3120E8E; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 39BB8120D36; Tue, 24 Jul 2018 10:08:34 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 15/23] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN Date: Tue, 24 Jul 2018 11:05:42 +0200 Message-Id: <20180724090550.29201-16-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080834.5709.43502@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 a7fa9e287477..e05c11ba26f6 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -285,18 +285,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; @@ -304,21 +303,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]); @@ -326,64 +338,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; @@ -391,43 +391,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 Tue Jul 24 09:05: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: 10541543 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 0404314BC for ; Tue, 24 Jul 2018 08:08:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC58928702 for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E0E5728707; Tue, 24 Jul 2018 08:08:39 +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 877A928702 for ; Tue, 24 Jul 2018 08:08:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388578AbeGXJNw (ORCPT ); Tue, 24 Jul 2018 05:13:52 -0400 Received: from mr02.mx01.tldhost.de ([62.108.41.231]:49250 "EHLO mr02.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388531AbeGXJNw (ORCPT ); Tue, 24 Jul 2018 05:13:52 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id E2A9F120ED7 for ; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id D905C120E78; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id D121A120E78; Tue, 24 Jul 2018 10:08:34 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 16/23] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_OUT Date: Tue, 24 Jul 2018 11:05:43 +0200 Message-Id: <20180724090550.29201-17-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080835.5725.22732@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 e05c11ba26f6..5dad62c7a996 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -413,7 +413,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; @@ -430,8 +431,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); @@ -450,12 +451,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); @@ -489,6 +492,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 Tue Jul 24 09:05: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: 10541545 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 6E9CC1822 for ; Tue, 24 Jul 2018 08:08:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61B0928702 for ; Tue, 24 Jul 2018 08:08:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 561C828704; Tue, 24 Jul 2018 08:08:40 +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 022B42870F for ; Tue, 24 Jul 2018 08:08:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388580AbeGXJNx (ORCPT ); Tue, 24 Jul 2018 05:13:53 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:42123 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNx (ORCPT ); Tue, 24 Jul 2018 05:13:53 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 9DA41120ECF for ; Tue, 24 Jul 2018 10:08:37 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 934C0120E7C; Tue, 24 Jul 2018 10:08:37 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 8DBF9120E61; Tue, 24 Jul 2018 10:08:35 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 17/23] usb: usbtmc: Replace USBTMC_TIMEOUT macros for control messages Date: Tue, 24 Jul 2018 11:05:44 +0200 Message-Id: <20180724090550.29201-18-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080835.5741.5582@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 5dad62c7a996..1d0ac45346c5 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -536,7 +536,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; @@ -670,7 +670,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; @@ -1817,7 +1817,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; @@ -1956,7 +1956,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 Tue Jul 24 09:05: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: 10541547 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 278231822 for ; Tue, 24 Jul 2018 08:08:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1A99928692 for ; Tue, 24 Jul 2018 08:08:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F12728702; Tue, 24 Jul 2018 08:08:41 +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 9E26728702 for ; Tue, 24 Jul 2018 08:08:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388584AbeGXJNx (ORCPT ); Tue, 24 Jul 2018 05:13:53 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:60261 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388531AbeGXJNx (ORCPT ); Tue, 24 Jul 2018 05:13:53 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 3B056120ED1 for ; Tue, 24 Jul 2018 10:08:38 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 310C6120EA0; Tue, 24 Jul 2018 10:08:38 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 2C16A120E65; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 18/23] usb: usbtmc: Add ioctl USBTMC_IOCTL_API_VERSION Date: Tue, 24 Jul 2018 11:05:45 +0200 Message-Id: <20180724090550.29201-19-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080836.5759.29672@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 1d0ac45346c5..10dc896bf043 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 @@ -2194,6 +2198,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 Tue Jul 24 09:05: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: 10541549 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 F227C1822 for ; Tue, 24 Jul 2018 08:08:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E57B628702 for ; Tue, 24 Jul 2018 08:08:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D9F442870F; Tue, 24 Jul 2018 08:08:41 +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 5D45028702 for ; Tue, 24 Jul 2018 08:08:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388588AbeGXJNy (ORCPT ); Tue, 24 Jul 2018 05:13:54 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:35476 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNy (ORCPT ); Tue, 24 Jul 2018 05:13:54 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id CB3D8120ED2 for ; Tue, 24 Jul 2018 10:08:38 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id BF9B2120D36; Tue, 24 Jul 2018 10:08:38 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id BAA7E120D36; Tue, 24 Jul 2018 10:08:36 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 19/23] usb: usbtmc: Update ioctl-number.txt Date: Tue, 24 Jul 2018 11:05:46 +0200 Message-Id: <20180724090550.29201-20-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080837.5777.36569@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 Tue Jul 24 09:05: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: 10541553 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 0B82114BC for ; Tue, 24 Jul 2018 08:08:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F3E8728702 for ; Tue, 24 Jul 2018 08:08:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E857C2870F; Tue, 24 Jul 2018 08:08:43 +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 91C1028702 for ; Tue, 24 Jul 2018 08:08:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388596AbeGXJN4 (ORCPT ); Tue, 24 Jul 2018 05:13:56 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:59880 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388531AbeGXJNz (ORCPT ); Tue, 24 Jul 2018 05:13:55 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 6E816120ED5 for ; Tue, 24 Jul 2018 10:08:39 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 640FD120E89; Tue, 24 Jul 2018 10:08:39 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 5EDAE120E78; Tue, 24 Jul 2018 10:08:37 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 20/23] usb: usbtmc: Remove redundant code Date: Tue, 24 Jul 2018 11:05:47 +0200 Message-Id: <20180724090550.29201-21-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080837.5793.15818@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 10dc896bf043..a6482e850532 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1760,12 +1760,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) @@ -1775,12 +1772,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) @@ -2204,11 +2198,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 Tue Jul 24 09:05: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: 10541551 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 9189D14BC for ; Tue, 24 Jul 2018 08:08:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7FB0D28692 for ; Tue, 24 Jul 2018 08:08:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7478828702; Tue, 24 Jul 2018 08:08: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 2EA0F28704 for ; Tue, 24 Jul 2018 08:08:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388590AbeGXJNz (ORCPT ); Tue, 24 Jul 2018 05:13:55 -0400 Received: from mr08.mx01.tldhost.de ([84.19.26.246]:58584 "EHLO mr08.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJNz (ORCPT ); Tue, 24 Jul 2018 05:13:55 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 081A5120E8C for ; Tue, 24 Jul 2018 10:08:40 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id F1EAC120E7C; Tue, 24 Jul 2018 10:08:39 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id ED771120D2F; Tue, 24 Jul 2018 10:08:37 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 21/23] usb: usbtmc: Remove redundant macro USBTMC_SIZE_IOBUFFER Date: Tue, 24 Jul 2018 11:05:48 +0200 Message-Id: <20180724090550.29201-22-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080838.5809.71162@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 a6482e850532..ddc2e4b78a3b 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 Tue Jul 24 09:05: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: 10541555 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 A47161822 for ; Tue, 24 Jul 2018 08:08:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 979C728702 for ; Tue, 24 Jul 2018 08:08:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8C2792870F; Tue, 24 Jul 2018 08:08: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 43F1428702 for ; Tue, 24 Jul 2018 08:08:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388595AbeGXJN4 (ORCPT ); Tue, 24 Jul 2018 05:13:56 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:60830 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388592AbeGXJN4 (ORCPT ); Tue, 24 Jul 2018 05:13:56 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id A139E120EA1 for ; Tue, 24 Jul 2018 10:08:40 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 96EC3120E65; Tue, 24 Jul 2018 10:08:40 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 90AD8120E65; Tue, 24 Jul 2018 10:08:38 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 22/23] usb: usbtmc: Fix split quoted string in debug message Date: Tue, 24 Jul 2018 11:05:49 +0200 Message-Id: <20180724090550.29201-23-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080839.5823.82045@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 ddc2e4b78a3b..9a6312a49b55 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2514,8 +2514,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 Tue Jul 24 09:05: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: 10541561 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 CC1721822 for ; Tue, 24 Jul 2018 08:08:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF69928692 for ; Tue, 24 Jul 2018 08:08:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B3C212870F; Tue, 24 Jul 2018 08:08: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 1DE4B28692 for ; Tue, 24 Jul 2018 08:08:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388597AbeGXJN6 (ORCPT ); Tue, 24 Jul 2018 05:13:58 -0400 Received: from mr01.mx01.tldhost.de ([62.108.36.247]:49994 "EHLO mr01.mx01.tldhost.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388455AbeGXJN6 (ORCPT ); Tue, 24 Jul 2018 05:13:58 -0400 Received: from mx01.tldhost.de (localhost [127.0.0.1]) by mx01.tldhost.de (Postfix) with ESMTP id 532CF120E80 for ; Tue, 24 Jul 2018 10:08:41 +0200 (CEST) Received: by mx01.tldhost.de (Postfix, from userid 1001) id 495A5120E61; Tue, 24 Jul 2018 10:08:41 +0200 (CEST) Received: from server12.tldhost.de (server12.tldhost.de [84.19.26.112]) by mx01.tldhost.de (Postfix) with ESMTPS id 456E5120D36; Tue, 24 Jul 2018 10:08:39 +0200 (CEST) From: Guido Kiener To: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, guido.kiener@rohde-schwarz.com, steve_bayless@keysight.com, dpenkler@gmail.com Cc: Guido Kiener Subject: [PATCH v3 23/23] usb: usbtmc: Remove sysfs group TermChar and auto_abort Date: Tue, 24 Jul 2018 11:05:50 +0200 Message-Id: <20180724090550.29201-24-guido@kiener-muenchen.de> In-Reply-To: <20180724090550.29201-1-guido@kiener-muenchen.de> References: <20180724090550.29201-1-guido@kiener-muenchen.de> X-PPP-Message-ID: <20180724080839.5845.5893@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 9a6312a49b55..f8c7dab6d786 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; @@ -211,11 +206,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); @@ -1866,72 +1860,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; @@ -2435,8 +2363,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; @@ -2510,8 +2436,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", @@ -2525,7 +2449,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); @@ -2539,7 +2462,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);