.. | .. |
---|
6 | 6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
---|
7 | 7 | */ |
---|
8 | 8 | |
---|
| 9 | +#include <asm/barrier.h> |
---|
9 | 10 | #include <linux/kernel.h> |
---|
10 | 11 | #include <linux/list.h> |
---|
11 | 12 | #include <linux/module.h> |
---|
.. | .. |
---|
1275 | 1276 | uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); |
---|
1276 | 1277 | } |
---|
1277 | 1278 | |
---|
1278 | | -static void uvc_ctrl_status_event_work(struct work_struct *work) |
---|
| 1279 | +void uvc_ctrl_status_event(struct uvc_video_chain *chain, |
---|
| 1280 | + struct uvc_control *ctrl, const u8 *data) |
---|
1279 | 1281 | { |
---|
1280 | | - struct uvc_device *dev = container_of(work, struct uvc_device, |
---|
1281 | | - async_ctrl.work); |
---|
1282 | | - struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|
1283 | | - struct uvc_video_chain *chain = w->chain; |
---|
1284 | 1282 | struct uvc_control_mapping *mapping; |
---|
1285 | | - struct uvc_control *ctrl = w->ctrl; |
---|
1286 | 1283 | struct uvc_fh *handle; |
---|
1287 | 1284 | unsigned int i; |
---|
1288 | | - int ret; |
---|
1289 | 1285 | |
---|
1290 | 1286 | mutex_lock(&chain->ctrl_mutex); |
---|
1291 | 1287 | |
---|
.. | .. |
---|
1293 | 1289 | ctrl->handle = NULL; |
---|
1294 | 1290 | |
---|
1295 | 1291 | list_for_each_entry(mapping, &ctrl->info.mappings, list) { |
---|
1296 | | - s32 value = __uvc_ctrl_get_value(mapping, w->data); |
---|
| 1292 | + s32 value = __uvc_ctrl_get_value(mapping, data); |
---|
1297 | 1293 | |
---|
1298 | 1294 | /* |
---|
1299 | 1295 | * handle may be NULL here if the device sends auto-update |
---|
.. | .. |
---|
1312 | 1308 | } |
---|
1313 | 1309 | |
---|
1314 | 1310 | mutex_unlock(&chain->ctrl_mutex); |
---|
| 1311 | +} |
---|
| 1312 | + |
---|
| 1313 | +static void uvc_ctrl_status_event_work(struct work_struct *work) |
---|
| 1314 | +{ |
---|
| 1315 | + struct uvc_device *dev = container_of(work, struct uvc_device, |
---|
| 1316 | + async_ctrl.work); |
---|
| 1317 | + struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|
| 1318 | + int ret; |
---|
| 1319 | + |
---|
| 1320 | + uvc_ctrl_status_event(w->chain, w->ctrl, w->data); |
---|
| 1321 | + |
---|
| 1322 | + /* The barrier is needed to synchronize with uvc_status_stop(). */ |
---|
| 1323 | + if (smp_load_acquire(&dev->flush_status)) |
---|
| 1324 | + return; |
---|
1315 | 1325 | |
---|
1316 | 1326 | /* Resubmit the URB. */ |
---|
1317 | 1327 | w->urb->interval = dev->int_ep->desc.bInterval; |
---|
.. | .. |
---|
1321 | 1331 | ret); |
---|
1322 | 1332 | } |
---|
1323 | 1333 | |
---|
1324 | | -bool uvc_ctrl_status_event(struct urb *urb, struct uvc_video_chain *chain, |
---|
1325 | | - struct uvc_control *ctrl, const u8 *data) |
---|
| 1334 | +bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain, |
---|
| 1335 | + struct uvc_control *ctrl, const u8 *data) |
---|
1326 | 1336 | { |
---|
1327 | 1337 | struct uvc_device *dev = chain->dev; |
---|
1328 | 1338 | struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|