Date: Tue, 23 Nov 2004 23:10:48 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 65745 for review Message-ID: <200411232310.iANNAmOK079313@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=65745 Change 65745 by jhb@jhb_slimer on 2004/11/23 23:10:26 IFC @65733. Affected files ... .. //depot/projects/smpng/sys/alpha/alpha/interrupt.c#31 integrate .. //depot/projects/smpng/sys/arm/arm/intr.c#5 integrate .. //depot/projects/smpng/sys/arm/xscale/i80321/uart_bus_i80321.c#2 integrate .. //depot/projects/smpng/sys/arm/xscale/i80321/uart_cpu_i80321.c#2 integrate .. //depot/projects/smpng/sys/boot/Makefile#17 integrate .. //depot/projects/smpng/sys/boot/efi/Makefile#2 integrate .. //depot/projects/smpng/sys/boot/efi/libefi/arch/ia64/ldscript.ia64#7 delete .. //depot/projects/smpng/sys/boot/efi/libefi/arch/ia64/start.S#7 delete .. //depot/projects/smpng/sys/boot/efi/loader/Makefile#12 delete .. //depot/projects/smpng/sys/boot/efi/loader/conf.c#9 delete .. //depot/projects/smpng/sys/boot/efi/loader/main.c#15 delete .. //depot/projects/smpng/sys/boot/efi/loader/version#5 delete .. //depot/projects/smpng/sys/boot/ia64/Makefile#4 integrate .. //depot/projects/smpng/sys/boot/ia64/efi/Makefile#1 branch .. //depot/projects/smpng/sys/boot/ia64/efi/conf.c#1 branch .. //depot/projects/smpng/sys/boot/ia64/efi/ldscript.ia64#1 branch .. //depot/projects/smpng/sys/boot/ia64/efi/main.c#1 branch .. //depot/projects/smpng/sys/boot/ia64/efi/start.S#1 branch .. //depot/projects/smpng/sys/boot/ia64/efi/version#1 branch .. //depot/projects/smpng/sys/conf/files.alpha#32 integrate .. //depot/projects/smpng/sys/conf/files.amd64#24 integrate .. //depot/projects/smpng/sys/conf/files.arm#3 integrate .. //depot/projects/smpng/sys/conf/files.i386#71 integrate .. //depot/projects/smpng/sys/conf/files.ia64#46 integrate .. //depot/projects/smpng/sys/conf/files.pc98#65 integrate .. //depot/projects/smpng/sys/dev/acpica/acpi_pci_link.c#23 integrate .. //depot/projects/smpng/sys/dev/acpica/acpi_pcib.c#27 integrate .. //depot/projects/smpng/sys/dev/acpica/acpi_pcib_acpi.c#17 integrate .. //depot/projects/smpng/sys/dev/acpica/acpi_pcib_pci.c#8 integrate .. //depot/projects/smpng/sys/dev/acpica/acpi_pcibvar.h#4 integrate .. //depot/projects/smpng/sys/geom/gate/g_gate.c#8 integrate .. //depot/projects/smpng/sys/kern/sys_pipe.c#49 integrate .. //depot/projects/smpng/sys/netgraph/ng_cisco.c#10 integrate .. //depot/projects/smpng/sys/netgraph/ng_iface.c#16 integrate .. //depot/projects/smpng/sys/netgraph/ng_one2many.c#11 integrate .. //depot/projects/smpng/sys/netgraph/ng_one2many.h#4 integrate .. //depot/projects/smpng/sys/netinet/tcp_input.c#63 integrate .. //depot/projects/smpng/sys/netinet/tcp_subr.c#59 integrate .. //depot/projects/smpng/sys/netinet/tcp_timer.c#20 integrate Differences ... ==== //depot/projects/smpng/sys/alpha/alpha/interrupt.c#31 (text+ko) ==== @@ -33,7 +33,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ /* __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $");*/ -__FBSDID("$FreeBSD: src/sys/alpha/alpha/interrupt.c,v 1.82 2004/07/20 06:32:32 alc Exp $"); +__FBSDID("$FreeBSD: src/sys/alpha/alpha/interrupt.c,v 1.83 2004/11/23 22:11:53 jhb Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -474,7 +474,7 @@ /* * Only one processor drives the actual timer. */ - if (PCPU_GET(cpuid) == boot_cpu_id) { + if (PCPU_GET(cpuid) == 0) { #endif (*platform.clockintr)(framep); /* divide hz (1024) by 8 to get stathz (128) */ ==== //depot/projects/smpng/sys/arm/arm/intr.c#5 (text+ko) ==== @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/arm/arm/intr.c,v 1.4 2004/11/12 21:49:05 cognet Exp $"); +__FBSDID("$FreeBSD: src/sys/arm/arm/intr.c,v 1.5 2004/11/23 16:31:16 cognet Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/syslog.h> @@ -139,17 +139,16 @@ continue; ih = TAILQ_FIRST(&ithd->it_handlers); if (ih && ih->ih_flags & IH_FAST) { + oldirqstate = disable_interrupts(I32_bit); TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { ih->ih_handler(ih->ih_argument ? ih->ih_argument : frame); } + restore_interrupts(oldirqstate); arm_unmask_irqs(1 << i); - } else if (ih) { - oldirqstate = enable_interrupts(I32_bit); + } else if (ih) ithread_schedule(ithd); - restore_interrupts(oldirqstate); - } irqnb |= arm_get_irqnb(frame); } td->td_intr_nesting_level--; ==== //depot/projects/smpng/sys/arm/xscale/i80321/uart_bus_i80321.c#2 (text+ko) ==== @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_bus_i80321.c,v 1.1 2004/09/23 22:45:36 cognet Exp $"); +__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_bus_i80321.c,v 1.2 2004/11/23 16:30:50 cognet Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -59,7 +59,6 @@ sizeof(struct uart_softc), }; -extern struct uart_class uart_i8251_class; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_i80321_probe(device_t dev) @@ -68,7 +67,7 @@ sc = device_get_softc(dev); sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); - sc->sc_class = &uart_i8251_class; + sc->sc_class = &uart_ns8250_class; bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); return(uart_bus_probe(dev, 0, 0, 0, 0)); } ==== //depot/projects/smpng/sys/arm/xscale/i80321/uart_cpu_i80321.c#2 (text+ko) ==== @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_cpu_i80321.c,v 1.1 2004/09/23 22:45:36 cognet Exp $"); +__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_cpu_i80321.c,v 1.2 2004/11/23 16:30:50 cognet Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -55,7 +55,7 @@ int uart_cpu_getdev(int devtype, struct uart_devinfo *di) { - di->ops = uart_i8251_ops; + di->ops = uart_ns8250_ops; di->bas.chan = 0; di->bas.bst = &obio_bs_tag; di->bas.regshft = 0; ==== //depot/projects/smpng/sys/boot/Makefile#17 (text+ko) ==== @@ -1,10 +1,15 @@ -# $FreeBSD: src/sys/boot/Makefile,v 1.24 2004/08/16 15:45:24 marius Exp $ +# $FreeBSD: src/sys/boot/Makefile,v 1.25 2004/11/23 05:52:00 marcel Exp $ .if !defined(NOFORTH) # Build the add-in FORTH interpreter. SUBDIR+= ficl .endif +# Build EFI library. +.if ${MACHINE_ARCH} == "ia64" +SUBDIR+= efi +.endif + # Build Open Firmware library. .if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "sparc64" SUBDIR+= ofw @@ -19,9 +24,4 @@ #SUBDIR+= arc #.endif -# Build EFI executable on ia64. -.if ${MACHINE_ARCH} == "ia64" -SUBDIR+= efi -.endif - .include <bsd.subdir.mk> ==== //depot/projects/smpng/sys/boot/efi/Makefile#2 (text+ko) ==== @@ -1,5 +1,5 @@ -# $FreeBSD: src/sys/boot/efi/Makefile,v 1.1 2001/06/09 16:49:48 dfr Exp $ +# $FreeBSD: src/sys/boot/efi/Makefile,v 1.2 2004/11/23 06:04:51 marcel Exp $ -SUBDIR= libefi loader +SUBDIR= libefi .include <bsd.subdir.mk> ==== //depot/projects/smpng/sys/boot/ia64/Makefile#4 (text+ko) ==== @@ -1,5 +1,5 @@ -# $FreeBSD: src/sys/boot/ia64/Makefile,v 1.3 2004/09/24 04:21:14 marcel Exp $ +# $FreeBSD: src/sys/boot/ia64/Makefile,v 1.4 2004/11/23 06:03:03 marcel Exp $ -SUBDIR= ski +SUBDIR= efi ski .include <bsd.subdir.mk> ==== //depot/projects/smpng/sys/conf/files.alpha#32 (text+ko) ==== @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $FreeBSD: src/sys/conf/files.alpha,v 1.114 2004/08/01 11:40:51 markm Exp $ +# $FreeBSD: src/sys/conf/files.alpha,v 1.115 2004/11/23 00:00:43 imp Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -179,7 +179,6 @@ dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c optional atkbdc dev/kbd/kbd.c optional atkbd -dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/ppc/ppc.c optional ppc ==== //depot/projects/smpng/sys/conf/files.amd64#24 (text+ko) ==== @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $FreeBSD: src/sys/conf/files.amd64,v 1.50 2004/09/28 07:29:54 markm Exp $ +# $FreeBSD: src/sys/conf/files.amd64,v 1.51 2004/11/23 00:00:43 imp Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -123,7 +123,6 @@ dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c optional atkbdc dev/kbd/kbd.c optional atkbd -dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/mem/memutil.c optional mem ==== //depot/projects/smpng/sys/conf/files.arm#3 (text+ko) ==== @@ -1,4 +1,4 @@ -# $FreeBSD: src/sys/conf/files.arm,v 1.3 2004/05/14 23:42:54 cognet Exp $ +# $FreeBSD: src/sys/conf/files.arm,v 1.4 2004/11/22 22:20:50 cognet Exp $ arm/arm/autoconf.c standard arm/arm/bcopy_page.S standard arm/arm/bcopyinout.S standard @@ -29,6 +29,7 @@ arm/arm/intr.c standard arm/arm/locore.S standard no-obj arm/arm/machdep.c standard +arm/arm/mem.c optional mem arm/arm/nexus.c optional nexus arm/arm/nexus_io.c optional nexus arm/arm/nexus_io_asm.S optional nexus ==== //depot/projects/smpng/sys/conf/files.i386#71 (text+ko) ==== @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $FreeBSD: src/sys/conf/files.i386,v 1.508 2004/11/15 05:54:14 imp Exp $ +# $FreeBSD: src/sys/conf/files.i386,v 1.509 2004/11/23 00:00:43 imp Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -157,7 +157,6 @@ dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c optional atkbdc dev/kbd/kbd.c optional atkbd -dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/kbd/kbd.c optional vt ==== //depot/projects/smpng/sys/conf/files.ia64#46 (text+ko) ==== @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $FreeBSD: src/sys/conf/files.ia64,v 1.73 2004/09/25 04:27:44 marcel Exp $ +# $FreeBSD: src/sys/conf/files.ia64,v 1.74 2004/11/23 00:00:43 imp Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -55,7 +55,6 @@ dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c optional atkbdc dev/kbd/kbd.c optional atkbd -dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/ppc/ppc.c optional ppc isa ==== //depot/projects/smpng/sys/conf/files.pc98#65 (text+ko) ==== @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $FreeBSD: src/sys/conf/files.pc98,v 1.306 2004/08/30 23:03:56 peter Exp $ +# $FreeBSD: src/sys/conf/files.pc98,v 1.307 2004/11/23 00:00:43 imp Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -105,7 +105,6 @@ dev/fb/fb.c optional gdc dev/fb/splash.c optional splash dev/fe/if_fe_cbus.c optional fe isa -dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/kbd/kbd.c optional pckbd ==== //depot/projects/smpng/sys/dev/acpica/acpi_pci_link.c#23 (text+ko) ==== @@ -25,17 +25,22 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.33 2004/09/25 06:15:56 njl Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.34 2004/11/23 22:26:44 jhb Exp $"); #include "opt_acpi.h" #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/bus.h> +#include <sys/limits.h> +#include <sys/malloc.h> +#include <sys/module.h> #include "acpi.h" #include <dev/acpica/acpivar.h> #include <dev/acpica/acpi_pcibvar.h> +#include <machine/pci_cfgreg.h> +#include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include "pcib_if.h" @@ -43,1119 +48,714 @@ #define _COMPONENT ACPI_BUS ACPI_MODULE_NAME("PCI_LINK") -TAILQ_HEAD(acpi_pci_link_entries, acpi_pci_link_entry); -static struct acpi_pci_link_entries acpi_pci_link_entries; ACPI_SERIAL_DECL(pci_link, "ACPI PCI link"); -TAILQ_HEAD(acpi_prt_entries, acpi_prt_entry); -static struct acpi_prt_entries acpi_prt_entries; +#define NUM_ISA_INTERRUPTS 16 +#define NUM_ACPI_INTERRUPTS 256 + +/* + * An ACPI PCI link device may contain multiple links. Each link has its + * own ACPI resource. _PRT entries specify which link is being used via + * the Source Index. + */ + +struct link; + +struct acpi_pci_link_softc { + int pl_num_links; + struct link *pl_links; +}; + +struct link { + struct acpi_pci_link_softc *l_sc; + uint8_t l_bios_irq; + uint8_t l_irq; + uint8_t l_initial_irq; + int l_res_index; + int l_num_irqs; + int *l_irqs; + int l_references; + int l_routed:1; + int l_isa_irq:1; + ACPI_RESOURCE l_prs_template; +}; + +struct link_res_request { + struct acpi_pci_link_softc *sc; + int count; +}; + +MALLOC_DEFINE(M_PCI_LINK, "PCI Link", "ACPI PCI Link structures"); -static int irq_penalty[MAX_ACPI_INTERRUPTS]; +static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS]; +static int pci_link_bios_isa_irqs; -static int acpi_pci_link_is_valid_irq(struct acpi_pci_link_entry *link, - UINT8 irq); -static void acpi_pci_link_update_irq_penalty(device_t dev, int busno); -static void acpi_pci_link_set_bootdisabled_priority(void); -static void acpi_pci_link_fixup_bootdisabled_link(void); +static char *pci_link_ids[] = { "PNP0C0F", NULL }; /* - * PCI link object management + * Fetch the short name associated with an ACPI handle and save it in the + * passed in buffer. */ - -static void -acpi_pci_link_dump_polarity(UINT32 ActiveHighLow) +static ACPI_STATUS +acpi_short_name(ACPI_HANDLE handle, char *buffer, size_t buflen) { + ACPI_BUFFER buf; - switch (ActiveHighLow) { - case ACPI_ACTIVE_HIGH: - printf("high,"); - break; - case ACPI_ACTIVE_LOW: - printf("low,"); - break; - default: - printf("unknown,"); - break; - } + buf.Length = buflen; + buf.Pointer = buffer; + return (AcpiGetName(handle, ACPI_SINGLE_NAME, &buf)); } -static void -acpi_pci_link_dump_trigger(UINT32 EdgeLevel) +static int +acpi_pci_link_probe(device_t dev) { + char descr[64], name[10]; - switch (EdgeLevel) { - case ACPI_EDGE_SENSITIVE: - printf("edge,"); - break; - case ACPI_LEVEL_SENSITIVE: - printf("level,"); - break; - default: - printf("unknown,"); - break; + /* + * We explicitly do not check _STA since not all systems set it to + * sensible values. + */ + if (!acpi_disabled("pci_link") && + ACPI_ID_PROBE(device_get_parent(dev), dev, pci_link_ids) != NULL) { + if (ACPI_FAILURE(acpi_short_name(acpi_get_handle(dev), name, + sizeof(name)))) + device_set_desc(dev, "ACPI PCI Link"); + else { + snprintf(descr, sizeof(descr), "ACPI PCI Link %s", + name); + device_set_desc_copy(dev, descr); + } + return (0); } + return (ENXIO); } -static void -acpi_pci_link_dump_sharemode(UINT32 SharedExclusive) +static ACPI_STATUS +acpi_count_resources(ACPI_RESOURCE *res, void *context) { + int *count; - switch (SharedExclusive) { - case ACPI_EXCLUSIVE: - printf("exclusive"); - break; - case ACPI_SHARED: - printf("sharable"); - break; - default: - printf("unknown"); - break; - } + count = (int *)context; + (*count)++; + return (AE_OK); } -static void -acpi_pci_link_entry_dump(struct acpi_prt_entry *entry) +static ACPI_STATUS +link_add_crs(ACPI_RESOURCE *res, void *context) { - UINT8 i; - ACPI_RESOURCE_IRQ *Irq; - ACPI_RESOURCE_EXT_IRQ *ExtIrq; - struct acpi_pci_link_entry *link; + struct link_res_request *req; + struct link *link; - if (entry == NULL || entry->pci_link == NULL) - return; - link = entry->pci_link; - - printf("%s irq%c%2d: ", acpi_name(link->handle), - (link->flags & ACPI_LINK_ROUTED) ? '*' : ' ', link->current_irq); - - printf("["); - if (link->number_of_interrupts) - printf("%2d", link->interrupts[0]); - for (i = 1; i < link->number_of_interrupts; i++) - printf("%3d", link->interrupts[i]); - printf("] %2d+ ", link->initial_irq); - - switch (link->possible_resources.Id) { + ACPI_SERIAL_ASSERT(pci_link); + req = (struct link_res_request *)context; + link = &req->sc->pl_links[req->count]; + req->count++; + switch (res->Id) { case ACPI_RSTYPE_IRQ: - Irq = &link->possible_resources.Data.Irq; - acpi_pci_link_dump_polarity(Irq->ActiveHighLow); - acpi_pci_link_dump_trigger(Irq->EdgeLevel); - acpi_pci_link_dump_sharemode(Irq->SharedExclusive); - break; case ACPI_RSTYPE_EXT_IRQ: - ExtIrq = &link->possible_resources.Data.ExtendedIrq; - acpi_pci_link_dump_polarity(ExtIrq->ActiveHighLow); - acpi_pci_link_dump_trigger(ExtIrq->EdgeLevel); - acpi_pci_link_dump_sharemode(ExtIrq->SharedExclusive); + if (res->Id == ACPI_RSTYPE_IRQ) { + if (res->Data.Irq.NumberOfInterrupts > 0) { + KASSERT(res->Data.Irq.NumberOfInterrupts == 1, + ("%s: too many interrupts", __func__)); + link->l_irq = res->Data.Irq.Interrupts[0]; + } + } else if (res->Data.ExtendedIrq.NumberOfInterrupts > 0) { + KASSERT(res->Data.ExtendedIrq.NumberOfInterrupts == 1, + ("%s: too many interrupts", __func__)); + link->l_irq = res->Data.ExtendedIrq.Interrupts[0]; + } + + /* + * An IRQ of zero means that the link isn't routed. + */ + if (link->l_irq == 0) + link->l_irq = PCI_INVALID_IRQ; break; } - - printf(" %d.%d.%d\n", entry->busno, - (int)(ACPI_ADR_PCI_SLOT(entry->prt.Address)), - (int)entry->prt.Pin); + return (AE_OK); } +/* + * Populate the set of possible IRQs for each device. + */ static ACPI_STATUS -acpi_pci_link_get_object_status(ACPI_HANDLE handle, UINT32 *sta) +link_add_prs(ACPI_RESOURCE *res, void *context) { - ACPI_DEVICE_INFO *devinfo; - ACPI_BUFFER buf; - ACPI_STATUS error; + struct link_res_request *req; + struct link *link; + UINT32 *irqs; + int i; - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - if (handle == NULL || sta == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n")); - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - error = AcpiGetObjectInfo(handle, &buf); - if (ACPI_FAILURE(error)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "couldn't get object info %s - %s\n", - acpi_name(handle), AcpiFormatException(error))); - return_ACPI_STATUS (error); - } - - devinfo = (ACPI_DEVICE_INFO *)buf.Pointer; - if ((devinfo->Valid & ACPI_VALID_HID) == 0 || - strcmp(devinfo->HardwareId.Value, "PNP0C0F") != 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid hardware ID - %s\n", - acpi_name(handle))); - AcpiOsFree(buf.Pointer); - return_ACPI_STATUS (AE_TYPE); - } - - if ((devinfo->Valid & ACPI_VALID_STA) != 0) { - *sta = devinfo->CurrentStatus; - } else { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "invalid status - %s\n", - acpi_name(handle))); - *sta = 0; - } - - AcpiOsFree(buf.Pointer); - return_ACPI_STATUS (AE_OK); -} - -static ACPI_STATUS -acpi_pci_link_get_irq_resources(ACPI_RESOURCE *resources, - UINT8 *number_of_interrupts, UINT8 interrupts[]) -{ - UINT8 count; - UINT8 i; - UINT32 NumberOfInterrupts; - UINT32 *Interrupts; - - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - if (resources == NULL || number_of_interrupts == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n")); - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - *number_of_interrupts = 0; - NumberOfInterrupts = 0; - Interrupts = NULL; - - if (resources->Id == ACPI_RSTYPE_START_DPF) - resources = ACPI_NEXT_RESOURCE(resources); - - if (resources->Id != ACPI_RSTYPE_IRQ && - resources->Id != ACPI_RSTYPE_EXT_IRQ) { - printf("acpi link get: resource %d is not an IRQ\n", - resources->Id); - return_ACPI_STATUS (AE_TYPE); - } - - switch (resources->Id) { + ACPI_SERIAL_ASSERT(pci_link); + req = (struct link_res_request *)context; + link = &req->sc->pl_links[req->count]; + req->count++; + switch (res->Id) { case ACPI_RSTYPE_IRQ: - NumberOfInterrupts = resources->Data.Irq.NumberOfInterrupts; - Interrupts = resources->Data.Irq.Interrupts; - break; case ACPI_RSTYPE_EXT_IRQ: - NumberOfInterrupts = - resources->Data.ExtendedIrq.NumberOfInterrupts; - Interrupts = resources->Data.ExtendedIrq.Interrupts; - break; - } - if (NumberOfInterrupts == 0) - return_ACPI_STATUS (AE_NULL_ENTRY); + /* + * Stash a copy of the resource for later use when doing + * _SRS. + */ + bcopy(res, &link->l_prs_template, sizeof(ACPI_RESOURCE)); + if (res->Id == ACPI_RSTYPE_IRQ) { + link->l_num_irqs = res->Data.Irq.NumberOfInterrupts; + irqs = res->Data.Irq.Interrupts; + } else { + link->l_num_irqs = + res->Data.ExtendedIrq.NumberOfInterrupts; + irqs = res->Data.ExtendedIrq.Interrupts; + } + if (link->l_num_irqs == 0) + break; - count = 0; - for (i = 0; i < NumberOfInterrupts; i++) { - if (i >= MAX_POSSIBLE_INTERRUPTS) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "too many IRQs (%d)\n", - i)); - break; + /* + * Save a list of the valid IRQs. Also, if all of the + * valid IRQs are ISA IRQs, then mark this link as + * routed via an ISA interrupt. + */ + link->l_isa_irq = 1; + link->l_irqs = malloc(sizeof(int) * link->l_num_irqs, + M_PCI_LINK, M_WAITOK | M_ZERO); + for (i = 0; i < link->l_num_irqs; i++) { + link->l_irqs[i] = irqs[i]; + if (irqs[1] >= NUM_ISA_INTERRUPTS) + link->l_isa_irq = 0; } - if (Interrupts[i] == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "invalid IRQ %d\n", - Interrupts[i])); - continue; - } - interrupts[count] = Interrupts[i]; - count++; + break; } - *number_of_interrupts = count; - - return_ACPI_STATUS (AE_OK); + return (AE_OK); } -static ACPI_STATUS -acpi_pci_link_get_current_irq(struct acpi_pci_link_entry *link, UINT8 *irq) +static int +link_valid_irq(struct link *link, int irq) { - ACPI_STATUS error; - ACPI_BUFFER buf; - ACPI_RESOURCE *resources; - UINT8 number_of_interrupts; - UINT8 interrupts[MAX_POSSIBLE_INTERRUPTS];; + int i; - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + ACPI_SERIAL_ASSERT(pci_link); - if (link == NULL || irq == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n")); - return_ACPI_STATUS (AE_BAD_PARAMETER); - } + /* Invalid interrupts are never valid. */ + if (!PCI_INTERRUPT_VALID(irq)) + return (0); - *irq = 0; - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - error = AcpiGetCurrentResources(link->handle, &buf); - if (ACPI_FAILURE(error)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "couldn't get PCI interrupt link device _CRS %s - %s\n", - acpi_name(link->handle), AcpiFormatException(error))); - return_ACPI_STATUS (error); - } - if (buf.Pointer == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "couldn't allocate memory - %s\n", - acpi_name(link->handle))); - return_ACPI_STATUS (AE_NO_MEMORY); - } + /* Any interrupt in the list of possible interrupts is valid. */ + for (i = 0; i < link->l_num_irqs; i++) + if (link->l_irqs[i] == irq) + return (1); - resources = (ACPI_RESOURCE *) buf.Pointer; - number_of_interrupts = 0; - bzero(interrupts, sizeof(interrupts)); - error = acpi_pci_link_get_irq_resources(resources, - &number_of_interrupts, interrupts); - AcpiOsFree(buf.Pointer); + /* + * For links routed via an ISA interrupt, if the SCI is routed via + * an ISA interrupt, the SCI is always treated as a valid IRQ. + */ + if (link->l_isa_irq && AcpiGbl_FADT->SciInt == irq && + irq < NUM_ISA_INTERRUPTS) + return (1); - if (ACPI_FAILURE(error)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "couldn't get current IRQ from interrupt link %s - %s\n", - acpi_name(link->handle), AcpiFormatException(error))); - return_ACPI_STATUS (error); - } - - if (number_of_interrupts == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "PCI interrupt link device _CRS data is corrupted - %s\n", - acpi_name(link->handle))); - return_ACPI_STATUS (AE_NULL_ENTRY); - } - - *irq = interrupts[0]; - - return_ACPI_STATUS (AE_OK); + /* If the interrupt wasn't found in the list it is not valid. */ + return (0); } -static ACPI_STATUS -acpi_pci_link_add_link(ACPI_HANDLE handle, struct acpi_prt_entry *entry) +static void +acpi_pci_link_dump(struct acpi_pci_link_softc *sc) { - ACPI_STATUS error; - ACPI_BUFFER buf; - ACPI_RESOURCE *resources; - struct acpi_pci_link_entry *link; + struct link *link; + int i, j; - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_SERIAL_ASSERT(pci_link); - - entry->pci_link = NULL; - TAILQ_FOREACH(link, &acpi_pci_link_entries, links) { - if (link->handle == handle) { - entry->pci_link = link; - link->references++; - return_ACPI_STATUS (AE_OK); - } + printf("Index IRQ Rtd Ref IRQs\n"); + for (i = 0; i < sc->pl_num_links; i++) { + link = &sc->pl_links[i]; + printf("%5d %3d %c %3d ", i, link->l_irq, + link->l_routed ? 'Y' : 'N', link->l_references); + if (link->l_num_irqs == 0) + printf(" none"); + else for (j = 0; j < link->l_num_irqs; j++) + printf(" %d", link->l_irqs[j]); + printf("\n"); } +} - link = AcpiOsAllocate(sizeof(struct acpi_pci_link_entry)); - if (link == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "couldn't allocate memory - %s\n", acpi_name(handle))); - return_ACPI_STATUS (AE_NO_MEMORY); - } +static int +acpi_pci_link_attach(device_t dev) +{ + struct acpi_pci_link_softc *sc; + struct link_res_request req; + ACPI_STATUS status; + int i; - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - - bzero(link, sizeof(struct acpi_pci_link_entry)); - link->handle = handle; + sc = device_get_softc(dev); + ACPI_SERIAL_BEGIN(pci_link); /* - * Get the IRQ configured at boot-time. If successful, set this - * as the initial IRQ. + * Count the number of current resources so we know how big of + * a link array to allocate. */ - error = acpi_pci_link_get_current_irq(link, &link->current_irq); - if (ACPI_SUCCESS(error)) { - link->initial_irq = link->current_irq; - } else { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "couldn't get current IRQ from interrupt link %s - %s\n", - acpi_name(handle), AcpiFormatException(error))); - link->initial_irq = 0; - } + status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", + acpi_count_resources, &sc->pl_num_links); + if (ACPI_FAILURE(status)) + return (ENXIO); + if (sc->pl_num_links == 0) + return (0); + sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links, + M_PCI_LINK, M_WAITOK | M_ZERO); - error = AcpiGetPossibleResources(handle, &buf); - if (ACPI_FAILURE(error)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "couldn't get interrupt link device _PRS data %s - %s\n", - acpi_name(handle), AcpiFormatException(error))); - goto out; + /* Initialize the child links. */ + for (i = 0; i < sc->pl_num_links; i++) { + sc->pl_links[i].l_irq = PCI_INVALID_IRQ; + sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ; + sc->pl_links[i].l_res_index = i; + sc->pl_links[i].l_sc = sc; + sc->pl_links[i].l_isa_irq = 0; } - if (buf.Pointer == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "_PRS buffer is empty - %s\n", acpi_name(handle))); - error = AE_NO_MEMORY; - goto out; + req.count = 0; + req.sc = sc; + status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", + link_add_crs, &req); + if (ACPI_FAILURE(status)) + goto fail; + req.count = 0; + status = AcpiWalkResources(acpi_get_handle(dev), "_PRS", + link_add_prs, &req); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) + goto fail; + if (bootverbose) { + device_printf(dev, "Links after initial probe:\n"); + acpi_pci_link_dump(sc); } - /* Skip any DPF descriptors. XXX We should centralize this code. */ - resources = (ACPI_RESOURCE *) buf.Pointer; - if (resources->Id == ACPI_RSTYPE_START_DPF) - resources = ACPI_NEXT_RESOURCE(resources); - - /* XXX This only handles one resource, ignoring SourceIndex. */ - bcopy(resources, &link->possible_resources, - sizeof(link->possible_resources)); - - error = acpi_pci_link_get_irq_resources(resources, - &link->number_of_interrupts, link->interrupts); - if (ACPI_FAILURE(error)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "couldn't get possible IRQs from interrupt link %s - %s\n", - acpi_name(handle), AcpiFormatException(error))); - goto out; + /* Verify initial IRQs if we have _PRS. */ + if (status != AE_NOT_FOUND) + for (i = 0; i < sc->pl_num_links; i++) + if (!link_valid_irq(&sc->pl_links[i], + sc->pl_links[i].l_irq)) + sc->pl_links[i].l_irq = PCI_INVALID_IRQ; + if (bootverbose) { + device_printf(dev, "Links after initial validation:\n"); + acpi_pci_link_dump(sc); } - if (link->number_of_interrupts == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "interrupt link device _PRS data is corrupted - %s\n", - acpi_name(handle))); - error = AE_NULL_ENTRY; - goto out; - } + /* Save initial IRQs. */ + for (i = 0; i < sc->pl_num_links; i++) + sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq; /* * Try to disable this link. If successful, set the current IRQ to * zero and flags to indicate this link is not routed. If we can't * run _DIS (i.e., the method doesn't exist), assume the initial * IRQ was routed by the BIOS. - * - * XXX Since we detect link devices via _PRT entries but run long - * after APIC mode has been enabled, we don't get a chance to - * disable links that will be unused (especially in APIC mode). - * Leaving them enabled can cause duplicate interrupts for some - * devices. The right fix is to probe links via their PNPID, so we - * see them no matter what the _PRT says. */ - if (ACPI_SUCCESS(AcpiEvaluateObject(handle, "_DIS", NULL, NULL))) { - link->current_irq = 0; - link->flags = ACPI_LINK_NONE; - } else - link->flags = ACPI_LINK_ROUTED; - - /* - * If the initial IRQ is invalid (not in _PRS), set it to 0 and - * mark this link as not routed. We won't use it as the preferred - * interrupt later when we route. - */ - if (!acpi_pci_link_is_valid_irq(link, link->initial_irq) && - link->initial_irq != 0) { - printf("ACPI link %s has invalid initial irq %d, ignoring\n", - acpi_name(handle), link->initial_irq); - link->initial_irq = 0; - link->flags = ACPI_LINK_NONE; + if (ACPI_SUCCESS(AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL, + NULL))) + for (i = 0; i < sc->pl_num_links; i++) + sc->pl_links[i].l_irq = PCI_INVALID_IRQ; + else + for (i = 0; i < sc->pl_num_links; i++) + if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq)) + sc->pl_links[i].l_routed = 1; + if (bootverbose) { + device_printf(dev, "Links after disable:\n"); + acpi_pci_link_dump(sc); } + ACPI_SERIAL_END(pci_link); + return (0); +fail: + ACPI_SERIAL_END(pci_link); + for (i = 0; i < sc->pl_num_links; i++) + if (sc->pl_links[i].l_irqs != NULL) + free(sc->pl_links[i].l_irqs, M_PCI_LINK); + free(sc->pl_links, M_PCI_LINK); + return (ENXIO); +} >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411232310.iANNAmOK079313>