summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorSophia Li <Sophia.Li@Sun.COM>2009-07-28 16:08:21 +0800
committerSophia Li <Sophia.Li@Sun.COM>2009-07-28 16:08:21 +0800
commit96f82fef09bdebba70a409640c49772b1cdf1a2a (patch)
tree50f8868b6b7c309a49a5866d0c951f4dcec0a4aa /usr
parent59f783ef68a5d9dc879272521eae58db83bf5f90 (diff)
downloadillumos-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.c40
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_introp.c23
-rw-r--r--usr/src/uts/i86xpv/io/psm/xpv_psm.c3
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);
}