Date: Thu, 11 Feb 2016 11:58:27 +0000 (UTC) From: Zbigniew Bodek <zbb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r295515 - in head/sys/arm64: arm64 include Message-ID: <201602111158.u1BBwRRI050315@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: zbb Date: Thu Feb 11 11:58:27 2016 New Revision: 295515 URL: https://svnweb.freebsd.org/changeset/base/295515 Log: Introduce bus_bind_intr method for ARM64 It can be used to bind specific interrupt to a particular CPU. Requires PIC support for interrupts binding. Reviewed by: wma Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5122 Modified: head/sys/arm64/arm64/intr_machdep.c head/sys/arm64/arm64/nexus.c head/sys/arm64/arm64/pic_if.m head/sys/arm64/include/intr.h Modified: head/sys/arm64/arm64/intr_machdep.c ============================================================================== --- head/sys/arm64/arm64/intr_machdep.c Thu Feb 11 11:57:13 2016 (r295514) +++ head/sys/arm64/arm64/intr_machdep.c Thu Feb 11 11:58:27 2016 (r295515) @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/proc.h> #include <sys/systm.h> #include <sys/bus.h> #include <sys/kernel.h> @@ -84,6 +85,7 @@ struct arm64_intr_entry { u_int i_hw_irq; /* Physical interrupt number */ u_int i_cntidx; /* Index in intrcnt table */ u_int i_handlers; /* Allocated handlers */ + u_int i_cpu; /* Assigned CPU */ u_long *i_cntp; /* Interrupt hit counter */ }; @@ -162,6 +164,8 @@ intr_allocate(u_int hw_irq) if (intr == NULL) return (NULL); + /* The default CPU is 0 but can be changed later by bind or shuffle */ + intr->i_cpu = 0; intr->i_event = NULL; intr->i_handlers = 0; intr->i_trig = INTR_TRIGGER_CONFORM; @@ -176,6 +180,44 @@ intr_allocate(u_int hw_irq) return intr; } +static int +intr_assign_cpu(void *arg, int cpu) +{ +#ifdef SMP + struct arm64_intr_entry *intr; + int error; + + if (root_pic == NULL) + panic("Cannot assing interrupt to CPU. No PIC configured"); + /* + * Set the interrupt to CPU affinity. + * Do not configure this in hardware during early boot. + * We will pick up the assignment once the APs are started. + */ + if (cpu != NOCPU) { + intr = arg; + if (!cold && smp_started) { + /* + * Bind the interrupt immediately + * if SMP is up and running. + */ + error = PIC_BIND(root_pic, intr->i_hw_irq, cpu); + if (error == 0) + intr->i_cpu = cpu; + } else { + /* Postpone binding until SMP is operational */ + intr->i_cpu = cpu; + error = 0; + } + } else + error = 0; + + return (error); +#else + return (EOPNOTSUPP); +#endif +} + static void intr_pre_ithread(void *arg) { @@ -339,7 +381,7 @@ arm_setup_intr(const char *name, driver_ if (intr->i_event == NULL) { error = intr_event_create(&intr->i_event, (void *)intr, 0, hw_irq, intr_pre_ithread, intr_post_ithread, - intr_post_filter, NULL, "irq%u", hw_irq); + intr_post_filter, intr_assign_cpu, "irq%u", hw_irq); if (error) return (error); } @@ -447,6 +489,42 @@ arm_cpu_intr(struct trapframe *tf) } #ifdef SMP +static void +arm_intr_smp_init(void *dummy __unused) +{ + struct arm64_intr_entry *intr; + int error; + + if (root_pic == NULL) + panic("Cannot assing interrupts to CPUs. No PIC configured"); + + mtx_lock_spin(&intr_list_lock); + SLIST_FOREACH(intr, &irq_slist_head, entries) { + mtx_unlock_spin(&intr_list_lock); + error = PIC_BIND(root_pic, intr->i_hw_irq, intr->i_cpu); + if (error != 0) + intr->i_cpu = 0; + mtx_lock_spin(&intr_list_lock); + } + mtx_unlock_spin(&intr_list_lock); +} +SYSINIT(arm_intr_smp_init, SI_SUB_SMP, SI_ORDER_ANY, arm_intr_smp_init, NULL); + +/* Attempt to bind the specified IRQ to the specified CPU. */ +int +arm_intr_bind(u_int hw_irq, int cpu) +{ + struct arm64_intr_entry *intr; + + mtx_lock_spin(&intr_list_lock); + intr = intr_lookup_locked(hw_irq); + mtx_unlock_spin(&intr_list_lock); + if (intr == NULL) + return (EINVAL); + + return (intr_event_bind(intr->i_event, cpu)); +} + void arm_setup_ipihandler(driver_filter_t *filt, u_int ipi) { Modified: head/sys/arm64/arm64/nexus.c ============================================================================== --- head/sys/arm64/arm64/nexus.c Thu Feb 11 11:57:13 2016 (r295514) +++ head/sys/arm64/arm64/nexus.c Thu Feb 11 11:58:27 2016 (r295515) @@ -113,6 +113,9 @@ static int nexus_deactivate_resource(dev static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); +#ifdef SMP +static int nexus_bind_intr(device_t, device_t, struct resource *, int); +#endif #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, @@ -131,7 +134,9 @@ static device_method_t nexus_methods[] = DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), - +#ifdef SMP + DEVMETHOD(bus_bind_intr, nexus_bind_intr), +#endif { 0, 0 } }; @@ -293,6 +298,15 @@ nexus_teardown_intr(device_t dev, device return (arm_teardown_intr(ih)); } +#ifdef SMP +static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + + return (arm_intr_bind(rman_get_start(irq), cpu)); +} +#endif + static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) Modified: head/sys/arm64/arm64/pic_if.m ============================================================================== --- head/sys/arm64/arm64/pic_if.m Thu Feb 11 11:57:13 2016 (r295514) +++ head/sys/arm64/arm64/pic_if.m Thu Feb 11 11:58:27 2016 (r295515) @@ -34,7 +34,11 @@ INTERFACE pic; CODE { - static pic_translate_code_t pic_translate_code_default; + static int pic_bind_default(device_t dev, u_int irq, u_int cpu) + { + + return (EOPNOTSUPP); + } static void pic_translate_code_default(device_t dev, u_int irq, int code, enum intr_trigger *trig, enum intr_polarity *pol) @@ -60,11 +64,11 @@ CODE { } }; -METHOD void bind { +METHOD int bind { device_t dev; u_int irq; - cpuset_t cpumask; -}; + u_int cpu; +} DEFAULT pic_bind_default; METHOD void translate_code { device_t dev; Modified: head/sys/arm64/include/intr.h ============================================================================== --- head/sys/arm64/include/intr.h Thu Feb 11 11:57:13 2016 (r295514) +++ head/sys/arm64/include/intr.h Thu Feb 11 11:58:27 2016 (r295515) @@ -49,6 +49,7 @@ void arm_unmask_irq(u_int); #ifdef SMP void arm_init_secondary(void); +int arm_intr_bind(u_int, int); void arm_setup_ipihandler(driver_filter_t *, u_int); void arm_unmask_ipi(u_int); #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201602111158.u1BBwRRI050315>