Skip to content

Commit c7b2a99

Browse files
author
Stefan Richter
committed
firewire: nosy: convert to unlocked ioctl
The required serialization of NOSY_IOC_START and NOSY_IOC_STOP is already provided by the client_list_lock. NOSY_IOC_FILTER does not really require serialization since accesses to tcode_mask are atomic on any sane CPU architecture. Nevertheless, make it explicit that we want this to be atomic by means of client_list_lock (which also surrounds the other tcode_mask access in the IRQ handler). While we are at it, change the type of tcode_mask to u32 for consistency with the user API. NOSY_IOC_GET_STATS does not require serialization against itself. But there is a bug here regarding concurrent updates of the two counters by the IRQ handler. Fix it by taking the client_list_lock in this ioctl too. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
1 parent b5e4772 commit c7b2a99

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

drivers/firewire/nosy.c

+17-12
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ struct pcilynx {
108108

109109
struct client {
110110
struct pcilynx *lynx;
111-
unsigned long tcode_mask;
111+
u32 tcode_mask;
112112
struct packet_buffer buffer;
113113
struct list_head link;
114114
};
@@ -351,17 +351,20 @@ nosy_read(struct file *file, char *buffer, size_t count, loff_t *offset)
351351
return packet_buffer_get(&client->buffer, buffer, count);
352352
}
353353

354-
static int
355-
nosy_ioctl(struct inode *inode, struct file *file,
356-
unsigned int cmd, unsigned long arg)
354+
static long
355+
nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
357356
{
358357
struct client *client = file->private_data;
358+
spinlock_t *client_list_lock = &client->lynx->client_list_lock;
359359
struct nosy_stats stats;
360360

361361
switch (cmd) {
362362
case NOSY_IOC_GET_STATS:
363+
spin_lock_irq(client_list_lock);
363364
stats.total_packet_count = client->buffer.total_packet_count;
364-
stats.lost_packet_count = client->buffer.lost_packet_count;
365+
stats.lost_packet_count = client->buffer.lost_packet_count;
366+
spin_unlock_irq(client_list_lock);
367+
365368
if (copy_to_user((void *) arg, &stats, sizeof stats))
366369
return -EFAULT;
367370
else
@@ -376,7 +379,9 @@ nosy_ioctl(struct inode *inode, struct file *file,
376379
return 0;
377380

378381
case NOSY_IOC_FILTER:
382+
spin_lock_irq(client_list_lock);
379383
client->tcode_mask = arg;
384+
spin_unlock_irq(client_list_lock);
380385
return 0;
381386

382387
default:
@@ -386,12 +391,12 @@ nosy_ioctl(struct inode *inode, struct file *file,
386391
}
387392

388393
static const struct file_operations nosy_ops = {
389-
.owner = THIS_MODULE,
390-
.read = nosy_read,
391-
.ioctl = nosy_ioctl,
392-
.poll = nosy_poll,
393-
.open = nosy_open,
394-
.release = nosy_release,
394+
.owner = THIS_MODULE,
395+
.read = nosy_read,
396+
.unlocked_ioctl = nosy_ioctl,
397+
.poll = nosy_poll,
398+
.open = nosy_open,
399+
.release = nosy_release,
395400
};
396401

397402
#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
@@ -409,7 +414,7 @@ packet_handler(struct pcilynx *lynx)
409414
{
410415
unsigned long flags;
411416
struct client *client;
412-
unsigned long tcode_mask;
417+
u32 tcode_mask;
413418
size_t length;
414419
struct link_packet *packet;
415420
struct timeval tv;

0 commit comments

Comments
 (0)