diff options
| author | John Baldwin <jhb@FreeBSD.org> | 2008-03-14 19:41:48 +0000 |
|---|---|---|
| committer | John Baldwin <jhb@FreeBSD.org> | 2008-03-14 19:41:48 +0000 |
| commit | eaf86d1678b7caea39710ed2b2086bb4e131eeda (patch) | |
| tree | c7c725651b1ad4c07a8fe93c253676ef3d6d5279 /sys/amd64 | |
| parent | 9e3bdede0f3df75b406a354c65350cb976a3f1df (diff) | |
Notes
Diffstat (limited to 'sys/amd64')
| -rw-r--r-- | sys/amd64/amd64/intr_machdep.c | 61 | ||||
| -rw-r--r-- | sys/amd64/include/intr_machdep.h | 3 |
2 files changed, 55 insertions, 9 deletions
diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c index 7efc7ace54ce..23d9278456cc 100644 --- a/sys/amd64/amd64/intr_machdep.c +++ b/sys/amd64/amd64/intr_machdep.c @@ -89,6 +89,7 @@ static int assign_cpu; static void intr_assign_next_cpu(struct intsrc *isrc); #endif +static int intr_assign_cpu(void *arg, u_char cpu); static void intr_init(void *__dummy); static int intr_pic_registered(struct pic *pic); static void intrcnt_setname(const char *name, int index); @@ -146,10 +147,12 @@ intr_register_source(struct intsrc *isrc) #ifdef INTR_FILTER error = intr_event_create(&isrc->is_event, isrc, 0, (mask_fn)isrc->is_pic->pic_enable_source, - intr_eoi_src, intr_disab_eoi_src, "irq%d:", vector); + intr_eoi_src, intr_disab_eoi_src, intr_assign_cpu, "irq%d:", + vector); #else error = intr_event_create(&isrc->is_event, isrc, 0, - (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector); + (mask_fn)isrc->is_pic->pic_enable_source, intr_assign_cpu, "irq%d:", + vector); #endif if (error) return (error); @@ -431,6 +434,28 @@ intr_suspend(void) sx_xunlock(&intr_table_lock); } +static int +intr_assign_cpu(void *arg, u_char cpu) +{ +#ifdef SMP + struct intsrc *isrc; + + /* + * Don't do anything during early boot. We will pick up the + * assignment once the APs are started. + */ + if (assign_cpu && cpu != NOCPU) { + isrc = arg; + sx_xlock(&intr_table_lock); + isrc->is_pic->pic_assign_cpu(isrc, cpu_apic_ids[cpu]); + sx_xunlock(&intr_table_lock); + } + return (0); +#else + return (EOPNOTSUPP); +#endif +} + static void intrcnt_setname(const char *name, int index) { @@ -542,15 +567,11 @@ static int current_cpu; static void intr_assign_next_cpu(struct intsrc *isrc) { - struct pic *pic; - u_int apic_id; /* * Assign this source to a local APIC in a round-robin fashion. */ - pic = isrc->is_pic; - apic_id = cpu_apic_ids[current_cpu]; - pic->pic_assign_cpu(isrc, apic_id); + isrc->is_pic->pic_assign_cpu(isrc, cpu_apic_ids[current_cpu]); do { current_cpu++; if (current_cpu > mp_maxid) @@ -558,6 +579,18 @@ intr_assign_next_cpu(struct intsrc *isrc) } while (!(intr_cpus & (1 << current_cpu))); } +/* Attempt to bind the specified IRQ to the specified CPU. */ +int +intr_bind(u_int vector, u_char cpu) +{ + struct intsrc *isrc; + + isrc = intr_lookup_source(vector); + if (isrc == NULL) + return (EINVAL); + return (intr_event_bind(isrc->is_event, cpu)); +} + /* * Add a CPU to our mask of valid CPUs that can be destinations of * interrupts. @@ -594,8 +627,18 @@ intr_shuffle_irqs(void *arg __unused) assign_cpu = 1; for (i = 0; i < NUM_IO_INTS; i++) { isrc = interrupt_sources[i]; - if (isrc != NULL && isrc->is_handlers > 0) - intr_assign_next_cpu(isrc); + if (isrc != NULL && isrc->is_handlers > 0) { + /* + * If this event is already bound to a CPU, + * then assign the source to that CPU instead + * of picking one via round-robin. + */ + if (isrc->is_event->ie_cpu != NOCPU) + isrc->is_pic->pic_assign_cpu(isrc, + cpu_apic_ids[isrc->is_event->ie_cpu]); + else + intr_assign_next_cpu(isrc); + } } sx_xunlock(&intr_table_lock); } diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h index 8b16c5e2fabc..7e1c43f65b90 100644 --- a/sys/amd64/include/intr_machdep.h +++ b/sys/amd64/include/intr_machdep.h @@ -137,6 +137,9 @@ void intr_add_cpu(u_int cpu); int intr_add_handler(const char *name, int vector, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep); +#ifdef SMP +int intr_bind(u_int vector, u_char cpu); +#endif int intr_config_intr(int vector, enum intr_trigger trig, enum intr_polarity pol); void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame); |
