summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/pciex/pcieb.c2
-rw-r--r--usr/src/uts/i86pc/io/isa.c7
-rw-r--r--usr/src/uts/i86pc/io/mp_platform_common.c90
-rw-r--r--usr/src/uts/i86pc/io/pci/pci_common.c6
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic.c4
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_introp.c30
-rw-r--r--usr/src/uts/i86pc/io/rootnex.c7
-rw-r--r--usr/src/uts/i86pc/sys/apic.h4
8 files changed, 82 insertions, 68 deletions
diff --git a/usr/src/uts/common/io/pciex/pcieb.c b/usr/src/uts/common/io/pciex/pcieb.c
index 66141bf523..264f6e4904 100644
--- a/usr/src/uts/common/io/pciex/pcieb.c
+++ b/usr/src/uts/common/io/pciex/pcieb.c
@@ -60,7 +60,7 @@
int pcieb_die = PF_ERR_FATAL_FLAGS;
/* flag to turn on MSI support */
-int pcieb_enable_msi = 0;
+int pcieb_enable_msi = 1;
#if defined(DEBUG)
uint_t pcieb_dbg_print = 0;
diff --git a/usr/src/uts/i86pc/io/isa.c b/usr/src/uts/i86pc/io/isa.c
index bcbe04699b..8080b0c2b1 100644
--- a/usr/src/uts/i86pc/io/isa.c
+++ b/usr/src/uts/i86pc/io/isa.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -833,8 +833,9 @@ isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
}
#endif
((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
- (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
- (int *)&hdlp->ih_vector);
+ if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
+ (int *)&hdlp->ih_vector) == PSM_FAILURE)
+ return (DDI_FAILURE);
/* Add the interrupt handler */
if (!add_avintr((void *)hdlp, ispec->intrspec_pri,
diff --git a/usr/src/uts/i86pc/io/mp_platform_common.c b/usr/src/uts/i86pc/io/mp_platform_common.c
index e218415adb..962741ce2e 100644
--- a/usr/src/uts/i86pc/io/mp_platform_common.c
+++ b/usr/src/uts/i86pc/io/mp_platform_common.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1549,12 +1549,12 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
uint32_t bind_cpu;
int intin, irqindex;
int ioapic_ix;
- apic_irq_t *irqptr, *irqheadptr, *irqp;
+ apic_irq_t *irqptr, *preirqptr, *irqheadptr, *irqp;
ulong_t iflag;
mutex_enter(&airq_mutex);
irqindex = IRQINDEX(irqno);
- irqptr = irqheadptr = apic_irq_table[irqindex];
+ irqptr = preirqptr = irqheadptr = apic_irq_table[irqindex];
DDI_INTR_IMPLDBG((CE_CONT, "apic_delspl: dip=0x%p type=%d irqno=0x%x "
"vector=0x%x\n", (void *)irqptr->airq_dip,
@@ -1563,6 +1563,7 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
while (irqptr) {
if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno)
break;
+ preirqptr = irqptr;
irqptr = irqptr->airq_next;
}
ASSERT(irqptr);
@@ -1571,6 +1572,10 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
mutex_exit(&airq_mutex);
+ /*
+ * If there are more interrupts at a higher IPL, we don't need
+ * to disable anything.
+ */
if (ipl < max_ipl)
return (PSM_SUCCESS);
@@ -1582,7 +1587,7 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
/*
* Clear irq_struct. If two devices shared an intpt
* line & 1 unloaded before picinit, we are hosed. But, then
- * we hope the machine will ...
+ * we hope the machine will survive.
*/
irqptr->airq_mps_intr_index = FREE_INDEX;
irqptr->airq_temp_cpu = IRQ_UNINIT;
@@ -1590,8 +1595,8 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
return (PSM_SUCCESS);
}
/*
- * Downgrade vector to new max_ipl if needed.If we cannot allocate,
- * use old IPL. Not very elegant, but then we hope ...
+ * Downgrade vector to new max_ipl if needed. If we cannot allocate,
+ * use old IPL. Not very elegant, but it should work.
*/
if ((irqptr->airq_ipl != max_ipl) && (max_ipl != PSM_INVALID_IPL) &&
!ioapic_mask_workaround[irqptr->airq_ioapicindex]) {
@@ -1705,6 +1710,9 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
}
}
+ /*
+ * If there are still active interrupts, we are done.
+ */
if (irqptr->airq_share)
return (PSM_SUCCESS);
@@ -1754,7 +1762,10 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
apic_vt_ops->apic_intrr_free_entry(irqptr);
#endif
- if (max_ipl == PSM_INVALID_IPL) {
+ /*
+ * This irq entry is the only one in the chain.
+ */
+ if (irqheadptr->airq_next == NULL) {
ASSERT(irqheadptr == irqptr);
bind_cpu = irqptr->airq_temp_cpu;
if (((uint32_t)bind_cpu != IRQ_UNBOUND) &&
@@ -1774,36 +1785,25 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
apic_free_vector(irqptr->airq_vector);
return (PSM_SUCCESS);
}
+
+ /*
+ * If we get here, we are sharing the vector and there are more than
+ * one active irq entries in the chain.
+ */
lock_clear(&apic_ioapic_lock);
intr_restore(iflag);
mutex_enter(&airq_mutex);
- if ((irqptr == apic_irq_table[irqindex])) {
- apic_irq_t *oldirqptr;
- /* Move valid irq entry to the head */
- irqheadptr = oldirqptr = irqptr;
- irqptr = irqptr->airq_next;
- ASSERT(irqptr);
- while (irqptr) {
- if (irqptr->airq_mps_intr_index != FREE_INDEX)
- break;
- oldirqptr = irqptr;
- irqptr = irqptr->airq_next;
- }
- /* remove all invalid ones from the beginning */
- apic_irq_table[irqindex] = irqptr;
- /*
- * and link them back after the head. The invalid ones
- * begin with irqheadptr and end at oldirqptr
- */
- oldirqptr->airq_next = irqptr->airq_next;
- irqptr->airq_next = irqheadptr;
+ /* Remove the irq entry from the chain */
+ if (irqptr == irqheadptr) { /* The irq entry is at the head */
+ apic_irq_table[irqindex] = irqptr->airq_next;
+ } else {
+ preirqptr->airq_next = irqptr->airq_next;
}
+ /* Free the irq entry */
+ kmem_free(irqptr, sizeof (apic_irq_t));
mutex_exit(&airq_mutex);
- irqptr->airq_temp_cpu = IRQ_UNINIT;
- irqptr->airq_mps_intr_index = FREE_INDEX;
-
return (PSM_SUCCESS);
}
@@ -1812,6 +1812,10 @@ apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl)
* called only from apic_intr_ops(). With the new ADII framework,
* the priority can no longer be retrieved through i_ddi_get_intrspec().
* It has to be passed in from the caller.
+ *
+ * Return value:
+ * Success: irqno for the given device
+ * Failure: -1
*/
int
apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type)
@@ -1894,31 +1898,27 @@ apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type)
busid = (int)apic_single_pci_busid;
if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS)
- goto nonpci;
+ return (-1);
ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA;
pci_config_teardown(&cfg_handle);
if (apic_enable_acpi && !apic_use_acpi_madt_only) {
if (apic_acpi_translate_pci_irq(dip, busid, devid,
ipin, &pci_irq, &intr_flag) != ACPI_PSM_SUCCESS)
- goto nonpci;
+ return (-1);
intr_flag.bustype = child_is_pciex ? BUS_PCIE : BUS_PCI;
- if ((newirq = apic_setup_irq_table(dip, pci_irq, NULL,
- ispec, &intr_flag, type)) == -1)
- goto nonpci;
- return (newirq);
+ return (apic_setup_irq_table(dip, pci_irq, NULL, ispec,
+ &intr_flag, type));
} else {
pci_irq = ((devid & 0x1f) << 2) | (ipin & 0x3);
if ((intrp = apic_find_io_intr_w_busid(pci_irq, busid))
== NULL) {
if ((pci_irq = apic_handle_pci_pci_bridge(dip,
devid, ipin, &intrp)) == -1)
- goto nonpci;
+ return (-1);
}
- if ((newirq = apic_setup_irq_table(dip, pci_irq, intrp,
- ispec, NULL, type)) == -1)
- goto nonpci;
- return (newirq);
+ return (apic_setup_irq_table(dip, pci_irq, intrp, ispec,
+ NULL, type));
}
} else if (strcmp(dev_type, "isa") == 0)
bustype = BUS_ISA;
@@ -1985,7 +1985,7 @@ nonpci:
defconf:
newirq = apic_setup_irq_table(dip, irqno, NULL, ispec, NULL, type);
if (newirq == -1)
- return (newirq);
+ return (-1);
ASSERT(IRQINDEX(newirq) == irqno);
ASSERT(apic_irq_table[irqno]);
return (newirq);
@@ -2212,7 +2212,12 @@ apic_share_vector(int irqno, iflag_t *intr_flagp, short intr_index, int ipl,
}
/*
+ * Allocate/Initialize the apic_irq_table[] entry for given irqno. If the entry
+ * is used already, we will try to allocate a new irqno.
*
+ * Return value:
+ * Success: irqno
+ * Failure: -1
*/
static int
apic_setup_irq_table(dev_info_t *dip, int irqno, struct apic_io_intr *intrp,
@@ -2681,6 +2686,7 @@ apic_allocate_irq(int irq)
psm_name);
return (-1);
}
+ apic_irq_table[freeirq]->airq_temp_cpu = IRQ_UNINIT;
apic_irq_table[freeirq]->airq_mps_intr_index = FREE_INDEX;
}
return (freeirq);
diff --git a/usr/src/uts/i86pc/io/pci/pci_common.c b/usr/src/uts/i86pc/io/pci/pci_common.c
index 03840580a3..ab74bd7bed 100644
--- a/usr/src/uts/i86pc/io/pci/pci_common.c
+++ b/usr/src/uts/i86pc/io/pci/pci_common.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -813,7 +813,9 @@ pci_enable_intr(dev_info_t *pdip, dev_info_t *rdip,
ihdl_plat_datap->ip_ispecp = ispec;
/* translate the interrupt if needed */
- (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq);
+ if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &irq) ==
+ PSM_FAILURE)
+ return (DDI_FAILURE);
DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x irq=%x\n",
hdlp->ih_pri, irq));
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic.c b/usr/src/uts/i86pc/io/pcplusmp/apic.c
index df0000ba7b..8aad513ed6 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1470,7 +1470,7 @@ apic_get_ipivect(int ipl, int type)
uchar_t vector;
int irq;
- if (irq = apic_allocate_irq(APIC_VECTOR(ipl))) {
+ if ((irq = apic_allocate_irq(APIC_VECTOR(ipl))) != -1) {
if (vector = apic_allocate_vector(ipl, irq, 1)) {
apic_irq_table[irq]->airq_mps_intr_index =
RESERVE_INDEX;
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
index b242aa0255..c79fa97dc9 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -268,19 +268,21 @@ apic_find_irq(dev_info_t *dip, struct intrspec *ispec, int type)
ispec->intrspec_pri, type));
for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) {
- if ((irqp = apic_irq_table[i]) == NULL)
- continue;
- if ((irqp->airq_dip == dip) &&
- (irqp->airq_origirq == ispec->intrspec_vec) &&
- (irqp->airq_ipl == ispec->intrspec_pri)) {
- if (type == DDI_INTR_TYPE_MSI) {
- if (irqp->airq_mps_intr_index == MSI_INDEX)
- return (irqp);
- } else if (type == DDI_INTR_TYPE_MSIX) {
- if (irqp->airq_mps_intr_index == MSIX_INDEX)
+ for (irqp = apic_irq_table[i]; irqp; irqp = irqp->airq_next) {
+ if ((irqp->airq_dip == dip) &&
+ (irqp->airq_origirq == ispec->intrspec_vec) &&
+ (irqp->airq_ipl == ispec->intrspec_pri)) {
+ if (type == DDI_INTR_TYPE_MSI) {
+ if (irqp->airq_mps_intr_index ==
+ MSI_INDEX)
+ return (irqp);
+ } else if (type == DDI_INTR_TYPE_MSIX) {
+ if (irqp->airq_mps_intr_index ==
+ MSIX_INDEX)
+ return (irqp);
+ } else
return (irqp);
- } else
- return (irqp);
+ }
}
}
DDI_INTR_IMPLDBG((CE_CONT, "apic_find_irq: return NULL\n"));
@@ -1002,6 +1004,8 @@ apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp,
case PSM_INTR_OP_XLATE_VECTOR:
ispec = ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp;
*result = apic_introp_xlate(dip, ispec, hdlp->ih_type);
+ if (*result == -1)
+ return (PSM_FAILURE);
break;
case PSM_INTR_OP_GET_PENDING:
if ((irqp = apic_find_irq(dip, ispec, hdlp->ih_type)) == NULL)
diff --git a/usr/src/uts/i86pc/io/rootnex.c b/usr/src/uts/i86pc/io/rootnex.c
index e84bf3e626..e9cad41302 100644
--- a/usr/src/uts/i86pc/io/rootnex.c
+++ b/usr/src/uts/i86pc/io/rootnex.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1454,8 +1454,9 @@ rootnex_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
return (DDI_FAILURE);
((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
- (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
- (int *)&hdlp->ih_vector);
+ if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
+ (int *)&hdlp->ih_vector) == PSM_FAILURE)
+ return (DDI_FAILURE);
/* Add the interrupt handler */
if (!add_avintr((void *)hdlp, ispec->intrspec_pri,
diff --git a/usr/src/uts/i86pc/sys/apic.h b/usr/src/uts/i86pc/sys/apic.h
index c20857ab4c..a941f1bd88 100644
--- a/usr/src/uts/i86pc/sys/apic.h
+++ b/usr/src/uts/i86pc/sys/apic.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -485,7 +485,7 @@ typedef struct apic_irq {
uchar_t airq_origirq; /* original irq passed in */
uint_t airq_busy; /* How frequently did clock find */
/* us in this */
- struct apic_irq *airq_next; /* chain of shared intpts */
+ struct apic_irq *airq_next; /* chain of intpts sharing a vector */
void *airq_intrr_private; /* intr remap private data */
} apic_irq_t;