diff options
author | Sophia Li <Sophia.Li@Sun.COM> | 2009-07-28 16:08:21 +0800 |
---|---|---|
committer | Sophia Li <Sophia.Li@Sun.COM> | 2009-07-28 16:08:21 +0800 |
commit | 96f82fef09bdebba70a409640c49772b1cdf1a2a (patch) | |
tree | 50f8868b6b7c309a49a5866d0c951f4dcec0a4aa /usr | |
parent | 59f783ef68a5d9dc879272521eae58db83bf5f90 (diff) | |
download | illumos-joyent-96f82fef09bdebba70a409640c49772b1cdf1a2a.tar.gz |
6773806 ddi_intr_set_pri always fail due to the bug in ddi_intr_alloc()
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/i86pc/io/pci/pci_common.c | 40 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/pcplusmp/apic_introp.c | 23 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/io/psm/xpv_psm.c | 3 |
3 files changed, 50 insertions, 16 deletions
diff --git a/usr/src/uts/i86pc/io/pci/pci_common.c b/usr/src/uts/i86pc/io/pci/pci_common.c index e9ddc98526..3dfb5fdce7 100644 --- a/usr/src/uts/i86pc/io/pci/pci_common.c +++ b/usr/src/uts/i86pc/io/pci/pci_common.c @@ -451,16 +451,40 @@ SUPPORTED_TYPES_OUT: if (psm_intr_ops == NULL) return (DDI_FAILURE); + isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum); + ispec = (struct intrspec *)isp; + if (ispec == NULL) + return (DDI_FAILURE); + + /* For fixed interrupts */ + if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) { + /* if interrupt is shared, return failure */ + ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; + psm_rval = (*psm_intr_ops)(rdip, hdlp, + PSM_INTR_OP_GET_SHARED, &psm_status); + /* + * For fixed interrupts, the irq may not have been + * allocated when SET_PRI is called, and the above + * GET_SHARED op may return PSM_FAILURE. This is not + * a real error and is ignored below. + */ + if ((psm_rval != PSM_FAILURE) && (psm_status == 1)) { + DDI_INTR_NEXDBG((CE_CONT, + "pci_common_intr_ops: " + "dip 0x%p cannot setpri, psm_rval=%d," + "psm_status=%d\n", (void *)rdip, psm_rval, + psm_status)); + return (DDI_FAILURE); + } + } + /* Change the priority */ if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) == PSM_FAILURE) return (DDI_FAILURE); /* update ispec */ - isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum); - ispec = (struct intrspec *)isp; - if (ispec) - ispec->intrspec_pri = *(int *)result; + ispec->intrspec_pri = *(int *)result; break; case DDI_INTROP_ADDISR: /* update ispec */ @@ -768,8 +792,10 @@ pci_enable_intr(dev_info_t *pdip, dev_info_t *rdip, ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum); if (ispec == NULL) return (DDI_FAILURE); - if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) + if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) { ispec->intrspec_vec = inum; + ispec->intrspec_pri = hdlp->ih_pri; + } ihdl_plat_datap->ip_ispecp = ispec; /* translate the interrupt if needed */ @@ -802,8 +828,10 @@ pci_disable_intr(dev_info_t *pdip, dev_info_t *rdip, ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum); if (ispec == NULL) return; - if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) + if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) { ispec->intrspec_vec = inum; + ispec->intrspec_pri = hdlp->ih_pri; + } ihdl_plat_datap->ip_ispecp = ispec; /* translate the interrupt if needed */ diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c index 4d5e054b5e..337de12269 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c +++ b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c @@ -1045,27 +1045,33 @@ apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, case PSM_INTR_OP_GET_SHARED: if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) return (PSM_FAILURE); + ispec = ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp; if ((irqp = apic_find_irq(dip, ispec, hdlp->ih_type)) == NULL) return (PSM_FAILURE); - *result = irqp->airq_share ? 1: 0; + *result = (irqp->airq_share > 1) ? 1: 0; break; case PSM_INTR_OP_SET_PRI: old_priority = hdlp->ih_pri; /* save old value */ new_priority = *(int *)result; /* try the new value */ - /* First, check if "hdlp->ih_scratch1" vectors exist? */ - if (apic_navail_vector(dip, new_priority) < hdlp->ih_scratch1) - return (PSM_FAILURE); + if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) { + return (PSM_SUCCESS); + } /* Now allocate the vectors */ - if (hdlp->ih_type == DDI_INTR_TYPE_MSI) + if (hdlp->ih_type == DDI_INTR_TYPE_MSI) { + /* SET_PRI does not support the case of multiple MSI */ + if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) > 1) + return (PSM_FAILURE); + count_vec = apic_alloc_msi_vectors(dip, hdlp->ih_inum, - hdlp->ih_scratch1, new_priority, + 1, new_priority, DDI_INTR_ALLOC_STRICT); - else + } else { count_vec = apic_alloc_msix_vectors(dip, hdlp->ih_inum, - hdlp->ih_scratch1, new_priority, + 1, new_priority, DDI_INTR_ALLOC_STRICT); + } /* Did we get new vectors? */ if (!count_vec) @@ -1074,7 +1080,6 @@ apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, /* Finally, free the previously allocated vectors */ apic_free_vectors(dip, hdlp->ih_inum, count_vec, old_priority, hdlp->ih_type); - hdlp->ih_pri = new_priority; /* set the new value */ break; case PSM_INTR_OP_SET_CPU: case PSM_INTR_OP_GRP_SET_CPU: diff --git a/usr/src/uts/i86xpv/io/psm/xpv_psm.c b/usr/src/uts/i86xpv/io/psm/xpv_psm.c index ba9093adc6..f2f223d270 100644 --- a/usr/src/uts/i86xpv/io/psm/xpv_psm.c +++ b/usr/src/uts/i86xpv/io/psm/xpv_psm.c @@ -738,10 +738,11 @@ xen_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, if (DOMAIN_IS_INITDOMAIN(xen_info)) { if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) return (PSM_FAILURE); + ispec = ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp; if ((irqp = apic_find_irq(dip, ispec, hdlp->ih_type)) == NULL) return (PSM_FAILURE); - *result = irqp->airq_share ? 1: 0; + *result = (irqp->airq_share > 1) ? 1: 0; } else { return (PSM_FAILURE); } |