Re: [RFC 07/12] HID: wiimote: Add output queue for wiimote driver
flat view
From: Oliver Neukum <oliver@neukum.org>
Date: 2011-06-15 06:42:19
Am Mittwoch, 15. Juni 2011, 01:45:52 schrieb David Herrmann:
quoted hunk ↗ jump to hunk
+struct wiimote_buf { + __u8 data[HID_MAX_BUFFER_SIZE]; + size_t size; +};
As this probably goes out over USB -> BT you are violating the DMA buffer constraints. Every buffer must be separately allocated with kmalloc().
quoted hunk ↗ jump to hunk
struct wiimote_data { atomic_t ready; struct hid_device *hdev; struct input_dev *input; + + spinlock_t qlock; + __u8 head; + __u8 tail; + struct wiimote_buf outq[WIIMOTE_BUFSIZE]; + struct work_struct worker; }; static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,@@ -36,6 +49,78 @@ static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, HID_OUTPUT_REPORT); } +static void wiimote_worker(struct work_struct *work) +{ + struct wiimote_data *wdata = container_of(work, struct wiimote_data, + worker); + + if (!atomic_read(&wdata->ready)) + return; + + spin_lock(&wdata->qlock);
You want _irqsave
quoted hunk ↗ jump to hunk
+ if (wdata->head != wdata->tail) { + spin_unlock(&wdata->qlock); + wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, + wdata->outq[wdata->tail].size); + spin_lock(&wdata->qlock); + + wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; + + /* + * We are using the shared workqueue so send at most one whole + * buffer and then reschedule ourself so we do not occupy the + * shared workqueue for too long. + */ + if (wdata->head != wdata->tail) + schedule_work(&wdata->worker); + } + + spin_unlock(&wdata->qlock); +}
Regards Oliver