Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -338,6 +338,7 @@ struct evtchn_close close = { .port = isrc->xi_port }; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) panic("EVTCHNOP_close failed"); + isrc->xi_close = 0; /* mark as closed */ } xen_intr_port_to_isrc[isrc->xi_port] = NULL; @@ -394,17 +395,23 @@ *isrcp = NULL; if (port_handlep == NULL) { printf("%s: %s: Bad event handle\n", intr_owner, __func__); - return (EINVAL); + error = EINVAL; + goto fail; } isrc = xen_intr_alloc_isrc(params); - if (isrc == NULL) - return (ENOSPC); + if (isrc == NULL) { + error = ENOSPC; + goto fail; + } mtx_lock(&xen_intr_isrc_lock); xen_intr_port_to_isrc[isrc->xi_port] = isrc; refcount_init(&isrc->xi_refcount, 1); mtx_unlock(&xen_intr_isrc_lock); + /* Now owned by isrc structure */ + params = isrc; + /* Assign the opaque handler */ *port_handlep = xen_intr_handle_from_isrc(isrc); @@ -437,6 +444,15 @@ } *isrcp = isrc; return (0); + +fail: + if (params->xi_close) { + evtchn_close_t close = { .port = params->xi_port }; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) + panic("EVTCHNOP_close failed"); + /* params->xi_close = 0; ** mark as closed */ + } + return (error); } /** @@ -950,7 +966,7 @@ enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; - struct xenisrc params = { .xi_type = EVTCHN_TYPE_PORT, }; + struct xenisrc params = { .xi_type = EVTCHN_TYPE_PORT, .xi_close = 1, }; struct evtchn_alloc_unbound alloc_unbound; int error; @@ -967,18 +983,9 @@ } params.xi_port = alloc_unbound.port; - error = xen_intr_bind_isrc(&isrc, ¶ms, + return (xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, flags, - port_handlep); - if (error != 0) { - evtchn_close_t close = { .port = alloc_unbound.port }; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) - panic("EVTCHNOP_close failed"); - return (error); - } - - isrc->xi_close = 1; - return (0); + port_handlep)); } int @@ -989,6 +996,11 @@ struct xenisrc *isrc; struct xenisrc params = { .xi_type = EVTCHN_TYPE_PORT, + /* + * The Event Channel API opened this port, so it is + * responsible for closing it automatically on unbind. + */ + .xi_close = 1, }; struct evtchn_bind_interdomain bind_interdomain; int error; @@ -1006,22 +1018,9 @@ } params.xi_port = bind_interdomain.local_port; - error = xen_intr_bind_isrc(&isrc, ¶ms, + return (xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, - flags, port_handlep); - if (error) { - evtchn_close_t close = { .port = bind_interdomain.local_port }; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) - panic("EVTCHNOP_close failed"); - return (error); - } - - /* - * The Event Channel API opened this port, so it is - * responsible for closing it automatically on unbind. - */ - isrc->xi_close = 1; - return (0); + flags, port_handlep)); } int