@@ -55,6 +55,50 @@ static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_values), 8));
5555 * interface to gpiolib GPIOs via ioctl()s.
5656 */
5757
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+
58102/*
59103 * GPIO line handle management
60104 */
@@ -191,8 +235,8 @@ static long linehandle_set_config(struct linehandle_state *lh,
191235 return 0 ;
192236}
193237
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 )
196240{
197241 struct linehandle_state * lh = file -> private_data ;
198242 void __user * ip = (void __user * )arg ;
@@ -250,6 +294,15 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd,
250294 }
251295}
252296
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+
253306#ifdef CONFIG_COMPAT
254307static long linehandle_ioctl_compat (struct file * file , unsigned int cmd ,
255308 unsigned long arg )
@@ -1381,8 +1434,8 @@ static long linereq_set_config(struct linereq *lr, void __user *ip)
13811434 return ret ;
13821435}
13831436
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 )
13861439{
13871440 struct linereq * lr = file -> private_data ;
13881441 void __user * ip = (void __user * )arg ;
@@ -1402,6 +1455,15 @@ static long linereq_ioctl(struct file *file, unsigned int cmd,
14021455 }
14031456}
14041457
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+
14051467#ifdef CONFIG_COMPAT
14061468static long linereq_ioctl_compat (struct file * file , unsigned int cmd ,
14071469 unsigned long arg )
@@ -1410,8 +1472,8 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd,
14101472}
14111473#endif
14121474
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 )
14151477{
14161478 struct linereq * lr = file -> private_data ;
14171479 __poll_t events = 0 ;
@@ -1428,10 +1490,16 @@ static __poll_t linereq_poll(struct file *file,
14281490 return events ;
14291491}
14301492
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 )
14351503{
14361504 struct linereq * lr = file -> private_data ;
14371505 struct gpio_v2_line_event le ;
@@ -1485,6 +1553,15 @@ static ssize_t linereq_read(struct file *file,
14851553 return bytes_read ;
14861554}
14871555
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+
14881565static void linereq_free (struct linereq * lr )
14891566{
14901567 unsigned int i ;
@@ -1722,8 +1799,8 @@ struct lineevent_state {
17221799 (GPIOEVENT_REQUEST_RISING_EDGE | \
17231800 GPIOEVENT_REQUEST_FALLING_EDGE)
17241801
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 )
17271804{
17281805 struct lineevent_state * le = file -> private_data ;
17291806 __poll_t events = 0 ;
@@ -1739,15 +1816,21 @@ static __poll_t lineevent_poll(struct file *file,
17391816 return events ;
17401817}
17411818
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+
17421827struct compat_gpioeevent_data {
17431828 compat_u64 timestamp ;
17441829 u32 id ;
17451830};
17461831
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 )
17511834{
17521835 struct lineevent_state * le = file -> private_data ;
17531836 struct gpioevent_data ge ;
@@ -1815,6 +1898,15 @@ static ssize_t lineevent_read(struct file *file,
18151898 return bytes_read ;
18161899}
18171900
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+
18181910static void lineevent_free (struct lineevent_state * le )
18191911{
18201912 if (le -> irq )
@@ -1832,8 +1924,8 @@ static int lineevent_release(struct inode *inode, struct file *file)
18321924 return 0 ;
18331925}
18341926
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 )
18371929{
18381930 struct lineevent_state * le = file -> private_data ;
18391931 void __user * ip = (void __user * )arg ;
@@ -1864,6 +1956,15 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd,
18641956 return - EINVAL ;
18651957}
18661958
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+
18671968#ifdef CONFIG_COMPAT
18681969static long lineevent_ioctl_compat (struct file * file , unsigned int cmd ,
18691970 unsigned long arg )
@@ -2422,8 +2523,8 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
24222523 return NOTIFY_OK ;
24232524}
24242525
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 )
24272528{
24282529 struct gpio_chardev_data * cdev = file -> private_data ;
24292530 __poll_t events = 0 ;
@@ -2440,8 +2541,17 @@ static __poll_t lineinfo_watch_poll(struct file *file,
24402541 return events ;
24412542}
24422543
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 )
24452555{
24462556 struct gpio_chardev_data * cdev = file -> private_data ;
24472557 struct gpio_v2_line_info_changed event ;
@@ -2519,6 +2629,15 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
25192629 return bytes_read ;
25202630}
25212631
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+
25222641/**
25232642 * gpio_chrdev_open() - open the chardev for ioctl operations
25242643 * @inode: inode for this chardev
@@ -2532,13 +2651,17 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
25322651 struct gpio_chardev_data * cdev ;
25332652 int ret = - ENOMEM ;
25342653
2654+ down_read (& gdev -> sem );
2655+
25352656 /* 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+ }
25382661
25392662 cdev = kzalloc (sizeof (* cdev ), GFP_KERNEL );
25402663 if (!cdev )
2541- return - ENOMEM ;
2664+ goto out_unlock ;
25422665
25432666 cdev -> watched_lines = bitmap_zalloc (gdev -> chip -> ngpio , GFP_KERNEL );
25442667 if (!cdev -> watched_lines )
@@ -2561,6 +2684,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
25612684 if (ret )
25622685 goto out_unregister_notifier ;
25632686
2687+ up_read (& gdev -> sem );
2688+
25642689 return ret ;
25652690
25662691out_unregister_notifier :
@@ -2570,6 +2695,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
25702695 bitmap_free (cdev -> watched_lines );
25712696out_free_cdev :
25722697 kfree (cdev );
2698+ out_unlock :
2699+ up_read (& gdev -> sem );
25732700 return ret ;
25742701}
25752702
0 commit comments