Skip to content

Commit 4f3c8d6

Browse files
GuidoKienergregkh
authored andcommitted
usb: usbtmc: Support Read Status Byte with SRQ per file
Add 'struct usbtmc_file_data' for each file handle to cache last srq_byte (=Status Byte with SRQ) received by usbtmc_interrupt(..) usbtmc488_ioctl_read_stb returns cached srq_byte when available for each file handle to avoid race conditions of concurrent applications. SRQ now sets EPOLLPRI instead of EPOLLIN since EPOLLIN is now reserved for asynchronous reads Tested-by: Dave Penkler <dpenkler@gmail.com> Reviewed-by: Steve Bayless <steve_bayless@keysight.com> Signed-off-by: Guido Kiener <guido.kiener@rohde-schwarz.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 04b453c commit 4f3c8d6

File tree

1 file changed

+105
-31
lines changed

1 file changed

+105
-31
lines changed

drivers/usb/class/usbtmc.c

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct usbtmc_device_data {
6767
const struct usb_device_id *id;
6868
struct usb_device *usb_dev;
6969
struct usb_interface *intf;
70+
struct list_head file_list;
7071

7172
unsigned int bulk_in;
7273
unsigned int bulk_out;
@@ -87,7 +88,6 @@ struct usbtmc_device_data {
8788
int iin_interval;
8889
struct urb *iin_urb;
8990
u16 iin_wMaxPacketSize;
90-
atomic_t srq_asserted;
9191

9292
/* coalesced usb488_caps from usbtmc_dev_capabilities */
9393
__u8 usb488_caps;
@@ -104,9 +104,21 @@ struct usbtmc_device_data {
104104
struct mutex io_mutex; /* only one i/o function running at a time */
105105
wait_queue_head_t waitq;
106106
struct fasync_struct *fasync;
107+
spinlock_t dev_lock; /* lock for file_list */
107108
};
108109
#define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref)
109110

111+
/*
112+
* This structure holds private data for each USBTMC file handle.
113+
*/
114+
struct usbtmc_file_data {
115+
struct usbtmc_device_data *data;
116+
struct list_head file_elem;
117+
118+
u8 srq_byte;
119+
atomic_t srq_asserted;
120+
};
121+
110122
/* Forward declarations */
111123
static struct usb_driver usbtmc_driver;
112124

@@ -122,29 +134,53 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
122134
{
123135
struct usb_interface *intf;
124136
struct usbtmc_device_data *data;
125-
int retval = 0;
137+
struct usbtmc_file_data *file_data;
126138

127139
intf = usb_find_interface(&usbtmc_driver, iminor(inode));
128140
if (!intf) {
129141
pr_err("can not find device for minor %d", iminor(inode));
130142
return -ENODEV;
131143
}
132144

145+
file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
146+
if (!file_data)
147+
return -ENOMEM;
148+
133149
data = usb_get_intfdata(intf);
134150
/* Protect reference to data from file structure until release */
135151
kref_get(&data->kref);
136152

153+
mutex_lock(&data->io_mutex);
154+
file_data->data = data;
155+
156+
INIT_LIST_HEAD(&file_data->file_elem);
157+
spin_lock_irq(&data->dev_lock);
158+
list_add_tail(&file_data->file_elem, &data->file_list);
159+
spin_unlock_irq(&data->dev_lock);
160+
mutex_unlock(&data->io_mutex);
161+
137162
/* Store pointer in file structure's private data field */
138-
filp->private_data = data;
163+
filp->private_data = file_data;
139164

140-
return retval;
165+
return 0;
141166
}
142167

143168
static int usbtmc_release(struct inode *inode, struct file *file)
144169
{
145-
struct usbtmc_device_data *data = file->private_data;
170+
struct usbtmc_file_data *file_data = file->private_data;
146171

147-
kref_put(&data->kref, usbtmc_delete);
172+
/* prevent IO _AND_ usbtmc_interrupt */
173+
mutex_lock(&file_data->data->io_mutex);
174+
spin_lock_irq(&file_data->data->dev_lock);
175+
176+
list_del(&file_data->file_elem);
177+
178+
spin_unlock_irq(&file_data->data->dev_lock);
179+
mutex_unlock(&file_data->data->io_mutex);
180+
181+
kref_put(&file_data->data->kref, usbtmc_delete);
182+
file_data->data = NULL;
183+
kfree(file_data);
148184
return 0;
149185
}
150186

@@ -369,10 +405,12 @@ static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
369405
return rv;
370406
}
371407

372-
static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
408+
static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
373409
void __user *arg)
374410
{
411+
struct usbtmc_device_data *data = file_data->data;
375412
struct device *dev = &data->intf->dev;
413+
int srq_asserted = 0;
376414
u8 *buffer;
377415
u8 tag;
378416
__u8 stb;
@@ -381,15 +419,25 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
381419
dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n",
382420
data->iin_ep_present);
383421

