Module Name:    src
Committed By:   mlelstv
Date:           Sat Jan  4 22:30:06 UTC 2020

Modified Files:
        src/sys/dev/usb: if_run.c if_runvar.h

Log Message:
Avoid race condition. Patch from bouyer@


To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.35 src/sys/dev/usb/if_run.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/usb/if_runvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/if_run.c
diff -u src/sys/dev/usb/if_run.c:1.34 src/sys/dev/usb/if_run.c:1.35
--- src/sys/dev/usb/if_run.c:1.34	Thu Dec 19 15:17:30 2019
+++ src/sys/dev/usb/if_run.c	Sat Jan  4 22:30:06 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_run.c,v 1.34 2019/12/19 15:17:30 gson Exp $	*/
+/*	$NetBSD: if_run.c,v 1.35 2020/01/04 22:30:06 mlelstv Exp $	*/
 /*	$OpenBSD: if_run.c,v 1.90 2012/03/24 15:11:04 jsg Exp $	*/
 
 /*-
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.34 2019/12/19 15:17:30 gson Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.35 2020/01/04 22:30:06 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1
 #include <sys/module.h>
 #include <sys/conf.h>
 #include <sys/device.h>
+#include <sys/atomic.h>
 
 #include <sys/bus.h>
 #include <machine/endian.h>
@@ -1784,10 +1785,11 @@ run_task(void *arg)
 	while (ring->next != ring->cur) {
 		cmd = &ring->cmd[ring->next];
 		splx(s);
+		membar_consumer();
 		/* callback */
 		cmd->cb(sc, cmd->data);
 		s = splusb();
-		ring->queued--;
+		atomic_dec_uint(&ring->queued);
 		ring->next = (ring->next + 1) % RUN_HOST_CMD_RING_COUNT;
 	}
 	wakeup(ring);
@@ -1810,10 +1812,11 @@ run_do_async(struct run_softc *sc, void 
 	cmd->cb = cb;
 	KASSERT(len <= sizeof(cmd->data));
 	memcpy(cmd->data, arg, len);
+	membar_producer();
 	ring->cur = (ring->cur + 1) % RUN_HOST_CMD_RING_COUNT;
 
 	/* if there is no pending command already, schedule a task */
-	if (++ring->queued == 1)
+	if (atomic_inc_uint_nv(&ring->queued) == 1)
 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
 	splx(s);
 }

Index: src/sys/dev/usb/if_runvar.h
diff -u src/sys/dev/usb/if_runvar.h:1.6 src/sys/dev/usb/if_runvar.h:1.7
--- src/sys/dev/usb/if_runvar.h:1.6	Tue Oct  8 07:30:58 2019
+++ src/sys/dev/usb/if_runvar.h	Sat Jan  4 22:30:06 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_runvar.h,v 1.6 2019/10/08 07:30:58 mlelstv Exp $	*/
+/*	$NetBSD: if_runvar.h,v 1.7 2020/01/04 22:30:06 mlelstv Exp $	*/
 /*	$OpenBSD: if_runvar.h,v 1.8 2010/02/08 18:46:47 damien Exp $	*/
 
 /*-
@@ -93,7 +93,7 @@ struct run_tx_ring {
 	struct run_tx_data	data[RUN_TX_RING_COUNT];
 	struct usbd_pipe *	pipeh;
 	int			cur;
-	int			queued;
+	volatile unsigned	queued;
 	uint8_t			pipe_no;
 };
 

Reply via email to