Skip to content

Commit

Permalink
Merge branch 'waitqueue'
Browse files Browse the repository at this point in the history
Killing the input and output URBs in flight when closing seems to
confuse the PIUIO hardware, causing it not to respond when the device is
re-opened.  We now use a wait queue to allow the last two URBs to
complete when closing, rather than shooting them out of the air.

This *appears* to fix issue #3.
  • Loading branch information
djpohly committed Aug 22, 2014
2 parents 2ed6e71 + 60c4063 commit 172dadd
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions mod/piuio.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/bitops.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
Expand Down Expand Up @@ -66,6 +68,7 @@ struct piuio {
struct usb_device *usbdev;
struct urb *in, *out;
struct usb_ctrlrequest cr_in, cr_out;
wait_queue_head_t shutdown_wait;

unsigned long old[PIUIO_MULTIPLEX][PIUIO_MSG_LONGS];
unsigned long new[PIUIO_MSG_LONGS];
Expand Down Expand Up @@ -119,7 +122,7 @@ static void piuio_in_completed(struct urb *urb)
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
goto in_finished;
default: /* error */
dev_warn(&piu->dev->dev, "in urb status %d received\n",
urb->status);
Expand Down Expand Up @@ -168,6 +171,10 @@ static void piuio_in_completed(struct urb *urb)
dev_err(&piu->dev->dev,
"usb_submit_urb(new) failed, status %d", i);
}

in_finished:
/* Let any waiting threads know we're done here */
wake_up(&piu->shutdown_wait);
}

static void piuio_out_completed(struct urb *urb)
Expand All @@ -181,7 +188,7 @@ static void piuio_out_completed(struct urb *urb)
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
goto out_finished;
default: /* error */
dev_warn(&piu->dev->dev, "out urb status %d received\n",
ret);
Expand Down Expand Up @@ -210,6 +217,10 @@ static void piuio_out_completed(struct urb *urb)
"usb_submit_urb(lights) failed, status %d\n",
ret);
}

out_finished:
/* Let any waiting threads know we're done here */
wake_up(&piu->shutdown_wait);
}


Expand All @@ -235,9 +246,15 @@ static void piuio_close(struct input_dev *dev)
{
struct piuio *piu = input_get_drvdata(dev);

/* Stop polling */
usb_kill_urb(piu->in);
usb_kill_urb(piu->out);
/* Stop polling, but wait for the last requests to complete */
usb_block_urb(piu->in);
usb_block_urb(piu->out);
wait_event_timeout(piu->shutdown_wait,
atomic_read(&piu->in->use_count) == 0 &&
atomic_read(&piu->out->use_count) == 0,
msecs_to_jiffies(5));
usb_unblock_urb(piu->in);
usb_unblock_urb(piu->out);

/* XXX Kill the lights! */
/* XXX Re-initialize parts of piuio struct */
Expand Down Expand Up @@ -292,6 +309,8 @@ static int piuio_init(struct piuio *piu, struct input_dev *dev,
if (!(piu->out = usb_alloc_urb(0, GFP_KERNEL)))
return -ENOMEM;

init_waitqueue_head(&piu->shutdown_wait);

piu->dev = dev;
piu->usbdev = usbdev;
usb_make_path(usbdev, piu->phys, sizeof(piu->phys));
Expand Down

0 comments on commit 172dadd

Please sign in to comment.