mp_platform_common.c revision 6bdf0ab58e83f1eea3ec057b462223bbab57e454
1N/A * The contents of this file are subject to the terms of the 1N/A * Common Development and Distribution License (the "License"). 1N/A * You may not use this file except in compliance with the License. 1N/A * See the License for the specific language governing permissions 1N/A * and limitations under the License. 1N/A * When distributing Covered Code, include this CDDL HEADER in each 1N/A * If applicable, add the following below this CDDL HEADER, with the 1N/A * fields enclosed by brackets "[]" replaced with your own identifying 1N/A * information: Portions Copyright [yyyy] [name of copyright owner] 1N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 1N/A * Use is subject to license terms. 1N/A * PSMI 1.1 extensions are supported only in 2.6 and later versions. 1N/A * PSMI 1.2 extensions are supported only in 2.7 and later versions. 1N/A * PSMI 1.3 and 1.4 extensions are supported in Solaris 10. 1N/A * PSMI 1.5 extensions are supported in Solaris Nevada. 1N/A * PSMI 1.6 extensions are supported in Solaris Nevada. 1N/A * Local Function Prototypes /* ACPI SCI interrupt configuration; -1 if SCI not used */ /* ACPI support routines */ /* Max wait time (in repetitions) for flags to clear in an RDT entry. */ /* The irq # is implicit in the array index: */ * APIC_MAX_VECTOR + 1 is the maximum # of IRQs as well. ioapic_reprogram_info * is indexed by IRQ number, NOT by vector number. * If enabled, the distribution works as follows: * On every interrupt entry, the current ipl for the CPU is set in cpu_info * and the irq corresponding to the ipl is also set in the aci_current array. * interrupt exit and setspl (due to soft interrupts) will cause the current * ipl to be be changed. This is cache friendly as these frequently used * paths write into a per cpu structure. * Sampling is done by checking the structures for all CPUs and incrementing * the busy field of the irq (if any) executing on each CPU and the busy field * of the corresponding CPU. * In periodic mode this is done on every clock interrupt. * In one-shot mode, this is done thru a cyclic with an interval of * apic_redistribute_sample_interval (default 10 milli sec). * Every apic_sample_factor_redistribution times we sample, we do computations * to decide which interrupt needs to be migrated (see comments * before apic_intr_redistribute(). * Following 3 variables start as % and can be patched or set using an * API to be defined in future. They will be scaled to * sample_factor_redistribution which is in turn set to hertz+1 (in periodic * mode), or 101 in one-shot mode to stagger it away from one sec processing /* sampling interval for interrupt redistribution for dynamic migration */ * number of times we sample before deciding to redistribute interrupts /* timeout for xlate_vector, mark_vector */ * For interrupt link devices, if apic_unconditional_srs is set, an irq resource * will be assigned (via _SRS). If it is not set, use the current * irq setting (via _CRS), but only if that irq is in the set of possible * irqs (returned by _PRS) for the device. * For interrupt link devices, if apic_prefer_crs is set when we are * assigning an IRQ resource to a device, prefer the current IRQ setting * over other possible irq settings under same conditions. * First available slot to be used as IRQ index into the apic_irq_table * for those interrupts (like MSI/X) that don't have a physical IRQ. * apic_ioapic_lock protects the ioapics (reg select), the status, temp_bound * and bound elements of cpus_info and the temp_cpu element of irq_struct * apic_defer_reprogram_lock ensures that only one processor is handling * deferred interrupt programming at *_intr_exit time. * The current number of deferred reprogrammings outstanding * Counters that keep track of deferred reprogramming stats static int apic_io_max = 0;
/* no. of i/o apics enabled */ /* At least MSB will be set if EISA bus */ * airq_mutex protects additions to the apic_irq_table - the first * pointer and any airq_nexts off of that one. It also protects * apic_max_device_irq & apic_min_device_irq. It also guarantees * that share_id is unique as new ids are generated only when new * irq_t structs are linked in. Once linked in the structs are never * deleted. temp_cpu & mps_intr_index field indicate if it is programmed * or allocated. Note that there is a slight gap between allocating in * apic_introp_xlate and programming in addspl. * Following declarations are for revectoring; used when ISRs at different /* 1 = acpi is enabled & working, 0 = acpi is not enabled or not there */ /* ACPI Multiple APIC Description Table ptr */ /* ACPI Interrupt Source Override Structure ptr */ /* ACPI Non-maskable Interrupt Sources ptr */ * The following added to identify a software poweroff method if available. * Auto-configuration routines * Look at MPSpec 1.4 (Intel Order # 242016-005) for details of what we do here * May work with 1.1 - but not guaranteed. * According to the MP Spec, the MP floating pointer structure * will be searched in the order described below: * 1. In the first kilobyte of Extended BIOS Data Area (EBDA) * 2. Within the last kilobyte of system base memory * 3. In the BIOS ROM address space between 0F0000h and 0FFFFh * Once we find the right signature with proper checksum, we call * either handle_defconf or parse_mpct to get all info necessary for /* Allow override for MADT-only mode */ /* Allow apic_use_acpi to override MADT-only mode */ * mapin the bios data area 40:0 * 40:13h - two-byte location reports the base memory size * 40:0Eh - two-byte location for the exact starting address of * the EBDA segment for EISA /*LINTED: pointer cast may result in improper alignment */ /* check the 1k of EBDA */ /* If not in EBDA, check the last k of system base memory */ /*LINTED: pointer cast may result in improper alignment */ /* if ebda == last k of base mem, skip to check BIOS ROM */ /* If still cannot find it, check the BIOS ROM space */ /* check IMCR is present or not */ /* check default configuration (dual CPUs) */ /* MP Configuration Table */ * Map in enough memory for the MP Configuration Table Header. * Use this table to read the total length of the BIOS data and /*LINTED: pointer cast may result in improper alignment */ /* check mp configuration table signature PCMP */ /* This is an ACPI machine No need for further checks */ * Map in the entries for this machine, ie. Processor * Entry Tables, Bus Entry Tables, etc. * They are in fixed order following one another /*LINTED: pointer cast may result in improper alignment */ /* Parse all information in the tables */ "Product ID = '%c%c%c%c%c%c%c%c%c%c%c%c'\n",
* We don't enable x2APIC when Solaris is running under xVM. "maximum no. of CPUs (= %d)",
"!apic: irq source: %d %d %d 0x%x %d %d\n",
* All logical processors with APIC ID values * of 255 and greater will have their APIC * reported through Processor X2APIC structure. * All logical processors with APIC ID less than * 255 will have their APIC reported through "!apic: local x2apic nmi: %d 0x%x %d\n",
/* advance to next entry */ * ACPI doesn't provide the local apic ver, get it directly from the * need to check Sitka on the following acpi problem * On the Sitka, the ioapic's apic_id field isn't reporting * the actual io apic id. We have reported this problem * to Intel. Until they fix the problem, we will get the * actual id directly from the ioapic. else {
/* set ioapic id to whatever reported by ACPI */ * Process SCI configuration here * An error may be returned here if * acpi-user-options specifies legacy mode * Now call acpi_init() to generate namespaces * If this fails, we don't attempt to use ACPI * even if we were able to get a MADT above * Call acpica_build_processor_map() now that we have * Squirrel away the SCI and flags for later on * in apic_picinit() when we're ready /* Enable ACPI APIC interrupt routing */ "?Using ACPI for CPU/IOAPIC information ONLY\n");
/* if setting APIC mode failed above, we fall through to cleanup */ * Handle default configuration. Fill in reqd global variables & tables * Fill all details as MP table does not give any more info /*LINTED: pointer cast may result in improper alignment */ /*LINTED: pointer cast may result in improper alignment */ * According to the PC+MP spec 1.1, the local ids * for the default configuration has to be 0 or 1 /* Parse the entries in MP configuration table and collect info that we need */ /*LINTED: pointer cast may result in improper alignment */ /* No need to count cpu entries if we won't use them */ /* Find max # of CPUS and allocate structure accordingly */ "maximum no. of CPUs (= %d)",
/*LINTED: pointer cast may result in improper alignment */ * start with index 1 as 0 needs to be filled in with Boot CPU, but * if we're bypassing this information, it has already been filled * in by acpi_probe(), so don't overwrite it. /* check whether the cpu exists or not */ * Save start of bus entries for later use. * Get EISA level cntrl if EISA bus is present. * Also get the CPI bus id for single CPI bus case * apic_single_pci_busid will be used only if * apic_pic_bus_total is equal to 1 /*LINTED: pointer cast may result in improper alignment */ * set ioapic id to whatever * may not need to set index * Don't assume all IO APICs in the system are the same. * Set to the minimum version. /* Assume all local APICs are of the same version. */ /* Look for the pattern "_MP_" */ for (i = 0; i <
len; i +=
16) {
if ((*(
cptr+i) ==
'_') &&
/*LINTED: pointer cast may result in improper alignment */ for (i = 0; i <
len; i++)
* Initialise vector->ipl and ipl->pri arrays. level_intr and irqtable * are also set to NULL. vector->irq is set to a value which cannot map * to a real irq to show that it is free. * Initialize apic_ipls from apic_vectortoipl. This array is * used in apic_intr_enter to determine the IPL to use for the * corresponding vector. On some systems, due to hardware errata * and interrupt sharing, the IPL may not correspond to the IPL listed * in apic_vectortoipl (see apic_addspl and apic_delspl). /* cpu 0 is always up (for now) */ /* These *must* be initted to B_TRUE! */ * Allocate a dummy irq table entry for the reserved entry. * This takes care of the race between removing an irq and * clock detecting a CPU in that irq during interrupt load /* mask interrupt vectors */ /* Bits 23-16 define the maximum redirection entries */ * Hack alert: deal with ACPI SCI interrupt chicken/egg here * acpica has already done add_avintr(); we just * to finish the job by mimicing translate_irq() * Fake up an intrspec and setup the tables * Add mask bits to disable interrupt vector from happening * at or above IPL. In addition, it should remove mask bits * to enable interrupt vectors below the given IPL. * Both add and delspl are complicated by the fact that different interrupts * may share IRQs. This can happen in two ways. * 1. The same H/W line is shared by more than 1 device * 1a. with interrupts at different IPLs * 1b. with interrupts at same IPL * 2. We ran out of vectors at a given IPL and started sharing vectors. * 1b and 2 should be handled gracefully, except for the fact some ISRs * will get called often when no interrupt is pending for the device. * For 1a, we just hope that the machine blows up with the person who * set it up that way!. In the meantime, we handle it at the higher IPL. /* return if it is not hardware interrupt */ /* Or if there are more interupts at a higher IPL */ * if apic_picinit() has not been called yet, just return. * At the end of apic_picinit(), we will call setup_io_intr(). * Upgrade vector if max_ipl is not earlier ipl. If we cannot allocate, * return failure. Not very elegant, but then we hope the * machine will blow up with ... * reprogram irq being added and every one else * who is not in the UNINIT state * We cannot upgrade the vector, but we can change * the IPL that this vector induces. * Note that we subtract APIC_BASE_VECT from the vector * here because this array is used in apic_intr_enter * (no need to add APIC_BASE_VECT in that hot code * path since we can do it in the rarely-executed path * Recompute mask bits for the given interrupt vector. * If there is no interrupt servicing routine for this * vector, this function should disable interrupt vector * from happening at all IPLs. If there are still * handlers using the given vector, this function should * disable the given vector from happening below the lowest * IPL of the remaining hadlers. /* return if it is not hardware interrupt */ * Clear irq_struct. If two devices shared an intpt * line & 1 unloaded before picinit, we are hosed. But, then * we hope the machine will ... * Downgrade vector to new max_ipl if needed.If we cannot allocate, * use old IPL. Not very elegant, but then we hope ... * We cannot downgrade the IPL of the vector below the vector's * hardware priority. If we did, it would be possible for a * higher-priority hardware vector to interrupt a CPU running at an IPL * lower than the hardware priority of the interrupting vector (but * higher than the soft IPL of this IRQ). When this happens, we would * then try to drop the IPL BELOW what it was (effectively dropping * below base_spl) which would be potentially catastrophic. * (e.g. Suppose the hardware vector associated with this IRQ is 0x40 * (hardware IPL of 4). Further assume that the old IPL of this IRQ * was 4, but the new IPL is 1. If we forced vector 0x40 to result in * an IPL of 1, it would be possible for the processor to be executing * at IPL 3 and for an interrupt to come in on vector 0x40, interrupting * the currently-executing ISR. When apic_intr_enter consults * apic_irqs[], it will return 1, bringing the IPL of the CPU down to 1 * so even though the processor was running at IPL 4, an IPL 1 * interrupt will have interrupted it, which must not happen)). * Effectively, this means that the hardware priority corresponding to * the IRQ's IPL (in apic_ipls[]) cannot be lower than the vector's * (In the above example, then, after removal of the IPL 4 device's * interrupt handler, the new IPL will continue to be 4 because the * hardware priority that IPL 1 implies is lower than the hardware * priority of the vector used.) /* apic_ipls is indexed by vector, starting at APIC_BASE_VECT */ * If there are still devices using this IRQ, determine the * If the desired IPL's hardware priority is lower * than that of the vector, use the hardware priority * of the vector to determine the new IPL. * Now, to get the right index for apic_vectortoipl, * we need to subtract APIC_BASE_VECT from the * hardware-vector-equivalent (in hwpri). Since hwpri * is already shifted, we shift APIC_BASE_VECT before * No more devices on this IRQ, so reset this vector's * element in apic_ipls to the original IPL for this * Make sure we only disable on the last * of the multi-MSI support * Disable the MSI-X vector * needs to clear its mask and addr/data for each MSI-X * Make sure we only disable on the last MSI-X * The assumption here is that this is safe, even for * systems with IOAPICs that suffer from the hardware * erratum because all devices have been quiesced before * they unregister their interrupt handlers. If that * assumption turns out to be false, this mask operation * can induce the same erratum result we're trying to /* If hardbound, temp_cpu == cpu */ /* Move valid irq entry to the head */ /* remove all invalid ones from the beginning */ * and link them back after the head. The invalid ones * begin with irqheadptr and end at oldirqptr * apic_introp_xlate() replaces apic_translate_irq() and is * 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. /* check if we have already translated this irq */ /* search iso entries first */ for (i = 0; i <
2; i++) {
/* MPS default configuration */ * On machines with PCI-PCI bridges, a device behind a PCI-PCI bridge * needs special handling. We may need to chase up the device tree, * using the PCI-PCI Bridge specification's "rotating IPIN assumptions", * to find the IPIN at the root bus that relates to the IPIN on the * subsidiary bus (for ACPI or MP). We may, however, have an entry * in the MP table or the ACPI namespace for this device itself. * We handle both cases in the search below. /* this is the non-acpi version */ * This is the rotating scheme documented in the * PCI-to-PCI spec. If the PCI-to-PCI bridge is * behind another PCI-to-PCI bridge, then it needs * to keep ascending until an interrupt entry is * found or the root is reached. /*LINTED: function will not fall off the bottom */ return (
0xFF);
/* shouldn't happen */ * See if two irqs are compatible for sharing a vector. * Currently we only support sharing of PCI devices. /* Assume active high by default */ * Attempt to share vector with someone else * Assign a share id which is free or which is larger /* shuffle the pointers to test apic_delspl path */ /* MSI/X doesn't need to setup ioapic stuffs */ /* need an irq for MSI/X to index into autovect[] */ /* Find ioapicindex. If destid was ALL, we will exit with 0. */ /* check whether this intin# has been used by another irqno */ /* default configuration */ /* This is OK to do really */ " instance %d and %s instance %d",
/* try high priority allocation now that share has failed */ * The slot is used by another irqno, so allocate * a free irqno for this interrupt /* setup I/O APIC entry for non-MSI/X interrupts */ * return the cpu to which this intr should be bound. * Check properties or any other mechanism to see if user wants it * bound to a specific CPU. If so, return the cpu id with high bit set. * If not, use the policy to choose a cpu and return the id. "!%s: %s (%s) instance #%d " "vector 0x%x ioapic 0x%x " "intin 0x%x is bound to cpu %d\n",
* search for "drvname"_intpt_bind_cpus property first, the * syntax of the property should be "a[,b,c,...]" where * instance 0 binds to cpu a, instance 1 binds to cpu b, * instance 3 binds to cpu c... * ddi_getlongprop() will search /option first, then / * if "drvname"_intpt_bind_cpus doesn't exist, then find * intpt_bind_cpus property. The syntax is the same, and * it applies to all the devices if its "drvname" specific * if somehow the binding instances defined in the * property are not enough for this instno., then * reuse the pattern for the next instance until * it reaches the requested instno /* if specific cpu is bogus, then default to cpu 0 */ /* indicate that we are bound at user request */ * no need to check apic_cpus[].aci_status, if specific cpu is * not up, then post_cpu_start will handle it. "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n",
"vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n",
* It can have more than 1 entry with same source bus IRQ, * but unique with the source bus id * Check if a particular irq need to be reserved for any io_intr * Check if the given ioapicindex intin combination has already been assigned * an irq. If so return irqno. Else -1 /* find ioapic and intin in the apic_irq_table[] and return the index */ "entry for ioapic:intin %x:%x " * if BIOS really defines every single irq in the mps * table, then don't worry about conflicting with * them, just use any free slot in apic_irq_table /* This shouldn't happen, but just in case */ /* Check if any I/O entry needs this IRQ */ /* Then see if it is free */ * Mark vector as being in the process of being deleted. Interrupts * may still come in on some CPU. The moment an interrupt comes with * the new vector, we know we can free the old one. Called only from * addspl and delspl with interrupts disabled. Because an interrupt * can be shared, but no interrupt from either device may come in, * we also use a timeout mechanism, which we arbitrarily set to * apic_revector_timeout microseconds. * This failure is not catastrophic. * But, the oldvec will never be freed. /* See if we already did this for drivers which do double addintrs */ * xlate_vector is called from intr_enter if revector_pending is set. * It will xlate it if needed and mark the old vector as free. /* Do we really need to do this ? */ * The incoming vector is new . See if a stale entry is /* There could have been more than one reprogramming! */ * compute the polarity, trigger mode and vector for programming into * the I/O apic and record in airq_rdt_entry. /* Assume edge triggered by default */ /* Assume active high by default */ * The 82489DX External APIC cannot do active low polarity interrupts. printf(
"setio: ioapic=%x intin=%x level=%x po=%x vector=%x\n",
* Bind interrupt corresponding to irq_ptr to bind_cpu. * Must be called with interrupts disabled and apic_ioapic_lock held /* Mask off high bit so it can be used as array index */ * Can't bind to a CPU that's not accepting interrupts: * If we are about to change the interrupt vector for this interrupt, * and this interrupt is level-triggered, attached to an IOAPIC, * has been delivered to a CPU and that CPU has not handled it * yet, we cannot reprogram the IOAPIC now. * NOTE: We do not unmask the RDT here, as an interrupt MAY * still come in before we have a chance to reprogram it below. * The reprogramming below will simultaneously change and /* Write the RDT entry -- no specific CPU binding */ * Write the vector, trigger, and polarity portion of /* Write the RDT entry -- bind to a specific CPU: */ /* Write the RDT entry -- bind to a specific CPU: */ /* Write the vector, trigger, and polarity portion of the RDT */ "apic_pci_msi_enable_vector\n"));
"apic_pci_msi_enable_mode\n"));
* Trying to clear the bit through normal * channels has failed. So as a last-ditch * effort, try to set the trigger mode to * edge, then to level. This has been * observed to work on many systems. * If the bit's STILL set, this interrupt may "not clear for IOAPIC %d intin %d.\n" "\tInterrupts to this pin may cease " * This function is protected by apic_ioapic_lock coupled with the * fact that interrupts are disabled. * Interrupts must be disabled during this function to prevent * self-deadlock. Interrupts are disabled because this function * is called from apic_check_stuck_interrupt(), which is called * from apic_rebind(), which requires its caller to disable interrupts. * On the off-chance that there's already a deferred * reprogramming on this irq, check, and if so, just update the * CPU and irq pointer to which the interrupt is targeted, then return. * This must be the last thing set, since we're not * grabbing any locks, apic_try_deferred_reprogram() will * make its decision about using this entry iff done * If there were previously no deferred reprogrammings, change * setlvlx to call apic_try_deferred_reprogram() * Acquire the apic_ioapic_lock so that any other operations that * may affect the apic_reprogram_info state are serialized. * It's still possible for the last deferred reprogramming to clear * between the time we entered this function and the time we get to * the for loop below. In that case, *setlvlx will have been set * back to *_intr_exit and drep will be NULL. (There's no way to * stop that from happening -- we would need to grab a lock before * calling *setlvlx, which is neither realistic nor prudent). * For each deferred RDT entry, try to reprogram it now. Note that * there is no lock acquisition to read apic_reprogram_info because * '.done' is set only after the other fields in the structure are set. * Either we found a deferred action to perform, or * we entered this function spuriously, after *setlvlx * was restored to point to *_intr_exit. Any other * permutation is invalid. * Though we can't really do anything about errors * at this point, keep track of them for reporting. * Note that it is very possible for apic_setup_io_intr * to re-register this very timeout if the Remote IRR bit * Wait for the delivery pending bit to clear. * If we're still waiting on the delivery of this interrupt, * continue to wait here until it is delivered (this should be * a very small amount of time, but include a timeout just in * Checks to see if the IOAPIC interrupt entry specified has its Remote IRR * bit set. Calls functions that modify the function that setlvlx points to, * so that the reprogramming can be retried very shortly. * This function will mask the RDT entry if the interrupt is level-triggered. * (The caller is responsible for unmasking the RDT entry.) * Returns non-zero if the caller should defer IOAPIC reprogramming. * Wait for the delivery pending bit to clear. * Mask the RDT entry, but only if it's a level-triggered * If there was a race and an interrupt was injected * just before we masked, check for that case here. * Then, unmask the RDT entry and try again. If we're * on our last try, don't unmask (because we want the * RDT entry to remain masked for the rest of the * If the remote IRR bit is set, then the interrupt has been sent * to a CPU for processing. We have no choice but to wait for * that CPU to process the interrupt, at which point the remote IRR * If the CPU that this RDT is bound to is NOT the current * CPU, wait until that CPU handles the interrupt and ACKs * it. If this interrupt is not bound to any CPU (that is, * if it's bound to the logical destination of "anyone"), it * may have been delivered to the current CPU so handle that * case by deferring the reprogramming (below). /* Remote IRR has cleared! */ * If we waited and the Remote IRR bit is still not cleared, * AND if we've invoked the timeout APIC_REPROGRAM_MAX_TIMEOUTS * times for this interrupt, try the last-ditch workaround: /* Mark this one as reprogrammed: */ * If waiting for the Remote IRR bit (above) didn't * allow it to clear, defer the reprogramming. * Add a new deferred-programming entry if the * caller passed a NULL one (and update the existing one * in case anything changed). /* Inform caller to defer IOAPIC programming: */ /* Remote IRR is clear */ * Called to migrate all interrupts at an irq to another cpu. * Must be called with interrupts disabled and apic_ioapic_lock held * apic_intr_redistribute does all the messy computations for identifying * which interrupt to move to which CPU. Currently we do just one interrupt * at a time. This reduces the time we spent doing all this within clock * interrupt. When it is done in idle, we could do more than 1. * First we find the most busy and the most free CPU (time in ISR only) * skipping those CPUs that has been identified as being ineligible (cpu_skip) * Then we look for IRQs which are closest to the difference between the * most busy CPU and the average ISR load. We try to find one whose load * is less than difference.If none exists, then we chose one larger than the * difference, provided it does not make the most idle CPU worse than the * most busy one. In the end, we clear all the busy fields for CPUs. For * IRQs, they are cleared as they are scanned. * Below we will check for CPU_INTR_ENABLE, bound, temp_bound, temp_cpu * without ioapic_lock. That is OK as we are just doing statistical * sampling anyway and any inaccuracy now will get corrected next time * The call to rebind which actually changes things will make sure * If no unbound interrupts or only 1 total on this "redistribute busy=%x free=%x max=%x min=%x",
/* Change to linked list per CPU ? */ /* Check for irq_busy & decide which one to move */ /* Also zero them for next round */ * Check for least busy CPU, * least busy, but more than /* Make change permenant */ /* Make change permenant */ * We leave cpu_skip set so that next time we * found nothing. Could be that we skipped over valid CPUs * or we have balanced everything. If we had a variable * ticks_for_redistribution, it could be increased here. * apic_int_busy, int_free etc would also need to be "from cache for device %s, instance #%d\n",
psm_name,
" acpi_translate_pci_irq failed for device %s, instance" "new irq %d for device %s, instance #%d\n",
psm_name,
* Adds an entry to the irq list passed in, and returns the new list. * Entries are added in priority order (lower numerical priorities are * placed closer to the head of the list) /* ->next is NULL from kmem_zalloc */ * New list -- return the new entry as the list. * Save original list pointer for return (since we're not modifying * Insertion sort, with entries with identical keys stored AFTER * existing entries (the less-than-or-equal test of priority does if (
prevp ==
NULL) {
/* Add at head of list (newent is the new head) */ * Frees the list passed in, deallocating all memory and leaving *listpp * apic_choose_irqs_from_prs returns a list of irqs selected from the list of * irqs returned by the link device's _PRS method. The irqs are chosen * to minimize contention in situations where the interrupt link device * can be programmed to steer interrupts to different interrupt controller * inputs (some of which may already be in use). The list is sorted in order * of irqs to use, with the highest priority given to interrupt controller * inputs that are not shared. When an interrupt controller input * must be shared, apic_choose_irqs_from_prs adds the possible irqs to the * returned list in the order that minimizes sharing (thereby ensuring lowest * possible latency from interrupt trigger time to ISR execution time). * If we do not prefer the current irq from _CRS * or if we do and this irq is the same as the * current irq from _CRS, this is the one * Edge-triggered interrupts cannot be shared * To work around BIOSes that contain incorrect * interrupt polarity information in interrupt * descriptors returned by _PRS, we assume that * the polarity of the other device sharing this * interrupt controller input is compatible. * If it's not, the caller will catch it when * the caller invokes the link device's _CRS method * (after invoking its _SRS method). "not compatible [%x:%x:%x !~ %x:%x:%x]",
* If we prefer the irq from _CRS, no need * to search any further (and make sure * to add this irq with the highest priority 0
/* Highest priority */,
* Priority is equal to the share count (lower * share count is higher priority). Note that * the intr flags passed in here are the ones we * changed above -- if incorrect, it will be * caught by the caller's _CRS flags comparison. /* Go to the next irqlist entry */ * Configures the irq for the interrupt link device identified by * Gets the current and the list of possible irq settings for the * device. If apic_unconditional_srs is not set, and the current * resource setting is in the list of possible irq settings, * current irq resource setting is passed to the caller. * Otherwise, picks an irq number from the list of possible irq * settings, and sets the irq of the device to this value. * If prefer_crs is set, among a set of irq numbers in the list that have * the least number of devices sharing the interrupt, we pick current irq * resource setting if it is a member of this set. * Passes the irq number in the value pointed to by pci_irqp, and * polarity and sensitivity in the structure pointed to by dipintrflagp * Note that if setting the irq resource failed, but successfuly obtained * the current irq resource settings, passes the current irq resources * and considers it a success. * ACPI_PSM_SUCCESS on success. * ACPI_PSM_FAILURE if an error occured during the configuration or * if a suitable irq was not found for this device, or if setting the * irq resource and obtaining the current resource fails. "or assign IRQ for device %s, instance #%d: The system was " "unable to get the list of potential IRQs from ACPI.",
* If an IRQ is set in CRS and that IRQ exists in the set * returned from _PRS, return that IRQ, otherwise print "current irq %d for device %s, instance #%d in ACPI's " "list of possible irqs for this device. Picking one from " "suitable irq from the list of possible irqs for device " "%s, instance #%d in ACPI's list of possible irqs",
* setting irq was successful, check to make sure CRS * reflects that. If CRS does not agree with what we * set, return the irq that was set. "(irqno %d) for device %s " "instance #%d, differs from " "current setting irqno %d",
* On at least one system, there was a bug in * a DSDT method called by _STA, causing _STA to * indicate that the link device was disabled * (when, in fact, it was enabled). Since _SRS * succeeded, assume that _CRS is lying and use * the iflags from this _PRS interrupt choice. * If we're wrong about the flags, the polarity * will be incorrect and we may get an interrupt * storm, but there's not much else we can do * Return the irq that was set, and not what _CRS * reports, since _CRS has been seen to return * different IRQs than what was passed to _SRS on some * systems (and just not return successfully on others). "irq %d failed for device %s instance #%d",
/* Disable the I/O APIC redirection entries */ /* Bits 23-16 define the maximum redirection entries */ * The assumption here is that this is safe, even for * systems with IOAPICs that suffer from the hardware * erratum because all devices have been quiesced before * this function is called from apic_shutdown() * (or equivalent). If that assumption turns out to be * false, this mask operation can induce the same * erratum result we're trying to avoid. * Looks for an IOAPIC with the specified physical address in the /ioapics * node in the device tree (created by the PCI enumerator). * Look in /ioapics, for the ioapic with * the physical address given /* The ioapics node was held by ddi_find_devinfo, so release it */ /* Setup parameter object */ * If on the boot processor then save the IOAPICs' IDs * the following only needs to be done once, so we do it on the * boot processor, since we know that we only have one of those /* Restore IOAPICs' APIC IDs */ * Reenter APIC mode before restoring LNK devices * restore acpi link device mappings PMD(
PMD_SX, (
":STATE_ALLOC: state %p, size %lx\n",
PMD(
PMD_SX, (
" STATE_FREE: state %p, size %lx\n",
PMD(
PMD_SX, (
" STATE_SAVE: state %p, size %lx\n",
PMD(
PMD_SX, (
" STATE_RESTORE: state %p, size %lx\n",