On Thu, May 17, 2018 at 07:03:27PM +0200, Guido Kiener wrote: > Add ioctls USBTMC_IOCTL_GET_TIMEOUT / USBTMC_IOCTL_SET_TIMEOUT to > get/set I/O timeout for specific file handle. > > Different operations on an instrument can take different lengths of > time thus it is important to be able to set the timeout slightly > longer than the expected duration of each operation to optimise the > responsiveness of the application. As the instrument may be shared by > multiple applications the timeout should be settable on a per file > descriptor basis. > > Tested-by: Dave Penkler <dpenkler@xxxxxxxxx> > Reviewed-by: Steve Bayless <steve_bayless@xxxxxxxxxxxx> > Signed-off-by: Dave Penkler <dpenkler@xxxxxxxxx> > Signed-off-by: Guido Kiener <guido.kiener@xxxxxxxxxxxxxxxxx> > --- > drivers/usb/class/usbtmc.c | 58 +++++++++++++++++++++++++++++++++--- > include/uapi/linux/usb/tmc.h | 2 ++ > 2 files changed, 56 insertions(+), 4 deletions(-) > > diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c > index 5754354429d8..ad7872003420 100644 > --- a/drivers/usb/class/usbtmc.c > +++ b/drivers/usb/class/usbtmc.c > @@ -30,6 +30,8 @@ > */ > #define USBTMC_SIZE_IOBUFFER 2048 > > +/* Minimum USB timeout (in milliseconds) */ > +#define USBTMC_MIN_TIMEOUT 100 > /* Default USB timeout (in milliseconds) */ > #define USBTMC_TIMEOUT 5000 > > @@ -116,6 +118,7 @@ struct usbtmc_file_data { > struct usbtmc_device_data *data; > struct list_head file_elem; > > + u32 timeout; > u8 srq_byte; > atomic_t srq_asserted; > > @@ -163,6 +166,7 @@ static int usbtmc_open(struct inode *inode, struct file *filp) > file_data->data = data; > > /* copy default values from device settings */ > + file_data->timeout = USBTMC_TIMEOUT; > file_data->TermChar = data->TermChar; > file_data->TermCharEnabled = data->TermCharEnabled; > file_data->auto_abort = data->auto_abort; > @@ -478,7 +482,7 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, > rv = wait_event_interruptible_timeout( > data->waitq, > atomic_read(&data->iin_data_valid) != 0, > - USBTMC_TIMEOUT); > + file_data->timeout); > if (rv < 0) { > dev_dbg(dev, "wait interrupted %d\n", rv); > goto exit; > @@ -613,7 +617,8 @@ static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data, > retval = usb_bulk_msg(data->usb_dev, > usb_sndbulkpipe(data->usb_dev, > data->bulk_out), > - buffer, USBTMC_HEADER_SIZE, &actual, USBTMC_TIMEOUT); > + buffer, USBTMC_HEADER_SIZE, > + &actual, file_data->timeout); > > /* Store bTag (in case we need to abort) */ > data->bTag_last_write = data->bTag; > @@ -681,7 +686,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, > usb_rcvbulkpipe(data->usb_dev, > data->bulk_in), > buffer, USBTMC_SIZE_IOBUFFER, &actual, > - USBTMC_TIMEOUT); > + file_data->timeout); > > dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual); > > @@ -854,7 +859,7 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, > usb_sndbulkpipe(data->usb_dev, > data->bulk_out), > buffer, n_bytes, > - &actual, USBTMC_TIMEOUT); > + &actual, file_data->timeout); > if (retval != 0) > break; > n_bytes -= actual; > @@ -1211,6 +1216,41 @@ static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) > return rv; > } > > +/* > + * Get the usb timeout value > + */ > +static int usbtmc_ioctl_get_timeout(struct usbtmc_file_data *file_data, > + void __user *arg) > +{ > + __u32 timeout; > + > + timeout = file_data->timeout; > + > + return put_user(timeout, (__u32 __user *)arg); > +} > + > +/* > + * Set the usb timeout value > + */ > +static int usbtmc_ioctl_set_timeout(struct usbtmc_file_data *file_data, > + void __user *arg) > +{ > + __u32 timeout; > + > + if (get_user(timeout, (__u32 __user *)arg)) > + return -EFAULT; > + > + /* Note that timeout = 0 means > + * MAX_SCHEDULE_TIMEOUT in usb_control_msg > + */ > + if (timeout < USBTMC_MIN_TIMEOUT) > + return -EINVAL; > + > + file_data->timeout = timeout; > + > + return 0; > +} > + > static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > { > struct usbtmc_file_data *file_data; > @@ -1251,6 +1291,16 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > retval = usbtmc_ioctl_abort_bulk_in(data); > break; > > + case USBTMC_IOCTL_GET_TIMEOUT: > + retval = usbtmc_ioctl_get_timeout(file_data, > + (void __user *)arg); > + break; > + > + case USBTMC_IOCTL_SET_TIMEOUT: > + retval = usbtmc_ioctl_set_timeout(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 03f6adc8f35b..d6de192150f4 100644 > --- a/include/uapi/linux/usb/tmc.h > +++ b/include/uapi/linux/usb/tmc.h > @@ -46,6 +46,8 @@ > #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_GET_TIMEOUT _IOR(USBTMC_IOC_NR, 9, unsigned int) > +#define USBTMC_IOCTL_SET_TIMEOUT _IOW(USBTMC_IOC_NR, 10, unsigned int) What is the "size" of unsigned int in 32 vs. 64 bit kernels? Shouldn't this be __u32? thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html