Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -726,8 +726,6 @@ return; } - xen_intr_port_to_isrc[isrc->xi_port] = isrc; - #ifdef SMP isrc->xi_cpu = 0; error = xen_intr_assign_cpu(&isrc->xi_intsrc, @@ -736,8 +734,6 @@ panic("unable to bind xen intr#%d to CPU#%d: %d", isrc->xi_virq, cpu, error); #endif - - evtchn_unmask_port(isrc->xi_port); } /** @@ -747,7 +743,6 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled) { shared_info_t *s = HYPERVISOR_shared_info; - struct xenisrc *isrc; u_int isrc_idx; int i; @@ -767,17 +762,41 @@ for (i = 0; i < nitems(s->evtchn_mask); i++) atomic_store_rel_long(&s->evtchn_mask[i], ~0); - /* Remove port -> isrc mappings */ - memset(xen_intr_port_to_isrc, 0, sizeof(xen_intr_port_to_isrc)); + /* Clear existing port mappings */ + for (isrc_idx = 0; isrc_idx < NR_EVENT_CHANNELS; ++isrc_idx) + if (xen_intr_port_to_isrc[isrc_idx] != NULL) + xen_intr_port_to_isrc[isrc_idx]->xi_port = ~0; - /* Free unused isrcs and rebind VIRQs and IPIs */ - for (isrc_idx = 0; isrc_idx < xen_intr_auto_vector_count; isrc_idx++) { - u_int vector; + /* Remap in-use isrcs, using xen_intr_port_to_isrc as listing */ + for (isrc_idx = 0; isrc_idx < NR_EVENT_CHANNELS; ++isrc_idx) { + struct xenisrc *cur = xen_intr_port_to_isrc[isrc_idx]; - vector = first_evtchn_irq + isrc_idx; - isrc = (struct xenisrc *)intr_lookup_source(vector); - if (isrc != NULL) - xen_intr_rebind_isrc(isrc); + /* empty or entry already taken care of */ + if (cur == NULL || cur->xi_port < NR_EVENT_CHANNELS) + continue; + + xen_intr_port_to_isrc[isrc_idx] = NULL; + + do { + struct xenisrc *next; + KASSERT(cur->xi_port >= NR_EVENT_CHANNELS, + ("%s(): Multiple channels on single intr?", + __func__)); + + xen_intr_rebind_isrc(cur); + + /* channel type which doesn't get rebound here */ + if (cur->xi_port >= NR_EVENT_CHANNELS) + break; + + next = xen_intr_port_to_isrc[cur->xi_port]; + + xen_intr_port_to_isrc[cur->xi_port] = cur; + + evtchn_unmask_port(cur->xi_port); + + cur = next; + } while (cur != NULL); } }