Changeset View
Changeset View
Standalone View
Standalone View
sys/xen/xen_intr.c
Show First 20 Lines • Show All 390 Lines • ▼ Show 20 Lines | xen_intr_bind_isrc(struct xenisrc **isrcp, const struct xenisrc *params, | ||||
void *arg, enum intr_type flags, xen_intr_handle_t *port_handlep) | void *arg, enum intr_type flags, xen_intr_handle_t *port_handlep) | ||||
{ | { | ||||
struct xenisrc *isrc; | struct xenisrc *isrc; | ||||
u_int cpu; | u_int cpu; | ||||
int error; | int error; | ||||
*isrcp = NULL; | *isrcp = NULL; | ||||
if (port_handlep == NULL) { | if (port_handlep == NULL) { | ||||
xen_intr_handle_t discard; | |||||
printf("%s: %s: Bad event handle\n", intr_owner, __func__); | printf("%s: %s: Bad event handle\n", intr_owner, __func__); | ||||
return (EINVAL); | port_handlep = &discard; | ||||
error = EINVAL; | |||||
goto failearly; | |||||
} | } | ||||
isrc = xen_intr_alloc_isrc(params); | isrc = xen_intr_alloc_isrc(params); | ||||
if (isrc == NULL) | if (isrc == NULL) { | ||||
return (ENOSPC); | error = ENOSPC; | ||||
goto failearly; | |||||
} | |||||
refcount_init(&isrc->xi_refcount, 1); | refcount_init(&isrc->xi_refcount, 1); | ||||
cpu = isrc->xi_cpu; | cpu = isrc->xi_cpu; | ||||
mtx_lock(&xen_intr_isrc_lock); | mtx_lock(&xen_intr_isrc_lock); | ||||
if (xen_intr_port_to_isrc[isrc->xi_port] != NULL) { | if (xen_intr_port_to_isrc[isrc->xi_port] != NULL) { | ||||
xen_intr_port_to_isrc[isrc->xi_port]->xi_port = ~0U; | xen_intr_port_to_isrc[isrc->xi_port]->xi_port = ~0U; | ||||
isrc->xi_cpu = xen_intr_port_to_isrc[isrc->xi_port]->xi_cpu; | isrc->xi_cpu = xen_intr_port_to_isrc[isrc->xi_port]->xi_cpu; | ||||
} else | } else | ||||
isrc->xi_cpu = 0; | isrc->xi_cpu = 0; | ||||
Show All 9 Lines | if (cpu > mp_maxid) { | ||||
* By default all interrupts are assigned to vCPU#0 | * By default all interrupts are assigned to vCPU#0 | ||||
* unless specified otherwise, so shuffle them to balance | * unless specified otherwise, so shuffle them to balance | ||||
* the interrupt load. | * the interrupt load. | ||||
*/ | */ | ||||
cpu = intr_next_cpu(0); | cpu = intr_next_cpu(0); | ||||
} | } | ||||
error = xen_arch_intr_event_bind(isrc, cpu); | error = xen_arch_intr_event_bind(isrc, cpu); | ||||
if (error != 0) { /* *very* unlikely */ | if (error != 0) /* *very* unlikely */ | ||||
xen_intr_release_isrc(isrc); | goto failrelease; | ||||
return (error); | |||||
} | |||||
if (isrc->xi_cpu != cpu) { | if (isrc->xi_cpu != cpu) { | ||||
/* | /* | ||||
* Too early in the boot process for the generic interrupt | * Too early in the boot process for the generic interrupt | ||||
* code to perform the binding. Update our event channel | * code to perform the binding. Update our event channel | ||||
* masks manually so events can't fire on the wrong cpu | * masks manually so events can't fire on the wrong cpu | ||||
* during AP startup. | * during AP startup. | ||||
*/ | */ | ||||
xen_intr_assign_cpu(isrc, cpu); | xen_intr_assign_cpu(isrc, cpu); | ||||
} | } | ||||
#endif | #endif | ||||
if (filter == NULL && handler == NULL) { | if (filter == NULL && handler == NULL) { | ||||
/* | /* | ||||
* No filter/handler provided, leave the event channel | * No filter/handler provided, leave the event channel | ||||
* masked and without a valid handler, the caller is | * masked and without a valid handler, the caller is | ||||
* in charge of setting that up. | * in charge of setting that up. | ||||
*/ | */ | ||||
*isrcp = isrc; | *isrcp = isrc; | ||||
return (0); | return (0); | ||||
} | } | ||||
error = xen_intr_add_handler(intr_owner, filter, handler, arg, flags, | error = xen_intr_add_handler(intr_owner, filter, handler, arg, flags, | ||||
*port_handlep); | *port_handlep); | ||||
if (error != 0) { | if (error != 0) | ||||
xen_intr_release_isrc(isrc); | goto failrelease; | ||||
return (error); | |||||
} | |||||
*isrcp = isrc; | *isrcp = isrc; | ||||
return (0); | return (0); | ||||
failrelease: | |||||
xen_intr_release_isrc(isrc); | |||||
failearly: | |||||
*port_handlep = NULL; | |||||
return (error); | |||||
} | } | ||||
/** | /** | ||||
* Determine the event channel ports at the given section of the | * Determine the event channel ports at the given section of the | ||||
* event port bitmap which have pending events for the given cpu. | * event port bitmap which have pending events for the given cpu. | ||||
* | * | ||||
* \param pcpu The Xen interrupt pcpu data for the cpu being querried. | * \param pcpu The Xen interrupt pcpu data for the cpu being querried. | ||||
* \param sh The Xen shared info area. | * \param sh The Xen shared info area. | ||||
▲ Show 20 Lines • Show All 852 Lines • Show Last 20 Lines |