From: "Alfred E. Heggestad" <aeh@db.org>
To: Oliver Neukum <oliver@neukum.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Jiri Kosina <jkosina@suse.cz>,
linux-usb@vger.kernel.org, linux-input@vger.kernel.org,
Henk.Vergonet@gmail.com
Subject: Re: [patch]reliably killing urbs in yealink driver
Date: Sat, 28 Jun 2008 17:11:17 +0200 [thread overview]
Message-ID: <48665495.30204@db.org> (raw)
In-Reply-To: <200806261344.32326.oliver@neukum.org>
Oliver Neukum wrote:
> Hi,
>
> yealink uses two URBs that submit each other. This arrangement cannot
> be reliably killed with usb_kill_urb() alone, as there's a window during which
> the wrong URB may be killed. The fix is to introduce a flag.
>
Hi Oliver,
just a small comments about this patch;
- the declaration of 'spin' and 'shutdown' is missing,
and hence the module does not build.
something like this should be added to struct yealink_dev:
spinlock_t spin;
char shutdown:1;
/alfred
> Regards
> Oliver
>
> Signed-off-by: Oliver Neukum <oneukum@suse.de>
>
> ---
>
> --- linux-2.6.26-sierra/drivers/input/misc/yealink.alt.c 2008-06-24 10:17:14.000000000 +0200
> +++ linux-2.6.26-sierra/drivers/input/misc/yealink.c 2008-06-26 13:34:35.000000000 +0200
> @@ -424,10 +424,10 @@ send_update:
> static void urb_irq_callback(struct urb *urb)
> {
> struct yealink_dev *yld = urb->context;
> - int ret;
> + int ret, status = urb->status;
>
> - if (urb->status)
> - err("%s - urb status %d", __FUNCTION__, urb->status);
> + if (status)
> + err("%s - urb status %d", __func__, status);
>
> switch (yld->irq_data->cmd) {
> case CMD_KEYPRESS:
> @@ -446,34 +446,43 @@ static void urb_irq_callback(struct urb
> }
>
> yealink_do_idle_tasks(yld);
> -
> - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
> - if (ret)
> - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
> + spin_lock(&yld->spin);
> + if (!yld->shutdown) {
> + ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
> + if (ret && ret != -EPERM)
> + err("%s - usb_submit_urb failed %d", __func__, ret);
> + }
> + spin_unlock(&yld->spin);
> }
>
> static void urb_ctl_callback(struct urb *urb)
> {
> struct yealink_dev *yld = urb->context;
> - int ret;
> + int ret = 0, status = urb->status;
>
> - if (urb->status)
> - err("%s - urb status %d", __FUNCTION__, urb->status);
> + if (status)
> + err("%s - urb status %d", __func__, status);
>
> switch (yld->ctl_data->cmd) {
> case CMD_KEYPRESS:
> case CMD_SCANCODE:
> /* ask for a response */
> - ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
> + spin_lock(&yld->spin);
> + if (!yld->shutdown)
> + ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
> + spin_unlock(&yld->spin);
> break;
> default:
> /* send new command */
> yealink_do_idle_tasks(yld);
> - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
> + spin_lock(&yld->spin);
> + if (!yld->shutdown)
> + ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
> + spin_unlock(&yld->spin);
> }
>
> - if (ret)
> - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
> + if (ret && ret != -EPERM)
> + err("%s - usb_submit_urb failed %d", __func__, ret);
> }
>
> /*******************************************************************************
> @@ -527,12 +536,25 @@ static int input_open(struct input_dev *
> return 0;
> }
>
> -static void input_close(struct input_dev *dev)
> +static void stop_traffic(struct yealink_dev *yld)
> {
> - struct yealink_dev *yld = input_get_drvdata(dev);
> + spin_lock_irq(&yld->spin);
> + yld->shutdown = 1;
> + spin_unlock_irq(&yld->spin);
>
> usb_kill_urb(yld->urb_ctl);
> usb_kill_urb(yld->urb_irq);
> +
> + spin_lock_irq(&yld->spin);
> + yld->shutdown = 0;
> + spin_unlock_irq(&yld->spin);
> +}
> +
> +static void input_close(struct input_dev *dev)
> +{
> + struct yealink_dev *yld = input_get_drvdata(dev);
> +
> + stop_traffic(yld);
> }
>
> /*******************************************************************************
> @@ -809,8 +831,7 @@ static int usb_cleanup(struct yealink_de
> if (yld == NULL)
> return err;
>
> - usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */
> - usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */
> + stop_traffic(yld);
>
> if (yld->idev) {
> if (err)
> @@ -866,6 +887,7 @@ static int usb_probe(struct usb_interfac
> return -ENOMEM;
>
> yld->udev = udev;
> + spin_lock_init(&yld->spin);
>
> yld->idev = input_dev = input_allocate_device();
> if (!input_dev)
>
next prev parent reply other threads:[~2008-06-28 15:11 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-26 11:44 [patch]reliably killing urbs in yealink driver Oliver Neukum
2008-06-26 14:26 ` Dmitry Torokhov
[not found] ` <20080626142633.GA16831-692KRdr1A+M6QviIW9vzWfIbXMQ5te18@public.gmane.org>
2008-06-26 14:32 ` Oliver Neukum
2008-06-26 17:43 ` Dmitry Torokhov
2008-06-27 12:00 ` Oliver Neukum
2008-06-28 15:11 ` Alfred E. Heggestad [this message]
2008-06-30 12:10 ` Oliver Neukum
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=48665495.30204@db.org \
--to=aeh@db.org \
--cc=Henk.Vergonet@gmail.com \
--cc=dmitry.torokhov@gmail.com \
--cc=jkosina@suse.cz \
--cc=linux-input@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=oliver@neukum.org \
/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).