From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Stefan Achatz <stefan_achatz@web.de>
Cc: Jiri Kosina <jkosina@suse.cz>,
Jussi Kivilinna <jussi.kivilinna@mbnet.fi>,
wylda@volny.cz, Pavel Machek <pavel@suse.cz>,
Alessandro Guido <ag@alessandroguido.name>,
Tomas Hanak <tomas.hanak@gmail.com>,
Jason Noble <nobleja@polezero.com>,
simon.windows@gmail.com,
Sean Hildebrand <silverwraithii@gmail.com>,
Sid Boyce <sboyce@blueyonder.co.uk>,
Henning Glawe <glaweh@debian.org>,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 4/4] Added locks for sysfs attributes and internal data.
Date: Mon, 8 Mar 2010 23:41:55 -0800 [thread overview]
Message-ID: <20100309074155.GA17288@core.coreip.homeip.net> (raw)
In-Reply-To: <201003081704.30119.stefan_achatz@web.de>
Hi Stefan,
On Mon, Mar 08, 2010 at 05:04:29PM +0100, Stefan Achatz wrote:
> From 47678162da8e374d6f132db21d89b718ee5cfbd1 Mon Sep 17 00:00:00 2001
> From: Stefan Achatz <erazor_de@users.sourceforge.net>
> Date: Mon, 8 Mar 2010 16:54:19 +0100
> Subject: [PATCH 4/4] Added locks for sysfs attributes and internal data.
>
> Added mutex lock to prevent different processes from accessing
> sysfs attributes at the same time.
> Added spin lock for internal data.
> ---
> drivers/hid/hid-roccat-kone.c | 246 ++++++++++++++++++++++++++++------------
> drivers/hid/hid-roccat-kone.h | 9 +-
> 2 files changed, 179 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
> index 941f5b3..eded7d4 100644
> --- a/drivers/hid/hid-roccat-kone.c
> +++ b/drivers/hid/hid-roccat-kone.c
> @@ -223,11 +223,6 @@ static int kone_get_profile(struct usb_device *usb_dev,
> if (number < 1 || number > 5)
> return -EINVAL;
>
> - /*
> - * The manufacturer uses a control message of type class with interface
> - * as recipient and provides the profile number as index parameter.
> - * This is prevented in userspace by function check_ctrlrecip.
> - */
> len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
> USB_REQ_CLEAR_FEATURE, USB_TYPE_CLASS
> | USB_RECIP_INTERFACE | USB_DIR_IN,
> @@ -398,16 +393,18 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
> static ssize_t kone_sysfs_set_settings(struct device *dev,
> struct device_attribute *attr, char const *buf, size_t size)
> {
> - struct hid_device *hdev = dev_get_drvdata(dev);
> - struct kone_device *kone = hid_get_drvdata(hdev);
> - struct usb_interface *intf = to_usb_interface(dev);
> - struct usb_device *usb_dev = interface_to_usbdev(intf);
> + struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> int err;
> + unsigned long flags;
>
> if (size != sizeof(struct kone_settings))
> return -EINVAL;
>
> + mutex_lock(&kone->kone_lock);
> err = kone_set_settings(usb_dev, (struct kone_settings const *)buf);
Hmm, this kind of casting tells me that this is binary, not text data
and thus binary sysfs attribute shoudl be used.
> + mutex_unlock(&kone->kone_lock);
> +
> if (err)
> return err;
>
> @@ -415,9 +412,10 @@ static ssize_t kone_sysfs_set_settings(struct device *dev,
> * If we get here, treat buf as okay (apart from checksum) and use value
> * of startup_profile as its at hand
> */
> + spin_lock_irqsave(&kone->actual_lock, flags);
> kone->act_profile = ((struct kone_settings *)buf)->startup_profile;
> - kone->act_profile_valid = 1;
> - kone->act_dpi_valid = 0;
> + kone->act_dpi = -1;
> + spin_unlock_irqrestore(&kone->actual_lock, flags);
>
You don't really need a spinlock to set one integer.
> return sizeof(struct kone_settings);
> }
> @@ -425,10 +423,14 @@ static ssize_t kone_sysfs_set_settings(struct device *dev,
> static ssize_t kone_sysfs_show_settings(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> - struct usb_interface *intf = to_usb_interface(dev);
> - struct usb_device *usb_dev = interface_to_usbdev(intf);
> + struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> int err;
> +
> + mutex_lock(&kone->kone_lock);
> err = kone_get_settings(usb_dev, (struct kone_settings *)buf);
> + mutex_unlock(&kone->kone_lock);
> +
> if (err)
> return err;
>
> @@ -437,10 +439,14 @@ static ssize_t kone_sysfs_show_settings(struct device *dev,
>
> static ssize_t kone_sysfs_get_profile(struct device *dev, char *buf, int number)
> {
> - struct usb_interface *intf = to_usb_interface(dev);
> - struct usb_device *usb_dev = interface_to_usbdev(intf);
> + struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> int err;
> +
> + mutex_lock(&kone->kone_lock);
> err = kone_get_profile(usb_dev, (struct kone_profile *)buf, number);
> + mutex_unlock(&kone->kone_lock);
> +
> if (err)
> return err;
> return sizeof(struct kone_profile);
> @@ -449,15 +455,17 @@ static ssize_t kone_sysfs_get_profile(struct device *dev, char *buf, int number)
> static ssize_t kone_sysfs_set_profile(struct device *dev, char const *buf,
> size_t size, int number)
> {
> - struct usb_interface *intf = to_usb_interface(dev);
> - struct usb_device *usb_dev = interface_to_usbdev(intf);
> -
> + struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> int err;
>
> if (size != sizeof(struct kone_profile))
> return -EINVAL;
>
> + mutex_lock(&kone->kone_lock);
> err = kone_set_profile(usb_dev, buf, number);
> + mutex_unlock(&kone->kone_lock);
> +
> if (err)
> return err;
>
> @@ -525,32 +533,68 @@ static ssize_t kone_sysfs_set_profile_5(struct device *dev,
> }
>
> /*
> - * Helper to fill kone_device structure with actual values
> - * On success returns 0
> - * On failure returns errno
> + * Fills act_profile in kone_device.
> + * Also writes result in @result.
> + * Once act_profile is valid, its not getting invalid any more.
> + * Returns on success 0, on failure errno
> */
> -static int kone_device_set_actual_values(struct kone_device *kone,
> - struct device *dev, int both)
> +static int kone_device_set_actual_profile(struct kone_device *kone,
> + struct device *dev, int *result)
> {
> - struct usb_interface *intf = to_usb_interface(dev);
> - struct usb_device *usb_dev = interface_to_usbdev(intf);
> - int err;
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> + int err, temp;
> + unsigned long flags;
>
> - /* first make sure profile is valid */
> - if (!kone->act_profile_valid) {
> - err = kone_get_startup_profile(usb_dev, &kone->act_profile);
> + spin_lock_irqsave(&kone->actual_lock, flags);
> + if (kone->act_profile == -1) {
> + spin_unlock_irqrestore(&kone->actual_lock, flags);
> + err = kone_get_startup_profile(usb_dev, &temp);
> if (err)
> return err;
> - kone->act_profile_valid = 1;
> + spin_lock_irq(&kone->actual_lock);
> + kone->act_profile = temp;
> + spin_unlock_irqrestore(&kone->actual_lock, flags);
You shoudl not be mixing _irq/_irqrestore. Also it is probably not
needed at all. If it is needed then the common style to acquire and
release locks only once in a function - this makes checking whether
lock/unlock is balanced easier.
> + if (result)
> + *result = temp;
> + } else {
> + if (result)
> + *result = kone->act_profile;
> + spin_unlock_irqrestore(&kone->actual_lock, flags);
> }
> + return 0;
> +}
> +
> +/*
> + * Fills act_dpi in kone_device.
> + * Also writes result in @result.
> + * On success returns 0
> + * On failure returns errno
> + */
> +static int kone_device_set_actual_dpi(struct kone_device *kone,
> + struct device *dev, int *result)
> +{
> + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
> + int err, temp;
> + unsigned long flags;
> +
> + kone_device_set_actual_profile(kone, dev, NULL);
>
> - /* then get startup dpi value */
> - if (!kone->act_dpi_valid && both) {
> + spin_lock_irqsave(&kone->actual_lock, flags);
> + if (kone->act_dpi == -1) {
> + spin_unlock_irqrestore(&kone->actual_lock, flags);
So what are we protecting exactly? What if act_dpi will become -1 here
(after you released the spinlock?
> err = kone_get_profile_startup_dpi(usb_dev, kone->act_profile,
> - &kone->act_dpi);
> + &temp);
Stopped looking - locking obviously is bogus and needs to be redone. You
need to decide what exactly needs protection and what critical sections
are.
--
Dmitry
next prev parent reply other threads:[~2010-03-09 7:42 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-20 8:11 [PATCH] HID: add driver for Roccat Kone gaming mouse Stefan Achatz
2010-02-21 8:13 ` Dmitry Torokhov
[not found] ` <201002211750.45618.erazor_de@users.sourceforge.net>
2010-02-22 6:29 ` [PATCH 2/2] HID: documentation additions and elimination of legacy filenames for Roccat Kone driver Dmitry Torokhov
2010-02-22 10:01 ` Jiri Kosina
2010-02-22 18:42 ` [PATCH 3/3] Adding documentation to sysfs attributes of roccat kone driver Stefan Achatz
2010-02-22 23:10 ` Dmitry Torokhov
2010-02-23 8:03 ` Stefan Achatz
2010-02-26 7:44 ` Dmitry Torokhov
2010-03-08 16:04 ` [PATCH 4/4] Added locks for sysfs attributes and internal data Stefan Achatz
2010-03-09 0:05 ` Jiri Kosina
2010-03-09 7:41 ` Dmitry Torokhov [this message]
2010-03-13 11:19 ` Stefan Achatz
2010-03-14 8:42 ` Dmitry Torokhov
2010-03-15 13:51 ` Jiri Kosina
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100309074155.GA17288@core.coreip.homeip.net \
--to=dmitry.torokhov@gmail.com \
--cc=ag@alessandroguido.name \
--cc=glaweh@debian.org \
--cc=jkosina@suse.cz \
--cc=jussi.kivilinna@mbnet.fi \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nobleja@polezero.com \
--cc=pavel@suse.cz \
--cc=sboyce@blueyonder.co.uk \
--cc=silverwraithii@gmail.com \
--cc=simon.windows@gmail.com \
--cc=stefan_achatz@web.de \
--cc=tomas.hanak@gmail.com \
--cc=wylda@volny.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).