@@ -55,6 +55,50 @@ static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_values), 8));
55
55
* interface to gpiolib GPIOs via ioctl()s.
56
56
*/
57
57
58
+ typedef __poll_t (* poll_fn )(struct file * , struct poll_table_struct * );
59
+ typedef long (* ioctl_fn )(struct file * , unsigned int , unsigned long );
60
+ typedef ssize_t (* read_fn )(struct file * , char __user * ,
61
+ size_t count , loff_t * );
62
+
63
+ static __poll_t call_poll_locked (struct file * file ,
64
+ struct poll_table_struct * wait ,
65
+ struct gpio_device * gdev , poll_fn func )
66
+ {
67
+ __poll_t ret ;
68
+
69
+ down_read (& gdev -> sem );
70
+ ret = func (file , wait );
71
+ up_read (& gdev -> sem );
72
+
73
+ return ret ;
74
+ }
75
+
76
+ static long call_ioctl_locked (struct file * file , unsigned int cmd ,
77
+ unsigned long arg , struct gpio_device * gdev ,
78
+ ioctl_fn func )
79
+ {
80
+ long ret ;
81
+
82
+ down_read (& gdev -> sem );
83
+ ret = func (file , cmd , arg );
84
+ up_read (& gdev -> sem );
85
+
86
+ return ret ;
87
+ }
88
+
89
+ static ssize_t call_read_locked (struct file * file , char __user * buf ,
90
+ size_t count , loff_t * f_ps ,
91
+ struct gpio_device * gdev , read_fn func )
92
+ {
93
+ ssize_t ret ;
94
+
95
+ down_read (& gdev -> sem );
96
+ ret = func (file , buf , count , f_ps );
97
+ up_read (& gdev -> sem );
98
+
99
+ return ret ;
100
+ }
101
+
58
102
/*
59
103
* GPIO line handle management
60
104
*/
@@ -191,8 +235,8 @@ static long linehandle_set_config(struct linehandle_state *lh,
191
235
return 0 ;
192
236
}
193
237
194
- static long linehandle_ioctl (struct file * file , unsigned int cmd ,
195
- unsigned long arg )
238
+ static long linehandle_ioctl_unlocked (struct file * file , unsigned int cmd ,
239
+ unsigned long arg )
196
240
{
197
241
struct linehandle_state * lh = file -> private_data ;
198
242
void __user * ip = (void __user * )arg ;
@@ -250,6 +294,15 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd,
250
294
}
251
295
}
252
296
297
+ static long linehandle_ioctl (struct file * file , unsigned int cmd ,
298
+ unsigned long arg )
299
+ {
300
+ struct linehandle_state * lh = file -> private_data ;
301
+
302
+ return call_ioctl_locked (file , cmd , arg , lh -> gdev ,
303
+ linehandle_ioctl_unlocked );
304
+ }
305
+
253
306
#ifdef CONFIG_COMPAT
254
307
static long linehandle_ioctl_compat (struct file * file , unsigned int cmd ,
255
308
unsigned long arg )
@@ -1381,8 +1434,8 @@ static long linereq_set_config(struct linereq *lr, void __user *ip)
1381
1434
return ret ;
1382
1435
}
1383
1436
1384
- static long linereq_ioctl (struct file * file , unsigned int cmd ,
1385
- unsigned long arg )
1437
+ static long linereq_ioctl_unlocked (struct file * file , unsigned int cmd ,
1438
+ unsigned long arg )
1386
1439
{
1387
1440
struct linereq * lr = file -> private_data ;
1388
1441
void __user * ip = (void __user * )arg ;
@@ -1402,6 +1455,15 @@ static long linereq_ioctl(struct file *file, unsigned int cmd,
1402
1455
}
1403
1456
}
1404
1457
1458
+ static long linereq_ioctl (struct file * file , unsigned int cmd ,
1459
+ unsigned long arg )
1460
+ {
1461
+ struct linereq * lr = file -> private_data ;
1462
+
1463
+ return call_ioctl_locked (file , cmd , arg , lr -> gdev ,
1464
+ linereq_ioctl_unlocked );
1465
+ }
1466
+
1405
1467
#ifdef CONFIG_COMPAT
1406
1468
static long linereq_ioctl_compat (struct file * file , unsigned int cmd ,
1407
1469
unsigned long arg )
@@ -1410,8 +1472,8 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd,
1410
1472
}
1411
1473
#endif
1412
1474
1413
- static __poll_t linereq_poll (struct file * file ,
1414
- struct poll_table_struct * wait )
1475
+ static __poll_t linereq_poll_unlocked (struct file * file ,
1476
+ struct poll_table_struct * wait )
1415
1477
{
1416
1478
struct linereq * lr = file -> private_data ;
1417
1479
__poll_t events = 0 ;
@@ -1428,10 +1490,16 @@ static __poll_t linereq_poll(struct file *file,
1428
1490
return events ;
1429
1491
}
1430
1492
1431
- static ssize_t linereq_read (struct file * file ,
1432
- char __user * buf ,
1433
- size_t count ,
1434
- loff_t * f_ps )
1493
+ static __poll_t linereq_poll (struct file * file ,
1494
+ struct poll_table_struct * wait )
1495
+ {
1496
+ struct linereq * lr = file -> private_data ;
1497
+
1498
+ return call_poll_locked (file , wait , lr -> gdev , linereq_poll_unlocked );
1499
+ }
1500
+
1501
+ static ssize_t linereq_read_unlocked (struct file * file , char __user * buf ,
1502
+ size_t count , loff_t * f_ps )
1435
1503
{
1436
1504
struct linereq * lr = file -> private_data ;
1437
1505
struct gpio_v2_line_event le ;
@@ -1485,6 +1553,15 @@ static ssize_t linereq_read(struct file *file,
1485
1553
return bytes_read ;
1486
1554
}
1487
1555
1556
+ static ssize_t linereq_read (struct file * file , char __user * buf ,
1557
+ size_t count , loff_t * f_ps )
1558
+ {
1559
+ struct linereq * lr = file -> private_data ;
1560
+
1561
+ return call_read_locked (file , buf , count , f_ps , lr -> gdev ,
1562
+ linereq_read_unlocked );
1563
+ }
1564
+
1488
1565
static void linereq_free (struct linereq * lr )
1489
1566
{
1490
1567
unsigned int i ;
@@ -1722,8 +1799,8 @@ struct lineevent_state {
1722
1799
(GPIOEVENT_REQUEST_RISING_EDGE | \
1723
1800
GPIOEVENT_REQUEST_FALLING_EDGE)
1724
1801
1725
- static __poll_t lineevent_poll (struct file * file ,
1726
- struct poll_table_struct * wait )
1802
+ static __poll_t lineevent_poll_unlocked (struct file * file ,
1803
+ struct poll_table_struct * wait )
1727
1804
{
1728
1805
struct lineevent_state * le = file -> private_data ;
1729
1806
__poll_t events = 0 ;
@@ -1739,15 +1816,21 @@ static __poll_t lineevent_poll(struct file *file,
1739
1816
return events ;
1740
1817
}
1741
1818
1819
+ static __poll_t lineevent_poll (struct file * file ,
1820
+ struct poll_table_struct * wait )
1821
+ {
1822
+ struct lineevent_state * le = file -> private_data ;
1823
+
1824
+ return call_poll_locked (file , wait , le -> gdev , lineevent_poll_unlocked );
1825
+ }
1826
+
1742
1827
struct compat_gpioeevent_data {
1743
1828
compat_u64 timestamp ;
1744
1829
u32 id ;
1745
1830
};
1746
1831
1747
- static ssize_t lineevent_read (struct file * file ,
1748
- char __user * buf ,
1749
- size_t count ,
1750
- loff_t * f_ps )
1832
+ static ssize_t lineevent_read_unlocked (struct file * file , char __user * buf ,
1833
+ size_t count , loff_t * f_ps )
1751
1834
{
1752
1835
struct lineevent_state * le = file -> private_data ;
1753
1836
struct gpioevent_data ge ;
@@ -1815,6 +1898,15 @@ static ssize_t lineevent_read(struct file *file,
1815
1898
return bytes_read ;
1816
1899
}
1817
1900
1901
+ static ssize_t lineevent_read (struct file * file , char __user * buf ,
1902
+ size_t count , loff_t * f_ps )
1903
+ {
1904
+ struct lineevent_state * le = file -> private_data ;
1905
+
1906
+ return call_read_locked (file , buf , count , f_ps , le -> gdev ,
1907
+ lineevent_read_unlocked );
1908
+ }
1909
+
1818
1910
static void lineevent_free (struct lineevent_state * le )
1819
1911
{
1820
1912
if (le -> irq )
@@ -1832,8 +1924,8 @@ static int lineevent_release(struct inode *inode, struct file *file)
1832
1924
return 0 ;
1833
1925
}
1834
1926
1835
- static long lineevent_ioctl (struct file * file , unsigned int cmd ,
1836
- unsigned long arg )
1927
+ static long lineevent_ioctl_unlocked (struct file * file , unsigned int cmd ,
1928
+ unsigned long arg )
1837
1929
{
1838
1930
struct lineevent_state * le = file -> private_data ;
1839
1931
void __user * ip = (void __user * )arg ;
@@ -1864,6 +1956,15 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd,
1864
1956
return - EINVAL ;
1865
1957
}
1866
1958
1959
+ static long lineevent_ioctl (struct file * file , unsigned int cmd ,
1960
+ unsigned long arg )
1961
+ {
1962
+ struct lineevent_state * le = file -> private_data ;
1963
+
1964
+ return call_ioctl_locked (file , cmd , arg , le -> gdev ,
1965
+ lineevent_ioctl_unlocked );
1966
+ }
1967
+
1867
1968
#ifdef CONFIG_COMPAT
1868
1969
static long lineevent_ioctl_compat (struct file * file , unsigned int cmd ,
1869
1970
unsigned long arg )
@@ -2422,8 +2523,8 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
2422
2523
return NOTIFY_OK ;
2423
2524
}
2424
2525
2425
- static __poll_t lineinfo_watch_poll (struct file * file ,
2426
- struct poll_table_struct * pollt )
2526
+ static __poll_t lineinfo_watch_poll_unlocked (struct file * file ,
2527
+ struct poll_table_struct * pollt )
2427
2528
{
2428
2529
struct gpio_chardev_data * cdev = file -> private_data ;
2429
2530
__poll_t events = 0 ;
@@ -2440,8 +2541,17 @@ static __poll_t lineinfo_watch_poll(struct file *file,
2440
2541
return events ;
2441
2542
}
2442
2543
2443
- static ssize_t lineinfo_watch_read (struct file * file , char __user * buf ,
2444
- size_t count , loff_t * off )
2544
+ static __poll_t lineinfo_watch_poll (struct file * file ,
2545
+ struct poll_table_struct * pollt )
2546
+ {
2547
+ struct gpio_chardev_data * cdev = file -> private_data ;
2548
+
2549
+ return call_poll_locked (file , pollt , cdev -> gdev ,
2550
+ lineinfo_watch_poll_unlocked );
2551
+ }
2552
+
2553
+ static ssize_t lineinfo_watch_read_unlocked (struct file * file , char __user * buf ,
2554
+ size_t count , loff_t * off )
2445
2555
{
2446
2556
struct gpio_chardev_data * cdev = file -> private_data ;
2447
2557
struct gpio_v2_line_info_changed event ;
@@ -2519,6 +2629,15 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
2519
2629
return bytes_read ;
2520
2630
}
2521
2631
2632
+ static ssize_t lineinfo_watch_read (struct file * file , char __user * buf ,
2633
+ size_t count , loff_t * off )
2634
+ {
2635
+ struct gpio_chardev_data * cdev = file -> private_data ;
2636
+
2637
+ return call_read_locked (file , buf , count , off , cdev -> gdev ,
2638
+ lineinfo_watch_read_unlocked );
2639
+ }
2640
+
2522
2641
/**
2523
2642
* gpio_chrdev_open() - open the chardev for ioctl operations
2524
2643
* @inode: inode for this chardev
@@ -2532,13 +2651,17 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
2532
2651
struct gpio_chardev_data * cdev ;
2533
2652
int ret = - ENOMEM ;
2534
2653
2654
+ down_read (& gdev -> sem );
2655
+
2535
2656
/* Fail on open if the backing gpiochip is gone */
2536
- if (!gdev -> chip )
2537
- return - ENODEV ;
2657
+ if (!gdev -> chip ) {
2658
+ ret = - ENODEV ;
2659
+ goto out_unlock ;
2660
+ }
2538
2661
2539
2662
cdev = kzalloc (sizeof (* cdev ), GFP_KERNEL );
2540
2663
if (!cdev )
2541
- return - ENOMEM ;
2664
+ goto out_unlock ;
2542
2665
2543
2666
cdev -> watched_lines = bitmap_zalloc (gdev -> chip -> ngpio , GFP_KERNEL );
2544
2667
if (!cdev -> watched_lines )
@@ -2561,6 +2684,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
2561
2684
if (ret )
2562
2685
goto out_unregister_notifier ;
2563
2686
2687
+ up_read (& gdev -> sem );
2688
+
2564
2689
return ret ;
2565
2690
2566
2691
out_unregister_notifier :
@@ -2570,6 +2695,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
2570
2695
bitmap_free (cdev -> watched_lines );
2571
2696
out_free_cdev :
2572
2697
kfree (cdev );
2698
+ out_unlock :
2699
+ up_read (& gdev -> sem );
2573
2700
return ret ;
2574
2701
}
2575
2702
0 commit comments