summaryrefslogtreecommitdiff
path: root/drivers/media/usb/siano/smsusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/siano/smsusb.c')
-rw-r--r--drivers/media/usb/siano/smsusb.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index 8abbd3cc8eba..c2e25876e93b 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <media/media-device.h>
#include "sms-cards.h"
#include "smsendian.h"
@@ -51,6 +52,9 @@ struct smsusb_urb_t {
struct smsusb_device_t *dev;
struct urb urb;
+
+ /* For the bottom half */
+ struct work_struct wq;
};
struct smsusb_device_t {
@@ -71,6 +75,18 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
struct smsusb_urb_t *surb);
/**
+ * Completing URB's callback handler - bottom half (proccess context)
+ * submits the URB prepared on smsusb_onresponse()
+ */
+static void do_submit_urb(struct work_struct *work)
+{
+ struct smsusb_urb_t *surb = container_of(work, struct smsusb_urb_t, wq);
+ struct smsusb_device_t *dev = surb->dev;
+
+ smsusb_submit_urb(dev, surb);
+}
+
+/**
* Completing URB's callback handler - top half (interrupt context)
* adds completing sms urb to the global surbs list and activtes the worker
* thread the surb
@@ -138,13 +154,15 @@ static void smsusb_onresponse(struct urb *urb)
exit_and_resubmit:
- smsusb_submit_urb(dev, surb);
+ INIT_WORK(&surb->wq, do_submit_urb);
+ schedule_work(&surb->wq);
}
static int smsusb_submit_urb(struct smsusb_device_t *dev,
struct smsusb_urb_t *surb)
{
if (!surb->cb) {
+ /* This function can sleep */
surb->cb = smscore_getbuffer(dev->coredev);
if (!surb->cb) {
pr_err("smscore_getbuffer(...) returned NULL\n");
@@ -353,15 +371,7 @@ static void *siano_media_device_register(struct smsusb_device_t *dev,
if (!mdev)
return NULL;
- mdev->dev = &udev->dev;
- strlcpy(mdev->model, board->name, sizeof(mdev->model));
- if (udev->serial)
- strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
- strcpy(mdev->bus_info, udev->devpath);
- mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
- mdev->driver_version = LINUX_VERSION_CODE;
-
- media_device_init(mdev);
+ media_device_usb_init(mdev, udev, board->name);
ret = media_device_register(mdev);
if (ret) {