Index: sys/x86/xen/xen_intr.c =================================================================== --- sys/x86/xen/xen_intr.c +++ sys/x86/xen/xen_intr.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,7 @@ u_int xi_activehi:1; u_int xi_edgetrigger:1; u_int xi_masked:1; + volatile u_int xi_refcount; }; static void xen_intr_suspend(struct pic *); @@ -325,6 +327,7 @@ (type == EVTCHN_TYPE_PIRQ) ? &xen_intr_pirq_pic : &xen_intr_pic; isrc->xi_vector = vector; isrc->xi_type = type; + refcount_init(&isrc->xi_refcount, 1); intr_register_source(&isrc->xi_intsrc); mtx_lock(&xen_intr_isrc_lock); @@ -343,7 +346,12 @@ { mtx_lock(&xen_intr_isrc_lock); + if (refcount_release(&isrc->xi_refcount) == 0) { + mtx_unlock(&xen_intr_isrc_lock); + return (0); + } if (isrc->xi_intsrc.is_handlers != 0) { + refcount_acquire(&isrc->xi_refcount); mtx_unlock(&xen_intr_isrc_lock); return (EBUSY); } @@ -1563,6 +1571,33 @@ return (error); } +int +xen_intr_get_reference(evtchn_port_t port) +{ + + if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS) + return (EINVAL); + + mtx_lock(&xen_intr_isrc_lock); + if (xen_intr_port_to_isrc[port] == NULL) { + mtx_unlock(&xen_intr_isrc_lock); + return (EINVAL); + } + refcount_acquire(&xen_intr_port_to_isrc[port]->xi_refcount); + mtx_unlock(&xen_intr_isrc_lock); + return (0); +} + +int +xen_intr_put_reference(evtchn_port_t port) +{ + + if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS || + xen_intr_port_to_isrc[port] == NULL) + return (EINVAL); + return (xen_intr_release_isrc(xen_intr_port_to_isrc[port])); +} + #ifdef DDB static const char * xen_intr_print_type(enum evtchn_type type) Index: sys/xen/xen_intr.h =================================================================== --- sys/xen/xen_intr.h +++ sys/xen/xen_intr.h @@ -263,4 +263,15 @@ driver_intr_t handler, void *arg, enum intr_type flags, xen_intr_handle_t handle); +/** + * Get and put references to an event channel port + * + * \param port Event channel port to which we get or put + * a reference + * + * \returns 0 on success, otherwise an errno. + */ +int xen_intr_get_reference(evtchn_port_t port); +int xen_intr_put_reference(evtchn_port_t port); + #endif /* _XEN_INTR_H_ */