struct smsusb_device_t *dev;
struct urb urb;
+
+ /* For the bottom half */
+ struct work_struct wq;
};
struct smsusb_device_t {
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
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");