diff options
Diffstat (limited to 'sys')
122 files changed, 2002 insertions, 3584 deletions
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index 9afb36c..c25d802 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -41,13 +41,13 @@ __FBSDID("$FreeBSD$"); #include <vm/pmap.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/pcb.h> #include <machine/pmap.h> #include <machine/specialreg.h> #ifdef SMP -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/smp.h> #include <machine/vmparam.h> #endif diff --git a/sys/amd64/acpica/madt.c b/sys/amd64/acpica/madt.c index 90ffd64..84bc831 100644 --- a/sys/amd64/acpica/madt.c +++ b/sys/amd64/acpica/madt.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index e50d3e7..0f7bc25 100644 --- a/sys/amd64/amd64/amd64_mem.c +++ b/sys/amd64/amd64/amd64_mem.c @@ -35,6 +35,10 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/sysctl.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + #include <machine/cputypes.h> #include <machine/md_var.h> #include <machine/specialreg.h> @@ -527,9 +531,9 @@ static int amd64_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) { struct mem_range_desc *targ; - int error = 0; + int error, i; - switch(*arg) { + switch (*arg) { case MEMRANGE_SET_UPDATE: /* * Make sure that what's being asked for is even @@ -568,6 +572,21 @@ amd64_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) return (EOPNOTSUPP); } + /* + * Ensure that the direct map region does not contain any mappings + * that span MTRRs of different types. However, the fixed MTRRs can + * be ignored, because a large page mapping the first 1 MB of physical + * memory is a special case that the processor handles. The entire + * TLB will be invalidated by amd64_mrstore(), so pmap_demote_DMAP() + * needn't do it. + */ + i = (sc->mr_cap & MR686_FIXMTRR) ? MTRR_N64K + MTRR_N16K + MTRR_N4K : 0; + mrd = sc->mr_desc + i; + for (; i < sc->mr_ndesc; i++, mrd++) { + if (mrd->mr_flags & MDF_ACTIVE) + pmap_demote_DMAP(mrd->mr_base, mrd->mr_len, FALSE); + } + /* Update the hardware. */ amd64_mrstore(sc); @@ -657,6 +676,21 @@ amd64_mrinit(struct mem_range_softc *sc) if (mrd->mr_flags & MDF_ACTIVE) mrd->mr_flags |= MDF_FIRMWARE; } + + /* + * Ensure that the direct map region does not contain any mappings + * that span MTRRs of different types. However, the fixed MTRRs can + * be ignored, because a large page mapping the first 1 MB of physical + * memory is a special case that the processor handles. Invalidate + * any old TLB entries that might hold inconsistent memory type + * information. + */ + i = (sc->mr_cap & MR686_FIXMTRR) ? MTRR_N64K + MTRR_N16K + MTRR_N4K : 0; + mrd = sc->mr_desc + i; + for (; i < sc->mr_ndesc; i++, mrd++) { + if (mrd->mr_flags & MDF_ACTIVE) + pmap_demote_DMAP(mrd->mr_base, mrd->mr_len, TRUE); + } } /* diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 73a0eab..e4c4ddf 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -39,7 +39,7 @@ #include "opt_smp.h" #include <machine/asmacros.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include "assym.s" diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index d6ebec5..613bce5 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> #include <nfsclient/nfsdiskless.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/cpu.h> #include <machine/pcb.h> #include <machine/sigframe.h> diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c index 3cdc69f..4edef81 100644 --- a/sys/amd64/amd64/intr_machdep.c +++ b/sys/amd64/amd64/intr_machdep.c @@ -458,7 +458,7 @@ intr_next_cpu(void) /* Leave all interrupts on the BSP during boot. */ if (!assign_cpu) - return (cpu_apic_ids[0]); + return (PCPU_GET(apic_id)); mtx_lock_spin(&icu_lock); apic_id = cpu_apic_ids[current_cpu]; diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 61a2cf8..eba788f 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -112,7 +112,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/cputypes.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/metadata.h> #include <machine/pc/bios.h> diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index c509b67..3868428 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -57,11 +57,11 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_kern.h> #include <vm/vm_extern.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/clock.h> #include <machine/cputypes.h> #include <machine/cpufunc.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/mp_watchdog.h> #include <machine/pcb.h> diff --git a/sys/amd64/amd64/mp_watchdog.c b/sys/amd64/amd64/mp_watchdog.c index 1803270..5cbd649 100644 --- a/sys/amd64/amd64/mp_watchdog.c +++ b/sys/amd64/amd64/mp_watchdog.c @@ -44,7 +44,7 @@ #include <sys/systm.h> #include <machine/smp.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/apicvar.h> #include <machine/mp_watchdog.h> diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c deleted file mode 100644 index 01cb093..0000000 --- a/sys/amd64/amd64/mptable.c +++ /dev/null @@ -1,1042 +0,0 @@ -/*- - * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> - * Copyright (c) 1996, by Steve Passe - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. The name of the developer may NOT be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/malloc.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> - -#include <machine/apicreg.h> -#include <machine/frame.h> -#include <machine/intr_machdep.h> -#include <machine/apicvar.h> -#include <machine/md_var.h> -#include <machine/mptable.h> -#include <machine/specialreg.h> - -#include <dev/pci/pcivar.h> - -/* string defined by the Intel MP Spec as identifying the MP table */ -#define MP_SIG 0x5f504d5f /* _MP_ */ - -#define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */ - -#define BIOS_BASE (0xf0000) -#define BIOS_SIZE (0x10000) -#define BIOS_COUNT (BIOS_SIZE/4) - -typedef void mptable_entry_handler(u_char *entry, void *arg); - -static basetable_entry basetable_entry_types[] = -{ - {0, 20, "Processor"}, - {1, 8, "Bus"}, - {2, 8, "I/O APIC"}, - {3, 8, "I/O INT"}, - {4, 8, "Local INT"} -}; - -typedef struct BUSDATA { - u_char bus_id; - enum busTypes bus_type; -} bus_datum; - -typedef struct INTDATA { - u_char int_type; - u_short int_flags; - u_char src_bus_id; - u_char src_bus_irq; - u_char dst_apic_id; - u_char dst_apic_int; - u_char int_vector; -} io_int, local_int; - -typedef struct BUSTYPENAME { - u_char type; - char name[7]; -} bus_type_name; - -/* From MP spec v1.4, table 4-8. */ -static bus_type_name bus_type_table[] = -{ - {UNKNOWN_BUSTYPE, "CBUS "}, - {UNKNOWN_BUSTYPE, "CBUSII"}, - {EISA, "EISA "}, - {UNKNOWN_BUSTYPE, "FUTURE"}, - {UNKNOWN_BUSTYPE, "INTERN"}, - {ISA, "ISA "}, - {UNKNOWN_BUSTYPE, "MBI "}, - {UNKNOWN_BUSTYPE, "MBII "}, - {MCA, "MCA "}, - {UNKNOWN_BUSTYPE, "MPI "}, - {UNKNOWN_BUSTYPE, "MPSA "}, - {UNKNOWN_BUSTYPE, "NUBUS "}, - {PCI, "PCI "}, - {UNKNOWN_BUSTYPE, "PCMCIA"}, - {UNKNOWN_BUSTYPE, "TC "}, - {UNKNOWN_BUSTYPE, "VL "}, - {UNKNOWN_BUSTYPE, "VME "}, - {UNKNOWN_BUSTYPE, "XPRESS"} -}; - -/* From MP spec v1.4, table 5-1. */ -static int default_data[7][5] = -{ -/* nbus, id0, type0, id1, type1 */ - {1, 0, ISA, 255, NOBUS}, - {1, 0, EISA, 255, NOBUS}, - {1, 0, EISA, 255, NOBUS}, - {1, 0, MCA, 255, NOBUS}, - {2, 0, ISA, 1, PCI}, - {2, 0, EISA, 1, PCI}, - {2, 0, MCA, 1, PCI} -}; - -struct pci_probe_table_args { - u_char bus; - u_char found; -}; - -struct pci_route_interrupt_args { - u_char bus; /* Source bus. */ - u_char irq; /* Source slot:pin. */ - int vector; /* Return value. */ -}; - -static mpfps_t mpfps; -static mpcth_t mpct; -static void *ioapics[MAX_APIC_ID + 1]; -static bus_datum *busses; -static int mptable_nioapics, mptable_nbusses, mptable_maxbusid; -static int pci0 = -1; - -static MALLOC_DEFINE(M_MPTABLE, "mptable", "MP Table Items"); - -static enum intr_polarity conforming_polarity(u_char src_bus, - u_char src_bus_irq); -static enum intr_trigger conforming_trigger(u_char src_bus, u_char src_bus_irq); -static enum intr_polarity intentry_polarity(int_entry_ptr intr); -static enum intr_trigger intentry_trigger(int_entry_ptr intr); -static int lookup_bus_type(char *name); -static void mptable_count_items(void); -static void mptable_count_items_handler(u_char *entry, void *arg); -#ifdef MPTABLE_FORCE_HTT -static void mptable_hyperthread_fixup(u_long id_mask); -#endif -static void mptable_parse_apics_and_busses(void); -static void mptable_parse_apics_and_busses_handler(u_char *entry, - void *arg); -static void mptable_parse_default_config_ints(void); -static void mptable_parse_ints(void); -static void mptable_parse_ints_handler(u_char *entry, void *arg); -static void mptable_parse_io_int(int_entry_ptr intr); -static void mptable_parse_local_int(int_entry_ptr intr); -static void mptable_pci_probe_table_handler(u_char *entry, void *arg); -static void mptable_pci_route_interrupt_handler(u_char *entry, void *arg); -static void mptable_pci_setup(void); -static int mptable_probe(void); -static int mptable_probe_cpus(void); -static void mptable_probe_cpus_handler(u_char *entry, void *arg __unused); -static void mptable_register(void *dummy); -static int mptable_setup_local(void); -static int mptable_setup_io(void); -static void mptable_walk_table(mptable_entry_handler *handler, void *arg); -static int search_for_sig(u_int32_t target, int count); - -static struct apic_enumerator mptable_enumerator = { - "MPTable", - mptable_probe, - mptable_probe_cpus, - mptable_setup_local, - mptable_setup_io -}; - -/* - * look for the MP spec signature - */ - -static int -search_for_sig(u_int32_t target, int count) -{ - int x; - u_int32_t *addr = (u_int32_t *) (KERNBASE + target); - - for (x = 0; x < count; x += 4) - if (addr[x] == MP_SIG) - /* make array index a byte index */ - return (target + (x * sizeof(u_int32_t))); - return (-1); -} - -static int -lookup_bus_type(char *name) -{ - int x; - - for (x = 0; x < MAX_BUSTYPE; ++x) - if (strncmp(bus_type_table[x].name, name, 6) == 0) - return (bus_type_table[x].type); - - return (UNKNOWN_BUSTYPE); -} - -/* - * Look for an Intel MP spec table (ie, SMP capable hardware). - */ -static int -mptable_probe(void) -{ - int x; - u_int32_t segment; - u_int32_t target; - - /* see if EBDA exists */ - segment = (u_int32_t) *(u_short *)(KERNBASE + 0x40e); - if (segment != 0) { - /* search first 1K of EBDA */ - target = (u_int32_t) (segment << 4); - if ((x = search_for_sig(target, 1024 / 4)) >= 0) - goto found; - } else { - /* last 1K of base memory, effective 'top of base' passed in */ - target = (u_int32_t) ((basemem * 1024) - 0x400); - if ((x = search_for_sig(target, 1024 / 4)) >= 0) - goto found; - } - - /* search the BIOS */ - target = (u_int32_t) BIOS_BASE; - if ((x = search_for_sig(target, BIOS_COUNT)) >= 0) - goto found; - - /* nothing found */ - return (ENXIO); - -found: - mpfps = (mpfps_t)(KERNBASE + x); - - /* Map in the configuration table if it exists. */ - if (mpfps->config_type != 0) { - if (bootverbose) - printf( - "MP Table version 1.%d found using Default Configuration %d\n", - mpfps->spec_rev, mpfps->config_type); - if (mpfps->config_type != 5 && mpfps->config_type != 6) { - printf( - "MP Table Default Configuration %d is unsupported\n", - mpfps->config_type); - return (ENXIO); - } - mpct = NULL; - } else { - if ((uintptr_t)mpfps->pap >= 1024 * 1024) { - printf("%s: Unable to map MP Configuration Table\n", - __func__); - return (ENXIO); - } - mpct = (mpcth_t)(KERNBASE + (uintptr_t)mpfps->pap); - if (mpct->base_table_length + (uintptr_t)mpfps->pap >= - 1024 * 1024) { - printf("%s: Unable to map end of MP Config Table\n", - __func__); - return (ENXIO); - } - if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' || - mpct->signature[2] != 'M' || mpct->signature[3] != 'P') { - printf("%s: MP Config Table has bad signature: %c%c%c%c\n", - __func__, mpct->signature[0], mpct->signature[1], - mpct->signature[2], mpct->signature[3]); - return (ENXIO); - } - if (bootverbose) - printf( - "MP Configuration Table version 1.%d found at %p\n", - mpct->spec_rev, mpct); - } - - return (-100); -} - -/* - * Run through the MP table enumerating CPUs. - */ -static int -mptable_probe_cpus(void) -{ - u_long cpu_mask; - - /* Is this a pre-defined config? */ - if (mpfps->config_type != 0) { - lapic_create(0, 1); - lapic_create(1, 0); - } else { - cpu_mask = 0; - mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask); -#ifdef MPTABLE_FORCE_HTT - mptable_hyperthread_fixup(cpu_mask); -#endif - } - return (0); -} - -/* - * Initialize the local APIC on the BSP. - */ -static int -mptable_setup_local(void) -{ - vm_paddr_t addr; - - /* Is this a pre-defined config? */ - printf("MPTable: <"); - if (mpfps->config_type != 0) { - addr = DEFAULT_APIC_BASE; - printf("Default Configuration %d", mpfps->config_type); - } else { - addr = mpct->apic_address; - printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id, - (int)sizeof(mpct->product_id), mpct->product_id); - } - printf(">\n"); - lapic_init(addr); - return (0); -} - -/* - * Run through the MP table enumerating I/O APICs. - */ -static int -mptable_setup_io(void) -{ - int i; - u_char byte; - - /* First, we count individual items and allocate arrays. */ - mptable_count_items(); - busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE, - M_WAITOK); - for (i = 0; i <= mptable_maxbusid; i++) - busses[i].bus_type = NOBUS; - - /* Second, we run through adding I/O APIC's and busses. */ - mptable_parse_apics_and_busses(); - - /* Third, we run through the table tweaking interrupt sources. */ - mptable_parse_ints(); - - /* Fourth, we register all the I/O APIC's. */ - for (i = 0; i <= MAX_APIC_ID; i++) - if (ioapics[i] != NULL) - ioapic_register(ioapics[i]); - - /* Fifth, we setup data structures to handle PCI interrupt routing. */ - mptable_pci_setup(); - - /* Finally, we throw the switch to enable the I/O APIC's. */ - if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) { - outb(0x22, 0x70); /* select IMCR */ - byte = inb(0x23); /* current contents */ - byte |= 0x01; /* mask external INTR */ - outb(0x23, byte); /* disconnect 8259s/NMI */ - } - - return (0); -} - -static void -mptable_register(void *dummy __unused) -{ - - apic_register_enumerator(&mptable_enumerator); -} -SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, - mptable_register, NULL); - -/* - * Call the handler routine for each entry in the MP config table. - */ -static void -mptable_walk_table(mptable_entry_handler *handler, void *arg) -{ - u_int i; - u_char *entry; - - entry = (u_char *)(mpct + 1); - for (i = 0; i < mpct->entry_count; i++) { - switch (*entry) { - case MPCT_ENTRY_PROCESSOR: - case MPCT_ENTRY_IOAPIC: - case MPCT_ENTRY_BUS: - case MPCT_ENTRY_INT: - case MPCT_ENTRY_LOCAL_INT: - break; - default: - panic("%s: Unknown MP Config Entry %d\n", __func__, - (int)*entry); - } - handler(entry, arg); - entry += basetable_entry_types[*entry].length; - } -} - -static void -mptable_probe_cpus_handler(u_char *entry, void *arg) -{ - proc_entry_ptr proc; - u_long *cpu_mask; - - switch (*entry) { - case MPCT_ENTRY_PROCESSOR: - proc = (proc_entry_ptr)entry; - if (proc->cpu_flags & PROCENTRY_FLAG_EN) { - lapic_create(proc->apic_id, proc->cpu_flags & - PROCENTRY_FLAG_BP); - if (proc->apic_id < MAX_LAPIC_ID) { - cpu_mask = (u_long *)arg; - *cpu_mask |= (1ul << proc->apic_id); - } - } - break; - } -} - -static void -mptable_count_items_handler(u_char *entry, void *arg __unused) -{ - io_apic_entry_ptr apic; - bus_entry_ptr bus; - - switch (*entry) { - case MPCT_ENTRY_BUS: - bus = (bus_entry_ptr)entry; - mptable_nbusses++; - if (bus->bus_id > mptable_maxbusid) - mptable_maxbusid = bus->bus_id; - break; - case MPCT_ENTRY_IOAPIC: - apic = (io_apic_entry_ptr)entry; - if (apic->apic_flags & IOAPICENTRY_FLAG_EN) - mptable_nioapics++; - break; - } -} - -/* - * Count items in the table. - */ -static void -mptable_count_items(void) -{ - - /* Is this a pre-defined config? */ - if (mpfps->config_type != 0) { - mptable_nioapics = 1; - switch (mpfps->config_type) { - case 1: - case 2: - case 3: - case 4: - mptable_nbusses = 1; - break; - case 5: - case 6: - case 7: - mptable_nbusses = 2; - break; - default: - panic("Unknown pre-defined MP Table config type %d", - mpfps->config_type); - } - mptable_maxbusid = mptable_nbusses - 1; - } else - mptable_walk_table(mptable_count_items_handler, NULL); -} - -/* - * Add a bus or I/O APIC from an entry in the table. - */ -static void -mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused) -{ - io_apic_entry_ptr apic; - bus_entry_ptr bus; - enum busTypes bus_type; - int i; - - - switch (*entry) { - case MPCT_ENTRY_BUS: - bus = (bus_entry_ptr)entry; - bus_type = lookup_bus_type(bus->bus_type); - if (bus_type == UNKNOWN_BUSTYPE) { - printf("MPTable: Unknown bus %d type \"", bus->bus_id); - for (i = 0; i < 6; i++) - printf("%c", bus->bus_type[i]); - printf("\"\n"); - } - busses[bus->bus_id].bus_id = bus->bus_id; - busses[bus->bus_id].bus_type = bus_type; - break; - case MPCT_ENTRY_IOAPIC: - apic = (io_apic_entry_ptr)entry; - if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN)) - break; - if (apic->apic_id > MAX_APIC_ID) - panic("%s: I/O APIC ID %d too high", __func__, - apic->apic_id); - if (ioapics[apic->apic_id] != NULL) - panic("%s: Double APIC ID %d", __func__, - apic->apic_id); - ioapics[apic->apic_id] = ioapic_create(apic->apic_address, - apic->apic_id, -1); - break; - default: - break; - } -} - -/* - * Enumerate I/O APIC's and busses. - */ -static void -mptable_parse_apics_and_busses(void) -{ - - /* Is this a pre-defined config? */ - if (mpfps->config_type != 0) { - ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0); - busses[0].bus_id = 0; - busses[0].bus_type = default_data[mpfps->config_type - 1][2]; - if (mptable_nbusses > 1) { - busses[1].bus_id = 1; - busses[1].bus_type = - default_data[mpfps->config_type - 1][4]; - } - } else - mptable_walk_table(mptable_parse_apics_and_busses_handler, - NULL); -} - -/* - * Determine conforming polarity for a given bus type. - */ -static enum intr_polarity -conforming_polarity(u_char src_bus, u_char src_bus_irq) -{ - - KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); - switch (busses[src_bus].bus_type) { - case ISA: - case EISA: - return (INTR_POLARITY_HIGH); - case PCI: - return (INTR_POLARITY_LOW); - default: - panic("%s: unknown bus type %d", __func__, - busses[src_bus].bus_type); - } -} - -/* - * Determine conforming trigger for a given bus type. - */ -static enum intr_trigger -conforming_trigger(u_char src_bus, u_char src_bus_irq) -{ - - KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); - switch (busses[src_bus].bus_type) { - case ISA: - if (elcr_found) - return (elcr_read_trigger(src_bus_irq)); - else - return (INTR_TRIGGER_EDGE); - case PCI: - return (INTR_TRIGGER_LEVEL); - case EISA: - KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq)); - KASSERT(elcr_found, ("Missing ELCR")); - return (elcr_read_trigger(src_bus_irq)); - default: - panic("%s: unknown bus type %d", __func__, - busses[src_bus].bus_type); - } -} - -static enum intr_polarity -intentry_polarity(int_entry_ptr intr) -{ - - switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) { - case INTENTRY_FLAGS_POLARITY_CONFORM: - return (conforming_polarity(intr->src_bus_id, - intr->src_bus_irq)); - case INTENTRY_FLAGS_POLARITY_ACTIVEHI: - return (INTR_POLARITY_HIGH); - case INTENTRY_FLAGS_POLARITY_ACTIVELO: - return (INTR_POLARITY_LOW); - default: - panic("Bogus interrupt flags"); - } -} - -static enum intr_trigger -intentry_trigger(int_entry_ptr intr) -{ - - switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) { - case INTENTRY_FLAGS_TRIGGER_CONFORM: - return (conforming_trigger(intr->src_bus_id, - intr->src_bus_irq)); - case INTENTRY_FLAGS_TRIGGER_EDGE: - return (INTR_TRIGGER_EDGE); - case INTENTRY_FLAGS_TRIGGER_LEVEL: - return (INTR_TRIGGER_LEVEL); - default: - panic("Bogus interrupt flags"); - } -} - -/* - * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC. - */ -static void -mptable_parse_io_int(int_entry_ptr intr) -{ - void *ioapic; - u_int pin, apic_id; - - apic_id = intr->dst_apic_id; - if (intr->dst_apic_id == 0xff) { - /* - * An APIC ID of 0xff means that the interrupt is connected - * to the specified pin on all I/O APICs in the system. If - * there is only one I/O APIC, then use that APIC to route - * the interrupts. If there is more than one I/O APIC, then - * punt. - */ - if (mptable_nioapics == 1) { - apic_id = 0; - while (ioapics[apic_id] == NULL) - apic_id++; - } else { - printf( - "MPTable: Ignoring global interrupt entry for pin %d\n", - intr->dst_apic_int); - return; - } - } - if (apic_id > MAX_APIC_ID) { - printf("MPTable: Ignoring interrupt entry for ioapic%d\n", - intr->dst_apic_id); - return; - } - ioapic = ioapics[apic_id]; - if (ioapic == NULL) { - printf( - "MPTable: Ignoring interrupt entry for missing ioapic%d\n", - apic_id); - return; - } - pin = intr->dst_apic_int; - switch (intr->int_type) { - case INTENTRY_TYPE_INT: - switch (busses[intr->src_bus_id].bus_type) { - case NOBUS: - panic("interrupt from missing bus"); - case ISA: - case EISA: - if (busses[intr->src_bus_id].bus_type == ISA) - ioapic_set_bus(ioapic, pin, APIC_BUS_ISA); - else - ioapic_set_bus(ioapic, pin, APIC_BUS_EISA); - if (intr->src_bus_irq == pin) - break; - ioapic_remap_vector(ioapic, pin, intr->src_bus_irq); - if (ioapic_get_vector(ioapic, intr->src_bus_irq) == - intr->src_bus_irq) - ioapic_disable_pin(ioapic, intr->src_bus_irq); - break; - case PCI: - ioapic_set_bus(ioapic, pin, APIC_BUS_PCI); - break; - default: - ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN); - break; - } - break; - case INTENTRY_TYPE_NMI: - ioapic_set_nmi(ioapic, pin); - break; - case INTENTRY_TYPE_SMI: - ioapic_set_smi(ioapic, pin); - break; - case INTENTRY_TYPE_EXTINT: - ioapic_set_extint(ioapic, pin); - break; - default: - panic("%s: invalid interrupt entry type %d\n", __func__, - intr->int_type); - } - if (intr->int_type == INTENTRY_TYPE_INT || - (intr->int_flags & INTENTRY_FLAGS_TRIGGER) != - INTENTRY_FLAGS_TRIGGER_CONFORM) - ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr)); - if (intr->int_type == INTENTRY_TYPE_INT || - (intr->int_flags & INTENTRY_FLAGS_POLARITY) != - INTENTRY_FLAGS_POLARITY_CONFORM) - ioapic_set_polarity(ioapic, pin, intentry_polarity(intr)); -} - -/* - * Parse an interrupt entry for a local APIC LVT pin. - */ -static void -mptable_parse_local_int(int_entry_ptr intr) -{ - u_int apic_id, pin; - - if (intr->dst_apic_id == 0xff) - apic_id = APIC_ID_ALL; - else - apic_id = intr->dst_apic_id; - if (intr->dst_apic_int == 0) - pin = LVT_LINT0; - else - pin = LVT_LINT1; - switch (intr->int_type) { - case INTENTRY_TYPE_INT: -#if 1 - printf( - "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n", - intr->dst_apic_int, intr->src_bus_irq); - return; -#else - lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED); - break; -#endif - case INTENTRY_TYPE_NMI: - lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); - break; - case INTENTRY_TYPE_SMI: - lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI); - break; - case INTENTRY_TYPE_EXTINT: - lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT); - break; - default: - panic("%s: invalid interrupt entry type %d\n", __func__, - intr->int_type); - } - if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) != - INTENTRY_FLAGS_TRIGGER_CONFORM) - lapic_set_lvt_triggermode(apic_id, pin, - intentry_trigger(intr)); - if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) != - INTENTRY_FLAGS_POLARITY_CONFORM) - lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr)); -} - -/* - * Parse interrupt entries. - */ -static void -mptable_parse_ints_handler(u_char *entry, void *arg __unused) -{ - int_entry_ptr intr; - - intr = (int_entry_ptr)entry; - switch (*entry) { - case MPCT_ENTRY_INT: - mptable_parse_io_int(intr); - break; - case MPCT_ENTRY_LOCAL_INT: - mptable_parse_local_int(intr); - break; - } -} - -/* - * Configure interrupt pins for a default configuration. For details see - * Table 5-2 in Section 5 of the MP Table specification. - */ -static void -mptable_parse_default_config_ints(void) -{ - struct INTENTRY entry; - int pin; - - /* - * All default configs route IRQs from bus 0 to the first 16 pins - * of the first I/O APIC with an APIC ID of 2. - */ - entry.type = MPCT_ENTRY_INT; - entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | - INTENTRY_FLAGS_TRIGGER_CONFORM; - entry.src_bus_id = 0; - entry.dst_apic_id = 2; - - /* Run through all 16 pins. */ - for (pin = 0; pin < 16; pin++) { - entry.dst_apic_int = pin; - switch (pin) { - case 0: - /* Pin 0 is an ExtINT pin. */ - entry.int_type = INTENTRY_TYPE_EXTINT; - break; - case 2: - /* IRQ 0 is routed to pin 2. */ - entry.int_type = INTENTRY_TYPE_INT; - entry.src_bus_irq = 0; - break; - default: - /* All other pins are identity mapped. */ - entry.int_type = INTENTRY_TYPE_INT; - entry.src_bus_irq = pin; - break; - } - mptable_parse_io_int(&entry); - } - - /* Certain configs disable certain pins. */ - if (mpfps->config_type == 7) - ioapic_disable_pin(ioapics[2], 0); - if (mpfps->config_type == 2) { - ioapic_disable_pin(ioapics[2], 2); - ioapic_disable_pin(ioapics[2], 13); - } -} - -/* - * Configure the interrupt pins - */ -static void -mptable_parse_ints(void) -{ - - /* Is this a pre-defined config? */ - if (mpfps->config_type != 0) { - /* Configure LINT pins. */ - lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT0, APIC_LVT_DM_EXTINT); - lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI); - - /* Configure I/O APIC pins. */ - mptable_parse_default_config_ints(); - } else - mptable_walk_table(mptable_parse_ints_handler, NULL); -} - -#ifdef MPTABLE_FORCE_HTT -/* - * Perform a hyperthreading "fix-up" to enumerate any logical CPU's - * that aren't already listed in the table. - * - * XXX: We assume that all of the physical CPUs in the - * system have the same number of logical CPUs. - * - * XXX: We assume that APIC ID's are allocated such that - * the APIC ID's for a physical processor are aligned - * with the number of logical CPU's in the processor. - */ -static void -mptable_hyperthread_fixup(u_long id_mask) -{ - u_int i, id, logical_cpus; - - /* Nothing to do if there is no HTT support. */ - if ((cpu_feature & CPUID_HTT) == 0) - return; - logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; - if (logical_cpus <= 1) - return; - - /* - * For each APIC ID of a CPU that is set in the mask, - * scan the other candidate APIC ID's for this - * physical processor. If any of those ID's are - * already in the table, then kill the fixup. - */ - for (id = 0; id <= MAX_LAPIC_ID; id++) { - if ((id_mask & 1 << id) == 0) - continue; - /* First, make sure we are on a logical_cpus boundary. */ - if (id % logical_cpus != 0) - return; - for (i = id + 1; i < id + logical_cpus; i++) - if ((id_mask & 1 << i) != 0) - return; - } - - /* - * Ok, the ID's checked out, so perform the fixup by - * adding the logical CPUs. - */ - while ((id = ffsl(id_mask)) != 0) { - id--; - for (i = id + 1; i < id + logical_cpus; i++) { - if (bootverbose) - printf( - "MPTable: Adding logical CPU %d from main CPU %d\n", - i, id); - lapic_create(i, 0); - } - id_mask &= ~(1 << id); - } -} -#endif /* MPTABLE_FORCE_HTT */ - -/* - * Support code for routing PCI interrupts using the MP Table. - */ -static void -mptable_pci_setup(void) -{ - int i; - - /* - * Find the first pci bus and call it 0. Panic if pci0 is not - * bus zero and there are multiple PCI busses. - */ - for (i = 0; i <= mptable_maxbusid; i++) - if (busses[i].bus_type == PCI) { - if (pci0 == -1) - pci0 = i; - else if (pci0 != 0) - panic( - "MPTable contains multiple PCI busses but no PCI bus 0"); - } -} - -static void -mptable_pci_probe_table_handler(u_char *entry, void *arg) -{ - struct pci_probe_table_args *args; - int_entry_ptr intr; - - if (*entry != MPCT_ENTRY_INT) - return; - intr = (int_entry_ptr)entry; - args = (struct pci_probe_table_args *)arg; - KASSERT(args->bus <= mptable_maxbusid, - ("bus %d is too big", args->bus)); - KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus")); - if (intr->src_bus_id == args->bus) - args->found = 1; -} - -int -mptable_pci_probe_table(int bus) -{ - struct pci_probe_table_args args; - - if (bus < 0) - return (EINVAL); - if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid) - return (ENXIO); - if (busses[pci0 + bus].bus_type != PCI) - return (ENXIO); - args.bus = pci0 + bus; - args.found = 0; - mptable_walk_table(mptable_pci_probe_table_handler, &args); - if (args.found == 0) - return (ENXIO); - return (0); -} - -static void -mptable_pci_route_interrupt_handler(u_char *entry, void *arg) -{ - struct pci_route_interrupt_args *args; - int_entry_ptr intr; - int vector; - - if (*entry != MPCT_ENTRY_INT) - return; - intr = (int_entry_ptr)entry; - args = (struct pci_route_interrupt_args *)arg; - if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq) - return; - - /* Make sure the APIC maps to a known APIC. */ - KASSERT(ioapics[intr->dst_apic_id] != NULL, - ("No I/O APIC %d to route interrupt to", intr->dst_apic_id)); - - /* - * Look up the vector for this APIC / pin combination. If we - * have previously matched an entry for this PCI IRQ but it - * has the same vector as this entry, just return. Otherwise, - * we use the vector for this APIC / pin combination. - */ - vector = ioapic_get_vector(ioapics[intr->dst_apic_id], - intr->dst_apic_int); - if (args->vector == vector) - return; - KASSERT(args->vector == -1, - ("Multiple IRQs for PCI interrupt %d.%d.INT%c: %d and %d\n", - args->bus, args->irq >> 2, 'A' + (args->irq & 0x3), args->vector, - vector)); - args->vector = vector; -} - -int -mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin) -{ - struct pci_route_interrupt_args args; - int slot; - - /* Like ACPI, pin numbers are 0-3, not 1-4. */ - pin--; - KASSERT(pci0 != -1, ("do not know how to route PCI interrupts")); - args.bus = pci_get_bus(dev) + pci0; - slot = pci_get_slot(dev); - - /* - * PCI interrupt entries in the MP Table encode both the slot and - * pin into the IRQ with the pin being the two least significant - * bits, the slot being the next five bits, and the most significant - * bit being reserved. - */ - args.irq = slot << 2 | pin; - args.vector = -1; - mptable_walk_table(mptable_pci_route_interrupt_handler, &args); - if (args.vector < 0) { - device_printf(pcib, "unable to route slot %d INT%c\n", slot, - 'A' + pin); - return (PCI_INVALID_IRQ); - } - if (bootverbose) - device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, - 'A' + pin, args.vector); - return (args.vector); -} diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c deleted file mode 100644 index 037d4ac..0000000 --- a/sys/amd64/amd64/nexus.c +++ /dev/null @@ -1,704 +0,0 @@ -/*- - * Copyright 1998 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * This code implements a `root nexus' for Intel Architecture - * machines. The function of the root nexus is to serve as an - * attachment point for both processors and buses, and to manage - * resources which are common to all of them. In particular, - * this code implements the core resource managers for interrupt - * requests, DMA requests (which rightfully should be a part of the - * ISA code but it's easier to do it here for now), I/O port addresses, - * and I/O memory address space. - */ - -#include "opt_isa.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/linker.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <machine/bus.h> -#include <machine/intr_machdep.h> -#include <sys/rman.h> -#include <sys/interrupt.h> - -#include <machine/vmparam.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <machine/pmap.h> - -#include <machine/metadata.h> -#include <machine/nexusvar.h> -#include <machine/resource.h> -#include <machine/pc/bios.h> - -#include "pcib_if.h" - -#ifdef DEV_ISA -#include <isa/isavar.h> -#include <x86/isa/isa.h> -#endif -#include <sys/rtprio.h> - -static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); - -#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) - -struct rman irq_rman, drq_rman, port_rman, mem_rman; - -static int nexus_probe(device_t); -static int nexus_attach(device_t); -static int nexus_print_all_resources(device_t dev); -static int nexus_print_child(device_t, device_t); -static device_t nexus_add_child(device_t bus, u_int order, const char *name, - int unit); -static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, - u_long, u_long, u_long, u_int); -#ifdef SMP -static int nexus_bind_intr(device_t, device_t, struct resource *, int); -#endif -static int nexus_config_intr(device_t, int, enum intr_trigger, - enum intr_polarity); -static int nexus_describe_intr(device_t dev, device_t child, - struct resource *irq, void *cookie, - const char *descr); -static int nexus_activate_resource(device_t, device_t, int, int, - struct resource *); -static int nexus_deactivate_resource(device_t, device_t, int, int, - struct resource *); -static int nexus_release_resource(device_t, device_t, int, int, - struct resource *); -static int nexus_setup_intr(device_t, device_t, struct resource *, int flags, - driver_filter_t filter, void (*)(void *), void *, - void **); -static int nexus_teardown_intr(device_t, device_t, struct resource *, - void *); -static struct resource_list *nexus_get_reslist(device_t dev, device_t child); -static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); -static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *); -static void nexus_delete_resource(device_t, device_t, int, int); -static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs); -static int nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs); -static int nexus_alloc_msix(device_t pcib, device_t dev, int *irq); -static int nexus_release_msix(device_t pcib, device_t dev, int irq); -static int nexus_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data); - -static device_method_t nexus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, nexus_probe), - DEVMETHOD(device_attach, nexus_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, nexus_print_child), - DEVMETHOD(bus_add_child, nexus_add_child), - DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), - DEVMETHOD(bus_release_resource, nexus_release_resource), - DEVMETHOD(bus_activate_resource, nexus_activate_resource), - DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), - DEVMETHOD(bus_setup_intr, nexus_setup_intr), - DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), -#ifdef SMP - DEVMETHOD(bus_bind_intr, nexus_bind_intr), -#endif - DEVMETHOD(bus_config_intr, nexus_config_intr), - DEVMETHOD(bus_describe_intr, nexus_describe_intr), - DEVMETHOD(bus_get_resource_list, nexus_get_reslist), - DEVMETHOD(bus_set_resource, nexus_set_resource), - DEVMETHOD(bus_get_resource, nexus_get_resource), - DEVMETHOD(bus_delete_resource, nexus_delete_resource), - - /* pcib interface */ - DEVMETHOD(pcib_alloc_msi, nexus_alloc_msi), - DEVMETHOD(pcib_release_msi, nexus_release_msi), - DEVMETHOD(pcib_alloc_msix, nexus_alloc_msix), - DEVMETHOD(pcib_release_msix, nexus_release_msix), - DEVMETHOD(pcib_map_msi, nexus_map_msi), - - { 0, 0 } -}; - -DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, 1); -static devclass_t nexus_devclass; - -DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); - -static int -nexus_probe(device_t dev) -{ - - device_quiet(dev); /* suppress attach message for neatness */ - return (BUS_PROBE_GENERIC); -} - -void -nexus_init_resources(void) -{ - int irq; - - /* - * XXX working notes: - * - * - IRQ resource creation should be moved to the PIC/APIC driver. - * - DRQ resource creation should be moved to the DMAC driver. - * - The above should be sorted to probe earlier than any child busses. - * - * - Leave I/O and memory creation here, as child probes may need them. - * (especially eg. ACPI) - */ - - /* - * IRQ's are on the mainboard on old systems, but on the ISA part - * of PCI->ISA bridges. There would be multiple sets of IRQs on - * multi-ISA-bus systems. PCI interrupts are routed to the ISA - * component, so in a way, PCI can be a partial child of an ISA bus(!). - * APIC interrupts are global though. - */ - irq_rman.rm_start = 0; - irq_rman.rm_type = RMAN_ARRAY; - irq_rman.rm_descr = "Interrupt request lines"; - irq_rman.rm_end = NUM_IO_INTS - 1; - if (rman_init(&irq_rman)) - panic("nexus_init_resources irq_rman"); - - /* - * We search for regions of existing IRQs and add those to the IRQ - * resource manager. - */ - for (irq = 0; irq < NUM_IO_INTS; irq++) - if (intr_lookup_source(irq) != NULL) - if (rman_manage_region(&irq_rman, irq, irq) != 0) - panic("nexus_init_resources irq_rman add"); - - /* - * ISA DMA on PCI systems is implemented in the ISA part of each - * PCI->ISA bridge and the channels can be duplicated if there are - * multiple bridges. (eg: laptops with docking stations) - */ - drq_rman.rm_start = 0; - drq_rman.rm_end = 7; - drq_rman.rm_type = RMAN_ARRAY; - drq_rman.rm_descr = "DMA request lines"; - /* XXX drq 0 not available on some machines */ - if (rman_init(&drq_rman) - || rman_manage_region(&drq_rman, - drq_rman.rm_start, drq_rman.rm_end)) - panic("nexus_init_resources drq_rman"); - - /* - * However, IO ports and Memory truely are global at this level, - * as are APIC interrupts (however many IO APICS there turn out - * to be on large systems..) - */ - port_rman.rm_start = 0; - port_rman.rm_end = 0xffff; - port_rman.rm_type = RMAN_ARRAY; - port_rman.rm_descr = "I/O ports"; - if (rman_init(&port_rman) - || rman_manage_region(&port_rman, 0, 0xffff)) - panic("nexus_init_resources port_rman"); - - mem_rman.rm_start = 0; - mem_rman.rm_end = ~0u; - mem_rman.rm_type = RMAN_ARRAY; - mem_rman.rm_descr = "I/O memory addresses"; - if (rman_init(&mem_rman) - || rman_manage_region(&mem_rman, 0, ~0)) - panic("nexus_init_resources mem_rman"); -} - -static int -nexus_attach(device_t dev) -{ - - nexus_init_resources(); - bus_generic_probe(dev); - - /* - * Explicitly add the legacy0 device here. Other platform - * types (such as ACPI), use their own nexus(4) subclass - * driver to override this routine and add their own root bus. - */ - if (BUS_ADD_CHILD(dev, 10, "legacy", 0) == NULL) - panic("legacy: could not attach"); - bus_generic_attach(dev); - return 0; -} - -static int -nexus_print_all_resources(device_t dev) -{ - struct nexus_device *ndev = DEVTONX(dev); - struct resource_list *rl = &ndev->nx_resources; - int retval = 0; - - if (STAILQ_FIRST(rl)) - retval += printf(" at"); - - retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); - retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); - retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); - - return retval; -} - -static int -nexus_print_child(device_t bus, device_t child) -{ - int retval = 0; - - retval += bus_print_child_header(bus, child); - retval += nexus_print_all_resources(child); - if (device_get_flags(child)) - retval += printf(" flags %#x", device_get_flags(child)); - retval += printf(" on motherboard\n"); /* XXX "motherboard", ick */ - - return (retval); -} - -static device_t -nexus_add_child(device_t bus, u_int order, const char *name, int unit) -{ - device_t child; - struct nexus_device *ndev; - - ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO); - if (!ndev) - return(0); - resource_list_init(&ndev->nx_resources); - - child = device_add_child_ordered(bus, order, name, unit); - - /* should we free this in nexus_child_detached? */ - device_set_ivars(child, ndev); - - return(child); -} - -/* - * Allocate a resource on behalf of child. NB: child is usually going to be a - * child of one of our descendants, not a direct child of nexus0. - */ -static struct resource * -nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct nexus_device *ndev = DEVTONX(child); - struct resource *rv; - struct resource_list_entry *rle; - struct rman *rm; - int needactivate = flags & RF_ACTIVE; - - /* - * If this is an allocation of the "default" range for a given RID, and - * we know what the resources for this device are (ie. they aren't maintained - * by a child bus), then work out the start/end values. - */ - if ((start == 0UL) && (end == ~0UL) && (count == 1)) { - if (ndev == NULL) - return(NULL); - rle = resource_list_find(&ndev->nx_resources, type, *rid); - if (rle == NULL) - return(NULL); - start = rle->start; - end = rle->end; - count = rle->count; - } - - flags &= ~RF_ACTIVE; - - switch (type) { - case SYS_RES_IRQ: - rm = &irq_rman; - break; - - case SYS_RES_DRQ: - rm = &drq_rman; - break; - - case SYS_RES_IOPORT: - rm = &port_rman; - break; - - case SYS_RES_MEMORY: - rm = &mem_rman; - break; - - default: - return 0; - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) - return 0; - rman_set_rid(rv, *rid); - - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return 0; - } - } - - return rv; -} - -static int -nexus_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - - /* - * If this is a memory resource, map it into the kernel. - */ - if (type == SYS_RES_MEMORY) { - void *vaddr; - - vaddr = pmap_mapdev(rman_get_start(r), rman_get_size(r)); - rman_set_virtual(r, vaddr); - rman_set_bustag(r, AMD64_BUS_SPACE_MEM); - rman_set_bushandle(r, (bus_space_handle_t) vaddr); - } else if (type == SYS_RES_IOPORT) { - rman_set_bustag(r, AMD64_BUS_SPACE_IO); - rman_set_bushandle(r, rman_get_start(r)); - } - return (rman_activate_resource(r)); -} - -static int -nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - /* - * If this is a memory resource, unmap it. - */ - if (type == SYS_RES_MEMORY) { - pmap_unmapdev((vm_offset_t)rman_get_virtual(r), - rman_get_size(r)); - } - - return (rman_deactivate_resource(r)); -} - -static int -nexus_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - if (rman_get_flags(r) & RF_ACTIVE) { - int error = bus_deactivate_resource(child, type, rid, r); - if (error) - return error; - } - return (rman_release_resource(r)); -} - -/* - * Currently this uses the really grody interface from kern/kern_intr.c - * (which really doesn't belong in kern/anything.c). Eventually, all of - * the code in kern_intr.c and machdep_intr.c should get moved here, since - * this is going to be the official interface. - */ -static int -nexus_setup_intr(device_t bus, device_t child, struct resource *irq, - int flags, driver_filter_t filter, void (*ihand)(void *), - void *arg, void **cookiep) -{ - int error; - - /* somebody tried to setup an irq that failed to allocate! */ - if (irq == NULL) - panic("nexus_setup_intr: NULL irq resource!"); - - *cookiep = 0; - if ((rman_get_flags(irq) & RF_SHAREABLE) == 0) - flags |= INTR_EXCL; - - /* - * We depend here on rman_activate_resource() being idempotent. - */ - error = rman_activate_resource(irq); - if (error) - return (error); - - error = intr_add_handler(device_get_nameunit(child), - rman_get_start(irq), filter, ihand, arg, flags, cookiep); - - return (error); -} - -static int -nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) -{ - return (intr_remove_handler(ih)); -} - -#ifdef SMP -static int -nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) -{ - return (intr_bind(rman_get_start(irq), cpu)); -} -#endif - -static int -nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, - enum intr_polarity pol) -{ - return (intr_config_intr(irq, trig, pol)); -} - -static int -nexus_describe_intr(device_t dev, device_t child, struct resource *irq, - void *cookie, const char *descr) -{ - - return (intr_describe(rman_get_start(irq), cookie, descr)); -} - -static struct resource_list * -nexus_get_reslist(device_t dev, device_t child) -{ - struct nexus_device *ndev = DEVTONX(child); - - return (&ndev->nx_resources); -} - -static int -nexus_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count) -{ - struct nexus_device *ndev = DEVTONX(child); - struct resource_list *rl = &ndev->nx_resources; - - /* XXX this should return a success/failure indicator */ - resource_list_add(rl, type, rid, start, start + count - 1, count); - return(0); -} - -static int -nexus_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp) -{ - struct nexus_device *ndev = DEVTONX(child); - struct resource_list *rl = &ndev->nx_resources; - struct resource_list_entry *rle; - - rle = resource_list_find(rl, type, rid); - if (!rle) - return(ENOENT); - if (startp) - *startp = rle->start; - if (countp) - *countp = rle->count; - return(0); -} - -static void -nexus_delete_resource(device_t dev, device_t child, int type, int rid) -{ - struct nexus_device *ndev = DEVTONX(child); - struct resource_list *rl = &ndev->nx_resources; - - resource_list_delete(rl, type, rid); -} - -/* Called from the MSI code to add new IRQs to the IRQ rman. */ -void -nexus_add_irq(u_long irq) -{ - - if (rman_manage_region(&irq_rman, irq, irq) != 0) - panic("%s: failed", __func__); -} - -static int -nexus_alloc_msix(device_t pcib, device_t dev, int *irq) -{ - - return (msix_alloc(dev, irq)); -} - -static int -nexus_release_msix(device_t pcib, device_t dev, int irq) -{ - - return (msix_release(irq)); -} - -static int -nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) -{ - - return (msi_alloc(dev, count, maxcount, irqs)); -} - -static int -nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs) -{ - - return (msi_release(irqs, count)); -} - -static int -nexus_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data) -{ - - return (msi_map(irq, addr, data)); -} - -/* Placeholder for system RAM. */ -static void -ram_identify(driver_t *driver, device_t parent) -{ - - if (resource_disabled("ram", 0)) - return; - if (BUS_ADD_CHILD(parent, 0, "ram", 0) == NULL) - panic("ram_identify"); -} - -static int -ram_probe(device_t dev) -{ - - device_quiet(dev); - device_set_desc(dev, "System RAM"); - return (0); -} - -static int -ram_attach(device_t dev) -{ - struct bios_smap *smapbase, *smap, *smapend; - struct resource *res; - caddr_t kmdp; - uint32_t smapsize; - int error, rid; - - /* Retrieve the system memory map from the loader. */ - kmdp = preload_search_by_type("elf kernel"); - if (kmdp == NULL) - kmdp = preload_search_by_type("elf64 kernel"); - smapbase = (struct bios_smap *)preload_search_info(kmdp, - MODINFO_METADATA | MODINFOMD_SMAP); - smapsize = *((u_int32_t *)smapbase - 1); - smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize); - - rid = 0; - for (smap = smapbase; smap < smapend; smap++) { - if (smap->type != SMAP_TYPE_MEMORY || smap->length == 0) - continue; - error = bus_set_resource(dev, SYS_RES_MEMORY, rid, smap->base, - smap->length); - if (error) - panic("ram_attach: resource %d failed set with %d", rid, - error); - res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0); - if (res == NULL) - panic("ram_attach: resource %d failed to attach", rid); - rid++; - } - return (0); -} - -static device_method_t ram_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, ram_identify), - DEVMETHOD(device_probe, ram_probe), - DEVMETHOD(device_attach, ram_attach), - { 0, 0 } -}; - -static driver_t ram_driver = { - "ram", - ram_methods, - 1, /* no softc */ -}; - -static devclass_t ram_devclass; - -DRIVER_MODULE(ram, nexus, ram_driver, ram_devclass, 0, 0); - -#ifdef DEV_ISA -/* - * Placeholder which claims PnP 'devices' which describe system - * resources. - */ -static struct isa_pnp_id sysresource_ids[] = { - { 0x010cd041 /* PNP0c01 */, "System Memory" }, - { 0x020cd041 /* PNP0c02 */, "System Resource" }, - { 0 } -}; - -static int -sysresource_probe(device_t dev) -{ - int result; - - if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, sysresource_ids)) <= 0) { - device_quiet(dev); - } - return(result); -} - -static int -sysresource_attach(device_t dev) -{ - return(0); -} - -static device_method_t sysresource_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sysresource_probe), - DEVMETHOD(device_attach, sysresource_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - { 0, 0 } -}; - -static driver_t sysresource_driver = { - "sysresource", - sysresource_methods, - 1, /* no softc */ -}; - -static devclass_t sysresource_devclass; - -DRIVER_MODULE(sysresource, isa, sysresource_driver, sysresource_devclass, 0, 0); -#endif /* DEV_ISA */ diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 0203917..aa20133 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -462,7 +462,7 @@ create_pagetables(vm_paddr_t *firstaddr) if (ndmpdp < 4) /* Minimum 4GB of dirmap */ ndmpdp = 4; DMPDPphys = allocpages(firstaddr, NDMPML4E); - if (TRUE || (amd_feature & AMDID_PAGE1GB) == 0) + if ((amd_feature & AMDID_PAGE1GB) == 0) DMPDphys = allocpages(firstaddr, ndmpdp); dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT; @@ -494,11 +494,16 @@ create_pagetables(vm_paddr_t *firstaddr) ((pdp_entry_t *)KPDPphys)[i + KPDPI] |= PG_RW | PG_V | PG_U; } - /* Now set up the direct map space using either 2MB or 1GB pages */ - /* Preset PG_M and PG_A because demotion expects it */ - if (TRUE || (amd_feature & AMDID_PAGE1GB) == 0) { + /* + * Now, set up the direct map region using either 2MB or 1GB pages. + * Later, if pmap_mapdev{_attr}() uses the direct map for non-write- + * back memory, pmap_change_attr() will demote any 2MB or 1GB page + * mappings that are partially used. + */ + if ((amd_feature & AMDID_PAGE1GB) == 0) { for (i = 0; i < NPDEPG * ndmpdp; i++) { ((pd_entry_t *)DMPDphys)[i] = (vm_paddr_t)i << PDRSHIFT; + /* Preset PG_M and PG_A because demotion expects it. */ ((pd_entry_t *)DMPDphys)[i] |= PG_RW | PG_V | PG_PS | PG_G | PG_M | PG_A; } @@ -512,6 +517,7 @@ create_pagetables(vm_paddr_t *firstaddr) for (i = 0; i < ndmpdp; i++) { ((pdp_entry_t *)DMPDPphys)[i] = (vm_paddr_t)i << PDPSHIFT; + /* Preset PG_M and PG_A because demotion expects it. */ ((pdp_entry_t *)DMPDPphys)[i] |= PG_RW | PG_V | PG_PS | PG_G | PG_M | PG_A; } @@ -4948,6 +4954,54 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) } /* + * Demotes any mapping within the direct map region that covers more than the + * specified range of physical addresses. This range's size must be a power + * of two and its starting address must be a multiple of its size. Since the + * demotion does not change any attributes of the mapping, a TLB invalidation + * is not mandatory. The caller may, however, request a TLB invalidation. + */ +void +pmap_demote_DMAP(vm_paddr_t base, vm_size_t len, boolean_t invalidate) +{ + pdp_entry_t *pdpe; + pd_entry_t *pde; + vm_offset_t va; + boolean_t changed; + + if (len == 0) + return; + KASSERT(powerof2(len), ("pmap_demote_DMAP: len is not a power of 2")); + KASSERT((base & (len - 1)) == 0, + ("pmap_demote_DMAP: base is not a multiple of len")); + if (len < NBPDP && base < dmaplimit) { + va = PHYS_TO_DMAP(base); + changed = FALSE; + PMAP_LOCK(kernel_pmap); + pdpe = pmap_pdpe(kernel_pmap, va); + if ((*pdpe & PG_V) == 0) + panic("pmap_demote_DMAP: invalid PDPE"); + if ((*pdpe & PG_PS) != 0) { + if (!pmap_demote_pdpe(kernel_pmap, pdpe, va)) + panic("pmap_demote_DMAP: PDPE failed"); + changed = TRUE; + } + if (len < NBPDR) { + pde = pmap_pdpe_to_pde(pdpe, va); + if ((*pde & PG_V) == 0) + panic("pmap_demote_DMAP: invalid PDE"); + if ((*pde & PG_PS) != 0) { + if (!pmap_demote_pde(kernel_pmap, pde, va)) + panic("pmap_demote_DMAP: PDE failed"); + changed = TRUE; + } + } + if (changed && invalidate) + pmap_invalidate_page(kernel_pmap, va); + PMAP_UNLOCK(kernel_pmap); + } +} + +/* * perform the pmap work for mincore */ int diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 69e94d9..786d8ec 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -83,7 +83,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/pcb.h> #ifdef SMP diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 53a4d63..45ccc64 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -307,6 +307,7 @@ extern vm_offset_t virtual_end; void pmap_bootstrap(vm_paddr_t *); int pmap_change_attr(vm_offset_t, vm_size_t, int); +void pmap_demote_DMAP(vm_paddr_t base, vm_size_t len, boolean_t invalidate); void pmap_init_pat(void); void pmap_kenter(vm_offset_t va, vm_paddr_t pa); void *pmap_kenter_temporary(vm_paddr_t pa, int i); diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index 0f725c8..4adb025 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -159,7 +159,7 @@ _startC(void) #if defined(FLASHADDR) && defined(LOADERRAMADDR) unsigned int pc; - __asm __volatile("adr %0, _start\n" + __asm __volatile("mov %0, pc\n" : "=r" (pc)); if ((FLASHADDR > LOADERRAMADDR && pc >= FLASHADDR) || (FLASHADDR < LOADERRAMADDR && pc < LOADERRAMADDR)) { @@ -173,11 +173,13 @@ _startC(void) */ unsigned int target_addr; unsigned int tmp_sp; + uint32_t src_addr = (uint32_t)&_start - PHYSADDR + FLASHADDR + + (pc - FLASHADDR - ((uint32_t)&_startC - PHYSADDR)) & 0xfffff000; target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR; tmp_sp = target_addr + 0x100000 + (unsigned int)&_end - (unsigned int)&_start; - memcpy((char *)target_addr, (char *)pc, + memcpy((char *)target_addr, (char *)src_addr, (unsigned int)&_end - (unsigned int)&_start); /* Temporary set the sp and jump to the new location. */ __asm __volatile( diff --git a/sys/boot/ofw/common/main.c b/sys/boot/ofw/common/main.c index 1a03e9b..52e69199 100644 --- a/sys/boot/ofw/common/main.c +++ b/sys/boot/ofw/common/main.c @@ -41,19 +41,23 @@ extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; -u_int32_t acells; +u_int32_t acells, scells; static char bootargs[128]; #define HEAP_SIZE 0x80000 +#define OF_puts(fd, text) OF_write(fd, text, strlen(text)) + void init_heap(void) { void *base; + ihandle_t stdout; if ((base = ofw_alloc_heap(HEAP_SIZE)) == (void *)0xffffffff) { - printf("Heap memory claim failed!\n"); + OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); + OF_puts(stdout, "Heap memory claim failed!\n"); OF_enter(); } @@ -64,25 +68,20 @@ uint64_t memsize(void) { phandle_t memoryp; - struct ofw_reg reg[4]; - struct ofw_reg2 reg2[8]; - int i; - u_int64_t sz, memsz; + cell_t reg[24]; + int i, sz; + u_int64_t memsz; + memsz = 0; memoryp = OF_instance_to_package(memory); - if (acells == 1) { - sz = OF_getprop(memoryp, "reg", ®, sizeof(reg)); - sz /= sizeof(struct ofw_reg); + sz = OF_getprop(memoryp, "reg", ®, sizeof(reg)); + sz /= sizeof(reg[0]); - for (i = 0, memsz = 0; i < sz; i++) - memsz += reg[i].size; - } else if (acells == 2) { - sz = OF_getprop(memoryp, "reg", ®2, sizeof(reg2)); - sz /= sizeof(struct ofw_reg2); - - for (i = 0, memsz = 0; i < sz; i++) - memsz += reg2[i].size; + for (i = 0; i < sz; i += (acells + scells)) { + if (scells > 1) + memsz += (uint64_t)reg[i + acells] << 32; + memsz += reg[i + acells + scells - 1]; } return (memsz); @@ -105,13 +104,9 @@ main(int (*openfirm)(void *)) root = OF_finddevice("/"); - acells = 1; + scells = acells = 1; OF_getprop(root, "#address-cells", &acells, sizeof(acells)); - - /* - * Set up console. - */ - cons_probe(); + OF_getprop(root, "#size-cells", &scells, sizeof(scells)); /* * Initialise the heap as early as possible. Once this is done, @@ -121,6 +116,11 @@ main(int (*openfirm)(void *)) init_heap(); /* + * Set up console. + */ + cons_probe(); + + /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) diff --git a/sys/boot/ofw/libofw/ofw_memory.c b/sys/boot/ofw/libofw/ofw_memory.c index ebf01af..60cc904 100644 --- a/sys/boot/ofw/libofw/ofw_memory.c +++ b/sys/boot/ofw/libofw/ofw_memory.c @@ -118,13 +118,19 @@ ofw_memmap(int acells) void * ofw_alloc_heap(unsigned int size) { - phandle_t memoryp; - struct ofw_reg available; + phandle_t memoryp, root; + cell_t available[4]; + cell_t acells; + + root = OF_finddevice("/"); + acells = 1; + OF_getprop(root, "#address-cells", &acells, sizeof(acells)); memoryp = OF_instance_to_package(memory); - OF_getprop(memoryp, "available", &available, sizeof(available)); + OF_getprop(memoryp, "available", available, sizeof(available)); - heap_base = OF_claim((void *)available.base, size, sizeof(register_t)); + heap_base = OF_claim((void *)available[acells-1], size, + sizeof(register_t)); if (heap_base != (void *)-1) { heap_size = size; diff --git a/sys/boot/ofw/libofw/ofw_net.c b/sys/boot/ofw/libofw/ofw_net.c index 17e1125..830fcda 100644 --- a/sys/boot/ofw/libofw/ofw_net.c +++ b/sys/boot/ofw/libofw/ofw_net.c @@ -230,7 +230,10 @@ punt: static void ofwn_end(struct netif *nif) { +#ifdef BROKEN + /* dma-free freezes at least some Apple ethernet controllers */ OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS); +#endif OF_close(netinstance); } diff --git a/sys/boot/ofw/libofw/openfirm.c b/sys/boot/ofw/libofw/openfirm.c index 8786d5d..4b84fa1 100644 --- a/sys/boot/ofw/libofw/openfirm.c +++ b/sys/boot/ofw/libofw/openfirm.c @@ -80,8 +80,13 @@ OF_init(int (*openfirm)(void *)) if ((chosen = OF_finddevice("/chosen")) == -1) OF_exit(); - if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) - OF_exit(); + if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) { + memory = OF_open("/memory"); + if (memory == -1) + memory = OF_open("/memory@0"); + if (memory == -1) + OF_exit(); + } if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1) OF_exit(); } diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c index b3e7908..97f566c 100644 --- a/sys/boot/sparc64/loader/main.c +++ b/sys/boot/sparc64/loader/main.c @@ -811,15 +811,15 @@ main(int (*openfirm)(void *)) archsw.arch_autoload = sparc64_autoload; archsw.arch_maphint = sparc64_maphint; + if (init_heap() == (vm_offset_t)-1) + OF_exit(); + setheap((void *)heapva, (void *)(heapva + HEAPSZ)); + /* * Probe for a console. */ cons_probe(); - if (init_heap() == (vm_offset_t)-1) - panic("%s: can't claim heap", __func__); - setheap((void *)heapva, (void *)(heapva + HEAPSZ)); - if ((root = OF_peer(0)) == -1) panic("%s: can't get root phandle", __func__); OF_getprop(root, "compatible", compatible, sizeof(compatible)); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c index 133343b..26b4e5f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c @@ -192,7 +192,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length, ASSERT(length <= DMU_MAX_ACCESS); - dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT; + dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT; if (flags & DMU_READ_NO_PREFETCH || length > zfetch_array_rd_sz) dbuf_flags |= DB_RF_NOPREFETCH; @@ -209,6 +209,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length, os_dsl_dataset->ds_object, (longlong_t)dn->dn_object, dn->dn_datablksz, (longlong_t)offset, (longlong_t)length); + rw_exit(&dn->dn_struct_rwlock); return (EIO); } nblks = 1; @@ -231,9 +232,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length, } /* initiate async i/o */ if (read) { - rw_exit(&dn->dn_struct_rwlock); (void) dbuf_read(db, zio, dbuf_flags); - rw_enter(&dn->dn_struct_rwlock, RW_READER); } dbp[i] = &db->db; } @@ -540,7 +539,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size, { dnode_t *dn; dmu_buf_t **dbp; - int numbufs, i, err; + int numbufs, err; err = dnode_hold(os->os, object, FTAG, &dn); if (err) @@ -551,7 +550,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size, * block. If we ever do the tail block optimization, we will need to * handle that here as well. */ - if (dn->dn_datablkshift == 0) { + if (dn->dn_maxblkid == 0) { int newsz = offset > dn->dn_datablksz ? 0 : MIN(size, dn->dn_datablksz - offset); bzero((char *)buf + newsz, size - newsz); @@ -560,6 +559,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size, while (size > 0) { uint64_t mylen = MIN(size, DMU_MAX_ACCESS / 2); + int i; /* * NB: we could do this block-at-a-time, but it's nice diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index bcbe514..ba0f0eb 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1031,6 +1031,10 @@ zfs_get_done(dmu_buf_t *db, void *vzgd) VFS_UNLOCK_GIANT(vfslocked); } +#ifdef DEBUG +static int zil_fault_io = 0; +#endif + /* * Get data to generate a TX_WRITE intent log record. */ @@ -1112,7 +1116,21 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) zgd->zgd_rl = rl; zgd->zgd_zilog = zfsvfs->z_log; zgd->zgd_bp = &lr->lr_blkptr; - VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db)); +#ifdef DEBUG + if (zil_fault_io) { + error = EIO; + zil_fault_io = 0; + } else { + error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db); + } +#else + error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db); +#endif + if (error != 0) { + kmem_free(zgd, sizeof (zgd_t)); + goto out; + } + ASSERT(boff == db->db_offset); lr->lr_blkoff = off - boff; error = dmu_sync(zio, db, &lr->lr_blkptr, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c index 1dd8ea0..490e50f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c @@ -933,6 +933,10 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb) } error = zilog->zl_get_data( itx->itx_private, lr, dbuf, lwb->lwb_zio); + if (error == EIO) { + txg_wait_synced(zilog->zl_dmu_pool, txg); + return (lwb); + } if (error) { ASSERT(error == ENOENT || error == EEXIST || error == EALREADY); diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a3b113b..fb4bc2f 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -104,7 +104,6 @@ amd64/amd64/cpu_switch.S standard amd64/amd64/db_disasm.c optional ddb amd64/amd64/db_interface.c optional ddb amd64/amd64/db_trace.c optional ddb -amd64/amd64/dump_machdep.c standard amd64/amd64/elf_machdep.c standard amd64/amd64/exception.S standard amd64/amd64/fpu.c standard @@ -122,9 +121,6 @@ amd64/amd64/minidump_machdep.c standard amd64/amd64/mp_machdep.c optional smp amd64/amd64/mp_watchdog.c optional mp_watchdog smp amd64/amd64/mpboot.S optional smp -amd64/amd64/mptable.c optional mptable -amd64/amd64/mptable_pci.c optional mptable pci -amd64/amd64/nexus.c standard amd64/amd64/pmap.c standard amd64/amd64/prof_machdep.c optional profiling-routine amd64/amd64/sigtramp.S standard @@ -321,7 +317,11 @@ x86/isa/isa_dma.c standard x86/isa/nmi.c standard x86/isa/orm.c optional isa x86/pci/qpi.c standard +x86/x86/dump_machdep.c standard x86/x86/io_apic.c standard x86/x86/local_apic.c standard x86/x86/mca.c standard +x86/x86/mptable.c optional mptable +x86/x86/mptable_pci.c optional mptable pci x86/x86/msi.c optional pci +x86/x86/nexus.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index f10a234..cb05bec 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -263,7 +263,6 @@ i386/i386/busdma_machdep.c standard i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb -i386/i386/dump_machdep.c standard i386/i386/elan-mmcr.c optional cpu_elan | cpu_soekris i386/i386/elf_machdep.c standard i386/i386/exception.s optional native @@ -290,10 +289,7 @@ i386/i386/mp_machdep.c optional native smp i386/xen/mp_machdep.c optional xen smp i386/i386/mp_watchdog.c optional mp_watchdog smp i386/i386/mpboot.s optional smp native -i386/i386/mptable.c optional apic native i386/xen/mptable.c optional apic xen -i386/i386/mptable_pci.c optional apic pci -i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon i386/i386/pmap.c optional native i386/xen/pmap.c optional xen @@ -395,7 +391,11 @@ x86/isa/isa_dma.c optional isa x86/isa/nmi.c standard x86/isa/orm.c optional isa x86/pci/qpi.c standard +x86/x86/dump_machdep.c standard x86/x86/io_apic.c optional apic x86/x86/local_apic.c optional apic x86/x86/mca.c standard +x86/x86/mptable.c optional apic native +x86/x86/mptable_pci.c optional apic pci x86/x86/msi.c optional apic pci +x86/x86/nexus.c standard diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index 7f90e9f..ab88e22 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -138,7 +138,6 @@ i386/i386/busdma_machdep.c standard i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb -i386/i386/dump_machdep.c standard i386/i386/elf_machdep.c standard i386/i386/exception.s standard i386/i386/gdb_machdep.c optional gdb @@ -157,9 +156,6 @@ i386/i386/mp_clock.c optional smp i386/i386/mp_machdep.c optional smp i386/i386/mp_watchdog.c optional mp_watchdog smp i386/i386/mpboot.s optional smp -i386/i386/mptable.c optional apic -i386/i386/mptable_pci.c optional apic pci -i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon i386/i386/pmap.c standard i386/i386/ptrace_machdep.c standard @@ -255,7 +251,11 @@ pc98/pc98/pc98_machdep.c standard x86/isa/atpic.c optional atpic x86/isa/clock.c standard x86/isa/isa.c optional isa +x86/x86/dump_machdep.c standard x86/x86/io_apic.c optional apic x86/x86/local_apic.c optional apic x86/x86/mca.c standard +x86/x86/mptable.c optional apic +x86/x86/mptable_pci.c optional apic pci x86/x86/msi.c optional apic pci +x86/x86/nexus.c standard diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 0dfe031..021c51d 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -22,6 +22,7 @@ dev/adb/adb_kbd.c optional adb dev/adb/adb_mouse.c optional adb dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb +dev/agp/agp_apple.c optional agp powermac dev/cfi/cfi_bus_fdt.c optional cfi fdt dev/fb/fb.c optional sc dev/fdt/fdt_powerpc.c optional fdt diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index c7e6281..80b1bc2 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -169,6 +169,9 @@ _ILINKS= machine .if ${MACHINE} != ${MACHINE_CPUARCH} _ILINKS+= ${MACHINE_CPUARCH} .endif +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +_ILINKS+= x86 +.endif # Ensure that the link exists without depending on it when it exists. .for _link in ${_ILINKS} @@ -181,8 +184,8 @@ ${_ILINKS}: @case ${.TARGET} in \ machine) \ path=${S}/${MACHINE}/include ;; \ - ${MACHINE_CPUARCH}) \ - path=${S}/${MACHINE_CPUARCH}/include ;; \ + *) \ + path=${S}/${.TARGET}/include ;; \ esac ; \ ${ECHO} ${.TARGET} "->" $$path ; \ ln -s $$path ${.TARGET} diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index de4ba36..2239d66 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -238,6 +238,9 @@ _ILINKS=@ machine .if ${MACHINE} != ${MACHINE_CPUARCH} _ILINKS+=${MACHINE_CPUARCH} .endif +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +_ILINKS+=x86 +.endif all: objwarn ${PROG} @@ -263,12 +266,12 @@ SYSDIR= ${_dir} ${_ILINKS}: @case ${.TARGET} in \ - ${MACHINE_CPUARCH}) \ - path=${SYSDIR}/${MACHINE_CPUARCH}/include ;; \ machine) \ path=${SYSDIR}/${MACHINE}/include ;; \ @) \ path=${SYSDIR} ;; \ + *) \ + path=${SYSDIR}/${.TARGET}/include ;; \ esac ; \ path=`(cd $$path && /bin/pwd)` ; \ ${ECHO} ${.TARGET} "->" $$path ; \ diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 index 78660e2..1bb60fe 100644 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -8,6 +8,7 @@ COUNT_IPIS opt_smp.h MAXMEM PERFMON PMAP_SHPGPERPROC opt_pmap.h +MPTABLE_FORCE_HTT MP_WATCHDOG # Options for emulators. These should only be used at config time, so diff --git a/sys/conf/options.powerpc b/sys/conf/options.powerpc index 82a8ffa..b7b3dbb 100644 --- a/sys/conf/options.powerpc +++ b/sys/conf/options.powerpc @@ -23,3 +23,7 @@ PSIM SC_OFWFB opt_ofwfb.h OFWCONS_POLL_HZ opt_ofw.h + +# AGP debugging support +AGP_DEBUG opt_agp.h + diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 24982fe..c0f17f6 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -86,6 +86,11 @@ static struct cdevsw acpi_cdevsw = { .d_name = "acpi", }; +struct acpi_interface { + ACPI_STRING *data; + int num; +}; + /* Global mutex for locking access to the ACPI subsystem. */ struct mtx acpi_mutex; @@ -163,6 +168,7 @@ static void acpi_enable_pcie(void); #endif static void acpi_hint_device_unit(device_t acdev, device_t child, const char *name, int *unitp); +static void acpi_reset_interfaces(device_t dev); static device_method_t acpi_methods[] = { /* Device interface */ @@ -232,6 +238,16 @@ SYSCTL_STRING(_debug_acpi, OID_AUTO, acpi_ca_version, CTLFLAG_RD, acpi_ca_version, 0, "Version of Intel ACPI-CA"); /* + * Allow overriding _OSI methods. + */ +static char acpi_install_interface[256]; +TUNABLE_STR("hw.acpi.install_interface", acpi_install_interface, + sizeof(acpi_install_interface)); +static char acpi_remove_interface[256]; +TUNABLE_STR("hw.acpi.remove_interface", acpi_remove_interface, + sizeof(acpi_remove_interface)); + +/* * Allow override of whether methods execute in parallel or not. * Enable this for serial behavior, which fixes "AE_ALREADY_EXISTS" * errors for AML that really can't handle parallel method execution. @@ -467,6 +483,9 @@ acpi_attach(device_t dev) goto out; } + /* Override OS interfaces if the user requested. */ + acpi_reset_interfaces(dev); + /* Load ACPI name space. */ status = AcpiLoadTables(); if (ACPI_FAILURE(status)) { @@ -3473,6 +3492,93 @@ acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS) } static int +acpi_parse_interfaces(char *str, struct acpi_interface *iface) +{ + char *p; + size_t len; + int i, j; + + p = str; + while (isspace(*p) || *p == ',') + p++; + len = strlen(p); + if (len == 0) + return (0); + p = strdup(p, M_TEMP); + for (i = 0; i < len; i++) + if (p[i] == ',') + p[i] = '\0'; + i = j = 0; + while (i < len) + if (isspace(p[i]) || p[i] == '\0') + i++; + else { + i += strlen(p + i) + 1; + j++; + } + if (j == 0) { + free(p, M_TEMP); + return (0); + } + iface->data = malloc(sizeof(*iface->data) * j, M_TEMP, M_WAITOK); + iface->num = j; + i = j = 0; + while (i < len) + if (isspace(p[i]) || p[i] == '\0') + i++; + else { + iface->data[j] = p + i; + i += strlen(p + i) + 1; + j++; + } + + return (j); +} + +static void +acpi_free_interfaces(struct acpi_interface *iface) +{ + + free(iface->data[0], M_TEMP); + free(iface->data, M_TEMP); +} + +static void +acpi_reset_interfaces(device_t dev) +{ + struct acpi_interface list; + ACPI_STATUS status; + int i; + + if (acpi_parse_interfaces(acpi_install_interface, &list) > 0) { + for (i = 0; i < list.num; i++) { + status = AcpiInstallInterface(list.data[i]); + if (ACPI_FAILURE(status)) + device_printf(dev, + "failed to install _OSI(\"%s\"): %s\n", + list.data[i], AcpiFormatException(status)); + else if (bootverbose) + device_printf(dev, "installed _OSI(\"%s\")\n", + list.data[i]); + } + acpi_free_interfaces(&list); + } + if (acpi_parse_interfaces(acpi_remove_interface, &list) > 0) { + for (i = 0; i < list.num; i++) { + status = AcpiRemoveInterface(list.data[i]); + if (ACPI_FAILURE(status)) + device_printf(dev, + "failed to remove _OSI(\"%s\"): %s\n", + list.data[i], AcpiFormatException(status)); + else if (bootverbose) + device_printf(dev, "removed _OSI(\"%s\")\n", + list.data[i]); + } + acpi_free_interfaces(&list); + } +} + +static int acpi_pm_func(u_long cmd, void *arg, ...) { int state, acpi_state; diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c index ab48085..09e2848 100644 --- a/sys/dev/agp/agp.c +++ b/sys/dev/agp/agp.c @@ -219,13 +219,16 @@ agp_generic_attach(device_t dev) * Find and map the aperture, RF_SHAREABLE for DRM but not RF_ACTIVE * because the kernel doesn't need to map it. */ - if (sc->as_aperture_rid == 0) - sc->as_aperture_rid = AGP_APBASE; - sc->as_aperture = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->as_aperture_rid, RF_SHAREABLE); - if (!sc->as_aperture) - return ENOMEM; + if (sc->as_aperture_rid != -1) { + if (sc->as_aperture_rid == 0) + sc->as_aperture_rid = AGP_APBASE; + + sc->as_aperture = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->as_aperture_rid, RF_SHAREABLE); + if (!sc->as_aperture) + return ENOMEM; + } /* * Work out an upper bound for agp memory allocation. This @@ -272,8 +275,9 @@ agp_free_res(device_t dev) { struct agp_softc *sc = device_get_softc(dev); - bus_release_resource(dev, SYS_RES_MEMORY, sc->as_aperture_rid, - sc->as_aperture); + if (sc->as_aperture != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->as_aperture_rid, + sc->as_aperture); mtx_destroy(&sc->as_lock); agp_flush_cache(); } @@ -729,7 +733,10 @@ agp_info_user(device_t dev, agp_info *info) info->bridge_id = pci_get_devid(dev); info->agp_mode = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4); - info->aper_base = rman_get_start(sc->as_aperture); + if (sc->as_aperture) + info->aper_base = rman_get_start(sc->as_aperture); + else + info->aper_base = 0; info->aper_size = AGP_GET_APERTURE(dev) >> 20; info->pg_total = info->pg_system = sc->as_maxmem >> AGP_PAGE_SHIFT; info->pg_used = sc->as_allocated >> AGP_PAGE_SHIFT; @@ -876,6 +883,8 @@ agp_mmap(struct cdev *kdev, vm_ooffset_t offset, vm_paddr_t *paddr, if (offset > AGP_GET_APERTURE(dev)) return -1; + if (sc->as_aperture == NULL) + return -1; *paddr = rman_get_start(sc->as_aperture) + offset; return 0; } @@ -917,8 +926,11 @@ agp_get_info(device_t dev, struct agp_info *info) info->ai_mode = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4); - info->ai_aperture_base = rman_get_start(sc->as_aperture); - info->ai_aperture_size = rman_get_size(sc->as_aperture); + if (sc->as_aperture != NULL) + info->ai_aperture_base = rman_get_start(sc->as_aperture); + else + info->ai_aperture_base = 0; + info->ai_aperture_size = AGP_GET_APERTURE(dev); info->ai_memory_allowed = sc->as_maxmem; info->ai_memory_used = sc->as_allocated; } diff --git a/sys/dev/agp/agp_apple.c b/sys/dev/agp/agp_apple.c new file mode 100644 index 0000000..e16e114 --- /dev/null +++ b/sys/dev/agp/agp_apple.c @@ -0,0 +1,302 @@ +/*- + * Copyright (c) 2010 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_bus.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> + +#include <machine/resource.h> + +#include <dev/agp/agppriv.h> +#include <dev/agp/agpreg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#include <vm/vm.h> +#include <vm/vm_object.h> +#include <vm/pmap.h> + +#define UNIN_AGP_GART_BASE 0x8c +#define UNIN_AGP_BASE_ADDR 0x90 +#define UNIN_AGP_GART_CONTROL 0x94 + +#define UNIN_AGP_GART_INVAL 0x00000001 +#define UNIN_AGP_GART_ENABLE 0x00000100 +#define UNIN_AGP_GART_2XRESET 0x00010000 +#define UNIN_AGP_U3_GART_PERFRD 0x00080000 + +struct agp_apple_softc { + struct agp_softc agp; + uint32_t aperture; + struct agp_gatt *gatt; + int u3; + int needs_2x_reset; +}; + +static int +agp_apple_probe(device_t dev) +{ + + if (resource_disabled("agp", device_get_unit(dev))) + return (ENXIO); + + if (pci_get_class(dev) != PCIC_BRIDGE + || pci_get_subclass(dev) != PCIS_BRIDGE_HOST) + return (ENXIO); + + if (agp_find_caps(dev) == 0) + return (ENXIO); + + if (pci_get_class(dev) != PCIC_BRIDGE + || pci_get_subclass(dev) != PCIS_BRIDGE_HOST) + return (ENXIO); + + switch (pci_get_devid(dev)) { + case 0x0020106b: + case 0x0027106b: + device_set_desc(dev, "Apple UniNorth AGP Bridge"); + return (BUS_PROBE_DEFAULT); + case 0x002d106b: + device_set_desc(dev, "Apple UniNorth 1.5 AGP Bridge"); + return (BUS_PROBE_DEFAULT); + case 0x0034106b: + device_set_desc(dev, "Apple UniNorth 2 AGP Bridge"); + return (BUS_PROBE_DEFAULT); + case 0x004b106b: + case 0x0058106b: + case 0x0059106b: + device_set_desc(dev, "Apple U3 AGP Bridge"); + return (BUS_PROBE_DEFAULT); + case 0x0066106b: + device_set_desc(dev, "Apple Intrepid AGP Bridge"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +agp_apple_attach(device_t dev) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + int error; + + /* Record quirks */ + sc->needs_2x_reset = 0; + sc->u3 = 0; + switch (pci_get_devid(dev)) { + case 0x0020106b: + case 0x0027106b: + sc->needs_2x_reset = 1; + break; + case 0x004b106b: + case 0x0058106b: + case 0x0059106b: + sc->u3 = 1; + break; + } + + /* Set the aperture bus address base (must be 0) */ + pci_write_config(dev, UNIN_AGP_BASE_ADDR, 0, 4); + agp_set_aperture_resource(dev, -1); + + error = agp_generic_attach(dev); + if (error) + return (error); + + sc->aperture = 256*1024*1024; + + for (sc->aperture = 256*1024*1024; sc->aperture >= 4*1024*1024; + sc->aperture /= 2) { + sc->gatt = agp_alloc_gatt(dev); + if (sc->gatt) + break; + } + if (sc->aperture < 4*1024*1024) { + agp_generic_detach(dev); + return ENOMEM; + } + + /* Install the gatt. */ + AGP_SET_APERTURE(dev, sc->aperture); + + /* XXX: U3 scratch page? */ + + /* Enable the aperture and TLB. */ + AGP_FLUSH_TLB(dev); + + return (0); +} + +static int +agp_apple_detach(device_t dev) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + + agp_free_cdev(dev); + + /* Disable the aperture and TLB */ + pci_write_config(dev, UNIN_AGP_GART_CONTROL, UNIN_AGP_GART_INVAL, 4); + pci_write_config(dev, UNIN_AGP_GART_CONTROL, 0, 4); + + if (sc->needs_2x_reset) { + pci_write_config(dev, UNIN_AGP_GART_CONTROL, + UNIN_AGP_GART_2XRESET, 4); + pci_write_config(dev, UNIN_AGP_GART_CONTROL, 0, 4); + } + + AGP_SET_APERTURE(dev, 0); + + agp_free_gatt(sc->gatt); + agp_free_res(dev); + return 0; +} + +static uint32_t +agp_apple_get_aperture(device_t dev) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + + return (sc->aperture); +} + +static int +agp_apple_set_aperture(device_t dev, uint32_t aperture) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + + /* + * Check for a multiple of 4 MB and make sure it is within the + * programmable range. + */ + if (aperture % (4*1024*1024) + || aperture < 4*1024*1024 + || aperture > ((sc->u3) ? 512 : 256)*1024*1024) + return EINVAL; + + /* The aperture value is a multiple of 4 MB */ + aperture /= (4*1024*1024); + + pci_write_config(dev, UNIN_AGP_GART_BASE, + (sc->gatt->ag_physical & 0xfffff000) | aperture, 4); + + return (0); +} + +static int +agp_apple_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + + if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) + return EINVAL; + + sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical; + __asm __volatile("dcbst 0,%0; sync" :: + "r"(&sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT]) : "memory"); + return (0); +} + +static int +agp_apple_unbind_page(device_t dev, vm_offset_t offset) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + + if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) + return EINVAL; + + sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0; + __asm __volatile("dcbst 0,%0; sync" :: + "r"(&sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT]) : "memory"); + return (0); +} + +static void +agp_apple_flush_tlb(device_t dev) +{ + struct agp_apple_softc *sc = device_get_softc(dev); + uint32_t cntrl = UNIN_AGP_GART_ENABLE; + + if (sc->u3) + cntrl |= UNIN_AGP_U3_GART_PERFRD; + + pci_write_config(dev, UNIN_AGP_GART_CONTROL, + cntrl | UNIN_AGP_GART_INVAL, 4); + pci_write_config(dev, UNIN_AGP_GART_CONTROL, cntrl, 4); + + if (sc->needs_2x_reset) { + pci_write_config(dev, UNIN_AGP_GART_CONTROL, + cntrl | UNIN_AGP_GART_2XRESET, 4); + pci_write_config(dev, UNIN_AGP_GART_CONTROL, cntrl, 4); + } +} + +static device_method_t agp_apple_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, agp_apple_probe), + DEVMETHOD(device_attach, agp_apple_attach), + DEVMETHOD(device_detach, agp_apple_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* AGP interface */ + DEVMETHOD(agp_get_aperture, agp_apple_get_aperture), + DEVMETHOD(agp_set_aperture, agp_apple_set_aperture), + DEVMETHOD(agp_bind_page, agp_apple_bind_page), + DEVMETHOD(agp_unbind_page, agp_apple_unbind_page), + DEVMETHOD(agp_flush_tlb, agp_apple_flush_tlb), + DEVMETHOD(agp_enable, agp_generic_enable), + DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory), + DEVMETHOD(agp_free_memory, agp_generic_free_memory), + DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), + DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), + + { 0, 0 } +}; + +static driver_t agp_apple_driver = { + "agp", + agp_apple_methods, + sizeof(struct agp_apple_softc), +}; + +static devclass_t agp_devclass; + +DRIVER_MODULE(agp_apple, hostb, agp_apple_driver, agp_devclass, 0, 0); +MODULE_DEPEND(agp_apple, agp, 1, 1, 1); +MODULE_DEPEND(agp_apple, pci, 1, 1, 1); diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c index 5f0f7ec..aee0e10 100644 --- a/sys/dev/alc/if_alc.c +++ b/sys/dev/alc/if_alc.c @@ -331,8 +331,8 @@ alc_miibus_statchg(device_t dev) reg = CSR_READ_4(sc, ALC_MAC_CFG); reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB; CSR_WRITE_4(sc, ALC_MAC_CFG, reg); + alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active)); } - alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active)); } static void diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 63c4c5d..59ce673 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -169,6 +169,8 @@ static const struct bge_type { { BCOM_VENDORID, BCOM_DEVICEID_BCM5714S }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5715 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5715S }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5717 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5718 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5720 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5721 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5722 }, @@ -289,6 +291,8 @@ static const struct bge_revision { { BGE_CHIPID_BCM5715_A0, "BCM5715 A0" }, { BGE_CHIPID_BCM5715_A1, "BCM5715 A1" }, { BGE_CHIPID_BCM5715_A3, "BCM5715 A3" }, + { BGE_CHIPID_BCM5717_A0, "BCM5717 A0" }, + { BGE_CHIPID_BCM5717_B0, "BCM5717 B0" }, { BGE_CHIPID_BCM5755_A0, "BCM5755 A0" }, { BGE_CHIPID_BCM5755_A1, "BCM5755 A1" }, { BGE_CHIPID_BCM5755_A2, "BCM5755 A2" }, @@ -332,6 +336,7 @@ static const struct bge_revision bge_majorrevs[] = { { BGE_ASICREV_BCM5787, "unknown BCM5754/5787" }, { BGE_ASICREV_BCM5906, "unknown BCM5906" }, { BGE_ASICREV_BCM57780, "unknown BCM57780" }, + { BGE_ASICREV_BCM5717, "unknown BCM5717" }, { 0, NULL } }; @@ -342,6 +347,7 @@ static const struct bge_revision bge_majorrevs[] = { #define BGE_IS_5714_FAMILY(sc) ((sc)->bge_flags & BGE_FLAG_5714_FAMILY) #define BGE_IS_575X_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_575X_PLUS) #define BGE_IS_5755_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5755_PLUS) +#define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS) const struct bge_revision * bge_lookup_rev(uint32_t); const struct bge_vendor * bge_lookup_vendor(uint16_t); @@ -367,6 +373,7 @@ static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]); static int bge_get_eaddr(struct bge_softc *, uint8_t[]); static void bge_txeof(struct bge_softc *, uint16_t); +static void bge_rxcsum(struct bge_softc *, struct bge_rx_bd *, struct mbuf *); static int bge_rxeof(struct bge_softc *, uint16_t, int); static void bge_asf_driver_up (struct bge_softc *); @@ -376,7 +383,7 @@ static void bge_stats_update(struct bge_softc *); static void bge_stats_update_regs(struct bge_softc *); static struct mbuf *bge_check_short_dma(struct mbuf *); static struct mbuf *bge_setup_tso(struct bge_softc *, struct mbuf *, - uint16_t *); + uint16_t *, uint16_t *); static int bge_encap(struct bge_softc *, struct mbuf **, uint32_t *); static void bge_intr(void *); @@ -1349,12 +1356,15 @@ bge_stop_fw(struct bge_softc *sc) static int bge_chipinit(struct bge_softc *sc) { - uint32_t dma_rw_ctl; + uint32_t dma_rw_ctl, misc_ctl; uint16_t val; int i; /* Set endianness before we access any non-PCI registers. */ - pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4); + misc_ctl = BGE_INIT; + if (sc->bge_flags & BGE_FLAG_TAGGED_STATUS) + misc_ctl |= BGE_PCIMISCCTL_TAGGED_STATUS; + pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, misc_ctl, 4); /* Clear the MAC control register */ CSR_WRITE_4(sc, BGE_MAC_MODE, 0); @@ -1446,6 +1456,8 @@ bge_chipinit(struct bge_softc *sc) if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; + if (BGE_IS_5717_PLUS(sc)) + dma_rw_ctl &= ~BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); /* @@ -1529,7 +1541,16 @@ bge_blockinit(struct bge_softc *sc) } /* Configure mbuf pool watermarks */ - if (!BGE_IS_5705_PLUS(sc)) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + if (sc->bge_ifp->if_mtu > ETHERMTU) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); + } else { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); + } + } else if (!BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); @@ -1621,7 +1642,16 @@ bge_blockinit(struct bge_softc *sc) BGE_ADDR_HI(sc->bge_ldata.bge_rx_std_ring_paddr); bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag, sc->bge_cdata.bge_rx_std_ring_map, BUS_DMASYNC_PREREAD); - if (BGE_IS_5705_PLUS(sc)) { + if (BGE_IS_5717_PLUS(sc)) { + /* + * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) + * Bits 15-2 : Maximum RX frame size + * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled + * Bit 0 : Reserved + */ + rcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(512, BGE_MAX_FRAMELEN << 2); + } else if (BGE_IS_5705_PLUS(sc)) { /* * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) * Bits 15-2 : Reserved (should be 0) @@ -1640,7 +1670,10 @@ bge_blockinit(struct bge_softc *sc) rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0); } - rcb->bge_nicaddr = BGE_STD_RX_RINGS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; + else + rcb->bge_nicaddr = BGE_STD_RX_RINGS; /* Write the standard receive producer ring control block. */ CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); @@ -1669,7 +1702,10 @@ bge_blockinit(struct bge_softc *sc) BUS_DMASYNC_PREREAD); rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_USE_EXT_RX_BD | BGE_RCB_FLAG_RING_DISABLED); - rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; + else + rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, @@ -1726,6 +1762,10 @@ bge_blockinit(struct bge_softc *sc) if (BGE_IS_JUMBO_CAPABLE(sc)) CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, BGE_JUMBO_RX_RING_CNT/8); + if (BGE_IS_5717_PLUS(sc)) { + CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); + CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); + } /* * Disable all send rings by setting the 'ring disabled' bit @@ -1750,8 +1790,11 @@ bge_blockinit(struct bge_softc *sc) BGE_HOSTADDR(taddr, sc->bge_ldata.bge_tx_ring_paddr); RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); - RCB_WRITE_4(sc, vrcb, bge_nicaddr, - BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717); + else + RCB_WRITE_4(sc, vrcb, bge_nicaddr, + BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); @@ -1760,7 +1803,10 @@ bge_blockinit(struct bge_softc *sc) * 'ring diabled' bit in the flags field of all the receive * return ring control blocks, located in NIC memory. */ - if (!BGE_IS_5705_PLUS(sc)) + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + /* Should be 17, use 16 until we get an SRAM map. */ + limit = 16; + } else if (!BGE_IS_5705_PLUS(sc)) limit = BGE_RX_RINGS_MAX; else if (sc->bge_asicrev == BGE_ASICREV_BCM5755) limit = 4; @@ -1936,6 +1982,10 @@ bge_blockinit(struct bge_softc *sc) /* Turn on read DMA state machine */ val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; + + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) @@ -1944,16 +1994,18 @@ bge_blockinit(struct bge_softc *sc) BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; if (sc->bge_flags & BGE_FLAG_PCIE) val |= BGE_RDMAMODE_FIFO_LONG_BURST; - if (sc->bge_flags & BGE_FLAG_TSO) { + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) { val |= BGE_RDMAMODE_TSO4_ENABLE; - if (sc->bge_asicrev == BGE_ASICREV_BCM5785 || + if (sc->bge_flags & BGE_FLAG_TSO3 || + sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) val |= BGE_RDMAMODE_TSO6_ENABLE; } if (sc->bge_asicrev == BGE_ASICREV_BCM5761 || sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || - sc->bge_asicrev == BGE_ASICREV_BCM57780) { + sc->bge_asicrev == BGE_ASICREV_BCM57780 || + BGE_IS_5717_PLUS(sc)) { /* * Enable fix for read DMA FIFO overruns. * The fix is to limit the number of RX BDs @@ -1989,8 +2041,9 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_SDC_MODE, val); /* Turn on send data initiator state machine */ - if (sc->bge_flags & BGE_FLAG_TSO) - CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 0x08); + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) + CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | + BGE_SDIMODE_HW_LSO_PRE_DMA); else CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); @@ -2104,9 +2157,22 @@ bge_probe(device_t dev) id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> BGE_PCIMISCCTL_ASICREV_SHIFT; - if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) - id = pci_read_config(dev, - BGE_PCI_PRODID_ASICREV, 4); + if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) { + /* + * Find the ASCI revision. Different chips + * use different registers. + */ + switch (pci_get_device(dev)) { + case BCOM_DEVICEID_BCM5717: + case BCOM_DEVICEID_BCM5718: + id = pci_read_config(dev, + BGE_PCI_GEN2_PRODID_ASICREV, 4); + break; + default: + id = pci_read_config(dev, + BGE_PCI_PRODID_ASICREV, 4); + } + } br = bge_lookup_rev(id); v = bge_lookup_vendor(vid); { @@ -2423,7 +2489,7 @@ bge_dma_alloc(struct bge_softc *sc) return (ENOMEM); } /* Create tag for Tx mbufs. */ - if (sc->bge_flags & BGE_FLAG_TSO) { + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) { txsegsz = BGE_TSOSEG_SZ; txmaxsegsz = 65535 + sizeof(struct ether_vlan_header); } else { @@ -2539,6 +2605,10 @@ bge_can_use_msi(struct bge_softc *sc) { int can_use_msi = 0; + /* Disable MSI for polling(4). */ +#ifdef DEVICE_POLLING + return (0); +#endif switch (sc->bge_asicrev) { case BGE_ASICREV_BCM5714_A0: case BGE_ASICREV_BCM5714: @@ -2568,7 +2638,7 @@ bge_attach(device_t dev) struct bge_softc *sc; uint32_t hwcfg = 0, misccfg; u_char eaddr[ETHER_ADDR_LEN]; - int error, msicount, phy_addr, reg, rid, trys; + int error, f, msicount, phy_addr, reg, rid, trys; sc = device_get_softc(dev); sc->bge_dev = dev; @@ -2594,14 +2664,55 @@ bge_attach(device_t dev) sc->bge_chipid = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> BGE_PCIMISCCTL_ASICREV_SHIFT; - if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) - sc->bge_chipid = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, - 4); + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) { + /* + * Find the ASCI revision. Different chips use different + * registers. + */ + switch (pci_get_device(dev)) { + case BCOM_DEVICEID_BCM5717: + case BCOM_DEVICEID_BCM5718: + sc->bge_chipid = pci_read_config(dev, + BGE_PCI_GEN2_PRODID_ASICREV, 4); + break; + default: + sc->bge_chipid = pci_read_config(dev, + BGE_PCI_PRODID_ASICREV, 4); + } + } sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); /* Set default PHY address. */ phy_addr = 1; + /* + * PHY address mapping for various devices. + * + * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | + * ---------+-------+-------+-------+-------+ + * BCM57XX | 1 | X | X | X | + * BCM5704 | 1 | X | 1 | X | + * BCM5717 | 1 | 8 | 2 | 9 | + * + * Other addresses may respond but they are not + * IEEE compliant PHYs and should be ignored. + */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + f = pci_get_function(dev); + if (sc->bge_chipid == BGE_CHIPID_BCM5717_A0) { + if (CSR_READ_4(sc, BGE_SGDIG_STS) & + BGE_SGDIGSTS_IS_SERDES) + phy_addr = f + 8; + else + phy_addr = f + 1; + } else if (sc->bge_chipid == BGE_CHIPID_BCM5717_B0) { + if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & + BGE_CPMU_PHY_STRAP_IS_SERDES) + phy_addr = f + 8; + else + phy_addr = f + 1; + } + } /* * Don't enable Ethernet@WireSpeed for the 5700, 5906, or the @@ -2610,7 +2721,8 @@ bge_attach(device_t dev) if (sc->bge_asicrev != BGE_ASICREV_BCM5700 && sc->bge_asicrev != BGE_ASICREV_BCM5906 && sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && - sc->bge_chipid != BGE_CHIPID_BCM5705_A1) + sc->bge_chipid != BGE_CHIPID_BCM5705_A1 && + !BGE_IS_5717_PLUS(sc)) sc->bge_phy_flags |= BGE_PHY_WIRESPEED; if (bge_has_eaddr(sc)) @@ -2618,6 +2730,11 @@ bge_attach(device_t dev) /* Save chipset family. */ switch (sc->bge_asicrev) { + case BGE_ASICREV_BCM5717: + sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS | + BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO | + BGE_FLAG_SHORT_DMA_BUG | BGE_FLAG_JUMBO_FRAME; + break; case BGE_ASICREV_BCM5755: case BGE_ASICREV_BCM5761: case BGE_ASICREV_BCM5784: @@ -2663,6 +2780,7 @@ bge_attach(device_t dev) sc->bge_phy_flags |= BGE_PHY_NO_3LED; if ((BGE_IS_5705_PLUS(sc)) && sc->bge_asicrev != BGE_ASICREV_BCM5906 && + sc->bge_asicrev != BGE_ASICREV_BCM5717 && sc->bge_asicrev != BGE_ASICREV_BCM5785 && sc->bge_asicrev != BGE_ASICREV_BCM57780) { if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || @@ -2679,7 +2797,8 @@ bge_attach(device_t dev) } /* Identify the chips that use an CPMU. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5784 || + if (BGE_IS_5717_PLUS(sc) || + sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5761 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) @@ -2722,7 +2841,10 @@ bge_attach(device_t dev) * the TSO to the controllers that are not affected TSO issues * (e.g. 5755 or higher). */ - if (BGE_IS_5755_PLUS(sc)) { + if (BGE_IS_5717_PLUS(sc)) { + /* BCM5717 requires different TSO configuration. */ + sc->bge_flags |= BGE_FLAG_TSO3; + } else if (BGE_IS_5755_PLUS(sc)) { /* * BCM5754 and BCM5787 shares the same ASIC id so * explicit device id check is required. @@ -2785,6 +2907,16 @@ bge_attach(device_t dev) } } + /* + * All controllers except BCM5700 supports tagged status but + * we use tagged status only for MSI case on BCM5717. Otherwise + * MSI on BCM5717 does not work. + */ +#ifndef DEVICE_POLLING + if (sc->bge_flags & BGE_FLAG_MSI && BGE_IS_5717_PLUS(sc)) + sc->bge_flags |= BGE_FLAG_TAGGED_STATUS; +#endif + sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); @@ -2848,7 +2980,9 @@ bge_attach(device_t dev) } /* 5705 limits RX return ring to 512 entries. */ - if (BGE_IS_5705_PLUS(sc)) + if (BGE_IS_5717_PLUS(sc)) + sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; + else if (BGE_IS_5705_PLUS(sc)) sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705; else sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; @@ -2893,7 +3027,7 @@ bge_attach(device_t dev) ifp->if_hwassist = sc->bge_csum_features; ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; - if ((sc->bge_flags & BGE_FLAG_TSO) != 0) { + if ((sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) != 0) { ifp->if_hwassist |= CSUM_TSO; ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_VLAN_HWTSO; } @@ -3340,6 +3474,7 @@ bge_reset(struct bge_softc *sc) /* XXX: Broadcom Linux driver. */ if (sc->bge_flags & BGE_FLAG_PCIE && + sc->bge_asicrev != BGE_ASICREV_BCM5717 && sc->bge_chipid != BGE_CHIPID_BCM5750_A0 && sc->bge_asicrev != BGE_ASICREV_BCM5785) { /* Enable Data FIFO protection. */ @@ -3480,20 +3615,8 @@ bge_rxeof(struct bge_softc *sc, uint16_t rx_prod, int holdlck) m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; m->m_pkthdr.rcvif = ifp; - if (ifp->if_capenable & IFCAP_RXCSUM) { - if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { - m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; - if ((cur_rx->bge_ip_csum ^ 0xFFFF) == 0) - m->m_pkthdr.csum_flags |= CSUM_IP_VALID; - } - if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM && - m->m_pkthdr.len >= ETHER_MIN_NOPAD) { - m->m_pkthdr.csum_data = - cur_rx->bge_tcp_udp_csum; - m->m_pkthdr.csum_flags |= - CSUM_DATA_VALID | CSUM_PSEUDO_HDR; - } - } + if (ifp->if_capenable & IFCAP_RXCSUM) + bge_rxcsum(sc, cur_rx, m); /* * If we received a packet with a vlan tag, @@ -3552,6 +3675,41 @@ bge_rxeof(struct bge_softc *sc, uint16_t rx_prod, int holdlck) } static void +bge_rxcsum(struct bge_softc *sc, struct bge_rx_bd *cur_rx, struct mbuf *m) +{ + + if (BGE_IS_5717_PLUS(sc)) { + if ((cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { + if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((cur_rx->bge_error_flag & + BGE_RXERRFLAG_IP_CSUM_NOK) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + } + if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { + m->m_pkthdr.csum_data = + cur_rx->bge_tcp_udp_csum; + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + } + } + } else { + if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((cur_rx->bge_ip_csum ^ 0xFFFF) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + } + if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM && + m->m_pkthdr.len >= ETHER_MIN_NOPAD) { + m->m_pkthdr.csum_data = + cur_rx->bge_tcp_udp_csum; + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + } + } +} + +static void bge_txeof(struct bge_softc *sc, uint16_t tx_cons) { struct bge_tx_bd *cur_tx; @@ -3668,7 +3826,7 @@ bge_intr_task(void *arg, int pending) { struct bge_softc *sc; struct ifnet *ifp; - uint32_t status; + uint32_t status, status_tag; uint16_t rx_prod, tx_cons; sc = (struct bge_softc *)arg; @@ -3689,16 +3847,19 @@ bge_intr_task(void *arg, int pending) rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx; tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx; status = sc->bge_ldata.bge_status_block->bge_status; + status_tag = sc->bge_ldata.bge_status_block->bge_status_tag << 24; sc->bge_ldata.bge_status_block->bge_status = 0; bus_dmamap_sync(sc->bge_cdata.bge_status_tag, sc->bge_cdata.bge_status_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + if ((sc->bge_flags & BGE_FLAG_TAGGED_STATUS) == 0) + status_tag = 0; if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) != 0) bge_link_upd(sc); /* Let controller work. */ - bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, status_tag); if (ifp->if_drv_flags & IFF_DRV_RUNNING && sc->bge_rx_saved_considx != rx_prod) { @@ -4104,7 +4265,8 @@ bge_check_short_dma(struct mbuf *m) } static struct mbuf * -bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss) +bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss, + uint16_t *flags) { struct ip *ip; struct tcphdr *tcp; @@ -4147,14 +4309,30 @@ bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss) * Broadcom controllers uses different descriptor format for * TSO depending on ASIC revision. Due to TSO-capable firmware * license issue and lower performance of firmware based TSO - * we only support hardware based TSO which is applicable for - * BCM5755 or newer controllers. Hardware based TSO uses 11 - * bits to store MSS and upper 5 bits are used to store IP/TCP - * header length(including IP/TCP options). The header length - * is expressed as 32 bits unit. + * we only support hardware based TSO. */ + /* Calculate header length, incl. TCP/IP options, in 32 bit units. */ hlen = ((ip->ip_hl << 2) + (tcp->th_off << 2)) >> 2; - *mss |= (hlen << 11); + if (sc->bge_flags & BGE_FLAG_TSO3) { + /* + * For BCM5717 and newer controllers, hardware based TSO + * uses the 14 lower bits of the bge_mss field to store the + * MSS and the upper 2 bits to store the lowest 2 bits of + * the IP/TCP header length. The upper 6 bits of the header + * length are stored in the bge_flags[14:10,4] field. Jumbo + * frames are supported. + */ + *mss |= ((hlen & 0x3) << 14); + *flags |= ((hlen & 0xF8) << 7) | ((hlen & 0x4) << 2); + } else { + /* + * For BCM5755 and newer controllers, hardware based TSO uses + * the lower 11 bits to store the MSS and the upper 5 bits to + * store the IP/TCP header length. Jumbo frames are not + * supported. + */ + *mss |= (hlen << 11); + } return (m); } @@ -4184,7 +4362,7 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx) m = *m_head; } if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { - *m_head = m = bge_setup_tso(sc, m, &mss); + *m_head = m = bge_setup_tso(sc, m, &mss, &csum_flags); if (*m_head == NULL) return (ENOBUFS); csum_flags |= BGE_TXBDFLAG_CPU_PRE_DMA | @@ -4207,21 +4385,26 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx) csum_flags |= BGE_TXBDFLAG_IP_FRAG; } - if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0 && - sc->bge_forced_collapse > 0 && - (sc->bge_flags & BGE_FLAG_PCIE) != 0 && m->m_next != NULL) { - /* - * Forcedly collapse mbuf chains to overcome hardware - * limitation which only support a single outstanding - * DMA read operation. - */ - if (sc->bge_forced_collapse == 1) - m = m_defrag(m, M_DONTWAIT); - else - m = m_collapse(m, M_DONTWAIT, sc->bge_forced_collapse); - if (m == NULL) - m = *m_head; - *m_head = m; + if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) { + if (sc->bge_flags & BGE_FLAG_JUMBO_FRAME && + m->m_pkthdr.len > ETHER_MAX_LEN) + csum_flags |= BGE_TXBDFLAG_JUMBO_FRAME; + if (sc->bge_forced_collapse > 0 && + (sc->bge_flags & BGE_FLAG_PCIE) != 0 && m->m_next != NULL) { + /* + * Forcedly collapse mbuf chains to overcome hardware + * limitation which only support a single outstanding + * DMA read operation. + */ + if (sc->bge_forced_collapse == 1) + m = m_defrag(m, M_DONTWAIT); + else + m = m_collapse(m, M_DONTWAIT, + sc->bge_forced_collapse); + if (m == NULL) + m = *m_head; + *m_head = m; + } } map = sc->bge_cdata.bge_tx_dmamap[idx]; diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h index a50bf59..6a9c2e8 100644 --- a/sys/dev/bge/if_bgereg.h +++ b/sys/dev/bge/if_bgereg.h @@ -82,6 +82,7 @@ #define BGE_UNMAPPED_END 0x00001FFF #define BGE_DMA_DESCRIPTORS 0x00002000 #define BGE_DMA_DESCRIPTORS_END 0x00003FFF +#define BGE_SEND_RING_5717 0x00004000 #define BGE_SEND_RING_1_TO_4 0x00004000 #define BGE_SEND_RING_1_TO_4_END 0x00005FFF @@ -100,6 +101,8 @@ #define BGE_BUFFPOOL_2_END 0x00017FFF #define BGE_BUFFPOOL_3 0x00018000 /* or expansion ROM */ #define BGE_BUFFPOOL_3_END 0x0001FFFF +#define BGE_STD_RX_RINGS_5717 0x00040000 +#define BGE_JUMBO_RX_RINGS_5717 0x00044400 /* Mappings for external SSRAM configurations */ #define BGE_SEND_RING_5_TO_6 0x00006000 @@ -219,6 +222,7 @@ #define BGE_PCI_ISR_MBX_HI 0xB0 #define BGE_PCI_ISR_MBX_LO 0xB4 #define BGE_PCI_PRODID_ASICREV 0xBC +#define BGE_PCI_GEN2_PRODID_ASICREV 0xF4 /* PCI Misc. Host control register */ #define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001 @@ -229,6 +233,7 @@ #define BGE_PCIMISCCTL_CLOCKCTL_RW 0x00000020 #define BGE_PCIMISCCTL_REG_WORDSWAP 0x00000040 #define BGE_PCIMISCCTL_INDIRECT_ACCESS 0x00000080 +#define BGE_PCIMISCCTL_TAGGED_STATUS 0x00000200 #define BGE_PCIMISCCTL_ASICREV 0xFFFF0000 #define BGE_PCIMISCCTL_ASICREV_SHIFT 16 @@ -311,6 +316,8 @@ #define BGE_CHIPID_BCM5906_A2 0xc002 #define BGE_CHIPID_BCM57780_A0 0x57780000 #define BGE_CHIPID_BCM57780_A1 0x57780001 +#define BGE_CHIPID_BCM5717_A0 0x05717000 +#define BGE_CHIPID_BCM5717_B0 0x05717100 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 12) @@ -331,6 +338,7 @@ /* Should consult BGE_PCI_PRODID_ASICREV for ChipID */ #define BGE_ASICREV_USE_PRODID_REG 0x0f /* BGE_PCI_PRODID_ASICREV ASIC rev. identifiers. */ +#define BGE_ASICREV_BCM5717 0x5717 #define BGE_ASICREV_BCM5761 0x5761 #define BGE_ASICREV_BCM5784 0x5784 #define BGE_ASICREV_BCM5785 0x5785 @@ -348,11 +356,14 @@ #define BGE_CHIPREV_5750_AX 0x40 #define BGE_CHIPREV_5750_BX 0x41 /* BGE_PCI_PRODID_ASICREV chip rev. identifiers. */ +#define BGE_CHIPREV_5717_AX 0x57170 +#define BGE_CHIPREV_5717_BX 0x57171 #define BGE_CHIPREV_5761_AX 0x57611 #define BGE_CHIPREV_5784_AX 0x57841 /* PCI DMA Read/Write Control register */ #define BGE_PCIDMARWCTL_MINDMA 0x000000FF +#define BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT 0x00000001 #define BGE_PCIDMARWCTL_RDADRR_BNDRY 0x00000700 #define BGE_PCIDMARWCTL_WRADDR_BNDRY 0x00003800 #define BGE_PCIDMARWCTL_ONEDMA_ATONCE 0x0000C000 @@ -566,6 +577,7 @@ #define BGE_TX_RINGS_MAX 4 #define BGE_TX_RINGS_EXTSSRAM_MAX 16 #define BGE_RX_RINGS_MAX 16 +#define BGE_RX_RINGS_MAX_5717 17 /* Ethernet MAC control registers */ #define BGE_MAC_MODE 0x0400 @@ -843,9 +855,10 @@ #define BGE_SGDIGCFG_AUTO 0x80000000 /* SGDIG status (not documented) */ +#define BGE_SGDIGSTS_DONE 0x00000002 +#define BGE_SGDIGSTS_IS_SERDES 0x00000100 #define BGE_SGDIGSTS_PAUSE_CAP 0x00080000 #define BGE_SGDIGSTS_ASYM_PAUSE 0x00100000 -#define BGE_SGDIGSTS_DONE 0x00000002 /* MI communication register */ @@ -911,6 +924,7 @@ #define BGE_SDIMODE_RESET 0x00000001 #define BGE_SDIMODE_ENABLE 0x00000002 #define BGE_SDIMODE_STATS_OFLOW_ATTN 0x00000004 +#define BGE_SDIMODE_HW_LSO_PRE_DMA 0x00000008 /* Send Data Initiator stats register */ #define BGE_SDISTAT_STATS_OFLOW_ATTN 0x00000004 @@ -1188,6 +1202,9 @@ #define BGE_RBDI_STD_REPL_THRESH 0x2C18 #define BGE_RBDI_JUMBO_REPL_THRESH 0x2C1C +#define BGE_STD_REPLENISH_LWM 0x2D00 +#define BGE_JMB_REPLENISH_LWM 0x2D04 + /* Receive BD Initiator Mode register */ #define BGE_RBDIMODE_RESET 0x00000001 #define BGE_RBDIMODE_ENABLE 0x00000002 @@ -1501,6 +1518,7 @@ #define BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN 0x00002000 #define BGE_RDMAMODE_FIFO_SIZE_128 0x00020000 #define BGE_RDMAMODE_FIFO_LONG_BURST 0x00030000 +#define BGE_RDMAMODE_MULT_DMA_RD_DIS 0x01000000 #define BGE_RDMAMODE_TSO4_ENABLE 0x08000000 #define BGE_RDMAMODE_TSO6_ENABLE 0x10000000 @@ -2068,15 +2086,27 @@ struct bge_tx_bd { #define BGE_TXBDFLAG_IP_CSUM 0x0002 #define BGE_TXBDFLAG_END 0x0004 #define BGE_TXBDFLAG_IP_FRAG 0x0008 +#define BGE_TXBDFLAG_JUMBO_FRAME 0x0008 /* 5717 */ #define BGE_TXBDFLAG_IP_FRAG_END 0x0010 +#define BGE_TXBDFLAG_HDRLEN_BIT2 0x0010 /* 5717 */ +#define BGE_TXBDFLAG_SNAP 0x0020 /* 5717 */ #define BGE_TXBDFLAG_VLAN_TAG 0x0040 #define BGE_TXBDFLAG_COAL_NOW 0x0080 #define BGE_TXBDFLAG_CPU_PRE_DMA 0x0100 #define BGE_TXBDFLAG_CPU_POST_DMA 0x0200 +#define BGE_TXBDFLAG_HDRLEN_BIT3 0x0400 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT4 0x0800 /* 5717 */ #define BGE_TXBDFLAG_INSERT_SRC_ADDR 0x1000 +#define BGE_TXBDFLAG_HDRLEN_BIT5 0x1000 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT6 0x2000 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT7 0x4000 /* 5717 */ #define BGE_TXBDFLAG_CHOOSE_SRC_ADDR 0x6000 #define BGE_TXBDFLAG_NO_CRC 0x8000 +#define BGE_TXBDFLAG_MSS_SIZE_MASK 0x3FFF /* 5717 */ +/* Bits [1:0] of the MSS header length. */ +#define BGE_TXBDFLAG_MSS_HDRLEN_MASK 0xC000 /* 5717 */ + #define BGE_NIC_TXRING_ADDR(ringno, size) \ BGE_SEND_RING_1_TO_4 + \ ((ringno * sizeof(struct bge_tx_bd) * size) / 4) @@ -2153,6 +2183,7 @@ struct bge_extrx_bd { #define BGE_RXBDFLAG_IP_CSUM 0x1000 #define BGE_RXBDFLAG_TCP_UDP_CSUM 0x2000 #define BGE_RXBDFLAG_TCP_UDP_IS_TCP 0x4000 +#define BGE_RXBDFLAG_IPV6 0x8000 #define BGE_RXERRFLAG_BAD_CRC 0x0001 #define BGE_RXERRFLAG_COLL_DETECT 0x0002 @@ -2162,6 +2193,7 @@ struct bge_extrx_bd { #define BGE_RXERRFLAG_RUNT 0x0020 #define BGE_RXERRFLAG_TRUNC_NO_RSRCS 0x0040 #define BGE_RXERRFLAG_GIANT 0x0080 +#define BGE_RXERRFLAG_IP_CSUM_NOK 0x1000 /* 5717 */ struct bge_sts_idx { #if BYTE_ORDER == LITTLE_ENDIAN @@ -2175,7 +2207,7 @@ struct bge_sts_idx { struct bge_status_block { uint32_t bge_status; - uint32_t bge_rsvd0; + uint32_t bge_status_tag; #if BYTE_ORDER == LITTLE_ENDIAN uint16_t bge_rx_jumbo_cons_idx; uint16_t bge_rx_std_cons_idx; @@ -2221,6 +2253,8 @@ struct bge_status_block { #define BCOM_DEVICEID_BCM5714S 0x1669 #define BCOM_DEVICEID_BCM5715 0x1678 #define BCOM_DEVICEID_BCM5715S 0x1679 +#define BCOM_DEVICEID_BCM5717 0x1655 +#define BCOM_DEVICEID_BCM5718 0x1656 #define BCOM_DEVICEID_BCM5720 0x1658 #define BCOM_DEVICEID_BCM5721 0x1659 #define BCOM_DEVICEID_BCM5722 0x165A @@ -2717,16 +2751,20 @@ struct bge_softc { #define BGE_FLAG_EADDR 0x00000008 #define BGE_FLAG_MII_SERDES 0x00000010 #define BGE_FLAG_CPMU_PRESENT 0x00000020 +#define BGE_FLAG_TAGGED_STATUS 0x00000040 #define BGE_FLAG_MSI 0x00000100 #define BGE_FLAG_PCIX 0x00000200 #define BGE_FLAG_PCIE 0x00000400 #define BGE_FLAG_TSO 0x00000800 +#define BGE_FLAG_TSO3 0x00001000 +#define BGE_FLAG_JUMBO_FRAME 0x00002000 #define BGE_FLAG_5700_FAMILY 0x00010000 #define BGE_FLAG_5705_PLUS 0x00020000 #define BGE_FLAG_5714_FAMILY 0x00040000 #define BGE_FLAG_575X_PLUS 0x00080000 #define BGE_FLAG_5755_PLUS 0x00100000 #define BGE_FLAG_5788 0x00200000 +#define BGE_FLAG_5717_PLUS 0x00400000 #define BGE_FLAG_40BIT_BUG 0x01000000 #define BGE_FLAG_4G_BNDRY_BUG 0x02000000 #define BGE_FLAG_RX_ALIGNBUG 0x04000000 diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c index 3554dbe..5e12c49 100644 --- a/sys/dev/e1000/e1000_82571.c +++ b/sys/dev/e1000/e1000_82571.c @@ -666,10 +666,15 @@ static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) **/ static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw) { + s32 ret_val; + DEBUGFUNC("e1000_get_hw_semaphore_82574"); E1000_MUTEX_LOCK(&hw->dev_spec._82571.swflag_mutex); - return e1000_get_hw_semaphore_82573(hw); + ret_val = e1000_get_hw_semaphore_82573(hw); + if (ret_val) + E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex); + return ret_val; } /** diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index af6100a..c41e144 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -93,8 +93,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.0.8"; - +char em_driver_version[] = "7.1.7"; /********************************************************************* * PCI Device ID Table @@ -170,6 +169,8 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_M_HV_LC, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_D_HV_DM, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_D_HV_DC, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH2_LV_LM, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH2_LV_V, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -256,6 +257,8 @@ static int em_dma_malloc(struct adapter *, bus_size_t, static void em_dma_free(struct adapter *, struct em_dma_alloc *); static int em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); static void em_print_nvm_info(struct adapter *); +static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); +static void em_print_debug_info(struct adapter *); static int em_is_valid_ether_addr(u8 *); static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); static void em_add_int_delay_sysctl(struct adapter *, const char *, @@ -282,6 +285,8 @@ static void em_handle_link(void *context, int pending); static void em_add_rx_process_limit(struct adapter *, const char *, const char *, int *, int); +static void em_set_flow_cntrl(struct adapter *, const char *, + const char *, int *, int); static __inline void em_rx_discard(struct rx_ring *, int); @@ -359,14 +364,6 @@ TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit); static int em_fc_setting = e1000_fc_full; TUNABLE_INT("hw.em.fc_setting", &em_fc_setting); -/* -** Shadow VFTA table, this is needed because -** the real vlan filter table gets cleared during -** a soft reset and the driver needs to be able -** to repopulate it. -*/ -static u32 em_shadow_vfta[EM_VFTA_SIZE]; - /* Global used in WOL setup with multiport cards */ static int global_quad_port_a = 0; @@ -449,6 +446,11 @@ em_attach(device_t dev) OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, em_sysctl_nvm_info, "I", "NVM Information"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, + em_sysctl_debug_info, "I", "Debug Information"); + callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); /* Determine hardware and mac info */ @@ -468,9 +470,10 @@ em_attach(device_t dev) ** identified */ if ((adapter->hw.mac.type == e1000_ich8lan) || - (adapter->hw.mac.type == e1000_pchlan) || (adapter->hw.mac.type == e1000_ich9lan) || - (adapter->hw.mac.type == e1000_ich10lan)) { + (adapter->hw.mac.type == e1000_ich10lan) || + (adapter->hw.mac.type == e1000_pchlan) || + (adapter->hw.mac.type == e1000_pch2lan)) { int rid = EM_BAR_TYPE_FLASH; adapter->flash = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); @@ -514,11 +517,16 @@ em_attach(device_t dev) E1000_REGISTER(&adapter->hw, E1000_TADV), em_tx_abs_int_delay_dflt); - /* Sysctls for limiting the amount of work done in the taskqueue */ + /* Sysctl for limiting the amount of work done in the taskqueue */ em_add_rx_process_limit(adapter, "rx_processing_limit", "max number of rx packets to process", &adapter->rx_process_limit, em_rx_process_limit); + /* Sysctl for setting the interface flow control */ + em_set_flow_cntrl(adapter, "flow_control", + "max number of rx packets to process", + &adapter->fc_setting, em_fc_setting); + /* * Validate number of transmit and receive descriptors. It * must not exceed hardware maximum, and must be multiple @@ -581,6 +589,11 @@ em_attach(device_t dev) goto err_late; } + /* Check SOL/IDER usage */ + if (e1000_check_reset_block(&adapter->hw)) + device_printf(dev, "PHY reset is blocked" + " due to SOL/IDER session.\n"); + /* ** Start from a known state, this is ** important in reading the nvm and @@ -644,11 +657,6 @@ em_attach(device_t dev) adapter->hw.mac.get_link_status = 1; em_update_link_status(adapter); - /* Indicate SOL/IDER usage */ - if (e1000_check_reset_block(&adapter->hw)) - device_printf(dev, - "PHY reset is blocked due to SOL/IDER session.\n"); - /* Register for VLAN events */ adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, em_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); @@ -857,7 +865,7 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) if (enq > 0) { /* Set the watchdog */ - txr->watchdog_check = TRUE; + txr->queue_status = EM_QUEUE_WORKING; txr->watchdog_time = ticks; } return (err); @@ -870,14 +878,8 @@ static int em_mq_start(struct ifnet *ifp, struct mbuf *m) { struct adapter *adapter = ifp->if_softc; - struct tx_ring *txr; - int i = 0, error = 0; - - /* Which queue to use */ - if ((m->m_flags & M_FLOWID) != 0) - i = m->m_pkthdr.flowid % adapter->num_queues; - - txr = &adapter->tx_rings[i]; + struct tx_ring *txr = adapter->tx_rings; + int error; if (EM_TX_TRYLOCK(txr)) { error = em_mq_start_locked(ifp, txr, m); @@ -953,7 +955,7 @@ em_start_locked(struct ifnet *ifp, struct tx_ring *txr) /* Set timeout in case hardware has problems transmitting. */ txr->watchdog_time = ticks; - txr->watchdog_check = TRUE; + txr->queue_status = EM_QUEUE_WORKING; } return; @@ -1029,6 +1031,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case e1000_82572: case e1000_ich9lan: case e1000_ich10lan: + case e1000_pch2lan: case e1000_82574: case e1000_80003es2lan: /* 9K Jumbo Frame size */ max_frame_size = 9234; @@ -1092,6 +1095,11 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; case SIOCSIFMEDIA: + /* + ** As the speed/duplex settings are being + ** changed, we need to reset the PHY. + */ + adapter->hw.phy.reset_disable = FALSE; /* Check SOL/IDER usage */ EM_CORE_LOCK(adapter); if (e1000_check_reset_block(&adapter->hw)) { @@ -1101,6 +1109,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; } EM_CORE_UNLOCK(adapter); + /* falls thru */ case SIOCGIFMEDIA: IOCTL_DEBUGOUT("ioctl rcv'd: \ SIOCxIFMEDIA (Get/Set Interface Media)"); @@ -1215,13 +1224,16 @@ em_init_locked(struct adapter *adapter) case e1000_82583: pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */ break; + case e1000_ich8lan: + pba = E1000_PBA_8K; + break; case e1000_ich9lan: case e1000_ich10lan: case e1000_pchlan: pba = E1000_PBA_10K; break; - case e1000_ich8lan: - pba = E1000_PBA_8K; + case e1000_pch2lan: + pba = E1000_PBA_26K; break; default: if (adapter->max_frame_size > 8192) @@ -1259,19 +1271,6 @@ em_init_locked(struct adapter *adapter) /* Setup VLAN support, basic and offload if available */ E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); - /* Use real VLAN Filter support? */ - if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { - if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) - /* Use real VLAN Filter support */ - em_setup_vlan_hw_support(adapter); - else { - u32 ctrl; - ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); - ctrl |= E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - } - } - /* Set hardware offload abilities */ ifp->if_hwassist = 0; if (ifp->if_capenable & IFCAP_TXCSUM) @@ -1289,6 +1288,17 @@ em_init_locked(struct adapter *adapter) /* Setup Multicast table */ em_set_multi(adapter); + /* + ** Figure out the desired mbuf + ** pool for doing jumbos + */ + if (adapter->max_frame_size <= 2048) + adapter->rx_mbuf_sz = MCLBYTES; + else if (adapter->max_frame_size <= 4096) + adapter->rx_mbuf_sz = MJUMPAGESIZE; + else + adapter->rx_mbuf_sz = MJUM9BYTES; + /* Prepare receive descriptors and buffers */ if (em_setup_receive_structures(adapter)) { device_printf(dev, "Could not setup receive structures\n"); @@ -1297,6 +1307,19 @@ em_init_locked(struct adapter *adapter) } em_initialize_receive_unit(adapter); + /* Use real VLAN Filter support? */ + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + /* Use real VLAN Filter support */ + em_setup_vlan_hw_support(adapter); + else { + u32 ctrl; + ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + } + } + /* Don't lose promiscuous settings */ em_set_promisc(adapter); @@ -1707,11 +1730,6 @@ em_media_change(struct ifnet *ifp) device_printf(adapter->dev, "Unsupported media type\n"); } - /* As the speed/duplex settings my have changed we need to - * reset the PHY. - */ - adapter->hw.phy.reset_disable = FALSE; - em_init_locked(adapter); EM_CORE_UNLOCK(adapter); @@ -1748,19 +1766,6 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) ip_off = poff = 0; /* - ** When doing checksum offload, it is critical to - ** make sure the first mbuf has more than header, - ** because that routine expects data to be present. - */ - if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) && - (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) { - m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); - *m_headp = m_head; - if (m_head == NULL) - return (ENOBUFS); - } - - /* * Intel recommends entire IP/TCP header length reside in a single * buffer. If multiple descriptors are used to describe the IP and * TCP header, each descriptor should describe one or more @@ -1830,6 +1835,7 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) *m_headp = NULL; return (ENOBUFS); } + ip = (struct ip *)(mtod(m_head, char *) + ip_off); ip->ip_len = 0; ip->ip_sum = 0; /* @@ -1838,6 +1844,7 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) * what hardware expect to see. This is adherence of * Microsoft's Large Send specification. */ + tp = (struct tcphdr *)(mtod(m_head, char *) + poff); tp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); } else if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { @@ -1847,12 +1854,15 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) *m_headp = NULL; return (ENOBUFS); } + ip = (struct ip *)(mtod(m_head, char *) + ip_off); + tp = (struct tcphdr *)(mtod(m_head, char *) + poff); } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { m_head = m_pullup(m_head, poff + sizeof(struct udphdr)); if (m_head == NULL) { *m_headp = NULL; return (ENOBUFS); } + ip = (struct ip *)(mtod(m_head, char *) + ip_off); } *m_headp = m_head; } @@ -1929,15 +1939,12 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) m_head = *m_headp; /* Do hardware assists */ -#if __FreeBSD_version >= 700000 if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { - em_tso_setup(txr, m_head, ip_off, ip, tp, &txd_upper, - &txd_lower); + em_tso_setup(txr, m_head, ip_off, ip, tp, + &txd_upper, &txd_lower); /* we need to make a final sentinel transmit desc */ tso_desc = TRUE; - } else -#endif - if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) + } else if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) em_transmit_checksum_setup(txr, m_head, ip_off, ip, &txd_upper, &txd_lower); @@ -2164,34 +2171,30 @@ em_local_timer(void *arg) em_update_stats_counters(adapter); /* Reset LAA into RAR[0] on 82571 */ - if (e1000_get_laa_state_82571(&adapter->hw) == TRUE) + if ((adapter->hw.mac.type == e1000_82571) && + e1000_get_laa_state_82571(&adapter->hw)) e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); /* - ** If flow control has paused us since last checking - ** it invalidates the watchdog timing, so dont run it. + ** Don't do TX watchdog check if we've been paused */ if (adapter->pause_frames) { adapter->pause_frames = 0; goto out; } /* - ** Check for time since any descriptor was cleaned + ** Check on the state of the TX queue(s), this + ** can be done without the lock because its RO + ** and the HUNG state will be static if set. */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - EM_TX_LOCK(txr); - if (txr->watchdog_check == FALSE) { - EM_TX_UNLOCK(txr); - continue; - } - if ((ticks - txr->watchdog_time) > EM_WATCHDOG) + for (int i = 0; i < adapter->num_queues; i++, txr++) + if (txr->queue_status == EM_QUEUE_HUNG) goto hung; - EM_TX_UNLOCK(txr); - } out: callout_reset(&adapter->timer, hz, em_local_timer, adapter); return; hung: + /* Looks like we're hung */ device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); device_printf(adapter->dev, "Queue(%d) tdh = %d, hw tdt = %d\n", txr->me, @@ -2272,7 +2275,7 @@ em_update_link_status(struct adapter *adapter) adapter->link_active = 0; /* Link down, disable watchdog */ for (int i = 0; i < adapter->num_queues; i++, txr++) - txr->watchdog_check = FALSE; + txr->queue_status = EM_QUEUE_IDLE; if_link_state_change(ifp, LINK_STATE_DOWN); } } @@ -2306,7 +2309,7 @@ em_stop(void *arg) /* Unarm watchdog timer. */ for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); - txr->watchdog_check = FALSE; + txr->queue_status = EM_QUEUE_IDLE; EM_TX_UNLOCK(txr); } @@ -2571,6 +2574,9 @@ em_free_pci_resources(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++) { txr = &adapter->tx_rings[i]; rxr = &adapter->rx_rings[i]; + /* an early abort? */ + if ((txr == NULL) || (rxr == NULL)) + break; rid = txr->msix +1; if (txr->tag != NULL) { bus_teardown_intr(dev, txr->res, txr->tag); @@ -2689,6 +2695,7 @@ static void em_reset(struct adapter *adapter) { device_t dev = adapter->dev; + struct ifnet *ifp = adapter->ifp; struct e1000_hw *hw = &adapter->hw; u16 rx_buffer_size; @@ -2733,15 +2740,25 @@ em_reset(struct adapter *adapter) hw->fc.send_xon = TRUE; /* Set Flow control, use the tunable location if sane */ - if ((em_fc_setting >= 0) || (em_fc_setting < 4)) - hw->fc.requested_mode = em_fc_setting; - else - hw->fc.requested_mode = e1000_fc_none; + hw->fc.requested_mode = adapter->fc_setting; - /* Override - workaround for PCHLAN issue */ + /* Workaround: no TX flow ctrl for PCH */ if (hw->mac.type == e1000_pchlan) hw->fc.requested_mode = e1000_fc_rx_pause; + /* Override - settings for PCH2LAN, ya its magic :) */ + if (hw->mac.type == e1000_pch2lan) { + hw->fc.high_water = 0x5C20; + hw->fc.low_water = 0x5048; + hw->fc.pause_time = 0x0650; + hw->fc.refresh_time = 0x0400; + /* Jumbos need adjusted PBA */ + if (ifp->if_mtu > ETHERMTU) + E1000_WRITE_REG(hw, E1000_PBA, 12); + else + E1000_WRITE_REG(hw, E1000_PBA, 26); + } + /* Issue a global reset */ e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); @@ -3173,6 +3190,7 @@ em_setup_transmit_ring(struct tx_ring *txr) /* Set number of descriptors available */ txr->tx_avail = adapter->num_tx_desc; + txr->queue_status = EM_QUEUE_IDLE; /* Clear checksum offload context. */ txr->last_hw_offload = 0; @@ -3233,7 +3251,7 @@ em_initialize_transmit_unit(struct adapter *adapter) E1000_READ_REG(&adapter->hw, E1000_TDBAL(i)), E1000_READ_REG(&adapter->hw, E1000_TDLEN(i))); - txr->watchdog_check = FALSE; + txr->queue_status = EM_QUEUE_IDLE; } /* Set the default values for the Tx Inter Packet Gap timer */ @@ -3610,16 +3628,20 @@ static bool em_txeof(struct tx_ring *txr) { struct adapter *adapter = txr->adapter; - int first, last, done; + int first, last, done, processed; struct em_buffer *tx_buffer; struct e1000_tx_desc *tx_desc, *eop_desc; struct ifnet *ifp = adapter->ifp; EM_TX_LOCK_ASSERT(txr); - if (txr->tx_avail == adapter->num_tx_desc) + /* No work, make sure watchdog is off */ + if (txr->tx_avail == adapter->num_tx_desc) { + txr->queue_status = EM_QUEUE_IDLE; return (FALSE); + } + processed = 0; first = txr->next_to_clean; tx_desc = &txr->tx_base[first]; tx_buffer = &txr->tx_buffers[first]; @@ -3646,6 +3668,7 @@ em_txeof(struct tx_ring *txr) tx_desc->lower.data = 0; tx_desc->buffer_addr = 0; ++txr->tx_avail; + ++processed; if (tx_buffer->m_head) { bus_dmamap_sync(txr->txtag, @@ -3681,6 +3704,16 @@ em_txeof(struct tx_ring *txr) txr->next_to_clean = first; + /* + ** Watchdog calculation, we know there's + ** work outstanding or the first return + ** would have been taken, so none processed + ** for too long indicates a hang. local timer + ** will examine this and do a reset if needed. + */ + if ((!processed) && ((ticks - txr->watchdog_time) > EM_WATCHDOG)) + txr->queue_status = EM_QUEUE_HUNG; + /* * If we have enough room, clear IFF_DRV_OACTIVE * to tell the stack that it is OK to send packets. @@ -3689,7 +3722,7 @@ em_txeof(struct tx_ring *txr) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* Disable watchdog if all clean */ if (txr->tx_avail == adapter->num_tx_desc) { - txr->watchdog_check = FALSE; + txr->queue_status = EM_QUEUE_IDLE; return (FALSE); } } @@ -3723,7 +3756,8 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit) */ if (rxbuf->m_head != NULL) goto reuse; - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getjcl(M_DONTWAIT, MT_DATA, + M_PKTHDR, adapter->rx_mbuf_sz); /* ** If we have a temporary resource shortage ** that causes a failure, just abort refresh @@ -3732,10 +3766,7 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit) */ if (m == NULL) goto update; - m->m_len = m->m_pkthdr.len = MCLBYTES; - - if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) - m_adj(m, ETHER_ALIGN); + m->m_len = m->m_pkthdr.len = adapter->rx_mbuf_sz; /* Use bus_dma machinery to setup the memory mapping */ error = bus_dmamap_load_mbuf_sg(rxr->rxtag, rxbuf->map, @@ -3801,9 +3832,9 @@ em_allocate_receive_buffers(struct rx_ring *rxr) BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MCLBYTES, /* maxsize */ + MJUM9BYTES, /* maxsize */ 1, /* nsegments */ - MCLBYTES, /* maxsegsize */ + MJUM9BYTES, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ @@ -3871,12 +3902,13 @@ em_setup_receive_ring(struct rx_ring *rxr) for (int j = 0; j != adapter->num_rx_desc; ++j) { rxbuf = &rxr->rx_buffers[j]; - rxbuf->m_head = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + rxbuf->m_head = m_getjcl(M_DONTWAIT, MT_DATA, + M_PKTHDR, adapter->rx_mbuf_sz); if (rxbuf->m_head == NULL) return (ENOBUFS); - rxbuf->m_head->m_len = MCLBYTES; + rxbuf->m_head->m_len = adapter->rx_mbuf_sz; rxbuf->m_head->m_flags &= ~M_HASFCS; /* we strip it */ - rxbuf->m_head->m_pkthdr.len = MCLBYTES; + rxbuf->m_head->m_pkthdr.len = adapter->rx_mbuf_sz; /* Get the memory mapping */ error = bus_dmamap_load_mbuf_sg(rxr->rxtag, @@ -4082,6 +4114,23 @@ em_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1); } + /* Set early receive threshold on appropriate hw */ + if (((adapter->hw.mac.type == e1000_ich9lan) || + (adapter->hw.mac.type == e1000_pch2lan) || + (adapter->hw.mac.type == e1000_ich10lan)) && + (ifp->if_mtu > ETHERMTU)) { + u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); + E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); + E1000_WRITE_REG(hw, E1000_ERT, 0x100 | (1 << 13)); + } + + if (adapter->hw.mac.type == e1000_pch2lan) { + if (ifp->if_mtu > ETHERMTU) + e1000_lv_jumbo_workaround_ich8lan(hw, TRUE); + else + e1000_lv_jumbo_workaround_ich8lan(hw, FALSE); + } + /* Setup the Receive Control Register */ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | @@ -4094,7 +4143,14 @@ em_initialize_receive_unit(struct adapter *adapter) /* Make sure VLAN Filters are off */ rctl &= ~E1000_RCTL_VFE; rctl &= ~E1000_RCTL_SBP; - rctl |= E1000_RCTL_SZ_2048; + + if (adapter->rx_mbuf_sz == MCLBYTES) + rctl |= E1000_RCTL_SZ_2048; + else if (adapter->rx_mbuf_sz == MJUMPAGESIZE) + rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; + else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) + rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; + if (ifp->if_mtu > ETHERMTU) rctl |= E1000_RCTL_LPE; else @@ -4190,7 +4246,7 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) rxr->fmp->m_flags |= M_VLANTAG; } #ifdef EM_MULTIQUEUE - rxr->fmp->m_pkthdr.flowid = curcpu; + rxr->fmp->m_pkthdr.flowid = rxr->msix; rxr->fmp->m_flags |= M_FLOWID; #endif #ifndef __NO_STRICT_ALIGNMENT @@ -4253,6 +4309,7 @@ skip: static __inline void em_rx_discard(struct rx_ring *rxr, int i) { + struct adapter *adapter = rxr->adapter; struct em_buffer *rbuf; struct mbuf *m; @@ -4267,7 +4324,7 @@ em_rx_discard(struct rx_ring *rxr, int i) /* Reset state, keep loaded DMA map and reuse */ m = rbuf->m_head; - m->m_len = m->m_pkthdr.len = MCLBYTES; + m->m_len = m->m_pkthdr.len = adapter->rx_mbuf_sz; m->m_flags |= M_PKTHDR; m->m_data = m->m_ext.ext_buf; m->m_next = NULL; @@ -4378,12 +4435,15 @@ em_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ return; + EM_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - em_shadow_vfta[index] |= (1 << bit); + adapter->shadow_vfta[index] |= (1 << bit); ++adapter->num_vlans; /* Re-init to load the changes */ - em_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + em_init_locked(adapter); + EM_CORE_UNLOCK(adapter); } /* @@ -4402,12 +4462,15 @@ em_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + EM_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - em_shadow_vfta[index] &= ~(1 << bit); + adapter->shadow_vfta[index] &= ~(1 << bit); --adapter->num_vlans; /* Re-init to load the changes */ - em_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + em_init_locked(adapter); + EM_CORE_UNLOCK(adapter); } static void @@ -4430,9 +4493,9 @@ em_setup_vlan_hw_support(struct adapter *adapter) ** we need to repopulate it now. */ for (int i = 0; i < EM_VFTA_SIZE; i++) - if (em_shadow_vfta[i] != 0) + if (adapter->shadow_vfta[i] != 0) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, - i, em_shadow_vfta[i]); + i, adapter->shadow_vfta[i]); reg = E1000_READ_REG(hw, E1000_CTRL); reg |= E1000_CTRL_VME; @@ -4443,10 +4506,6 @@ em_setup_vlan_hw_support(struct adapter *adapter) reg &= ~E1000_RCTL_CFIEN; reg |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); - - /* Update the frame size */ - E1000_WRITE_REG(&adapter->hw, E1000_RLPML, - adapter->max_frame_size + VLAN_TAG_SIZE); } static void @@ -4615,6 +4674,7 @@ em_get_wakeup(device_t dev) case e1000_ich9lan: case e1000_ich10lan: case e1000_pchlan: + case e1000_pch2lan: apme_mask = E1000_WUC_APME; adapter->has_amt = TRUE; eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC); @@ -4706,7 +4766,8 @@ em_enable_wakeup(device_t dev) E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); } - if (adapter->hw.mac.type == e1000_pchlan) { + if ((adapter->hw.mac.type == e1000_pchlan) || + (adapter->hw.mac.type == e1000_pch2lan)) { if (em_enable_phy_wakeup(adapter)) return; } else { @@ -4739,16 +4800,7 @@ em_enable_phy_wakeup(struct adapter *adapter) u16 preg; /* copy MAC RARs to PHY RARs */ - for (int i = 0; i < adapter->hw.mac.rar_entry_count; i++) { - mreg = E1000_READ_REG(hw, E1000_RAL(i)); - e1000_write_phy_reg(hw, BM_RAR_L(i), (u16)(mreg & 0xFFFF)); - e1000_write_phy_reg(hw, BM_RAR_M(i), - (u16)((mreg >> 16) & 0xFFFF)); - mreg = E1000_READ_REG(hw, E1000_RAH(i)); - e1000_write_phy_reg(hw, BM_RAR_H(i), (u16)(mreg & 0xFFFF)); - e1000_write_phy_reg(hw, BM_RAR_CTRL(i), - (u16)((mreg >> 16) & 0xFFFF)); - } + e1000_copy_rx_addrs_to_phy_ich8lan(hw); /* copy MAC MTA to PHY MTA */ for (int i = 0; i < adapter->hw.mac.mta_reg_count; i++) { @@ -5359,4 +5411,70 @@ em_add_rx_process_limit(struct adapter *adapter, const char *name, OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } +static void +em_set_flow_cntrl(struct adapter *adapter, const char *name, + const char *description, int *limit, int value) +{ + *limit = value; + SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), + OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); +} + +static int +em_sysctl_debug_info(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter; + int error; + int result; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + adapter = (struct adapter *)arg1; + em_print_debug_info(adapter); + } + + return (error); +} + +/* +** This routine is meant to be fluid, add whatever is +** needed for debugging a problem. -jfv +*/ +static void +em_print_debug_info(struct adapter *adapter) +{ + device_t dev = adapter->dev; + struct tx_ring *txr = adapter->tx_rings; + struct rx_ring *rxr = adapter->rx_rings; + if (adapter->ifp->if_drv_flags & IFF_DRV_RUNNING) + printf("Interface is RUNNING "); + else + printf("Interface is NOT RUNNING\n"); + if (adapter->ifp->if_drv_flags & IFF_DRV_OACTIVE) + printf("and ACTIVE\n"); + else + printf("and INACTIVE\n"); + + device_printf(dev, "hw tdh = %d, hw tdt = %d\n", + E1000_READ_REG(&adapter->hw, E1000_TDH(0)), + E1000_READ_REG(&adapter->hw, E1000_TDT(0))); + device_printf(dev, "hw rdh = %d, hw rdt = %d\n", + E1000_READ_REG(&adapter->hw, E1000_RDH(0)), + E1000_READ_REG(&adapter->hw, E1000_RDT(0))); + device_printf(dev, "Tx Queue Status = %d\n", txr->queue_status); + device_printf(dev, "TX descriptors avail = %d\n", + txr->tx_avail); + device_printf(dev, "Tx Descriptors avail failure = %ld\n", + txr->no_desc_avail); + device_printf(dev, "RX discarded packets = %ld\n", + rxr->rx_discarded); + device_printf(dev, "RX Next to Check = %d\n", rxr->next_to_check); + device_printf(dev, "RX Next to Refresh = %d\n", rxr->next_to_refresh); +} diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index fec34ac..8bfd600 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -188,6 +188,10 @@ #define EM_EEPROM_APME 0x400; #define EM_82544_APME 0x0004; +#define EM_QUEUE_IDLE 0 +#define EM_QUEUE_WORKING 1 +#define EM_QUEUE_HUNG 2 + /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will @@ -272,7 +276,7 @@ struct tx_ring { u32 me; u32 msix; u32 ims; - bool watchdog_check; + int queue_status; int watchdog_time; struct em_dma_alloc txdma; struct e1000_tx_desc *tx_base; @@ -391,6 +395,7 @@ struct adapter { struct rx_ring *rx_rings; int num_rx_desc; u32 rx_process_limit; + u32 rx_mbuf_sz; /* Management and WOL features */ u32 wol; @@ -400,11 +405,21 @@ struct adapter { /* Multicast array memory */ u8 *mta; - /* Info about the board itself */ - uint8_t link_active; - uint16_t link_speed; - uint16_t link_duplex; - uint32_t smartspeed; + /* + ** Shadow VFTA table, this is needed because + ** the real vlan filter table gets cleared during + ** a soft reset and the driver needs to be able + ** to repopulate it. + */ + u32 shadow_vfta[EM_VFTA_SIZE]; + + /* Info about the interface */ + u8 link_active; + u16 link_speed; + u16 link_duplex; + u32 smartspeed; + u32 fc_setting; + struct em_int_delay_info tx_int_delay; struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c index 846d6bf..21686e6 100644 --- a/sys/dev/e1000/if_lem.c +++ b/sys/dev/e1000/if_lem.c @@ -51,9 +51,7 @@ #include <sys/sockio.h> #include <sys/sysctl.h> #include <sys/taskqueue.h> -#if __FreeBSD_version >= 700029 #include <sys/eventhandler.h> -#endif #include <machine/bus.h> #include <machine/resource.h> @@ -86,8 +84,7 @@ /********************************************************************* * Legacy Em Driver version: *********************************************************************/ -char lem_driver_version[] = "1.0.2"; - +char lem_driver_version[] = "1.0.3"; /********************************************************************* * PCI Device ID Table @@ -209,11 +206,9 @@ static void lem_disable_promisc(struct adapter *); static void lem_set_multi(struct adapter *); static void lem_update_link_status(struct adapter *); static int lem_get_buf(struct adapter *, int); -#if __FreeBSD_version >= 700029 static void lem_register_vlan(void *, struct ifnet *, u16); static void lem_unregister_vlan(void *, struct ifnet *, u16); static void lem_setup_vlan_hw_support(struct adapter *); -#endif static int lem_xmit(struct adapter *, struct mbuf **); static void lem_smartspeed(struct adapter *); static int lem_82547_fifo_workaround(struct adapter *, int); @@ -231,6 +226,8 @@ static u32 lem_fill_descriptors (bus_addr_t address, u32 length, static int lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS); static void lem_add_int_delay_sysctl(struct adapter *, const char *, const char *, struct em_int_delay_info *, int, int); +static void lem_set_flow_cntrl(struct adapter *, const char *, + const char *, int *, int); /* Management and WOL Support */ static void lem_init_manageability(struct adapter *); static void lem_release_manageability(struct adapter *); @@ -244,11 +241,7 @@ static void lem_led_func(void *, int); #ifdef EM_LEGACY_IRQ static void lem_intr(void *); #else /* FAST IRQ */ -#if __FreeBSD_version < 700000 -static void lem_irq_fast(void *); -#else static int lem_irq_fast(void *); -#endif static void lem_handle_rxtx(void *context, int pending); static void lem_handle_link(void *context, int pending); static void lem_add_rx_process_limit(struct adapter *, const char *, @@ -320,14 +313,6 @@ TUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit); static int lem_fc_setting = e1000_fc_full; TUNABLE_INT("hw.em.fc_setting", &lem_fc_setting); -/* -** Shadow VFTA table, this is needed because -** the real vlan filter table gets cleared during -** a soft reset and the driver needs to be able -** to repopulate it. -*/ -static u32 lem_shadow_vfta[EM_VFTA_SIZE]; - /* Global used in WOL setup with multiport cards */ static int global_quad_port_a = 0; @@ -462,6 +447,11 @@ lem_attach(device_t dev) lem_rx_process_limit); #endif + /* Sysctl for setting the interface flow control */ + lem_set_flow_cntrl(adapter, "flow_control", + "max number of rx packets to process", + &adapter->fc_setting, lem_fc_setting); + /* * Validate number of transmit and receive descriptors. It * must not exceed hardware maximum, and must be multiple @@ -638,13 +628,11 @@ lem_attach(device_t dev) else adapter->pcix_82544 = FALSE; -#if __FreeBSD_version >= 700029 /* Register for VLAN events */ adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, lem_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, lem_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); -#endif lem_add_hw_stats(adapter); @@ -702,11 +690,7 @@ lem_detach(device_t dev) INIT_DEBUGOUT("em_detach: begin"); /* Make sure VLANS are not using driver */ -#if __FreeBSD_version >= 700000 if (adapter->ifp->if_vlantrunk != NULL) { -#else - if (adapter->ifp->if_nvlans != 0) { -#endif device_printf(dev,"Vlan in use, detach first\n"); return (EBUSY); } @@ -730,13 +714,11 @@ lem_detach(device_t dev) EM_TX_UNLOCK(adapter); EM_CORE_UNLOCK(adapter); -#if __FreeBSD_version >= 700029 /* Unregister VLAN events */ if (adapter->vlan_attach != NULL) EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); if (adapter->vlan_detach != NULL) EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); -#endif ether_ifdetach(adapter->ifp); callout_drain(&adapter->timer); @@ -831,6 +813,19 @@ lem_start_locked(struct ifnet *ifp) if (!adapter->link_active) return; + /* + * Force a cleanup if number of TX descriptors + * available hits the threshold + */ + if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { + lem_txeof(adapter); + /* Now do we at least have a minimal? */ + if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) { + adapter->no_tx_desc_avail1++; + return; + } + } + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); @@ -1043,9 +1038,7 @@ lem_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) lem_init(adapter); -#if __FreeBSD_version >= 700000 VLAN_CAPABILITIES(ifp); -#endif break; } @@ -1135,17 +1128,8 @@ lem_init_locked(struct adapter *adapter) /* Setup VLAN support, basic and offload if available */ E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); -#if __FreeBSD_version < 700029 - if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { - u32 ctrl; - ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); - ctrl |= E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - } -#else /* Use real VLAN Filter support */ lem_setup_vlan_hw_support(adapter); -#endif /* Set hardware offload abilities */ ifp->if_hwassist = 0; @@ -1174,6 +1158,19 @@ lem_init_locked(struct adapter *adapter) } lem_initialize_receive_unit(adapter); + /* Use real VLAN Filter support? */ + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + /* Use real VLAN Filter support */ + lem_setup_vlan_hw_support(adapter); + else { + u32 ctrl; + ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + } + } + /* Don't lose promiscuous settings */ lem_set_promisc(adapter); @@ -1276,7 +1273,6 @@ lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) * Legacy Interrupt Service routine * *********************************************************************/ - static void lem_intr(void *arg) { @@ -1311,7 +1307,6 @@ lem_intr(void *arg) } EM_TX_LOCK(adapter); - lem_txeof(adapter); lem_rxeof(adapter, -1, NULL); lem_txeof(adapter); if (ifp->if_drv_flags & IFF_DRV_RUNNING && @@ -1354,8 +1349,7 @@ lem_handle_rxtx(void *context, int pending) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if (lem_rxeof(adapter, adapter->rx_process_limit, NULL) != 0) - taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); + lem_rxeof(adapter, adapter->rx_process_limit, NULL); EM_TX_LOCK(adapter); lem_txeof(adapter); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) @@ -1363,7 +1357,8 @@ lem_handle_rxtx(void *context, int pending) EM_TX_UNLOCK(adapter); } - lem_enable_intr(adapter); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + lem_enable_intr(adapter); } /********************************************************************* @@ -1371,13 +1366,7 @@ lem_handle_rxtx(void *context, int pending) * Fast Legacy/MSI Combined Interrupt Service routine * *********************************************************************/ -#if __FreeBSD_version < 700000 -#define FILTER_STRAY -#define FILTER_HANDLED -static void -#else static int -#endif lem_irq_fast(void *arg) { struct adapter *adapter = arg; @@ -1550,25 +1539,10 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp) struct mbuf *m_head; u32 txd_upper, txd_lower, txd_used, txd_saved; int error, nsegs, i, j, first, last = 0; -#if __FreeBSD_version < 700000 - struct m_tag *mtag; -#endif + m_head = *m_headp; txd_upper = txd_lower = txd_used = txd_saved = 0; - /* - * Force a cleanup if number of TX descriptors - * available hits the threshold - */ - if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { - lem_txeof(adapter); - /* Now do we at least have a minimal? */ - if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) { - adapter->no_tx_desc_avail1++; - return (ENOBUFS); - } - } - /* ** When doing checksum offload, it is critical to ** make sure the first mbuf has more than header, @@ -1712,20 +1686,6 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp) else adapter->num_tx_desc_avail -= nsegs; - /* - ** Handle VLAN tag, this is the - ** biggest difference between - ** 6.x and 7 - */ -#if __FreeBSD_version < 700000 - /* Find out if we are in vlan mode. */ - mtag = VLAN_OUTPUT_TAG(ifp, m_head); - if (mtag != NULL) { - ctxd->upper.fields.special = - htole16(VLAN_TAG_VALUE(mtag)); - ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE); - } -#else /* FreeBSD 7 */ if (m_head->m_flags & M_VLANTAG) { /* Set the vlan id. */ ctxd->upper.fields.special = @@ -1733,7 +1693,6 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp) /* Tell hardware to add tag */ ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE); } -#endif tx_buffer->m_head = m_head; tx_buffer_mapped->map = tx_buffer->map; @@ -2249,11 +2208,7 @@ lem_allocate_irq(struct adapter *adapter) #ifdef EM_LEGACY_IRQ /* We do Legacy setup */ if ((error = bus_setup_intr(dev, adapter->res[0], -#if __FreeBSD_version > 700000 INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, -#else /* 6.X */ - INTR_TYPE_NET | INTR_MPSAFE, lem_intr, adapter, -#endif &adapter->tag[0])) != 0) { device_printf(dev, "Failed to register interrupt handler"); return (error); @@ -2270,13 +2225,8 @@ lem_allocate_irq(struct adapter *adapter) taskqueue_thread_enqueue, &adapter->tq); taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", device_get_nameunit(adapter->dev)); -#if __FreeBSD_version < 700000 - if ((error = bus_setup_intr(dev, adapter->res[0], - INTR_TYPE_NET | INTR_FAST, lem_irq_fast, adapter, -#else if ((error = bus_setup_intr(dev, adapter->res[0], INTR_TYPE_NET, lem_irq_fast, NULL, adapter, -#endif &adapter->tag[0])) != 0) { device_printf(dev, "Failed to register fast interrupt " "handler: %d\n", error); @@ -2362,7 +2312,7 @@ lem_hardware_init(struct adapter *adapter) adapter->hw.fc.send_xon = TRUE; /* Set Flow control, use the tunable location if sane */ - if ((lem_fc_setting >= 0) || (lem_fc_setting < 4)) + if ((lem_fc_setting >= 0) && (lem_fc_setting < 4)) adapter->hw.fc.requested_mode = lem_fc_setting; else adapter->hw.fc.requested_mode = e1000_fc_none; @@ -2410,14 +2360,8 @@ lem_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities = ifp->if_capenable = 0; if (adapter->hw.mac.type >= e1000_82543) { - int version_cap; -#if __FreeBSD_version < 700000 - version_cap = IFCAP_HWCSUM; -#else - version_cap = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; -#endif - ifp->if_capabilities |= version_cap; - ifp->if_capenable |= version_cap; + ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; + ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; } /* @@ -2427,6 +2371,16 @@ lem_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; + /* + ** Dont turn this on by default, if vlans are + ** created on another pseudo device (eg. lagg) + ** then vlan events are not passed thru, breaking + ** operation, but with HW FILTER off it works. If + ** using vlans directly on the em driver you can + ** enable this and get full hardware tag filtering. + */ + ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; + #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif @@ -2551,11 +2505,7 @@ lem_dma_malloc(struct adapter *adapter, bus_size_t size, { int error; -#if __FreeBSD_version >= 700000 error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ -#else - error = bus_dma_tag_create(NULL, /* parent */ -#endif EM_DBA_ALIGN, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ @@ -2640,21 +2590,17 @@ lem_allocate_transmit_structures(struct adapter *adapter) /* * Create DMA tags for tx descriptors */ -#if __FreeBSD_version >= 700000 if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ -#else - if ((error = bus_dma_tag_create(NULL, /* parent */ -#endif 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - EM_TSO_SIZE, /* maxsize */ + MCLBYTES * EM_MAX_SCATTER, /* maxsize */ EM_MAX_SCATTER, /* nsegments */ - EM_TSO_SEG_SIZE, /* maxsegsize */ + MCLBYTES, /* maxsegsize */ 0, /* flags */ - NULL, /* lockfunc */ - NULL, /* lockarg */ + NULL, /* lockfunc */ + NULL, /* lockarg */ &adapter->txtag)) != 0) { device_printf(dev, "Unable to allocate TX DMA tag\n"); goto fail; @@ -3072,23 +3018,20 @@ lem_txeof(struct adapter *adapter) BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); adapter->next_tx_to_clean = first; + adapter->num_tx_desc_avail = num_avail; /* * If we have enough room, clear IFF_DRV_OACTIVE to * tell the stack that it is OK to send packets. * If there are no pending descriptors, clear the watchdog. */ - if (num_avail > EM_TX_CLEANUP_THRESHOLD) { + if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - if (num_avail == adapter->num_tx_desc) { + if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { adapter->watchdog_check = FALSE; - adapter->num_tx_desc_avail = num_avail; return; } } - - adapter->num_tx_desc_avail = num_avail; - return; } /********************************************************************* @@ -3185,11 +3128,7 @@ lem_allocate_receive_structures(struct adapter *adapter) return (ENOMEM); } -#if __FreeBSD_version >= 700000 error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ -#else - error = bus_dma_tag_create(NULL, /* parent */ -#endif 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ @@ -3459,7 +3398,7 @@ lem_rxeof(struct adapter *adapter, int count, int *done) { struct ifnet *ifp = adapter->ifp;; struct mbuf *mp; - u8 status, accept_frame = 0, eop = 0; + u8 status = 0, accept_frame = 0, eop = 0; u16 len, desc_len, prev_len_adj; int i, rx_sent = 0; struct e1000_rx_desc *current_desc; @@ -3477,11 +3416,13 @@ lem_rxeof(struct adapter *adapter, int count, int *done) return (FALSE); } - while ((current_desc->status & E1000_RXD_STAT_DD) && - (count != 0) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) { + while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { struct mbuf *m = NULL; + status = current_desc->status; + if ((status & E1000_RXD_STAT_DD) == 0) + break; + mp = adapter->rx_buffer_area[i].m_head; /* * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT @@ -3493,7 +3434,6 @@ lem_rxeof(struct adapter *adapter, int count, int *done) accept_frame = 1; prev_len_adj = 0; desc_len = le16toh(current_desc->length); - status = current_desc->status; if (status & E1000_RXD_STAT_EOP) { count--; eop = 1; @@ -3571,16 +3511,10 @@ lem_rxeof(struct adapter *adapter, int count, int *done) goto skip; #endif if (status & E1000_RXD_STAT_VP) { -#if __FreeBSD_version < 700000 - VLAN_INPUT_TAG_NEW(ifp, adapter->fmp, - (le16toh(current_desc->special) & - E1000_RXD_SPC_VLAN_MASK)); -#else adapter->fmp->m_pkthdr.ether_vtag = (le16toh(current_desc->special) & E1000_RXD_SPC_VLAN_MASK); adapter->fmp->m_flags |= M_VLANTAG; -#endif } #ifndef __NO_STRICT_ALIGNMENT skip: @@ -3636,7 +3570,7 @@ discard: if (done != NULL) *done = rx_sent; EM_RX_UNLOCK(adapter); - return (current_desc->status & E1000_RXD_STAT_DD); + return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); } #ifndef __NO_STRICT_ALIGNMENT @@ -3728,7 +3662,6 @@ lem_receive_checksum(struct adapter *adapter, } } -#if __FreeBSD_version >= 700029 /* * This routine is run via an vlan * config EVENT @@ -3745,12 +3678,15 @@ lem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ return; + EM_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - lem_shadow_vfta[index] |= (1 << bit); + adapter->shadow_vfta[index] |= (1 << bit); ++adapter->num_vlans; /* Re-init to load the changes */ - lem_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + lem_init_locked(adapter); + EM_CORE_UNLOCK(adapter); } /* @@ -3769,12 +3705,15 @@ lem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + EM_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - lem_shadow_vfta[index] &= ~(1 << bit); + adapter->shadow_vfta[index] &= ~(1 << bit); --adapter->num_vlans; /* Re-init to load the changes */ - lem_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + lem_init_locked(adapter); + EM_CORE_UNLOCK(adapter); } static void @@ -3797,9 +3736,9 @@ lem_setup_vlan_hw_support(struct adapter *adapter) ** we need to repopulate it now. */ for (int i = 0; i < EM_VFTA_SIZE; i++) - if (lem_shadow_vfta[i] != 0) + if (adapter->shadow_vfta[i] != 0) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, - i, lem_shadow_vfta[i]); + i, adapter->shadow_vfta[i]); reg = E1000_READ_REG(hw, E1000_CTRL); reg |= E1000_CTRL_VME; @@ -3815,7 +3754,6 @@ lem_setup_vlan_hw_support(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, E1000_RLPML, adapter->max_frame_size + VLAN_TAG_SIZE); } -#endif static void lem_enable_intr(struct adapter *adapter) @@ -4661,6 +4599,16 @@ lem_add_int_delay_sysctl(struct adapter *adapter, const char *name, info, 0, lem_sysctl_int_delay, "I", description); } +static void +lem_set_flow_cntrl(struct adapter *adapter, const char *name, + const char *description, int *limit, int value) +{ + *limit = value; + SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), + OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); +} + #ifndef EM_LEGACY_IRQ static void lem_add_rx_process_limit(struct adapter *adapter, const char *name, @@ -4672,5 +4620,3 @@ lem_add_rx_process_limit(struct adapter *adapter, const char *name, OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } #endif - - diff --git a/sys/dev/e1000/if_lem.h b/sys/dev/e1000/if_lem.h index 2f76aa8..e866d07e 100644 --- a/sys/dev/e1000/if_lem.h +++ b/sys/dev/e1000/if_lem.h @@ -328,11 +328,9 @@ struct adapter { struct task tx_task; struct taskqueue *tq; /* private task queue */ -#if __FreeBSD_version >= 700029 eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; u32 num_vlans; -#endif /* Management and WOL features */ u32 wol; @@ -341,11 +339,22 @@ struct adapter { /* Multicast array memory */ u8 *mta; - /* Info about the board itself */ + + /* + ** Shadow VFTA table, this is needed because + ** the real vlan filter table gets cleared during + ** a soft reset and the driver needs to be able + ** to repopulate it. + */ + u32 shadow_vfta[EM_VFTA_SIZE]; + + /* Info about the interface */ uint8_t link_active; uint16_t link_speed; uint16_t link_duplex; uint32_t smartspeed; + uint32_t fc_setting; + struct em_int_delay_info tx_int_delay; struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; @@ -407,6 +416,9 @@ struct adapter { unsigned long no_tx_dma_setup; unsigned long watchdog_events; unsigned long rx_overruns; + unsigned long rx_irq; + unsigned long tx_irq; + unsigned long link_irq; /* 82547 workaround */ uint32_t tx_fifo_size; diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 9f915df..454ee22 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -141,6 +141,7 @@ static const struct mii_phydesc brgphys[] = { MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709C), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5761), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709S), + MII_PHY_DESC(xxBROADCOM_ALT2, BCM5717C), MII_PHY_DESC(BROADCOM2, BCM5906), MII_PHY_END }; @@ -253,6 +254,9 @@ brgphy_attach(device_t dev) break; } break; + case MII_OUI_xxBROADCOM_ALT2: + /* No special handling yet. */ + break; default: device_printf(dev, "Unrecognized OUI for PHY!\n"); } @@ -1011,6 +1015,7 @@ brgphy_reset(struct mii_softc *sc) } break; case MII_OUI_xxBROADCOM_ALT1: + case MII_OUI_xxBROADCOM_ALT2: break; } diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c index e763c21..f49f7c4 100644 --- a/sys/dev/mii/e1000phy.c +++ b/sys/dev/mii/e1000phy.c @@ -206,7 +206,7 @@ e1000phy_reset(struct mii_softc *sc) reg &= ~E1000_SCR_MODE_MASK; reg |= E1000_SCR_MODE_1000BX; PHY_WRITE(sc, E1000_SCR, reg); - if ((sc->mii_flags & MIIF_MACPRIV0) != 0) { + if ((sc->mii_flags & MIIF_PHYPRIV0) != 0) { /* Set SIGDET polarity low for SFP module. */ PHY_WRITE(sc, E1000_EADR, 1); reg = PHY_READ(sc, E1000_SCR); diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index 015d53c..d1cc4f5 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -107,8 +107,8 @@ mii_phy_setmedia(struct mii_softc *sc) if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 || - (sc->mii_flags & MIIF_FORCEANEG)) - (void) mii_phy_auto(sc); + (sc->mii_flags & MIIF_FORCEANEG) != 0) + (void)mii_phy_auto(sc); return; } @@ -124,64 +124,59 @@ mii_phy_setmedia(struct mii_softc *sc) bmcr = mii_media_table[ife->ifm_data].mm_bmcr; gtcr = mii_media_table[ife->ifm_data].mm_gtcr; - if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { + if ((mii->mii_media.ifm_media & IFM_ETH_MASTER) != 0) { switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_1000_T: - gtcr |= GTCR_MAN_MS|GTCR_ADV_MS; + gtcr |= GTCR_MAN_MS | GTCR_ADV_MS; break; default: - panic("mii_phy_setmedia: MASTER on wrong media"); + printf("mii_phy_setmedia: MASTER on wrong media\n"); } } - if (ife->ifm_media & IFM_LOOP) + if ((ife->ifm_media & IFM_LOOP) != 0) bmcr |= BMCR_LOOP; PHY_WRITE(sc, MII_ANAR, anar); PHY_WRITE(sc, MII_BMCR, bmcr); - if (sc->mii_flags & MIIF_HAVE_GTCR) + if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) PHY_WRITE(sc, MII_100T2CR, gtcr); } int mii_phy_auto(struct mii_softc *sc) { + int anar, gtcr; /* * Check for 1000BASE-X. Autonegotiation is a bit * different on such devices. */ - if (sc->mii_flags & MIIF_IS_1000X) { - uint16_t anar = 0; - - if (sc->mii_extcapabilities & EXTSR_1000XFDX) + if ((sc->mii_flags & MIIF_IS_1000X) != 0) { + anar = 0; + if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) anar |= ANAR_X_FD; - if (sc->mii_extcapabilities & EXTSR_1000XHDX) + if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0) anar |= ANAR_X_HD; - if (sc->mii_flags & MIIF_DOPAUSE) { + if ((sc->mii_flags & MIIF_DOPAUSE) != 0) { /* XXX Asymmetric vs. symmetric? */ anar |= ANLPAR_X_PAUSE_TOWARDS; } - PHY_WRITE(sc, MII_ANAR, anar); } else { - uint16_t anar; - anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; - if (sc->mii_flags & MIIF_DOPAUSE) + if ((sc->mii_flags & MIIF_DOPAUSE) != 0) anar |= ANAR_FC; PHY_WRITE(sc, MII_ANAR, anar); - if (sc->mii_flags & MIIF_HAVE_GTCR) { - uint16_t gtcr = 0; - - if (sc->mii_extcapabilities & EXTSR_1000TFDX) + if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) { + gtcr = 0; + if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) gtcr |= GTCR_ADV_1000TFDX; - if (sc->mii_extcapabilities & EXTSR_1000THDX) + if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) gtcr |= GTCR_ADV_1000THDX; - PHY_WRITE(sc, MII_100T2CR, gtcr); } } @@ -213,7 +208,7 @@ mii_phy_tick(struct mii_softc *sc) /* Read the status register twice; BMSR_LINK is latch-low. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); - if (reg & BMSR_LINK) { + if ((reg & BMSR_LINK) != 0) { sc->mii_ticks = 0; /* reset autonegotiation timer. */ /* See above. */ return (0); @@ -243,7 +238,7 @@ mii_phy_reset(struct mii_softc *sc) struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; int reg, i; - if (sc->mii_flags & MIIF_NOISOLATE) + if ((sc->mii_flags & MIIF_NOISOLATE) != 0) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; @@ -303,7 +298,10 @@ mii_phy_add_media(struct mii_softc *sc) return; } - /* Set aneg timer for 10/100 media. Gigabit media handled below. */ + /* + * Set the autonegotiation timer for 10/100 media. Gigabit media is + * handled below. + */ sc->mii_anegticks = MII_ANEGTICKS; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) @@ -318,55 +316,54 @@ mii_phy_add_media(struct mii_softc *sc) * HomePNA PHYs. And there is really only one media type * that is supported. */ - if (sc->mii_flags & MIIF_IS_HPNA) { - if (sc->mii_capabilities & BMSR_10THDX) { + if ((sc->mii_flags & MIIF_IS_HPNA) != 0) { + if ((sc->mii_capabilities & BMSR_10THDX) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, - sc->mii_inst), - MII_MEDIA_10_T); + sc->mii_inst), MII_MEDIA_10_T); PRINT("HomePNA1"); } return; } - if (sc->mii_capabilities & BMSR_10THDX) { + if ((sc->mii_capabilities & BMSR_10THDX) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), MII_MEDIA_10_T); PRINT("10baseT"); } - if (sc->mii_capabilities & BMSR_10TFDX) { + if ((sc->mii_capabilities & BMSR_10TFDX) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), MII_MEDIA_10_T_FDX); PRINT("10baseT-FDX"); } - if (sc->mii_capabilities & BMSR_100TXHDX) { + if ((sc->mii_capabilities & BMSR_100TXHDX) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), MII_MEDIA_100_TX); PRINT("100baseTX"); } - if (sc->mii_capabilities & BMSR_100TXFDX) { + if ((sc->mii_capabilities & BMSR_100TXFDX) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), MII_MEDIA_100_TX_FDX); PRINT("100baseTX-FDX"); } - if (sc->mii_capabilities & BMSR_100T4) { + if ((sc->mii_capabilities & BMSR_100T4) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), MII_MEDIA_100_T4); PRINT("100baseT4"); } - if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { + if ((sc->mii_extcapabilities & EXTSR_MEDIAMASK) != 0) { /* * XXX Right now only handle 1000SX and 1000TX. Need - * XXX to handle 1000LX and 1000CX some how. + * XXX to handle 1000LX and 1000CX somehow. */ - if (sc->mii_extcapabilities & EXTSR_1000XHDX) { + if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_IS_1000X; ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, sc->mii_inst), MII_MEDIA_1000_X); PRINT("1000baseSX"); } - if (sc->mii_extcapabilities & EXTSR_1000XFDX) { + if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_IS_1000X; ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, @@ -382,7 +379,7 @@ mii_phy_add_media(struct mii_softc *sc) * * All 1000baseT PHYs have a 1000baseT control register. */ - if (sc->mii_extcapabilities & EXTSR_1000THDX) { + if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_HAVE_GTCR; mii->mii_media.ifm_mask |= IFM_ETH_MASTER; @@ -390,7 +387,7 @@ mii_phy_add_media(struct mii_softc *sc) sc->mii_inst), MII_MEDIA_1000_T); PRINT("1000baseT"); } - if (sc->mii_extcapabilities & EXTSR_1000TFDX) { + if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_HAVE_GTCR; mii->mii_media.ifm_mask |= IFM_ETH_MASTER; @@ -400,7 +397,7 @@ mii_phy_add_media(struct mii_softc *sc) } } - if (sc->mii_capabilities & BMSR_ANEG) { + if ((sc->mii_capabilities & BMSR_ANEG) != 0) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA); /* intentionally invalid index */ PRINT("auto"); @@ -418,8 +415,7 @@ mii_phy_detach(device_t dev) mii_phy_down(sc); sc->mii_dev = NULL; LIST_REMOVE(sc, mii_list); - - return(0); + return (0); } const struct mii_phydesc * @@ -452,6 +448,5 @@ mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv) device_set_desc(dev, mpd->mpd_name); return (mrv); } - return (ENXIO); } diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index e0ea555..34c5f94 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -81,6 +81,7 @@ oui xxINTEL 0x00f800 Intel oui xxALTIMA 0x000895 Altima Communications oui xxBROADCOM 0x000818 Broadcom Corporation oui xxBROADCOM_ALT1 0x0050ef Broadcom Corporation +oui xxBROADCOM_ALT2 0x00d897 Broadcom Corporation oui xxICS 0x00057d Integrated Circuit Systems oui xxSEEQ 0x0005be Seeq oui xxSIS 0x000760 Silicon Integrated Systems @@ -153,6 +154,7 @@ model xxBROADCOM_ALT1 BCM5784 0x003a BCM5784 10/100/1000baseTX PHY model xxBROADCOM_ALT1 BCM5709C 0x003c BCM5709C 10/100/1000baseTX PHY model xxBROADCOM_ALT1 BCM5761 0x003d BCM5761 10/100/1000baseTX PHY model xxBROADCOM_ALT1 BCM5709S 0x003f BCM5709S 1000/2500baseSX PHY +model xxBROADCOM_ALT2 BCM5717C 0x0020 BCM5717C 10/100/1000baseTX PHY model BROADCOM2 BCM5906 0x0004 BCM5906 10/100baseTX PHY /* Cicada Semiconductor PHYs (now owned by Vitesse?) */ diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 15a3f3f..6783cf5 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -148,7 +148,7 @@ typedef struct mii_softc mii_softc_t; /* * Special `locators' passed to mii_attach(). If one of these is not * an `any' value, we look for *that* PHY and configure it. If both - * are not `any', that is an error, and mii_attach() will panic. + * are not `any', that is an error, and mii_attach() will fail. */ #define MII_OFFSET_ANY -1 #define MII_PHY_ANY -1 diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 8887fc1..495bd82 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -88,7 +88,7 @@ static void usb_init_endpoint(struct usb_device *, uint8_t, struct usb_endpoint *); static void usb_unconfigure(struct usb_device *, uint8_t); static void usb_detach_device_sub(struct usb_device *, device_t *, - uint8_t); + char **, uint8_t); static uint8_t usb_probe_and_attach_sub(struct usb_device *, struct usb_attach_arg *); static void usb_init_attach_arg(struct usb_device *, @@ -1035,9 +1035,10 @@ usb_reset_iface_endpoints(struct usb_device *udev, uint8_t iface_index) *------------------------------------------------------------------------*/ static void usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, - uint8_t flag) + char **ppnpinfo, uint8_t flag) { device_t dev; + char *pnpinfo; int err; dev = *ppdev; @@ -1069,11 +1070,17 @@ usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, goto error; } } + + pnpinfo = *ppnpinfo; + if (pnpinfo != NULL) { + *ppnpinfo = NULL; + free(pnpinfo, M_USBDEV); + } return; error: /* Detach is not allowed to fail in the USB world */ - panic("A USB driver would not detach\n"); + panic("usb_detach_device_sub: A USB driver would not detach\n"); } /*------------------------------------------------------------------------* @@ -1122,7 +1129,8 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index, /* looks like the end of the USB interfaces */ break; } - usb_detach_device_sub(udev, &iface->subdev, flag); + usb_detach_device_sub(udev, &iface->subdev, + &iface->pnpinfo, flag); } } @@ -2714,3 +2722,37 @@ usbd_enum_is_locked(struct usb_device *udev) { return (sx_xlocked(&udev->enum_sx)); } + +/* + * The following function is used to set the per-interface specific + * plug and play information. The string referred to by the pnpinfo + * argument can safely be freed after calling this function. The + * pnpinfo of an interface will be reset at device detach or when + * passing a NULL argument to this function. This function + * returns zero on success, else a USB_ERR_XXX failure code. + */ + +usb_error_t +usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpinfo) +{ + struct usb_interface *iface; + + iface = usbd_get_iface(udev, iface_index); + if (iface == NULL) + return (USB_ERR_INVAL); + + if (iface->pnpinfo != NULL) { + free(iface->pnpinfo, M_USBDEV); + iface->pnpinfo = NULL; + } + + if (pnpinfo == NULL || pnpinfo[0] == 0) + return (0); /* success */ + + iface->pnpinfo = strdup(pnpinfo, M_USBDEV); + if (iface->pnpinfo == NULL) + return (USB_ERR_NOMEM); + + return (0); /* success */ +} + diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index afeadaa..b2870a3 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -1330,7 +1330,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, "devclass=0x%02x devsubclass=0x%02x " "sernum=\"%s\" " "release=0x%04x " - "intclass=0x%02x intsubclass=0x%02x", + "intclass=0x%02x intsubclass=0x%02x" "%s%s", UGETW(res.udev->ddesc.idVendor), UGETW(res.udev->ddesc.idProduct), res.udev->ddesc.bDeviceClass, @@ -1338,7 +1338,9 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, usb_get_serial(res.udev), UGETW(res.udev->ddesc.bcdDevice), iface->idesc->bInterfaceClass, - iface->idesc->bInterfaceSubClass); + iface->idesc->bInterfaceSubClass, + iface->pnpinfo ? " " : "", + iface->pnpinfo ? iface->pnpinfo : ""); } else { if (buflen) { buf[0] = '\0'; diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 1c2d412..6d4a911 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -171,6 +171,7 @@ struct usb_interface { struct usb_host_interface *cur_altsetting; struct usb_device *linux_udev; void *bsd_priv_sc; /* device specific information */ + char *pnpinfo; /* additional PnP-info for this interface */ uint8_t num_altsetting; /* number of alternate settings */ uint8_t bsd_iface_index; }; @@ -444,6 +445,8 @@ enum usb_hc_mode usbd_get_mode(struct usb_device *udev); enum usb_dev_speed usbd_get_speed(struct usb_device *udev); void device_set_usb_desc(device_t dev); void usb_pause_mtx(struct mtx *mtx, int _ticks); +usb_error_t usbd_set_pnpinfo(struct usb_device *udev, + uint8_t iface_index, const char *pnpinfo); const struct usb_device_id *usbd_lookup_id_by_info( const struct usb_device_id *id, usb_size_t sizeof_id, diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 72087f5..458149d 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -2827,8 +2827,11 @@ xbb_detach(device_t dev) DPRINTF("\n"); - taskqueue_free(xbb->io_taskqueue); - devstat_remove_entry(xbb->xbb_stats); + if (xbb->io_taskqueue != NULL) + taskqueue_free(xbb->io_taskqueue); + + if (xbb->xbb_stats != NULL) + devstat_remove_entry(xbb->xbb_stats); xbb_close_backend(xbb); xbb_free_communication_mem(xbb); diff --git a/sys/fs/nfs/nfsclstate.h b/sys/fs/nfs/nfsclstate.h index 72d8eeb..bb46220 100644 --- a/sys/fs/nfs/nfsclstate.h +++ b/sys/fs/nfs/nfsclstate.h @@ -118,6 +118,7 @@ struct nfscldeleg { #define NFSCLDL_NEEDRECLAIM 0x08 #define NFSCLDL_ZAPPED 0x10 #define NFSCLDL_MODTIMESET 0x20 +#define NFSCLDL_DELEGRET 0x40 /* * MALLOC'd to the correct length to accommodate the file handle. diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 8ca1c43..430b494 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -236,6 +236,15 @@ ncl_reclaim(struct vop_reclaim_args *ap) if (prtactive && vrefcnt(vp) != 0) vprint("ncl_reclaim: pushing active", vp); + if (NFS_ISV4(vp) && vp->v_type == VREG) + /* + * Since mmap()'d files do I/O after VOP_CLOSE(), the NFSv4 + * Close operations are delayed until ncl_inactive(). + * However, since VOP_INACTIVE() is not guaranteed to be + * called, we need to do it again here. + */ + (void) nfsrpc_close(vp, 1, ap->a_td); + /* * If the NLM is running, give it a chance to abort pending * locks. diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index b6fad20..2281f32 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -929,8 +929,10 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len, ldp = dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len); /* Just sanity check for correct type of delegation */ - if (dp != NULL && ((dp->nfsdl_flags & NFSCLDL_RECALL) || - (type == F_WRLCK && !(dp->nfsdl_flags & NFSCLDL_WRITE)))) + if (dp != NULL && ((dp->nfsdl_flags & + (NFSCLDL_RECALL | NFSCLDL_DELEGRET)) != 0 || + (type == F_WRLCK && + (dp->nfsdl_flags & NFSCLDL_WRITE) == 0))) dp = NULL; } if (dp != NULL) { @@ -2495,8 +2497,8 @@ tryagain: if (dp->nfsdl_rwlock.nfslock_usecnt == 0 && dp->nfsdl_rwlock.nfslock_lock == 0 && dp->nfsdl_timestamp < NFSD_MONOSEC && - !(dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_ZAPPED | - NFSCLDL_NEEDRECLAIM))) { + (dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_ZAPPED | + NFSCLDL_NEEDRECLAIM | NFSCLDL_DELEGRET)) == 0) { clearok = 1; LIST_FOREACH(owp, &dp->nfsdl_owner, nfsow_list) { op = LIST_FIRST(&owp->nfsow_open); @@ -3086,7 +3088,8 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p) if (clp != NULL) { dp = nfscl_finddeleg(clp, nfhp->nfh_fh, nfhp->nfh_len); - if (dp != NULL) { + if (dp != NULL && (dp->nfsdl_flags & + NFSCLDL_DELEGRET) == 0) { dp->nfsdl_flags |= NFSCLDL_RECALL; wakeup((caddr_t)clp); @@ -3338,7 +3341,6 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, np = VTONFS(vp); } dp->nfsdl_flags &= ~NFSCLDL_MODTIMESET; - NFSINVALATTRCACHE(np); /* * Ok, if it's a write delegation, flush data to the server, so @@ -3347,21 +3349,14 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, ret = 0; NFSLOCKNODE(np); if ((dp->nfsdl_flags & NFSCLDL_WRITE) && (np->n_flag & NMODIFIED)) { -#ifdef APPLE - OSBitOrAtomic((u_int32_t)NDELEGRECALL, (UInt32 *)&np->n_flag); -#else np->n_flag |= NDELEGRECALL; -#endif NFSUNLOCKNODE(np); ret = ncl_flush(vp, MNT_WAIT, cred, p, 1, called_from_renewthread); NFSLOCKNODE(np); -#ifdef APPLE - OSBitAndAtomic((int32_t)~(NMODIFIED | NDELEGRECALL), (UInt32 *)&np->n_flag); -#else - np->n_flag &= ~(NMODIFIED | NDELEGRECALL); -#endif + np->n_flag &= ~NDELEGRECALL; } + NFSINVALATTRCACHE(np); NFSUNLOCKNODE(np); if (ret == EIO && called_from_renewthread != 0) { /* @@ -3534,8 +3529,10 @@ nfscl_totalrecall(struct nfsclclient *clp) { struct nfscldeleg *dp; - TAILQ_FOREACH(dp, &clp->nfsc_deleg, nfsdl_list) - dp->nfsdl_flags |= NFSCLDL_RECALL; + TAILQ_FOREACH(dp, &clp->nfsc_deleg, nfsdl_list) { + if ((dp->nfsdl_flags & NFSCLDL_DELEGRET) == 0) + dp->nfsdl_flags |= NFSCLDL_RECALL; + } } /* @@ -3754,8 +3751,9 @@ nfscl_mustflush(vnode_t vp) return (1); } dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len); - if (dp != NULL && (dp->nfsdl_flags & (NFSCLDL_WRITE | NFSCLDL_RECALL)) - == NFSCLDL_WRITE && + if (dp != NULL && (dp->nfsdl_flags & + (NFSCLDL_WRITE | NFSCLDL_RECALL | NFSCLDL_DELEGRET)) == + NFSCLDL_WRITE && (dp->nfsdl_sizelimit >= np->n_size || !NFSHASSTRICT3530(nmp))) { NFSUNLOCKCLSTATE(); @@ -3787,9 +3785,10 @@ nfscl_nodeleg(vnode_t vp, int writedeleg) return (1); } dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len); - if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_RECALL) == 0 && - (writedeleg == 0 || (dp->nfsdl_flags & NFSCLDL_WRITE) - == NFSCLDL_WRITE)) { + if (dp != NULL && + (dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_DELEGRET)) == 0 && + (writedeleg == 0 || (dp->nfsdl_flags & NFSCLDL_WRITE) == + NFSCLDL_WRITE)) { NFSUNLOCKCLSTATE(); return (0); } @@ -3860,6 +3859,7 @@ nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp) } } if (needsrecall && !triedrecall) { + dp->nfsdl_flags |= NFSCLDL_DELEGRET; islept = 0; while (!igotlock) { igotlock = nfsv4_lock(&clp->nfsc_lock, 1, @@ -3958,6 +3958,7 @@ nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp, } } if (needsrecall && !triedrecall) { + dp->nfsdl_flags |= NFSCLDL_DELEGRET; islept = 0; while (!igotlock) { igotlock = nfsv4_lock(&clp->nfsc_lock, 1, diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index b02c4bf..e32f397 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -494,24 +494,46 @@ nfs_open(struct vop_open_args *ap) * Now, if this Open will be doing reading, re-validate/flush the * cache, so that Close/Open coherency is maintained. */ - if ((fmode & FREAD) != 0 && - (!NFS_ISV4(vp) || nfscl_mustflush(vp) != 0)) { + mtx_lock(&np->n_mtx); + if (np->n_flag & NMODIFIED) { + mtx_unlock(&np->n_mtx); + error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); + if (error == EINTR || error == EIO) { + if (NFS_ISV4(vp)) + (void) nfsrpc_close(vp, 0, ap->a_td); + return (error); + } mtx_lock(&np->n_mtx); - if (np->n_flag & NMODIFIED) { - mtx_unlock(&np->n_mtx); - error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); - if (error == EINTR || error == EIO) { - if (NFS_ISV4(vp)) - (void) nfsrpc_close(vp, 0, ap->a_td); - return (error); - } - mtx_lock(&np->n_mtx); - np->n_attrstamp = 0; + np->n_attrstamp = 0; + if (vp->v_type == VDIR) + np->n_direofoffset = 0; + mtx_unlock(&np->n_mtx); + error = VOP_GETATTR(vp, &vattr, ap->a_cred); + if (error) { + if (NFS_ISV4(vp)) + (void) nfsrpc_close(vp, 0, ap->a_td); + return (error); + } + mtx_lock(&np->n_mtx); + np->n_mtime = vattr.va_mtime; + if (NFS_ISV4(vp)) + np->n_change = vattr.va_filerev; + } else { + mtx_unlock(&np->n_mtx); + error = VOP_GETATTR(vp, &vattr, ap->a_cred); + if (error) { + if (NFS_ISV4(vp)) + (void) nfsrpc_close(vp, 0, ap->a_td); + return (error); + } + mtx_lock(&np->n_mtx); + if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) || + NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { if (vp->v_type == VDIR) np->n_direofoffset = 0; mtx_unlock(&np->n_mtx); - error = VOP_GETATTR(vp, &vattr, ap->a_cred); - if (error) { + error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); + if (error == EINTR || error == EIO) { if (NFS_ISV4(vp)) (void) nfsrpc_close(vp, 0, ap->a_td); return (error); @@ -520,42 +542,16 @@ nfs_open(struct vop_open_args *ap) np->n_mtime = vattr.va_mtime; if (NFS_ISV4(vp)) np->n_change = vattr.va_filerev; - mtx_unlock(&np->n_mtx); - } else { - mtx_unlock(&np->n_mtx); - error = VOP_GETATTR(vp, &vattr, ap->a_cred); - if (error) { - if (NFS_ISV4(vp)) - (void) nfsrpc_close(vp, 0, ap->a_td); - return (error); - } - mtx_lock(&np->n_mtx); - if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) || - NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { - if (vp->v_type == VDIR) - np->n_direofoffset = 0; - mtx_unlock(&np->n_mtx); - error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); - if (error == EINTR || error == EIO) { - if (NFS_ISV4(vp)) - (void) nfsrpc_close(vp, 0, - ap->a_td); - return (error); - } - mtx_lock(&np->n_mtx); - np->n_mtime = vattr.va_mtime; - if (NFS_ISV4(vp)) - np->n_change = vattr.va_filerev; - } - mtx_unlock(&np->n_mtx); } } /* * If the object has >= 1 O_DIRECT active opens, we disable caching. */ - if (newnfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) { + if (newnfs_directio_enable && (fmode & O_DIRECT) && + (vp->v_type == VREG)) { if (np->n_directio_opens == 0) { + mtx_unlock(&np->n_mtx); error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); if (error) { if (NFS_ISV4(vp)) @@ -564,12 +560,10 @@ nfs_open(struct vop_open_args *ap) } mtx_lock(&np->n_mtx); np->n_flag |= NNONCACHE; - } else { - mtx_lock(&np->n_mtx); } np->n_directio_opens++; - mtx_unlock(&np->n_mtx); } + mtx_unlock(&np->n_mtx); vnode_create_vobject(vp, vattr.va_size, ap->a_td); return (0); } diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c index 60bc31f..2397d80 100644 --- a/sys/i386/acpica/acpi_wakeup.c +++ b/sys/i386/acpica/acpi_wakeup.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/cpufunc.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/segments.h> #include <contrib/dev/acpica/include/acpi.h> diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c index 5013c21..f153696 100644 --- a/sys/i386/acpica/madt.c +++ b/sys/i386/acpica/madt.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index cbe3871..100ce90 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -39,7 +39,7 @@ #include "opt_smp.h" #include <machine/asmacros.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include "assym.s" diff --git a/sys/i386/i386/dump_machdep.c b/sys/i386/i386/dump_machdep.c deleted file mode 100644 index d0c6ba7..0000000 --- a/sys/i386/i386/dump_machdep.c +++ /dev/null @@ -1,363 +0,0 @@ -/*- - * Copyright (c) 2002 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/cons.h> -#include <sys/sysctl.h> -#include <sys/kernel.h> -#include <sys/kerneldump.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <machine/elf.h> -#include <machine/md_var.h> - -CTASSERT(sizeof(struct kerneldumpheader) == 512); - -int do_minidump = 1; -TUNABLE_INT("debug.minidump", &do_minidump); -SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RW, &do_minidump, 0, - "Enable mini crash dumps"); - -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - -#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) -#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1)) - -struct md_pa { - vm_paddr_t md_start; - vm_paddr_t md_size; -}; - -typedef int callback_t(struct md_pa *, int, void *); - -static struct kerneldumpheader kdh; -static off_t dumplo, fileofs; - -/* Handle buffered writes. */ -static char buffer[DEV_BSIZE]; -static size_t fragsz; - -/* 20 phys_avail entry pairs correspond to 10 md_pa's */ -static struct md_pa dump_map[10]; - -static void -md_pa_init(void) -{ - int n, idx; - - bzero(dump_map, sizeof(dump_map)); - for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) { - idx = n * 2; - if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0) - break; - dump_map[n].md_start = dump_avail[idx]; - dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx]; - } -} - -static struct md_pa * -md_pa_first(void) -{ - - return (&dump_map[0]); -} - -static struct md_pa * -md_pa_next(struct md_pa *mdp) -{ - - mdp++; - if (mdp->md_size == 0) - mdp = NULL; - return (mdp); -} - -static int -buf_write(struct dumperinfo *di, char *ptr, size_t sz) -{ - size_t len; - int error; - - while (sz) { - len = DEV_BSIZE - fragsz; - if (len > sz) - len = sz; - bcopy(ptr, buffer + fragsz, len); - fragsz += len; - ptr += len; - sz -= len; - if (fragsz == DEV_BSIZE) { - error = dump_write(di, buffer, 0, dumplo, - DEV_BSIZE); - if (error) - return error; - dumplo += DEV_BSIZE; - fragsz = 0; - } - } - - return (0); -} - -static int -buf_flush(struct dumperinfo *di) -{ - int error; - - if (fragsz == 0) - return (0); - - error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE); - dumplo += DEV_BSIZE; - fragsz = 0; - return (error); -} - -#define PG2MB(pgs) ((pgs + (1 << 8) - 1) >> 8) - -static int -cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) -{ - struct dumperinfo *di = (struct dumperinfo*)arg; - vm_paddr_t a, pa; - void *va; - uint64_t pgs; - size_t counter, sz, chunk; - int i, c, error, twiddle; - u_int maxdumppgs; - - error = 0; /* catch case in which chunk size is 0 */ - counter = 0; /* Update twiddle every 16MB */ - twiddle = 0; - va = 0; - pgs = mdp->md_size / PAGE_SIZE; - pa = mdp->md_start; - maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS); - if (maxdumppgs == 0) /* seatbelt */ - maxdumppgs = 1; - - printf(" chunk %d: %lldMB (%lld pages)", seqnr, PG2MB(pgs), pgs); - - while (pgs) { - chunk = pgs; - if (chunk > maxdumppgs) - chunk = maxdumppgs; - sz = chunk << PAGE_SHIFT; - counter += sz; - if (counter >> 24) { - printf(" %lld", PG2MB(pgs)); - counter &= (1<<24) - 1; - } - for (i = 0; i < chunk; i++) { - a = pa + i * PAGE_SIZE; - va = pmap_kenter_temporary(trunc_page(a), i); - } - error = dump_write(di, va, 0, dumplo, sz); - if (error) - break; - dumplo += sz; - pgs -= chunk; - pa += sz; - - /* Check for user abort. */ - c = cncheckc(); - if (c == 0x03) - return (ECANCELED); - if (c != -1) - printf(" (CTRL-C to abort) "); - } - printf(" ... %s\n", (error) ? "fail" : "ok"); - return (error); -} - -static int -cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg) -{ - struct dumperinfo *di = (struct dumperinfo*)arg; - Elf_Phdr phdr; - uint64_t size; - int error; - - size = mdp->md_size; - bzero(&phdr, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_flags = PF_R; /* XXX */ - phdr.p_offset = fileofs; - phdr.p_vaddr = mdp->md_start; - phdr.p_paddr = mdp->md_start; - phdr.p_filesz = size; - phdr.p_memsz = size; - phdr.p_align = PAGE_SIZE; - - error = buf_write(di, (char*)&phdr, sizeof(phdr)); - fileofs += phdr.p_filesz; - return (error); -} - -static int -cb_size(struct md_pa *mdp, int seqnr, void *arg) -{ - uint64_t *sz = (uint64_t*)arg; - - *sz += (uint64_t)mdp->md_size; - return (0); -} - -static int -foreach_chunk(callback_t cb, void *arg) -{ - struct md_pa *mdp; - int error, seqnr; - - seqnr = 0; - mdp = md_pa_first(); - while (mdp != NULL) { - error = (*cb)(mdp, seqnr++, arg); - if (error) - return (-error); - mdp = md_pa_next(mdp); - } - return (seqnr); -} - -void -dumpsys(struct dumperinfo *di) -{ - Elf_Ehdr ehdr; - uint64_t dumpsize; - off_t hdrgap; - size_t hdrsz; - int error; - - if (do_minidump) { - minidumpsys(di); - return; - } - bzero(&ehdr, sizeof(ehdr)); - ehdr.e_ident[EI_MAG0] = ELFMAG0; - ehdr.e_ident[EI_MAG1] = ELFMAG1; - ehdr.e_ident[EI_MAG2] = ELFMAG2; - ehdr.e_ident[EI_MAG3] = ELFMAG3; - ehdr.e_ident[EI_CLASS] = ELF_CLASS; -#if BYTE_ORDER == LITTLE_ENDIAN - ehdr.e_ident[EI_DATA] = ELFDATA2LSB; -#else - ehdr.e_ident[EI_DATA] = ELFDATA2MSB; -#endif - ehdr.e_ident[EI_VERSION] = EV_CURRENT; - ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */ - ehdr.e_type = ET_CORE; - ehdr.e_machine = EM_386; - ehdr.e_phoff = sizeof(ehdr); - ehdr.e_flags = 0; - ehdr.e_ehsize = sizeof(ehdr); - ehdr.e_phentsize = sizeof(Elf_Phdr); - ehdr.e_shentsize = sizeof(Elf_Shdr); - - md_pa_init(); - - /* Calculate dump size. */ - dumpsize = 0L; - ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize); - hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; - fileofs = MD_ALIGN(hdrsz); - dumpsize += fileofs; - hdrgap = fileofs - DEV_ALIGN(hdrsz); - - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) { - error = ENOSPC; - goto fail; - } - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= sizeof(kdh) * 2; - - mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_I386_VERSION, dumpsize, di->blocksize); - - printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20, - ehdr.e_phnum); - - /* Dump leader */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); - if (error) - goto fail; - dumplo += sizeof(kdh); - - /* Dump ELF header */ - error = buf_write(di, (char*)&ehdr, sizeof(ehdr)); - if (error) - goto fail; - - /* Dump program headers */ - error = foreach_chunk(cb_dumphdr, di); - if (error < 0) - goto fail; - buf_flush(di); - - /* - * All headers are written using blocked I/O, so we know the - * current offset is (still) block aligned. Skip the alignement - * in the file to have the segment contents aligned at page - * boundary. We cannot use MD_ALIGN on dumplo, because we don't - * care and may very well be unaligned within the dump device. - */ - dumplo += hdrgap; - - /* Dump memory chunks (updates dumplo) */ - error = foreach_chunk(cb_dumpdata, di); - if (error < 0) - goto fail; - - /* Dump trailer */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); - if (error) - goto fail; - - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); - printf("\nDump complete\n"); - return; - - fail: - if (error < 0) - error = -error; - - if (error == ECANCELED) - printf("\nDump aborted\n"); - else if (error == ENOSPC) - printf("\nDump failed. Partition too small.\n"); - else - printf("\n** DUMP FAILED (ERROR %d) **\n", error); -} diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index fae7833..523b194 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$"); #include <nfsclient/nfs.h> #include <nfsclient/nfsdiskless.h> #ifdef DEV_APIC -#include <machine/apicreg.h> +#include <x86/apicreg.h> #endif #include <machine/cpu.h> #include <machine/pcb.h> diff --git a/sys/i386/i386/intr_machdep.c b/sys/i386/i386/intr_machdep.c index 35179fa..77b8004 100644 --- a/sys/i386/i386/intr_machdep.c +++ b/sys/i386/i386/intr_machdep.c @@ -424,7 +424,7 @@ intr_next_cpu(void) /* Leave all interrupts on the BSP during boot. */ if (!assign_cpu) - return (cpu_apic_ids[0]); + return (PCPU_GET(apic_id)); mtx_lock_spin(&icu_lock); apic_id = cpu_apic_ids[current_cpu]; diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 5c0b7ff..255bec6 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -115,7 +115,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/cputypes.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/metadata.h> #include <machine/pc/bios.h> diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index c69f6f9..b99c19c 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -72,10 +72,10 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_kern.h> #include <vm/vm_extern.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/clock.h> #include <machine/cputypes.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/mp_watchdog.h> #include <machine/pcb.h> diff --git a/sys/i386/i386/mp_watchdog.c b/sys/i386/i386/mp_watchdog.c index 1803270..5cbd649 100644 --- a/sys/i386/i386/mp_watchdog.c +++ b/sys/i386/i386/mp_watchdog.c @@ -44,7 +44,7 @@ #include <sys/systm.h> #include <machine/smp.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/apicvar.h> #include <machine/mp_watchdog.h> diff --git a/sys/i386/i386/mpboot.s b/sys/i386/i386/mpboot.s index 8870858..a3ef283 100644 --- a/sys/i386/i386/mpboot.s +++ b/sys/i386/i386/mpboot.s @@ -32,7 +32,7 @@ #include "opt_pmap.h" #include <machine/asmacros.h> /* miscellaneous asm macros */ -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/specialreg.h> #include "assym.s" diff --git a/sys/i386/i386/mptable_pci.c b/sys/i386/i386/mptable_pci.c deleted file mode 100644 index 47a666d..0000000 --- a/sys/i386/i386/mptable_pci.c +++ /dev/null @@ -1,177 +0,0 @@ -/*- - * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Host to PCI and PCI to PCI bridge drivers that use the MP Table to route - * interrupts from PCI devices to I/O APICs. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcib_private.h> -#include <machine/legacyvar.h> -#include <machine/mptable.h> -#include <machine/pci_cfgreg.h> - -#include "pcib_if.h" - -/* Host to PCI bridge driver. */ - -static int -mptable_hostb_probe(device_t dev) -{ - - if (pci_cfgregopen() == 0) - return (ENXIO); - if (mptable_pci_probe_table(pcib_get_bus(dev)) != 0) - return (ENXIO); - device_set_desc(dev, "MPTable Host-PCI bridge"); - return (0); -} - -static int -mptable_hostb_attach(device_t dev) -{ - - device_add_child(dev, "pci", pcib_get_bus(dev)); - return (bus_generic_attach(dev)); -} - -/* Pass MSI requests up to the nexus. */ -static int -mptable_hostb_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, - int *irqs) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount, - irqs)); -} - -static int -mptable_hostb_alloc_msix(device_t pcib, device_t dev, int *irq) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); -} - -static int -mptable_hostb_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, - uint32_t *data) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); -} - -static device_method_t mptable_hostb_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mptable_hostb_probe), - DEVMETHOD(device_attach, mptable_hostb_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar), - DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, legacy_pcib_maxslots), - DEVMETHOD(pcib_read_config, legacy_pcib_read_config), - DEVMETHOD(pcib_write_config, legacy_pcib_write_config), - DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt), - DEVMETHOD(pcib_alloc_msi, mptable_hostb_alloc_msi), - DEVMETHOD(pcib_release_msi, pcib_release_msi), - DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix), - DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, mptable_hostb_map_msi), - - { 0, 0 } -}; - -static devclass_t hostb_devclass; - -DEFINE_CLASS_0(pcib, mptable_hostb_driver, mptable_hostb_methods, 1); -DRIVER_MODULE(mptable_pcib, legacy, mptable_hostb_driver, hostb_devclass, 0, 0); - -/* PCI to PCI bridge driver. */ - -static int -mptable_pcib_probe(device_t dev) -{ - int bus; - - if ((pci_get_class(dev) != PCIC_BRIDGE) || - (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) - return (ENXIO); - bus = pci_read_config(dev, PCIR_SECBUS_1, 1); - if (bus == 0) - return (ENXIO); - if (mptable_pci_probe_table(bus) != 0) - return (ENXIO); - device_set_desc(dev, "MPTable PCI-PCI bridge"); - return (-1000); -} - -static device_method_t mptable_pcib_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mptable_pcib_probe), - - /* pcib interface */ - DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt), - - {0, 0} -}; - -static devclass_t pcib_devclass; - -DEFINE_CLASS_1(pcib, mptable_pcib_driver, mptable_pcib_pci_methods, - sizeof(struct pcib_softc), pcib_driver); -DRIVER_MODULE(mptable_pcib, pci, mptable_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 7b7bdc4..dc10559 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -86,7 +86,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/pcb.h> #ifdef SMP diff --git a/sys/i386/include/apicreg.h b/sys/i386/include/apicreg.h deleted file mode 100644 index fee629b..0000000 --- a/sys/i386/include/apicreg.h +++ /dev/null @@ -1,445 +0,0 @@ -/*- - * Copyright (c) 1996, by Peter Wemm and Steve Passe - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. The name of the developer may NOT be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_APICREG_H_ -#define _MACHINE_APICREG_H_ - -/* - * Local && I/O APIC definitions. - */ - -/* - * Pentium P54C+ Built-in APIC - * (Advanced programmable Interrupt Controller) - * - * Base Address of Built-in APIC in memory location - * is 0xfee00000. - * - * Map of APIC Registers: - * - * Offset (hex) Description Read/Write state - * 000 Reserved - * 010 Reserved - * 020 ID Local APIC ID R/W - * 030 VER Local APIC Version R - * 040 Reserved - * 050 Reserved - * 060 Reserved - * 070 Reserved - * 080 Task Priority Register R/W - * 090 Arbitration Priority Register R - * 0A0 Processor Priority Register R - * 0B0 EOI Register W - * 0C0 RRR Remote read R - * 0D0 Logical Destination R/W - * 0E0 Destination Format Register 0..27 R; 28..31 R/W - * 0F0 SVR Spurious Interrupt Vector Reg. 0..3 R; 4..9 R/W - * 100 ISR 000-031 R - * 110 ISR 032-063 R - * 120 ISR 064-095 R - * 130 ISR 095-128 R - * 140 ISR 128-159 R - * 150 ISR 160-191 R - * 160 ISR 192-223 R - * 170 ISR 224-255 R - * 180 TMR 000-031 R - * 190 TMR 032-063 R - * 1A0 TMR 064-095 R - * 1B0 TMR 095-128 R - * 1C0 TMR 128-159 R - * 1D0 TMR 160-191 R - * 1E0 TMR 192-223 R - * 1F0 TMR 224-255 R - * 200 IRR 000-031 R - * 210 IRR 032-063 R - * 220 IRR 064-095 R - * 230 IRR 095-128 R - * 240 IRR 128-159 R - * 250 IRR 160-191 R - * 260 IRR 192-223 R - * 270 IRR 224-255 R - * 280 Error Status Register R - * 290 Reserved - * 2A0 Reserved - * 2B0 Reserved - * 2C0 Reserved - * 2D0 Reserved - * 2E0 Reserved - * 2F0 Local Vector Table (CMCI) R/W - * 300 ICR_LOW Interrupt Command Reg. (0-31) R/W - * 310 ICR_HI Interrupt Command Reg. (32-63) R/W - * 320 Local Vector Table (Timer) R/W - * 330 Local Vector Table (Thermal) R/W (PIV+) - * 340 Local Vector Table (Performance) R/W (P6+) - * 350 LVT1 Local Vector Table (LINT0) R/W - * 360 LVT2 Local Vector Table (LINT1) R/W - * 370 LVT3 Local Vector Table (ERROR) R/W - * 380 Initial Count Reg. for Timer R/W - * 390 Current Count of Timer R - * 3A0 Reserved - * 3B0 Reserved - * 3C0 Reserved - * 3D0 Reserved - * 3E0 Timer Divide Configuration Reg. R/W - * 3F0 Reserved - */ - - -/****************************************************************************** - * global defines, etc. - */ - - -/****************************************************************************** - * LOCAL APIC structure - */ - -#ifndef LOCORE -#include <sys/types.h> - -#define PAD3 int : 32; int : 32; int : 32 -#define PAD4 int : 32; int : 32; int : 32; int : 32 - -struct LAPIC { - /* reserved */ PAD4; - /* reserved */ PAD4; - u_int32_t id; PAD3; - u_int32_t version; PAD3; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - u_int32_t tpr; PAD3; - u_int32_t apr; PAD3; - u_int32_t ppr; PAD3; - u_int32_t eoi; PAD3; - /* reserved */ PAD4; - u_int32_t ldr; PAD3; - u_int32_t dfr; PAD3; - u_int32_t svr; PAD3; - u_int32_t isr0; PAD3; - u_int32_t isr1; PAD3; - u_int32_t isr2; PAD3; - u_int32_t isr3; PAD3; - u_int32_t isr4; PAD3; - u_int32_t isr5; PAD3; - u_int32_t isr6; PAD3; - u_int32_t isr7; PAD3; - u_int32_t tmr0; PAD3; - u_int32_t tmr1; PAD3; - u_int32_t tmr2; PAD3; - u_int32_t tmr3; PAD3; - u_int32_t tmr4; PAD3; - u_int32_t tmr5; PAD3; - u_int32_t tmr6; PAD3; - u_int32_t tmr7; PAD3; - u_int32_t irr0; PAD3; - u_int32_t irr1; PAD3; - u_int32_t irr2; PAD3; - u_int32_t irr3; PAD3; - u_int32_t irr4; PAD3; - u_int32_t irr5; PAD3; - u_int32_t irr6; PAD3; - u_int32_t irr7; PAD3; - u_int32_t esr; PAD3; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - u_int32_t lvt_cmci; PAD3; - u_int32_t icr_lo; PAD3; - u_int32_t icr_hi; PAD3; - u_int32_t lvt_timer; PAD3; - u_int32_t lvt_thermal; PAD3; - u_int32_t lvt_pcint; PAD3; - u_int32_t lvt_lint0; PAD3; - u_int32_t lvt_lint1; PAD3; - u_int32_t lvt_error; PAD3; - u_int32_t icr_timer; PAD3; - u_int32_t ccr_timer; PAD3; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - /* reserved */ PAD4; - u_int32_t dcr_timer; PAD3; - /* reserved */ PAD4; -}; - -typedef struct LAPIC lapic_t; - -/****************************************************************************** - * I/O APIC structure - */ - -struct IOAPIC { - u_int32_t ioregsel; PAD3; - u_int32_t iowin; PAD3; -}; - -typedef struct IOAPIC ioapic_t; - -#undef PAD4 -#undef PAD3 - -#endif /* !LOCORE */ - - -/****************************************************************************** - * various code 'logical' values - */ - -/****************************************************************************** - * LOCAL APIC defines - */ - -/* default physical locations of LOCAL (CPU) APICs */ -#define DEFAULT_APIC_BASE 0xfee00000 - -/* constants relating to APIC ID registers */ -#define APIC_ID_MASK 0xff000000 -#define APIC_ID_SHIFT 24 -#define APIC_ID_CLUSTER 0xf0 -#define APIC_ID_CLUSTER_ID 0x0f -#define APIC_MAX_CLUSTER 0xe -#define APIC_MAX_INTRACLUSTER_ID 3 -#define APIC_ID_CLUSTER_SHIFT 4 - -/* fields in VER */ -#define APIC_VER_VERSION 0x000000ff -#define APIC_VER_MAXLVT 0x00ff0000 -#define MAXLVTSHIFT 16 -#define APIC_VER_EOI_SUPPRESSION 0x01000000 - -/* fields in LDR */ -#define APIC_LDR_RESERVED 0x00ffffff - -/* fields in DFR */ -#define APIC_DFR_RESERVED 0x0fffffff -#define APIC_DFR_MODEL_MASK 0xf0000000 -#define APIC_DFR_MODEL_FLAT 0xf0000000 -#define APIC_DFR_MODEL_CLUSTER 0x00000000 - -/* fields in SVR */ -#define APIC_SVR_VECTOR 0x000000ff -#define APIC_SVR_VEC_PROG 0x000000f0 -#define APIC_SVR_VEC_FIX 0x0000000f -#define APIC_SVR_ENABLE 0x00000100 -# define APIC_SVR_SWDIS 0x00000000 -# define APIC_SVR_SWEN 0x00000100 -#define APIC_SVR_FOCUS 0x00000200 -# define APIC_SVR_FEN 0x00000000 -# define APIC_SVR_FDIS 0x00000200 -#define APIC_SVR_EOI_SUPPRESSION 0x00001000 - -/* fields in TPR */ -#define APIC_TPR_PRIO 0x000000ff -# define APIC_TPR_INT 0x000000f0 -# define APIC_TPR_SUB 0x0000000f - -/* fields in ESR */ -#define APIC_ESR_SEND_CS_ERROR 0x00000001 -#define APIC_ESR_RECEIVE_CS_ERROR 0x00000002 -#define APIC_ESR_SEND_ACCEPT 0x00000004 -#define APIC_ESR_RECEIVE_ACCEPT 0x00000008 -#define APIC_ESR_SEND_ILLEGAL_VECTOR 0x00000020 -#define APIC_ESR_RECEIVE_ILLEGAL_VECTOR 0x00000040 -#define APIC_ESR_ILLEGAL_REGISTER 0x00000080 - -/* fields in ICR_LOW */ -#define APIC_VECTOR_MASK 0x000000ff - -#define APIC_DELMODE_MASK 0x00000700 -# define APIC_DELMODE_FIXED 0x00000000 -# define APIC_DELMODE_LOWPRIO 0x00000100 -# define APIC_DELMODE_SMI 0x00000200 -# define APIC_DELMODE_RR 0x00000300 -# define APIC_DELMODE_NMI 0x00000400 -# define APIC_DELMODE_INIT 0x00000500 -# define APIC_DELMODE_STARTUP 0x00000600 -# define APIC_DELMODE_RESV 0x00000700 - -#define APIC_DESTMODE_MASK 0x00000800 -# define APIC_DESTMODE_PHY 0x00000000 -# define APIC_DESTMODE_LOG 0x00000800 - -#define APIC_DELSTAT_MASK 0x00001000 -# define APIC_DELSTAT_IDLE 0x00000000 -# define APIC_DELSTAT_PEND 0x00001000 - -#define APIC_RESV1_MASK 0x00002000 - -#define APIC_LEVEL_MASK 0x00004000 -# define APIC_LEVEL_DEASSERT 0x00000000 -# define APIC_LEVEL_ASSERT 0x00004000 - -#define APIC_TRIGMOD_MASK 0x00008000 -# define APIC_TRIGMOD_EDGE 0x00000000 -# define APIC_TRIGMOD_LEVEL 0x00008000 - -#define APIC_RRSTAT_MASK 0x00030000 -# define APIC_RRSTAT_INVALID 0x00000000 -# define APIC_RRSTAT_INPROG 0x00010000 -# define APIC_RRSTAT_VALID 0x00020000 -# define APIC_RRSTAT_RESV 0x00030000 - -#define APIC_DEST_MASK 0x000c0000 -# define APIC_DEST_DESTFLD 0x00000000 -# define APIC_DEST_SELF 0x00040000 -# define APIC_DEST_ALLISELF 0x00080000 -# define APIC_DEST_ALLESELF 0x000c0000 - -#define APIC_RESV2_MASK 0xfff00000 - -#define APIC_ICRLO_RESV_MASK (APIC_RESV1_MASK | APIC_RESV2_MASK) - -/* fields in LVT1/2 */ -#define APIC_LVT_VECTOR 0x000000ff -#define APIC_LVT_DM 0x00000700 -# define APIC_LVT_DM_FIXED 0x00000000 -# define APIC_LVT_DM_SMI 0x00000200 -# define APIC_LVT_DM_NMI 0x00000400 -# define APIC_LVT_DM_INIT 0x00000500 -# define APIC_LVT_DM_EXTINT 0x00000700 -#define APIC_LVT_DS 0x00001000 -#define APIC_LVT_IIPP 0x00002000 -#define APIC_LVT_IIPP_INTALO 0x00002000 -#define APIC_LVT_IIPP_INTAHI 0x00000000 -#define APIC_LVT_RIRR 0x00004000 -#define APIC_LVT_TM 0x00008000 -#define APIC_LVT_M 0x00010000 - - -/* fields in LVT Timer */ -#define APIC_LVTT_VECTOR 0x000000ff -#define APIC_LVTT_DS 0x00001000 -#define APIC_LVTT_M 0x00010000 -#define APIC_LVTT_TM 0x00020000 -# define APIC_LVTT_TM_ONE_SHOT 0x00000000 -# define APIC_LVTT_TM_PERIODIC 0x00020000 - - -/* APIC timer current count */ -#define APIC_TIMER_MAX_COUNT 0xffffffff - -/* fields in TDCR */ -#define APIC_TDCR_2 0x00 -#define APIC_TDCR_4 0x01 -#define APIC_TDCR_8 0x02 -#define APIC_TDCR_16 0x03 -#define APIC_TDCR_32 0x08 -#define APIC_TDCR_64 0x09 -#define APIC_TDCR_128 0x0a -#define APIC_TDCR_1 0x0b - -/****************************************************************************** - * I/O APIC defines - */ - -/* default physical locations of an IO APIC */ -#define DEFAULT_IO_APIC_BASE 0xfec00000 - -/* window register offset */ -#define IOAPIC_WINDOW 0x10 -#define IOAPIC_EOIR 0x40 - -/* indexes into IO APIC */ -#define IOAPIC_ID 0x00 -#define IOAPIC_VER 0x01 -#define IOAPIC_ARB 0x02 -#define IOAPIC_REDTBL 0x10 -#define IOAPIC_REDTBL0 IOAPIC_REDTBL -#define IOAPIC_REDTBL1 (IOAPIC_REDTBL+0x02) -#define IOAPIC_REDTBL2 (IOAPIC_REDTBL+0x04) -#define IOAPIC_REDTBL3 (IOAPIC_REDTBL+0x06) -#define IOAPIC_REDTBL4 (IOAPIC_REDTBL+0x08) -#define IOAPIC_REDTBL5 (IOAPIC_REDTBL+0x0a) -#define IOAPIC_REDTBL6 (IOAPIC_REDTBL+0x0c) -#define IOAPIC_REDTBL7 (IOAPIC_REDTBL+0x0e) -#define IOAPIC_REDTBL8 (IOAPIC_REDTBL+0x10) -#define IOAPIC_REDTBL9 (IOAPIC_REDTBL+0x12) -#define IOAPIC_REDTBL10 (IOAPIC_REDTBL+0x14) -#define IOAPIC_REDTBL11 (IOAPIC_REDTBL+0x16) -#define IOAPIC_REDTBL12 (IOAPIC_REDTBL+0x18) -#define IOAPIC_REDTBL13 (IOAPIC_REDTBL+0x1a) -#define IOAPIC_REDTBL14 (IOAPIC_REDTBL+0x1c) -#define IOAPIC_REDTBL15 (IOAPIC_REDTBL+0x1e) -#define IOAPIC_REDTBL16 (IOAPIC_REDTBL+0x20) -#define IOAPIC_REDTBL17 (IOAPIC_REDTBL+0x22) -#define IOAPIC_REDTBL18 (IOAPIC_REDTBL+0x24) -#define IOAPIC_REDTBL19 (IOAPIC_REDTBL+0x26) -#define IOAPIC_REDTBL20 (IOAPIC_REDTBL+0x28) -#define IOAPIC_REDTBL21 (IOAPIC_REDTBL+0x2a) -#define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c) -#define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e) - -/* fields in VER */ -#define IOART_VER_VERSION 0x000000ff -#define IOART_VER_MAXREDIR 0x00ff0000 -#define MAXREDIRSHIFT 16 - -/* - * fields in the IO APIC's redirection table entries - */ -#define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */ - -#define IOART_RESV 0x00fe0000 /* reserved */ - -#define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */ -# define IOART_INTMCLR 0x00000000 /* clear, allow INTs */ -# define IOART_INTMSET 0x00010000 /* set, inhibit INTs */ - -#define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */ -# define IOART_TRGREDG 0x00000000 /* edge */ -# define IOART_TRGRLVL 0x00008000 /* level */ - -#define IOART_REM_IRR 0x00004000 /* RO: remote IRR */ - -#define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */ -# define IOART_INTAHI 0x00000000 /* active high */ -# define IOART_INTALO 0x00002000 /* active low */ - -#define IOART_DELIVS 0x00001000 /* RO: delivery status */ - -#define IOART_DESTMOD 0x00000800 /* R/W: destination mode */ -# define IOART_DESTPHY 0x00000000 /* physical */ -# define IOART_DESTLOG 0x00000800 /* logical */ - -#define IOART_DELMOD 0x00000700 /* R/W: delivery mode */ -# define IOART_DELFIXED 0x00000000 /* fixed */ -# define IOART_DELLOPRI 0x00000100 /* lowest priority */ -# define IOART_DELSMI 0x00000200 /* System Management INT */ -# define IOART_DELRSV1 0x00000300 /* reserved */ -# define IOART_DELNMI 0x00000400 /* NMI signal */ -# define IOART_DELINIT 0x00000500 /* INIT signal */ -# define IOART_DELRSV2 0x00000600 /* reserved */ -# define IOART_DELEXINT 0x00000700 /* External INTerrupt */ - -#define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */ - -#endif /* _MACHINE_APICREG_H_ */ diff --git a/sys/i386/include/mca.h b/sys/i386/include/mca.h deleted file mode 100644 index dd6e69c..0000000 --- a/sys/i386/include/mca.h +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright (c) 2009 Advanced Computing Technologies LLC - * Written by: John H. Baldwin <jhb@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef __MACHINE_MCA_H__ -#define __MACHINE_MCA_H__ - -struct mca_record { - uint64_t mr_status; - uint64_t mr_addr; - uint64_t mr_misc; - uint64_t mr_tsc; - int mr_apic_id; - int mr_bank; - uint64_t mr_mcg_cap; - uint64_t mr_mcg_status; - int mr_cpu_id; - int mr_cpu_vendor_id; - int mr_cpu; -}; - -#ifdef _KERNEL - -void cmc_intr(void); -void mca_init(void); -int mca_intr(void); -void mca_resume(void); - -#endif - -#endif /* !__MACHINE_MCA_H__ */ diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index 43a82ab..60165cb 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_extern.h> #include <vm/vm_page.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/md_var.h> #include <machine/mp_watchdog.h> #include <machine/pcb.h> diff --git a/sys/i386/xen/mptable.c b/sys/i386/xen/mptable.c index c6c7d53..fe01cd5 100644 --- a/sys/i386/xen/mptable.c +++ b/sys/i386/xen/mptable.c @@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index d697689..b86ea91 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -180,6 +180,9 @@ mi_startup(void) int verbose; #endif + if (boothowto & RB_VERBOSE) + bootverbose++; + if (sysinit == NULL) { sysinit = SET_BEGIN(sysinit_set); sysinit_end = SET_LIMIT(sysinit_set); @@ -327,15 +330,6 @@ SYSINIT(diagwarn2, SI_SUB_RUN_SCHEDULER, SI_ORDER_THIRD + 2, print_caddr_t, diag_warn); #endif -static void -set_boot_verbose(void *data __unused) -{ - - if (boothowto & RB_VERBOSE) - bootverbose++; -} -SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL); - static int null_fetch_syscall_args(struct thread *td __unused, struct syscall_args *sa __unused) diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c index 23aa9df..c5eb659 100644 --- a/sys/kern/kern_cpuset.c +++ b/sys/kern/kern_cpuset.c @@ -107,6 +107,10 @@ static struct setlist cpuset_ids; static struct unrhdr *cpuset_unr; static struct cpuset *cpuset_zero; +/* Return the size of cpuset_t at the kernel level */ +SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD, + 0, sizeof(cpuset_t), "sizeof(cpuset_t)"); + cpuset_t *cpuset_root; /* diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 98f55da..f60af40 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -295,8 +295,7 @@ callout_tickstofirst(int limit) sc = &cc->cc_callwheel[ (curticks+skip) & callwheelmask ]; /* search scanning ticks */ TAILQ_FOREACH( c, sc, c_links.tqe ){ - if (c && (c->c_time <= curticks + ncallout) - && (c->c_time > 0)) + if (c->c_time - curticks <= ncallout) goto out; } skip++; diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index 4765c1c..0005968 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -2712,6 +2712,7 @@ sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS) sbuf_delete(topo); return (err); } + #endif SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler"); @@ -2748,6 +2749,7 @@ SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0, SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A", "XML dump of detected CPU topology"); + #endif /* ps compat. All cpu percentages from ULE are weighted. */ diff --git a/sys/kern/subr_acl_nfs4.c b/sys/kern/subr_acl_nfs4.c index cf664bf..767f04b 100644 --- a/sys/kern/subr_acl_nfs4.c +++ b/sys/kern/subr_acl_nfs4.c @@ -162,7 +162,7 @@ vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid, accmode_t priv_granted = 0; int denied, explicitly_denied, access_mask, is_directory, must_be_owner = 0; - mode_t file_mode; + mode_t file_mode = 0; KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND | VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS | diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 5a48a67..0efdbc1 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -129,8 +129,6 @@ static u_long nchash; /* size of hash table */ SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0, "Size of namecache hash table"); static u_long ncnegfactor = 16; /* ratio of negative entries */ -/* _debug sysctl left for backward compatibility */ -SYSCTL_ULONG(_debug, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, ""); SYSCTL_ULONG(_vfs, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, "Ratio of negative namecache entries"); static u_long numneg; /* number of negative entries allocated */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 452cc8f..a5ce22c 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -631,6 +631,7 @@ _xe= xe .endif .if ${MACHINE_CPUARCH} == "powerpc" +_agp= agp _an= an _bm= bm _cpufreq= cpufreq diff --git a/sys/modules/agp/Makefile b/sys/modules/agp/Makefile index f77e38c..9e28657 100644 --- a/sys/modules/agp/Makefile +++ b/sys/modules/agp/Makefile @@ -11,9 +11,12 @@ SRCS+= agp_i810.c agp_intel.c agp_via.c agp_sis.c agp_ali.c agp_amd.c \ .if ${MACHINE} == "i386" SRCS+= agp_amd64.c .endif -.if ${MACHINE_CPUARCH} == "amd64" +.if ${MACHINE_CPUARCH} == "amd64" SRCS+= agp_amd64.c agp_i810.c agp_via.c .endif +.if ${MACHINE_CPUARCH} == "powerpc" +SRCS+= agp_apple.c +.endif SRCS+= device_if.h bus_if.h agp_if.h pci_if.h SRCS+= opt_agp.h opt_bus.h MFILES= kern/device_if.m kern/bus_if.m dev/agp/agp_if.m dev/pci/pci_if.m diff --git a/sys/net/bpf.h b/sys/net/bpf.h index b1aad51..d4c369d 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -844,6 +844,143 @@ struct bpf_zbuf_header { */ #define DLT_IEEE802_15_4_NONASK_PHY 215 +/* + * David Gibson <david@gibson.dropbear.id.au> requested this for + * captures from the Linux kernel /dev/input/eventN devices. This + * is used to communicate keystrokes and mouse movements from the + * Linux kernel to display systems, such as Xorg. + */ +#define DLT_LINUX_EVDEV 216 + +/* + * GSM Um and Abis interfaces, preceded by a "gsmtap" header. + * + * Requested by Harald Welte <laforge@gnumonks.org>. + */ +#define DLT_GSMTAP_UM 217 +#define DLT_GSMTAP_ABIS 218 + +/* + * MPLS, with an MPLS label as the link-layer header. + * Requested by Michele Marchetto <michele@openbsd.org> on behalf + * of OpenBSD. + */ +#define DLT_MPLS 219 + +/* + * USB packets, beginning with a Linux USB header, with the USB header + * padded to 64 bytes; required for memory-mapped access. + */ +#define DLT_USB_LINUX_MMAPPED 220 + +/* + * DECT packets, with a pseudo-header; requested by + * Matthias Wenzel <tcpdump@mazzoo.de>. + */ +#define DLT_DECT 221 +/* + * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov> + * Date: Mon, 11 May 2009 11:18:30 -0500 + * + * DLT_AOS. We need it for AOS Space Data Link Protocol. + * I have already written dissectors for but need an OK from + * legal before I can submit a patch. + * + */ +#define DLT_AOS 222 + +/* + * Wireless HART (Highway Addressable Remote Transducer) + * From the HART Communication Foundation + * IES/PAS 62591 + * + * Requested by Sam Roberts <vieuxtech@gmail.com>. + */ +#define DLT_WIHART 223 + +/* + * Fibre Channel FC-2 frames, beginning with a Frame_Header. + * Requested by Kahou Lei <kahou82@gmail.com>. + */ +#define DLT_FC_2 224 + +/* + * Fibre Channel FC-2 frames, beginning with an encoding of the + * SOF, and ending with an encoding of the EOF. + * + * The encodings represent the frame delimiters as 4-byte sequences + * representing the corresponding ordered sets, with K28.5 + * represented as 0xBC, and the D symbols as the corresponding + * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2, + * is represented as 0xBC 0xB5 0x55 0x55. + * + * Requested by Kahou Lei <kahou82@gmail.com>. + */ +#define DLT_FC_2_WITH_FRAME_DELIMS 225 +/* + * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>. + * + * The pseudo-header starts with a one-byte version number; for version 2, + * the pseudo-header is: + * + * struct dl_ipnetinfo { + * u_int8_t dli_version; + * u_int8_t dli_family; + * u_int16_t dli_htype; + * u_int32_t dli_pktlen; + * u_int32_t dli_ifindex; + * u_int32_t dli_grifindex; + * u_int32_t dli_zsrc; + * u_int32_t dli_zdst; + * }; + * + * dli_version is 2 for the current version of the pseudo-header. + * + * dli_family is a Solaris address family value, so it's 2 for IPv4 + * and 26 for IPv6. + * + * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing + * packets, and 2 for packets arriving from another zone on the same + * machine. + * + * dli_pktlen is the length of the packet data following the pseudo-header + * (so the captured length minus dli_pktlen is the length of the + * pseudo-header, assuming the entire pseudo-header was captured). + * + * dli_ifindex is the interface index of the interface on which the + * packet arrived. + * + * dli_grifindex is the group interface index number (for IPMP interfaces). + * + * dli_zsrc is the zone identifier for the source of the packet. + * + * dli_zdst is the zone identifier for the destination of the packet. + * + * A zone number of 0 is the global zone; a zone number of 0xffffffff + * means that the packet arrived from another host on the network, not + * from another zone on the same machine. + * + * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates + * which of those it is. + */ +#define DLT_IPNET 226 + +/* + * CAN (Controller Area Network) frames, with a pseudo-header as supplied + * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux + * source. + * + * Requested by Felix Obenhuber <felix@obenhuber.de>. + */ +#define DLT_CAN_SOCKETCAN 227 + +/* + * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies + * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>. + */ +#define DLT_IPV4 228 +#define DLT_IPV6 229 + /* * DLT and savefile link type values are split into a class and * a member of that class. A class value of 0 indicates a regular diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index a6ea36e..f18236f 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -291,8 +291,6 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, return (0); } } - /* XXXXX - */ retry: IF_AFDATA_RLOCK(ifp); la = lla_lookup(LLTABLE(ifp), flags, dst); @@ -381,7 +379,7 @@ retry: int canceled; LLE_ADDREF(la); - la->la_expire = time_second + V_arpt_down; + la->la_expire = time_second; canceled = callout_reset(&la->la_timer, hz * V_arpt_down, arptimer, la); if (canceled) diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index 1f48dd6..712040f 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -126,6 +126,11 @@ VNET_DEFINE(int, ip4_esp_randpad) = -1; */ VNET_DEFINE(int, crypto_support) = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; +FEATURE(ipsec, "Internet Protocol Security (IPsec)"); +#ifdef IPSEC_NAT_T +FEATURE(ipsec_natt, "UDP Encapsulation of IPsec ESP Packets ('NAT-T')"); +#endif + SYSCTL_DECL(_net_inet_ipsec); /* net.inet.ipsec */ diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index fd50ca8..52f5bfc 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -779,10 +779,10 @@ static const char *nfs_opts[] = { "from", "nfs_args", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union", "noclusterr", "noclusterw", "multilabel", "acls", "force", "update", "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport", - "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize", - "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", - "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3", "sec", - "maxgroups", "principal", "negnametimeo", + "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", + "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin", + "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3", + "sec", "maxgroups", "principal", "negnametimeo", NULL }; /* diff --git a/sys/pc98/include/apicreg.h b/sys/pc98/include/apicreg.h deleted file mode 100644 index a9766d5..0000000 --- a/sys/pc98/include/apicreg.h +++ /dev/null @@ -1,6 +0,0 @@ -/*- - * This file is in the public domain. - */ -/* $FreeBSD$ */ - -#include <i386/apicreg.h> diff --git a/sys/pc98/include/bus.h b/sys/pc98/include/bus.h index 07b7ea3..b12845c 100644 --- a/sys/pc98/include/bus.h +++ b/sys/pc98/include/bus.h @@ -158,8 +158,8 @@ struct bus_space_access_methods { * Access methods for bus resources and address space. */ struct bus_space_tag { -#define BUS_SPACE_IO 0 -#define BUS_SPACE_MEM 1 +#define BUS_SPACE_TAG_IO 0 +#define BUS_SPACE_TAG_MEM 1 u_int bs_tag; /* bus space flags */ struct bus_space_access_methods bs_da; /* direct access */ diff --git a/sys/pc98/include/mca.h b/sys/pc98/include/mca.h deleted file mode 100644 index a047f87..0000000 --- a/sys/pc98/include/mca.h +++ /dev/null @@ -1,6 +0,0 @@ -/*- - * This file is in the public domain. - */ -/* $FreeBSD$ */ - -#include <i386/mca.h> diff --git a/sys/pc98/pc98/busiosubr.c b/sys/pc98/pc98/busiosubr.c index dffe5ff..926c1ce 100644 --- a/sys/pc98/pc98/busiosubr.c +++ b/sys/pc98/pc98/busiosubr.c @@ -63,7 +63,7 @@ _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2) _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4) struct bus_space_tag SBUS_io_space_tag = { - BUS_SPACE_IO, + BUS_SPACE_TAG_IO, /* direct bus access methods */ { @@ -81,7 +81,7 @@ struct bus_space_tag SBUS_io_space_tag = { }; struct bus_space_tag SBUS_mem_space_tag = { - BUS_SPACE_MEM, + BUS_SPACE_TAG_MEM, /* direct bus access methods */ { @@ -109,7 +109,7 @@ _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2) _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4) struct bus_space_tag NEPC_io_space_tag = { - BUS_SPACE_IO, + BUS_SPACE_TAG_IO, /* direct bus access methods */ { @@ -127,7 +127,7 @@ struct bus_space_tag NEPC_io_space_tag = { }; struct bus_space_tag NEPC_mem_space_tag = { - BUS_SPACE_MEM, + BUS_SPACE_TAG_MEM, /* direct bus access methods */ { @@ -256,7 +256,7 @@ i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, pbase = pbsh->bsh_base + offset; switch (t->bs_tag) { - case BUS_SPACE_IO: + case BUS_SPACE_TAG_IO: if (pbsh->bsh_iatsz > 0) { if (offset >= pbsh->bsh_iatsz || offset + size > pbsh->bsh_iatsz) @@ -265,7 +265,7 @@ i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, } break; - case BUS_SPACE_MEM: + case BUS_SPACE_TAG_MEM: if (pbsh->bsh_iatsz > 0) return EINVAL; if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) @@ -282,7 +282,7 @@ i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, return error; switch (t->bs_tag) { - case BUS_SPACE_IO: + case BUS_SPACE_TAG_IO: if (pbsh->bsh_iatsz > 0) { for (i = 0; i < size; i ++) bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; @@ -295,7 +295,7 @@ i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, } break; - case BUS_SPACE_MEM: + case BUS_SPACE_TAG_MEM: break; } diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 32328c5..e01ef68 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -112,7 +112,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/cputypes.h> #include <machine/intr_machdep.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/pc/bios.h> #include <machine/pcb.h> diff --git a/sys/powerpc/aim/copyinout.c b/sys/powerpc/aim/copyinout.c index ab2d1f32..15623ed 100644 --- a/sys/powerpc/aim/copyinout.c +++ b/sys/powerpc/aim/copyinout.c @@ -81,9 +81,7 @@ static __inline void set_user_sr(pmap_t pm, const void *addr) { struct slb *slb; - register_t esid, vsid, slb1, slb2; - - esid = USER_ADDR >> ADDR_SR_SHFT; + register_t slbv; /* Try lockless look-up first */ slb = user_va_to_slb_entry(pm, (vm_offset_t)addr); @@ -91,20 +89,24 @@ set_user_sr(pmap_t pm, const void *addr) if (slb == NULL) { /* If it isn't there, we need to pre-fault the VSID */ PMAP_LOCK(pm); - vsid = va_to_vsid(pm, (vm_offset_t)addr); + slbv = va_to_vsid(pm, (vm_offset_t)addr) << SLBV_VSID_SHIFT; PMAP_UNLOCK(pm); } else { - vsid = slb->slbv >> SLBV_VSID_SHIFT; + slbv = slb->slbv; } - slb1 = vsid << SLBV_VSID_SHIFT; - slb2 = (esid << SLBE_ESID_SHIFT) | SLBE_VALID | USER_SR; + /* Mark segment no-execute */ + slbv |= SLBV_N; + + /* If we have already set this VSID, we can just return */ + if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == slbv) + return; + __asm __volatile ("isync; slbie %0; slbmte %1, %2; isync" :: + "r"(USER_ADDR), "r"(slbv), "r"(USER_SLB_SLBE)); curthread->td_pcb->pcb_cpu.aim.usr_segm = (uintptr_t)addr >> ADDR_SR_SHFT; - __asm __volatile ("slbie %0; slbmte %1, %2" :: "r"(esid << 28), - "r"(slb1), "r"(slb2)); - isync(); + curthread->td_pcb->pcb_cpu.aim.usr_vsid = slbv; } #else static __inline void @@ -114,9 +116,16 @@ set_user_sr(pmap_t pm, const void *addr) vsid = va_to_vsid(pm, (vm_offset_t)addr); - isync(); - __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid)); - isync(); + /* If we have already set this VSID, we can just return */ + if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == vsid) + return; + + /* Mark segment no-execute */ + vsid |= SR_N; + + __asm __volatile("isync"); + curthread->td_pcb->pcb_cpu.aim.usr_vsid = vsid; + __asm __volatile("mtsr %0,%1; isync" :: "n"(USER_SR), "r"(vsid)); } #endif diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 27d4ef3..5ba029c 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -304,6 +304,7 @@ vm_paddr_t moea_extract(mmu_t, pmap_t, vm_offset_t); vm_page_t moea_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t); void moea_init(mmu_t); boolean_t moea_is_modified(mmu_t, vm_page_t); +boolean_t moea_is_prefaultable(mmu_t, pmap_t, vm_offset_t); boolean_t moea_is_referenced(mmu_t, vm_page_t); boolean_t moea_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); @@ -347,6 +348,7 @@ static mmu_method_t moea_methods[] = { MMUMETHOD(mmu_extract_and_hold, moea_extract_and_hold), MMUMETHOD(mmu_init, moea_init), MMUMETHOD(mmu_is_modified, moea_is_modified), + MMUMETHOD(mmu_is_prefaultable, moea_is_prefaultable), MMUMETHOD(mmu_is_referenced, moea_is_referenced), MMUMETHOD(mmu_ts_referenced, moea_ts_referenced), MMUMETHOD(mmu_map, moea_map), @@ -1324,6 +1326,19 @@ moea_is_modified(mmu_t mmu, vm_page_t m) return (moea_query_bit(m, PTE_CHG)); } +boolean_t +moea_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t va) +{ + struct pvo_entry *pvo; + boolean_t rv; + + PMAP_LOCK(pmap); + pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); + rv = pvo == NULL || (pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0; + PMAP_UNLOCK(pmap); + return (rv); +} + void moea_clear_reference(mmu_t mmu, vm_page_t m) { @@ -2430,7 +2445,7 @@ moea_bat_mapped(int idx, vm_offset_t pa, vm_size_t size) /* * Return immediately if not a valid mapping */ - if (!battable[idx].batu & BAT_Vs) + if (!(battable[idx].batu & BAT_Vs)) return (EINVAL); /* diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 5e74a13..cfb822e 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -400,6 +400,7 @@ vm_paddr_t moea64_extract(mmu_t, pmap_t, vm_offset_t); vm_page_t moea64_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t); void moea64_init(mmu_t); boolean_t moea64_is_modified(mmu_t, vm_page_t); +boolean_t moea64_is_prefaultable(mmu_t, pmap_t, vm_offset_t); boolean_t moea64_is_referenced(mmu_t, vm_page_t); boolean_t moea64_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); @@ -441,6 +442,7 @@ static mmu_method_t moea64_methods[] = { MMUMETHOD(mmu_extract_and_hold, moea64_extract_and_hold), MMUMETHOD(mmu_init, moea64_init), MMUMETHOD(mmu_is_modified, moea64_is_modified), + MMUMETHOD(mmu_is_prefaultable, moea64_is_prefaultable), MMUMETHOD(mmu_is_referenced, moea64_is_referenced), MMUMETHOD(mmu_ts_referenced, moea64_ts_referenced), MMUMETHOD(mmu_map, moea64_map), @@ -1786,6 +1788,19 @@ moea64_is_modified(mmu_t mmu, vm_page_t m) return (moea64_query_bit(m, LPTE_CHG)); } +boolean_t +moea64_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t va) +{ + struct pvo_entry *pvo; + boolean_t rv; + + PMAP_LOCK(pmap); + pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF); + rv = pvo == NULL || (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0; + PMAP_UNLOCK(pmap); + return (rv); +} + void moea64_clear_reference(mmu_t mmu, vm_page_t m) { diff --git a/sys/powerpc/aim/slb.c b/sys/powerpc/aim/slb.c index e7bdaf8..9d8828a 100644 --- a/sys/powerpc/aim/slb.c +++ b/sys/powerpc/aim/slb.c @@ -200,7 +200,7 @@ kernel_va_to_slbv(vm_offset_t va) esid = (uintptr_t)va >> ADDR_SR_SHFT; /* Set kernel VSID to deterministic value */ - slbv = va_to_vsid(kernel_pmap, va) << SLBV_VSID_SHIFT; + slbv = (KERNEL_VSID((uintptr_t)va >> ADDR_SR_SHFT)) << SLBV_VSID_SHIFT; /* Figure out if this is a large-page mapping */ if (hw_direct_map && va < VM_MIN_KERNEL_ADDRESS) { @@ -421,19 +421,19 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv) slbcache = PCPU_GET(slb); - /* Check for an unused slot, abusing the USER_SR slot as a full flag */ - if (slbcache[USER_SR].slbe == 0) { - for (i = 0; i < USER_SR; i++) { + /* Check for an unused slot, abusing the user slot as a full flag */ + if (slbcache[USER_SLB_SLOT].slbe == 0) { + for (i = 0; i < USER_SLB_SLOT; i++) { if (!(slbcache[i].slbe & SLBE_VALID)) goto fillkernslb; } - if (i == USER_SR) - slbcache[USER_SR].slbe = 1; + if (i == USER_SLB_SLOT) + slbcache[USER_SLB_SLOT].slbe = 1; } for (i = mftb() % 64, j = 0; j < 64; j++, i = (i+1) % 64) { - if (i == USER_SR) + if (i == USER_SLB_SLOT) continue; if (SLB_SPILLABLE(slbcache[i].slbe)) diff --git a/sys/powerpc/aim/swtch32.S b/sys/powerpc/aim/swtch32.S index f5dba2a..3b608f8 100644 --- a/sys/powerpc/aim/swtch32.S +++ b/sys/powerpc/aim/swtch32.S @@ -89,7 +89,6 @@ ENTRY(cpu_switch) mflr %r16 /* Save the link register */ stw %r16,PCB_LR(%r6) mfsr %r16,USER_SR /* Save USER_SR for copyin/out */ - isync stw %r16,PCB_AIM_USR_VSID(%r6) stw %r1,PCB_SP(%r6) /* Save the stack pointer */ stw %r2,PCB_TOC(%r6) /* Save the TOC pointer */ @@ -162,6 +161,7 @@ blocked_loop: lwz %r5,PCB_LR(%r3) /* Load the link register */ mtlr %r5 lwz %r5,PCB_AIM_USR_VSID(%r3) /* Load the USER_SR segment reg */ + isync mtsr USER_SR,%r5 isync lwz %r1,PCB_SP(%r3) /* Load the stack pointer */ diff --git a/sys/powerpc/aim/swtch64.S b/sys/powerpc/aim/swtch64.S index 6ba9843..f1af24e 100644 --- a/sys/powerpc/aim/swtch64.S +++ b/sys/powerpc/aim/swtch64.S @@ -110,13 +110,9 @@ ENTRY(cpu_switch) std %r1,PCB_SP(%r6) /* Save the stack pointer */ std %r2,PCB_TOC(%r6) /* Save the TOC pointer */ - li %r14,0 /* Save USER_SR for copyin/out */ - li %r15,0 - li %r16,USER_SR - slbmfee %r14, %r16 + li %r15,0 /* Save user segment for copyin/out */ + li %r16,USER_SLB_SLOT slbmfev %r15, %r16 - isync - std %r14,PCB_AIM_USR_ESID(%r6) std %r15,PCB_AIM_USR_VSID(%r6) mr %r14,%r3 /* Copy the old thread ptr... */ @@ -221,17 +217,21 @@ blocked_loop: ld %r1,PCB_SP(%r3) /* Load the stack pointer */ ld %r2,PCB_TOC(%r3) /* Load the TOC pointer */ - lis %r5,USER_ADDR@highesta /* Load the USER_SR segment reg */ + lis %r5,USER_ADDR@highesta /* Load the copyin/out segment reg */ ori %r5,%r5,USER_ADDR@highera sldi %r5,%r5,32 oris %r5,%r5,USER_ADDR@ha + isync slbie %r5 + lis %r6,USER_SLB_SLBE@highesta + ori %r6,%r6,USER_SLB_SLBE@highera + sldi %r6,%r6,32 + oris %r6,%r6,USER_SLB_SLBE@ha + ori %r6,%r6,USER_SLB_SLBE@l ld %r5,PCB_AIM_USR_VSID(%r3) - ld %r6,PCB_AIM_USR_ESID(%r3) - ori %r6,%r6,USER_SR slbmte %r5,%r6 - isync + /* * Perform a dummy stdcx. to clear any reservations we may have * inherited from the previous thread. It doesn't matter if the diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index db48e7b..22f55a7 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -249,8 +249,16 @@ trap(struct trapframe *frame) return; break; #ifdef __powerpc64__ - case EXC_ISE: case EXC_DSE: + if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) { + __asm __volatile ("slbmte %0, %1" :: + "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), + "r"(USER_SLB_SLBE)); + return; + } + + /* FALLTHROUGH */ + case EXC_ISE: if (handle_slb_spill(kernel_pmap, (type == EXC_ISE) ? frame->srr0 : frame->cpu.aim.dar) != 0) diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index 6482553..1cefc28 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -54,7 +54,7 @@ lwz sr,9*4(pmap); mtsr 9,sr; \ lwz sr,10*4(pmap); mtsr 10,sr; \ lwz sr,11*4(pmap); mtsr 11,sr; \ - lwz sr,12*4(pmap); mtsr 12,sr; \ + /* Skip segment 12 (USER_SR), which is restored differently */ \ lwz sr,13*4(pmap); mtsr 13,sr; \ lwz sr,14*4(pmap); mtsr 14,sr; \ lwz sr,15*4(pmap); mtsr 15,sr; isync; @@ -66,7 +66,9 @@ GET_CPUINFO(pmap); \ lwz pmap,PC_CURPMAP(pmap); \ lwzu sr,PM_SR(pmap); \ - RESTORE_SRS(pmap,sr) + RESTORE_SRS(pmap,sr) \ + /* Restore SR 12 */ \ + lwz sr,12*4(pmap); mtsr 12,sr /* * Kernel SRs are loaded directly from kernel_pmap_ @@ -537,6 +539,11 @@ u_trap: */ k_trap: FRAME_SETUP(PC_TEMPSAVE) + /* Restore USER_SR */ + GET_CPUINFO(%r30) + lwz %r30,PC_CURPCB(%r30) + lwz %r30,PCB_AIM_USR_VSID(%r30) + mtsr USER_SR,%r30; sync; isync /* Call C interrupt dispatcher: */ trapagain: addi %r3,%r1,8 diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index e0dae3c..db54d4b 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -99,7 +99,7 @@ instkernslb: addi %r28, %r28, 16; /* Advance pointer */ addi %r29, %r29, 1; - cmpli 0, %r29, USER_SR; /* Repeat if we are not at the end */ + cmpli 0, %r29, USER_SLB_SLOT; /* Repeat if we are not at the end */ blt instkernslb; blr; diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c index d1d569f..7bd0fb7 100644 --- a/sys/powerpc/aim/vm_machdep.c +++ b/sys/powerpc/aim/vm_machdep.c @@ -197,7 +197,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) pcb->pcb_lr = (register_t)fork_trampoline; #endif pcb->pcb_cpu.aim.usr_vsid = 0; - pcb->pcb_cpu.aim.usr_esid = 0; /* Setup to release spin count in fork_exit(). */ td2->td_md.md_spinlock_count = 1; diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC index c23e9ac..2d1a0ca 100644 --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -84,6 +84,7 @@ device cpufreq # Standard busses device pci +device agp # ATA and ATAPI devices device ata diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 index b861e51..b18dee9 100644 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -83,6 +83,7 @@ device cpufreq # Standard busses device pci +device agp # ATA and ATAPI devices device ata diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES index 7248eab..a9a620a 100644 --- a/sys/powerpc/conf/NOTES +++ b/sys/powerpc/conf/NOTES @@ -30,6 +30,7 @@ device cpufreq # Standard busses device pci +device agp device bm # Apple BMAC (Big Mac Ethernet) device kiic # Apple Keywest I2C Controller diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h index a037276..ede7644 100644 --- a/sys/powerpc/include/pcb.h +++ b/sys/powerpc/include/pcb.h @@ -67,7 +67,6 @@ struct pcb { union { struct { vm_offset_t usr_segm; /* Base address */ - register_t usr_esid; /* USER_SR segment */ register_t usr_vsid; /* USER_SR segment */ } aim; struct { diff --git a/sys/powerpc/include/slb.h b/sys/powerpc/include/slb.h index 0d650b3..f675e15 100644 --- a/sys/powerpc/include/slb.h +++ b/sys/powerpc/include/slb.h @@ -62,6 +62,13 @@ #define SLBE_ESID_MASK 0xfffffffff0000000UL /* Effective segment ID mask */ #define SLBE_ESID_SHIFT 28 +/* + * User segment for copyin/out + */ +#define USER_SLB_SLOT 63 +#define USER_SLB_SLBE (((USER_ADDR >> ADDR_SR_SHFT) << SLBE_ESID_SHIFT) | \ + SLBE_VALID | USER_SLB_SLOT) + struct slb { uint64_t slbv; uint64_t slbe; diff --git a/sys/powerpc/include/sr.h b/sys/powerpc/include/sr.h index ed9801a..ae66314 100644 --- a/sys/powerpc/include/sr.h +++ b/sys/powerpc/include/sr.h @@ -42,11 +42,7 @@ #define SR_VSID_MASK 0x00ffffff /* Virtual Segment ID mask */ /* Kernel segment register usage */ -#ifdef __powerpc64__ -#define USER_SR 63 -#else #define USER_SR 12 -#endif #define KERNEL_SR 13 #define KERNEL2_SR 14 #define KERNEL3_SR 15 diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c index 3af4d60..ab5c870 100644 --- a/sys/powerpc/powermac/cpcht.c +++ b/sys/powerpc/powermac/cpcht.c @@ -162,6 +162,7 @@ struct cpcht_softc { vm_offset_t sc_data; uint64_t sc_populated_slots; struct rman sc_mem_rman; + struct rman sc_io_rman; struct cpcht_irq htirq_map[128]; struct mtx htirq_mtx; @@ -177,6 +178,9 @@ static devclass_t cpcht_devclass; DRIVER_MODULE(cpcht, nexus, cpcht_driver, cpcht_devclass, 0, 0); +#define CPCHT_IOPORT_BASE 0xf4000000UL /* Hardwired */ +#define CPCHT_IOPORT_SIZE 0x00400000UL + #define HTAPIC_REQUEST_EOI 0x20 #define HTAPIC_TRIGGER_LEVEL 0x02 #define HTAPIC_MASK 0x01 @@ -236,7 +240,14 @@ cpcht_attach(device_t dev) sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "CPCHT Device Memory"; error = rman_init(&sc->sc_mem_rman); + if (error) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + return (error); + } + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "CPCHT I/O Memory"; + error = rman_init(&sc->sc_io_rman); if (error) { device_printf(dev, "rman_init() failed. error = %d\n", error); return (error); @@ -248,6 +259,9 @@ cpcht_attach(device_t dev) * where we get the HT interrupts properties. */ + /* I/O port mappings are usually not in the device tree */ + rman_manage_region(&sc->sc_io_rman, 0, CPCHT_IOPORT_SIZE - 1); + bzero(sc->htirq_map, sizeof(sc->htirq_map)); mtx_init(&sc->htirq_mtx, "cpcht irq", NULL, MTX_DEF); for (i = 0; i < 8; i++) @@ -299,6 +313,9 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) case OFW_PCI_PHYS_HI_SPACE_CONFIG: break; case OFW_PCI_PHYS_HI_SPACE_IO: + rman_manage_region(&sc->sc_io_rman, rp->pci_lo, + rp->pci_lo + rp->size_lo - 1); + break; case OFW_PCI_PHYS_HI_SPACE_MEM32: rman_manage_region(&sc->sc_mem_rman, rp->pci_lo, rp->pci_lo + rp->size_lo - 1); @@ -507,8 +524,9 @@ cpcht_alloc_resource(device_t bus, device_t child, int type, int *rid, switch (type) { case SYS_RES_IOPORT: end = min(end, start + count); + rm = &sc->sc_io_rman; + break; - /* FALLTHROUGH */ case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; @@ -562,6 +580,9 @@ cpcht_activate_resource(device_t bus, device_t child, int type, int rid, start = (vm_offset_t)rman_get_start(res); + if (type == SYS_RES_IOPORT) + start += CPCHT_IOPORT_BASE; + if (bootverbose) printf("cpcht mapdev: start %zx, len %ld\n", start, rman_get_size(res)); diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index a4e397d..efcd805 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -986,7 +986,6 @@ cpu_set_upcall(struct thread *td, struct thread *td0) pcb2->pcb_lr = (register_t)fork_trampoline; #endif pcb2->pcb_cpu.aim.usr_vsid = 0; - pcb2->pcb_cpu.aim.usr_esid = 0; /* Setup to release spin count in fork_exit(). */ td->td_md.md_spinlock_count = 1; diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c index 3437ca0..9f59498 100644 --- a/sys/powerpc/powerpc/genassym.c +++ b/sys/powerpc/powerpc/genassym.c @@ -103,13 +103,15 @@ ASSYM(TLBSAVE_BOOKE_R31, TLBSAVE_BOOKE_R31*sizeof(register_t)); ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); #if defined(AIM) -ASSYM(USER_SR, USER_SR); ASSYM(USER_ADDR, USER_ADDR); #ifdef __powerpc64__ ASSYM(PC_KERNSLB, offsetof(struct pcpu, pc_slb)); ASSYM(PC_USERSLB, offsetof(struct pcpu, pc_userslb)); +ASSYM(USER_SLB_SLOT, USER_SLB_SLOT); +ASSYM(USER_SLB_SLBE, USER_SLB_SLBE); #else ASSYM(PM_SR, offsetof(struct pmap, pm_sr)); +ASSYM(USER_SR, USER_SR); #endif #elif defined(E500) ASSYM(PM_PDIR, offsetof(struct pmap, pm_pdir)); @@ -187,7 +189,6 @@ ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_FPU, PCB_FPU); ASSYM(PCB_VEC, PCB_VEC); -ASSYM(PCB_AIM_USR_ESID, offsetof(struct pcb, pcb_cpu.aim.usr_esid)); ASSYM(PCB_AIM_USR_VSID, offsetof(struct pcb, pcb_cpu.aim.usr_vsid)); ASSYM(PCB_BOOKE_CTR, offsetof(struct pcb, pcb_cpu.booke.ctr)); ASSYM(PCB_BOOKE_XER, offsetof(struct pcb, pcb_cpu.booke.xer)); diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index b34a07f..d12e110 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -1065,7 +1065,7 @@ pmap_pinit0(pmap_t pm) PMAP_LOCK_INIT(pm); for (i = 0; i < MAXCPU; i++) - pm->pm_context[i] = 0; + pm->pm_context[i] = TLB_CTX_KERNEL; pm->pm_active = 0; pm->pm_tsb = NULL; pm->pm_tsb_obj = NULL; @@ -1103,6 +1103,12 @@ pmap_pinit(pmap_t pm) if (pm->pm_tsb_obj == NULL) pm->pm_tsb_obj = vm_object_allocate(OBJT_PHYS, TSB_PAGES); + mtx_lock_spin(&sched_lock); + for (i = 0; i < MAXCPU; i++) + pm->pm_context[i] = -1; + pm->pm_active = 0; + mtx_unlock_spin(&sched_lock); + VM_OBJECT_LOCK(pm->pm_tsb_obj); for (i = 0; i < TSB_PAGES; i++) { m = vm_page_grab(pm->pm_tsb_obj, i, VM_ALLOC_NOBUSY | @@ -1114,9 +1120,6 @@ pmap_pinit(pmap_t pm) VM_OBJECT_UNLOCK(pm->pm_tsb_obj); pmap_qenter((vm_offset_t)pm->pm_tsb, ma, TSB_PAGES); - for (i = 0; i < MAXCPU; i++) - pm->pm_context[i] = -1; - pm->pm_active = 0; bzero(&pm->pm_stats, sizeof(pm->pm_stats)); return (1); } diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c index 82c24a5..84879d1 100644 --- a/sys/sparc64/sparc64/tick.c +++ b/sys/sparc64/sparc64/tick.c @@ -78,28 +78,69 @@ u_int tick_et_use_stick = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, tick_et_use_stick, CTLFLAG_RD, &tick_et_use_stick, 0, "tick event timer uses STICK instead of TICK"); +typedef uint64_t rd_tick_t(void); +static rd_tick_t *rd_tick; +typedef void wr_tick_cmpr_t(uint64_t); +static wr_tick_cmpr_t *wr_tick_cmpr; + static struct timecounter stick_tc; -static struct timecounter tick_tc; static struct eventtimer tick_et; +static struct timecounter tick_tc; -static uint64_t tick_cputicks(void); -static timecounter_get_t stick_get_timecount_up; #ifdef SMP static timecounter_get_t stick_get_timecount_mp; #endif -static timecounter_get_t tick_get_timecount_up; +static timecounter_get_t stick_get_timecount_up; +static rd_tick_t stick_rd; +static wr_tick_cmpr_t stick_wr_cmpr; +static int tick_et_start(struct eventtimer *et, struct bintime *first, + struct bintime *period); +static int tick_et_stop(struct eventtimer *et); #ifdef SMP static timecounter_get_t tick_get_timecount_mp; #endif -static int tick_et_start(struct eventtimer *et, - struct bintime *first, struct bintime *period); -static int tick_et_stop(struct eventtimer *et); +static timecounter_get_t tick_get_timecount_up; static void tick_intr(struct trapframe *tf); -static void tick_intr_bbwar(struct trapframe *tf); static inline void tick_process(struct trapframe *tf); -static inline void tick_process_periodic(struct trapframe *tf, u_long tick, - u_long tick_increment, u_long adj); -static void stick_intr(struct trapframe *tf); +static rd_tick_t tick_rd; +static wr_tick_cmpr_t tick_wr_cmpr; +static wr_tick_cmpr_t tick_wr_cmpr_bbwar; +static uint64_t tick_cputicks(void); + +static uint64_t +stick_rd(void) +{ + + return (rdstick()); +} + +static void +stick_wr_cmpr(uint64_t tick) +{ + + wrstickcmpr(tick, 0); +} + +static uint64_t +tick_rd(void) +{ + + return (rd(tick)); +} + +static void +tick_wr_cmpr(uint64_t tick_cmpr) +{ + + wr(tick_cmpr, tick_cmpr, 0); +} + +static void +tick_wr_cmpr_bbwar(uint64_t tick_cmpr) +{ + + wrtickcmpr(tick_cmpr, 0); +} static uint64_t tick_cputicks(void) @@ -128,17 +169,22 @@ cpu_initclocks(void) * frequencies they shouldn't be used except when really necessary. */ if (tick_et_use_stick != 0) { - intr_setup(PIL_TICK, stick_intr, -1, NULL, NULL); + rd_tick = stick_rd; + wr_tick_cmpr = stick_wr_cmpr; /* * We don't provide a CPU ticker as long as the frequency * supplied isn't actually used per-CPU. */ } else { - intr_setup(PIL_TICK, PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && - PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ? - tick_intr_bbwar : tick_intr, -1, NULL, NULL); + rd_tick = tick_rd; + if (PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && + PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII) + wr_tick_cmpr = tick_wr_cmpr_bbwar; + else + wr_tick_cmpr = tick_wr_cmpr; set_cputicker(tick_cputicks, clock, 0); } + intr_setup(PIL_TICK, tick_intr, -1, NULL, NULL); /* * Initialize the (S)TICK-based timecounter(s). @@ -214,106 +260,56 @@ tick_process(struct trapframe *tf) critical_exit(); } -/* - * NB: the sequence of reading the (S)TICK register, calculating the value - * of the next tick and writing it to the (S)TICK_COMPARE register must not - * be interrupted, not even by an IPI, otherwise a value that is in the past - * could be written in the worst case, causing the periodic timer to stop. - */ - static void tick_intr(struct trapframe *tf) { - u_long adj, tick, tick_increment; - register_t s; - - s = intr_disable(); - tick_increment = PCPU_GET(tickincrement); - if (tick_increment != 0) { - adj = PCPU_GET(tickadj); - tick = rd(tick); - wr(tick_cmpr, tick + tick_increment - adj, 0); - intr_restore(s); - tick_process_periodic(tf, tick, tick_increment, adj); - } else { - intr_restore(s); - tick_process(tf); - } -} - -static void -tick_intr_bbwar(struct trapframe *tf) -{ - u_long adj, tick, tick_increment; - register_t s; - - s = intr_disable(); - tick_increment = PCPU_GET(tickincrement); - if (tick_increment != 0) { - adj = PCPU_GET(tickadj); - tick = rd(tick); - wrtickcmpr(tick + tick_increment - adj, 0); - intr_restore(s); - tick_process_periodic(tf, tick, tick_increment, adj); - } else { - intr_restore(s); - tick_process(tf); - } -} - -static void -stick_intr(struct trapframe *tf) -{ - u_long adj, stick, tick_increment; + u_long adj, ref, tick, tick_increment; + long delta; register_t s; + int count; - s = intr_disable(); tick_increment = PCPU_GET(tickincrement); if (tick_increment != 0) { + /* + * NB: the sequence of reading the (S)TICK register, + * calculating the value of the next tick and writing it to + * the (S)TICK_COMPARE register must not be interrupted, not + * even by an IPI, otherwise a value that is in the past could + * be written in the worst case and thus causing the periodic + * timer to stop. + */ + s = intr_disable(); adj = PCPU_GET(tickadj); - stick = rdstick(); - wrstickcmpr(stick + tick_increment - adj, 0); + tick = rd_tick(); + wr_tick_cmpr(tick + tick_increment - adj); intr_restore(s); - tick_process_periodic(tf, stick, tick_increment, adj); - } else { - intr_restore(s); - tick_process(tf); - } -} - -static inline void -tick_process_periodic(struct trapframe *tf, u_long tick, - u_long tick_increment, u_long adj) -{ - u_long ref; - long delta; - int count; - - ref = PCPU_GET(tickref); - delta = tick - ref; - count = 0; - while (delta >= tick_increment) { - tick_process(tf); - delta -= tick_increment; - ref += tick_increment; - if (adj != 0) - adjust_ticks++; - count++; - } - if (count > 0) { - adjust_missed += count - 1; - if (delta > (tick_increment >> 3)) { - if (adj == 0) - adjust_edges++; - adj = tick_increment >> 4; - } else + ref = PCPU_GET(tickref); + delta = tick - ref; + count = 0; + while (delta >= tick_increment) { + tick_process(tf); + delta -= tick_increment; + ref += tick_increment; + if (adj != 0) + adjust_ticks++; + count++; + } + if (count > 0) { + adjust_missed += count - 1; + if (delta > (tick_increment >> 3)) { + if (adj == 0) + adjust_edges++; + adj = tick_increment >> 4; + } else + adj = 0; + } else { adj = 0; - } else { - adj = 0; - adjust_excess++; - } - PCPU_SET(tickref, ref); - PCPU_SET(tickadj, adj); + adjust_excess++; + } + PCPU_SET(tickref, ref); + PCPU_SET(tickadj, adj); + } else + tick_process(tf); } static u_int @@ -387,19 +383,13 @@ tick_et_start(struct eventtimer *et, struct bintime *first, * out one tick to make sure that it is not missed. */ s = intr_disable(); - if (tick_et_use_stick != 0) - base = rdstick(); - else - base = rd(tick); + base = rd_tick(); if (div != 0) { PCPU_SET(tickadj, 0); base = roundup(base, div); } PCPU_SET(tickref, base); - if (tick_et_use_stick != 0) - wrstickcmpr(base + fdiv, 0); - else - wrtickcmpr(base + fdiv, 0); + wr_tick_cmpr(base + fdiv); intr_restore(s); return (0); } diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index d7c1d0d..9c89689 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -72,7 +72,8 @@ static int ufs_mindirhashsize = DIRBLKSIZ * 5; SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_minsize, CTLFLAG_RW, &ufs_mindirhashsize, 0, "minimum directory size in bytes for which to use hashed lookup"); -static int ufs_dirhashmaxmem = 2 * 1024 * 1024; +static int ufs_dirhashmaxmem = 2 * 1024 * 1024; /* NOTE: initial value. It is + tuned in ufsdirhash_init() */ SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_maxmem, CTLFLAG_RW, &ufs_dirhashmaxmem, 0, "maximum allowed dirhash memory usage"); static int ufs_dirhashmem; @@ -1290,6 +1291,9 @@ ufsdirhash_lowmem() void ufsdirhash_init() { + ufs_dirhashmaxmem = lmax(roundup(hibufspace / 64, PAGE_SIZE), + 2 * 1024 * 1024); + ufsdirhash_zone = uma_zcreate("DIRHASH", DH_NBLKOFF * sizeof(doff_t), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mtx_init(&ufsdirhash_mtx, "dirhash list", NULL, MTX_DEF); diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c index 26e4981..16b6747 100644 --- a/sys/vm/vm_phys.c +++ b/sys/vm/vm_phys.c @@ -137,11 +137,11 @@ sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS) sbuf_printf(&sbuf, "-- -- "); sbuf_printf(&sbuf, "--\n"); for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { - sbuf_printf(&sbuf, " %2.2d (%6.6dK)", oind, + sbuf_printf(&sbuf, " %2d (%6dK)", oind, 1 << (PAGE_SHIFT - 10 + oind)); for (pind = 0; pind < VM_NFREEPOOL; pind++) { fl = vm_phys_free_queues[flind][pind]; - sbuf_printf(&sbuf, " | %6.6d", fl[oind].lcnt); + sbuf_printf(&sbuf, " | %6d", fl[oind].lcnt); } sbuf_printf(&sbuf, "\n"); } diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c index aa8e80f..423bb31 100644 --- a/sys/vm/vm_reserv.c +++ b/sys/vm/vm_reserv.c @@ -193,7 +193,7 @@ sysctl_vm_reserv_partpopq(SYSCTL_HANDLER_ARGS) unused_pages += VM_LEVEL_0_NPAGES - rv->popcnt; } mtx_unlock(&vm_page_queue_free_mtx); - sbuf_printf(&sbuf, "%5.5d: %6.6dK, %6.6d\n", level, + sbuf_printf(&sbuf, "%5d: %6dK, %6d\n", level, unused_pages * (PAGE_SIZE / 1024), counter); } error = sbuf_finish(&sbuf); diff --git a/sys/amd64/include/apicreg.h b/sys/x86/include/apicreg.h index fee629b..00cb571 100644 --- a/sys/amd64/include/apicreg.h +++ b/sys/x86/include/apicreg.h @@ -25,8 +25,8 @@ * $FreeBSD$ */ -#ifndef _MACHINE_APICREG_H_ -#define _MACHINE_APICREG_H_ +#ifndef _X86_APICREG_H_ +#define _X86_APICREG_H_ /* * Local && I/O APIC definitions. @@ -442,4 +442,4 @@ typedef struct IOAPIC ioapic_t; #define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */ -#endif /* _MACHINE_APICREG_H_ */ +#endif /* _X86_APICREG_H_ */ diff --git a/sys/amd64/include/mca.h b/sys/x86/include/mca.h index dd6e69c..9322737 100644 --- a/sys/amd64/include/mca.h +++ b/sys/x86/include/mca.h @@ -27,8 +27,8 @@ * $FreeBSD$ */ -#ifndef __MACHINE_MCA_H__ -#define __MACHINE_MCA_H__ +#ifndef __X86_MCA_H__ +#define __X86_MCA_H__ struct mca_record { uint64_t mr_status; @@ -53,4 +53,4 @@ void mca_resume(void); #endif -#endif /* !__MACHINE_MCA_H__ */ +#endif /* !__X86_MCA_H__ */ diff --git a/sys/amd64/amd64/dump_machdep.c b/sys/x86/x86/dump_machdep.c index a62f1e4..d0a7612 100644 --- a/sys/amd64/amd64/dump_machdep.c +++ b/sys/x86/x86/dump_machdep.c @@ -39,6 +39,14 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> #include <machine/md_var.h> +#ifdef __amd64__ +#define KERNELDUMP_VERSION KERNELDUMP_AMD64_VERSION +#define EM_VALUE EM_X86_64 +#else +#define KERNELDUMP_VERSION KERNELDUMP_I386_VERSION +#define EM_VALUE EM_386 +#endif + CTASSERT(sizeof(struct kerneldumpheader) == 512); int do_minidump = 1; @@ -168,7 +176,8 @@ cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) if (maxdumppgs == 0) /* seatbelt */ maxdumppgs = 1; - printf(" chunk %d: %ldMB (%ld pages)", seqnr, PG2MB(pgs), pgs); + printf(" chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs), + (uintmax_t)pgs); while (pgs) { chunk = pgs; @@ -177,7 +186,7 @@ cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) sz = chunk << PAGE_SHIFT; counter += sz; if (counter >> 24) { - printf(" %ld", PG2MB(pgs)); + printf(" %ju", (uintmax_t)PG2MB(pgs)); counter &= (1<<24) - 1; } for (i = 0; i < chunk; i++) { @@ -279,7 +288,7 @@ dumpsys(struct dumperinfo *di) ehdr.e_ident[EI_VERSION] = EV_CURRENT; ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */ ehdr.e_type = ET_CORE; - ehdr.e_machine = EM_X86_64; + ehdr.e_machine = EM_VALUE; ehdr.e_phoff = sizeof(ehdr); ehdr.e_flags = 0; ehdr.e_ehsize = sizeof(ehdr); @@ -304,7 +313,8 @@ dumpsys(struct dumperinfo *di) dumplo = di->mediaoffset + di->mediasize - dumpsize; dumplo -= sizeof(kdh) * 2; - mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, dumpsize, di->blocksize); + mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize, + di->blocksize); printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20, ehdr.e_phnum); diff --git a/sys/x86/x86/io_apic.c b/sys/x86/x86/io_apic.c index 4468486..da97def 100644 --- a/sys/x86/x86/io_apic.c +++ b/sys/x86/x86/io_apic.c @@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 6c72d28..63a6843 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -54,13 +54,13 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/cpu.h> #include <machine/cputypes.h> #include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/smp.h> #include <machine/specialreg.h> diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index a5567e0..5ee090b 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <machine/intr_machdep.h> #include <machine/apicvar.h> #include <machine/cputypes.h> -#include <machine/mca.h> +#include <x86/mca.h> #include <machine/md_var.h> #include <machine/specialreg.h> diff --git a/sys/i386/i386/mptable.c b/sys/x86/x86/mptable.c index dccb64b..cad83a2 100644 --- a/sys/i386/i386/mptable.c +++ b/sys/x86/x86/mptable.c @@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <vm/pmap.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/apicvar.h> @@ -51,7 +51,11 @@ __FBSDID("$FreeBSD$"); /* string defined by the Intel MP Spec as identifying the MP table */ #define MP_SIG 0x5f504d5f /* _MP_ */ +#ifdef __amd64__ +#define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */ +#else #define MAX_LAPIC_ID 31 /* Max local APIC ID for HTT fixup */ +#endif #ifdef PC98 #define BIOS_BASE (0xe8000) diff --git a/sys/amd64/amd64/mptable_pci.c b/sys/x86/x86/mptable_pci.c index 47a666d..47a666d 100644 --- a/sys/amd64/amd64/mptable_pci.c +++ b/sys/x86/x86/mptable_pci.c diff --git a/sys/x86/x86/msi.c b/sys/x86/x86/msi.c index 428894e..381f097 100644 --- a/sys/x86/x86/msi.c +++ b/sys/x86/x86/msi.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/sx.h> #include <sys/systm.h> -#include <machine/apicreg.h> +#include <x86/apicreg.h> #include <machine/cputypes.h> #include <machine/md_var.h> #include <machine/frame.h> diff --git a/sys/i386/i386/nexus.c b/sys/x86/x86/nexus.c index ec87528..c343730 100644 --- a/sys/i386/i386/nexus.c +++ b/sys/x86/x86/nexus.c @@ -41,13 +41,18 @@ __FBSDID("$FreeBSD$"); * and I/O memory address space. */ +#ifdef __amd64__ +#define DEV_APIC +#else #include "opt_apic.h" +#endif #include "opt_isa.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/linker.h> #include <sys/malloc.h> #include <sys/module.h> #include <machine/bus.h> @@ -60,8 +65,10 @@ __FBSDID("$FreeBSD$"); #include <vm/pmap.h> #include <machine/pmap.h> +#include <machine/metadata.h> #include <machine/nexusvar.h> #include <machine/resource.h> +#include <machine/pc/bios.h> #ifdef DEV_APIC #include "pcib_if.h" @@ -77,6 +84,16 @@ __FBSDID("$FreeBSD$"); #endif #include <sys/rtprio.h> +#ifdef __amd64__ +#define BUS_SPACE_IO AMD64_BUS_SPACE_IO +#define BUS_SPACE_MEM AMD64_BUS_SPACE_MEM +#else +#define BUS_SPACE_IO I386_BUS_SPACE_IO +#define BUS_SPACE_MEM I386_BUS_SPACE_MEM +#endif + +#define ELF_KERN_STR ("elf"__XSTRING(__ELF_WORD_SIZE)" kernel") + static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) @@ -416,7 +433,7 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid, #else rman_set_bushandle(r, rman_get_start(r)); #endif - rman_set_bustag(r, I386_BUS_SPACE_IO); + rman_set_bustag(r, BUS_SPACE_IO); break; case SYS_RES_MEMORY: #ifdef PC98 @@ -427,7 +444,7 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid, #endif vaddr = pmap_mapdev(rman_get_start(r), rman_get_size(r)); rman_set_virtual(r, vaddr); - rman_set_bustag(r, I386_BUS_SPACE_MEM); + rman_set_bustag(r, BUS_SPACE_MEM); #ifdef PC98 /* PC-98: the type of bus_space_handle_t is the structure. */ bh->bsh_base = (bus_addr_t) vaddr; @@ -652,10 +669,46 @@ ram_probe(device_t dev) static int ram_attach(device_t dev) { + struct bios_smap *smapbase, *smap, *smapend; struct resource *res; vm_paddr_t *p; + caddr_t kmdp; + uint32_t smapsize; int error, i, rid; + /* Retrieve the system memory map from the loader. */ + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type(ELF_KERN_STR); + if (kmdp != NULL) + smapbase = (struct bios_smap *)preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_SMAP); + else + smapbase = NULL; + if (smapbase != NULL) { + smapsize = *((u_int32_t *)smapbase - 1); + smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize); + + rid = 0; + for (smap = smapbase; smap < smapend; smap++) { + if (smap->type != SMAP_TYPE_MEMORY || + smap->length == 0) + continue; + error = bus_set_resource(dev, SYS_RES_MEMORY, rid, + smap->base, smap->length); + if (error) + panic("ram_attach: resource %d failed set with %d", + rid, error); + res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + 0); + if (res == NULL) + panic("ram_attach: resource %d failed to attach", + rid); + rid++; + } + return (0); + } + /* * We use the dump_avail[] array rather than phys_avail[] for * the memory map as phys_avail[] contains holes for kernel |