diff options
author | jhb <jhb@FreeBSD.org> | 2012-04-02 17:26:21 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-04-02 17:26:21 +0000 |
commit | f021ea5434f592e3851c6ac7ba55f702497922a1 (patch) | |
tree | 089a7b044405029969ebb09261922e032495eb37 /sys/x86 | |
parent | 17b84cf2382e9ad71907f9d8ce1ad2a7d692b6f6 (diff) | |
download | FreeBSD-src-f021ea5434f592e3851c6ac7ba55f702497922a1.zip FreeBSD-src-f021ea5434f592e3851c6ac7ba55f702497922a1.tar.gz |
Further tweak the changes made in r233709. The kernel doesn't permit
sleeping from a swi handler (even though in this case it would be ok), so
switch the refill and scanning SWI handlers to being tasks on a fast
taskqueue. Also, only schedule the refill task for a CMCI as an MC# can
fire at any time, so it should do the minimal amount of work needed and
avoid opportunities to deadlock before it panics (such as scheduling a
task it won't ever need in practice). To handle the case of an MC# only
finding recoverable errors (which should never happen), always try to
refill the event free list when the periodic scan executes.
MFC after: 2 weeks
Diffstat (limited to 'sys/x86')
-rw-r--r-- | sys/x86/x86/mca.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index 9887cc7..f1369cd 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/sysctl.h> #include <sys/systm.h> +#include <sys/taskqueue.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> #include <machine/cputypes.h> @@ -108,8 +109,9 @@ static int mca_freecount; static STAILQ_HEAD(, mca_internal) mca_records; static struct callout mca_timer; static int mca_ticks = 3600; /* Check hourly by default. */ +static struct taskqueue *mca_tq; +static struct task mca_refill_task, mca_scan_task; static struct mtx mca_lock; -static void *mca_refill_swi, *mca_scan_swi; #ifdef DEV_APIC static struct cmc_state **cmc_state; /* Indexed by cpuid, bank */ @@ -439,7 +441,7 @@ mca_fill_freelist(void) } static void -mca_refill(void *arg) +mca_refill(void *context, int pending) { mca_fill_freelist(); @@ -464,8 +466,6 @@ mca_record_entry(enum scan_mode mode, const struct mca_record *record) } STAILQ_REMOVE_HEAD(&mca_freelist, link); mca_freecount--; - if (mca_refill_swi != NULL) - swi_sched(mca_refill_swi, 0); } rec->rec = *record; @@ -473,6 +473,8 @@ mca_record_entry(enum scan_mode mode, const struct mca_record *record) STAILQ_INSERT_TAIL(&mca_records, rec, link); mca_count++; mtx_unlock_spin(&mca_lock); + if (mode == CMCI) + taskqueue_enqueue_fast(mca_tq, &mca_refill_task); } #ifdef DEV_APIC @@ -616,12 +618,13 @@ mca_scan(enum scan_mode mode) * them to the console. */ static void -mca_scan_cpus(void *arg) +mca_scan_cpus(void *context, int pending) { struct mca_internal *mca; struct thread *td; int count, cpu; + mca_fill_freelist(); td = curthread; count = 0; thread_lock(td); @@ -649,7 +652,7 @@ static void mca_periodic_scan(void *arg) { - swi_sched(mca_scan_swi, 1); + taskqueue_enqueue_fast(mca_tq, &mca_scan_task); callout_reset(&mca_timer, mca_ticks * hz, mca_periodic_scan, NULL); } @@ -663,23 +666,29 @@ sysctl_mca_scan(SYSCTL_HANDLER_ARGS) if (error) return (error); if (i) - swi_sched(mca_scan_swi, 1); + taskqueue_enqueue_fast(mca_tq, &mca_scan_task); return (0); } static void +mca_createtq(void *dummy) +{ + if (mca_banks <= 0) + return; + + mca_tq = taskqueue_create_fast("mca", M_WAITOK, + taskqueue_thread_enqueue, &mca_tq); + taskqueue_start_threads(&mca_tq, 1, PI_SWI(SWI_TQ), "mca taskq"); +} +SYSINIT(mca_createtq, SI_SUB_CONFIGURE, SI_ORDER_ANY, mca_createtq, NULL); + +static void mca_startup(void *dummy) { - struct intr_event *ie; - if (!mca_enabled || !(cpu_feature & CPUID_MCA)) + if (mca_banks <= 0) return; - ie = NULL; - swi_add(&ie, "mca:scan", mca_scan_cpus, NULL, SWI_TQ, INTR_MPSAFE, - &mca_scan_swi); - swi_add(&ie, "mca:refill", mca_refill, NULL, SWI_TQ, INTR_MPSAFE, - &mca_refill_swi); callout_reset(&mca_timer, mca_ticks * hz, mca_periodic_scan, NULL); } SYSINIT(mca_startup, SI_SUB_SMP, SI_ORDER_ANY, mca_startup, NULL); @@ -718,8 +727,10 @@ mca_setup(uint64_t mcg_cap) mca_banks = mcg_cap & MCG_CAP_COUNT; mtx_init(&mca_lock, "mca", NULL, MTX_SPIN); STAILQ_INIT(&mca_records); + TASK_INIT(&mca_scan_task, 0, mca_scan_cpus, NULL); callout_init(&mca_timer, CALLOUT_MPSAFE); STAILQ_INIT(&mca_freelist); + TASK_INIT(&mca_refill_task, 0, mca_refill, NULL); mca_fill_freelist(); SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, "count", CTLFLAG_RD, &mca_count, 0, "Record count"); |