summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-01-29 10:57:36 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-01-29 10:57:36 +0100
commita5b385b26fb88ecb0408c684643adec481596dd8 (patch)
tree3e841635f40eacd81b54d29af3a1549382bf7f87 /freebsd/sys/kern
parentRemove obsolete file (diff)
downloadrtems-libbsd-a5b385b26fb88ecb0408c684643adec481596dd8.tar.bz2
Update to FreeBSD stable/12 2019-01-29
Git mirror commit 7005c2e76a6bfb359bf2f1acb8382c0b7a01f4be.
Diffstat (limited to 'freebsd/sys/kern')
-rw-r--r--freebsd/sys/kern/kern_intr.c104
-rw-r--r--freebsd/sys/kern/kern_mtxpool.c4
-rw-r--r--freebsd/sys/kern/subr_bus.c58
-rw-r--r--freebsd/sys/kern/subr_rman.c15
4 files changed, 170 insertions, 11 deletions
diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index 20117eac..9c647eb6 100644
--- a/freebsd/sys/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
@@ -756,6 +756,28 @@ intr_event_barrier(struct intr_event *ie)
atomic_thread_fence_acq();
}
+static void
+intr_handler_barrier(struct intr_handler *handler)
+{
+ struct intr_event *ie;
+
+ ie = handler->ih_event;
+ mtx_assert(&ie->ie_lock, MA_OWNED);
+ KASSERT((handler->ih_flags & IH_DEAD) == 0,
+ ("update for a removed handler"));
+
+ if (ie->ie_thread == NULL) {
+ intr_event_barrier(ie);
+ return;
+ }
+ if ((handler->ih_flags & IH_CHANGED) == 0) {
+ handler->ih_flags |= IH_CHANGED;
+ intr_event_schedule_thread(ie);
+ }
+ while ((handler->ih_flags & IH_CHANGED) != 0)
+ msleep(handler, &ie->ie_lock, 0, "ih_barr", 0);
+}
+
/*
* Sleep until an ithread finishes executing an interrupt handler.
*
@@ -880,6 +902,49 @@ intr_event_remove_handler(void *cookie)
}
#endif /* __rtems__ */
+int
+intr_event_suspend_handler(void *cookie)
+{
+ struct intr_handler *handler = (struct intr_handler *)cookie;
+ struct intr_event *ie;
+
+ if (handler == NULL)
+ return (EINVAL);
+ ie = handler->ih_event;
+ KASSERT(ie != NULL,
+ ("interrupt handler \"%s\" has a NULL interrupt event",
+ handler->ih_name));
+ mtx_lock(&ie->ie_lock);
+ handler->ih_flags |= IH_SUSP;
+ intr_handler_barrier(handler);
+ mtx_unlock(&ie->ie_lock);
+ return (0);
+}
+
+int
+intr_event_resume_handler(void *cookie)
+{
+ struct intr_handler *handler = (struct intr_handler *)cookie;
+ struct intr_event *ie;
+
+ if (handler == NULL)
+ return (EINVAL);
+ ie = handler->ih_event;
+ KASSERT(ie != NULL,
+ ("interrupt handler \"%s\" has a NULL interrupt event",
+ handler->ih_name));
+
+ /*
+ * intr_handler_barrier() acts not only as a barrier,
+ * it also allows to check for any pending interrupts.
+ */
+ mtx_lock(&ie->ie_lock);
+ handler->ih_flags &= ~IH_SUSP;
+ intr_handler_barrier(handler);
+ mtx_unlock(&ie->ie_lock);
+ return (0);
+}
+
static int
intr_event_schedule_thread(struct intr_event *ie)
{
@@ -1068,10 +1133,21 @@ intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
*/
ihp = ih;
+ if ((ih->ih_flags & IH_CHANGED) != 0) {
+ mtx_lock(&ie->ie_lock);
+ ih->ih_flags &= ~IH_CHANGED;
+ wakeup(ih);
+ mtx_unlock(&ie->ie_lock);
+ }
+
/* Skip filter only handlers */
if (ih->ih_handler == NULL)
continue;
+ /* Skip suspended handlers */
+ if ((ih->ih_flags & IH_SUSP) != 0)
+ continue;
+
/*
* For software interrupt threads, we only execute
* handlers that have their need flag set. Hardware
@@ -1255,8 +1331,9 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
struct intr_handler *ih;
struct trapframe *oldframe;
struct thread *td;
- int ret, thread;
int phase;
+ int ret;
+ bool filter, thread;
td = curthread;
@@ -1275,7 +1352,8 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
* a trapframe as its argument.
*/
td->td_intr_nesting_level++;
- thread = 0;
+ filter = false;
+ thread = false;
ret = 0;
critical_enter();
oldframe = td->td_intr_frame;
@@ -1291,8 +1369,10 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
atomic_thread_fence_seq_cst();
CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if ((ih->ih_flags & IH_SUSP) != 0)
+ continue;
if (ih->ih_filter == NULL) {
- thread = 1;
+ thread = true;
continue;
}
CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
@@ -1307,24 +1387,25 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
(ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
("%s: incorrect return value %#x from %s", __func__, ret,
ih->ih_name));
+ filter = filter || ret == FILTER_HANDLED;
- /*
+ /*
* Wrapper handler special handling:
*
- * in some particular cases (like pccard and pccbb),
+ * in some particular cases (like pccard and pccbb),
* the _real_ device handler is wrapped in a couple of
* functions - a filter wrapper and an ithread wrapper.
- * In this case (and just in this case), the filter wrapper
+ * In this case (and just in this case), the filter wrapper
* could ask the system to schedule the ithread and mask
* the interrupt source if the wrapped handler is composed
* of just an ithread handler.
*
- * TODO: write a generic wrapper to avoid people rolling
- * their own
+ * TODO: write a generic wrapper to avoid people rolling
+ * their own.
*/
if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
+ thread = true;
}
}
atomic_add_rel_int(&ie->ie_active[phase], -1);
@@ -1348,6 +1429,11 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
}
critical_exit();
td->td_intr_nesting_level--;
+#ifdef notyet
+ /* The interrupt is not aknowledged by any filter and has no ithread. */
+ if (!thread && !filter)
+ return (EINVAL);
+#endif
return (0);
}
diff --git a/freebsd/sys/kern/kern_mtxpool.c b/freebsd/sys/kern/kern_mtxpool.c
index 7f6c4dce..bc47d826 100644
--- a/freebsd/sys/kern/kern_mtxpool.c
+++ b/freebsd/sys/kern/kern_mtxpool.c
@@ -64,14 +64,14 @@ static MALLOC_DEFINE(M_MTXPOOL, "mtx_pool", "mutex pool");
/* Pool sizes must be a power of two */
#ifndef MTX_POOL_SLEEP_SIZE
-#define MTX_POOL_SLEEP_SIZE 128
+#define MTX_POOL_SLEEP_SIZE 1024
#endif
struct mtxpool_header {
int mtxpool_size;
int mtxpool_mask;
int mtxpool_shift;
- int mtxpool_next;
+ int mtxpool_next __aligned(CACHE_LINE_SIZE);
};
struct mtx_pool {
diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 391b2ed6..29fdfe34 100644
--- a/freebsd/sys/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
@@ -4101,6 +4101,36 @@ bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
}
/**
+ * @brief Helper function for implementing BUS_SUSPEND_INTR().
+ *
+ * This simple implementation of BUS_SUSPEND_INTR() simply calls the
+ * BUS_SUSPEND_INTR() method of the parent of @p dev.
+ */
+int
+bus_generic_suspend_intr(device_t dev, device_t child, struct resource *irq)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_SUSPEND_INTR(dev->parent, child, irq));
+ return (EINVAL);
+}
+
+/**
+ * @brief Helper function for implementing BUS_RESUME_INTR().
+ *
+ * This simple implementation of BUS_RESUME_INTR() simply calls the
+ * BUS_RESUME_INTR() method of the parent of @p dev.
+ */
+int
+bus_generic_resume_intr(device_t dev, device_t child, struct resource *irq)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_RESUME_INTR(dev->parent, child, irq));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_ADJUST_RESOURCE().
*
* This simple implementation of BUS_ADJUST_RESOURCE() simply calls the
@@ -4668,6 +4698,34 @@ bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
}
/**
+ * @brief Wrapper function for BUS_SUSPEND_INTR().
+ *
+ * This function simply calls the BUS_SUSPEND_INTR() method of the
+ * parent of @p dev.
+ */
+int
+bus_suspend_intr(device_t dev, struct resource *r)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_SUSPEND_INTR(dev->parent, dev, r));
+}
+
+/**
+ * @brief Wrapper function for BUS_RESUME_INTR().
+ *
+ * This function simply calls the BUS_RESUME_INTR() method of the
+ * parent of @p dev.
+ */
+int
+bus_resume_intr(device_t dev, struct resource *r)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_RESUME_INTR(dev->parent, dev, r));
+}
+
+/**
* @brief Wrapper function for BUS_BIND_INTR().
*
* This function simply calls the BUS_BIND_INTR() method of the
diff --git a/freebsd/sys/kern/subr_rman.c b/freebsd/sys/kern/subr_rman.c
index 75f22dd5..e307df46 100644
--- a/freebsd/sys/kern/subr_rman.c
+++ b/freebsd/sys/kern/subr_rman.c
@@ -96,6 +96,7 @@ struct resource_i {
rman_res_t r_end; /* index of the last entry (inclusive) */
u_int r_flags;
void *r_virtual; /* virtual address of this resource */
+ void *r_irq_cookie; /* interrupt cookie for this (interrupt) resource */
device_t r_dev; /* device which has allocated this resource */
struct rman *r_rm; /* resource manager from whence this came */
int r_rid; /* optional rid for this resource. */
@@ -871,6 +872,20 @@ rman_get_virtual(struct resource *r)
}
void
+rman_set_irq_cookie(struct resource *r, void *c)
+{
+
+ r->__r_i->r_irq_cookie = c;
+}
+
+void *
+rman_get_irq_cookie(struct resource *r)
+{
+
+ return (r->__r_i->r_irq_cookie);
+}
+
+void
rman_set_bustag(struct resource *r, bus_space_tag_t t)
{