forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/media/usb/uvc/uvc_status.c
....@@ -1,16 +1,12 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * uvc_status.c -- USB Video Class driver - Status endpoint
34 *
45 * Copyright (C) 2005-2009
56 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
127 */
138
9
+#include <asm/barrier.h>
1410 #include <linux/kernel.h>
1511 #include <linux/input.h>
1612 #include <linux/slab.h>
....@@ -184,7 +180,8 @@
184180
185181 switch (status->bAttribute) {
186182 case UVC_CTRL_VALUE_CHANGE:
187
- return uvc_ctrl_status_event(urb, chain, ctrl, status->bValue);
183
+ return uvc_ctrl_status_event_async(urb, chain, ctrl,
184
+ status->bValue);
188185
189186 case UVC_CTRL_INFO_CHANGE:
190187 case UVC_CTRL_FAILURE_CHANGE:
....@@ -314,5 +311,41 @@
314311
315312 void uvc_status_stop(struct uvc_device *dev)
316313 {
314
+ struct uvc_ctrl_work *w = &dev->async_ctrl;
315
+
316
+ /*
317
+ * Prevent the asynchronous control handler from requeing the URB. The
318
+ * barrier is needed so the flush_status change is visible to other
319
+ * CPUs running the asynchronous handler before usb_kill_urb() is
320
+ * called below.
321
+ */
322
+ smp_store_release(&dev->flush_status, true);
323
+
324
+ /*
325
+ * Cancel any pending asynchronous work. If any status event was queued,
326
+ * process it synchronously.
327
+ */
328
+ if (cancel_work_sync(&w->work))
329
+ uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
330
+
331
+ /* Kill the urb. */
317332 usb_kill_urb(dev->int_urb);
333
+
334
+ /*
335
+ * The URB completion handler may have queued asynchronous work. This
336
+ * won't resubmit the URB as flush_status is set, but it needs to be
337
+ * cancelled before returning or it could then race with a future
338
+ * uvc_status_start() call.
339
+ */
340
+ if (cancel_work_sync(&w->work))
341
+ uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
342
+
343
+ /*
344
+ * From this point, there are no events on the queue and the status URB
345
+ * is dead. No events will be queued until uvc_status_start() is called.
346
+ * The barrier is needed to make sure that flush_status is visible to
347
+ * uvc_ctrl_status_event_work() when uvc_status_start() will be called
348
+ * again.
349
+ */
350
+ smp_store_release(&dev->flush_status, false);
318351 }