summaryrefslogtreecommitdiffstats
path: root/freebsd
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-10-04 12:06:44 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-10-04 14:14:51 +0200
commit1e77a45d54bfc52eb76453f3e1327645acc8f77b (patch)
treee06ee24573a7e7b1e29f830bd9662427b504946e /freebsd
parentrtwn: Align mbuf to avoid realignment in rx path (diff)
downloadrtems-libbsd-1e77a45d54bfc52eb76453f3e1327645acc8f77b.tar.bz2
saf1761_otg: Use real interrupt handler
The USB_BUS_SPIN_LOCK() is only used internally to the bus driver. Replace the mutex with an interrupt disable/enable section. Execute the interrupt filter in a real interrupt context and forward the interrupt handler to the interrupt server if necessary.
Diffstat (limited to 'freebsd')
-rw-r--r--freebsd/sys/dev/usb/controller/saf1761_otg.c25
-rw-r--r--freebsd/sys/dev/usb/controller/saf1761_otg.h6
-rw-r--r--freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c28
3 files changed, 53 insertions, 6 deletions
diff --git a/freebsd/sys/dev/usb/controller/saf1761_otg.c b/freebsd/sys/dev/usb/controller/saf1761_otg.c
index e1ce5eb6..cb9e50cf 100644
--- a/freebsd/sys/dev/usb/controller/saf1761_otg.c
+++ b/freebsd/sys/dev/usb/controller/saf1761_otg.c
@@ -88,6 +88,15 @@
#ifdef LIBBSP_ARM_ATSAM_BSP_H
#include <bsp/pin-config.h>
#endif /* LIBBSP_ARM_ATSAM_BSP_H */
+#undef USB_BUS_SPIN_LOCK
+#undef USB_BUS_SPIN_UNLOCK
+#define USB_BUS_SPIN_LOCK(_b) \
+ do { \
+ rtems_interrupt_level usb_bus_spin_lock; \
+ rtems_interrupt_disable(usb_bus_spin_lock)
+#define USB_BUS_SPIN_UNLOCK(_b) \
+ rtems_interrupt_enable(usb_bus_spin_lock); \
+ } while (0)
#endif /* __rtems__ */
#define SAF1761_OTG_BUS2SC(bus) \
@@ -1668,6 +1677,7 @@ saf1761_otg_interrupt(void *arg)
{
struct saf1761_otg_softc *sc = arg;
uint32_t status;
+ bool xfer_complete;
USB_BUS_LOCK(&sc->sc_bus);
USB_BUS_SPIN_LOCK(&sc->sc_bus);
@@ -1735,13 +1745,16 @@ saf1761_otg_interrupt(void *arg)
}
}
- if (sc->sc_xfer_complete != 0) {
+ xfer_complete = (sc->sc_xfer_complete != 0);
+ if (xfer_complete)
sc->sc_xfer_complete = 0;
+ USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
+
+ if (xfer_complete)
/* complete FIFOs, if any */
saf1761_otg_interrupt_complete_locked(sc);
- }
- USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
+
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -2232,10 +2245,10 @@ saf1761_otg_device_done(struct usb_xfer *xfer, usb_error_t error)
saf1761_host_channel_free(sc, td);
}
+ USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
+
/* dequeue transfer and start next transfer */
usbd_transfer_done(xfer, error);
-
- USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
}
static void
@@ -2600,8 +2613,8 @@ saf1761_otg_do_poll(struct usb_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
USB_BUS_SPIN_LOCK(&sc->sc_bus);
saf1761_otg_interrupt_poll_locked(sc);
- saf1761_otg_interrupt_complete_locked(sc);
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
+ saf1761_otg_interrupt_complete_locked(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
diff --git a/freebsd/sys/dev/usb/controller/saf1761_otg.h b/freebsd/sys/dev/usb/controller/saf1761_otg.h
index 4ab9b629..afee30bc 100644
--- a/freebsd/sys/dev/usb/controller/saf1761_otg.h
+++ b/freebsd/sys/dev/usb/controller/saf1761_otg.h
@@ -32,6 +32,9 @@
#ifndef _SAF1761_OTG_H_
#define _SAF1761_OTG_H_
+#ifdef __rtems__
+#include <rtems/irq-extension.h>
+#endif /* __rtems__ */
#define SOTG_MAX_DEVICES MIN(USB_MAX_DEVICES, 32)
#define SOTG_FS_MAX_PACKET_SIZE 64
#define SOTG_HS_MAX_PACKET_SIZE 512
@@ -163,6 +166,9 @@ struct saf1761_otg_softc {
uint8_t sc_hub_idata[1];
struct saf1761_otg_flags sc_flags;
+#ifdef __rtems__
+ rtems_interrupt_server_request sc_irq_srv_req;
+#endif /* __rtems__ */
};
/* prototypes */
diff --git a/freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c b/freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c
index 32b6b92c..c088716a 100644
--- a/freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c
+++ b/freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c
@@ -135,6 +135,19 @@ saf1761_otg_fdt_probe(device_t dev)
return (0);
}
+#ifdef __rtems__
+static void
+saf1761_otg_filter_interrupt_wrapper(void *arg)
+{
+ struct saf1761_otg_softc *sc = arg;
+ int status;
+
+ status = saf1761_otg_filter_interrupt(sc);
+ if ((status & FILTER_SCHEDULE_THREAD) != 0) {
+ rtems_interrupt_server_request_submit(&sc->sc_irq_srv_req);
+ }
+}
+#endif /* __rtems__ */
static int
saf1761_otg_fdt_attach(device_t dev)
{
@@ -142,6 +155,9 @@ saf1761_otg_fdt_attach(device_t dev)
char param[24];
int err;
int rid;
+#ifdef __rtems__
+ rtems_status_code status;
+#endif /* __rtems__ */
#ifndef __rtems__
/* get configuration from FDT */
@@ -243,8 +259,20 @@ saf1761_otg_fdt_attach(device_t dev)
PIO_EnableIt(&saf_irq);
#endif /* LIBBSP_ARM_ATSAM_BSP_H */
#endif /* __rtems__ */
+#ifndef __rtems__
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY | INTR_MPSAFE,
&saf1761_otg_filter_interrupt, &saf1761_otg_interrupt, sc, &sc->sc_intr_hdl);
+#else /* __rtems__ */
+ rtems_interrupt_server_request_initialize(
+ RTEMS_INTERRUPT_SERVER_DEFAULT, &sc->sc_irq_srv_req,
+ saf1761_otg_interrupt, sc);
+ rtems_interrupt_server_request_set_vector(&sc->sc_irq_srv_req,
+ rman_get_start(sc->sc_irq_res));
+ status = rtems_interrupt_handler_install(
+ rman_get_start(sc->sc_irq_res), device_get_nameunit(dev),
+ RTEMS_INTERRUPT_SHARED, saf1761_otg_filter_interrupt_wrapper, sc);
+ err = (status == RTEMS_SUCCESSFUL) ? 0 : EINVAL;
+#endif /* __rtems__ */
if (err) {
sc->sc_intr_hdl = NULL;
goto error;