422+
spin_lock_irq(&data->dev_lock);
423+
srq_asserted = atomic_xchg(&file_data->srq_asserted, srq_asserted);
424+
if (srq_asserted) {
425+
/* a STB with SRQ is already received */
426+
stb = file_data->srq_byte;
427+
spin_unlock_irq(&data->dev_lock);
428+
rv = put_user(stb, (__u8 __user *)arg);
429+
dev_dbg(dev, "stb:0x%02x with srq received %d\n",
430+
(unsigned int)stb, rv);
431+
return rv;
432+
}
433+
spin_unlock_irq(&data->dev_lock);
434+
384435
buffer = kmalloc(8, GFP_KERNEL);
385436
if (!buffer)
386437
return -ENOMEM;
387438

388439
atomic_set(&data->iin_data_valid, 0);
389440

390-
/* must issue read_stb before using poll or select */
391-
atomic_set(&data->srq_asserted, 0);
392-
393441
rv = usb_control_msg(data->usb_dev,
394442
usb_rcvctrlpipe(data->usb_dev, 0),
395443
USBTMC488_REQUEST_READ_STATUS_BYTE,
@@ -435,9 +483,8 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
435483
stb = buffer[2];
436484
}
437485

438-
rv = copy_to_user(arg, &stb, sizeof(stb));
439-
if (rv)
440-
rv = -EFAULT;
486+
rv = put_user(stb, (__u8 __user *)arg);
487+
dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)stb, rv);
441488

442489
exit:
443490
/* bump interrupt bTag */
@@ -565,6 +612,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
565612
static ssize_t usbtmc_read(struct file *filp, char __user *buf,
566613
size_t count, loff_t *f_pos)
567614
{
615+
struct usbtmc_file_data *file_data;
568616
struct usbtmc_device_data *data;
569617
struct device *dev;
570618
u32 n_characters;
@@ -576,7 +624,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
576624
size_t this_part;
577625

578626
/* Get pointer to private data structure */
579-
data = filp->private_data;
627+
file_data = filp->private_data;
628+
data = file_data->data;
580629
dev = &data->intf->dev;
581630

582631
buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
@@ -721,6 +770,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
721770
static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
722771
size_t count, loff_t *f_pos)
723772
{
773+
struct usbtmc_file_data *file_data;
724774
struct usbtmc_device_data *data;
725775
u8 *buffer;
726776
int retval;
@@ -730,7 +780,8 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
730780
int done;
731781
int this_part;
732782

733-
data = filp->private_data;
783+
file_data = filp->private_data;
784+
data = file_data->data;
734785

735786
buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
736787
if (!buffer)
@@ -1140,10 +1191,13 @@ static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data)
11401191

