diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/pciex/pcieb.c | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/isa.c | 7 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/mp_platform_common.c | 90 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/pci/pci_common.c | 6 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/pcplusmp/apic.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/pcplusmp/apic_introp.c | 30 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/rootnex.c | 7 | ||||
-rw-r--r-- | usr/src/uts/i86pc/sys/apic.h | 4 |
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; |