Module Name: src
Committed By: riastradh
Date: Sun Mar 23 20:20:38 UTC 2014
Modified Files:
src/sys/dev/usb: umcs.c
Log Message:
Simplify synchronization between umcs(4) intr and task.
ok martin@, nick@
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/usb/umcs.c
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/umcs.c
diff -u src/sys/dev/usb/umcs.c:1.5 src/sys/dev/usb/umcs.c:1.6
--- src/sys/dev/usb/umcs.c:1.5 Sat Mar 22 20:56:04 2014
+++ src/sys/dev/usb/umcs.c Sun Mar 23 20:20:38 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: umcs.c,v 1.5 2014/03/22 20:56:04 martin Exp $ */
+/* $NetBSD: umcs.c,v 1.6 2014/03/23 20:20:38 riastradh Exp $ */
/* $FreeBSD: head/sys/dev/usb/serial/umcs.c 260559 2014-01-12 11:44:28Z hselasky $ */
/*-
@@ -41,7 +41,7 @@
*
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.5 2014/03/22 20:56:04 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.6 2014/03/23 20:20:38 riastradh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -78,9 +78,6 @@ __KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.5
*/
struct umcs7840_softc_oneport {
device_t sc_port_ucom; /* ucom subdevice */
- volatile uint32_t /* changes for this port have */
- sc_port_changed; /* been signaled,
- call ucom_status_change() */
unsigned int sc_port_phys; /* physical port number */
uint8_t sc_port_lcr; /* local line control register */
uint8_t sc_port_mcr; /* local modem control register */
@@ -94,6 +91,7 @@ struct umcs7840_softc {
uint8_t *sc_intr_buf; /* buffer for interrupt xfer */
unsigned int sc_intr_buflen; /* size of buffer */
struct usb_task sc_change_task; /* async status changes */
+ volatile uint32_t sc_change_mask; /* mask of port changes */
struct umcs7840_softc_oneport sc_ports[UMCS7840_MAX_PORTS];
/* data for each port */
uint8_t sc_numports; /* number of ports (subunits) */
@@ -889,7 +887,7 @@ umcs7840_intr(usbd_xfer_handle xfer, usb
usbd_get_xfer_status(xfer, NULL, NULL, &actlen, NULL);
if (actlen == 5 || actlen == 13) {
- usb_rem_task(sc->sc_udev, &sc->sc_change_task);
+ uint32_t change_mask = 0;
/* Check status of all ports */
for (subunit = 0; subunit < sc->sc_numports; subunit++) {
uint8_t pn = sc->sc_ports[subunit].sc_port_phys;
@@ -904,7 +902,7 @@ umcs7840_intr(usbd_xfer_handle xfer, usb
case MCS7840_UART_ISR_RXHASDATA:
case MCS7840_UART_ISR_RXTIMEOUT:
case MCS7840_UART_ISR_MSCHANGE:
- sc->sc_ports[subunit].sc_port_changed = 1;
+ change_mask |= (1U << subunit);
break;
default:
/* Do nothing */
@@ -912,9 +910,11 @@ umcs7840_intr(usbd_xfer_handle xfer, usb
}
}
- membar_exit();
- usb_add_task(sc->sc_udev, &sc->sc_change_task,
- USB_TASKQ_DRIVER);
+ if (change_mask != 0) {
+ atomic_or_32(&sc->sc_change_mask, change_mask);
+ usb_add_task(sc->sc_udev, &sc->sc_change_task,
+ USB_TASKQ_DRIVER);
+ }
} else {
aprint_error_dev(sc->sc_dev,
"Invalid interrupt data length %d", actlen);
@@ -925,14 +925,13 @@ static void
umcs7840_change_task(void *arg)
{
struct umcs7840_softc *sc = arg;
+ uint32_t change_mask;
int i;
+ change_mask = atomic_swap_32(&sc->sc_change_mask, 0);
for (i = 0; i < sc->sc_numports; i++) {
- if (sc->sc_ports[i].sc_port_changed) {
- sc->sc_ports[i].sc_port_changed = 0;
- membar_exit();
+ if (ISSET(change_mask, (1U << i)))
ucom_status_change(device_private(
sc->sc_ports[i].sc_port_ucom));
- }
}
}