11411192
static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
11421193
{
1194+
struct usbtmc_file_data *file_data;
11431195
struct usbtmc_device_data *data;
11441196
int retval = -EBADRQC;
11451197

1146-
data = file->private_data;
1198+
file_data = file->private_data;
1199+
data = file_data->data;
1200+
11471201
mutex_lock(&data->io_mutex);
11481202
if (data->zombie) {
11491203
retval = -ENODEV;
@@ -1184,7 +1238,8 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
11841238
break;
11851239

11861240
case USBTMC488_IOCTL_READ_STB:
1187-
retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg);
1241+
retval = usbtmc488_ioctl_read_stb(file_data,
1242+
(void __user *)arg);
11881243
break;
11891244

11901245
case USBTMC488_IOCTL_REN_CONTROL:
@@ -1210,14 +1265,15 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
12101265

12111266
static int usbtmc_fasync(int fd, struct file *file, int on)
12121267
{
1213-
struct usbtmc_device_data *data = file->private_data;
1268+
struct usbtmc_file_data *file_data = file->private_data;
12141269

1215-
return fasync_helper(fd, file, on, &data->fasync);
1270+
return fasync_helper(fd, file, on, &file_data->data->fasync);
12161271
}
12171272

12181273
static __poll_t usbtmc_poll(struct file *file, poll_table *wait)
12191274
{
1220-
struct usbtmc_device_data *data = file->private_data;
1275+
struct usbtmc_file_data *file_data = file->private_data;
1276+
struct usbtmc_device_data *data = file_data->data;
12211277
__poll_t mask;
12221278

12231279
mutex_lock(&data->io_mutex);
@@ -1229,7 +1285,7 @@ static __poll_t usbtmc_poll(struct file *file, poll_table *wait)
12291285

12301286
poll_wait(file, &data->waitq, wait);
12311287

1232-
mask = (atomic_read(&data->srq_asserted)) ? EPOLLIN | EPOLLRDNORM : 0;
1288+
mask = (atomic_read(&file_data->srq_asserted)) ? EPOLLPRI : 0;
12331289

12341290
no_poll:
12351291
mutex_unlock(&data->io_mutex);
@@ -1276,15 +1332,33 @@ static void usbtmc_interrupt(struct urb *urb)
12761332
}
12771333
/* check for SRQ notification */
12781334
if (data->iin_buffer[0] == 0x81) {
1335+
unsigned long flags;
1336+
struct list_head *elem;
1337+
12791338
if (data->fasync)
12801339
kill_fasync(&data->fasync,
1281-
SIGIO, POLL_IN);
1340+
SIGIO, POLL_PRI);
12821341

1283-
atomic_set(&data->srq_asserted, 1);
1284-
wake_up_interruptible(&data->waitq);
1342+
spin_lock_irqsave(&data->dev_lock, flags);
1343+
list_for_each(elem, &data->file_list) {
1344+
struct usbtmc_file_data *file_data;
1345+
1346+
file_data = list_entry(elem,
1347+
struct usbtmc_file_data,
1348+
file_elem);
1349+
file_data->srq_byte = data->iin_buffer[1];
1350+
atomic_set(&file_data->srq_asserted, 1);
1351+
}
1352+
spin_unlock_irqrestore(&data->dev_lock, flags);
1353+
1354+
dev_dbg(dev, "srq received bTag %x stb %x\n",
1355+
(unsigned int)data->iin_buffer[0],
1356+
(unsigned int)data->iin_buffer[1]);
1357+
wake_up_interruptible_all(&data->waitq);
12851358
goto exit;
12861359
}
1287-
dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]);
1360+
dev_warn(dev, "invalid notification: %x\n",
1361+
data->iin_buffer[0]);
12881362
break;
12891363
case -EOVERFLOW:
12901364
dev_err(dev, "overflow with length %d, actual length is %d\n",
@@ -1295,6 +1369,7 @@ static void usbtmc_interrupt(struct urb *urb)
12951369
case -ESHUTDOWN:
12961370
case -EILSEQ:
12971371
case -ETIME:
1372+
case -EPIPE:
12981373
/* urb terminated, clean up */
12991374
dev_dbg(dev, "urb terminated, status: %d\n", status);
13001375
return;
@@ -1339,7 +1414,9 @@ static int usbtmc_probe(struct usb_interface *intf,
13391414
mutex_init(&data->io_mutex);
13401415
init_waitqueue_head(&data->waitq);
13411416
atomic_set(&data->iin_data_valid, 0);
1342-
atomic_set(&data->srq_asserted, 0);
1417+
INIT_LIST_HEAD(&data->file_list);
1418+
spin_lock_init(&data->dev_lock);
1419+
13431420
data->zombie = 0;
13441421

13451422
/* Initialize USBTMC bTag and other fields */
@@ -1442,17 +1519,14 @@ static int usbtmc_probe(struct usb_interface *intf,
14421519

14431520
static void usbtmc_disconnect(struct usb_interface *intf)
14441521
{
1445-
struct usbtmc_device_data *data;
1522+
struct usbtmc_device_data *data = usb_get_intfdata(intf);
14461523

1447-
dev_dbg(&intf->dev, "usbtmc_disconnect called\n");
1448-
1449-
data = usb_get_intfdata(intf);
14501524
usb_deregister_dev(intf, &usbtmc_class);
14511525
sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
14521526
sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
14531527
mutex_lock(&data->io_mutex);
14541528
data->zombie = 1;
1455-
wake_up_all(&data->waitq);
1529+
wake_up_interruptible_all(&data->waitq);
14561530
mutex_unlock(&data->io_mutex);
14571531
usbtmc_free_int(data);
14581532
kref_put(&data->kref, usbtmc_delete);

0 commit comments

Comments
 (0)