Mercurial > illumos > illumos-gate
changeset 4329:35ac1e4ee309
6560134 niumx could lose interrupts during redistribution
author | jf137018 |
---|---|
date | Fri, 25 May 2007 13:25:30 -0700 |
parents | fe6ac87d8e60 |
children | dfd7c5e23fa0 |
files | usr/src/uts/sun4v/io/niumx/niumx.c |
diffstat | 1 files changed, 41 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/sun4v/io/niumx/niumx.c Fri May 25 10:59:41 2007 -0700 +++ b/usr/src/uts/sun4v/io/niumx/niumx.c Fri May 25 13:25:30 2007 -0700 @@ -166,6 +166,9 @@ return (mod_info(&modlinkage, modinfop)); } + +hrtime_t niumx_intr_timeout = 2ull * NANOSEC; /* 2 seconds in nanoseconds */ + void niumx_intr_dist(void *arg) { @@ -178,7 +181,9 @@ for (; i < NIUMX_MAX_INTRS; i++, ih_p++) { sysino_t sysino = ih_p->ih_sysino; cpuid_t cpuid; - int intr_state; + int intr_state, state; + hrtime_t start; + dev_info_t *dip = ih_p->ih_dip; if (!sysino || /* sequence is significant */ (hvio_intr_getvalid(sysino, &intr_state) != H_EOK) || (intr_state == HV_INTR_NOTVALID) || @@ -186,6 +191,21 @@ continue; (void) hvio_intr_setvalid(sysino, HV_INTR_NOTVALID); + + /* check for pending interrupts, busy wait if so */ + for (start = gethrtime(); !panicstr && + (hvio_intr_getstate(sysino, &state) == H_EOK) && + (state == HV_INTR_DELIVERED_STATE); /* */) { + if (gethrtime() - start > niumx_intr_timeout) { + cmn_err(CE_WARN, "%s%d: niumx_intr_dist: " + "pending interrupt (%x,%lx) timedout\n", + ddi_driver_name(dip), ddi_get_instance(dip), + ih_p->ih_inum, sysino); + (void) hvio_intr_setstate(sysino, + HV_INTR_IDLE_STATE); + break; + } + } (void) hvio_intr_settarget(sysino, cpuid); (void) hvio_intr_setvalid(sysino, HV_INTR_VALID); ih_p->ih_cpuid = cpuid; @@ -895,10 +915,10 @@ ddi_intr_handle_impl_t *hdlp) { niumx_ih_t *ih_p; - cpuid_t curr_cpu; devino_t *inos_p; - int inoslen, ret = DDI_SUCCESS; - uint64_t hvret; + int inoslen, ret = DDI_SUCCESS, state; + hrtime_t start; + sysino_t sysino; ASSERT(hdlp->ih_inum < NIUMX_MAX_INTRS); @@ -909,21 +929,26 @@ goto fail1; } ih_p = niumx_ihtable + inos_p[hdlp->ih_inum]; - DBG(DBG_R_INTX, dip, "removing (%x,%x)\n", ih_p->ih_inum, - ih_p->ih_sysino); + sysino = ih_p->ih_sysino; + DBG(DBG_R_INTX, dip, "removing (%x,%x)\n", ih_p->ih_inum, sysino); + + (void) hvio_intr_setvalid(sysino, HV_INTR_NOTVALID); - /* Get the current cpu */ - if ((hvret = hvio_intr_gettarget(ih_p->ih_sysino, &curr_cpu)) - != H_EOK) { - DBG(DBG_R_INTX, dip, "hvio_intr_gettarget failed, ret 0x%x\n", - hvret); - ret = DDI_FAILURE; - goto fail2; + /* check for pending interrupts, busy wait if so */ + for (start = gethrtime(); !panicstr && + (hvio_intr_getstate(sysino, &state) == H_EOK) && + (state == HV_INTR_DELIVERED_STATE); /* */) { + if (gethrtime() - start > niumx_intr_timeout) { + cmn_err(CE_WARN, "%s%d: niumx_intr_dist: " + "pending interrupt (%x,%lx) timedout\n", + ddi_driver_name(dip), ddi_get_instance(dip), + ih_p->ih_inum, sysino); + ret = DDI_FAILURE; + goto fail2; + } } - intr_dist_cpuid_rem_device_weight(ih_p->ih_cpuid, rdip); - - hdlp->ih_vector = ih_p->ih_sysino; + hdlp->ih_vector = (uint32_t)sysino; if (hdlp->ih_vector != NULL) i_ddi_rem_ivintr(hdlp); fail2: