diff options
Diffstat (limited to 'usr/src/uts/sun4')
-rw-r--r-- | usr/src/uts/sun4/io/px/px_ib.c | 19 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/px/px_intr.c | 44 |
2 files changed, 53 insertions, 10 deletions
diff --git a/usr/src/uts/sun4/io/px/px_ib.c b/usr/src/uts/sun4/io/px/px_ib.c index 9355a15741..90fec6ae2c 100644 --- a/usr/src/uts/sun4/io/px/px_ib.c +++ b/usr/src/uts/sun4/io/px/px_ib.c @@ -699,14 +699,6 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p) /* Disable the interrupt */ PX_INTR_DISABLE(px_p->px_dip, sysino); - if (ipil_p->ipil_ih_size == 1) { - if (ih_lst != ih_p) - goto not_found; - - /* No need to set head/tail as ino_p will be freed */ - goto reset; - } - /* Busy wait on pending interrupt */ for (start_time = gethrtime(); !panicstr && ((ret = px_lib_intr_getstate(dip, sysino, &intr_state)) @@ -727,7 +719,8 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p) * because of jabber we need to clear the pending state in case the * jabber has gone away. */ - if (ino_p->ino_unclaimed_intrs > px_unclaimed_intr_max) { + if (ret == DDI_SUCCESS && + ino_p->ino_unclaimed_intrs > px_unclaimed_intr_max) { cmn_err(CE_WARN, "%s%d: px_ib_ino_rem_intr: " "ino 0x%x has been unblocked", ddi_driver_name(dip), ddi_get_instance(dip), ino); @@ -743,6 +736,14 @@ px_ib_ino_rem_intr(px_t *px_p, px_ino_pil_t *ipil_p, px_ih_t *ih_p) return (ret); } + if (ipil_p->ipil_ih_size == 1) { + if (ih_lst != ih_p) + goto not_found; + + /* No need to set head/tail as ino_p will be freed */ + goto reset; + } + /* Search the link list for ih_p */ for (i = 0; (i < ipil_p->ipil_ih_size) && (ih_lst->ih_next != ih_p); i++, ih_lst = ih_lst->ih_next) diff --git a/usr/src/uts/sun4/io/px/px_intr.c b/usr/src/uts/sun4/io/px/px_intr.c index 4248faf4e4..50999acc39 100644 --- a/usr/src/uts/sun4/io/px/px_intr.c +++ b/usr/src/uts/sun4/io/px/px_intr.c @@ -952,6 +952,7 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip, px_ino_pil_t *ipil_p, *ipil_list; int32_t weight; int ret = DDI_SUCCESS; + cpuid_t curr_cpu; ino = hdlp->ih_vector; @@ -968,7 +969,7 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip, ino_p = px_ib_locate_ino(ib_p, ino); ipil_list = ino_p ? ino_p->ino_ipil_p : NULL; - /* Sharing ino */ + /* Sharing the INO using a PIL that already exists */ if (ino_p && (ipil_p = px_ib_ino_locate_ipil(ino_p, hdlp->ih_pri))) { if (px_ib_intr_locate_ih(ipil_p, rdip, hdlp->ih_inum, 0, 0)) { DBG(DBG_A_INTX, dip, "px_add_intx_intr: " @@ -988,6 +989,44 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip, goto ino_done; } + /* Sharing the INO using a new PIL */ + if (ipil_list != NULL) { + intr_state_t intr_state; + hrtime_t start_time; + + /* + * disable INO to avoid lopil race condition with + * px_intx_intr + */ + + if ((ret = px_lib_intr_gettarget(dip, ino_p->ino_sysino, + &curr_cpu)) != DDI_SUCCESS) { + DBG(DBG_IB, dip, + "px_add_intx_intr px_intr_gettarget() failed\n"); + + goto fail1; + } + + /* Disable the interrupt */ + PX_INTR_DISABLE(dip, ino_p->ino_sysino); + + /* Busy wait on pending interrupt */ + for (start_time = gethrtime(); !panicstr && + ((ret = px_lib_intr_getstate(dip, ino_p->ino_sysino, + &intr_state)) == DDI_SUCCESS) && + (intr_state == INTR_DELIVERED_STATE); /* */) { + if (gethrtime() - start_time > px_intrpend_timeout) { + cmn_err(CE_WARN, "%s%d: px_add_intx_intr: " + "pending sysino 0x%lx(ino 0x%x) timeout", + ddi_driver_name(dip), ddi_get_instance(dip), + ino_p->ino_sysino, ino_p->ino_ino); + + ret = DDI_FAILURE; + goto fail1; + } + } + } + if (hdlp->ih_pri == 0) hdlp->ih_pri = pci_class_to_pil(rdip); @@ -1025,6 +1064,9 @@ px_add_intx_intr(dev_info_t *dip, dev_info_t *rdip, /* Enable interrupt */ px_ib_intr_enable(px_p, ino_p->ino_cpuid, ino); + } else { + /* Re-enable interrupt */ + PX_INTR_ENABLE(dip, ino_p->ino_sysino, curr_cpu); } ino_done: |