16
16
17
17
#include <linux/kernel.h>
18
18
#include <linux/wait.h>
19
- #include <linux/spinlock_types .h>
19
+ #include <linux/mutex .h>
20
20
#include <linux/device.h>
21
21
#include <linux/cdev.h>
22
22
#include <linux/init.h>
@@ -133,9 +133,9 @@ struct axis_fifo {
133
133
int has_tx_fifo ; /* whether the IP has the tx fifo enabled */
134
134
135
135
wait_queue_head_t read_queue ; /* wait queue for asynchronos read */
136
- spinlock_t read_queue_lock ; /* lock for reading waitqueue */
136
+ struct mutex read_lock ; /* lock for reading */
137
137
wait_queue_head_t write_queue ; /* wait queue for asynchronos write */
138
- spinlock_t write_queue_lock ; /* lock for writing waitqueue */
138
+ struct mutex write_lock ; /* lock for writing */
139
139
unsigned int write_flags ; /* write file flags */
140
140
unsigned int read_flags ; /* read file flags */
141
141
@@ -336,7 +336,21 @@ static void reset_ip_core(struct axis_fifo *fifo)
336
336
iowrite32 (XLLF_INT_ALL_MASK , fifo -> base_addr + XLLF_ISR_OFFSET );
337
337
}
338
338
339
- /* reads a single packet from the fifo as dictated by the tlast signal */
339
+ /**
340
+ * axis_fifo_write() - Read a packet from AXIS-FIFO character device.
341
+ * @f Open file.
342
+ * @buf User space buffer to read to.
343
+ * @len User space buffer length.
344
+ * @off Buffer offset.
345
+ *
346
+ * As defined by the device's documentation, we need to check the device's
347
+ * occupancy before reading the length register and then the data. All these
348
+ * operations must be executed atomically, in order and one after the other
349
+ * without missing any.
350
+ *
351
+ * Returns the number of bytes read from the device or negative error code
352
+ * on failure.
353
+ */
340
354
static ssize_t axis_fifo_read (struct file * f , char __user * buf ,
341
355
size_t len , loff_t * off )
342
356
{
@@ -350,51 +364,54 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
350
364
u32 tmp_buf [READ_BUF_SIZE ];
351
365
352
366
if (fifo -> read_flags & O_NONBLOCK ) {
353
- /* opened in non-blocking mode
354
- * return if there are no packets available
367
+ /*
368
+ * Device opened in non-blocking mode. Try to lock it and then
369
+ * check if any packet is available.
355
370
*/
356
- if (!ioread32 ( fifo -> base_addr + XLLF_RDFO_OFFSET ))
371
+ if (!mutex_trylock ( & fifo -> read_lock ))
357
372
return - EAGAIN ;
373
+
374
+ if (!ioread32 (fifo -> base_addr + XLLF_RDFO_OFFSET )) {
375
+ ret = - EAGAIN ;
376
+ goto end_unlock ;
377
+ }
358
378
} else {
359
379
/* opened in blocking mode
360
380
* wait for a packet available interrupt (or timeout)
361
381
* if nothing is currently available
362
382
*/
363
- spin_lock_irq (& fifo -> read_queue_lock );
364
- ret = wait_event_interruptible_lock_irq_timeout
365
- (fifo -> read_queue ,
366
- ioread32 (fifo -> base_addr + XLLF_RDFO_OFFSET ),
367
- fifo -> read_queue_lock ,
368
- (read_timeout >= 0 ) ? msecs_to_jiffies (read_timeout ) :
383
+ mutex_lock (& fifo -> read_lock );
384
+ ret = wait_event_interruptible_timeout (fifo -> read_queue ,
385
+ ioread32 (fifo -> base_addr + XLLF_RDFO_OFFSET ),
386
+ (read_timeout >= 0 ) ? msecs_to_jiffies (read_timeout ) :
369
387
MAX_SCHEDULE_TIMEOUT );
370
- spin_unlock_irq (& fifo -> read_queue_lock );
371
388
372
- if (ret == 0 ) {
373
- /* timeout occurred */
374
- dev_dbg (fifo -> dt_device , "read timeout" );
375
- return - EAGAIN ;
376
- } else if (ret == - ERESTARTSYS ) {
377
- /* signal received */
378
- return - ERESTARTSYS ;
379
- } else if (ret < 0 ) {
380
- dev_err (fifo -> dt_device , "wait_event_interruptible_timeout() error in read (ret=%i)\n" ,
381
- ret );
382
- return ret ;
389
+ if (ret <= 0 ) {
390
+ if (ret == 0 ) {
391
+ ret = - EAGAIN ;
392
+ } else if (ret != - ERESTARTSYS ) {
393
+ dev_err (fifo -> dt_device , "wait_event_interruptible_timeout() error in read (ret=%i)\n" ,
394
+ ret );
395
+ }
396
+
397
+ goto end_unlock ;
383
398
}
384
399
}
385
400
386
401
bytes_available = ioread32 (fifo -> base_addr + XLLF_RLR_OFFSET );
387
402
if (!bytes_available ) {
388
403
dev_err (fifo -> dt_device , "received a packet of length 0 - fifo core will be reset\n" );
389
404
reset_ip_core (fifo );
390
- return - EIO ;
405
+ ret = - EIO ;
406
+ goto end_unlock ;
391
407
}
392
408
393
409
if (bytes_available > len ) {
394
410
dev_err (fifo -> dt_device , "user read buffer too small (available bytes=%zu user buffer bytes=%zu) - fifo core will be reset\n" ,
395
411
bytes_available , len );
396
412
reset_ip_core (fifo );
397
- return - EINVAL ;
413
+ ret = - EINVAL ;
414
+ goto end_unlock ;
398
415
}
399
416
400
417
if (bytes_available % sizeof (u32 )) {
@@ -403,7 +420,8 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
403
420
*/
404
421
dev_err (fifo -> dt_device , "received a packet that isn't word-aligned - fifo core will be reset\n" );
405
422
reset_ip_core (fifo );
406
- return - EIO ;
423
+ ret = - EIO ;
424
+ goto end_unlock ;
407
425
}
408
426
409
427
words_available = bytes_available / sizeof (u32 );
@@ -423,16 +441,37 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
423
441
if (copy_to_user (buf + copied * sizeof (u32 ), tmp_buf ,
424
442
copy * sizeof (u32 ))) {
425
443
reset_ip_core (fifo );
426
- return - EFAULT ;
444
+ ret = - EFAULT ;
445
+ goto end_unlock ;
427
446
}
428
447
429
448
copied += copy ;
430
449
words_available -= copy ;
431
450
}
432
451
433
- return bytes_available ;
452
+ ret = bytes_available ;
453
+
454
+ end_unlock :
455
+ mutex_unlock (& fifo -> read_lock );
456
+
457
+ return ret ;
434
458
}
435
459
460
+ /**
461
+ * axis_fifo_write() - Write buffer to AXIS-FIFO character device.
462
+ * @f Open file.
463
+ * @buf User space buffer to write to the device.
464
+ * @len User space buffer length.
465
+ * @off Buffer offset.
466
+ *
467
+ * As defined by the device's documentation, we need to write to the device's
468
+ * data buffer then to the device's packet length register atomically. Also,
469
+ * we need to lock before checking if the device has available space to avoid
470
+ * any concurrency issue.
471
+ *
472
+ * Returns the number of bytes written to the device or negative error code
473
+ * on failure.
474
+ */
436
475
static ssize_t axis_fifo_write (struct file * f , const char __user * buf ,
437
476
size_t len , loff_t * off )
438
477
{
@@ -465,43 +504,40 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
465
504
}
466
505
467
506
if (fifo -> write_flags & O_NONBLOCK ) {
468
- /* opened in non-blocking mode
469
- * return if there is not enough room available in the fifo
507
+ /*
508
+ * Device opened in non-blocking mode. Try to lock it and then
509
+ * check if there is any room to write the given buffer.
470
510
*/
511
+ if (!mutex_trylock (& fifo -> write_lock ))
512
+ return - EAGAIN ;
513
+
471
514
if (words_to_write > ioread32 (fifo -> base_addr +
472
515
XLLF_TDFV_OFFSET )) {
473
- return - EAGAIN ;
516
+ ret = - EAGAIN ;
517
+ goto end_unlock ;
474
518
}
475
519
} else {
476
520
/* opened in blocking mode */
477
521
478
522
/* wait for an interrupt (or timeout) if there isn't
479
523
* currently enough room in the fifo
480
524
*/
481
- spin_lock_irq (& fifo -> write_queue_lock );
482
- ret = wait_event_interruptible_lock_irq_timeout
483
- (fifo -> write_queue ,
484
- ioread32 (fifo -> base_addr + XLLF_TDFV_OFFSET )
525
+ mutex_lock (& fifo -> write_lock );
526
+ ret = wait_event_interruptible_timeout (fifo -> write_queue ,
527
+ ioread32 (fifo -> base_addr + XLLF_TDFV_OFFSET )
485
528
>= words_to_write ,
486
- fifo -> write_queue_lock ,
487
- (write_timeout >= 0 ) ?
488
- msecs_to_jiffies (write_timeout ) :
529
+ (write_timeout >= 0 ) ? msecs_to_jiffies (write_timeout ) :
489
530
MAX_SCHEDULE_TIMEOUT );
490
- spin_unlock_irq (& fifo -> write_queue_lock );
491
531
492
- if (ret == 0 ) {
493
- /* timeout occurred */
494
- dev_dbg (fifo -> dt_device , "write timeout\n" );
495
- return - EAGAIN ;
496
- } else if (ret == - ERESTARTSYS ) {
497
- /* signal received */
498
- return - ERESTARTSYS ;
499
- } else if (ret < 0 ) {
500
- /* unknown error */
501
- dev_err (fifo -> dt_device ,
502
- "wait_event_interruptible_timeout() error in write (ret=%i)\n" ,
503
- ret );
504
- return ret ;
532
+ if (ret <= 0 ) {
533
+ if (ret == 0 ) {
534
+ ret = - EAGAIN ;
535
+ } else if (ret != - ERESTARTSYS ) {
536
+ dev_err (fifo -> dt_device , "wait_event_interruptible_timeout() error in write (ret=%i)\n" ,
537
+ ret );
538
+ }
539
+
540
+ goto end_unlock ;
505
541
}
506
542
}
507
543
@@ -515,7 +551,8 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
515
551
if (copy_from_user (tmp_buf , buf + copied * sizeof (u32 ),
516
552
copy * sizeof (u32 ))) {
517
553
reset_ip_core (fifo );
518
- return - EFAULT ;
554
+ ret = - EFAULT ;
555
+ goto end_unlock ;
519
556
}
520
557
521
558
for (i = 0 ; i < copy ; i ++ )
@@ -526,10 +563,15 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
526
563
words_to_write -= copy ;
527
564
}
528
565
566
+ ret = copied * sizeof (u32 );
567
+
529
568
/* write packet size to fifo */
530
- iowrite32 (copied * sizeof (u32 ), fifo -> base_addr + XLLF_TLR_OFFSET );
569
+ iowrite32 (ret , fifo -> base_addr + XLLF_TLR_OFFSET );
570
+
571
+ end_unlock :
572
+ mutex_unlock (& fifo -> write_lock );
531
573
532
- return ( ssize_t ) copied * sizeof ( u32 ) ;
574
+ return ret ;
533
575
}
534
576
535
577
static irqreturn_t axis_fifo_irq (int irq , void * dw )
@@ -789,8 +831,8 @@ static int axis_fifo_probe(struct platform_device *pdev)
789
831
init_waitqueue_head (& fifo -> read_queue );
790
832
init_waitqueue_head (& fifo -> write_queue );
791
833
792
- spin_lock_init (& fifo -> read_queue_lock );
793
- spin_lock_init (& fifo -> write_queue_lock );
834
+ mutex_init (& fifo -> read_lock );
835
+ mutex_init (& fifo -> write_lock );
794
836
795
837
/* ----------------------------
796
838
* init device memory space
0 commit comments