Skip to content

Commit f3efefb

Browse files
committed
Input: yealink - simplify locking in sysfs attribute handling
The locking rules in the driver came from era when sysfs attributes could live past the point of time when device would be unbound from the driver, and so used module-global semaphore (potentially shared between multiple yealink devices). Thankfully these times are long gone and attributes will not be accessible once they are removed. Simplify the logic by moving to per-device mutex, stop checking if there is driver data instance attached to the interface, and use guard notation to acquire the mutex. Reviewed-by: Greg Kroah-Hartman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 295b89a commit f3efefb

File tree

1 file changed

+20
-52
lines changed

1 file changed

+20
-52
lines changed

drivers/input/misc/yealink.c

+20-52
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include <linux/kernel.h>
3737
#include <linux/slab.h>
3838
#include <linux/module.h>
39-
#include <linux/rwsem.h>
39+
#include <linux/mutex.h>
4040
#include <linux/usb/input.h>
4141
#include <linux/map_to_7segment.h>
4242

@@ -103,6 +103,8 @@ struct yealink_dev {
103103
u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
104104
int key_code; /* last reported key */
105105

106+
struct mutex sysfs_mutex;
107+
106108
unsigned int shutdown:1;
107109

108110
int stat_ix;
@@ -548,8 +550,6 @@ static void input_close(struct input_dev *dev)
548550
* sysfs interface
549551
******************************************************************************/
550552

551-
static DECLARE_RWSEM(sysfs_rwsema);
552-
553553
/* Interface to the 7-segments translation table aka. char set.
554554
*/
555555
static ssize_t show_map(struct device *dev, struct device_attribute *attr,
@@ -580,15 +580,10 @@ static ssize_t store_map(struct device *dev, struct device_attribute *attr,
580580
*/
581581
static ssize_t show_line(struct device *dev, char *buf, int a, int b)
582582
{
583-
struct yealink_dev *yld;
583+
struct yealink_dev *yld = dev_get_drvdata(dev);
584584
int i;
585585

586-
down_read(&sysfs_rwsema);
587-
yld = dev_get_drvdata(dev);
588-
if (yld == NULL) {
589-
up_read(&sysfs_rwsema);
590-
return -ENODEV;
591-
}
586+
guard(mutex)(&yld->sysfs_mutex);
592587

593588
for (i = a; i < b; i++)
594589
*buf++ = lcdMap[i].type;
@@ -598,7 +593,6 @@ static ssize_t show_line(struct device *dev, char *buf, int a, int b)
598593
*buf++ = '\n';
599594
*buf = 0;
600595

601-
up_read(&sysfs_rwsema);
602596
return 3 + ((b - a) << 1);
603597
}
604598

@@ -630,22 +624,16 @@ static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
630624
static ssize_t store_line(struct device *dev, const char *buf, size_t count,
631625
int el, size_t len)
632626
{
633-
struct yealink_dev *yld;
627+
struct yealink_dev *yld = dev_get_drvdata(dev);
634628
int i;
635629

636-
down_write(&sysfs_rwsema);
637-
yld = dev_get_drvdata(dev);
638-
if (yld == NULL) {
639-
up_write(&sysfs_rwsema);
640-
return -ENODEV;
641-
}
630+
guard(mutex)(&yld->sysfs_mutex);
642631

643632
if (len > count)
644633
len = count;
645634
for (i = 0; i < len; i++)
646635
setChar(yld, el++, buf[i]);
647636

648-
up_write(&sysfs_rwsema);
649637
return count;
650638
}
651639

@@ -675,15 +663,10 @@ static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
675663
static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
676664
char *buf)
677665
{
678-
struct yealink_dev *yld;
666+
struct yealink_dev *yld = dev_get_drvdata(dev);
679667
int i, ret = 1;
680668

681-
down_read(&sysfs_rwsema);
682-
yld = dev_get_drvdata(dev);
683-
if (yld == NULL) {
684-
up_read(&sysfs_rwsema);
685-
return -ENODEV;
686-
}
669+
guard(mutex)(&yld->sysfs_mutex);
687670

688671
for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
689672
if (lcdMap[i].type != '.')
@@ -692,23 +675,18 @@ static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
692675
yld->lcdMap[i] == ' ' ? " " : "on",
693676
lcdMap[i].u.p.name);
694677
}
695-
up_read(&sysfs_rwsema);
678+
696679
return ret;
697680
}
698681

699682
/* Change the visibility of a particular element. */
700683
static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
701684
int chr)
702685
{
703-
struct yealink_dev *yld;
686+
struct yealink_dev *yld = dev_get_drvdata(dev);
704687
int i;
705688

706-
down_write(&sysfs_rwsema);
707-
yld = dev_get_drvdata(dev);
708-
if (yld == NULL) {
709-
up_write(&sysfs_rwsema);
710-
return -ENODEV;
711-
}
689+
guard(mutex)(&yld->sysfs_mutex);
712690

713691
for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
714692
if (lcdMap[i].type != '.')
@@ -719,7 +697,6 @@ static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
719697
}
720698
}
721699

722-
up_write(&sysfs_rwsema);
723700
return count;
724701
}
725702

@@ -739,22 +716,16 @@ static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
739716
*/
740717

741718
/* Stores raw ringtone data in the phone */
742-
static ssize_t store_ringtone(struct device *dev,
743-
struct device_attribute *attr,
744-
const char *buf, size_t count)
719+
static ssize_t store_ringtone(struct device *dev, struct device_attribute *attr,
720+
const char *buf, size_t count)
745721
{
746-
struct yealink_dev *yld;
722+
struct yealink_dev *yld = dev_get_drvdata(dev);
747723

748-
down_write(&sysfs_rwsema);
749-
yld = dev_get_drvdata(dev);
750-
if (yld == NULL) {
751-
up_write(&sysfs_rwsema);
752-
return -ENODEV;
753-
}
724+
guard(mutex)(&yld->sysfs_mutex);
754725

755726
/* TODO locking with async usb control interface??? */
756727
yealink_set_ringtone(yld, (char *)buf, count);
757-
up_write(&sysfs_rwsema);
728+
758729
return count;
759730
}
760731

@@ -835,14 +806,10 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
835806

836807
static void usb_disconnect(struct usb_interface *intf)
837808
{
838-
struct yealink_dev *yld;
839-
840-
down_write(&sysfs_rwsema);
841-
yld = usb_get_intfdata(intf);
842-
usb_set_intfdata(intf, NULL);
843-
up_write(&sysfs_rwsema);
809+
struct yealink_dev *yld = usb_get_intfdata(intf);
844810

845811
usb_cleanup(yld, 0);
812+
usb_set_intfdata(intf, NULL);
846813
}
847814

848815
static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -870,6 +837,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
870837

871838
yld->udev = udev;
872839
yld->intf = intf;
840+
mutex_init(&yld->sysfs_mutex);
873841

874842
yld->idev = input_dev = input_allocate_device();
875843
if (!input_dev)

0 commit comments

Comments
 (0)