diff options
author | attilio <attilio@FreeBSD.org> | 2012-07-12 02:15:06 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2012-07-12 02:15:06 +0000 |
commit | cc7c02f8bf91a669b803d07125980d38f96161f8 (patch) | |
tree | a8be73b1e54943d7b641db517dd1279f6f8a7510 /sys | |
parent | a23ed68137cccbe53a9340dbc1de0779d2518589 (diff) | |
parent | 675a214708d3e1fb79cbcf6bd8a46e0f1cc4823d (diff) | |
download | FreeBSD-src-cc7c02f8bf91a669b803d07125980d38f96161f8.zip FreeBSD-src-cc7c02f8bf91a669b803d07125980d38f96161f8.tar.gz |
Merge from vmcontention
Diffstat (limited to 'sys')
152 files changed, 3717 insertions, 1855 deletions
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 77e11bc..ca951ad 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -73,10 +73,6 @@ __FBSDID("$FreeBSD$"); #define fxrstor(addr) __asm __volatile("fxrstor %0" : : "m" (*(addr))) #define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr))) #define ldmxcsr(csr) __asm __volatile("ldmxcsr %0" : : "m" (csr)) -#define start_emulating() __asm __volatile( \ - "smsw %%ax; orb %0,%%al; lmsw %%ax" \ - : : "n" (CR0_TS) : "ax") -#define stop_emulating() __asm __volatile("clts") static __inline void xrstor(char *addr, uint64_t mask) @@ -109,13 +105,14 @@ void fnstsw(caddr_t addr); void fxsave(caddr_t addr); void fxrstor(caddr_t addr); void ldmxcsr(u_int csr); -void start_emulating(void); -void stop_emulating(void); void xrstor(char *addr, uint64_t mask); void xsave(char *addr, uint64_t mask); #endif /* __GNUCLIKE_ASM && !lint */ +#define start_emulating() load_cr0(rcr0() | CR0_TS) +#define stop_emulating() clts() + #define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_cw) #define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_sw) diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 9580d79..8044fe5 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/memrange.h> #include <sys/msgbuf.h> #include <sys/mutex.h> #include <sys/pcpu.h> @@ -206,6 +207,8 @@ struct pcpu __pcpu[MAXCPU]; struct mtx icu_lock; +struct mem_range_softc mem_range_softc; + struct mtx dt_lock; /* lock for GDT and LDT */ static void diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c index b86f5dd..abbbb21 100644 --- a/sys/amd64/amd64/mem.c +++ b/sys/amd64/amd64/mem.c @@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$"); */ MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors"); -struct mem_range_softc mem_range_softc; - /* ARGSUSED */ int memrw(struct cdev *dev, struct uio *uio, int flags) diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 829efc1..94d4133 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -107,6 +107,13 @@ clflush(u_long addr) } static __inline void +clts(void) +{ + + __asm __volatile("clts"); +} + +static __inline void disable_intr(void) { __asm __volatile("cli" : : : "memory"); @@ -702,6 +709,9 @@ intr_restore(register_t rflags) int breakpoint(void); u_int bsfl(u_int mask); u_int bsrl(u_int mask); +void clflush(u_long addr); +void clts(void); +void cpuid_count(u_int ax, u_int cx, u_int *p); void disable_intr(void); void do_cpuid(u_int ax, u_int *p); void enable_intr(void); diff --git a/sys/arm/at91/at91.c b/sys/arm/at91/at91.c index 877b746..da3aa72 100644 --- a/sys/arm/at91/at91.c +++ b/sys/arm/at91/at91.c @@ -270,10 +270,12 @@ at91_attach(device_t dev) } - /* Our device list will be added automatically by the cpu device + /* + * Our device list will be added automatically by the cpu device * e.g. at91rm9200.c when it is identified. To ensure that the * CPU and PMC are attached first any other "identified" devices - * call BUS_ADD_CHILD(9) with an "order" of at least 2. */ + * call BUS_ADD_CHILD(9) with an "order" of at least 2. + */ bus_generic_probe(dev); bus_generic_attach(dev); @@ -363,7 +365,7 @@ at91_setup_intr(device_t dev, device_t child, struct at91_softc *sc = device_get_softc(dev); int error; - if (rman_get_start(ires) == sc->sc_irq_system && filt == NULL) + if (rman_get_start(ires) == AT91_IRQ_SYSTEM && filt == NULL) panic("All system interrupt ISRs must be FILTER"); error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, intr, arg, cookiep); @@ -471,6 +473,41 @@ at91_eoi(void *unused) IC_EOICR, 0); } +void +at91_add_child(device_t dev, int prio, const char *name, int unit, + bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) +{ + device_t kid; + struct at91_ivar *ivar; + + kid = device_add_child_ordered(dev, prio, name, unit); + if (kid == NULL) { + printf("Can't add child %s%d ordered\n", name, unit); + return; + } + ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); + if (ivar == NULL) { + device_delete_child(dev, kid); + printf("Can't add alloc ivar\n"); + return; + } + device_set_ivars(kid, ivar); + resource_list_init(&ivar->resources); + if (irq0 != -1) { + bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); + if (irq0 != AT91_IRQ_SYSTEM) + at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); + } + if (irq1 != 0) + bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); + if (irq2 != 0) + bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); + if (addr != 0 && addr < AT91_BASE) + addr += AT91_BASE; + if (addr != 0) + bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); +} + static device_method_t at91_methods[] = { DEVMETHOD(device_probe, at91_probe), DEVMETHOD(device_attach, at91_attach), diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index 23732ef..0bb79bd 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -90,6 +90,8 @@ __FBSDID("$FreeBSD$"); #include <arm/at91/at91board.h> #include <arm/at91/at91var.h> +#include <arm/at91/at91soc.h> +#include <arm/at91/at91_usartreg.h> #include <arm/at91/at91rm92reg.h> #include <arm/at91/at91sam9g20reg.h> @@ -115,10 +117,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -126,7 +124,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; @@ -282,7 +279,7 @@ static const char *soc_subtype_name[] = { [AT91_ST_SAM9X35] = "at91sam9x35", }; -struct at91_soc_info soc_data; +struct at91_soc_info soc_info; /* * Read the SoC ID from the CIDR register and try to match it against the @@ -295,103 +292,117 @@ at91_try_id(uint32_t dbgu_base) { uint32_t socid; - soc_data.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base + + soc_info.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base + DBGU_C1R); - socid = soc_data.cidr & ~AT91_CPU_VERSION_MASK; + socid = soc_info.cidr & ~AT91_CPU_VERSION_MASK; - soc_data.type = AT91_T_NONE; - soc_data.subtype = AT91_ST_NONE; - soc_data.family = (soc_data.cidr & AT91_CPU_FAMILY_MASK) >> 20; - soc_data.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base + + soc_info.type = AT91_T_NONE; + soc_info.subtype = AT91_ST_NONE; + soc_info.family = (soc_info.cidr & AT91_CPU_FAMILY_MASK) >> 20; + soc_info.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base + DBGU_C2R); switch (socid) { case AT91_CPU_CAP9: - soc_data.type = AT91_T_CAP9; + soc_info.type = AT91_T_CAP9; break; case AT91_CPU_RM9200: - soc_data.type = AT91_T_RM9200; + soc_info.type = AT91_T_RM9200; break; case AT91_CPU_SAM9XE128: case AT91_CPU_SAM9XE256: case AT91_CPU_SAM9XE512: case AT91_CPU_SAM9260: - soc_data.type = AT91_T_SAM9260; - if (soc_data.family == AT91_FAMILY_SAM9XE) - soc_data.subtype = AT91_ST_SAM9XE; + soc_info.type = AT91_T_SAM9260; + if (soc_info.family == AT91_FAMILY_SAM9XE) + soc_info.subtype = AT91_ST_SAM9XE; break; case AT91_CPU_SAM9261: - soc_data.type = AT91_T_SAM9261; + soc_info.type = AT91_T_SAM9261; break; case AT91_CPU_SAM9263: - soc_data.type = AT91_T_SAM9263; + soc_info.type = AT91_T_SAM9263; break; case AT91_CPU_SAM9G10: - soc_data.type = AT91_T_SAM9G10; + soc_info.type = AT91_T_SAM9G10; break; case AT91_CPU_SAM9G20: - soc_data.type = AT91_T_SAM9G20; + soc_info.type = AT91_T_SAM9G20; break; case AT91_CPU_SAM9G45: - soc_data.type = AT91_T_SAM9G45; + soc_info.type = AT91_T_SAM9G45; break; case AT91_CPU_SAM9N12: - soc_data.type = AT91_T_SAM9N12; + soc_info.type = AT91_T_SAM9N12; break; case AT91_CPU_SAM9RL64: - soc_data.type = AT91_T_SAM9RL; + soc_info.type = AT91_T_SAM9RL; break; case AT91_CPU_SAM9X5: - soc_data.type = AT91_T_SAM9X5; + soc_info.type = AT91_T_SAM9X5; break; default: return (0); } - switch (soc_data.type) { + switch (soc_info.type) { case AT91_T_SAM9G45: - switch (soc_data.exid) { + switch (soc_info.exid) { case AT91_EXID_SAM9G45: - soc_data.subtype = AT91_ST_SAM9G45; + soc_info.subtype = AT91_ST_SAM9G45; break; case AT91_EXID_SAM9G46: - soc_data.subtype = AT91_ST_SAM9G46; + soc_info.subtype = AT91_ST_SAM9G46; break; case AT91_EXID_SAM9M10: - soc_data.subtype = AT91_ST_SAM9M10; + soc_info.subtype = AT91_ST_SAM9M10; break; case AT91_EXID_SAM9M11: - soc_data.subtype = AT91_ST_SAM9M11; + soc_info.subtype = AT91_ST_SAM9M11; break; } break; case AT91_T_SAM9X5: - switch (soc_data.exid) { + switch (soc_info.exid) { case AT91_EXID_SAM9G15: - soc_data.subtype = AT91_ST_SAM9G15; + soc_info.subtype = AT91_ST_SAM9G15; break; case AT91_EXID_SAM9G25: - soc_data.subtype = AT91_ST_SAM9G25; + soc_info.subtype = AT91_ST_SAM9G25; break; case AT91_EXID_SAM9G35: - soc_data.subtype = AT91_ST_SAM9G35; + soc_info.subtype = AT91_ST_SAM9G35; break; case AT91_EXID_SAM9X25: - soc_data.subtype = AT91_ST_SAM9X25; + soc_info.subtype = AT91_ST_SAM9X25; break; case AT91_EXID_SAM9X35: - soc_data.subtype = AT91_ST_SAM9X35; + soc_info.subtype = AT91_ST_SAM9X35; break; } break; default: break; } - snprintf(soc_data.name, sizeof(soc_data.name), "%s%s%s", - soc_type_name[soc_data.type], - soc_data.subtype == AT91_ST_NONE ? "" : " subtype ", - soc_data.subtype == AT91_ST_NONE ? "" : - soc_subtype_name[soc_data.subtype]); + /* + * Disable interrupts in the DBGU unit... + */ + *(volatile uint32_t *)(AT91_BASE + dbgu_base + USART_IDR) = 0xffffffff; + + /* + * Save the name for later... + */ + snprintf(soc_info.name, sizeof(soc_info.name), "%s%s%s", + soc_type_name[soc_info.type], + soc_info.subtype == AT91_ST_NONE ? "" : " subtype ", + soc_info.subtype == AT91_ST_NONE ? "" : + soc_subtype_name[soc_info.subtype]); + + /* + * try to get the matching CPU support. + */ + soc_info.soc_data = at91_match_soc(soc_info.type, soc_info.subtype); + return (1); } @@ -544,6 +555,9 @@ initarm(struct arm_boot_params *abp) cninit(); + if (soc_info.soc_data == NULL) + printf("Warning: No soc support for %s found.\n", soc_info.name); + memsize = board_init(); physmem = memsize / PAGE_SIZE; @@ -633,16 +647,16 @@ void DELAY(int n) { - if (soc_data.delay) - soc_data.delay(n); + if (soc_info.soc_data) + soc_info.soc_data->soc_delay(n); } void cpu_reset(void) { - if (soc_data.reset) - soc_data.reset(); + if (soc_info.soc_data) + soc_info.soc_data->soc_reset(); while (1) continue; } diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index f69477e..196aa64 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -313,7 +313,7 @@ static int at91_mci_is_mci1rev2xx(void) { - switch (soc_data.type) { + switch (soc_info.type) { case AT91_T_SAM9260: case AT91_T_SAM9263: case AT91_T_CAP9: diff --git a/sys/arm/at91/at91_pit.c b/sys/arm/at91/at91_pit.c index 2a9656a..853dddc 100644 --- a/sys/arm/at91/at91_pit.c +++ b/sys/arm/at91/at91_pit.c @@ -59,7 +59,7 @@ static struct pit_softc { } *sc; static uint32_t timecount = 0; -static unsigned at91pit_get_timecount(struct timecounter *tc); +static unsigned at91_pit_get_timecount(struct timecounter *tc); static int pit_intr(void *arg); static inline uint32_t @@ -76,8 +76,8 @@ WR4(struct pit_softc *sc, bus_size_t off, uint32_t val) bus_write_4(sc->mem_res, off, val); } -static void -at91pit_delay(int us) +void +at91_pit_delay(int us) { int32_t cnt, last, piv; uint64_t pit_freq; @@ -99,8 +99,8 @@ at91pit_delay(int us) } } -static struct timecounter at91pit_timecounter = { - at91pit_get_timecount, /* get_timecount */ +static struct timecounter at91_pit_timecounter = { + at91_pit_get_timecount, /* get_timecount */ NULL, /* no poll_pps */ 0xffffffff, /* counter mask */ 0 / PIT_PRESCALE, /* frequency */ @@ -109,7 +109,7 @@ static struct timecounter at91pit_timecounter = { }; static int -at91pit_probe(device_t dev) +at91_pit_probe(device_t dev) { device_set_desc(dev, "AT91SAM9 PIT"); @@ -117,7 +117,7 @@ at91pit_probe(device_t dev) } static int -at91pit_attach(device_t dev) +at91_pit_attach(device_t dev) { void *ih; int rid, err = 0; @@ -148,32 +148,31 @@ at91pit_attach(device_t dev) err = bus_setup_intr(dev, irq, INTR_TYPE_CLK, pit_intr, NULL, NULL, &ih); - at91pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE; - tc_init(&at91pit_timecounter); + at91_pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE; + tc_init(&at91_pit_timecounter); /* Enable the PIT here. */ WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) | PIT_EN | PIT_IEN); - soc_data.delay = at91pit_delay; out: return (err); } -static device_method_t at91pit_methods[] = { - DEVMETHOD(device_probe, at91pit_probe), - DEVMETHOD(device_attach, at91pit_attach), +static device_method_t at91_pit_methods[] = { + DEVMETHOD(device_probe, at91_pit_probe), + DEVMETHOD(device_attach, at91_pit_attach), DEVMETHOD_END }; -static driver_t at91pit_driver = { +static driver_t at91_pit_driver = { "at91_pit", - at91pit_methods, + at91_pit_methods, sizeof(struct pit_softc), }; -static devclass_t at91pit_devclass; +static devclass_t at91_pit_devclass; -DRIVER_MODULE(at91_pit, atmelarm, at91pit_driver, at91pit_devclass, NULL, +DRIVER_MODULE(at91_pit, atmelarm, at91_pit_driver, at91_pit_devclass, NULL, NULL); static int @@ -195,7 +194,7 @@ pit_intr(void *arg) } static unsigned -at91pit_get_timecount(struct timecounter *tc) +at91_pit_get_timecount(struct timecounter *tc) { uint32_t piir, icnt; diff --git a/sys/arm/at91/at91_pitreg.h b/sys/arm/at91/at91_pitreg.h index 7817c22..5e87e39 100644 --- a/sys/arm/at91/at91_pitreg.h +++ b/sys/arm/at91/at91_pitreg.h @@ -25,8 +25,8 @@ /* $FreeBSD$ */ -#ifndef ARM_AT91_AT91PITREG_H -#define ARM_AT91_AT91PITREG_H +#ifndef ARM_AT91_AT91_PITREG_H +#define ARM_AT91_AT91_PITREG_H #define PIT_MR 0x0 #define PIT_SR 0x4 @@ -42,4 +42,6 @@ /* PIT_SR */ #define PIT_PITS_DONE 1 /* interrupt done */ -#endif /* ARM_AT91_AT91PITREG_H */ +void at91_pit_delay(int us); + +#endif /* ARM_AT91_AT91_PITREG_H */ diff --git a/sys/arm/at91/at91_reset.S b/sys/arm/at91/at91_reset.S index 6ff7da0..28703cc 100644 --- a/sys/arm/at91/at91_reset.S +++ b/sys/arm/at91/at91_reset.S @@ -1,13 +1,14 @@ #include <machine/asm.h> #include <arm/at91/at91_rstreg.h> +#include <arm/at91/at91reg.h> #include <arm/at91/at91sam9g20reg.h> __FBSDID("$FreeBSD$"); -#define SDRAM_TR (AT91SAM9G20_BASE + \ +#define SDRAM_TR (AT91_BASE + \ AT91SAM9G20_SDRAMC_BASE + AT91SAM9G20_SDRAMC_TR) -#define SDRAM_LPR (AT91SAM9G20_BASE + \ +#define SDRAM_LPR (AT91_BASE + \ AT91SAM9G20_SDRAMC_BASE + AT91SAM9G20_SDRAMC_LPR) -#define RSTC_RCR (AT91SAM9G20_BASE + \ +#define RSTC_RCR (AT91_BASE + \ AT91SAM9G20_RSTC_BASE + RST_CR) /* diff --git a/sys/arm/at91/at91_rst.c b/sys/arm/at91/at91_rst.c index dbd041b..0879072 100644 --- a/sys/arm/at91/at91_rst.c +++ b/sys/arm/at91/at91_rst.c @@ -42,26 +42,26 @@ __FBSDID("$FreeBSD$"); #define RST_TIMEOUT (5) /* Seconds to hold NRST for hard reset */ #define RST_TICK (20) /* sample NRST at hz/RST_TICK intervals */ -static int at91rst_intr(void *arg); +static int at91_rst_intr(void *arg); -static struct at91rst_softc { +static struct at91_rst_softc { struct resource *mem_res; /* Memory resource */ struct resource *irq_res; /* IRQ resource */ void *intrhand; /* Interrupt handle */ struct callout tick_ch; /* Tick callout */ device_t sc_dev; u_int shutdown; /* Shutdown in progress */ -} *at91rst_sc; +} *at91_rst_sc; static inline uint32_t -RD4(struct at91rst_softc *sc, bus_size_t off) +RD4(struct at91_rst_softc *sc, bus_size_t off) { return (bus_read_4(sc->mem_res, off)); } static inline void -WR4(struct at91rst_softc *sc, bus_size_t off, uint32_t val) +WR4(struct at91_rst_softc *sc, bus_size_t off, uint32_t val) { bus_write_4(sc->mem_res, off, val); @@ -70,17 +70,17 @@ WR4(struct at91rst_softc *sc, bus_size_t off, uint32_t val) void cpu_reset_sam9g20(void) __attribute__((weak)); void cpu_reset_sam9g20(void) {} -static void -at91rst_cpu_reset(void) +void +at91_rst_cpu_reset(void) { - if (at91rst_sc) { + if (at91_rst_sc) { cpu_reset_sam9g20(); /* May be null */ - WR4(at91rst_sc, RST_MR, + WR4(at91_rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSTEN | RST_MR_KEY); - WR4(at91rst_sc, RST_CR, + WR4(at91_rst_sc, RST_CR, RST_CR_PROCRST | RST_CR_PERRST | RST_CR_EXTRST | @@ -91,7 +91,7 @@ at91rst_cpu_reset(void) } static int -at91rst_probe(device_t dev) +at91_rst_probe(device_t dev) { device_set_desc(dev, "AT91SAM9 Reset Controller"); @@ -99,13 +99,13 @@ at91rst_probe(device_t dev) } static int -at91rst_attach(device_t dev) +at91_rst_attach(device_t dev) { - struct at91rst_softc *sc; + struct at91_rst_softc *sc; const char *cause; int rid, err; - at91rst_sc = sc = device_get_softc(dev); + at91_rst_sc = sc = device_get_softc(dev); sc->sc_dev = dev; callout_init(&sc->tick_ch, 0); @@ -129,11 +129,11 @@ at91rst_attach(device_t dev) /* Activate the interrupt. */ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, - at91rst_intr, NULL, sc, &sc->intrhand); + at91_rst_intr, NULL, sc, &sc->intrhand); if (err) device_printf(dev, "could not establish interrupt handler.\n"); - WR4(at91rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSIEN | RST_MR_KEY); + WR4(at91_rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSIEN | RST_MR_KEY); switch (RD4(sc, RST_SR) & RST_SR_RST_MASK) { case RST_SR_RST_POW: @@ -157,15 +157,14 @@ at91rst_attach(device_t dev) } device_printf(dev, "Reset cause: %s.\n", cause); - soc_data.reset = at91rst_cpu_reset; out: return (err); } static void -at91rst_tick(void *argp) +at91_rst_tick(void *argp) { - struct at91rst_softc *sc = argp; + struct at91_rst_softc *sc = argp; if (sc->shutdown++ >= RST_TIMEOUT * RST_TICK) { /* User released the button in morre than RST_TIMEOUT */ @@ -176,36 +175,36 @@ at91rst_tick(void *argp) device_printf(sc->sc_dev, "shutting down...\n"); shutdown_nice(0); } else { - callout_reset(&sc->tick_ch, hz/RST_TICK, at91rst_tick, sc); + callout_reset(&sc->tick_ch, hz/RST_TICK, at91_rst_tick, sc); } } static int -at91rst_intr(void *argp) +at91_rst_intr(void *argp) { - struct at91rst_softc *sc = argp; + struct at91_rst_softc *sc = argp; if (RD4(sc, RST_SR) & RST_SR_URSTS) { if (sc->shutdown == 0) - callout_reset(&sc->tick_ch, hz/RST_TICK, at91rst_tick, sc); + callout_reset(&sc->tick_ch, hz/RST_TICK, at91_rst_tick, sc); return (FILTER_HANDLED); } return (FILTER_STRAY); } -static device_method_t at91rst_methods[] = { - DEVMETHOD(device_probe, at91rst_probe), - DEVMETHOD(device_attach, at91rst_attach), +static device_method_t at91_rst_methods[] = { + DEVMETHOD(device_probe, at91_rst_probe), + DEVMETHOD(device_attach, at91_rst_attach), DEVMETHOD_END }; -static driver_t at91rst_driver = { +static driver_t at91_rst_driver = { "at91_rst", - at91rst_methods, - sizeof(struct at91rst_softc), + at91_rst_methods, + sizeof(struct at91_rst_softc), }; -static devclass_t at91rst_devclass; +static devclass_t at91_rst_devclass; -DRIVER_MODULE(at91_rst, atmelarm, at91rst_driver, at91rst_devclass, NULL, +DRIVER_MODULE(at91_rst, atmelarm, at91_rst_driver, at91_rst_devclass, NULL, NULL); diff --git a/sys/arm/at91/at91_rstreg.h b/sys/arm/at91/at91_rstreg.h index f075b2c..ee64f14 100644 --- a/sys/arm/at91/at91_rstreg.h +++ b/sys/arm/at91/at91_rstreg.h @@ -25,8 +25,8 @@ /* $FreeBSD$ */ -#ifndef ARM_AT91_AT91RSTREG_H -#define ARM_AT91_AT91RSTREG_H +#ifndef ARM_AT91_AT91_RSTREG_H +#define ARM_AT91_AT91_RSTREG_H #define RST_CR 0x0 /* Control Register */ #define RST_SR 0x4 /* Status Register */ @@ -56,4 +56,8 @@ #define RST_MR_ERSTL(x) ((x)<<8) /* External reset length */ #define RST_MR_KEY (0xa5<<24) -#endif /* ARM_AT91_AT91RSTREG_H */ +#ifndef __ASSEMBLER__ +void at91_rst_cpu_reset(void); +#endif + +#endif /* ARM_AT91_AT91_RSTREG_H */ diff --git a/sys/arm/at91/at91_st.c b/sys/arm/at91/at91_st.c index 6a3284e..a18be2e 100644 --- a/sys/arm/at91/at91_st.c +++ b/sys/arm/at91/at91_st.c @@ -43,24 +43,45 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <machine/frame.h> #include <machine/intr.h> -#include <arm/at91/at91rm92reg.h> #include <arm/at91/at91var.h> #include <arm/at91/at91_streg.h> +#include <arm/at91/at91rm92reg.h> -static struct at91st_softc { - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - device_t sc_dev; +static struct at91_st_softc { + struct resource * sc_irq_res; + struct resource * sc_mem_res; + void * sc_intrhand; eventhandler_tag sc_wet; /* watchdog event handler tag */ } *timer_softc; -#define RD4(off) \ - bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh, (off)) -#define WR4(off, val) \ - bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, (off), (val)) +static inline uint32_t +RD4(bus_size_t off) +{ + + if (timer_softc == NULL) { + uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off); + + return *p; + } + + return (bus_read_4(timer_softc->sc_mem_res, off)); +} + +static inline void +WR4(bus_size_t off, uint32_t val) +{ + + if (timer_softc == NULL) { + uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off); + + *p = val; + } + else + bus_write_4(timer_softc->sc_mem_res, off, val); +} -static void at91st_watchdog(void *, u_int, int *); -static void at91st_initclocks(struct at91st_softc *); +static void at91_st_watchdog(void *, u_int, int *); +static void at91_st_initclocks(device_t , struct at91_st_softc *); static inline int st_crtr(void) @@ -73,10 +94,10 @@ st_crtr(void) return (cur1); } -static unsigned at91st_get_timecount(struct timecounter *tc); +static unsigned at91_st_get_timecount(struct timecounter *tc); -static struct timecounter at91st_timecounter = { - at91st_get_timecount, /* get_timecount */ +static struct timecounter at91_st_timecounter = { + at91_st_get_timecount, /* get_timecount */ NULL, /* no poll_pps */ 0xfffffu, /* counter_mask */ 32768, /* frequency */ @@ -84,8 +105,21 @@ static struct timecounter at91st_timecounter = { 1000 /* quality */ }; -static void -at91st_delay(int n) +static int +clock_intr(void *arg) +{ + struct trapframe *fp = arg; + + /* The interrupt is shared, so we have to make sure it's for us. */ + if (RD4(ST_SR) & ST_SR_PITS) { + hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp)); + return (FILTER_HANDLED); + } + return (FILTER_STRAY); +} + +void +at91_st_delay(int n) { uint32_t start, end, cur; @@ -104,8 +138,8 @@ at91st_delay(int n) } } -static void -at91st_cpu_reset(void) +void +at91_st_cpu_reset(void) { /* * Reset the CPU by programmig the watchdog timer to reset the @@ -119,63 +153,102 @@ at91st_cpu_reset(void) } static int -at91st_probe(device_t dev) +at91_st_probe(device_t dev) { device_set_desc(dev, "ST"); return (0); } +static void +at91_st_deactivate(device_t dev) +{ + struct at91_st_softc *sc = timer_softc; + + if (sc->sc_intrhand) + bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand); + sc->sc_intrhand = NULL; + + if (sc->sc_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, + rman_get_rid(sc->sc_irq_res), sc->sc_irq_res); + sc->sc_irq_res = NULL; + + if (sc->sc_mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(sc->sc_mem_res), sc->sc_mem_res); + sc->sc_mem_res = NULL; +} + static int -at91st_attach(device_t dev) +at91_st_activate(device_t dev) { - struct at91_softc *sc = device_get_softc(device_get_parent(dev)); + int rid; + int err; + struct at91_st_softc *sc = timer_softc; - timer_softc = device_get_softc(dev); - timer_softc->sc_st = sc->sc_st; - timer_softc->sc_dev = dev; - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_ST_BASE, - AT91RM92_ST_SIZE, &timer_softc->sc_sh) != 0) - panic("couldn't subregion timer registers"); - /* - * Real time counter increments every clock cycle, need to set before - * initializing clocks so that DELAY works. - */ - WR4(ST_RTMR, 1); + rid = 0; + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + err = ENOMEM; + if (sc->sc_mem_res == NULL) + goto out; /* Disable all interrupts */ WR4(ST_IDR, 0xffffffff); - /* disable watchdog timer */ - WR4(ST_WDMR, 0); - soc_data.delay = at91st_delay; - soc_data.reset = at91st_cpu_reset; // XXX kinda late to be setting this... + + /* The system timer shares the system irq (1) */ + rid = 0; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE | RF_SHAREABLE); + if (sc->sc_irq_res == NULL) { + printf("Unable to allocate irq for the system timer"); + goto out; + } + err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_CLK, clock_intr, + NULL, NULL, &sc->sc_intrhand); +out: + if (err != 0) + at91_st_deactivate(dev); + return (err); +} + +static int +at91_st_attach(device_t dev) +{ + int err; + + timer_softc = device_get_softc(dev); + err = at91_st_activate(dev); + if (err) + return err; timer_softc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list, - at91st_watchdog, dev, 0); + at91_st_watchdog, dev, 0); device_printf(dev, "watchdog registered, timeout intervall max. 64 sec\n"); - at91st_initclocks(timer_softc); + at91_st_initclocks(dev, timer_softc); return (0); } -static device_method_t at91st_methods[] = { - DEVMETHOD(device_probe, at91st_probe), - DEVMETHOD(device_attach, at91st_attach), +static device_method_t at91_st_methods[] = { + DEVMETHOD(device_probe, at91_st_probe), + DEVMETHOD(device_attach, at91_st_attach), {0, 0}, }; -static driver_t at91st_driver = { +static driver_t at91_st_driver = { "at91_st", - at91st_methods, - sizeof(struct at91st_softc), + at91_st_methods, + sizeof(struct at91_st_softc), }; -static devclass_t at91st_devclass; +static devclass_t at91_st_devclass; -DRIVER_MODULE(at91_st, atmelarm, at91st_driver, at91st_devclass, 0, 0); +DRIVER_MODULE(at91_st, atmelarm, at91_st_driver, at91_st_devclass, 0, 0); static unsigned -at91st_get_timecount(struct timecounter *tc) +at91_st_get_timecount(struct timecounter *tc) { return (st_crtr()); } @@ -194,7 +267,7 @@ at91st_get_timecount(struct timecounter *tc) * interval, I think this is the best solution. */ static void -at91st_watchdog(void *argp, u_int cmd, int *error) +at91_st_watchdog(void *argp, u_int cmd, int *error) { uint32_t wdog; int t; @@ -210,50 +283,31 @@ at91st_watchdog(void *argp, u_int cmd, int *error) WR4(ST_CR, ST_CR_WDRST); } -static int -clock_intr(void *arg) -{ - struct trapframe *fp = arg; - - /* The interrupt is shared, so we have to make sure it's for us. */ - if (RD4(ST_SR) & ST_SR_PITS) { - hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp)); - return (FILTER_HANDLED); - } - return (FILTER_STRAY); -} - static void -at91st_initclocks(struct at91st_softc *sc) +at91_st_initclocks(device_t dev, struct at91_st_softc *sc) { int rel_value; - struct resource *irq; - int rid = 0; - void *ih; - device_t dev = sc->sc_dev; + + /* + * Real time counter increments every clock cycle, need to set before + * initializing clocks so that DELAY works. + */ + WR4(ST_RTMR, 1); + /* disable watchdog timer */ + WR4(ST_WDMR, 0); rel_value = 32768 / hz; if (rel_value < 1) rel_value = 1; if (32768 % hz) { - printf("Cannot get %d Hz clock; using %dHz\n", hz, 32768 / rel_value); + device_printf(dev, "Cannot get %d Hz clock; using %dHz\n", hz, + 32768 / rel_value); hz = 32768 / rel_value; tick = 1000000 / hz; } - /* Disable all interrupts. */ - WR4(ST_IDR, 0xffffffff); - /* The system timer shares the system irq (1) */ - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1, - RF_ACTIVE | RF_SHAREABLE); - if (!irq) - panic("Unable to allocate irq for the system timer"); - else - bus_setup_intr(dev, irq, INTR_TYPE_CLK, - clock_intr, NULL, NULL, &ih); - WR4(ST_PIMR, rel_value); /* Enable PITS interrupts. */ WR4(ST_IER, ST_SR_PITS); - tc_init(&at91st_timecounter); + tc_init(&at91_st_timecounter); } diff --git a/sys/arm/at91/at91_streg.h b/sys/arm/at91/at91_streg.h index 47b1419..48a63c3 100644 --- a/sys/arm/at91/at91_streg.h +++ b/sys/arm/at91/at91_streg.h @@ -55,4 +55,7 @@ /* ST_CRTR */ #define ST_CRTR_MASK 0xfffff /* 20-bit counter */ +void at91_st_delay(int n); +void at91_st_cpu_reset(void); + #endif /* ARM_AT91_AT91STREG_H */ diff --git a/sys/arm/at91/at91reg.h b/sys/arm/at91/at91reg.h index 475da60..e0aaa81 100644 --- a/sys/arm/at91/at91reg.h +++ b/sys/arm/at91/at91reg.h @@ -85,4 +85,6 @@ #define AT91_EXID_SAM9G25 0x00000003 #define AT91_EXID_SAM9X25 0x00000004 +#define AT91_IRQ_SYSTEM 1 + #endif /* _AT91REG_H_ */ diff --git a/sys/arm/at91/at91rm9200.c b/sys/arm/at91/at91rm9200.c index ddddb78..51627f0 100644 --- a/sys/arm/at91/at91rm9200.c +++ b/sys/arm/at91/at91rm9200.c @@ -38,10 +38,14 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <arm/at91/at91var.h> +#include <arm/at91/at91reg.h> #include <arm/at91/at91rm92reg.h> #include <arm/at91/at91_aicreg.h> #include <arm/at91/at91_pmcreg.h> +#include <arm/at91/at91_streg.h> #include <arm/at91/at91_pmcvar.h> +#include <arm/at91/at91soc.h> + struct at91rm92_softc { device_t dev; @@ -49,8 +53,6 @@ struct at91rm92_softc { bus_space_handle_t sc_sh; bus_space_handle_t sc_sys_sh; bus_space_handle_t sc_aic_sh; - bus_space_handle_t sc_dbg_sh; - bus_space_handle_t sc_matrix_sh; }; /* * Standard priority levels for the system. 0 is lowest and 7 is highest. @@ -136,41 +138,6 @@ static const struct cpu_devs at91_devs[] = }; static void -at91_add_child(device_t dev, int prio, const char *name, int unit, - bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) -{ - device_t kid; - struct at91_ivar *ivar; - - kid = device_add_child_ordered(dev, prio, name, unit); - if (kid == NULL) { - printf("Can't add child %s%d ordered\n", name, unit); - return; - } - ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); - if (ivar == NULL) { - device_delete_child(dev, kid); - printf("Can't add alloc ivar\n"); - return; - } - device_set_ivars(kid, ivar); - resource_list_init(&ivar->resources); - if (irq0 != -1) { - bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); - if (irq0 != AT91RM92_IRQ_SYSTEM) - at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); - } - if (irq1 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); - if (irq2 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); - if (addr != 0 && addr < AT91RM92_BASE) - addr += AT91RM92_BASE; - if (addr != 0) - bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); -} - -static void at91_cpu_add_builtin_children(device_t dev) { int i; @@ -207,7 +174,7 @@ static int at91_probe(device_t dev) { - device_set_desc(dev, soc_data.name); + device_set_desc(dev, soc_info.name); return (0); } @@ -228,17 +195,12 @@ at91_attach(device_t dev) AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0) panic("Enable to map system registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_DBGU_BASE, - AT91RM92_DBGU_SIZE, &sc->sc_dbg_sh) != 0) - panic("Enable to map DBGU registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE, AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0) panic("Enable to map system registers"); /* XXX Hack to tell atmelarm about the AIC */ at91sc->sc_aic_sh = sc->sc_aic_sh; - at91sc->sc_irq_system = AT91RM92_IRQ_SYSTEM; for (i = 0; i < 32; i++) { bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + @@ -264,9 +226,6 @@ at91_attach(device_t dev) /* Disable all interrupts for the SDRAM controller */ bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff); - /* Disable all interrupts for DBGU */ - bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); - /* Update USB device port clock info */ clk = at91_pmc_clock_ref("udpck"); clk->pmc_mask = PMC_SCER_UDP; @@ -321,3 +280,10 @@ static driver_t at91rm92_driver = { static devclass_t at91rm92_devclass; DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0); + +static struct at91_soc_data soc_data = { + .soc_delay = at91_st_delay, + .soc_reset = at91_st_cpu_reset +}; + +AT91_SOC(AT91_T_RM9200, &soc_data); diff --git a/sys/arm/at91/at91rm92reg.h b/sys/arm/at91/at91rm92reg.h index 129c01b..66fad34 100644 --- a/sys/arm/at91/at91rm92reg.h +++ b/sys/arm/at91/at91rm92reg.h @@ -70,7 +70,6 @@ * 0xf0000000 - 0xfffffffff : Peripherals */ -#define AT91RM92_BASE 0xd0000000 /* Usart */ #define AT91RM92_USART_SIZE 0x4000 diff --git a/sys/arm/at91/at91sam9260.c b/sys/arm/at91/at91sam9260.c index c246abc..9ea0335 100644 --- a/sys/arm/at91/at91sam9260.c +++ b/sys/arm/at91/at91sam9260.c @@ -38,10 +38,14 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <arm/at91/at91var.h> +#include <arm/at91/at91reg.h> +#include <arm/at91/at91soc.h> #include <arm/at91/at91_aicreg.h> #include <arm/at91/at91sam9260reg.h> +#include <arm/at91/at91_pitreg.h> #include <arm/at91/at91_pmcreg.h> #include <arm/at91/at91_pmcvar.h> +#include <arm/at91/at91_rstreg.h> struct at91sam9_softc { device_t dev; @@ -49,7 +53,6 @@ struct at91sam9_softc { bus_space_handle_t sc_sh; bus_space_handle_t sc_sys_sh; bus_space_handle_t sc_aic_sh; - bus_space_handle_t sc_dbg_sh; bus_space_handle_t sc_matrix_sh; }; @@ -129,41 +132,6 @@ static const struct cpu_devs at91_devs[] = }; static void -at91_add_child(device_t dev, int prio, const char *name, int unit, - bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) -{ - device_t kid; - struct at91_ivar *ivar; - - kid = device_add_child_ordered(dev, prio, name, unit); - if (kid == NULL) { - printf("Can't add child %s%d ordered\n", name, unit); - return; - } - ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); - if (ivar == NULL) { - device_delete_child(dev, kid); - printf("Can't add alloc ivar\n"); - return; - } - device_set_ivars(kid, ivar); - resource_list_init(&ivar->resources); - if (irq0 != -1) { - bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); - if (irq0 != AT91SAM9260_IRQ_SYSTEM) - at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); - } - if (irq1 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); - if (irq2 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); - if (addr != 0 && addr < AT91SAM9260_BASE) - addr += AT91SAM9260_BASE; - if (addr != 0) - bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); -} - -static void at91_cpu_add_builtin_children(device_t dev) { int i; @@ -197,7 +165,7 @@ static void at91_identify(driver_t *drv, device_t parent) { - if (soc_data.type == AT91_T_SAM9260) { + if (soc_info.type == AT91_T_SAM9260) { at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0); at91_cpu_add_builtin_children(parent); } @@ -207,7 +175,7 @@ static int at91_probe(device_t dev) { - device_set_desc(dev, soc_data.name); + device_set_desc(dev, soc_info.name); return (0); } @@ -228,17 +196,12 @@ at91_attach(device_t dev) AT91SAM9260_SYS_SIZE, &sc->sc_sys_sh) != 0) panic("Enable to map system registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_DBGU_BASE, - AT91SAM9260_DBGU_SIZE, &sc->sc_dbg_sh) != 0) - panic("Enable to map DBGU registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_AIC_BASE, AT91SAM9260_AIC_SIZE, &sc->sc_aic_sh) != 0) panic("Enable to map system registers"); /* XXX Hack to tell atmelarm about the AIC */ at91sc->sc_aic_sh = sc->sc_aic_sh; - at91sc->sc_irq_system = AT91SAM9260_IRQ_SYSTEM; for (i = 0; i < 32; i++) { bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + @@ -258,9 +221,6 @@ at91_attach(device_t dev) bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); - /* Disable all interrupts for DBGU */ - bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_MATRIX_BASE, AT91SAM9260_MATRIX_SIZE, &sc->sc_matrix_sh) != 0) @@ -336,3 +296,10 @@ static devclass_t at91sam9260_devclass; DRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass, NULL, NULL); + +static struct at91_soc_data soc_data = { + .soc_delay = at91_pit_delay, + .soc_reset = at91_rst_cpu_reset +}; + +AT91_SOC(AT91_T_SAM9260, &soc_data); diff --git a/sys/arm/at91/at91sam9260reg.h b/sys/arm/at91/at91sam9260reg.h index 659a951..e04afb8 100644 --- a/sys/arm/at91/at91sam9260reg.h +++ b/sys/arm/at91/at91sam9260reg.h @@ -72,8 +72,6 @@ #define AT91_CHIPSELECT_7 0x80000000 -#define AT91SAM9260_BASE 0xd0000000 - #define AT91SAM9260_EMAC_BASE 0xffc4000 #define AT91SAM9260_EMAC_SIZE 0x4000 diff --git a/sys/arm/at91/at91sam9g20.c b/sys/arm/at91/at91sam9g20.c index 668b057..4b87ad0 100644 --- a/sys/arm/at91/at91sam9g20.c +++ b/sys/arm/at91/at91sam9g20.c @@ -38,10 +38,14 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <arm/at91/at91var.h> +#include <arm/at91/at91reg.h> +#include <arm/at91/at91soc.h> #include <arm/at91/at91_aicreg.h> #include <arm/at91/at91sam9g20reg.h> +#include <arm/at91/at91_pitreg.h> #include <arm/at91/at91_pmcreg.h> #include <arm/at91/at91_pmcvar.h> +#include <arm/at91/at91_rstreg.h> struct at91sam9_softc { device_t dev; @@ -49,7 +53,6 @@ struct at91sam9_softc { bus_space_handle_t sc_sh; bus_space_handle_t sc_sys_sh; bus_space_handle_t sc_aic_sh; - bus_space_handle_t sc_dbg_sh; bus_space_handle_t sc_matrix_sh; }; @@ -129,41 +132,6 @@ static const struct cpu_devs at91_devs[] = }; static void -at91_add_child(device_t dev, int prio, const char *name, int unit, - bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) -{ - device_t kid; - struct at91_ivar *ivar; - - kid = device_add_child_ordered(dev, prio, name, unit); - if (kid == NULL) { - printf("Can't add child %s%d ordered\n", name, unit); - return; - } - ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); - if (ivar == NULL) { - device_delete_child(dev, kid); - printf("Can't add alloc ivar\n"); - return; - } - device_set_ivars(kid, ivar); - resource_list_init(&ivar->resources); - if (irq0 != -1) { - bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); - if (irq0 != AT91SAM9G20_IRQ_SYSTEM) - at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); - } - if (irq1 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); - if (irq2 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); - if (addr != 0 && addr < AT91SAM9G20_BASE) - addr += AT91SAM9G20_BASE; - if (addr != 0) - bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); -} - -static void at91_cpu_add_builtin_children(device_t dev) { int i; @@ -214,7 +182,7 @@ static int at91_probe(device_t dev) { - device_set_desc(dev, soc_data.name); + device_set_desc(dev, soc_info.name); return (0); } @@ -239,17 +207,12 @@ at91_attach(device_t dev) AT91SAM9G20_SYS_SIZE, &sc->sc_sys_sh) != 0) panic("Enable to map system registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_DBGU_BASE, - AT91SAM9G20_DBGU_SIZE, &sc->sc_dbg_sh) != 0) - panic("Enable to map DBGU registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_AIC_BASE, AT91SAM9G20_AIC_SIZE, &sc->sc_aic_sh) != 0) panic("Enable to map system registers"); /* XXX Hack to tell atmelarm about the AIC */ at91sc->sc_aic_sh = sc->sc_aic_sh; - at91sc->sc_irq_system = AT91SAM9G20_IRQ_SYSTEM; for (i = 0; i < 32; i++) { bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + @@ -269,9 +232,6 @@ at91_attach(device_t dev) bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); - /* Disable all interrupts for DBGU */ - bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_MATRIX_BASE, AT91SAM9G20_MATRIX_SIZE, &sc->sc_matrix_sh) != 0) @@ -338,3 +298,10 @@ static driver_t at91sam9_driver = { static devclass_t at91sam9_devclass; DRIVER_MODULE(at91sam, atmelarm, at91sam9_driver, at91sam9_devclass, 0, 0); + +static struct at91_soc_data soc_data = { + .soc_delay = at91_pit_delay, + .soc_reset = at91_rst_cpu_reset +}; + +AT91_SOC(AT91_T_SAM9G20, &soc_data); diff --git a/sys/arm/at91/at91sam9g20reg.h b/sys/arm/at91/at91sam9g20reg.h index 7311ade..ab686c3 100644 --- a/sys/arm/at91/at91sam9g20reg.h +++ b/sys/arm/at91/at91sam9g20reg.h @@ -73,8 +73,6 @@ #define AT91_CHIPSELECT_7 0x80000000 -#define AT91SAM9G20_BASE 0xd0000000 - #define AT91SAM9G20_EMAC_BASE 0xffc4000 #define AT91SAM9G20_EMAC_SIZE 0x4000 diff --git a/sys/arm/at91/at91sam9x25.c b/sys/arm/at91/at91sam9x25.c index fa19300..b84d30c 100644 --- a/sys/arm/at91/at91sam9x25.c +++ b/sys/arm/at91/at91sam9x25.c @@ -38,10 +38,14 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <arm/at91/at91var.h> +#include <arm/at91/at91reg.h> +#include <arm/at91/at91soc.h> #include <arm/at91/at91_aicreg.h> #include <arm/at91/at91sam9x25reg.h> +#include <arm/at91/at91_pitreg.h> #include <arm/at91/at91_pmcreg.h> #include <arm/at91/at91_pmcvar.h> +#include <arm/at91/at91_rstreg.h> struct at91sam9x25_softc { device_t dev; @@ -49,8 +53,6 @@ struct at91sam9x25_softc { bus_space_handle_t sc_sh; bus_space_handle_t sc_sys_sh; bus_space_handle_t sc_aic_sh; - bus_space_handle_t sc_dbg_sh; - bus_space_handle_t sc_matrix_sh; }; /* @@ -132,41 +134,6 @@ static const struct cpu_devs at91_devs[] = }; static void -at91_add_child(device_t dev, int prio, const char *name, int unit, - bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) -{ - device_t kid; - struct at91_ivar *ivar; - - kid = device_add_child_ordered(dev, prio, name, unit); - if (kid == NULL) { - printf("Can't add child %s%d ordered\n", name, unit); - return; - } - ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); - if (ivar == NULL) { - device_delete_child(dev, kid); - printf("Can't add alloc ivar\n"); - return; - } - device_set_ivars(kid, ivar); - resource_list_init(&ivar->resources); - if (irq0 != -1) { - bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); - if (irq0 != AT91SAM9X25_IRQ_SYSTEM) - at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); - } - if (irq1 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); - if (irq2 != 0) - bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); - if (addr != 0 && addr < AT91SAM9X25_BASE) - addr += AT91SAM9X25_BASE; - if (addr != 0) - bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); -} - -static void at91_cpu_add_builtin_children(device_t dev) { int i; @@ -207,7 +174,7 @@ static void at91_identify(driver_t *drv, device_t parent) { - if (soc_data.type == AT91_T_SAM9X5 && soc_data.subtype == AT91_ST_SAM9X25) { + if (soc_info.type == AT91_T_SAM9X5 && soc_info.subtype == AT91_ST_SAM9X25) { at91_add_child(parent, 0, "at91sam9x25", 0, 0, 0, -1, 0, 0); at91_cpu_add_builtin_children(parent); } @@ -242,17 +209,12 @@ at91_attach(device_t dev) AT91SAM9X25_SYS_SIZE, &sc->sc_sys_sh) != 0) panic("Enable to map system registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9X25_DBGU_BASE, - AT91SAM9X25_DBGU_SIZE, &sc->sc_dbg_sh) != 0) - panic("Enable to map DBGU registers"); - if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9X25_AIC_BASE, AT91SAM9X25_AIC_SIZE, &sc->sc_aic_sh) != 0) panic("Enable to map system registers"); /* XXX Hack to tell atmelarm about the AIC */ at91sc->sc_aic_sh = sc->sc_aic_sh; - at91sc->sc_irq_system = AT91SAM9X25_IRQ_SYSTEM; for (i = 0; i < 32; i++) { bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + @@ -272,23 +234,6 @@ at91_attach(device_t dev) bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); - /* Disable all interrupts for DBGU */ - bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); - - if (bus_space_subregion(sc->sc_st, sc->sc_sh, - AT91SAM9X25_MATRIX_BASE, AT91SAM9X25_MATRIX_SIZE, - &sc->sc_matrix_sh) != 0) - panic("Enable to map matrix registers"); - -#if 0 /* wrong, placeholder */ - /* activate NAND*/ - i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh, - AT91SAM9X25_EBICSA); - bus_space_write_4(sc->sc_st, sc->sc_matrix_sh, - AT91SAM9X25_EBICSA, - i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); -#endif - /* Update USB device port clock info */ clk = at91_pmc_clock_ref("udpck"); clk->pmc_mask = PMC_SCER_UDP_SAM9; @@ -342,3 +287,10 @@ static driver_t at91sam9x25_driver = { static devclass_t at91sam9x25_devclass; DRIVER_MODULE(at91sam9x25, atmelarm, at91sam9x25_driver, at91sam9x25_devclass, 0, 0); + +static struct at91_soc_data soc_data = { + .soc_delay = at91_pit_delay, + .soc_reset = at91_rst_cpu_reset +}; + +AT91_SOC_SUB(AT91_T_SAM9X5, AT91_ST_SAM9X25, &soc_data); diff --git a/sys/arm/at91/at91sam9x25reg.h b/sys/arm/at91/at91sam9x25reg.h index e8bc0e5..d497e2b 100644 --- a/sys/arm/at91/at91sam9x25reg.h +++ b/sys/arm/at91/at91sam9x25reg.h @@ -73,8 +73,6 @@ #define AT91_CHIPSELECT_4 0x50000000 #define AT91_CHIPSELECT_5 0x60000000 -#define AT91SAM9X25_BASE 0xd0000000 - #define AT91SAM9X25_EMAC_SIZE 0x4000 #define AT91SAM9X25_EMAC0_BASE 0x802c000 #define AT91SAM9X25_EMAC0_SIZE AT91SAM9X25_EMAC_SIZE diff --git a/sys/arm/at91/at91soc.c b/sys/arm/at91/at91soc.c new file mode 100644 index 0000000..7031e83 --- /dev/null +++ b/sys/arm/at91/at91soc.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2012 Warner Losh. 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 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 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 <arm/at91/at91var.h> +#include <arm/at91/at91soc.h> + +SET_DECLARE(at91_socs, const struct at91_soc); + +struct at91_soc_data * +at91_match_soc(enum at91_soc_type type, enum at91_soc_subtype subtype) +{ + const struct at91_soc **socp; + + SET_FOREACH(socp, at91_socs) { + if ((*socp)->soc_type != type) + continue; + if ((*socp)->soc_subtype != AT91_ST_ANY && + (*socp)->soc_subtype != subtype) + continue; + return (*socp)->soc_data; + } + return NULL; +} diff --git a/sys/arm/at91/at91soc.h b/sys/arm/at91/at91soc.h new file mode 100644 index 0000000..e2f4d41 --- /dev/null +++ b/sys/arm/at91/at91soc.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2012 Warner Losh. 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 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 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 _ARM_AT91_AT91SOC_H_ +#define _ARM_AT91_AT91SOC_H_ + +#include <sys/linker_set.h> + +struct at91_soc { + enum at91_soc_type soc_type; /* Family of mail type of SoC */ + enum at91_soc_subtype soc_subtype; /* More specific soc, if any */ + struct at91_soc_data *soc_data; +}; + +// Make varadic +#define AT91_SOC(type, data) \ + static struct at91_soc this_soc = { \ + .soc_type = type, \ + .soc_subtype = AT91_ST_ANY, \ + .soc_data = data, \ + }; \ + DATA_SET(at91_socs, this_soc); + +#define AT91_SOC_SUB(type, subtype, data) \ + static struct at91_soc this_soc = { \ + .soc_type = type, \ + .soc_subtype = subtype, \ + .soc_data = data, \ + }; \ + DATA_SET(at91_socs, this_soc); + +struct at91_soc_data *at91_match_soc(enum at91_soc_type, enum at91_soc_subtype); + +#endif /* _ARM_AT91_AT91SOC_H_ */ diff --git a/sys/arm/at91/at91var.h b/sys/arm/at91/at91var.h index 7a3ce95..183b723 100644 --- a/sys/arm/at91/at91var.h +++ b/sys/arm/at91/at91var.h @@ -40,7 +40,6 @@ struct at91_softc { bus_space_handle_t sc_aic_sh; struct rman sc_irq_rman; struct rman sc_mem_rman; - uint32_t sc_irq_system; }; struct at91_ivar { @@ -75,6 +74,7 @@ enum at91_soc_type { }; enum at91_soc_subtype { + AT91_ST_ANY = -1, /* Match any type */ AT91_ST_NONE = 0, /* AT91RM9200 */ AT91_ST_RM9200_BGA, @@ -105,6 +105,11 @@ enum at91_soc_family { typedef void (*DELAY_t)(int); typedef void (*cpu_reset_t)(void); +struct at91_soc_data { + DELAY_t soc_delay; + cpu_reset_t soc_reset; +}; + struct at91_soc_info { enum at91_soc_type type; enum at91_soc_subtype subtype; @@ -112,11 +117,10 @@ struct at91_soc_info { uint32_t cidr; uint32_t exid; char name[AT91_SOC_NAME_MAX]; - DELAY_t delay; - cpu_reset_t reset; + struct at91_soc_data *soc_data; }; -extern struct at91_soc_info soc_data; +extern struct at91_soc_info soc_info; static inline int at91_is_rm92(void); static inline int at91_is_sam9(void); @@ -127,30 +131,33 @@ static inline int at91_is_rm92(void) { - return (soc_data.type == AT91_T_RM9200); + return (soc_info.type == AT91_T_RM9200); } static inline int at91_is_sam9(void) { - return (soc_data.family == AT91_FAMILY_SAM9); + return (soc_info.family == AT91_FAMILY_SAM9); } static inline int at91_is_sam9xe(void) { - return (soc_data.family == AT91_FAMILY_SAM9XE); + return (soc_info.family == AT91_FAMILY_SAM9XE); } static inline int at91_cpu_is(u_int cpu) { - return (soc_data.type == cpu); + return (soc_info.type == cpu); } +void at91_add_child(device_t dev, int prio, const char *name, int unit, + bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2); + extern uint32_t at91_irq_system; extern uint32_t at91_master_clock; void at91_pmc_init_clock(void); diff --git a/sys/arm/at91/files.at91 b/sys/arm/at91/files.at91 index 0816901..8e3a75d 100644 --- a/sys/arm/at91/files.at91 +++ b/sys/arm/at91/files.at91 @@ -27,6 +27,7 @@ arm/at91/uart_dev_at91usart.c optional uart # # All the "systems on a chip" we support # +arm/at91/at91soc.c standard arm/at91/at91rm9200.c optional at91rm9200 arm/at91/at91sam9260.c optional at91sam9260 arm/at91/at91sam9g20.c optional at91sam9g20 diff --git a/sys/arm/at91/uart_bus_at91usart.c b/sys/arm/at91/uart_bus_at91usart.c index c5e3f82..b042537 100644 --- a/sys/arm/at91/uart_bus_at91usart.c +++ b/sys/arm/at91/uart_bus_at91usart.c @@ -42,33 +42,32 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart_bus.h> #include <dev/uart/uart_cpu.h> -#include <arm/at91/at91rm92reg.h> #include <arm/at91/at91var.h> #include "uart_if.h" -static int usart_at91rm92_probe(device_t dev); +static int usart_at91_probe(device_t dev); extern struct uart_class at91_usart_class; -static device_method_t usart_at91rm92_methods[] = { +static device_method_t usart_at91_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, usart_at91rm92_probe), + DEVMETHOD(device_probe, usart_at91_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; -static driver_t usart_at91rm92_driver = { +static driver_t usart_at91_driver = { uart_driver_name, - usart_at91rm92_methods, + usart_at91_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int -usart_at91rm92_probe(device_t dev) +usart_at91_probe(device_t dev) { struct uart_softc *sc; @@ -104,4 +103,4 @@ usart_at91rm92_probe(device_t dev) } -DRIVER_MODULE(uart, atmelarm, usart_at91rm92_driver, uart_devclass, 0, 0); +DRIVER_MODULE(uart, atmelarm, usart_at91_driver, uart_devclass, 0, 0); diff --git a/sys/arm/at91/uart_cpu_at91rm9200usart.c b/sys/arm/at91/uart_cpu_at91rm9200usart.c index 098e368..cb39bf9 100644 --- a/sys/arm/at91/uart_cpu_at91rm9200usart.c +++ b/sys/arm/at91/uart_cpu_at91rm9200usart.c @@ -73,7 +73,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) * XXX: Not pretty, but will work because we map the needed addresses * early. */ - di->bas.bsh = AT91RM92_BASE + AT91RM92_DBGU_BASE; + di->bas.bsh = AT91_BASE + AT91RM92_DBGU_BASE; di->baudrate = 115200; di->bas.regshft = 0; di->bas.rclk = 0; diff --git a/sys/arm/conf/KB920X b/sys/arm/conf/KB920X index ea50c8b..d102f5f 100644 --- a/sys/arm/conf/KB920X +++ b/sys/arm/conf/KB920X @@ -24,7 +24,7 @@ include "../at91/std.kb920x" # The AT91 platform doesn't use /boot/loader, so we have to statically wire # hints. hints "KB920X.hints" -#makeoptions MODULES_OVERRIDE="" +makeoptions MODULES_OVERRIDE="" makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols options DDB @@ -137,6 +137,7 @@ device wlan_wep # 802.11 WEP support device wlan_ccmp # 802.11 CCMP support device wlan_tkip # 802.11 TKIP support device wlan_amrr # AMRR transmit rate control algorithm + options IEEE80211_SUPPORT_MESH options AH_SUPPORT_AR5416 diff --git a/sys/arm/econa/econa_machdep.c b/sys/arm/econa/econa_machdep.c index 62c8a1b..de18fd1 100644 --- a/sys/arm/econa/econa_machdep.c +++ b/sys/arm/econa/econa_machdep.c @@ -103,10 +103,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -114,7 +110,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c index bb08933..0c12aea 100644 --- a/sys/arm/mv/mv_machdep.c +++ b/sys/arm/mv/mv_machdep.c @@ -115,16 +115,11 @@ extern unsigned char _edata[]; extern unsigned char __bss_start[]; extern unsigned char _end[]; -#ifdef DDB -extern vm_offset_t ksym_start, ksym_end; -#endif - extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; extern vm_offset_t pmap_bootstrap_lastaddr; -extern int *end; struct pv_addr kernel_pt_table[KERNEL_PT_MAX]; struct pcpu __pcpu; @@ -134,7 +129,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; vm_offset_t pmap_bootstrap_lastaddr; const struct pmap_devmap *pmap_devmap_bootstrap_table; diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/s3c2xx0/s3c24x0_machdep.c index caf4ba8..4f14c5c 100644 --- a/sys/arm/s3c2xx0/s3c24x0_machdep.c +++ b/sys/arm/s3c2xx0/s3c24x0_machdep.c @@ -118,10 +118,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -129,7 +125,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; @@ -203,10 +198,6 @@ static const struct pmap_devmap s3c24x0_devmap[] = { #define ioreg_read32(a) (*(volatile uint32_t *)(a)) #define ioreg_write32(a,v) (*(volatile uint32_t *)(a)=(v)) -#ifdef DDB -extern vm_offset_t ksym_start, ksym_end; -#endif - struct arm32_dma_range s3c24x0_range = { .dr_sysbase = 0, .dr_busbase = 0, diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c index 9bc80d5..3a3e0f9 100644 --- a/sys/arm/sa11x0/assabet_machdep.c +++ b/sys/arm/sa11x0/assabet_machdep.c @@ -119,14 +119,10 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - extern vm_offset_t sa1110_uart_vaddr; extern vm_offset_t sa1_cache_clean_addr; -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -140,7 +136,6 @@ vm_paddr_t dump_avail[4]; vm_paddr_t physical_start; vm_paddr_t physical_end; vm_paddr_t physical_freestart; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr irqstack; diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c index 0508244..fe781cc 100644 --- a/sys/arm/xscale/i80321/ep80219_machdep.c +++ b/sys/arm/xscale/i80321/ep80219_machdep.c @@ -115,10 +115,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -126,7 +122,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c index 9790c0b..e9f3fae 100644 --- a/sys/arm/xscale/i80321/iq31244_machdep.c +++ b/sys/arm/xscale/i80321/iq31244_machdep.c @@ -115,10 +115,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -126,7 +122,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 8567b17..2fa7ca1 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -117,7 +117,6 @@ extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern int *end; struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -126,7 +125,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index 5c1819c..6c87510 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -119,10 +119,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -130,7 +126,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[10]; vm_paddr_t dump_avail[4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index da5787a..d0e3f0c 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -115,10 +115,6 @@ extern u_int undefined_handler_address; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern void *_end; - -extern int *end; - struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; @@ -126,7 +122,6 @@ struct pcpu *pcpup = &__pcpu; vm_paddr_t phys_avail[PXA2X0_SDRAM_BANKS * 2 + 4]; vm_paddr_t dump_avail[PXA2X0_SDRAM_BANKS * 2 + 4]; -vm_offset_t physical_pages; struct pv_addr systempage; struct pv_addr msgbufpv; diff --git a/sys/arm/xscale/std.xscale b/sys/arm/xscale/std.xscale index 2e5ea81..336000b 100644 --- a/sys/arm/xscale/std.xscale +++ b/sys/arm/xscale/std.xscale @@ -1,3 +1,3 @@ # $FreeBSD$ -machine arm armeb +# machine arm armeb options ARM_CACHE_LOCK_ENABLE diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index 5faf68e..5135efb 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -171,8 +171,8 @@ ata_op_string(struct ata_cmd *cmd) case 0xf2: return ("SECURITY_UNLOCK"); case 0xf3: return ("SECURITY_ERASE_PREPARE"); case 0xf4: return ("SECURITY_ERASE_UNIT"); - case 0xf5: return ("SECURITY_FREE_LOCK"); - case 0xf6: return ("SECURITY DISABLE PASSWORD"); + case 0xf5: return ("SECURITY_FREEZE_LOCK"); + case 0xf6: return ("SECURITY_DISABLE_PASSWORD"); case 0xf8: return ("READ_NATIVE_MAX_ADDRESS"); case 0xf9: return ("SET_MAX_ADDRESS"); } diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index ae40b3c..08c756e 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -368,9 +368,9 @@ TUNABLE_INT("kern.cam.ada.retry_count", &ada_retry_count); SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW, &ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout); -SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW, +SYSCTL_INT(_kern_cam_ada, OID_AUTO, send_ordered, CTLFLAG_RW, &ada_send_ordered, 0, "Send Ordered Tags"); -TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered); +TUNABLE_INT("kern.cam.ada.send_ordered", &ada_send_ordered); SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW, &ada_spindown_shutdown, 0, "Spin down upon shutdown"); TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown); diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index e842af6..8a5c72a 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -883,9 +883,9 @@ TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count); SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW, &da_default_timeout, 0, "Normal I/O timeout (in seconds)"); TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout); -SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW, +SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RW, &da_send_ordered, 0, "Send Ordered Tags"); -TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered); +TUNABLE_INT("kern.cam.da.send_ordered", &da_send_ordered); /* * DA_ORDEREDTAG_INTERVAL determines how often, relative diff --git a/sys/conf/files b/sys/conf/files index 76bd91c..c0c52da 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -412,6 +412,7 @@ contrib/dev/acpica/components/tables/tbfind.c optional acpi contrib/dev/acpica/components/tables/tbinstal.c optional acpi contrib/dev/acpica/components/tables/tbutils.c optional acpi contrib/dev/acpica/components/tables/tbxface.c optional acpi +contrib/dev/acpica/components/tables/tbxfload.c optional acpi contrib/dev/acpica/components/tables/tbxfroot.c optional acpi contrib/dev/acpica/components/utilities/utaddress.c optional acpi contrib/dev/acpica/components/utilities/utalloc.c optional acpi @@ -421,6 +422,7 @@ contrib/dev/acpica/components/utilities/utdebug.c optional acpi contrib/dev/acpica/components/utilities/utdecode.c optional acpi contrib/dev/acpica/components/utilities/utdelete.c optional acpi contrib/dev/acpica/components/utilities/uteval.c optional acpi +contrib/dev/acpica/components/utilities/utexcep.c optional acpi contrib/dev/acpica/components/utilities/utglobal.c optional acpi contrib/dev/acpica/components/utilities/utids.c optional acpi contrib/dev/acpica/components/utilities/utinit.c optional acpi diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt index 2123937..605e678 100644 --- a/sys/contrib/dev/acpica/changes.txt +++ b/sys/contrib/dev/acpica/changes.txt @@ -1,4 +1,82 @@ ---------------------------------------- +11 July 2012. Summary of changes for version 20120711: + +This release is available at https://www.acpica.org/downloads The ACPI 5.0 +specification is available at www.acpi.info + +1) ACPICA Kernel-resident Subsystem: + +Fixed a possible fault in the return package object repair code. Fixes a +problem that can occur when a lone package object is wrapped with an outer +package object in order to force conformance to the ACPI specification. Can +affect these predefined names: _ALR, _MLS, _PSS, _TRT, _TSS, _PRT, _HPX, _DLM, +_CSD, _PSD, _TSD. + +Removed code to disable/enable bus master arbitration (ARB_DIS bit in the +PM2_CNT register) in the ACPICA sleep/wake interfaces. Management of the +ARB_DIS bit must be implemented in the host-dependent C3 processor power state +support. Note, ARB_DIS is obsolete and only applies to older chipsets, both +Intel and other vendors. (for Intel: ICH4-M and earlier) + +This change removes the code to disable/enable bus master arbitration during +suspend/resume. Use of the ARB_DIS bit in the optional PM2_CNT register causes +resume problems on some machines. The change has been in use for over seven +years within Linux. + +Implemented two new external interfaces to support host-directed dynamic ACPI +table load and unload. They are intended to simplify the host implementation +of hot-plug support: + AcpiLoadTable: Load an SSDT from a buffer into the namespace. + AcpiUnloadParentTable: Unload an SSDT via a named object owned by the table. +See the ACPICA reference for additional details. Adds one new file, +components/tables/tbxfload.c + +Implemented and deployed two new interfaces for errors and warnings that are +known to be caused by BIOS/firmware issues: + AcpiBiosError: Prints "ACPI Firmware Error" message. + AcpiBiosWarning: Prints "ACPI Firmware Warning" message. +Deployed these new interfaces in the ACPICA Table Manager code for ACPI table +and FADT errors. Additional deployment to be completed as appropriate in the +future. The associated conditional macros are ACPI_BIOS_ERROR and +ACPI_BIOS_WARNING. See the ACPICA reference for additional details. ACPICA BZ +843. + +Implicit notify support: ensure that no memory allocation occurs within a +critical region. This fix moves a memory allocation outside of the time that a +spinlock is held. Fixes issues on systems that do not allow this behavior. +Jung-uk Kim. + +Split exception code utilities and tables into a new file, utilities/utexcep.c + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The debug +version of the code includes the debug output trace mechanism and has a much +larger code and data size. + + Previous Release: + Non-Debug Version: 93.1K Code, 25.1K Data, 118.2K Total + Debug Version: 172.9K Code, 73.6K Data, 246.5K Total + Current Release: + Non-Debug Version: 93.5K Code, 25.3K Data, 118.8K Total + Debug Version: 173.7K Code, 74.0K Data, 247.7K Total + + +2) iASL Compiler/Disassembler and Tools: + +iASL: Fixed a parser problem for hosts where EOF is defined as -1 instead of +0. Jung-uk Kim. + +Debugger: Enhanced the "tables" command to emit additional information about +the current set of ACPI tables, including the owner ID and flags decode. + +Debugger: Reimplemented the "unload" command to use the new +AcpiUnloadParentTable external interface. This command was disable previously +due to need for an unload interface. + +AcpiHelp: Added a new option to decode ACPICA exception codes. The -e option +will decode 16-bit hex status codes (ACPI_STATUS) to name strings. + +---------------------------------------- 20 June 2012. Summary of changes for version 20120620: This release is available at https://www.acpica.org/downloads diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c index c17fc95..5a8fa2f 100644 --- a/sys/contrib/dev/acpica/compiler/aslmain.c +++ b/sys/contrib/dev/acpica/compiler/aslmain.c @@ -96,7 +96,7 @@ AslDoResponseFile ( #define ASL_TOKEN_SEPARATORS " \t\n" -#define ASL_SUPPORTED_OPTIONS "@:2b|c|d^D:e:fgh^i|I:l^mno|p:P^r:s|t|T:G^v|w|x:z" +#define ASL_SUPPORTED_OPTIONS "@:2b|c|d^D:e:fgh^i|I:l^mno|p:P^r:s|t|T:G^v^w|x:z" /******************************************************************************* @@ -119,6 +119,7 @@ Options ( printf ("\nGlobal:\n"); ACPI_OPTION ("-@ <file>", "Specify command file"); ACPI_OPTION ("-I <dir>", "Specify additional include directory"); + ACPI_OPTION ("-v", "Display compiler version"); printf ("\nPreprocessor:\n"); ACPI_OPTION ("-D <symbol>", "Define symbol for preprocessor use"); @@ -751,9 +752,13 @@ AslDoOptions ( break; - case 'v': /* Verbosity settings */ + case 'v': /* Version and verbosity settings */ switch (AcpiGbl_Optarg[0]) { + case '^': + printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); + exit (0); + case 'a': /* Disable All error/warning messages */ diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c index 033b1fd..2b18653 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c +++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c @@ -254,12 +254,53 @@ AcpiDbDisplayTableInfo ( ACPI_STATUS Status; + /* Header */ + + AcpiOsPrintf ("Idx ID Status Type Sig Address Len Header\n"); + /* Walk the entire root table list */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { TableDesc = &AcpiGbl_RootTableList.Tables[i]; - AcpiOsPrintf ("%u ", i); + + /* Index and Table ID */ + + AcpiOsPrintf ("%3u %.2u ", i, TableDesc->OwnerId); + + /* Decode the table flags */ + + if (!(TableDesc->Flags & ACPI_TABLE_IS_LOADED)) + { + AcpiOsPrintf ("NotLoaded "); + } + else + { + AcpiOsPrintf (" Loaded "); + } + + switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_UNKNOWN: + AcpiOsPrintf ("Unknown "); + break; + + case ACPI_TABLE_ORIGIN_MAPPED: + AcpiOsPrintf ("Mapped "); + break; + + case ACPI_TABLE_ORIGIN_ALLOCATED: + AcpiOsPrintf ("Allocated "); + break; + + case ACPI_TABLE_ORIGIN_OVERRIDE: + AcpiOsPrintf ("Override "); + break; + + default: + AcpiOsPrintf ("INVALID "); + break; + } /* Make sure that the table is mapped */ @@ -290,55 +331,45 @@ AcpiDbDisplayTableInfo ( * * FUNCTION: AcpiDbUnloadAcpiTable * - * PARAMETERS: TableArg - Name of the table to be unloaded - * InstanceArg - Which instance of the table to unload (if - * there are multiple tables of the same type) + * PARAMETERS: ObjectName - Namespace pathname for an object that + * is owned by the table to be unloaded * - * RETURN: Nonde + * RETURN: None * - * DESCRIPTION: Unload an ACPI table. - * Instance is not implemented + * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned + * by the table. * ******************************************************************************/ void AcpiDbUnloadAcpiTable ( - char *TableArg, - char *InstanceArg) + char *ObjectName) { -/* TBD: Need to reimplement for new data structures */ - -#if 0 - UINT32 i; + ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; - /* Search all tables for the target type */ + /* Translate name to an Named object */ - for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++) + Node = AcpiDbConvertToNode (ObjectName); + if (!Node) { - if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature, - AcpiGbl_TableData[i].SigLength)) - { - /* Found the table, unload it */ - - Status = AcpiUnloadTable (i); - if (ACPI_SUCCESS (Status)) - { - AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg); - } - else - { - AcpiOsPrintf ("%s, while unloading [%s]\n", - AcpiFormatException (Status), TableArg); - } - - return; - } + AcpiOsPrintf ("Could not find [%s] in namespace\n", + ObjectName); + return; } - AcpiOsPrintf ("Unknown table type [%s]\n", TableArg); -#endif + Status = AcpiUnloadParentTable (ACPI_CAST_PTR (ACPI_HANDLE, Node)); + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf ("Parent of [%s] (%p) unloaded and uninstalled\n", + ObjectName, Node); + } + else + { + AcpiOsPrintf ("%s, while unloading parent table of [%s]\n", + AcpiFormatException (Status), ObjectName); + } } diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c index e56fad9..f18398c 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbinput.c +++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c @@ -250,7 +250,7 @@ AcpiDbDisplayHelp ( AcpiOsPrintf (" Stack Display CPU stack usage\n"); AcpiOsPrintf (" Tables Info about current ACPI table(s)\n"); AcpiOsPrintf (" Tables Display info about loaded ACPI tables\n"); - AcpiOsPrintf (" Unload <TableSig> [Instance] Unload an ACPI table\n"); + AcpiOsPrintf (" Unload <Namepath> Unload an ACPI table via namespace object\n"); AcpiOsPrintf (" ! <CommandNumber> Execute command from history buffer\n"); AcpiOsPrintf (" !! Execute last command again\n"); @@ -894,7 +894,7 @@ AcpiDbCommandDispatch ( break; case CMD_UNLOAD: - AcpiDbUnloadAcpiTable (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + AcpiDbUnloadAcpiTable (AcpiGbl_DbArgs[1]); break; case CMD_EXIT: diff --git a/sys/contrib/dev/acpica/components/events/evxfgpe.c b/sys/contrib/dev/acpica/components/events/evxfgpe.c index 3a43733..7befa99d 100644 --- a/sys/contrib/dev/acpica/components/events/evxfgpe.c +++ b/sys/contrib/dev/acpica/components/events/evxfgpe.c @@ -83,7 +83,7 @@ AcpiUpdateAllGpes ( ACPI_STATUS Status; - ACPI_FUNCTION_TRACE (AcpiUpdateGpes); + ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes); Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); @@ -298,7 +298,8 @@ AcpiSetupGpeForWake ( ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_NAMESPACE_NODE *DeviceNode; - ACPI_GPE_NOTIFY_INFO *NewNotify, *Notify; + ACPI_GPE_NOTIFY_INFO *Notify; + ACPI_GPE_NOTIFY_INFO *NewNotify; ACPI_CPU_FLAGS Flags; @@ -334,6 +335,11 @@ AcpiSetupGpeForWake ( return_ACPI_STATUS (AE_BAD_PARAMETER); } + /* + * Allocate a new notify object up front, in case it is needed. + * Memory allocation while holding a spinlock is a big no-no + * on some hosts. + */ NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); if (!NewNotify) { @@ -401,8 +407,12 @@ AcpiSetupGpeForWake ( GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; Status = AE_OK; + UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Delete the notify object if it was not used above */ + if (NewNotify) { ACPI_FREE (NewNotify); diff --git a/sys/contrib/dev/acpica/components/executer/exprep.c b/sys/contrib/dev/acpica/components/executer/exprep.c index 993f75b..dc40831 100644 --- a/sys/contrib/dev/acpica/components/executer/exprep.c +++ b/sys/contrib/dev/acpica/components/executer/exprep.c @@ -418,8 +418,8 @@ AcpiExPrepCommonFieldObject ( * * RETURN: Status * - * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type DefField and - * connect it to the parent Node. + * DESCRIPTION: Construct an object of type ACPI_OPERAND_OBJECT with a + * subtype of DefField and connect it to the parent Node. * ******************************************************************************/ diff --git a/sys/contrib/dev/acpica/components/executer/exresolv.c b/sys/contrib/dev/acpica/components/executer/exresolv.c index bc29bde..15ac718 100644 --- a/sys/contrib/dev/acpica/components/executer/exresolv.c +++ b/sys/contrib/dev/acpica/components/executer/exresolv.c @@ -165,7 +165,7 @@ AcpiExResolveObjectToValue ( StackDesc = *StackPtr; - /* This is an ACPI_OPERAND_OBJECT */ + /* This is an object of type ACPI_OPERAND_OBJECT */ switch (StackDesc->Common.Type) { diff --git a/sys/contrib/dev/acpica/components/executer/exstore.c b/sys/contrib/dev/acpica/components/executer/exstore.c index a66aa16..aeba0c3 100644 --- a/sys/contrib/dev/acpica/components/executer/exstore.c +++ b/sys/contrib/dev/acpica/components/executer/exstore.c @@ -68,15 +68,15 @@ AcpiExStoreObjectToIndex ( * FUNCTION: AcpiExStore * * PARAMETERS: *SourceDesc - Value to be stored - * *DestDesc - Where to store it. Must be an NS node - * or an ACPI_OPERAND_OBJECT of type + * *DestDesc - Where to store it. Must be an NS node + * or ACPI_OPERAND_OBJECT of type * Reference; * WalkState - Current walk state * * RETURN: Status * * DESCRIPTION: Store the value described by SourceDesc into the location - * described by DestDesc. Called by various interpreter + * described by DestDesc. Called by various interpreter * functions to store the result of an operation into * the destination operand -- not just simply the actual "Store" * ASL operator. diff --git a/sys/contrib/dev/acpica/components/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c index 45414ce..b2df4f8 100644 --- a/sys/contrib/dev/acpica/components/executer/exutils.c +++ b/sys/contrib/dev/acpica/components/executer/exutils.c @@ -121,7 +121,7 @@ AcpiExEnterInterpreter ( * * DESCRIPTION: Reacquire the interpreter execution region from within the * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with + * fatal system error. Used in conjunction with * RelinquishInterpreter * ******************************************************************************/ diff --git a/sys/contrib/dev/acpica/components/hardware/hwsleep.c b/sys/contrib/dev/acpica/components/hardware/hwsleep.c index f5a9eba..2a80c25 100644 --- a/sys/contrib/dev/acpica/components/hardware/hwsleep.c +++ b/sys/contrib/dev/acpica/components/hardware/hwsleep.c @@ -100,20 +100,6 @@ AcpiHwLegacySleep ( return_ACPI_STATUS (Status); } - if (SleepState != ACPI_STATE_S5) - { - /* - * Disable BM arbitration. This feature is contained within an - * optional register (PM2 Control), so ignore a BAD_ADDRESS - * exception. - */ - Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1); - if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS)) - { - return_ACPI_STATUS (Status); - } - } - /* * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs @@ -394,17 +380,6 @@ AcpiHwLegacyWake ( AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId, ACPI_CLEAR_STATUS); - /* - * Enable BM arbitration. This feature is contained within an - * optional register (PM2 Control), so ignore a BAD_ADDRESS - * exception. - */ - Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0); - if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS)) - { - return_ACPI_STATUS (Status); - } - AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS (Status); } diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c index fa6fec8..bd7abea 100644 --- a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c +++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c @@ -101,6 +101,14 @@ AcpiSetFirmwareWakingVector ( ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + /* Set the 32-bit vector */ AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; diff --git a/sys/contrib/dev/acpica/components/namespace/nspredef.c b/sys/contrib/dev/acpica/components/namespace/nspredef.c index 9ce2405..fd003fb 100644 --- a/sys/contrib/dev/acpica/components/namespace/nspredef.c +++ b/sys/contrib/dev/acpica/components/namespace/nspredef.c @@ -681,7 +681,7 @@ AcpiNsCheckPackage ( { /* Create the new outer package and populate it */ - Status = AcpiNsWrapWithPackage (Data, *Elements, ReturnObjectPtr); + Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr); if (ACPI_FAILURE (Status)) { return (Status); diff --git a/sys/contrib/dev/acpica/components/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c index 2cfd066..f65591e 100644 --- a/sys/contrib/dev/acpica/components/parser/psxface.c +++ b/sys/contrib/dev/acpica/components/parser/psxface.c @@ -348,8 +348,8 @@ AcpiPsExecuteMethod ( } /* - * Start method evaluation with an implicit return of zero. This is done - * for Windows compatibility. + * Start method evaluation with an implicit return of zero. + * This is done for Windows compatibility. */ if (AcpiGbl_EnableInterpreterSlack) { diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c index dd1f6ae..5fb3294 100644 --- a/sys/contrib/dev/acpica/components/resources/rscreate.c +++ b/sys/contrib/dev/acpica/components/resources/rscreate.c @@ -209,8 +209,8 @@ AcpiRsCreateResourceList ( * * FUNCTION: AcpiRsCreatePciRoutingTable * - * PARAMETERS: PackageObject - Pointer to an ACPI_OPERAND_OBJECT - * package + * PARAMETERS: PackageObject - Pointer to a package containing one + * of more ACPI_OPERAND_OBJECTs * OutputBuffer - Pointer to the user's buffer * * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. @@ -218,7 +218,7 @@ AcpiRsCreateResourceList ( * AE_BUFFER_OVERFLOW and OutputBuffer->Length will point * to the size buffer needed. * - * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT package and creates a + * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT package and creates a * linked list of PCI interrupt descriptions * * NOTE: It is the caller's responsibility to ensure that the start of the diff --git a/sys/contrib/dev/acpica/components/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c index 083e350..9e4e16a 100644 --- a/sys/contrib/dev/acpica/components/resources/rsutils.c +++ b/sys/contrib/dev/acpica/components/resources/rsutils.c @@ -181,7 +181,7 @@ AcpiRsMoveData ( /* * 16-, 32-, and 64-bit cases must use the move macros that perform - * endian conversion and/or accomodate hardware that cannot perform + * endian conversion and/or accommodate hardware that cannot perform * misaligned memory transfers */ case ACPI_RSC_MOVE16: diff --git a/sys/contrib/dev/acpica/components/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c index cbf8426..a4d8fa1 100644 --- a/sys/contrib/dev/acpica/components/tables/tbfadt.c +++ b/sys/contrib/dev/acpica/components/tables/tbfadt.c @@ -192,7 +192,7 @@ static ACPI_FADT_PM_INFO FadtPmInfoTable[] = * * PARAMETERS: GenericAddress - GAS struct to be initialized * SpaceId - ACPI Space ID for this register - * ByteWidth - Width of this register, in bytes + * ByteWidth - Width of this register * Address - Address of the register * * RETURN: None @@ -338,7 +338,7 @@ AcpiTbCreateLocalFadt ( */ if (Length > sizeof (ACPI_TABLE_FADT)) { - ACPI_WARNING ((AE_INFO, + ACPI_BIOS_WARNING ((AE_INFO, "FADT (revision %u) is longer than ACPI 5.0 version, " "truncating length %u to %u", Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT))); @@ -486,8 +486,9 @@ AcpiTbConvertFadt ( if (Address64->Address && Address32 && (Address64->Address != (UINT64) Address32)) { - ACPI_ERROR ((AE_INFO, - "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32", + ACPI_BIOS_ERROR ((AE_INFO, + "32/64X address mismatch in FADT/%s: " + "0x%8.8X/0x%8.8X%8.8X, using 32", FadtInfoTable[i].Name, Address32, ACPI_FORMAT_UINT64 (Address64->Address))); } @@ -546,7 +547,7 @@ AcpiTbValidateFadt ( if (AcpiGbl_FADT.Facs && (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs)) { - ACPI_WARNING ((AE_INFO, + ACPI_BIOS_WARNING ((AE_INFO, "32/64X FACS address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs))); @@ -557,7 +558,7 @@ AcpiTbValidateFadt ( if (AcpiGbl_FADT.Dsdt && (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt)) { - ACPI_WARNING ((AE_INFO, + ACPI_BIOS_WARNING ((AE_INFO, "32/64X DSDT address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt))); @@ -593,8 +594,8 @@ AcpiTbValidateFadt ( if (Address64->Address && (Address64->BitWidth != ACPI_MUL_8 (Length))) { - ACPI_WARNING ((AE_INFO, - "32/64X length mismatch in %s: %u/%u", + ACPI_BIOS_WARNING ((AE_INFO, + "32/64X length mismatch in FADT/%s: %u/%u", Name, ACPI_MUL_8 (Length), Address64->BitWidth)); } @@ -606,9 +607,9 @@ AcpiTbValidateFadt ( */ if (!Address64->Address || !Length) { - ACPI_ERROR ((AE_INFO, - "Required field %s has zero address and/or length:" - " 0x%8.8X%8.8X/0x%X", + ACPI_BIOS_ERROR ((AE_INFO, + "Required FADT field %s has zero address and/or length: " + "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } @@ -622,8 +623,8 @@ AcpiTbValidateFadt ( if ((Address64->Address && !Length) || (!Address64->Address && Length)) { - ACPI_WARNING ((AE_INFO, - "Optional field %s has zero address or length: " + ACPI_BIOS_WARNING ((AE_INFO, + "Optional FADT field %s has zero address or length: " "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } @@ -674,8 +675,8 @@ AcpiTbSetupFadtRegisters ( (FadtInfoTable[i].DefaultLength > 0) && (FadtInfoTable[i].DefaultLength != Target64->BitWidth)) { - ACPI_WARNING ((AE_INFO, - "Invalid length for %s: %u, using default %u", + ACPI_BIOS_WARNING ((AE_INFO, + "Invalid length for FADT/%s: %u, using default %u", FadtInfoTable[i].Name, Target64->BitWidth, FadtInfoTable[i].DefaultLength)); diff --git a/sys/contrib/dev/acpica/components/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c index b5a908c..f56144c 100644 --- a/sys/contrib/dev/acpica/components/tables/tbinstal.c +++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c @@ -157,8 +157,9 @@ AcpiTbAddTable ( (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3))) { - ACPI_ERROR ((AE_INFO, - "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx", + ACPI_BIOS_ERROR ((AE_INFO, + "Table has invalid signature [%4.4s] (0x%8.8X), " + "must be SSDT or OEMx", AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ? TableDesc->Pointer->Signature : "????", *(UINT32 *) TableDesc->Pointer->Signature)); diff --git a/sys/contrib/dev/acpica/components/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c index d053b19..0c9ca76 100644 --- a/sys/contrib/dev/acpica/components/tables/tbutils.c +++ b/sys/contrib/dev/acpica/components/tables/tbutils.c @@ -287,8 +287,9 @@ AcpiTbVerifyChecksum ( if (Checksum) { - ACPI_WARNING ((AE_INFO, - "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", + ACPI_BIOS_WARNING ((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", Table->Signature, Table->Checksum, (UINT8) (Table->Checksum - Checksum))); @@ -356,8 +357,9 @@ AcpiTbCheckDsdtHeader ( if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) { - ACPI_ERROR ((AE_INFO, - "The DSDT has been corrupted or replaced - old, new headers below")); + ACPI_BIOS_ERROR ((AE_INFO, + "The DSDT has been corrupted or replaced - " + "old, new headers below")); AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); @@ -460,27 +462,12 @@ AcpiTbInstallTable ( return; } - /* Skip SSDT when DSDT is overriden */ - - if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) && - (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & - ACPI_TABLE_ORIGIN_OVERRIDE)) - { - ACPI_INFO ((AE_INFO, - "%4.4s @ 0x%p Table override, replaced with:", ACPI_SIG_SSDT, - ACPI_CAST_PTR (void, Address))); - AcpiTbPrintTableHeader ( - AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Address, - AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer); - goto UnmapAndExit; - } - /* If a particular signature is expected (DSDT/FACS), it must match */ if (Signature && !ACPI_COMPARE_NAME (Table->Signature, Signature)) { - ACPI_ERROR ((AE_INFO, + ACPI_BIOS_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]", *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); goto UnmapAndExit; @@ -498,6 +485,19 @@ AcpiTbInstallTable ( TableDesc->Flags = ACPI_TABLE_ORIGIN_MAPPED; ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); + /* When DSDT is overriden, assume SSDT is also overriden with it */ + + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) && + (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & + ACPI_TABLE_ORIGIN_OVERRIDE)) + { + TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE; + ACPI_INFO ((AE_INFO, + "%4.4s %p Logical table override, replaced with %4.4s", + ACPI_SIG_SSDT, ACPI_CAST_PTR (void, Address), ACPI_SIG_DSDT)); + goto UnmapAndExit; + } + /* * ACPI Table Override: * @@ -599,7 +599,7 @@ AcpiTbGetRootTableEntry ( { /* Will truncate 64-bit address to 32 bits, issue warning */ - ACPI_WARNING ((AE_INFO, + ACPI_BIOS_WARNING ((AE_INFO, "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," " truncating", ACPI_FORMAT_UINT64 (Address64))); @@ -701,7 +701,8 @@ AcpiTbParseRootTable ( if (Length < sizeof (ACPI_TABLE_HEADER)) { - ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); + ACPI_BIOS_ERROR ((AE_INFO, + "Invalid table length 0x%X in RSDT/XSDT", Length)); return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } diff --git a/sys/contrib/dev/acpica/components/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c index dc03a2c..f4a1e52 100644 --- a/sys/contrib/dev/acpica/components/tables/tbxface.c +++ b/sys/contrib/dev/acpica/components/tables/tbxface.c @@ -1,7 +1,6 @@ /****************************************************************************** * - * Module Name: tbxface - Public interfaces to the ACPI subsystem - * ACPI table oriented interfaces + * Module Name: tbxface - ACPI table oriented external interfaces * *****************************************************************************/ @@ -46,18 +45,11 @@ #include <contrib/dev/acpica/include/acpi.h> #include <contrib/dev/acpica/include/accommon.h> -#include <contrib/dev/acpica/include/acnamesp.h> #include <contrib/dev/acpica/include/actables.h> #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME ("tbxface") -/* Local prototypes */ - -static ACPI_STATUS -AcpiTbLoadNamespace ( - void); - /******************************************************************************* * @@ -458,165 +450,6 @@ ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) /******************************************************************************* * - * FUNCTION: AcpiTbLoadNamespace - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in - * the RSDT/XSDT. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiTbLoadNamespace ( - void) -{ - ACPI_STATUS Status; - UINT32 i; - ACPI_TABLE_HEADER *NewDsdt; - - - ACPI_FUNCTION_TRACE (TbLoadNamespace); - - - (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - - /* - * Load the namespace. The DSDT is required, but any SSDT and - * PSDT tables are optional. Verify the DSDT. - */ - if (!AcpiGbl_RootTableList.CurrentTableCount || - !ACPI_COMPARE_NAME ( - &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), - ACPI_SIG_DSDT) || - ACPI_FAILURE (AcpiTbVerifyTable ( - &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) - { - Status = AE_NO_ACPI_TABLES; - goto UnlockAndExit; - } - - /* - * Save the DSDT pointer for simple access. This is the mapped memory - * address. We must take care here because the address of the .Tables - * array can change dynamically as tables are loaded at run-time. Note: - * .Pointer field is not validated until after call to AcpiTbVerifyTable. - */ - AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; - - /* - * Optionally copy the entire DSDT to local memory (instead of simply - * mapping it.) There are some BIOSs that corrupt or replace the original - * DSDT, creating the need for this option. Default is FALSE, do not copy - * the DSDT. - */ - if (AcpiGbl_CopyDsdtLocally) - { - NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); - if (NewDsdt) - { - AcpiGbl_DSDT = NewDsdt; - } - } - - /* - * Save the original DSDT header for detection of table corruption - * and/or replacement of the DSDT from outside the OS. - */ - ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, - sizeof (ACPI_TABLE_HEADER)); - - (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); - - /* Load and parse tables */ - - Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ - - (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) - { - if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), - ACPI_SIG_SSDT) && - !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), - ACPI_SIG_PSDT)) || - ACPI_FAILURE (AcpiTbVerifyTable ( - &AcpiGbl_RootTableList.Tables[i]))) - { - continue; - } - - /* Skip SSDT when DSDT is overriden */ - - if (ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), - ACPI_SIG_SSDT) && - (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & - ACPI_TABLE_ORIGIN_OVERRIDE)) - { - continue; - } - - /* Ignore errors while loading tables, get as many as possible */ - - (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); - (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); - (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - } - - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - -UnlockAndExit: - (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiLoadTables - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT - * - ******************************************************************************/ - -ACPI_STATUS -AcpiLoadTables ( - void) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (AcpiLoadTables); - - - /* Load the namespace from the tables */ - - Status = AcpiTbLoadNamespace (); - if (ACPI_FAILURE (Status)) - { - ACPI_EXCEPTION ((AE_INFO, Status, - "While loading namespace from ACPI tables")); - } - - return_ACPI_STATUS (Status); -} - -ACPI_EXPORT_SYMBOL (AcpiLoadTables) - - -/******************************************************************************* - * * FUNCTION: AcpiInstallTableHandler * * PARAMETERS: Handler - Table event handler diff --git a/sys/contrib/dev/acpica/components/tables/tbxfload.c b/sys/contrib/dev/acpica/components/tables/tbxfload.c new file mode 100644 index 0000000..a2cc15f --- /dev/null +++ b/sys/contrib/dev/acpica/components/tables/tbxfload.c @@ -0,0 +1,415 @@ +/****************************************************************************** + * + * Module Name: tbxfload - Table load/unload external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#define __TBXFLOAD_C__ + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/acnamesp.h> +#include <contrib/dev/acpica/include/actables.h> + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxfload") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiTbLoadNamespace ( + void); + + +/******************************************************************************* + * + * FUNCTION: AcpiLoadTables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLoadTables ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLoadTables); + + + /* Load the namespace from the tables */ + + Status = AcpiTbLoadNamespace (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While loading namespace from ACPI tables")); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLoadTables) + + +/******************************************************************************* + * + * FUNCTION: AcpiTbLoadNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiTbLoadNamespace ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + ACPI_TABLE_HEADER *NewDsdt; + + + ACPI_FUNCTION_TRACE (TbLoadNamespace); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* + * Load the namespace. The DSDT is required, but any SSDT and + * PSDT tables are optional. Verify the DSDT. + */ + if (!AcpiGbl_RootTableList.CurrentTableCount || + !ACPI_COMPARE_NAME ( + &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), + ACPI_SIG_DSDT) || + ACPI_FAILURE (AcpiTbVerifyTable ( + &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) + { + Status = AE_NO_ACPI_TABLES; + goto UnlockAndExit; + } + + /* + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time. Note: + * .Pointer field is not validated until after call to AcpiTbVerifyTable. + */ + AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; + + /* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ + if (AcpiGbl_CopyDsdtLocally) + { + NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); + if (NewDsdt) + { + AcpiGbl_DSDT = NewDsdt; + } + } + + /* + * Save the original DSDT header for detection of table corruption + * and/or replacement of the DSDT from outside the OS. + */ + ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, + sizeof (ACPI_TABLE_HEADER)); + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + + /* Load and parse tables */ + + Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_SSDT) && + !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_PSDT)) || + ACPI_FAILURE (AcpiTbVerifyTable ( + &AcpiGbl_RootTableList.Tables[i]))) + { + continue; + } + + /* Skip SSDT when it is overriden with DSDT */ + if (ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_SSDT) && + (AcpiGbl_RootTableList.Tables[i].Flags & + ACPI_TABLE_ORIGIN_OVERRIDE)) + { + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiLoadTable + * + * PARAMETERS: Table - Pointer to a buffer containing the ACPI + * table to be loaded. + * + * RETURN: Status + * + * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must + * be a valid ACPI table with a valid ACPI table header. + * Note1: Mainly intended to support hotplug addition of SSDTs. + * Note2: Does not copy the incoming table. User is reponsible + * to ensure that the table is not deleted or unmapped. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLoadTable ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_TABLE_DESC TableDesc; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (AcpiLoadTable); + + + /* Parameter validation */ + + if (!Table) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Init local table descriptor */ + + ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC)); + TableDesc.Address = ACPI_PTR_TO_PHYSADDR (Table); + TableDesc.Pointer = Table; + TableDesc.Length = Table->Length; + TableDesc.Flags = ACPI_TABLE_ORIGIN_UNKNOWN; + + /* Must acquire the interpreter lock during this operation */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Install the table and load it into the namespace */ + + ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); + Status = AcpiTbAddTable (&TableDesc, &TableIndex); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); + + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, + AcpiGbl_TableHandlerContext); + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLoadTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiUnloadParentTable + * + * PARAMETERS: Object - Handle to any namespace object owned by + * the table to be unloaded + * + * RETURN: Status + * + * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads + * the table and deletes all namespace objects associated with + * that table. Unloading of the DSDT is not allowed. + * Note: Mainly intended to support hotplug removal of SSDTs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUnloadParentTable ( + ACPI_HANDLE Object) +{ + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); + ACPI_STATUS Status = AE_NOT_EXIST; + ACPI_OWNER_ID OwnerId; + UINT32 i; + + + ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); + + + /* Parameter validation */ + + if (!Object) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * The node OwnerId is currently the same as the parent table ID. + * However, this could change in the future. + */ + OwnerId = Node->OwnerId; + if (!OwnerId) + { + /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ + + return_ACPI_STATUS (AE_TYPE); + } + + /* Must acquire the interpreter lock during this operation */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Find the table in the global table list */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) + { + continue; + } + + /* + * Allow unload of SSDT and OEMx tables only. Do not allow unload + * of the DSDT. No other types of tables should get here, since + * only these types can contain AML and thus are the only types + * that can create namespace objects. + */ + if (ACPI_COMPARE_NAME ( + AcpiGbl_RootTableList.Tables[i].Signature.Ascii, + ACPI_SIG_DSDT)) + { + Status = AE_TYPE; + break; + } + + /* Ensure the table is actually loaded */ + + if (!AcpiTbIsTableLoaded (i)) + { + Status = AE_NOT_EXIST; + break; + } + + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, + AcpiGbl_RootTableList.Tables[i].Pointer, + AcpiGbl_TableHandlerContext); + } + + /* + * Delete all namespace objects owned by this table. Note that + * these objects can appear anywhere in the namespace by virtue + * of the AML "Scope" operator. Thus, we need to track ownership + * by an ID, not simply a position within the hierarchy. + */ + Status = AcpiTbDeleteNamespaceByOwner (i); + if (ACPI_FAILURE (Status)) + { + break; + } + + Status = AcpiTbReleaseOwnerId (i); + AcpiTbSetTableLoadedFlag (i, FALSE); + break; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) diff --git a/sys/contrib/dev/acpica/components/tables/tbxfroot.c b/sys/contrib/dev/acpica/components/tables/tbxfroot.c index c6ade4e..bcb7ba3 100644 --- a/sys/contrib/dev/acpica/components/tables/tbxfroot.c +++ b/sys/contrib/dev/acpica/components/tables/tbxfroot.c @@ -234,7 +234,7 @@ AcpiFindRootPointer ( /* A valid RSDP was not found */ - ACPI_ERROR ((AE_INFO, "A valid RSDP was not found")); + ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); return_ACPI_STATUS (AE_NOT_FOUND); } diff --git a/sys/contrib/dev/acpica/components/utilities/utdecode.c b/sys/contrib/dev/acpica/components/utilities/utdecode.c index 689d495..ef423e9 100644 --- a/sys/contrib/dev/acpica/components/utilities/utdecode.c +++ b/sys/contrib/dev/acpica/components/utilities/utdecode.c @@ -51,47 +51,6 @@ ACPI_MODULE_NAME ("utdecode") -/******************************************************************************* - * - * FUNCTION: AcpiFormatException - * - * PARAMETERS: Status - The ACPI_STATUS code to be formatted - * - * RETURN: A string containing the exception text. A valid pointer is - * always returned. - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string - * It is here instead of utxface.c so it is always present. - * - ******************************************************************************/ - -const char * -AcpiFormatException ( - ACPI_STATUS Status) -{ - const char *Exception = NULL; - - - ACPI_FUNCTION_ENTRY (); - - - Exception = AcpiUtValidateException (Status); - if (!Exception) - { - /* Exception code was not recognized */ - - ACPI_ERROR ((AE_INFO, - "Unknown exception code: 0x%8.8X", Status)); - - Exception = "UNKNOWN_STATUS_CODE"; - } - - return (ACPI_CAST_PTR (const char, Exception)); -} - -ACPI_EXPORT_SYMBOL (AcpiFormatException) - - /* * Properties of the ACPI Object Types, both internal and external. * The table is indexed by values of ACPI_OBJECT_TYPE @@ -180,16 +139,17 @@ AcpiUtHexToAsciiChar ( const char *AcpiGbl_RegionTypes[ACPI_NUM_PREDEFINED_REGIONS] = { - "SystemMemory", - "SystemIO", - "PCI_Config", - "EmbeddedControl", - "SMBus", - "SystemCMOS", - "PCIBARTarget", - "IPMI", - "GeneralPurposeIo", - "GenericSerialBus" + "SystemMemory", /* 0x00 */ + "SystemIO", /* 0x01 */ + "PCI_Config", /* 0x02 */ + "EmbeddedControl", /* 0x03 */ + "SMBus", /* 0x04 */ + "SystemCMOS", /* 0x05 */ + "PCIBARTarget", /* 0x06 */ + "IPMI", /* 0x07 */ + "GeneralPurposeIo", /* 0x08 */ + "GenericSerialBus", /* 0x09 */ + "PCC" /* 0x0A */ }; diff --git a/sys/contrib/dev/acpica/components/utilities/utexcep.c b/sys/contrib/dev/acpica/components/utilities/utexcep.c new file mode 100644 index 0000000..0f38227 --- /dev/null +++ b/sys/contrib/dev/acpica/components/utilities/utexcep.c @@ -0,0 +1,174 @@ +/******************************************************************************* + * + * Module Name: utexcep - Exception code support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + + +#define __UTEXCEP_C__ + +#define ACPI_DEFINE_EXCEPTION_TABLE +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utexcep") + + +/******************************************************************************* + * + * FUNCTION: AcpiFormatException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII + * string. Returns "unknown status" string for invalid codes. + * + ******************************************************************************/ + +const char * +AcpiFormatException ( + ACPI_STATUS Status) +{ + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + Exception = AcpiUtValidateException (Status); + if (!Exception) + { + /* Exception code was not recognized */ + + ACPI_ERROR ((AE_INFO, + "Unknown exception code: 0x%8.8X", Status)); + + Exception = "UNKNOWN_STATUS_CODE"; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} + +ACPI_EXPORT_SYMBOL (AcpiFormatException) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. NULL if exception is + * not valid. + * + * DESCRIPTION: This function validates and translates an ACPI exception into + * an ASCII string. + * + ******************************************************************************/ + +const char * +AcpiUtValidateException ( + ACPI_STATUS Status) +{ + UINT32 SubStatus; + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Status is composed of two parts, a "type" and an actual code + */ + SubStatus = (Status & ~AE_CODE_MASK); + + switch (Status & AE_CODE_MASK) + { + case AE_CODE_ENVIRONMENTAL: + + if (SubStatus <= AE_CODE_ENV_MAX) + { + Exception = AcpiGbl_ExceptionNames_Env [SubStatus]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (SubStatus <= AE_CODE_PGM_MAX) + { + Exception = AcpiGbl_ExceptionNames_Pgm [SubStatus]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (SubStatus <= AE_CODE_TBL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Tbl [SubStatus]; + } + break; + + case AE_CODE_AML: + + if (SubStatus <= AE_CODE_AML_MAX) + { + Exception = AcpiGbl_ExceptionNames_Aml [SubStatus]; + } + break; + + case AE_CODE_CONTROL: + + if (SubStatus <= AE_CODE_CTRL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Ctrl [SubStatus]; + } + break; + + default: + break; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} diff --git a/sys/contrib/dev/acpica/components/utilities/utglobal.c b/sys/contrib/dev/acpica/components/utilities/utglobal.c index 9e74d7d..5bb5991 100644 --- a/sys/contrib/dev/acpica/components/utilities/utglobal.c +++ b/sys/contrib/dev/acpica/components/utilities/utglobal.c @@ -211,8 +211,9 @@ ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS] = * * RETURN: Status * - * DESCRIPTION: Init ACPICA globals. All globals that require specific - * initialization should be initialized here! + * DESCRIPTION: Initialize ACPICA globals. All globals that require specific + * initialization should be initialized here. This allows for + * a warm restart. * ******************************************************************************/ diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c index 62eb817..78cdbcd 100644 --- a/sys/contrib/dev/acpica/components/utilities/utmisc.c +++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c @@ -92,86 +92,6 @@ UtConvertBackslashes ( /******************************************************************************* * - * FUNCTION: AcpiUtValidateException - * - * PARAMETERS: Status - The ACPI_STATUS code to be formatted - * - * RETURN: A string containing the exception text. NULL if exception is - * not valid. - * - * DESCRIPTION: This function validates and translates an ACPI exception into - * an ASCII string. - * - ******************************************************************************/ - -const char * -AcpiUtValidateException ( - ACPI_STATUS Status) -{ - UINT32 SubStatus; - const char *Exception = NULL; - - - ACPI_FUNCTION_ENTRY (); - - - /* - * Status is composed of two parts, a "type" and an actual code - */ - SubStatus = (Status & ~AE_CODE_MASK); - - switch (Status & AE_CODE_MASK) - { - case AE_CODE_ENVIRONMENTAL: - - if (SubStatus <= AE_CODE_ENV_MAX) - { - Exception = AcpiGbl_ExceptionNames_Env [SubStatus]; - } - break; - - case AE_CODE_PROGRAMMER: - - if (SubStatus <= AE_CODE_PGM_MAX) - { - Exception = AcpiGbl_ExceptionNames_Pgm [SubStatus]; - } - break; - - case AE_CODE_ACPI_TABLES: - - if (SubStatus <= AE_CODE_TBL_MAX) - { - Exception = AcpiGbl_ExceptionNames_Tbl [SubStatus]; - } - break; - - case AE_CODE_AML: - - if (SubStatus <= AE_CODE_AML_MAX) - { - Exception = AcpiGbl_ExceptionNames_Aml [SubStatus]; - } - break; - - case AE_CODE_CONTROL: - - if (SubStatus <= AE_CODE_CTRL_MAX) - { - Exception = AcpiGbl_ExceptionNames_Ctrl [SubStatus]; - } - break; - - default: - break; - } - - return (ACPI_CAST_PTR (const char, Exception)); -} - - -/******************************************************************************* - * * FUNCTION: AcpiUtIsPciRootBridge * * PARAMETERS: Id - The HID/CID in string format diff --git a/sys/contrib/dev/acpica/components/utilities/utobject.c b/sys/contrib/dev/acpica/components/utilities/utobject.c index 9d90a39..09ff6cf 100644 --- a/sys/contrib/dev/acpica/components/utilities/utobject.c +++ b/sys/contrib/dev/acpica/components/utilities/utobject.c @@ -366,7 +366,7 @@ AcpiUtCreateStringObject ( * * RETURN: TRUE if object is valid, FALSE otherwise * - * DESCRIPTION: Validate a pointer to be an ACPI_OPERAND_OBJECT + * DESCRIPTION: Validate a pointer to be of type ACPI_OPERAND_OBJECT * ******************************************************************************/ @@ -392,7 +392,7 @@ AcpiUtValidInternalObject ( { case ACPI_DESC_TYPE_OPERAND: - /* The object appears to be a valid ACPI_OPERAND_OBJECT */ + /* The object appears to be a valid ACPI_OPERAND_OBJECT */ return (TRUE); @@ -473,7 +473,7 @@ AcpiUtDeleteObjectDesc ( ACPI_FUNCTION_TRACE_PTR (UtDeleteObjectDesc, Object); - /* Object must be an ACPI_OPERAND_OBJECT */ + /* Object must be of type ACPI_OPERAND_OBJECT */ if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) { diff --git a/sys/contrib/dev/acpica/components/utilities/utresrc.c b/sys/contrib/dev/acpica/components/utilities/utresrc.c index 494d3fe..a7c8fcc 100644 --- a/sys/contrib/dev/acpica/components/utilities/utresrc.c +++ b/sys/contrib/dev/acpica/components/utilities/utresrc.c @@ -1,6 +1,6 @@ /******************************************************************************* * - * Module Name: utresrc - Resource managment utilities + * Module Name: utresrc - Resource management utilities * ******************************************************************************/ @@ -57,7 +57,7 @@ /* * Strings used to decode resource descriptors. - * Used by both the disasssembler and the debugger resource dump routines + * Used by both the disassembler and the debugger resource dump routines */ const char *AcpiGbl_BmDecode[] = { diff --git a/sys/contrib/dev/acpica/components/utilities/utxferror.c b/sys/contrib/dev/acpica/components/utilities/utxferror.c index 09df461..0db86ab 100644 --- a/sys/contrib/dev/acpica/components/utilities/utxferror.c +++ b/sys/contrib/dev/acpica/components/utilities/utxferror.c @@ -87,6 +87,9 @@ extern FILE *AcpiGbl_OutputFile; #define ACPI_MSG_WARNING "ACPI Warning: " #define ACPI_MSG_INFO "ACPI: " +#define ACPI_MSG_BIOS_ERROR "ACPI Firmware Error: " +#define ACPI_MSG_BIOS_WARNING "ACPI Firmware Warning: " + /* * Common message suffix */ @@ -257,6 +260,84 @@ AcpiInfo ( ACPI_EXPORT_SYMBOL (AcpiInfo) +/******************************************************************************* + * + * FUNCTION: AcpiBiosError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Firmware Error" message with module/line/version + * info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiBiosError) + + +/******************************************************************************* + * + * FUNCTION: AcpiBiosWarning + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Firmware Warning" message with module/line/version + * info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_BIOS_WARNING); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiBiosWarning) + + /* * The remainder of this module contains internal error functions that may * be configured out. diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h index f89cf37..5c91c87 100644 --- a/sys/contrib/dev/acpica/include/acdebug.h +++ b/sys/contrib/dev/acpica/include/acdebug.h @@ -112,8 +112,7 @@ AcpiDbDisplayTemplate ( void AcpiDbUnloadAcpiTable ( - char *TableArg, - char *InstanceArg); + char *Name); void AcpiDbSendNotify ( diff --git a/sys/contrib/dev/acpica/include/acexcep.h b/sys/contrib/dev/acpica/include/acexcep.h index 10f5a11..856a359 100644 --- a/sys/contrib/dev/acpica/include/acexcep.h +++ b/sys/contrib/dev/acpica/include/acexcep.h @@ -53,6 +53,7 @@ #define AE_CODE_ACPI_TABLES 0x2000 #define AE_CODE_AML 0x3000 #define AE_CODE_CONTROL 0x4000 +#define AE_CODE_MAX 0x4000 #define AE_CODE_MASK 0xF000 @@ -188,7 +189,7 @@ /* Exception strings for AcpiFormatException */ -#ifdef DEFINE_ACPI_GLOBALS +#ifdef ACPI_DEFINE_EXCEPTION_TABLE /* * String versions of the exception codes above @@ -307,6 +308,6 @@ char const *AcpiGbl_ExceptionNames_Ctrl[] = "AE_CTRL_PARSE_PENDING" }; -#endif /* ACPI GLOBALS */ +#endif /* EXCEPTION_TABLE */ #endif /* __ACEXCEP_H__ */ diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h index 5535c1d..1fc2bc6 100644 --- a/sys/contrib/dev/acpica/include/acglobal.h +++ b/sys/contrib/dev/acpica/include/acglobal.h @@ -287,17 +287,8 @@ ACPI_EXTERN UINT8 AcpiGbl_OsiData; ACPI_EXTERN ACPI_INTERFACE_INFO *AcpiGbl_SupportedInterfaces; ACPI_EXTERN ACPI_ADDRESS_RANGE *AcpiGbl_AddressRangeList[ACPI_ADDRESS_RANGE_MAX]; - #ifndef DEFINE_ACPI_GLOBALS -/* Exception codes */ - -extern char const *AcpiGbl_ExceptionNames_Env[]; -extern char const *AcpiGbl_ExceptionNames_Pgm[]; -extern char const *AcpiGbl_ExceptionNames_Tbl[]; -extern char const *AcpiGbl_ExceptionNames_Aml[]; -extern char const *AcpiGbl_ExceptionNames_Ctrl[]; - /* Other miscellaneous */ extern BOOLEAN AcpiGbl_Shutdown; diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h index cdb9cb1..591bb6b 100644 --- a/sys/contrib/dev/acpica/include/acmacros.h +++ b/sys/contrib/dev/acpica/include/acmacros.h @@ -274,8 +274,8 @@ #define ACPI_INSERT_BITS(Target, Mask, Source) Target = ((Target & (~(Mask))) | (Source & Mask)) /* - * An ACPI_NAMESPACE_NODE can appear in some contexts - * where a pointer to an ACPI_OPERAND_OBJECT can also + * An object of type ACPI_NAMESPACE_NODE can appear in some contexts + * where a pointer to an object of type ACPI_OPERAND_OBJECT can also * appear. This macro is used to distinguish them. * * The "Descriptor" field is the first field in both structures. diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h index e0f4a52..daf1aff 100644 --- a/sys/contrib/dev/acpica/include/acobject.h +++ b/sys/contrib/dev/acpica/include/acobject.h @@ -123,8 +123,8 @@ typedef struct acpi_object_integer /* - * Note: The String and Buffer object must be identical through the Pointer - * and Length elements. There is code that depends on this. + * Note: The String and Buffer object must be identical through the + * pointer and length elements. There is code that depends on this. * * Fields common to both Strings and Buffers */ diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h index a1d89d4..193d0ac 100644 --- a/sys/contrib/dev/acpica/include/acoutput.h +++ b/sys/contrib/dev/acpica/include/acoutput.h @@ -217,6 +217,8 @@ #define ACPI_WARNING(plist) AcpiWarning plist #define ACPI_EXCEPTION(plist) AcpiException plist #define ACPI_ERROR(plist) AcpiError plist +#define ACPI_BIOS_WARNING(plist) AcpiBiosWarning plist +#define ACPI_BIOS_ERROR(plist) AcpiBiosError plist #define ACPI_DEBUG_OBJECT(obj,l,i) AcpiExDoDebugObject(obj,l,i) #else @@ -227,6 +229,8 @@ #define ACPI_WARNING(plist) #define ACPI_EXCEPTION(plist) #define ACPI_ERROR(plist) +#define ACPI_BIOS_WARNING(plist) +#define ACPI_BIOS_ERROR(plist) #define ACPI_DEBUG_OBJECT(obj,l,i) #endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h index 9e1bcf1..4fdc7c6 100644 --- a/sys/contrib/dev/acpica/include/acpixf.h +++ b/sys/contrib/dev/acpica/include/acpixf.h @@ -48,7 +48,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20120620 +#define ACPI_CA_VERSION 0x20120711 #include <contrib/dev/acpica/include/acconfig.h> #include <contrib/dev/acpica/include/actypes.h> @@ -201,6 +201,22 @@ AcpiFree ( /* + * ACPI table load/unload interfaces + */ +ACPI_STATUS +AcpiLoadTable ( + ACPI_TABLE_HEADER *Table); + +ACPI_STATUS +AcpiUnloadParentTable ( + ACPI_HANDLE Object); + +ACPI_STATUS +AcpiLoadTables ( + void); + + +/* * ACPI table manipulation interfaces */ ACPI_STATUS @@ -212,10 +228,6 @@ AcpiFindRootPointer ( ACPI_SIZE *RsdpAddress); ACPI_STATUS -AcpiLoadTables ( - void); - -ACPI_STATUS AcpiGetTableHeader ( ACPI_STRING Signature, UINT32 Instance, @@ -757,6 +769,20 @@ AcpiInfo ( const char *Format, ...) ACPI_PRINTF_LIKE(3); +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) ACPI_PRINTF_LIKE(3); + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) ACPI_PRINTF_LIKE(3); + /* * Debug output diff --git a/sys/contrib/dev/acpica/include/actbl1.h b/sys/contrib/dev/acpica/include/actbl1.h index 824135d..c24178f 100644 --- a/sys/contrib/dev/acpica/include/actbl1.h +++ b/sys/contrib/dev/acpica/include/actbl1.h @@ -130,7 +130,7 @@ typedef struct acpi_table_bert { ACPI_TABLE_HEADER Header; /* Common ACPI table header */ UINT32 RegionLength; /* Length of the boot error region */ - UINT64 Address; /* Physical addresss of the error region */ + UINT64 Address; /* Physical address of the error region */ } ACPI_TABLE_BERT; diff --git a/sys/contrib/dev/acpica/include/platform/acenv.h b/sys/contrib/dev/acpica/include/platform/acenv.h index 922e24a..e82d9bb 100644 --- a/sys/contrib/dev/acpica/include/platform/acenv.h +++ b/sys/contrib/dev/acpica/include/platform/acenv.h @@ -108,9 +108,9 @@ #endif #ifdef ACPI_HELP_APP -#define ACPI_DEBUG_OUTPUT #define ACPI_APPLICATION #define ACPI_SINGLE_THREADED +#define ACPI_NO_ERROR_MESSAGES #endif /* Linkable ACPICA library */ diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c index 54ddfdc..c0f592c 100644 --- a/sys/dev/agp/agp_i810.c +++ b/sys/dev/agp/agp_i810.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> +#include <machine/md_var.h> #include <sys/rman.h> MALLOC_DECLARE(M_AGP); @@ -1438,7 +1439,7 @@ agp_i810_attach(device_t dev) if (error) return (error); - if (ptoa((vm_paddr_t)realmem) > + if (ptoa((vm_paddr_t)Maxmem) > (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) { device_printf(dev, "agp_i810 does not support physical " "memory above %ju.\n", (uintmax_t)(1ULL << diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c index 5a8046d..dea1736 100644 --- a/sys/dev/ath/ath_hal/ah.c +++ b/sys/dev/ath/ath_hal/ah.c @@ -630,6 +630,34 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_CAP_REG_FLAG: *result = AH_PRIVATE(ah)->ah_currentRDext; return HAL_OK; + case HAL_CAP_ENHANCED_DMA_SUPPORT: + return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_NUM_TXMAPS: + *result = pCap->halNumTxMaps; + return HAL_OK; + case HAL_CAP_TXDESCLEN: + *result = pCap->halTxDescLen; + return HAL_OK; + case HAL_CAP_TXSTATUSLEN: + *result = pCap->halTxStatusLen; + return HAL_OK; + case HAL_CAP_RXSTATUSLEN: + *result = pCap->halRxStatusLen; + return HAL_OK; + case HAL_CAP_RXFIFODEPTH: + switch (capability) { + case HAL_RX_QUEUE_HP: + *result = pCap->halRxHpFifoDepth; + return HAL_OK; + case HAL_RX_QUEUE_LP: + *result = pCap->halRxLpFifoDepth; + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_RXBUFSIZE: + case HAL_CAP_NUM_MR_RETRIES: + return HAL_EINVAL; /* XXX not yet */ case HAL_CAP_BT_COEX: return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_HT20_SGI: @@ -667,6 +695,7 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP; + default: return HAL_EINVAL; } diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index 9cc7e75..aa3e8b6 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -149,9 +149,14 @@ typedef enum { HAL_CAP_TS = 72, /* 3 stream */ HAL_CAP_ENHANCED_DMA_SUPPORT = 75, /* DMA FIFO support */ + HAL_CAP_NUM_TXMAPS = 76, /* Number of buffers in a transmit descriptor */ + HAL_CAP_TXDESCLEN = 77, /* Length of transmit descriptor */ + HAL_CAP_TXSTATUSLEN = 78, /* Length of transmit status descriptor */ + HAL_CAP_RXSTATUSLEN = 79, /* Length of transmit status descriptor */ + HAL_CAP_RXFIFODEPTH = 80, /* Receive hardware FIFO depth */ + HAL_CAP_RXBUFSIZE = 81, /* Receive Buffer Length */ + HAL_CAP_NUM_MR_RETRIES = 82, /* limit on multirate retries */ - HAL_CAP_RXBUFSIZE = 81, - HAL_CAP_NUM_MR_RETRIES = 82, HAL_CAP_OL_PWRCTRL = 84, /* Open loop TX power control */ HAL_CAP_BB_PANIC_WATCHDOG = 92, @@ -210,7 +215,7 @@ typedef enum { typedef enum { HAL_RX_QUEUE_HP = 0, /* high priority recv queue */ - HAL_RX_QUEUE_LP = 0, /* low priority recv queue */ + HAL_RX_QUEUE_LP = 1, /* low priority recv queue */ } HAL_RX_QUEUE; #define HAL_NUM_RX_QUEUES 2 /* max possible # of queues */ @@ -404,7 +409,10 @@ typedef enum { */ typedef enum { HAL_INT_RX = 0x00000001, /* Non-common mapping */ - HAL_INT_RXDESC = 0x00000002, + HAL_INT_RXDESC = 0x00000002, /* Legacy mapping */ + HAL_INT_RXHP = 0x00000001, /* EDMA */ + HAL_INT_RXLP = 0x00000002, /* EDMA */ + HAL_INT_RXERR = 0x00000004, HAL_INT_RXNOFRM = 0x00000008, HAL_INT_RXEOL = 0x00000010, HAL_INT_RXORN = 0x00000020, @@ -1078,8 +1086,8 @@ struct ath_hal { const struct ath_desc *ds, int *rates, int *tries); /* Receive Functions */ - uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*); - void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp); + uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*, HAL_RX_QUEUE); + void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp, HAL_RX_QUEUE); void __ahdecl(*ah_enableReceive)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_stopDmaReceive)(struct ath_hal*); void __ahdecl(*ah_startPcuReceive)(struct ath_hal*); diff --git a/sys/dev/ath/ath_hal/ah_debug.h b/sys/dev/ath/ath_hal/ah_debug.h index bd1a251..6cd2627 100644 --- a/sys/dev/ath/ath_hal/ah_debug.h +++ b/sys/dev/ath/ath_hal/ah_debug.h @@ -47,6 +47,11 @@ enum { HAL_DEBUG_DIVERSITY = 0x00100000, /* diversity debugging */ HAL_DEBUG_DFS = 0x00200000, /* DFS debugging */ HAL_DEBUG_HANG = 0x00400000, /* BB/MAC hang debugging */ + HAL_DEBUG_CALIBRATE = 0x00800000, /* setup calibration */ + HAL_DEBUG_POWER_MGMT = 0x01000000, /* power calibration */ + HAL_DEBUG_CHANNEL = 0x02000000, + HAL_DEBUG_QUEUE = 0x04000000, + HAL_DEBUG_PRINT_REG = 0x08000000, HAL_DEBUG_UNMASKABLE = 0x80000000, /* always printed */ HAL_DEBUG_ANY = 0xffffffff diff --git a/sys/dev/ath/ath_hal/ah_desc.h b/sys/dev/ath/ath_hal/ah_desc.h index 48c7a3e..1203ebb 100644 --- a/sys/dev/ath/ath_hal/ah_desc.h +++ b/sys/dev/ath/ath_hal/ah_desc.h @@ -122,11 +122,12 @@ struct ath_rx_status { int8_t rs_rssi_ext[3]; /* rx frame RSSI [ext, chain 0-2] */ uint8_t rs_isaggr; /* is part of the aggregate */ uint8_t rs_moreaggr; /* more frames in aggr to follow */ + uint16_t rs_flags; /* misc flags */ uint8_t rs_num_delims; /* number of delims in aggr */ - uint8_t rs_flags; /* misc flags */ + uint8_t rs_spare0; /* padding */ uint32_t rs_evm0; /* evm bytes */ uint32_t rs_evm1; - uint32_t rs_evm2; + uint32_t rs_evm2; uint32_t rs_evm3; /* needed for ar9300 and later */ uint32_t rs_evm4; /* needed for ar9300 and later */ #endif /* AH_SUPPORT_AR5416 */ @@ -138,16 +139,19 @@ struct ath_rx_status { #define HAL_RXERR_FIFO 0x04 /* fifo overrun */ #define HAL_RXERR_DECRYPT 0x08 /* non-Michael decrypt error */ #define HAL_RXERR_MIC 0x10 /* Michael MIC decrypt error */ +#define HAL_RXERR_INCOMP 0x20 /* Rx Desc processing is incomplete */ +#define HAL_RXERR_KEYMISS 0x40 /* Key not found in keycache */ /* bits found in rs_flags */ -#define HAL_RX_MORE 0x01 /* more descriptors follow */ -#define HAL_RX_MORE_AGGR 0x02 /* more frames in aggr */ -#define HAL_RX_GI 0x04 /* full gi */ -#define HAL_RX_2040 0x08 /* 40 Mhz */ -#define HAL_RX_DELIM_CRC_PRE 0x10 /* crc error in delimiter pre */ -#define HAL_RX_DELIM_CRC_POST 0x20 /* crc error in delim after */ -#define HAL_RX_DECRYPT_BUSY 0x40 /* decrypt was too slow */ -#define HAL_RX_HI_RX_CHAIN 0x80 /* SM power save: hi Rx chain control */ +#define HAL_RX_MORE 0x0001 /* more descriptors follow */ +#define HAL_RX_MORE_AGGR 0x0002 /* more frames in aggr */ +#define HAL_RX_GI 0x0004 /* full gi */ +#define HAL_RX_2040 0x0008 /* 40 Mhz */ +#define HAL_RX_DELIM_CRC_PRE 0x0010 /* crc error in delimiter pre */ +#define HAL_RX_DELIM_CRC_POST 0x0020 /* crc error in delim after */ +#define HAL_RX_DECRYPT_BUSY 0x0040 /* decrypt was too slow */ +#define HAL_RX_HI_RX_CHAIN 0x0080 /* SM power save: hi Rx chain control */ +#define HAL_RX_IS_APSD 0x0100 /* Is ASPD trigger frame */ enum { HAL_PHYERR_UNDERRUN = 0, /* Transmit underrun */ @@ -178,6 +182,8 @@ enum { HAL_PHYERR_HT_CRC_ERROR = 34, /* */ HAL_PHYERR_HT_LENGTH_ILLEGAL = 35, /* */ HAL_PHYERR_HT_RATE_ILLEGAL = 36, /* */ + + HAL_PHYERR_SPECTRAL = 38, }; /* value found in rs_keyix to mark invalid entries */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h index 68e3af5..657e250 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210.h +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -180,8 +180,8 @@ extern void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); extern HAL_BOOL ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *, int *rates, int *tries); -extern uint32_t ar5210GetRxDP(struct ath_hal *); -extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp); +extern uint32_t ar5210GetRxDP(struct ath_hal *, HAL_RX_QUEUE); +extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5210EnableReceive(struct ath_hal *); extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *); extern void ar5210StartPcuReceive(struct ath_hal *); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c index bdb4d57..3a1220b 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c @@ -30,8 +30,10 @@ * Get the RXDP. */ uint32_t -ar5210GetRxDP(struct ath_hal *ah) +ar5210GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); return OS_REG_READ(ah, AR_RXDP); } @@ -39,8 +41,10 @@ ar5210GetRxDP(struct ath_hal *ah) * Set the RxDP. */ void -ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp) +ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); OS_REG_WRITE(ah, AR_RXDP, rxdp); } diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h index 122206b..1d6c8af 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h @@ -205,8 +205,8 @@ extern void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); extern HAL_BOOL ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries); -extern uint32_t ar5211GetRxDP(struct ath_hal *); -extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp); +extern uint32_t ar5211GetRxDP(struct ath_hal *, HAL_RX_QUEUE); +extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5211EnableReceive(struct ath_hal *); extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *); extern void ar5211StartPcuReceive(struct ath_hal *); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c index 733559e..27c4835 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c @@ -30,8 +30,10 @@ * Get the RXDP. */ uint32_t -ar5211GetRxDP(struct ath_hal *ah) +ar5211GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); return OS_REG_READ(ah, AR_RXDP); } @@ -39,8 +41,10 @@ ar5211GetRxDP(struct ath_hal *ah) * Set the RxDP. */ void -ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp) +ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); OS_REG_WRITE(ah, AR_RXDP, rxdp); HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); } diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h index d651691..a8b95d1 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h @@ -519,8 +519,8 @@ extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, extern HAL_POWER_MODE ar5212GetPowerMode(struct ath_hal *ah); extern HAL_BOOL ar5212GetPowerStatus(struct ath_hal *ah); -extern uint32_t ar5212GetRxDP(struct ath_hal *ath); -extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp); +extern uint32_t ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE); +extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5212EnableReceive(struct ath_hal *ah); extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah); extern void ar5212StartPcuReceive(struct ath_hal *ah); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c index db4f93d..00b04ca 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c @@ -29,8 +29,10 @@ * Get the RXDP. */ uint32_t -ar5212GetRxDP(struct ath_hal *ath) +ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); return OS_REG_READ(ath, AR_RXDP); } @@ -38,8 +40,10 @@ ar5212GetRxDP(struct ath_hal *ath) * Set the RxDP. */ void -ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp) +ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) { + + HALASSERT(qtype == HAL_RX_QUEUE_HP); OS_REG_WRITE(ah, AR_RXDP, rxdp); HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); } diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index c5dc03f..965a1fd 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -116,9 +116,6 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/ath_tx99/ath_tx99.h> #endif -#define ATH_KTR_INTR KTR_SPARE4 -#define ATH_KTR_ERR KTR_SPARE3 - /* * ATH_BCBUF determines the number of vap's that can transmit * beacons and also (currently) the number of vap's that can @@ -157,8 +154,6 @@ static void ath_update_promisc(struct ifnet *); static void ath_updateslot(struct ifnet *); static void ath_bstuck_proc(void *, int); static void ath_reset_proc(void *, int); -static void ath_descdma_cleanup(struct ath_softc *sc, - struct ath_descdma *, ath_bufhead *); static int ath_desc_alloc(struct ath_softc *); static void ath_desc_free(struct ath_softc *); static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *, @@ -239,15 +234,15 @@ static int ath_anicalinterval = 100; /* ANI calibration - 100 msec */ SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval, 0, "ANI calibration (msecs)"); -static int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */ +int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */ SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, 0, "rx buffers allocated"); TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf); -static int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ +int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf, 0, "tx buffers allocated"); TUNABLE_INT("hw.ath.txbuf", &ath_txbuf); -static int ath_txbuf_mgmt = ATH_MGMT_TXBUF; /* # mgmt tx buffers to allocate */ +int ath_txbuf_mgmt = ATH_MGMT_TXBUF; /* # mgmt tx buffers to allocate */ SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RW, &ath_txbuf_mgmt, 0, "tx (mgmt) buffers allocated"); TUNABLE_INT("hw.ath.txbuf_mgmt", &ath_txbuf_mgmt); @@ -308,9 +303,10 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) * * This is required before the descriptors are allocated. */ - if (ath_hal_hasedma(sc->sc_ah)) + if (ath_hal_hasedma(sc->sc_ah)) { + sc->sc_isedma = 1; ath_recv_setup_edma(sc); - else + } else ath_recv_setup_legacy(sc); /* @@ -378,6 +374,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) if_printf(ifp, "failed to allocate descriptors: %d\n", error); goto bad; } + + error = ath_rxdma_setup(sc); + if (error != 0) { + if_printf(ifp, "failed to allocate RX descriptors: %d\n", + error); + goto bad; + } + callout_init_mtx(&sc->sc_cal_ch, &sc->sc_mtx, 0); callout_init_mtx(&sc->sc_wd_ch, &sc->sc_mtx, 0); @@ -854,6 +858,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) bad2: ath_tx_cleanup(sc); ath_desc_free(sc); + ath_rxdma_teardown(sc); bad: if (ah) ath_hal_detach(ah); @@ -896,6 +901,7 @@ ath_detach(struct ath_softc *sc) ath_dfs_detach(sc); ath_desc_free(sc); + ath_rxdma_teardown(sc); ath_tx_cleanup(sc); ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */ if_free(ifp); @@ -1615,7 +1621,11 @@ ath_intr(void *arg) /* bump tx trigger level */ ath_hal_updatetxtriglevel(ah, AH_TRUE); } - if (status & HAL_INT_RX) { + /* + * Handle both the legacy and RX EDMA interrupt bits. + * Note that HAL_INT_RXLP is also HAL_INT_RXDESC. + */ + if (status & (HAL_INT_RX | HAL_INT_RXHP | HAL_INT_RXLP)) { sc->sc_stats.ast_rx_intr++; taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); } @@ -1861,6 +1871,14 @@ ath_init(void *arg) sc->sc_imask = HAL_INT_RX | HAL_INT_TX | HAL_INT_RXEOL | HAL_INT_RXORN | HAL_INT_FATAL | HAL_INT_GLOBAL; + + /* + * Enable RX EDMA bits. Note these overlap with + * HAL_INT_RX and HAL_INT_RXDESC respectively. + */ + if (sc->sc_isedma) + sc->sc_imask |= (HAL_INT_RXHP | HAL_INT_RXLP); + /* * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. @@ -2594,6 +2612,13 @@ ath_mode_init(struct ath_softc *sc) /* configure operational mode */ ath_hal_setopmode(ah); + DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_MODE, + "%s: ah=%p, ifp=%p, if_addr=%p\n", + __func__, + ah, + ifp, + (ifp == NULL) ? NULL : ifp->if_addr); + /* handle any link-level address change */ ath_hal_setmac(ah, IF_LLADDR(ifp)); @@ -2724,7 +2749,7 @@ ath_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) *paddr = segs->ds_addr; } -static int +int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head, const char *name, int nbuf, int ndesc) @@ -2863,7 +2888,7 @@ fail0: #undef ATH_DESC_4KB_BOUND_CHECK } -static void +void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head) { @@ -2904,15 +2929,9 @@ ath_desc_alloc(struct ath_softc *sc) { int error; - error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, - "rx", ath_rxbuf, 1); - if (error != 0) - return error; - error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, "tx", ath_txbuf, ATH_TXDESC); if (error != 0) { - ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); return error; } sc->sc_txbuf_cnt = ath_txbuf; @@ -2920,7 +2939,6 @@ ath_desc_alloc(struct ath_softc *sc) error = ath_descdma_setup(sc, &sc->sc_txdma_mgmt, &sc->sc_txbuf_mgmt, "tx_mgmt", ath_txbuf_mgmt, ATH_TXDESC); if (error != 0) { - ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); return error; } @@ -2933,7 +2951,6 @@ ath_desc_alloc(struct ath_softc *sc) error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf, "beacon", ATH_BCBUF, 1); if (error != 0) { - ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); ath_descdma_cleanup(sc, &sc->sc_txdma_mgmt, &sc->sc_txbuf_mgmt); @@ -2950,8 +2967,6 @@ ath_desc_free(struct ath_softc *sc) ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf); if (sc->sc_txdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); - if (sc->sc_rxdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); if (sc->sc_txdma_mgmt.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->sc_txdma_mgmt, &sc->sc_txbuf_mgmt); diff --git a/sys/dev/ath/if_ath_debug.c b/sys/dev/ath/if_ath_debug.c index 0b49a06..da898be 100644 --- a/sys/dev/ath/if_ath_debug.c +++ b/sys/dev/ath/if_ath_debug.c @@ -118,6 +118,16 @@ ath_printrxbuf(struct ath_softc *sc, const struct ath_buf *bf, ds->ds_hw[2], ds->ds_hw[3], ds->ds_hw[4], ds->ds_hw[5], ds->ds_hw[6], ds->ds_hw[7], ds->ds_hw[8]); + } else if (ah->ah_magic == 0x19741014) { + printf(" %08x %08x %08x %08x %08x %08x %08x\n", + ds->ds_hw[2], ds->ds_hw[3], ds->ds_hw[4], + ds->ds_hw[5], ds->ds_hw[6], ds->ds_hw[7], + ds->ds_hw[8]); + + printf(" %08x %08x %08x %08x %08x %08x %08x\n", + ds->ds_hw[9], ds->ds_hw[10], ds->ds_hw[11], + ds->ds_hw[12], ds->ds_hw[13], ds->ds_hw[14], + ds->ds_hw[15]); } } } diff --git a/sys/dev/ath/if_ath_debug.h b/sys/dev/ath/if_ath_debug.h index ff514ce..2e6ebf5 100644 --- a/sys/dev/ath/if_ath_debug.h +++ b/sys/dev/ath/if_ath_debug.h @@ -64,9 +64,14 @@ enum { ATH_DEBUG_SW_TX_RETRIES = 0x040000000ULL, /* software TX retries */ ATH_DEBUG_FATAL = 0x080000000ULL, /* fatal errors */ ATH_DEBUG_SW_TX_BAR = 0x100000000ULL, /* BAR TX */ + ATH_DEBUG_EDMA_RX = 0x200000000ULL, /* RX EDMA state */ + ATH_DEBUG_ANY = 0xffffffffffffffffULL }; +#define ATH_KTR_INTR KTR_SPARE4 +#define ATH_KTR_ERR KTR_SPARE3 + extern uint64_t ath_debug; #define IFF_DUMPPKTS(sc, m) \ @@ -86,6 +91,9 @@ extern void ath_printrxbuf(struct ath_softc *, const struct ath_buf *bf, extern void ath_printtxbuf(struct ath_softc *, const struct ath_buf *bf, u_int qnum, u_int ix, int done); #else /* ATH_DEBUG */ +#define ATH_KTR_INTR 0 +#define ATH_KTR_ERR 0 + #define IFF_DUMPPKTS(sc, m) \ ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) #define DPRINTF(sc, m, fmt, ...) do { \ diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index 4c1d24b..0a51fee 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -48,6 +48,10 @@ ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) +extern int ath_rxbuf; +extern int ath_txbuf; +extern int ath_txbuf_mgmt; + extern int ath_tx_findrix(const struct ath_softc *sc, uint8_t rate); extern struct ath_buf * ath_getbuf(struct ath_softc *sc, @@ -80,6 +84,11 @@ extern void ath_setdefantenna(struct ath_softc *sc, u_int antenna); extern void ath_setslottime(struct ath_softc *sc); +extern int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, + ath_bufhead *head, const char *name, int nbuf, int ndesc); +extern void ath_descdma_cleanup(struct ath_softc *sc, + struct ath_descdma *dd, ath_bufhead *head); + /* * This is only here so that the RX proc function can call it. * It's very likely that the "start TX after RX" call should be diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index dd03fb9..eba6ba5 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -115,9 +115,6 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/ath_tx99/ath_tx99.h> #endif -#define ATH_KTR_INTR KTR_SPARE4 -#define ATH_KTR_ERR KTR_SPARE3 - /* * Calculate the receive filter according to the * operating mode and state: @@ -463,9 +460,9 @@ ath_handle_micerror(struct ieee80211com *ic, } } -static int +int ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, - uint64_t tsf, int nf, struct ath_buf *bf) + uint64_t tsf, int nf, HAL_RX_QUEUE qtype, struct ath_buf *bf) { struct ath_hal *ah = sc->sc_ah; struct mbuf *m = bf->bf_m; @@ -475,6 +472,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, struct ieee80211com *ic = ifp->if_l2com; struct ieee80211_node *ni; int is_good = 0; + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; /* * Calculate the correct 64 bit TSF given @@ -559,9 +557,9 @@ rx_error: /* * Cleanup any pending partial frame. */ - if (sc->sc_rxpending != NULL) { - m_freem(sc->sc_rxpending); - sc->sc_rxpending = NULL; + if (re->m_rxpending != NULL) { + m_freem(re->m_rxpending); + re->m_rxpending = NULL; } /* * When a tap is present pass error frames @@ -608,25 +606,25 @@ rx_accept: * it for the next completed descriptor, it * will be used to construct a jumbogram. */ - if (sc->sc_rxpending != NULL) { + if (re->m_rxpending != NULL) { /* NB: max frame size is currently 2 clusters */ sc->sc_stats.ast_rx_toobig++; - m_freem(sc->sc_rxpending); + m_freem(re->m_rxpending); } m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = len; - sc->sc_rxpending = m; + re->m_rxpending = m; goto rx_next; - } else if (sc->sc_rxpending != NULL) { + } else if (re->m_rxpending != NULL) { /* * This is the second part of a jumbogram, * chain it to the first mbuf, adjust the * frame length, and clear the rxpending state. */ - sc->sc_rxpending->m_next = m; - sc->sc_rxpending->m_pkthdr.len += len; - m = sc->sc_rxpending; - sc->sc_rxpending = NULL; + re->m_rxpending->m_next = m; + re->m_rxpending->m_pkthdr.len += len; + m = re->m_rxpending; + re->m_rxpending = NULL; } else { /* * Normal single-descriptor receive; setup @@ -883,7 +881,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) /* * Process a single frame. */ - if (ath_rx_pkt(sc, rs, status, tsf, nf, bf)) + if (ath_rx_pkt(sc, rs, status, tsf, nf, HAL_RX_QUEUE_HP, bf)) ngood++; rx_proc_next: TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); @@ -916,7 +914,7 @@ rx_proc_next: * Are there any net80211 buffer calls involved? */ bf = TAILQ_FIRST(&sc->sc_rxbuf); - ath_hal_putrxbuf(ah, bf->bf_daddr); + ath_hal_putrxbuf(ah, bf->bf_daddr, HAL_RX_QUEUE_HP); ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ @@ -1002,7 +1000,7 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay) device_printf(sc->sc_dev, "%s: rx queue %p, link %p\n", __func__, - (caddr_t)(uintptr_t) ath_hal_getrxbuf(ah), + (caddr_t)(uintptr_t) ath_hal_getrxbuf(ah, HAL_RX_QUEUE_HP), sc->sc_rxlink); ix = 0; TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { @@ -1016,9 +1014,16 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay) } } #endif - if (sc->sc_rxpending != NULL) { - m_freem(sc->sc_rxpending); - sc->sc_rxpending = NULL; + /* + * Free both high/low RX pending, just in case. + */ + if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending != NULL) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; + } + if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending != NULL) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; } sc->sc_rxlink = NULL; /* just in case */ #undef PA2DESC @@ -1034,7 +1039,8 @@ ath_legacy_startrecv(struct ath_softc *sc) struct ath_buf *bf; sc->sc_rxlink = NULL; - sc->sc_rxpending = NULL; + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { int error = ath_rxbuf_init(sc, bf); if (error != 0) { @@ -1046,13 +1052,38 @@ ath_legacy_startrecv(struct ath_softc *sc) } bf = TAILQ_FIRST(&sc->sc_rxbuf); - ath_hal_putrxbuf(ah, bf->bf_daddr); + ath_hal_putrxbuf(ah, bf->bf_daddr, HAL_RX_QUEUE_HP); ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ return 0; } +static int +ath_legacy_dma_rxsetup(struct ath_softc *sc) +{ + int error; + + device_printf(sc->sc_dev, "%s: called\n", __func__); + + error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, + "rx", ath_rxbuf, 1); + if (error != 0) + return (error); + + return (0); +} + +static int +ath_legacy_dma_rxteardown(struct ath_softc *sc) +{ + + device_printf(sc->sc_dev, "%s: called\n", __func__); + + if (sc->sc_rxdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); + return (0); +} void ath_recv_setup_legacy(struct ath_softc *sc) @@ -1065,4 +1096,7 @@ ath_recv_setup_legacy(struct ath_softc *sc) sc->sc_rx.recv_flush = ath_legacy_flushrecv; sc->sc_rx.recv_tasklet = ath_legacy_rx_tasklet; sc->sc_rx.recv_rxbuf_init = ath_legacy_rxbuf_init; + + sc->sc_rx.recv_setup = ath_legacy_dma_rxsetup; + sc->sc_rx.recv_teardown = ath_legacy_dma_rxteardown; } diff --git a/sys/dev/ath/if_ath_rx.h b/sys/dev/ath/if_ath_rx.h index f99425e..504ff80 100644 --- a/sys/dev/ath/if_ath_rx.h +++ b/sys/dev/ath/if_ath_rx.h @@ -43,6 +43,10 @@ extern void ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, (_sc)->sc_rx.recv_flush((_sc)) #define ath_rxbuf_init(_sc, _bf) \ (_sc)->sc_rx.recv_rxbuf_init((_sc), (_bf)) +#define ath_rxdma_setup(_sc) \ + (_sc)->sc_rx.recv_setup(_sc) +#define ath_rxdma_teardown(_sc) \ + (_sc)->sc_rx.recv_teardown(_sc) #if 0 extern int ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf); @@ -52,6 +56,10 @@ extern void ath_stoprecv(struct ath_softc *sc, int dodelay); extern int ath_startrecv(struct ath_softc *sc); #endif +extern int ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, + HAL_STATUS status, uint64_t tsf, int nf, HAL_RX_QUEUE qtype, + struct ath_buf *bf); + extern void ath_recv_setup_legacy(struct ath_softc *sc); #endif diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c index dc9b1a9..9e3580d 100644 --- a/sys/dev/ath/if_ath_rx_edma.c +++ b/sys/dev/ath/if_ath_rx_edma.c @@ -117,6 +117,40 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/if_ath_rx_edma.h> +/* + * some general macros + */ +#define INCR(_l, _sz) (_l) ++; (_l) &= ((_sz) - 1) +#define DECR(_l, _sz) (_l) --; (_l) &= ((_sz) - 1) + +MALLOC_DECLARE(M_ATHDEV); + +/* + * XXX TODO: + * + * + Add an RX lock, just to ensure we don't have things clash; + * + Make sure the FIFO is correctly flushed and reinitialised + * through a reset; + * + Handle the "kickpcu" state where the FIFO overflows. + * + Implement a "flush" routine, which doesn't push any + * new frames into the FIFO. + * + Verify multi-descriptor frames work! + * + There's a "memory use after free" which needs to be tracked down + * and fixed ASAP. I've seen this in the legacy path too, so it + * may be a generic RX path issue. + */ + +/* + * XXX shuffle the function orders so these pre-declarations aren't + * required! + */ +static int ath_edma_rxfifo_alloc(struct ath_softc *sc, HAL_RX_QUEUE qtype, + int nbufs); +static int ath_edma_rxfifo_flush(struct ath_softc *sc, HAL_RX_QUEUE qtype); +static void ath_edma_rxbuf_free(struct ath_softc *sc, struct ath_buf *bf); +static int ath_edma_recv_proc_queue(struct ath_softc *sc, + HAL_RX_QUEUE qtype, int dosched); + static void ath_edma_stoprecv(struct ath_softc *sc, int dodelay) { @@ -128,25 +162,108 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay) DELAY(3000); - if (sc->sc_rxpending != NULL) { - m_freem(sc->sc_rxpending); - sc->sc_rxpending = NULL; + /* Flush RX pending for each queue */ + /* XXX should generic-ify this */ + if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; + } + + if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; } +} - sc->sc_rxlink = NULL; +/* + * Re-initialise the FIFO given the current buffer contents. + * Specifically, walk from head -> tail, pushing the FIFO contents + * back into the FIFO. + */ +static void +ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + struct ath_buf *bf; + int i, j; + + i = re->m_fifo_head; + for (j = 0; j < re->m_fifo_depth; j++) { + bf = re->m_fifo[i]; + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: Q%d: pos=%i, addr=0x%jx\n", + __func__, + qtype, + i, + (uintmax_t)bf->bf_daddr); + ath_hal_putrxbuf(sc->sc_ah, bf->bf_daddr, qtype); + INCR(i, re->m_fifolen); + } + + /* Ensure this worked out right */ + if (i != re->m_fifo_tail) { + device_printf(sc->sc_dev, "%s: i (%d) != tail! (%d)\n", + __func__, + i, + re->m_fifo_tail); + } } +/* + * Start receive. + * + * XXX TODO: this needs to reallocate the FIFO entries when a reset + * occurs, in case the FIFO is filled up and no new descriptors get + * thrown into the FIFO. + */ static int ath_edma_startrecv(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; - sc->sc_rxlink = NULL; - sc->sc_rxpending = NULL; + /* Enable RX FIFO */ + ath_hal_rxena(ah); + + /* + * Entries should only be written out if the + * FIFO is empty. + * + * XXX This isn't correct. I should be looking + * at the value of AR_RXDP_SIZE (0x0070) to determine + * how many entries are in here. + * + * A warm reset will clear the registers but not the FIFO. + * + * And I believe this is actually the address of the last + * handled buffer rather than the current FIFO pointer. + * So if no frames have been (yet) seen, we'll reinit the + * FIFO. + * + * I'll chase that up at some point. + */ + if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_HP) == 0) { + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: Re-initing HP FIFO\n", __func__); + ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP); + } + if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_LP) == 0) { + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: Re-initing LP FIFO\n", __func__); + ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_LP); + } + + /* Add up to m_fifolen entries in each queue */ + /* + * These must occur after the above write so the FIFO buffers + * are pushed/tracked in the same order as the hardware will + * process them. + */ + ath_edma_rxfifo_alloc(sc, HAL_RX_QUEUE_HP, + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_fifolen); + + ath_edma_rxfifo_alloc(sc, HAL_RX_QUEUE_LP, + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_fifolen); - /* XXX setup HP RX queue FIFO pointer */ - /* XXX setup LP RX queue FIFO pointer */ - /* XXX ath_hal_rxena() */ ath_mode_init(sc); ath_hal_startpcurecv(ah); return (0); @@ -157,6 +274,123 @@ ath_edma_recv_flush(struct ath_softc *sc) { device_printf(sc->sc_dev, "%s: called\n", __func__); + + ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 0); + ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 0); +} + +/* + * Process frames from the current queue. + * + * TODO: + * + * + Add a "dosched" flag, so we don't reschedule any FIFO frames + * to the hardware or re-kick the PCU after 'kickpcu' is set. + * + * + Perhaps split "check FIFO contents" and "handle frames", so + * we can run the "check FIFO contents" in ath_intr(), but + * "handle frames" in the RX tasklet. + */ +static int +ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, + int dosched) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + struct ath_rx_status *rs; + struct ath_desc *ds; + struct ath_buf *bf; + struct mbuf *m; + HAL_STATUS status; + struct ath_hal *ah = sc->sc_ah; + uint64_t tsf; + int16_t nf; + int ngood = 0; + + tsf = ath_hal_gettsf64(ah); + nf = ath_hal_getchannoise(ah, sc->sc_curchan); + sc->sc_stats.ast_rx_noise = nf; + + do { + bf = re->m_fifo[re->m_fifo_head]; + /* This shouldn't occur! */ + if (bf == NULL) { + device_printf(sc->sc_dev, "%s: Q%d: NULL bf?\n", + __func__, + qtype); + break; + } + m = bf->bf_m; + ds = bf->bf_desc; + + /* + * Sync descriptor memory - this also syncs the buffer for us. + * + * EDMA descriptors are in cached memory. + */ + bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, + BUS_DMASYNC_POSTREAD); + rs = &bf->bf_status.ds_rxstat; + status = ath_hal_rxprocdesc(ah, ds, bf->bf_daddr, NULL, rs); +#ifdef ATH_DEBUG + if (sc->sc_debug & ATH_DEBUG_RECV_DESC) + ath_printrxbuf(sc, bf, 0, status == HAL_OK); +#endif + if (status == HAL_EINPROGRESS) + break; + + /* + * Completed descriptor. + * + * In the future we'll call ath_rx_pkt(), but it first + * has to be taught about EDMA RX queues (so it can + * access sc_rxpending correctly.) + */ + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: Q%d: completed!\n", __func__, qtype); + + /* + * Remove the FIFO entry! + */ + re->m_fifo[re->m_fifo_head] = NULL; + + /* + * Skip the RX descriptor status - start at the data offset + */ + m_adj(m, sc->sc_rx_statuslen); + + /* Handle the frame */ + if (ath_rx_pkt(sc, rs, status, tsf, nf, qtype, bf)) + ngood++; + + /* Free the buffer/mbuf */ + ath_edma_rxbuf_free(sc, bf); + + /* Bump the descriptor FIFO stats */ + INCR(re->m_fifo_head, re->m_fifolen); + re->m_fifo_depth--; + /* XXX check it doesn't fall below 0 */ + } while (re->m_fifo_depth > 0); + + /* Handle resched and kickpcu appropriately */ + ATH_PCU_LOCK(sc); + if (dosched && sc->sc_kickpcu) { + CTR0(ATH_KTR_ERR, "ath_edma_recv_proc_queue(): kickpcu"); + device_printf(sc->sc_dev, "%s: handled %d descriptors\n", + __func__, ngood); + + /* + * XXX TODO: what should occur here? Just re-poke and + * re-enable the RX FIFO? + */ + sc->sc_kickpcu = 0; + } + ATH_PCU_UNLOCK(sc); + + /* Append some more fresh frames to the FIFO */ + if (dosched) + ath_edma_rxfifo_alloc(sc, qtype, re->m_fifolen); + + return (ngood); } static void @@ -164,18 +398,336 @@ ath_edma_recv_tasklet(void *arg, int npending) { struct ath_softc *sc = (struct ath_softc *) arg; - device_printf(sc->sc_dev, "%s: called; npending=%d\n", + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n", __func__, npending); - /* XXX TODO */ + + ATH_PCU_LOCK(sc); + if (sc->sc_inreset_cnt > 0) { + device_printf(sc->sc_dev, "%s: sc_inreset_cnt > 0; skipping\n", + __func__); + ATH_PCU_UNLOCK(sc); + return; + } + ATH_PCU_UNLOCK(sc); + + ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1); + ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1); } +/* + * Allocate an RX mbuf for the given ath_buf and initialise + * it for EDMA. + * + * + Allocate a 4KB mbuf; + * + Setup the DMA map for the given buffer; + * + Keep a pointer to the start of the mbuf - that's where the + * descriptor lies; + * + Take a pointer to the start of the RX buffer, set the + * mbuf "start" to be there; + * + Return that. + */ static int ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) { - device_printf(sc->sc_dev, "%s: called; bf=%p\n", __func__, bf); - return (EIO); + struct mbuf *m; + int error; + int len; + +// device_printf(sc->sc_dev, "%s: called; bf=%p\n", __func__, bf); + + m = m_getm(NULL, sc->sc_edma_bufsize, M_DONTWAIT, MT_DATA); + if (! m) + return (ENOBUFS); /* XXX ?*/ + + /* XXX warn/enforce alignment */ + + len = m->m_ext.ext_size; +#if 0 + device_printf(sc->sc_dev, "%s: called: m=%p, size=%d, mtod=%p\n", + __func__, + m, + len, + mtod(m, char *)); +#endif + + m->m_pkthdr.len = m->m_len = m->m_ext.ext_size; + + /* + * Create DMA mapping. + */ + error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, + bf->bf_dmamap, m, bf->bf_segs, &bf->bf_nseg, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, "%s: failed; error=%d\n", + __func__, + error); + m_freem(m); + return (error); + } + + /* + * Populate ath_buf fields. + */ + + bf->bf_desc = mtod(m, struct ath_desc *); + bf->bf_daddr = bf->bf_segs[0].ds_addr; + bf->bf_lastds = bf->bf_desc; /* XXX only really for TX? */ + bf->bf_m = m; + + /* Zero the descriptor */ + memset(bf->bf_desc, '\0', sc->sc_rx_statuslen); + +#if 0 + /* + * Adjust mbuf header and length/size to compensate for the + * descriptor size. + */ + m_adj(m, sc->sc_rx_statuslen); +#endif + + /* Finish! */ + + return (0); +} + +static struct ath_buf * +ath_edma_rxbuf_alloc(struct ath_softc *sc) +{ + struct ath_buf *bf; + int error; + + /* Allocate buffer */ + bf = TAILQ_FIRST(&sc->sc_rxbuf); + /* XXX shouldn't happen upon startup? */ + if (bf == NULL) + return (NULL); + + /* Remove it from the free list */ + TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); + + /* Assign RX mbuf to it */ + error = ath_edma_rxbuf_init(sc, bf); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: bf=%p, rxbuf alloc failed! error=%d\n", + __func__, + bf, + error); + TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + return (NULL); + } + + return (bf); +} + +static void +ath_edma_rxbuf_free(struct ath_softc *sc, struct ath_buf *bf) +{ + + bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); + + if (bf->bf_m) { + m_freem(bf->bf_m); + bf->bf_m = NULL; + } + + /* XXX lock? */ + TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); +} + +/* + * Allocate up to 'n' entries and push them onto the hardware FIFO. + * + * Return how many entries were successfully pushed onto the + * FIFO. + */ +static int +ath_edma_rxfifo_alloc(struct ath_softc *sc, HAL_RX_QUEUE qtype, int nbufs) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + struct ath_buf *bf; + int i; + + /* + * Allocate buffers until the FIFO is full or nbufs is reached. + */ + for (i = 0; i < nbufs && re->m_fifo_depth < re->m_fifolen; i++) { + /* Ensure the FIFO is already blank, complain loudly! */ + if (re->m_fifo[re->m_fifo_tail] != NULL) { + device_printf(sc->sc_dev, + "%s: Q%d: fifo[%d] != NULL (%p)\n", + __func__, + qtype, + re->m_fifo_tail, + re->m_fifo[re->m_fifo_tail]); + + /* Free the slot */ + ath_edma_rxbuf_free(sc, re->m_fifo[re->m_fifo_tail]); + re->m_fifo_depth--; + /* XXX check it's not < 0 */ + re->m_fifo[re->m_fifo_tail] = NULL; + } + + bf = ath_edma_rxbuf_alloc(sc); + /* XXX should ensure the FIFO is not NULL? */ + if (bf == NULL) { + device_printf(sc->sc_dev, "%s: Q%d: alloc failed?\n", + __func__, + qtype); + break; + } + + re->m_fifo[re->m_fifo_tail] = bf; + + /* + * Flush the descriptor contents before it's handed to the + * hardware. + */ + bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, + BUS_DMASYNC_PREREAD); + + /* Write to the RX FIFO */ + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Q%d: putrxbuf=%p\n", + __func__, + qtype, + bf->bf_desc); + ath_hal_putrxbuf(sc->sc_ah, bf->bf_daddr, qtype); + + re->m_fifo_depth++; + INCR(re->m_fifo_tail, re->m_fifolen); + } + + /* + * Return how many were allocated. + */ + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Q%d: nbufs=%d, nalloced=%d\n", + __func__, + qtype, + nbufs, + i); + return (i); +} + +static int +ath_edma_rxfifo_flush(struct ath_softc *sc, HAL_RX_QUEUE qtype) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + int i; + + for (i = 0; i < re->m_fifolen; i++) { + if (re->m_fifo[i] != NULL) { +#ifdef ATH_DEBUG + struct ath_buf *bf = re->m_fifo[i]; + + if (sc->sc_debug & ATH_DEBUG_RECV_DESC) + ath_printrxbuf(sc, bf, 0, HAL_OK); +#endif + ath_edma_rxbuf_free(sc, re->m_fifo[i]); + re->m_fifo[i] = NULL; + re->m_fifo_depth--; + } + } + + if (re->m_rxpending != NULL) { + m_freem(re->m_rxpending); + re->m_rxpending = NULL; + } + re->m_fifo_head = re->m_fifo_tail = re->m_fifo_depth = 0; + + return (0); +} + +/* + * Setup the initial RX FIFO structure. + */ +static int +ath_edma_setup_rxfifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + + if (! ath_hal_getrxfifodepth(sc->sc_ah, qtype, &re->m_fifolen)) { + device_printf(sc->sc_dev, "%s: qtype=%d, failed\n", + __func__, + qtype); + return (-EINVAL); + } + device_printf(sc->sc_dev, "%s: type=%d, FIFO depth = %d entries\n", + __func__, + qtype, + re->m_fifolen); + + /* Allocate ath_buf FIFO array, pre-zero'ed */ + re->m_fifo = malloc(sizeof(struct ath_buf *) * re->m_fifolen, + M_ATHDEV, + M_NOWAIT | M_ZERO); + if (re->m_fifo == NULL) { + device_printf(sc->sc_dev, "%s: malloc failed\n", + __func__); + return (-ENOMEM); + } + + /* + * Set initial "empty" state. + */ + re->m_rxpending = NULL; + re->m_fifo_head = re->m_fifo_tail = re->m_fifo_depth = 0; + + return (0); +} + +static int +ath_edma_rxfifo_free(struct ath_softc *sc, HAL_RX_QUEUE qtype) +{ + struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; + + device_printf(sc->sc_dev, "%s: called; qtype=%d\n", + __func__, + qtype); + + free(re->m_fifo, M_ATHDEV); + + return (0); +} + +static int +ath_edma_dma_rxsetup(struct ath_softc *sc) +{ + int error; + + /* Create RX DMA tag */ + /* Create RX ath_buf array */ + + error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, + "rx", ath_rxbuf, 1); + if (error != 0) + return error; + + (void) ath_edma_setup_rxfifo(sc, HAL_RX_QUEUE_HP); + (void) ath_edma_setup_rxfifo(sc, HAL_RX_QUEUE_LP); + + return (0); +} + +static int +ath_edma_dma_rxteardown(struct ath_softc *sc) +{ + + device_printf(sc->sc_dev, "%s: called\n", __func__); + + ath_edma_rxfifo_flush(sc, HAL_RX_QUEUE_HP); + ath_edma_rxfifo_free(sc, HAL_RX_QUEUE_HP); + + ath_edma_rxfifo_flush(sc, HAL_RX_QUEUE_LP); + ath_edma_rxfifo_free(sc, HAL_RX_QUEUE_LP); + + /* Free RX ath_buf */ + /* Free RX DMA tag */ + if (sc->sc_rxdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); + + return (0); } void @@ -184,9 +736,35 @@ ath_recv_setup_edma(struct ath_softc *sc) device_printf(sc->sc_dev, "DMA setup: EDMA\n"); + /* Set buffer size to 4k */ + sc->sc_edma_bufsize = 4096; + + /* Configure the hardware with this */ + (void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize); + + /* Fetch EDMA field and buffer sizes */ + (void) ath_hal_getrxstatuslen(sc->sc_ah, &sc->sc_rx_statuslen); + (void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen); + (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); + (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); + + device_printf(sc->sc_dev, "RX status length: %d\n", + sc->sc_rx_statuslen); + device_printf(sc->sc_dev, "TX descriptor length: %d\n", + sc->sc_tx_desclen); + device_printf(sc->sc_dev, "TX status length: %d\n", + sc->sc_tx_statuslen); + device_printf(sc->sc_dev, "TX/RX buffer size: %d\n", + sc->sc_edma_bufsize); + device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", + sc->sc_tx_nmaps); + sc->sc_rx.recv_stop = ath_edma_stoprecv; sc->sc_rx.recv_start = ath_edma_startrecv; sc->sc_rx.recv_flush = ath_edma_recv_flush; sc->sc_rx.recv_tasklet = ath_edma_recv_tasklet; sc->sc_rx.recv_rxbuf_init = ath_edma_rxbuf_init; + + sc->sc_rx.recv_setup = ath_edma_dma_rxsetup; + sc->sc_rx.recv_teardown = ath_edma_dma_rxteardown; } diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 46efd61..934f9dc 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -3583,6 +3583,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, "seq_st=%d\n", __func__, hasba, tx_ok, isaggr, seq_st); /* XXX TODO: schedule an interface reset */ +#ifdef ATH_DEBUG + ath_printtxbuf(sc, bf_first, + sc->sc_ac2q[atid->ac]->axq_qnum, 0, 0); +#endif } /* diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index d622df5..7370e01 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -379,6 +379,20 @@ struct ath_rx_methods { void (*recv_tasklet)(void *arg, int npending); int (*recv_rxbuf_init)(struct ath_softc *sc, struct ath_buf *bf); + int (*recv_setup)(struct ath_softc *sc); + int (*recv_teardown)(struct ath_softc *sc); +}; + +/* + * Represent the current state of the RX FIFO. + */ +struct ath_rx_edma { + struct ath_buf **m_fifo; + int m_fifolen; + int m_fifo_head; + int m_fifo_tail; + int m_fifo_depth; + struct mbuf *m_rxpending; }; struct ath_softc { @@ -395,6 +409,12 @@ struct ath_softc { uint32_t sc_bssidmask; /* bssid mask */ struct ath_rx_methods sc_rx; + struct ath_rx_edma sc_rxedma[2]; /* HP/LP queues */ + int sc_rx_statuslen; + int sc_tx_desclen; + int sc_tx_statuslen; + int sc_tx_nmaps; /* Number of TX maps */ + int sc_edma_bufsize; void (*sc_node_cleanup)(struct ieee80211_node *); void (*sc_node_free)(struct ieee80211_node *); @@ -439,7 +459,8 @@ struct ath_softc { sc_setcca : 1,/* set/clr CCA with TDMA */ sc_resetcal : 1,/* reset cal state next trip */ sc_rxslink : 1,/* do self-linked final descriptor */ - sc_rxtsf32 : 1;/* RX dec TSF is 32 bits */ + sc_rxtsf32 : 1,/* RX dec TSF is 32 bits */ + sc_isedma : 1;/* supports EDMA */ uint32_t sc_eerd; /* regdomain from EEPROM */ uint32_t sc_eecc; /* country code from EEPROM */ /* rate tables */ @@ -510,7 +531,6 @@ struct ath_softc { struct ath_descdma sc_rxdma; /* RX descriptors */ ath_bufhead sc_rxbuf; /* receive buffer */ - struct mbuf *sc_rxpending; /* pending receive data */ u_int32_t *sc_rxlink; /* link ptr in last RX desc */ struct task sc_rxtask; /* rx int processing */ u_int8_t sc_defant; /* current default antenna */ @@ -745,8 +765,8 @@ void ath_intr(void *); ((*(_ah)->ah_setMulticastFilter)((_ah), (_mfilt0), (_mfilt1))) #define ath_hal_waitforbeacon(_ah, _bf) \ ((*(_ah)->ah_waitForBeaconDone)((_ah), (_bf)->bf_daddr)) -#define ath_hal_putrxbuf(_ah, _bufaddr) \ - ((*(_ah)->ah_setRxDP)((_ah), (_bufaddr))) +#define ath_hal_putrxbuf(_ah, _bufaddr, _rxq) \ + ((*(_ah)->ah_setRxDP)((_ah), (_bufaddr), (_rxq))) /* NB: common across all chips */ #define AR_TSF_L32 0x804c /* MAC local clock lower 32 bits */ #define ath_hal_gettsf32(_ah) \ @@ -763,8 +783,8 @@ void ath_intr(void *); ((*(_ah)->ah_getTxDP)((_ah), (_q))) #define ath_hal_numtxpending(_ah, _q) \ ((*(_ah)->ah_numTxPending)((_ah), (_q))) -#define ath_hal_getrxbuf(_ah) \ - ((*(_ah)->ah_getRxDP)((_ah))) +#define ath_hal_getrxbuf(_ah, _rxq) \ + ((*(_ah)->ah_getRxDP)((_ah), (_rxq))) #define ath_hal_txstart(_ah, _q) \ ((*(_ah)->ah_startTxDma)((_ah), (_q))) #define ath_hal_setchannel(_ah, _chan) \ @@ -953,11 +973,34 @@ void ath_intr(void *); #define ath_hal_setintmit(_ah, _v) \ ath_hal_setcapability(_ah, HAL_CAP_INTMIT, \ HAL_CAP_INTMIT_ENABLE, _v, NULL) + +/* EDMA definitions */ #define ath_hal_hasedma(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_ENHANCED_DMA_SUPPORT, \ 0, NULL) == HAL_OK) +#define ath_hal_getrxfifodepth(_ah, _qtype, _req) \ + (ath_hal_getcapability(_ah, HAL_CAP_RXFIFODEPTH, _qtype, _req) \ + == HAL_OK) +#define ath_hal_getntxmaps(_ah, _req) \ + (ath_hal_getcapability(_ah, HAL_CAP_NUM_TXMAPS, 0, _req) \ + == HAL_OK) +#define ath_hal_gettxdesclen(_ah, _req) \ + (ath_hal_getcapability(_ah, HAL_CAP_TXDESCLEN, 0, _req) \ + == HAL_OK) +#define ath_hal_gettxstatuslen(_ah, _req) \ + (ath_hal_getcapability(_ah, HAL_CAP_TXSTATUSLEN, 0, _req) \ + == HAL_OK) +#define ath_hal_getrxstatuslen(_ah, _req) \ + (ath_hal_getcapability(_ah, HAL_CAP_RXSTATUSLEN, 0, _req) \ + == HAL_OK) +#define ath_hal_setrxbufsize(_ah, _req) \ + (ath_hal_setcapability(_ah, HAL_CAP_RXBUFSIZE, 0, _req, NULL) \ + == HAL_OK) + #define ath_hal_getchannoise(_ah, _c) \ ((*(_ah)->ah_getChanNoise)((_ah), (_c))) + +/* 802.11n HAL methods */ #define ath_hal_getrxchainmask(_ah, _prxchainmask) \ (ath_hal_getcapability(_ah, HAL_CAP_RX_CHAINMASK, 0, _prxchainmask)) #define ath_hal_gettxchainmask(_ah, _ptxchainmask) \ diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 7d48fe9..4ded12d 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -401,14 +401,16 @@ first_vector(struct port_info *pi) return (0); for_each_port(sc, i) { + struct port_info *p = sc->port[i]; + if (i == pi->port_id) break; #ifdef TCP_OFFLOAD if (sc->flags & INTR_DIRECT) - rc += pi->nrxq + pi->nofldrxq; + rc += p->nrxq + p->nofldrxq; else - rc += max(pi->nrxq, pi->nofldrxq); + rc += max(p->nrxq, p->nofldrxq); #else /* * Not compiled with offload support and intr_count > 1. Only @@ -419,7 +421,7 @@ first_vector(struct port_info *pi) ("%s: intr_count %d, !INTR_DIRECT", __func__, sc->intr_count)); - rc += pi->nrxq; + rc += p->nrxq; #endif } diff --git a/sys/dev/mfi/mfi_disk.c b/sys/dev/mfi/mfi_disk.c index fc43e67..18ceb99 100644 --- a/sys/dev/mfi/mfi_disk.c +++ b/sys/dev/mfi/mfi_disk.c @@ -298,6 +298,7 @@ mfi_disk_complete(struct bio *bio) hdr = bio->bio_driver1; if (bio->bio_flags & BIO_ERROR) { + bio->bio_resid = bio->bio_bcount; if (bio->bio_error == 0) bio->bio_error = EIO; disk_err(bio, "hard error", -1, 1); diff --git a/sys/dev/mfi/mfivar.h b/sys/dev/mfi/mfivar.h index d38fcc3..176a10a 100644 --- a/sys/dev/mfi/mfivar.h +++ b/sys/dev/mfi/mfivar.h @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/taskqueue.h> +#include "opt_mfi.h" /* * SCSI structures and definitions are used from here, but no linking diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c index 6d65439..b7b29d7 100644 --- a/sys/dev/usb/usb_pf.c +++ b/sys/dev/usb/usb_pf.c @@ -44,8 +44,10 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <net/if.h> #include <net/if_types.h> +#include <net/if_clone.h> #include <net/bpf.h> #include <sys/sysctl.h> +#include <net/route.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -58,35 +60,146 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usb_pf.h> #include <dev/usb/usb_transfer.h> -static int usb_no_pf; - -SYSCTL_INT(_hw_usb, OID_AUTO, no_pf, CTLFLAG_RW, - &usb_no_pf, 0, "Set to disable USB packet filtering"); +#define USBUSNAME "usbus" + +static void usbpf_init(void); +static void usbpf_uninit(void); +static int usbpf_ioctl(struct ifnet *, u_long, caddr_t); +static int usbpf_clone_match(struct if_clone *, const char *); +static int usbpf_clone_create(struct if_clone *, char *, size_t, caddr_t); +static int usbpf_clone_destroy(struct if_clone *, struct ifnet *); +static struct usb_bus *usbpf_ifname2ubus(const char *); +static uint32_t usbpf_aggregate_xferflags(struct usb_xfer_flags *); +static uint32_t usbpf_aggregate_status(struct usb_xfer_flags_int *); +static int usbpf_xfer_frame_is_read(struct usb_xfer *, uint32_t); +static uint32_t usbpf_xfer_precompute_size(struct usb_xfer *, int); + +static struct if_clone usbpf_cloner = IFC_CLONE_INITIALIZER( + USBUSNAME, NULL, IF_MAXUNIT, + NULL, usbpf_clone_match, usbpf_clone_create, usbpf_clone_destroy); + +SYSINIT(usbpf_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_init, NULL); +SYSUNINIT(usbpf_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_uninit, NULL); + +static void +usbpf_init(void) +{ -TUNABLE_INT("hw.usb.no_pf", &usb_no_pf); + if_clone_attach(&usbpf_cloner); +} -void -usbpf_attach(struct usb_bus *ubus) +static void +usbpf_uninit(void) { - struct ifnet *ifp; - - if (usb_no_pf != 0) { - ubus->ifp = NULL; + int devlcnt; + device_t *devlp; + devclass_t dc; + struct usb_bus *ubus; + int error; + int i; + + if_clone_detach(&usbpf_cloner); + + dc = devclass_find(USBUSNAME); + if (dc == NULL) + return; + error = devclass_get_devices(dc, &devlp, &devlcnt); + if (error) return; + for (i = 0; i < devlcnt; i++) { + ubus = device_get_softc(devlp[i]); + if (ubus != NULL && ubus->ifp != NULL) + usbpf_clone_destroy(&usbpf_cloner, ubus->ifp); } +} + +static int +usbpf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + + /* No configuration allowed. */ + return (EINVAL); +} + +static struct usb_bus * +usbpf_ifname2ubus(const char *ifname) +{ + device_t dev; + devclass_t dc; + int unit; + int error; + + if (strncmp(ifname, USBUSNAME, sizeof(USBUSNAME) - 1) != 0) + return (NULL); + error = ifc_name2unit(ifname, &unit); + if (error || unit < 0) + return (NULL); + dc = devclass_find(USBUSNAME); + if (dc == NULL) + return (NULL); + dev = devclass_get_device(dc, unit); + if (dev == NULL) + return (NULL); + + return (device_get_softc(dev)); +} + +static int +usbpf_clone_match(struct if_clone *ifc, const char *name) +{ + struct usb_bus *ubus; + + ubus = usbpf_ifname2ubus(name); + if (ubus == NULL) + return (0); + if (ubus->ifp != NULL) + return (0); + + return (1); +} +static int +usbpf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) +{ + int error; + int unit; + struct ifnet *ifp; + struct usb_bus *ubus; + + error = ifc_name2unit(name, &unit); + if (error) + return (error); + if (unit < 0) + return (EINVAL); + + ubus = usbpf_ifname2ubus(name); + if (ubus == NULL) + return (1); + if (ubus->ifp != NULL) + return (1); + + error = ifc_alloc_unit(ifc, &unit); + if (error) { + ifc_free_unit(ifc, unit); + device_printf(ubus->parent, "usbpf: Could not allocate " + "instance\n"); + return (error); + } ifp = ubus->ifp = if_alloc(IFT_USB); if (ifp == NULL) { + ifc_free_unit(ifc, unit); device_printf(ubus->parent, "usbpf: Could not allocate " "instance\n"); - return; + return (ENOSPC); } - - if_initname(ifp, "usbus", device_get_unit(ubus->bdev)); - ifp->if_flags = IFF_CANTCONFIG; + strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname)); + ifp->if_softc = ubus; + ifp->if_dname = ifc->ifc_name; + ifp->if_dunit = unit; + ifp->if_ioctl = usbpf_ioctl; if_attach(ifp); - if_up(ifp); - + ifp->if_flags |= IFF_UP; + rt_ifmsg(ifp); /* * XXX According to the specification of DLT_USB, it indicates * packets beginning with USB setup header. But not sure all @@ -94,6 +207,31 @@ usbpf_attach(struct usb_bus *ubus) */ bpfattach(ifp, DLT_USB, USBPF_HDR_LEN); + return (0); +} + +static int +usbpf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) +{ + struct usb_bus *ubus; + int unit; + + ubus = ifp->if_softc; + unit = ifp->if_dunit; + + ubus->ifp = NULL; + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); + ifc_free_unit(ifc, unit); + + return (0); +} + +void +usbpf_attach(struct usb_bus *ubus) +{ + if (bootverbose) device_printf(ubus->parent, "usbpf: Attached\n"); } @@ -101,15 +239,11 @@ usbpf_attach(struct usb_bus *ubus) void usbpf_detach(struct usb_bus *ubus) { - struct ifnet *ifp = ubus->ifp; - if (ifp != NULL) { - bpfdetach(ifp); - if_down(ifp); - if_detach(ifp); - if_free(ifp); - } - ubus->ifp = NULL; + if (ubus->ifp != NULL) + usbpf_clone_destroy(&usbpf_cloner, ubus->ifp); + if (bootverbose) + device_printf(ubus->parent, "usbpf: Detached\n"); } static uint32_t @@ -259,8 +393,6 @@ usbpf_xfertap(struct usb_xfer *xfer, int type) bus = xfer->xroot->bus; /* sanity checks */ - if (usb_no_pf != 0) - return; if (bus->ifp == NULL) return; if (!bpf_peers_present(bus->ifp->if_bpf)) diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 643964d..aedea58 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -2140,6 +2140,7 @@ product LOGITEC RT2870_1 0x0162 RT2870 product LOGITEC RT2870_2 0x0163 RT2870 product LOGITEC RT2870_3 0x0164 RT2870 product LOGITEC LANW300NU2 0x0166 LAN-W300N/U2 +product LOGITEC LANW150NU2 0x0168 LAN-W150N/U2 /* Longcheer Holdings, Ltd. products */ product LONGCHEER WM66 0x6061 Longcheer WM66 HSDPA @@ -2204,7 +2205,8 @@ product MELCO RT2870_1 0x0148 RT2870 product MELCO RT2870_2 0x0150 RT2870 product MELCO WLIUCGN 0x015d WLI-UC-GN product MELCO WLIUCG301N 0x016f WLI-UC-G301N -product MELCO WLIUCGNM 0x01a2 WLI-UC-GNM +product MELCO WLIUCGNM 0x01a2 WLI-UC-GNM +product MELCO WLIUCGNM2 0x01ee WLI-UC-GNM2 /* Merlin products */ product MERLIN V620 0x1110 Merlin V620 @@ -2618,6 +2620,7 @@ product PLANEX2 GWUS54GD 0xed01 GW-US54GD product PLANEX2 GWUSMM 0xed02 GW-USMM product PLANEX2 RT2870 0xed06 RT2870 product PLANEX2 GWUSMICRON 0xed14 GW-USMicroN +product PLANEX2 GWUSVALUEEZ 0xed17 GW-USValue-EZ product PLANEX3 GWUS54GZ 0xab10 GW-US54GZ product PLANEX3 GU1000T 0xab11 GU-1000T product PLANEX3 GWUS54MINI 0xab13 GW-US54Mini diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 94ac4ea..c3a714d 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -209,6 +209,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(LOGITEC, RT2870_2), RUN_DEV(LOGITEC, RT2870_3), RUN_DEV(LOGITEC, LANW300NU2), + RUN_DEV(LOGITEC, LANW150NU2), RUN_DEV(MELCO, RT2870_1), RUN_DEV(MELCO, RT2870_2), RUN_DEV(MELCO, WLIUCAG300N), @@ -216,6 +217,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(MELCO, WLIUCG301N), RUN_DEV(MELCO, WLIUCGN), RUN_DEV(MELCO, WLIUCGNM), + RUN_DEV(MELCO, WLIUCGNM2), RUN_DEV(MOTOROLA4, RT2770), RUN_DEV(MOTOROLA4, RT3070), RUN_DEV(MSI, RT3070_1), diff --git a/sys/dev/virtio/balloon/virtio_balloon.c b/sys/dev/virtio/balloon/virtio_balloon.c index d589a73..9b45459 100644 --- a/sys/dev/virtio/balloon/virtio_balloon.c +++ b/sys/dev/virtio/balloon/virtio_balloon.c @@ -412,7 +412,6 @@ vtballoon_send_page_frames(struct vtballoon_softc *sc, struct virtqueue *vq, * interrupt handler will wake us up. */ VTBALLOON_LOCK(sc); - while ((c = virtqueue_dequeue(vq, NULL)) == NULL) msleep_spin(sc, VTBALLOON_MTX(sc), "vtbspf", 0); VTBALLOON_UNLOCK(sc); diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c index d05fa7a..d35421a 100644 --- a/sys/dev/virtio/block/virtio_blk.c +++ b/sys/dev/virtio/block/virtio_blk.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <sys/taskqueue.h> #include <geom/geom_disk.h> -#include <vm/uma.h> #include <machine/bus.h> #include <machine/resource.h> @@ -119,7 +118,7 @@ static int vtblk_shutdown(device_t); static int vtblk_open(struct disk *); static int vtblk_close(struct disk *); static int vtblk_ioctl(struct disk *, u_long, void *, int, - struct thread *); + struct thread *); static int vtblk_dump(void *, void *, vm_offset_t, off_t, size_t); static void vtblk_strategy(struct bio *); @@ -193,7 +192,7 @@ TUNABLE_INT("hw.vtblk.no_ident", &vtblk_no_ident); mtx_assert(VTBLK_MTX((_sc)), MA_NOTOWNED) #define VTBLK_DISK_NAME "vtbd" -#define VTBLK_QUIESCE_TIMEOUT (30 * hz) +#define VTBLK_QUIESCE_TIMEOUT (30 * hz) /* * Each block request uses at least two segments - one for the header @@ -201,8 +200,6 @@ TUNABLE_INT("hw.vtblk.no_ident", &vtblk_no_ident); */ #define VTBLK_MIN_SEGMENTS 2 -static uma_zone_t vtblk_req_zone; - static device_method_t vtblk_methods[] = { /* Device methods. */ DEVMETHOD(device_probe, vtblk_probe), @@ -236,19 +233,8 @@ vtblk_modevent(module_t mod, int type, void *unused) switch (type) { case MOD_LOAD: - vtblk_req_zone = uma_zcreate("vtblk_request", - sizeof(struct vtblk_request), - NULL, NULL, NULL, NULL, 0, 0); - break; case MOD_QUIESCE: case MOD_UNLOAD: - if (uma_zone_get_cur(vtblk_req_zone) > 0) - error = EBUSY; - else if (type == MOD_UNLOAD) { - uma_zdestroy(vtblk_req_zone); - vtblk_req_zone = NULL; - } - break; case MOD_SHUTDOWN: break; default: @@ -316,7 +302,7 @@ vtblk_attach(device_t dev) } sc->vtblk_max_nsegs = vtblk_maximum_segments(sc, &blkcfg); - if (sc->vtblk_max_nsegs <= VTBLK_MIN_SEGMENTS) { + if (sc->vtblk_max_nsegs <= VTBLK_MIN_SEGMENTS) { error = EINVAL; device_printf(dev, "fewer than minimum number of segments " "allowed: %d\n", sc->vtblk_max_nsegs); @@ -493,7 +479,6 @@ vtblk_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, int error; dp = arg; - error = 0; if ((sc = dp->d_drv1) == NULL) return (ENXIO); @@ -539,7 +524,7 @@ vtblk_strategy(struct bio *bp) return; } -#ifdef INVARIANTS +#ifdef INVARIANTS /* * Prevent read/write buffers spanning too many segments from * getting into the queue. This should only trip if d_maxsize @@ -547,13 +532,13 @@ vtblk_strategy(struct bio *bp) */ if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { int nsegs, max_nsegs; - + nsegs = sglist_count(bp->bio_data, bp->bio_bcount); max_nsegs = sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS; KASSERT(nsegs <= max_nsegs, - ("bio spanned too many segments: %d, max: %d", - nsegs, max_nsegs)); + ("bio %p spanned too many segments: %d, max: %d", + bp, nsegs, max_nsegs)); } #endif @@ -800,27 +785,22 @@ vtblk_execute_request(struct vtblk_softc *sc, struct vtblk_request *req) VTBLK_LOCK_ASSERT(sc); sglist_reset(sg); - error = sglist_append(sg, &req->vbr_hdr, - sizeof(struct virtio_blk_outhdr)); - KASSERT(error == 0, ("error adding header to sglist")); - KASSERT(sg->sg_nseg == 1, - ("header spanned multiple segments: %d", sg->sg_nseg)); + + sglist_append(sg, &req->vbr_hdr, sizeof(struct virtio_blk_outhdr)); if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { error = sglist_append(sg, bp->bio_data, bp->bio_bcount); - KASSERT(error == 0, ("error adding buffer to sglist")); + if (error || sg->sg_nseg == sg->sg_maxseg) + panic("%s: data buffer too big bio:%p error:%d", + __FUNCTION__, bp, error); /* BIO_READ means the host writes into our buffer. */ if (bp->bio_cmd == BIO_READ) - writable += sg->sg_nseg - 1; + writable = sg->sg_nseg - 1; } - error = sglist_append(sg, &req->vbr_ack, sizeof(uint8_t)); - KASSERT(error == 0, ("error adding ack to sglist")); writable++; - - KASSERT(sg->sg_nseg >= VTBLK_MIN_SEGMENTS, - ("fewer than min segments: %d", sg->sg_nseg)); + sglist_append(sg, &req->vbr_ack, sizeof(uint8_t)); readable = sg->sg_nseg - writable; @@ -995,12 +975,10 @@ vtblk_flush_dump(struct vtblk_softc *sc) static int vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req) { - device_t dev; struct virtqueue *vq; struct vtblk_request *r; int error; - dev = sc->vtblk_dev; vq = sc->vtblk_vq; if (!virtqueue_empty(vq)) @@ -1013,12 +991,12 @@ vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req) virtqueue_notify(vq); r = virtqueue_poll(vq, NULL); - KASSERT(r == req, ("unexpected request response")); + KASSERT(r == req, ("unexpected request response: %p/%p", r, req)); error = vtblk_request_error(req); if (error && bootverbose) { - device_printf(dev, "vtblk_poll_request: IO error: %d\n", - error); + device_printf(sc->vtblk_dev, + "%s: IO error: %d\n", __FUNCTION__, error); } return (error); @@ -1090,6 +1068,20 @@ vtblk_drain(struct vtblk_softc *sc) vtblk_free_requests(sc); } +#ifdef INVARIANTS +static void +vtblk_request_invariants(struct vtblk_request *req) +{ + int hdr_nsegs, ack_nsegs; + + hdr_nsegs = sglist_count(&req->vbr_hdr, sizeof(req->vbr_hdr)); + ack_nsegs = sglist_count(&req->vbr_ack, sizeof(req->vbr_ack)); + + KASSERT(hdr_nsegs == 1, ("request header crossed page boundary")); + KASSERT(ack_nsegs == 1, ("request ack crossed page boundary")); +} +#endif + static int vtblk_alloc_requests(struct vtblk_softc *sc) { @@ -1107,10 +1099,14 @@ vtblk_alloc_requests(struct vtblk_softc *sc) nreqs /= VTBLK_MIN_SEGMENTS; for (i = 0; i < nreqs; i++) { - req = uma_zalloc(vtblk_req_zone, M_NOWAIT); + req = malloc(sizeof(struct vtblk_request), M_DEVBUF, M_NOWAIT); if (req == NULL) return (ENOMEM); +#ifdef INVARIANTS + vtblk_request_invariants(req); +#endif + sc->vtblk_request_count++; vtblk_enqueue_request(sc, req); } @@ -1128,10 +1124,11 @@ vtblk_free_requests(struct vtblk_softc *sc) while ((req = vtblk_dequeue_request(sc)) != NULL) { sc->vtblk_request_count--; - uma_zfree(vtblk_req_zone, req); + free(req, M_DEVBUF); } - KASSERT(sc->vtblk_request_count == 0, ("leaked requests")); + KASSERT(sc->vtblk_request_count == 0, + ("leaked requests: %d", sc->vtblk_request_count)); } static struct vtblk_request * diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index 64a82ac..e6fef90 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -748,11 +748,9 @@ vtnet_is_link_up(struct vtnet_softc *sc) static void vtnet_update_link_status(struct vtnet_softc *sc) { - device_t dev; struct ifnet *ifp; int link; - dev = sc->vtnet_dev; ifp = sc->vtnet_ifp; link = vtnet_is_link_up(sc); diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index 56813e4..917ca84 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -57,12 +57,15 @@ struct vtpci_softc { struct resource *vtpci_msix_res; uint64_t vtpci_features; uint32_t vtpci_flags; -#define VIRTIO_PCI_FLAG_NO_MSI 0x0001 -#define VIRTIO_PCI_FLAG_MSI 0x0002 -#define VIRTIO_PCI_FLAG_NO_MSIX 0x0010 -#define VIRTIO_PCI_FLAG_MSIX 0x0020 -#define VIRTIO_PCI_FLAG_SHARED_MSIX 0x0040 - +#define VTPCI_FLAG_NO_MSI 0x0001 +#define VTPCI_FLAG_NO_MSIX 0x0002 +#define VTPCI_FLAG_LEGACY 0x1000 +#define VTPCI_FLAG_MSI 0x2000 +#define VTPCI_FLAG_MSIX 0x4000 +#define VTPCI_FLAG_SHARED_MSIX 0x8000 +#define VTPCI_FLAG_ITYPE_MASK 0xF000 + + /* This "bus" will only ever have one child. */ device_t vtpci_child_dev; struct virtio_feature_desc *vtpci_child_feat_desc; @@ -80,7 +83,8 @@ struct vtpci_softc { int vtpci_nvqs; struct vtpci_virtqueue { struct virtqueue *vq; - + /* Device did not provide a callback for this virtqueue. */ + int no_intr; /* Index into vtpci_intr_res[] below. Unused, then -1. */ int ires_idx; } vtpci_vqx[VIRTIO_MAX_VIRTQUEUES]; @@ -130,24 +134,39 @@ static void vtpci_describe_features(struct vtpci_softc *, const char *, uint64_t); static void vtpci_probe_and_attach_child(struct vtpci_softc *); -static int vtpci_alloc_interrupts(struct vtpci_softc *, int, int, - struct vq_alloc_info *); -static int vtpci_alloc_intr_resources(struct vtpci_softc *, int, - struct vq_alloc_info *); -static int vtpci_alloc_msi(struct vtpci_softc *); -static int vtpci_alloc_msix(struct vtpci_softc *, int); +static int vtpci_alloc_msix(struct vtpci_softc *, int); +static int vtpci_alloc_msi(struct vtpci_softc *); +static int vtpci_alloc_intr_msix_pervq(struct vtpci_softc *); +static int vtpci_alloc_intr_msix_shared(struct vtpci_softc *); +static int vtpci_alloc_intr_msi(struct vtpci_softc *); +static int vtpci_alloc_intr_legacy(struct vtpci_softc *); +static int vtpci_alloc_intr_resources(struct vtpci_softc *); + +static int vtpci_setup_legacy_interrupt(struct vtpci_softc *, + enum intr_type); +static int vtpci_setup_msix_interrupts(struct vtpci_softc *, + enum intr_type); +static int vtpci_setup_interrupts(struct vtpci_softc *, enum intr_type); + static int vtpci_register_msix_vector(struct vtpci_softc *, int, int); +static int vtpci_set_host_msix_vectors(struct vtpci_softc *); +static int vtpci_reinit_virtqueue(struct vtpci_softc *, int); static void vtpci_free_interrupts(struct vtpci_softc *); static void vtpci_free_virtqueues(struct vtpci_softc *); +static void vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *); static void vtpci_release_child_resources(struct vtpci_softc *); static void vtpci_reset(struct vtpci_softc *); +static void vtpci_select_virtqueue(struct vtpci_softc *, int); + static int vtpci_legacy_intr(void *); static int vtpci_vq_shared_intr(void *); static int vtpci_vq_intr(void *); static int vtpci_config_intr(void *); +#define vtpci_setup_msi_interrupt vtpci_setup_legacy_interrupt + /* * I/O port read/write wrappers. */ @@ -252,7 +271,7 @@ vtpci_attach(device_t dev) } if (pci_find_cap(dev, PCIY_MSI, NULL) != 0) - sc->vtpci_flags |= VIRTIO_PCI_FLAG_NO_MSI; + sc->vtpci_flags |= VTPCI_FLAG_NO_MSI; if (pci_find_cap(dev, PCIY_MSIX, NULL) == 0) { rid = PCIR_BAR(1); @@ -261,7 +280,7 @@ vtpci_attach(device_t dev) } if (sc->vtpci_msix_res == NULL) - sc->vtpci_flags |= VIRTIO_PCI_FLAG_NO_MSIX; + sc->vtpci_flags |= VTPCI_FLAG_NO_MSIX; vtpci_reset(sc); @@ -372,6 +391,16 @@ vtpci_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) switch (index) { case VIRTIO_IVAR_DEVTYPE: + case VIRTIO_IVAR_SUBDEVICE: + *result = pci_get_subdevice(dev); + break; + case VIRTIO_IVAR_VENDOR: + *result = pci_get_vendor(dev); + break; + case VIRTIO_IVAR_DEVICE: + *result = pci_get_device(dev); + break; + case VIRTIO_IVAR_SUBVENDOR: *result = pci_get_subdevice(dev); break; default: @@ -442,102 +471,97 @@ vtpci_alloc_virtqueues(device_t dev, int flags, int nvqs, struct vq_alloc_info *vq_info) { struct vtpci_softc *sc; + struct virtqueue *vq; struct vtpci_virtqueue *vqx; struct vq_alloc_info *info; - int queue, error; - uint16_t vq_size; + int idx, error; + uint16_t size; sc = device_get_softc(dev); + error = 0; - if (sc->vtpci_nvqs != 0 || nvqs <= 0 || - nvqs > VIRTIO_MAX_VIRTQUEUES) + if (sc->vtpci_nvqs != 0) + return (EALREADY); + if (nvqs <= 0 || nvqs > VIRTIO_MAX_VIRTQUEUES) return (EINVAL); - error = vtpci_alloc_interrupts(sc, flags, nvqs, vq_info); - if (error) { - device_printf(dev, "cannot allocate interrupts\n"); - return (error); - } + if (flags & VIRTIO_ALLOC_VQS_DISABLE_MSIX) + sc->vtpci_flags |= VTPCI_FLAG_NO_MSIX; - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) { - error = vtpci_register_msix_vector(sc, - VIRTIO_MSI_CONFIG_VECTOR, 0); - if (error) - return (error); - } - - for (queue = 0; queue < nvqs; queue++) { - vqx = &sc->vtpci_vqx[queue]; - info = &vq_info[queue]; + for (idx = 0; idx < nvqs; idx++) { + vqx = &sc->vtpci_vqx[idx]; + info = &vq_info[idx]; - vtpci_write_config_2(sc, VIRTIO_PCI_QUEUE_SEL, queue); - - vq_size = vtpci_read_config_2(sc, VIRTIO_PCI_QUEUE_NUM); - error = virtqueue_alloc(dev, queue, vq_size, - VIRTIO_PCI_VRING_ALIGN, 0xFFFFFFFFUL, info, &vqx->vq); - if (error) - return (error); + vtpci_select_virtqueue(sc, idx); + size = vtpci_read_config_2(sc, VIRTIO_PCI_QUEUE_NUM); - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) { - error = vtpci_register_msix_vector(sc, - VIRTIO_MSI_QUEUE_VECTOR, vqx->ires_idx); - if (error) - return (error); + error = virtqueue_alloc(dev, idx, size, VIRTIO_PCI_VRING_ALIGN, + 0xFFFFFFFFUL, info, &vq); + if (error) { + device_printf(dev, + "cannot allocate virtqueue %d: %d\n", idx, error); + break; } vtpci_write_config_4(sc, VIRTIO_PCI_QUEUE_PFN, - virtqueue_paddr(vqx->vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + virtqueue_paddr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + + vqx->vq = *info->vqai_vq = vq; + vqx->no_intr = info->vqai_intr == NULL; - *info->vqai_vq = vqx->vq; sc->vtpci_nvqs++; } - return (0); + return (error); } static int vtpci_setup_intr(device_t dev, enum intr_type type) { struct vtpci_softc *sc; - struct vtpci_intr_resource *ires; - struct vtpci_virtqueue *vqx; - int i, flags, error; + int attempt, error; sc = device_get_softc(dev); - flags = type | INTR_MPSAFE; - ires = &sc->vtpci_intr_res[0]; - - if ((sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) == 0) { - error = bus_setup_intr(dev, ires->irq, flags, - vtpci_legacy_intr, NULL, sc, &ires->intrhand); - - return (error); - } - error = bus_setup_intr(dev, ires->irq, flags, vtpci_config_intr, - NULL, sc, &ires->intrhand); - if (error) - return (error); + for (attempt = 0; attempt < 5; attempt++) { + /* + * Start with the most desirable interrupt configuration and + * fallback towards less desirable ones. + */ + switch (attempt) { + case 0: + error = vtpci_alloc_intr_msix_pervq(sc); + break; + case 1: + error = vtpci_alloc_intr_msix_shared(sc); + break; + case 2: + error = vtpci_alloc_intr_msi(sc); + break; + case 3: + error = vtpci_alloc_intr_legacy(sc); + break; + default: + device_printf(dev, + "exhausted all interrupt allocation attempts\n"); + return (ENXIO); + } - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_SHARED_MSIX) { - ires = &sc->vtpci_intr_res[1]; - error = bus_setup_intr(dev, ires->irq, flags, - vtpci_vq_shared_intr, NULL, sc, &ires->intrhand); + if (error == 0 && vtpci_setup_interrupts(sc, type) == 0) + break; - return (error); + vtpci_cleanup_setup_intr_attempt(sc); } - /* Setup an interrupt handler for each virtqueue. */ - for (i = 0; i < sc->vtpci_nvqs; i++) { - vqx = &sc->vtpci_vqx[i]; - if (vqx->ires_idx < 1) - continue; - - ires = &sc->vtpci_intr_res[vqx->ires_idx]; - error = bus_setup_intr(dev, ires->irq, flags, - vtpci_vq_intr, NULL, vqx->vq, &ires->intrhand); - if (error) - return (error); + if (bootverbose) { + if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) + device_printf(dev, "using legacy interrupt\n"); + else if (sc->vtpci_flags & VTPCI_FLAG_MSI) + device_printf(dev, "using MSI interrupt\n"); + else if (sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) + device_printf(dev, "using shared MSIX interrupts\n"); + else + device_printf(dev, "using per VQ MSIX interrupts\n"); } return (0); @@ -554,20 +578,19 @@ static int vtpci_reinit(device_t dev, uint64_t features) { struct vtpci_softc *sc; - struct vtpci_virtqueue *vqx; - struct virtqueue *vq; - int queue, error; - uint16_t vq_size; + int idx, error; sc = device_get_softc(dev); /* - * Redrive the device initialization. This is a bit of an abuse - * of the specification, but both VirtualBox and QEMU/KVM seem - * to play nice. We do not allow the host device to change from - * what was originally negotiated beyond what the guest driver - * changed (MSIX state should not change, number of virtqueues - * and their size remain the same, etc). + * Redrive the device initialization. This is a bit of an abuse of + * the specification, but VirtualBox, QEMU/KVM, and BHyVe seem to + * play nice. + * + * We do not allow the host device to change from what was originally + * negotiated beyond what the guest driver changed. MSIX state should + * not change, number of virtqueues and their size remain the same, etc. + * This will need to be rethought when we want to support migration. */ if (vtpci_get_status(dev) != VIRTIO_CONFIG_STATUS_RESET) @@ -582,34 +605,16 @@ vtpci_reinit(device_t dev, uint64_t features) vtpci_negotiate_features(dev, features); - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) { - error = vtpci_register_msix_vector(sc, - VIRTIO_MSI_CONFIG_VECTOR, 0); + for (idx = 0; idx < sc->vtpci_nvqs; idx++) { + error = vtpci_reinit_virtqueue(sc, idx); if (error) return (error); } - for (queue = 0; queue < sc->vtpci_nvqs; queue++) { - vqx = &sc->vtpci_vqx[queue]; - vq = vqx->vq; - - KASSERT(vq != NULL, ("vq %d not allocated", queue)); - vtpci_write_config_2(sc, VIRTIO_PCI_QUEUE_SEL, queue); - - vq_size = vtpci_read_config_2(sc, VIRTIO_PCI_QUEUE_NUM); - error = virtqueue_reinit(vq, vq_size); + if (sc->vtpci_flags & VTPCI_FLAG_MSIX) { + error = vtpci_set_host_msix_vectors(sc); if (error) return (error); - - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) { - error = vtpci_register_msix_vector(sc, - VIRTIO_MSI_QUEUE_VECTOR, vqx->ires_idx); - if (error) - return (error); - } - - vtpci_write_config_4(sc, VIRTIO_PCI_QUEUE_PFN, - virtqueue_paddr(vqx->vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } return (0); @@ -744,7 +749,6 @@ vtpci_probe_and_attach_child(struct vtpci_softc *sc) vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED); vtpci_reset(sc); vtpci_release_child_resources(sc); - /* Reset status for future attempt. */ vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_ACK); } else @@ -752,42 +756,126 @@ vtpci_probe_and_attach_child(struct vtpci_softc *sc) } static int -vtpci_alloc_interrupts(struct vtpci_softc *sc, int flags, int nvqs, - struct vq_alloc_info *vq_info) +vtpci_alloc_msix(struct vtpci_softc *sc, int nvectors) +{ + device_t dev; + int nmsix, cnt, required; + + dev = sc->vtpci_dev; + + /* Allocate an additional vector for the config changes. */ + required = nvectors + 1; + + nmsix = pci_msix_count(dev); + if (nmsix < required) + return (1); + + cnt = required; + if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) { + sc->vtpci_nintr_res = required; + return (0); + } + + pci_release_msi(dev); + + return (1); +} + +static int +vtpci_alloc_msi(struct vtpci_softc *sc) +{ + device_t dev; + int nmsi, cnt, required; + + dev = sc->vtpci_dev; + required = 1; + + nmsi = pci_msi_count(dev); + if (nmsi < required) + return (1); + + cnt = required; + if (pci_alloc_msi(dev, &cnt) == 0 && cnt >= required) { + sc->vtpci_nintr_res = required; + return (0); + } + + pci_release_msi(dev); + + return (1); +} + +static int +vtpci_alloc_intr_msix_pervq(struct vtpci_softc *sc) { int i, nvectors, error; - /* - * Only allocate a vector for virtqueues that are actually - * expecting an interrupt. - */ - for (nvectors = 0, i = 0; i < nvqs; i++) - if (vq_info[i].vqai_intr != NULL) + if (vtpci_disable_msix != 0 || + sc->vtpci_flags & VTPCI_FLAG_NO_MSIX) + return (ENOTSUP); + + for (nvectors = 0, i = 0; i < sc->vtpci_nvqs; i++) { + if (sc->vtpci_vqx[i].no_intr == 0) nvectors++; + } + + error = vtpci_alloc_msix(sc, nvectors); + if (error) + return (error); + + sc->vtpci_flags |= VTPCI_FLAG_MSIX; + + return (0); +} + +static int +vtpci_alloc_intr_msix_shared(struct vtpci_softc *sc) +{ + int error; if (vtpci_disable_msix != 0 || - sc->vtpci_flags & VIRTIO_PCI_FLAG_NO_MSIX || - flags & VIRTIO_ALLOC_VQS_DISABLE_MSIX || - vtpci_alloc_msix(sc, nvectors) != 0) { - /* - * Use MSI interrupts if available. Otherwise, we fallback - * to legacy interrupts. - */ - if ((sc->vtpci_flags & VIRTIO_PCI_FLAG_NO_MSI) == 0 && - vtpci_alloc_msi(sc) == 0) - sc->vtpci_flags |= VIRTIO_PCI_FLAG_MSI; + sc->vtpci_flags & VTPCI_FLAG_NO_MSIX) + return (ENOTSUP); - sc->vtpci_nintr_res = 1; - } + error = vtpci_alloc_msix(sc, 1); + if (error) + return (error); - error = vtpci_alloc_intr_resources(sc, nvqs, vq_info); + sc->vtpci_flags |= VTPCI_FLAG_MSIX | VTPCI_FLAG_SHARED_MSIX; - return (error); + return (0); } static int -vtpci_alloc_intr_resources(struct vtpci_softc *sc, int nvqs, - struct vq_alloc_info *vq_info) +vtpci_alloc_intr_msi(struct vtpci_softc *sc) +{ + int error; + + /* Only BHyVe supports MSI. */ + if (sc->vtpci_flags & VTPCI_FLAG_NO_MSI) + return (ENOTSUP); + + error = vtpci_alloc_msi(sc); + if (error) + return (error); + + sc->vtpci_flags |= VTPCI_FLAG_MSI; + + return (0); +} + +static int +vtpci_alloc_intr_legacy(struct vtpci_softc *sc) +{ + + sc->vtpci_flags |= VTPCI_FLAG_LEGACY; + sc->vtpci_nintr_res = 1; + + return (0); +} + +static int +vtpci_alloc_intr_resources(struct vtpci_softc *sc) { device_t dev; struct resource *irq; @@ -795,14 +883,14 @@ vtpci_alloc_intr_resources(struct vtpci_softc *sc, int nvqs, int i, rid, flags, res_idx; dev = sc->vtpci_dev; - flags = RF_ACTIVE; - if ((sc->vtpci_flags & - (VIRTIO_PCI_FLAG_MSI | VIRTIO_PCI_FLAG_MSIX)) == 0) { + if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) { rid = 0; - flags |= RF_SHAREABLE; - } else + flags = RF_ACTIVE | RF_SHAREABLE; + } else { rid = 1; + flags = RF_ACTIVE; + } for (i = 0; i < sc->vtpci_nintr_res; i++) { irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, flags); @@ -814,16 +902,16 @@ vtpci_alloc_intr_resources(struct vtpci_softc *sc, int nvqs, } /* - * Map the virtqueue into the correct index in vq_intr_res[]. Note the - * first index is reserved for configuration changes notifications. + * Map the virtqueue into the correct index in vq_intr_res[]. The + * first index is reserved for configuration changed notifications. */ - for (i = 0, res_idx = 1; i < nvqs; i++) { + for (i = 0, res_idx = 1; i < sc->vtpci_nvqs; i++) { vqx = &sc->vtpci_vqx[i]; - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) { - if (vq_info[i].vqai_intr == NULL) + if (sc->vtpci_flags & VTPCI_FLAG_MSIX) { + if (vqx->no_intr != 0) vqx->ires_idx = -1; - else if (sc->vtpci_flags & VIRTIO_PCI_FLAG_SHARED_MSIX) + else if (sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) vqx->ires_idx = res_idx; else vqx->ires_idx = res_idx++; @@ -835,110 +923,180 @@ vtpci_alloc_intr_resources(struct vtpci_softc *sc, int nvqs, } static int -vtpci_alloc_msi(struct vtpci_softc *sc) +vtpci_setup_legacy_interrupt(struct vtpci_softc *sc, enum intr_type type) { device_t dev; - int nmsi, cnt; + struct vtpci_intr_resource *ires; + int error; dev = sc->vtpci_dev; - nmsi = pci_msi_count(dev); - - if (nmsi < 1) - return (1); - cnt = 1; - if (pci_alloc_msi(dev, &cnt) == 0 && cnt == 1) - return (0); + ires = &sc->vtpci_intr_res[0]; + error = bus_setup_intr(dev, ires->irq, type, vtpci_legacy_intr, NULL, + sc, &ires->intrhand); - return (1); + return (error); } static int -vtpci_alloc_msix(struct vtpci_softc *sc, int nvectors) +vtpci_setup_msix_interrupts(struct vtpci_softc *sc, enum intr_type type) { device_t dev; - int nmsix, cnt, required; + struct vtpci_intr_resource *ires; + struct vtpci_virtqueue *vqx; + int i, error; dev = sc->vtpci_dev; - nmsix = pci_msix_count(dev); - if (nmsix < 1) - return (1); + /* + * The first resource is used for configuration changed interrupts. + */ + ires = &sc->vtpci_intr_res[0]; + error = bus_setup_intr(dev, ires->irq, type, vtpci_config_intr, + NULL, sc, &ires->intrhand); + if (error) + return (error); - /* An additional vector is needed for the config changes. */ - required = nvectors + 1; - if (nmsix >= required) { - cnt = required; - if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) - goto out; + if (sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) { + ires = &sc->vtpci_intr_res[1]; - pci_release_msi(dev); + error = bus_setup_intr(dev, ires->irq, type, + vtpci_vq_shared_intr, NULL, sc, &ires->intrhand); + if (error) + return (error); + } else { + /* + * Each remaining resource is assigned to a specific virtqueue. + */ + for (i = 0; i < sc->vtpci_nvqs; i++) { + vqx = &sc->vtpci_vqx[i]; + if (vqx->ires_idx < 1) + continue; + + ires = &sc->vtpci_intr_res[vqx->ires_idx]; + error = bus_setup_intr(dev, ires->irq, type, + vtpci_vq_intr, NULL, vqx->vq, &ires->intrhand); + if (error) + return (error); + } } - /* Attempt shared MSIX configuration. */ - required = 2; - if (nmsix >= required) { - cnt = required; - if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) { - sc->vtpci_flags |= VIRTIO_PCI_FLAG_SHARED_MSIX; - goto out; - } + error = vtpci_set_host_msix_vectors(sc); + if (error) + return (error); - pci_release_msi(dev); - } + return (0); +} - return (1); +static int +vtpci_setup_interrupts(struct vtpci_softc *sc, enum intr_type type) +{ + int error; -out: - sc->vtpci_nintr_res = required; - sc->vtpci_flags |= VIRTIO_PCI_FLAG_MSIX; + type |= INTR_MPSAFE; + KASSERT(sc->vtpci_flags & VTPCI_FLAG_ITYPE_MASK, + ("no interrupt type selected: %#x", sc->vtpci_flags)); - if (bootverbose) { - if (sc->vtpci_flags & VIRTIO_PCI_FLAG_SHARED_MSIX) - device_printf(dev, "using shared virtqueue MSIX\n"); - else - device_printf(dev, "using per virtqueue MSIX\n"); - } + error = vtpci_alloc_intr_resources(sc); + if (error) + return (error); - return (0); + if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) + error = vtpci_setup_legacy_interrupt(sc, type); + else if (sc->vtpci_flags & VTPCI_FLAG_MSI) + error = vtpci_setup_msi_interrupt(sc, type); + else + error = vtpci_setup_msix_interrupts(sc, type); + + return (error); } static int vtpci_register_msix_vector(struct vtpci_softc *sc, int offset, int res_idx) { device_t dev; - uint16_t vector; + uint16_t vector, rdvector; dev = sc->vtpci_dev; - if (offset != VIRTIO_MSI_CONFIG_VECTOR && - offset != VIRTIO_MSI_QUEUE_VECTOR) - return (EINVAL); - if (res_idx != -1) { - /* Map from rid to host vector. */ + /* Map from guest rid to host vector. */ vector = sc->vtpci_intr_res[res_idx].rid - 1; } else vector = VIRTIO_MSI_NO_VECTOR; - /* The first resource is special; make sure it is used correctly. */ + /* + * Assert the first resource is always used for the configuration + * changed interrupts. + */ if (res_idx == 0) { - KASSERT(vector == 0, ("unexpected config vector")); - KASSERT(offset == VIRTIO_MSI_CONFIG_VECTOR, - ("unexpected config offset")); - } + KASSERT(vector == 0 && offset == VIRTIO_MSI_CONFIG_VECTOR, + ("bad first res use vector:%d offset:%d", vector, offset)); + } else + KASSERT(offset == VIRTIO_MSI_QUEUE_VECTOR, ("bad offset")); vtpci_write_config_2(sc, offset, vector); - if (vtpci_read_config_2(sc, offset) != vector) { - device_printf(dev, "insufficient host resources for " - "MSIX interrupts\n"); + /* Read vector to determine if the host had sufficient resources. */ + rdvector = vtpci_read_config_2(sc, offset); + if (rdvector != vector) { + device_printf(dev, + "insufficient host resources for MSIX interrupts\n"); return (ENODEV); } return (0); } +static int +vtpci_set_host_msix_vectors(struct vtpci_softc *sc) +{ + struct vtpci_virtqueue *vqx; + int idx, error; + + error = vtpci_register_msix_vector(sc, VIRTIO_MSI_CONFIG_VECTOR, 0); + if (error) + return (error); + + for (idx = 0; idx < sc->vtpci_nvqs; idx++) { + vqx = &sc->vtpci_vqx[idx]; + + vtpci_select_virtqueue(sc, idx); + error = vtpci_register_msix_vector(sc, VIRTIO_MSI_QUEUE_VECTOR, + vqx->ires_idx); + if (error) + return (error); + } + + return (0); +} + +static int +vtpci_reinit_virtqueue(struct vtpci_softc *sc, int idx) +{ + struct vtpci_virtqueue *vqx; + struct virtqueue *vq; + int error; + uint16_t size; + + vqx = &sc->vtpci_vqx[idx]; + vq = vqx->vq; + + KASSERT(vq != NULL, ("vq %d not allocated", idx)); + + vtpci_select_virtqueue(sc, idx); + size = vtpci_read_config_2(sc, VIRTIO_PCI_QUEUE_NUM); + + error = virtqueue_reinit(vq, size); + if (error) + return (error); + + vtpci_write_config_4(sc, VIRTIO_PCI_QUEUE_PFN, + virtqueue_paddr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + + return (0); +} + static void vtpci_free_interrupts(struct vtpci_softc *sc) { @@ -947,15 +1105,8 @@ vtpci_free_interrupts(struct vtpci_softc *sc) int i; dev = sc->vtpci_dev; - sc->vtpci_nintr_res = 0; - - if (sc->vtpci_flags & (VIRTIO_PCI_FLAG_MSI | VIRTIO_PCI_FLAG_MSIX)) { - pci_release_msi(dev); - sc->vtpci_flags &= ~(VIRTIO_PCI_FLAG_MSI | - VIRTIO_PCI_FLAG_MSIX | VIRTIO_PCI_FLAG_SHARED_MSIX); - } - for (i = 0; i < 1 + VIRTIO_MAX_VIRTQUEUES; i++) { + for (i = 0; i < sc->vtpci_nintr_res; i++) { ires = &sc->vtpci_intr_res[i]; if (ires->intrhand != NULL) { @@ -971,6 +1122,12 @@ vtpci_free_interrupts(struct vtpci_softc *sc) ires->rid = -1; } + + if (sc->vtpci_flags & (VTPCI_FLAG_MSI | VTPCI_FLAG_MSIX)) + pci_release_msi(dev); + + sc->vtpci_nintr_res = 0; + sc->vtpci_flags &= ~VTPCI_FLAG_ITYPE_MASK; } static void @@ -979,16 +1136,33 @@ vtpci_free_virtqueues(struct vtpci_softc *sc) struct vtpci_virtqueue *vqx; int i; + for (i = 0; i < sc->vtpci_nvqs; i++) { + vqx = &sc->vtpci_vqx[i]; + + virtqueue_free(vqx->vq); + vqx->vq = NULL; + } + sc->vtpci_nvqs = 0; +} - for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) { - vqx = &sc->vtpci_vqx[i]; +static void +vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *sc) +{ + int idx; - if (vqx->vq != NULL) { - virtqueue_free(vqx->vq); - vqx->vq = NULL; + if (sc->vtpci_flags & VTPCI_FLAG_MSIX) { + vtpci_write_config_2(sc, VIRTIO_MSI_CONFIG_VECTOR, + VIRTIO_MSI_NO_VECTOR); + + for (idx = 0; idx < sc->vtpci_nvqs; idx++) { + vtpci_select_virtqueue(sc, idx); + vtpci_write_config_2(sc, VIRTIO_MSI_QUEUE_VECTOR, + VIRTIO_MSI_NO_VECTOR); } } + + vtpci_free_interrupts(sc); } static void @@ -1010,6 +1184,13 @@ vtpci_reset(struct vtpci_softc *sc) vtpci_set_status(sc->vtpci_dev, VIRTIO_CONFIG_STATUS_RESET); } +static void +vtpci_select_virtqueue(struct vtpci_softc *sc, int idx) +{ + + vtpci_write_config_2(sc, VIRTIO_PCI_QUEUE_SEL, idx); +} + static int vtpci_legacy_intr(void *xsc) { diff --git a/sys/dev/virtio/pci/virtio_pci.h b/sys/dev/virtio/pci/virtio_pci.h index d8daa31..485cf4f 100644 --- a/sys/dev/virtio/pci/virtio_pci.h +++ b/sys/dev/virtio/pci/virtio_pci.h @@ -73,7 +73,7 @@ * configuration space. */ #define VIRTIO_PCI_CONFIG(sc) \ - (((sc)->vtpci_flags & VIRTIO_PCI_FLAG_MSIX) ? 24 : 20) + (((sc)->vtpci_flags & VTPCI_FLAG_MSIX) ? 24 : 20) /* * How many bits to shift physical queue address written to QUEUE_PFN. diff --git a/sys/dev/virtio/virtio.c b/sys/dev/virtio/virtio.c index e385575..1cac3c7 100644 --- a/sys/dev/virtio/virtio.c +++ b/sys/dev/virtio/virtio.c @@ -86,28 +86,6 @@ virtio_device_name(uint16_t devid) return (NULL); } -int -virtio_get_device_type(device_t dev) -{ - uintptr_t devtype; - - devtype = -1; - - BUS_READ_IVAR(device_get_parent(dev), dev, - VIRTIO_IVAR_DEVTYPE, &devtype); - - return ((int) devtype); -} - -void -virtio_set_feature_desc(device_t dev, - struct virtio_feature_desc *feature_desc) -{ - - BUS_WRITE_IVAR(device_get_parent(dev), dev, - VIRTIO_IVAR_FEATURE_DESC, (uintptr_t) feature_desc); -} - void virtio_describe(device_t dev, const char *msg, uint64_t features, struct virtio_feature_desc *feature_desc) @@ -184,6 +162,21 @@ virtio_feature_name(uint64_t val, struct virtio_feature_desc *feature_desc) * VirtIO bus method wrappers. */ +void +virtio_read_ivar(device_t dev, int ivar, uintptr_t *val) +{ + + *val = -1; + BUS_READ_IVAR(device_get_parent(dev), dev, ivar, val); +} + +void +virtio_write_ivar(device_t dev, int ivar, uintptr_t val) +{ + + BUS_WRITE_IVAR(device_get_parent(dev), dev, ivar, val); +} + uint64_t virtio_negotiate_features(device_t dev, uint64_t child_features) { diff --git a/sys/dev/virtio/virtio.h b/sys/dev/virtio/virtio.h index e0ecfb9..8c22b12 100644 --- a/sys/dev/virtio/virtio.h +++ b/sys/dev/virtio/virtio.h @@ -91,6 +91,10 @@ struct vq_alloc_info; */ #define VIRTIO_IVAR_DEVTYPE 1 #define VIRTIO_IVAR_FEATURE_DESC 2 +#define VIRTIO_IVAR_VENDOR 3 +#define VIRTIO_IVAR_DEVICE 4 +#define VIRTIO_IVAR_SUBVENDOR 5 +#define VIRTIO_IVAR_SUBDEVICE 6 struct virtio_feature_desc { uint64_t vfd_val; @@ -98,15 +102,14 @@ struct virtio_feature_desc { }; const char *virtio_device_name(uint16_t devid); -int virtio_get_device_type(device_t dev); -void virtio_set_feature_desc(device_t dev, - struct virtio_feature_desc *feature_desc); void virtio_describe(device_t dev, const char *msg, uint64_t features, struct virtio_feature_desc *feature_desc); /* * VirtIO Bus Methods. */ +void virtio_read_ivar(device_t dev, int ivar, uintptr_t *val); +void virtio_write_ivar(device_t dev, int ivar, uintptr_t val); uint64_t virtio_negotiate_features(device_t dev, uint64_t child_features); int virtio_alloc_virtqueues(device_t dev, int flags, int nvqs, struct vq_alloc_info *info); @@ -148,4 +151,28 @@ VIRTIO_RDWR_DEVICE_CONFIG(1, uint8_t); VIRTIO_RDWR_DEVICE_CONFIG(2, uint16_t); VIRTIO_RDWR_DEVICE_CONFIG(4, uint32_t); +#define VIRTIO_READ_IVAR(name, ivar) \ +static inline int \ +__CONCAT(virtio_get_,name)(device_t dev) \ +{ \ + uintptr_t val; \ + virtio_read_ivar(dev, ivar, &val); \ + return ((int) val); \ +} + +VIRTIO_READ_IVAR(device_type, VIRTIO_IVAR_DEVTYPE); +VIRTIO_READ_IVAR(vendor, VIRTIO_IVAR_VENDOR); +VIRTIO_READ_IVAR(device, VIRTIO_IVAR_DEVICE); +VIRTIO_READ_IVAR(subvendor, VIRTIO_IVAR_SUBVENDOR); +VIRTIO_READ_IVAR(subdevice, VIRTIO_IVAR_SUBDEVICE); + +#define VIRTIO_WRITE_IVAR(name, ivar) \ +static inline void \ +__CONCAT(virtio_set_,name)(device_t dev, void *val) \ +{ \ + virtio_write_ivar(dev, ivar, (uintptr_t) val); \ +} + +VIRTIO_WRITE_IVAR(feature_desc, VIRTIO_IVAR_FEATURE_DESC); + #endif /* _VIRTIO_H_ */ diff --git a/sys/dev/virtio/virtio_ring.h b/sys/dev/virtio/virtio_ring.h index 0d00013..8e902ab 100644 --- a/sys/dev/virtio/virtio_ring.h +++ b/sys/dev/virtio/virtio_ring.h @@ -120,8 +120,8 @@ struct vring { * We publish the used event index at the end of the available ring, and vice * versa. They are at the end for backwards compatibility. */ -#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) -#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) +#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) +#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) static inline int vring_size(unsigned int num, unsigned long align) @@ -129,10 +129,11 @@ vring_size(unsigned int num, unsigned long align) int size; size = num * sizeof(struct vring_desc); - size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)); + size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + + sizeof(uint16_t); size = (size + align - 1) & ~(align - 1); size += sizeof(struct vring_used) + - (num * sizeof(struct vring_used_elem)); + (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); return (size); } diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c index 31f47d0..83d39ba 100644 --- a/sys/dev/virtio/virtqueue.c +++ b/sys/dev/virtio/virtqueue.c @@ -127,6 +127,7 @@ static uint16_t vq_ring_enqueue_segments(struct virtqueue *, static int vq_ring_use_indirect(struct virtqueue *, int); static void vq_ring_enqueue_indirect(struct virtqueue *, void *, struct sglist *, int, int); +static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t); static int vq_ring_must_notify_host(struct virtqueue *); static void vq_ring_notify_host(struct virtqueue *); static void vq_ring_free_chain(struct virtqueue *, uint16_t); @@ -311,7 +312,7 @@ virtqueue_reinit(struct virtqueue *vq, uint16_t size) /* Warn if the virtqueue was not properly cleaned up. */ if (vq->vq_free_cnt != vq->vq_nentries) { device_printf(vq->vq_dev, - "%s: warning, '%s' virtqueue not empty, " + "%s: warning '%s' virtqueue not empty, " "leaking %d entries\n", __func__, vq->vq_name, vq->vq_nentries - vq->vq_free_cnt); } @@ -390,6 +391,7 @@ virtqueue_full(struct virtqueue *vq) void virtqueue_notify(struct virtqueue *vq) { + /* Ensure updated avail->idx is visible to host. */ mb(); @@ -428,58 +430,22 @@ int virtqueue_enable_intr(struct virtqueue *vq) { - /* - * Enable interrupts, making sure we get the latest - * index of what's already been consumed. - */ - vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) - vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx; - else - vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - - mb(); - - /* - * Additional items may have been consumed in the time between - * since we last checked and enabled interrupts above. Let our - * caller know so it processes the new entries. - */ - if (vq->vq_used_cons_idx != vq->vq_ring.used->idx) - return (1); - - return (0); + return (vq_ring_enable_interrupt(vq, 0)); } int virtqueue_postpone_intr(struct virtqueue *vq) { - uint16_t ndesc; + uint16_t ndesc, avail_idx; /* - * Postpone until at least half of the available descriptors - * have been consumed. - * - * XXX Adaptive factor? (Linux uses 3/4) + * Request the next interrupt be postponed until at least half + * of the available descriptors have been consumed. */ - ndesc = (uint16_t)(vq->vq_ring.avail->idx - vq->vq_used_cons_idx) / 2; + avail_idx = vq->vq_ring.avail->idx; + ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx) / 2; - if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) - vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; - else - vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - - mb(); - - /* - * Enough items may have already been consumed to meet our - * threshold since we last checked. Let our caller know so - * it processes the new entries. - */ - if (virtqueue_nused(vq) > ndesc) - return (1); - - return (0); + return (vq_ring_enable_interrupt(vq, ndesc)); } void @@ -752,6 +718,32 @@ vq_ring_enqueue_indirect(struct virtqueue *vq, void *cookie, } static int +vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) +{ + + /* + * Enable interrupts, making sure we get the latest index of + * what's already been consumed. + */ + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) + vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; + else + vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + + mb(); + + /* + * Enough items may have already been consumed to meet our threshold + * since we last checked. Let our caller know so it processes the new + * entries. + */ + if (virtqueue_nused(vq) > ndesc) + return (1); + + return (0); +} + +static int vq_ring_must_notify_host(struct virtqueue *vq) { uint16_t new_idx, prev_idx, event_idx; @@ -788,8 +780,8 @@ vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) VQ_RING_ASSERT_CHAIN_TERM(vq); vq->vq_free_cnt += dxp->ndescs; - dxp->ndescs--; +#ifdef INVARIANTS if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) { while (dp->flags & VRING_DESC_F_NEXT) { VQ_RING_ASSERT_VALID_IDX(vq, dp->next); @@ -797,7 +789,10 @@ vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) dxp->ndescs--; } } - VQASSERT(vq, dxp->ndescs == 0, "failed to free entire desc chain"); + VQASSERT(vq, dxp->ndescs == 1, + "failed to free entire desc chain, remaining: %d", dxp->ndescs); +#endif + dxp->ndescs = 0; /* * We must append the existing free chain, if any, to the end of diff --git a/sys/dev/virtio/virtqueue.h b/sys/dev/virtio/virtqueue.h index a84d7a1..0296b8c 100644 --- a/sys/dev/virtio/virtqueue.h +++ b/sys/dev/virtio/virtqueue.h @@ -35,11 +35,7 @@ struct sglist; /* Support for indirect buffer descriptors. */ #define VIRTIO_RING_F_INDIRECT_DESC (1 << 28) -/* The guest publishes the used index for which it expects an interrupt - * at the end of the avail ring. Host should ignore the avail->flags field. - * The host publishes the avail index for which it expects a kick - * at the end of the used ring. Guest should ignore the used->flags field. - */ +/* Support to suppress interrupt until specific index is reached. */ #define VIRTIO_RING_F_EVENT_IDX (1 << 29) /* Device callback for a virtqueue interrupt. */ diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c index 9d81f71..f3ac646 100644 --- a/sys/fs/ntfs/ntfs_subr.c +++ b/sys/fs/ntfs/ntfs_subr.c @@ -1353,174 +1353,6 @@ ntfs_filesize( } /* - * This is one of write routine. - */ -int -ntfs_writeattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - size_t init; - int error = 0; - off_t off = roff, left = rsize, towrite; - caddr_t data = rdata; - struct ntvattr *vap; - *initp = 0; - - while (left) { - error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, - ntfs_btocn(off), &vap); - if (error) - return (error); - towrite = MIN(left, ntfs_cntob(vap->va_vcnend + 1) - off); - ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n", - (u_int32_t) off, (u_int32_t) towrite, - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend)); - error = ntfs_writentvattr_plain(ntmp, ip, vap, - off - ntfs_cntob(vap->va_vcnstart), - towrite, data, &init, uio); - if (error) { - printf("ntfs_writeattr_plain: " \ - "ntfs_writentvattr_plain failed: o: %d, s: %d\n", - (u_int32_t) off, (u_int32_t) towrite); - printf("ntfs_writeattr_plain: attrib: %d - %d\n", - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend); - ntfs_ntvattrrele(vap); - break; - } - ntfs_ntvattrrele(vap); - left -= towrite; - off += towrite; - data = data + towrite; - *initp += init; - } - - return (error); -} - -/* - * This is one of write routine. - * - * ntnode should be locked. - */ -int -ntfs_writentvattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - struct ntvattr * vap, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - int error = 0; - off_t off; - int cnt; - cn_t ccn, ccl, cn, left, cl; - caddr_t data = rdata; - struct buf *bp; - size_t tocopy; - - *initp = 0; - - if ((vap->va_flag & NTFS_AF_INRUN) == 0) { - printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); - return ENOTTY; - } - - ddprintf(("ntfs_writentvattr_plain: data in run: %ld chains\n", - vap->va_vruncnt)); - - off = roff; - left = rsize; - ccl = 0; - ccn = 0; - cnt = 0; - for (; left && (cnt < vap->va_vruncnt); cnt++) { - ccn = vap->va_vruncn[cnt]; - ccl = vap->va_vruncl[cnt]; - - ddprintf(("ntfs_writentvattr_plain: " \ - "left %d, cn: 0x%x, cl: %d, off: %d\n", \ - (u_int32_t) left, (u_int32_t) ccn, \ - (u_int32_t) ccl, (u_int32_t) off)); - - if (ntfs_cntob(ccl) < off) { - off -= ntfs_cntob(ccl); - cnt++; - continue; - } - if (!ccn && ip->i_number != NTFS_BOOTINO) - continue; /* XXX */ - - ccl -= ntfs_btocn(off); - cn = ccn + ntfs_btocn(off); - off = ntfs_btocnoff(off); - - while (left && ccl) { - /* - * Always read and write single clusters at a time - - * we need to avoid requesting differently-sized - * blocks at the same disk offsets to avoid - * confusing the buffer cache. - */ - tocopy = MIN(left, ntfs_cntob(1) - off); - cl = ntfs_btocl(tocopy + off); - KASSERT(cl == 1 && tocopy <= ntfs_cntob(1), - ("single cluster limit mistake")); - ddprintf(("ntfs_writentvattr_plain: write: " \ - "cn: 0x%x cl: %d, off: %d len: %d, left: %d\n", - (u_int32_t) cn, (u_int32_t) cl, - (u_int32_t) off, (u_int32_t) tocopy, - (u_int32_t) left)); - if ((off == 0) && (tocopy == ntfs_cntob(cl))) - { - bp = getblk(ntmp->ntm_devvp, ntfs_cntobn(cn) - * ntmp->ntm_multiplier, - ntfs_cntob(cl), 0, 0, 0); - clrbuf(bp); - } else { - error = bread(ntmp->ntm_devvp, ntfs_cntobn(cn) - * ntmp->ntm_multiplier, - ntfs_cntob(cl), NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - } - if (uio) - uiomove(bp->b_data + off, tocopy, uio); - else - memcpy(bp->b_data + off, data, tocopy); - bawrite(bp); - data = data + tocopy; - *initp += tocopy; - off = 0; - left -= tocopy; - cn += cl; - ccl -= cl; - } - } - - if (left) { - printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); - error = EINVAL; - } - - return (error); -} - -/* * This is one of read routines. * * ntnode should be locked. diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h index ce46986..9ccbb42 100644 --- a/sys/fs/ntfs/ntfs_subr.h +++ b/sys/fs/ntfs/ntfs_subr.h @@ -99,8 +99,6 @@ void ntfs_ntref(struct ntnode *); void ntfs_ntrele(struct ntnode *); void ntfs_ntput(struct ntnode *); int ntfs_loadntnode( struct ntfsmount *, struct ntnode * ); -int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *, struct uio *); -int ntfs_writeattr_plain(struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *, struct uio *); void ntfs_toupper_init(void); void ntfs_toupper_destroy(void); int ntfs_toupper_use(struct mount *, struct ntfsmount *); diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index 20061cc..d664f2c 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -152,7 +152,6 @@ static int ntfs_mount(struct mount *mp) { int err = 0, error; - accmode_t accmode; struct vnode *devvp; struct nameidata ndp; struct thread *td; @@ -162,6 +161,11 @@ ntfs_mount(struct mount *mp) if (vfs_filteropt(mp->mnt_optnew, ntfs_opts)) return (EINVAL); + /* Force mount as read-only. */ + MNT_ILOCK(mp); + mp->mnt_flag |= MNT_RDONLY; + MNT_IUNLOCK(mp); + from = vfs_getopts(mp->mnt_optnew, "from", &error); if (error) return (error); @@ -173,11 +177,10 @@ ntfs_mount(struct mount *mp) if (mp->mnt_flag & MNT_UPDATE) { if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) { /* Process export requests in vfs_mount.c */ - goto success; + return (0); } else { printf("ntfs_mount(): MNT_UPDATE not supported\n"); - err = EINVAL; - goto error_1; + return (EINVAL); } } @@ -187,10 +190,8 @@ ntfs_mount(struct mount *mp) */ NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); err = namei(&ndp); - if (err) { - /* can't get devvp!*/ - goto error_1; - } + if (err) + return (err); NDFREE(&ndp, NDF_ONLY_PNBUF); devvp = ndp.ni_vp; @@ -203,10 +204,7 @@ ntfs_mount(struct mount *mp) * If mount by non-root, then verify that user has necessary * permissions on the device. */ - accmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accmode |= VWRITE; - err = VOP_ACCESS(devvp, accmode, td->td_ucred, td); + err = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); if (err) err = priv_check(td, PRIV_VFS_MOUNT_PERM); if (err) { @@ -214,52 +212,23 @@ ntfs_mount(struct mount *mp) return (err); } - if (mp->mnt_flag & MNT_UPDATE) { -#if 0 - /* - ******************** - * UPDATE - ******************** - */ - - if (devvp != ntmp->um_devvp) - err = EINVAL; /* needs translation */ - vput(devvp); - if (err) - return (err); -#endif - } else { - /* - ******************** - * NEW MOUNT - ******************** - */ - - /* - * Since this is a new mount, we want the names for - * the device and the mount point copied in. If an - * error occurs, the mountpoint is discarded by the - * upper level code. Note that vfs_mount() handles - * copying the mountpoint f_mntonname for us, so we - * don't have to do it here unless we want to set it - * to something other than "path" for some rason. - */ - /* Save "mounted from" info for mount point (NULL pad)*/ - vfs_mountedfrom(mp, from); - - err = ntfs_mountfs(devvp, mp, td); - } - if (err) { - vrele(devvp); - return (err); - } - goto success; + /* + * Since this is a new mount, we want the names for the device and + * the mount point copied in. If an error occurs, the mountpoint is + * discarded by the upper level code. Note that vfs_mount() handles + * copying the mountpoint f_mntonname for us, so we don't have to do + * it here unless we want to set it to something other than "path" + * for some rason. + */ -error_1: /* no state to back out*/ - /* XXX: missing NDFREE(&ndp, ...) */ + err = ntfs_mountfs(devvp, mp, td); + if (err == 0) { -success: + /* Save "mounted from" info for mount point. */ + vfs_mountedfrom(mp, from); + } else + vrele(devvp); return (err); } @@ -275,13 +244,12 @@ ntfs_mountfs(devvp, mp, td) struct buf *bp; struct ntfsmount *ntmp; struct cdev *dev = devvp->v_rdev; - int error, ronly, i, v; + int error, i, v; struct vnode *vp; struct g_consumer *cp; struct g_provider *pp; char *cs_ntfs, *cs_local; - ronly = (mp->mnt_flag & MNT_RDONLY) != 0; DROP_GIANT(); g_topology_lock(); @@ -296,7 +264,7 @@ ntfs_mountfs(devvp, mp, td) if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0)) error = EPERM; else - error = g_vfs_open(devvp, &cp, "ntfs", ronly ? 0 : 1); + error = g_vfs_open(devvp, &cp, "ntfs", 0); g_topology_unlock(); PICKUP_GIANT(); diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c index 8de8ca4..edcf137 100644 --- a/sys/fs/ntfs/ntfs_vnops.c +++ b/sys/fs/ntfs/ntfs_vnops.c @@ -67,7 +67,6 @@ #include <sys/unistd.h> /* for pathconf(2) constants */ static vop_read_t ntfs_read; -static vop_write_t ntfs_write; static vop_getattr_t ntfs_getattr; static vop_inactive_t ntfs_inactive; static vop_reclaim_t ntfs_reclaim; @@ -78,7 +77,6 @@ static vop_open_t ntfs_open; static vop_close_t ntfs_close; static vop_readdir_t ntfs_readdir; static vop_cachedlookup_t ntfs_lookup; -static vop_fsync_t ntfs_fsync; static vop_pathconf_t ntfs_pathconf; static vop_vptofh_t ntfs_vptofh; @@ -272,6 +270,7 @@ ntfs_strategy(ap) register struct fnode *fp = VTOF(vp); register struct ntnode *ip = FTONT(fp); struct ntfsmount *ntmp = ip->i_mp; + u_int32_t toread; int error; dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n", @@ -281,99 +280,33 @@ ntfs_strategy(ap) dprintf(("strategy: bcount: %d flags: 0x%x\n", (u_int32_t)bp->b_bcount,bp->b_flags)); - if (bp->b_iocmd == BIO_READ) { - u_int32_t toread; - - if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { - clrbuf(bp); - error = 0; - } else { - toread = MIN(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); - dprintf(("ntfs_strategy: toread: %d, fsize: %d\n", - toread,(u_int32_t)fp->f_size)); - - error = ntfs_readattr(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno), - toread, bp->b_data, NULL); - - if (error) { - printf("ntfs_strategy: ntfs_readattr failed\n"); - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - } + KASSERT(bp->b_iocmd == BIO_READ, ("Invalid buffer\n")); - bzero(bp->b_data + toread, bp->b_bcount - toread); - } + if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { + clrbuf(bp); + error = 0; } else { - size_t tmp; - u_int32_t towrite; + toread = MIN(bp->b_bcount, + fp->f_size-ntfs_cntob(bp->b_blkno)); + dprintf(("ntfs_strategy: toread: %d, fsize: %d\n", + toread,(u_int32_t)fp->f_size)); - if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) { - printf("ntfs_strategy: CAN'T EXTEND FILE\n"); - bp->b_error = error = EFBIG; + error = ntfs_readattr(ntmp, ip, fp->f_attrtype, + fp->f_attrname, ntfs_cntob(bp->b_blkno), + toread, bp->b_data, NULL); + + if (error) { + printf("ntfs_strategy: ntfs_readattr failed\n"); + bp->b_error = error; bp->b_ioflags |= BIO_ERROR; - } else { - towrite = MIN(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); - dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n", - towrite,(u_int32_t)fp->f_size)); - - error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite, - bp->b_data, &tmp, NULL); - - if (error) { - printf("ntfs_strategy: ntfs_writeattr fail\n"); - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - } } + + bzero(bp->b_data + toread, bp->b_bcount - toread); } bufdone(bp); return (0); } -static int -ntfs_write(ap) - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct uio *uio = ap->a_uio; - struct ntfsmount *ntmp = ip->i_mp; - u_int64_t towrite; - size_t written; - int error; - - dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size)); - - if (uio->uio_resid + uio->uio_offset > fp->f_size) { - printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n"); - return (EFBIG); - } - - towrite = MIN(uio->uio_resid, fp->f_size - uio->uio_offset); - - dprintf((", towrite: %d\n",(u_int32_t)towrite)); - - error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, - fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio); -#ifdef NTFS_DEBUG - if (error) - printf("ntfs_write: ntfs_writeattr failed: %d\n", error); -#endif - - return (error); -} - int ntfs_access(ap) struct vop_access_args /* { @@ -390,7 +323,7 @@ ntfs_access(ap) dprintf(("ntfs_access: %d\n",ip->i_number)); /* - * Disallow write attempts on read-only filesystems; + * Disallow write attempts as we assume read-only filesystems; * unless the file is a socket, fifo, or a block or * character device resident on the filesystem. */ @@ -399,8 +332,8 @@ ntfs_access(ap) case VDIR: case VLNK: case VREG: - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); + return (EROFS); + default: break; } } @@ -630,7 +563,6 @@ ntfs_lookup(ap) return (error); if ((cnp->cn_flags & ISLASTCN) && - (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); @@ -679,24 +611,6 @@ ntfs_lookup(ap) } /* - * Flush the blocks of a file to disk. - * - * This function is worthless for vnodes that represent directories. Maybe we - * could just do a sync if they try an fsync on a directory file. - */ -static int -ntfs_fsync(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct thread *a_td; - } */ *ap; -{ - return (0); -} - -/* * Return POSIX pathconf information applicable to NTFS filesystem */ int @@ -756,7 +670,6 @@ struct vop_vector ntfs_vnodeops = { .vop_bmap = ntfs_bmap, .vop_cachedlookup = ntfs_lookup, .vop_close = ntfs_close, - .vop_fsync = ntfs_fsync, .vop_getattr = ntfs_getattr, .vop_inactive = ntfs_inactive, .vop_lookup = vfs_cache_lookup, @@ -766,6 +679,5 @@ struct vop_vector ntfs_vnodeops = { .vop_readdir = ntfs_readdir, .vop_reclaim = ntfs_reclaim, .vop_strategy = ntfs_strategy, - .vop_write = ntfs_write, .vop_vptofh = ntfs_vptofh, }; diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index de105f0..40c8c46 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/memrange.h> #include <sys/msgbuf.h> #include <sys/mutex.h> #include <sys/pcpu.h> @@ -247,6 +248,8 @@ struct pcpu __pcpu[MAXCPU]; struct mtx icu_lock; +struct mem_range_softc mem_range_softc; + static void cpu_startup(dummy) void *dummy; diff --git a/sys/i386/i386/mem.c b/sys/i386/i386/mem.c index dbbe242f..9c83f47 100644 --- a/sys/i386/i386/mem.c +++ b/sys/i386/i386/mem.c @@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$"); */ MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors"); -struct mem_range_softc mem_range_softc; - static struct sx memsxlock; SX_SYSINIT(memsxlockinit, &memsxlock, "/dev/mem lock"); diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index 7116f76..62d268d 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -97,6 +97,13 @@ clflush(u_long addr) } static __inline void +clts(void) +{ + + __asm __volatile("clts"); +} + +static __inline void disable_intr(void) { #ifdef XEN @@ -688,6 +695,9 @@ intr_restore(register_t eflags) int breakpoint(void); u_int bsfl(u_int mask); u_int bsrl(u_int mask); +void clflush(u_long addr); +void clts(void); +void cpuid_count(u_int ax, u_int cx, u_int *p); void disable_intr(void); void do_cpuid(u_int ax, u_int *p); void enable_intr(void); diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 0da580f..50c812c 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -100,15 +100,6 @@ __FBSDID("$FreeBSD$"); #define fxrstor(addr) __asm __volatile("fxrstor %0" : : "m" (*(addr))) #define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr))) #endif -#ifdef XEN -#define start_emulating() (HYPERVISOR_fpu_taskswitch(1)) -#define stop_emulating() (HYPERVISOR_fpu_taskswitch(0)) -#else -#define start_emulating() __asm __volatile( \ - "smsw %%ax; orb %0,%%al; lmsw %%ax" \ - : : "n" (CR0_TS) : "ax") -#define stop_emulating() __asm __volatile("clts") -#endif #else /* !(__GNUCLIKE_ASM && !lint) */ void fldcw(u_short cw); @@ -123,11 +114,17 @@ void frstor(caddr_t addr); void fxsave(caddr_t addr); void fxrstor(caddr_t addr); #endif -void start_emulating(void); -void stop_emulating(void); #endif /* __GNUCLIKE_ASM && !lint */ +#ifdef XEN +#define start_emulating() (HYPERVISOR_fpu_taskswitch(1)) +#define stop_emulating() (HYPERVISOR_fpu_taskswitch(0)) +#else +#define start_emulating() load_cr0(rcr0() | CR0_TS) +#define stop_emulating() clts() +#endif + #ifdef CPU_ENABLE_SSE #define GET_FPU_CW(thread) \ (cpu_fxsr ? \ diff --git a/sys/kern/dtio_kdtrace.c b/sys/kern/dtio_kdtrace.c new file mode 100644 index 0000000..cfac370 --- /dev/null +++ b/sys/kern/dtio_kdtrace.c @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 2012 Advanced Computing Technologies LLC + * Written by George Neville-Neil gnn@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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> + +#include <sys/dtrace.h> +#include "../sys/dtrace_bsd.h" + + +static int dtio_unload(void); +static void dtio_getargdesc(void *, dtrace_id_t, void *, + dtrace_argdesc_t *); +static void dtio_provide(void *, dtrace_probedesc_t *); +static void dtio_destroy(void *, dtrace_id_t, void *); +static void dtio_enable(void *, dtrace_id_t, void *); +static void dtio_disable(void *, dtrace_id_t, void *); +static void dtio_load(void *); + +static dtrace_pattr_t dtio_attr = { +{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, +}; + +static char *genunix = "genunix"; + +/* + * Name strings. + */ +static char *dtio_start_str = "start"; +static char *dtio_done_str = "done"; +static char *dtio_wait_start_str = "wait-start"; +static char *dtio_wait_done_str = "wait-done"; + +static dtrace_pops_t dtio_pops = { + dtio_provide, + NULL, + dtio_enable, + dtio_disable, + NULL, + NULL, + dtio_getargdesc, + NULL, + NULL, + dtio_destroy +}; + +static dtrace_provider_id_t dtio_id; + +extern uint32_t dtio_start_id; +extern uint32_t dtio_done_id; +extern uint32_t dtio_wait_start_id; +extern uint32_t dtio_wait_done_id; + +static void +dtio_getargdesc(void *arg, dtrace_id_t id, void *parg, + dtrace_argdesc_t *desc) +{ + const char *p = NULL; + + switch (desc->dtargd_ndx) { + case 0: + p = "struct bio *"; + break; + case 1: + p = "struct devstat *"; + break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + } + + if (p != NULL) + strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native)); +} + +static void +dtio_provide(void *arg, dtrace_probedesc_t *desc) +{ + if (desc != NULL) + return; + + if (dtrace_probe_lookup(dtio_id, genunix, NULL, + dtio_start_str) == 0) { + dtio_start_id = dtrace_probe_create(dtio_id, genunix, NULL, + dtio_start_str, 0, NULL); + } + if (dtrace_probe_lookup(dtio_id, genunix, NULL, dtio_done_str) == 0) { + dtio_done_id = dtrace_probe_create(dtio_id, genunix, NULL, + dtio_done_str, 0, NULL); + } + if (dtrace_probe_lookup(dtio_id, genunix, NULL, + dtio_wait_start_str) == 0) { + dtio_wait_start_id = dtrace_probe_create(dtio_id, genunix, + NULL, + dtio_wait_start_str, + 0, NULL); + } + if (dtrace_probe_lookup(dtio_id, genunix, NULL, + dtio_wait_done_str) == 0) { + dtio_wait_done_id = dtrace_probe_create(dtio_id, genunix, NULL, + dtio_wait_done_str, 0, NULL); + } + +} + +static void +dtio_destroy(void *arg, dtrace_id_t id, void *parg) +{ +} + +static void +dtio_enable(void *arg, dtrace_id_t id, void *parg) +{ + if (id == dtio_start_id) + dtrace_io_start_probe = + (dtrace_io_start_probe_func_t)dtrace_probe; + else if (id == dtio_done_id) + dtrace_io_done_probe = + (dtrace_io_done_probe_func_t)dtrace_probe; + else if (id == dtio_wait_start_id) + dtrace_io_wait_start_probe = + (dtrace_io_wait_start_probe_func_t)dtrace_probe; + else if (id == dtio_wait_done_id) + dtrace_io_wait_done_probe = + (dtrace_io_wait_done_probe_func_t)dtrace_probe; + else + printf("dtrace io provider: unknown ID\n"); + +} + +static void +dtio_disable(void *arg, dtrace_id_t id, void *parg) +{ + if (id == dtio_start_id) + dtrace_io_start_probe = NULL; + else if (id == dtio_done_id) + dtrace_io_done_probe = NULL; + else if (id == dtio_wait_start_id) + dtrace_io_wait_start_probe = NULL; + else if (id == dtio_wait_done_id) + dtrace_io_wait_done_probe = NULL; + else + printf("dtrace io provider: unknown ID\n"); + +} + +static void +dtio_load(void *dummy) +{ + if (dtrace_register("io", &dtio_attr, DTRACE_PRIV_USER, NULL, + &dtio_pops, NULL, &dtio_id) != 0) + return; +} + + +static int +dtio_unload() +{ + dtrace_io_start_probe = NULL; + dtrace_io_done_probe = NULL; + dtrace_io_wait_start_probe = NULL; + dtrace_io_wait_done_probe = NULL; + + return (dtrace_unregister(dtio_id)); +} + +static int +dtio_modevent(module_t mod __unused, int type, void *data __unused) +{ + int error = 0; + + switch (type) { + case MOD_LOAD: + break; + + case MOD_UNLOAD: + break; + + case MOD_SHUTDOWN: + break; + + default: + error = EOPNOTSUPP; + break; + } + + return (error); +} + +SYSINIT(dtio_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, + dtio_load, NULL); +SYSUNINIT(dtio_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, + dtio_unload, NULL); + +DEV_MODULE(dtio, dtio_modevent, NULL); +MODULE_VERSION(dtio, 1); +MODULE_DEPEND(dtio, dtrace, 1, 1, 1); +MODULE_DEPEND(dtio, opensolaris, 1, 1, 1); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index a4b7580..f8e3f3d 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2275,8 +2275,8 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, struct file *fp; #ifdef CAPABILITIES struct file *fp_fromcap; - int error; #endif + int error; *fpp = NULL; if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) @@ -2315,7 +2315,7 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, else error = cap_funwrap_mmap(fp, needrights, maxprotp, &fp_fromcap); - if (error) { + if (error != 0) { fdrop(fp, td); return (error); } @@ -2341,13 +2341,29 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, /* * FREAD and FWRITE failure return EBADF as per POSIX. */ - if ((flags == FREAD && (fp->f_flag & FREAD) == 0) || - (flags == FWRITE && (fp->f_flag & FWRITE) == 0) || - (flags == (FREAD | FEXEC) && - (((fp->f_flag & flags) == 0) || ((fp->f_flag & FWRITE) != 0)))) { + error = 0; + switch (flags) { + case FREAD: + case FWRITE: + if ((fp->f_flag & flags) == 0) + error = EBADF; + break; + case FEXEC: + if ((fp->f_flag & (FREAD | FEXEC)) == 0 || + ((fp->f_flag & FWRITE) != 0)) + error = EBADF; + break; + case 0: + break; + default: + KASSERT(0, ("wrong flags")); + } + + if (error != 0) { fdrop(fp, td); - return (EBADF); + return (error); } + *fpp = fp; return (0); } @@ -2448,7 +2464,7 @@ int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp) { - return (_fgetvp(td, fd, FREAD | FEXEC, rights, NULL, vpp)); + return (_fgetvp(td, fd, FEXEC, rights, NULL, vpp)); } #ifdef notyet diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 52a0c40..2685a8b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2436,9 +2436,10 @@ ptracestop(struct thread *td, int sig) } stopme: thread_suspend_switch(td); - if (!(p->p_flag & P_TRACED)) { + if (p->p_xthread == td) + p->p_xthread = NULL; + if (!(p->p_flag & P_TRACED)) break; - } if (td->td_dbgflags & TDB_SUSPEND) { if (p->p_flag & P_SINGLE_EXIT) break; diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index bbbfdbf..c44ef27 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -29,6 +29,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_kdtrace.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -44,6 +46,58 @@ __FBSDID("$FreeBSD$"); #include <machine/atomic.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +dtrace_io_start_probe_func_t dtrace_io_start_probe; +dtrace_io_done_probe_func_t dtrace_io_done_probe; +dtrace_io_wait_start_probe_func_t dtrace_io_wait_start_probe; +dtrace_io_wait_done_probe_func_t dtrace_io_wait_done_probe; + +uint32_t dtio_start_id; +uint32_t dtio_done_id; +uint32_t dtio_wait_start_id; +uint32_t dtio_wait_done_id; + +#define DTRACE_DEVSTAT_START() \ + if (dtrace_io_start_probe != NULL) \ + (*dtrace_io_start_probe)(dtio_start_id, NULL, ds); + +#define DTRACE_DEVSTAT_BIO_START() \ + if (dtrace_io_start_probe != NULL) \ + (*dtrace_io_start_probe)(dtio_start_id, bp, ds); + +#define DTRACE_DEVSTAT_DONE() \ + if (dtrace_io_done_probe != NULL) \ + (*dtrace_io_done_probe)(dtio_done_id, NULL, ds); + +#define DTRACE_DEVSTAT_BIO_DONE() \ + if (dtrace_io_done_probe != NULL) \ + (*dtrace_io_done_probe)(dtio_done_id, bp, ds); + +#define DTRACE_DEVSTAT_WAIT_START() \ + if (dtrace_io_wait_start_probe != NULL) \ + (*dtrace_io_wait_start_probe)(dtio_wait_start_id, NULL, ds); + +#define DTRACE_DEVSTAT_WAIT_DONE() \ + if (dtrace_io_wait_done_probe != NULL) \ + (*dtrace_io_wait_done_probe)(dtio_wait_done_id, NULL, ds); + +#else /* ! KDTRACE_HOOKS */ + +#define DTRACE_DEVSTAT_START() + +#define DTRACE_DEVSTAT_BIO_START() + +#define DTRACE_DEVSTAT_DONE() + +#define DTRACE_DEVSTAT_BIO_DONE() + +#define DTRACE_DEVSTAT_WAIT_START() + +#define DTRACE_DEVSTAT_WAIT_DONE() +#endif /* KDTRACE_HOOKS */ + static int devstat_num_devs; static long devstat_generation = 1; static int devstat_version = DEVSTAT_VERSION; @@ -227,6 +281,7 @@ devstat_start_transaction(struct devstat *ds, struct bintime *now) } ds->start_count++; atomic_add_rel_int(&ds->sequence0, 1); + DTRACE_DEVSTAT_START(); } void @@ -241,6 +296,7 @@ devstat_start_transaction_bio(struct devstat *ds, struct bio *bp) binuptime(&bp->bio_t0); devstat_start_transaction(ds, &bp->bio_t0); + DTRACE_DEVSTAT_BIO_START(); } /* @@ -312,6 +368,7 @@ devstat_end_transaction(struct devstat *ds, uint32_t bytes, ds->end_count++; atomic_add_rel_int(&ds->sequence0, 1); + DTRACE_DEVSTAT_DONE(); } void @@ -334,6 +391,7 @@ devstat_end_transaction_bio(struct devstat *ds, struct bio *bp) devstat_end_transaction(ds, bp->bio_bcount - bp->bio_resid, DEVSTAT_TAG_SIMPLE, flg, NULL, &bp->bio_t0); + DTRACE_DEVSTAT_BIO_DONE(); } /* diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 9c6c204..10209ec 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -635,7 +635,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) struct iovec iov; struct uio uio; struct proc *curp, *p, *pp; - struct thread *td2 = NULL; + struct thread *td2 = NULL, *td3; struct ptrace_io_desc *piod = NULL; struct ptrace_lwpinfo *pl; int error, write, tmp, num; @@ -953,10 +953,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) td2->td_xsig = data; if (req == PT_DETACH) { - struct thread *td3; - FOREACH_THREAD_IN_PROC(p, td3) { + FOREACH_THREAD_IN_PROC(p, td3) td3->td_dbgflags &= ~TDB_SUSPEND; - } } /* * unsuspend all threads, to not let a thread run, @@ -967,6 +965,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED); thread_unsuspend(p); PROC_SUNLOCK(p); + if (req == PT_ATTACH) + kern_psignal(p, data); } else { if (data) kern_psignal(p, data); diff --git a/sys/mips/nlm/board.c b/sys/mips/nlm/board.c index b4b0439..c6fd59d 100644 --- a/sys/mips/nlm/board.c +++ b/sys/mips/nlm/board.c @@ -362,6 +362,8 @@ nlm_print_processor_info(void) revstr = "A2"; break; case 3: revstr = "B0"; break; + case 4: + revstr = "B1"; break; default: revstr = "??"; break; } diff --git a/sys/mips/nlm/dev/net/mdio.c b/sys/mips/nlm/dev/net/mdio.c index 362312f..ed2abe4 100644 --- a/sys/mips/nlm/dev/net/mdio.c +++ b/sys/mips/nlm/dev/net/mdio.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include <mips/nlm/hal/nae.h> #include <mips/nlm/hal/mdio.h> +#include <mips/nlm/xlp.h> + /* Internal MDIO READ/WRITE Routines */ int nlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block, @@ -176,12 +178,7 @@ nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, int intf_type, int phyaddr, int regidx) { uint32_t mdio_ld_cmd; - uint32_t val; - - val = EXT_G_MDIO_CMD_SP | - (phyaddr << EXT_G_MDIO_PHYADDR_POS) | - (regidx << EXT_G_MDIO_REGADDR_POS) | - EXT_G_MDIO_DIV; + uint32_t ctrlval; mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4))); @@ -195,14 +192,22 @@ nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, EXT_G_MDIO_STAT_MBSY); } - nlm_write_nae_reg(nae_base, + ctrlval = EXT_G_MDIO_CMD_SP | + (phyaddr << EXT_G_MDIO_PHYADDR_POS) | + (regidx << EXT_G_MDIO_REGADDR_POS); + if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) + ctrlval |= EXT_G_MDIO_DIV; + else + ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; + + nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), - val); + ctrlval); nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), - val | (1<<18)); - + ctrlval | (1<<18)); + DELAY(1000); /* poll master busy bit until it is not busy */ while(nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & @@ -210,7 +215,7 @@ nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), - val); + ctrlval); /* Read the data back */ return nlm_read_nae_reg(nae_base, @@ -236,11 +241,6 @@ nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, uint32_t mdio_ld_cmd; uint32_t ctrlval; - ctrlval = EXT_G_MDIO_CMD_SP | - (phyaddr << EXT_G_MDIO_PHYADDR_POS) | - (regidx << EXT_G_MDIO_REGADDR_POS) | - EXT_G_MDIO_DIV; - mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4))); if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { @@ -258,6 +258,14 @@ nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)), val); + ctrlval = EXT_G_MDIO_CMD_SP | + (phyaddr << EXT_G_MDIO_PHYADDR_POS) | + (regidx << EXT_G_MDIO_REGADDR_POS); + if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) + ctrlval |= EXT_G_MDIO_DIV; + else + ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; + nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), ctrlval); @@ -265,6 +273,7 @@ nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), ctrlval | EXT_G_MDIO_CMD_LCD); + DELAY(1000); /* poll master busy bit until it is not busy */ while(nlm_read_nae_reg(nae_base, @@ -291,11 +300,17 @@ int nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block, int intf_type) { + uint32_t ctrlval; + + if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) + ctrlval = EXT_G_MDIO_DIV; + else + ctrlval = EXT_G_MDIO_DIV_WITH_HW_DIV64; + nlm_write_nae_reg(nae_base, - NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), - EXT_G_MDIO_MMRST | EXT_G_MDIO_DIV); + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), + EXT_G_MDIO_MMRST | ctrlval); nlm_write_nae_reg(nae_base, - NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), - EXT_G_MDIO_DIV); + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval); return (0); } diff --git a/sys/mips/nlm/hal/mdio.h b/sys/mips/nlm/hal/mdio.h index 6288391..a1e720b 100644 --- a/sys/mips/nlm/hal/mdio.h +++ b/sys/mips/nlm/hal/mdio.h @@ -81,6 +81,7 @@ #define EXT_G_MDIO_CMD_SC 0x00080000 #define EXT_G_MDIO_MMRST 0x00100000 #define EXT_G_MDIO_DIV 0x0000001E +#define EXT_G_MDIO_DIV_WITH_HW_DIV64 0x00000010 #define EXT_G_MDIO_RD_STAT_MASK 0x0000FFFF #define EXT_G_MDIO_STAT_LFV 0x00010000 diff --git a/sys/mips/nlm/xlp.h b/sys/mips/nlm/xlp.h index 3414aed..832c951 100644 --- a/sys/mips/nlm/xlp.h +++ b/sys/mips/nlm/xlp.h @@ -57,6 +57,7 @@ #define XLP_REVISION_A1 0x01 #define XLP_REVISION_A2 0x02 #define XLP_REVISION_B0 0x03 +#define XLP_REVISION_B1 0x04 #ifndef LOCORE /* @@ -87,6 +88,16 @@ static __inline int nlm_is_xlp3xx(void) return (nlm_processor_id() == CHIP_PROCESSOR_ID_XLP_3XX); } +static __inline int nlm_is_xlp3xx_ax(void) +{ + uint32_t procid = mips_rd_prid(); + int prid = (procid >> 8) & 0xff; + int rev = procid & 0xff; + + return (prid == CHIP_PROCESSOR_ID_XLP_3XX && + rev < XLP_REVISION_B0); +} + static __inline int nlm_is_xlp4xx(void) { int prid = nlm_processor_id(); @@ -116,5 +127,17 @@ static __inline int nlm_is_xlp8xx_ax(void) (rev < XLP_REVISION_B0)); } +static __inline int nlm_is_xlp8xx_b0(void) +{ + uint32_t procid = mips_rd_prid(); + int prid = (procid >> 8) & 0xff; + int rev = procid & 0xff; + + return ((prid == CHIP_PROCESSOR_ID_XLP_8XX || + prid == CHIP_PROCESSOR_ID_XLP_432 || + prid == CHIP_PROCESSOR_ID_XLP_416) && + rev == XLP_REVISION_B0); +} + #endif /* LOCORE */ #endif /* __NLM_XLP_H__ */ diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c index bd4fd4c..0610a15 100644 --- a/sys/mips/nlm/xlp_pci.c +++ b/sys/mips/nlm/xlp_pci.c @@ -507,13 +507,13 @@ xlp_pcib_hardware_swap_enable(int node, int link) nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_BASE, bar); bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_LIMIT0 + link); - nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar); + nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar | 0xFFF); bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_BASE0 + link); nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_BASE, bar); bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link); - nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar); + nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF); } static int diff --git a/sys/modules/acpi/acpi/Makefile b/sys/modules/acpi/acpi/Makefile index 6da186f..973d5d1 100644 --- a/sys/modules/acpi/acpi/Makefile +++ b/sys/modules/acpi/acpi/Makefile @@ -54,11 +54,11 @@ SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c pstree.c psutils.c SRCS+= pswalk.c psxface.c SRCS+= rsaddr.c rscalc.c rscreate.c rsdump.c rsinfo.c rsio.c rsirq.c rslist.c SRCS+= rsmemory.c rsmisc.c rsserial.c rsutils.c rsxface.c -SRCS+= tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c tbxfroot.c +SRCS+= tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c tbxfload.c tbxfroot.c SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c utdecode.c -SRCS+= utdelete.c uteval.c utglobal.c utids.c utinit.c utlock.c utmath.c -SRCS+= utmisc.c utmutex.c utobject.c utosi.c utresrc.c utstate.c utxface.c -SRCS+= utxferror.c +SRCS+= utdelete.c uteval.c utexcep.c utglobal.c utids.c utinit.c utlock.c +SRCS+= utmath.c utmisc.c utmutex.c utobject.c utosi.c utresrc.c utstate.c +SRCS+= utxface.c utxferror.c #SRCS+= utxfmutex.c # OSPM layer and core hardware drivers @@ -86,6 +86,9 @@ SRCS+= opt_kstack_pages.h opt_nfs.h opt_apic.h opt_compat.h opt_hwpmc_hooks.h .if KTR CFLAGS+=-DKTR .endif +.if SMP +CFLAGS+=-DSMP +.endif .if ACPI_MAX_TASKS CFLAGS+=-DACPI_MAX_TASKS=${ACPI_MAX_TASKS} .endif @@ -113,14 +116,6 @@ ASM_CFLAGS= -x assembler-with-cpp -DLOCORE ${CFLAGS} NORMAL_S= ${CC} -c ${ASM_CFLAGS} ${WERROR} ${.IMPSRC} NM?= nm -.if ${MACHINE_CPUARCH} == "amd64" -.if !defined(KERNBUILDDIR) -CFLAGS+=-DSMP -.endif -SRCS+= acpi_switch.S -acpi_switch.o: acpi_switch.S - ${NORMAL_S} -.endif acpi_wakecode.o: acpi_wakecode.S assym.s ${NORMAL_S} acpi_wakecode.bin: acpi_wakecode.o diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile index f8f3785..02423e9 100644 --- a/sys/modules/dtrace/Makefile +++ b/sys/modules/dtrace/Makefile @@ -9,6 +9,7 @@ SUBDIR= dtmalloc \ dtrace \ dtraceall \ dtrace_test \ + dtio \ prototype \ sdt \ systrace diff --git a/sys/modules/dtrace/dtio/Makefile b/sys/modules/dtrace/dtio/Makefile new file mode 100644 index 0000000..ff68ce4 --- /dev/null +++ b/sys/modules/dtrace/dtio/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../kern + +KMOD= dtio +SRCS= dtio_kdtrace.c \ + vnode_if.h + +CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \ + -I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/common \ + -I${.CURDIR}/../../.. + +.include <bsd.kmod.mk> diff --git a/sys/modules/dtrace/dtraceall/dtraceall.c b/sys/modules/dtrace/dtraceall/dtraceall.c index 61896bf..9d7a23d 100644 --- a/sys/modules/dtrace/dtraceall/dtraceall.c +++ b/sys/modules/dtrace/dtraceall/dtraceall.c @@ -65,6 +65,7 @@ MODULE_VERSION(dtraceall, 1); MODULE_DEPEND(dtraceall, cyclic, 1, 1, 1); MODULE_DEPEND(dtraceall, opensolaris, 1, 1, 1); MODULE_DEPEND(dtraceall, dtrace, 1, 1, 1); +MODULE_DEPEND(dtraceall, dtio, 1, 1, 1); MODULE_DEPEND(dtraceall, dtmalloc, 1, 1, 1); MODULE_DEPEND(dtraceall, dtnfscl, 1, 1, 1); MODULE_DEPEND(dtraceall, dtnfsclient, 1, 1, 1); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b35559b..7f44bc2 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1811,8 +1811,10 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m) m->m_flags &= ~M_VLANTAG; } - if (err == 0) - dst_ifp->if_transmit(dst_ifp, m); + if ((err = dst_ifp->if_transmit(dst_ifp, m))) { + m_freem(m0); + break; + } } if (err == 0) { diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index fe22ed7..2a67e18 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -904,39 +904,41 @@ epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) if_link_state_change(oifp, LINK_STATE_DOWN); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; oifp->if_drv_flags &= ~IFF_DRV_RUNNING; + + /* + * Get rid of our second half. As the other of the two + * interfaces may reside in a different vnet, we need to + * switch before freeing them. + */ + CURVNET_SET_QUIET(oifp->if_vnet); ether_ifdetach(oifp); - ether_ifdetach(ifp); /* * Wait for all packets to be dispatched to if_input. - * The numbers can only go down as the interfaces are + * The numbers can only go down as the interface is * detached so there is no need to use atomics. */ - DPRINTF("sca refcnt=%u scb refcnt=%u\n", sca->refcount, scb->refcount); - EPAIR_REFCOUNT_ASSERT(sca->refcount == 1 && scb->refcount == 1, - ("%s: ifp=%p sca->refcount!=1: %d || ifp=%p scb->refcount!=1: %d", - __func__, ifp, sca->refcount, oifp, scb->refcount)); - - /* - * Get rid of our second half. - */ + DPRINTF("scb refcnt=%u\n", scb->refcount); + EPAIR_REFCOUNT_ASSERT(scb->refcount == 1, + ("%s: ifp=%p scb->refcount!=1: %d", __func__, oifp, scb->refcount)); oifp->if_softc = NULL; error = if_clone_destroyif(ifc, oifp); if (error) panic("%s: if_clone_destroyif() for our 2nd iface failed: %d", __func__, error); + if_free(oifp); + ifmedia_removeall(&scb->media); + free(scb, M_EPAIR); + CURVNET_RESTORE(); + ether_ifdetach(ifp); /* - * Finish cleaning up. Free them and release the unit. - * As the other of the two interfaces my reside in a different vnet, - * we need to switch before freeing them. + * Wait for all packets to be dispatched to if_input. */ - CURVNET_SET_QUIET(oifp->if_vnet); - if_free(oifp); - CURVNET_RESTORE(); + DPRINTF("sca refcnt=%u\n", sca->refcount); + EPAIR_REFCOUNT_ASSERT(sca->refcount == 1, + ("%s: ifp=%p sca->refcount!=1: %d", __func__, ifp, sca->refcount)); if_free(ifp); ifmedia_removeall(&sca->media); - ifmedia_removeall(&scb->media); - free(scb, M_EPAIR); free(sca, M_EPAIR); ifc_free_unit(ifc, unit); diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c index b9ed6b3..14eb2a2 100644 --- a/sys/netinet/ipfw/ip_fw_log.c +++ b/sys/netinet/ipfw/ip_fw_log.c @@ -44,8 +44,11 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/sysctl.h> #include <sys/syslog.h> +#include <sys/lock.h> +#include <sys/rwlock.h> #include <net/ethernet.h> /* for ETHERTYPE_IP */ #include <net/if.h> +#include <net/if_clone.h> #include <net/vnet.h> #include <net/if_types.h> /* for IFT_ETHER */ #include <net/bpf.h> /* for BPF */ @@ -90,6 +93,15 @@ ipfw_log_bpf(int onoff) } #else /* !WITHOUT_BPF */ static struct ifnet *log_if; /* hook to attach to bpf */ +static struct rwlock log_if_lock; +#define LOGIF_LOCK_INIT(x) rw_init(&log_if_lock, "ipfw log_if lock") +#define LOGIF_LOCK_DESTROY(x) rw_destroy(&log_if_lock) +#define LOGIF_RLOCK(x) rw_rlock(&log_if_lock) +#define LOGIF_RUNLOCK(x) rw_runlock(&log_if_lock) +#define LOGIF_WLOCK(x) rw_wlock(&log_if_lock) +#define LOGIF_WUNLOCK(x) rw_wunlock(&log_if_lock) + +#define IPFWNAME "ipfw" /* we use this dummy function for all ifnet callbacks */ static int @@ -116,37 +128,105 @@ ipfw_log_start(struct ifnet* ifp) static const u_char ipfwbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +static int +ipfw_log_clone_match(struct if_clone *ifc, const char *name) +{ + + return (strncmp(name, IPFWNAME, sizeof(IPFWNAME) - 1) == 0); +} + +static int +ipfw_log_clone_create(struct if_clone *ifc, char *name, size_t len, + caddr_t params) +{ + int error; + int unit; + struct ifnet *ifp; + + error = ifc_name2unit(name, &unit); + if (error) + return (error); + + error = ifc_alloc_unit(ifc, &unit); + if (error) + return (error); + + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) { + ifc_free_unit(ifc, unit); + return (ENOSPC); + } + ifp->if_dname = IPFWNAME; + ifp->if_dunit = unit; + snprintf(ifp->if_xname, IFNAMSIZ, "%s%d", IPFWNAME, unit); + strlcpy(name, ifp->if_xname, len); + ifp->if_mtu = 65536; + ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_init = (void *)log_dummy; + ifp->if_ioctl = log_dummy; + ifp->if_start = ipfw_log_start; + ifp->if_output = ipfw_log_output; + ifp->if_addrlen = 6; + ifp->if_hdrlen = 14; + ifp->if_broadcastaddr = ipfwbroadcastaddr; + ifp->if_baudrate = IF_Mbps(10); + + LOGIF_WLOCK(); + if (log_if == NULL) + log_if = ifp; + else { + LOGIF_WUNLOCK(); + if_free(ifp); + ifc_free_unit(ifc, unit); + return (EEXIST); + } + LOGIF_WUNLOCK(); + if_attach(ifp); + bpfattach(ifp, DLT_EN10MB, 14); + + return (0); +} + +static int +ipfw_log_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) +{ + int unit; + + if (ifp == NULL) + return (0); + + LOGIF_WLOCK(); + if (log_if != NULL && ifp == log_if) + log_if = NULL; + else { + LOGIF_WUNLOCK(); + return (EINVAL); + } + LOGIF_WUNLOCK(); + + unit = ifp->if_dunit; + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); + ifc_free_unit(ifc, unit); + + return (0); +} + +static struct if_clone ipfw_log_cloner = IFC_CLONE_INITIALIZER( + IPFWNAME, NULL, IF_MAXUNIT, + NULL, ipfw_log_clone_match, ipfw_log_clone_create, ipfw_log_clone_destroy); + void ipfw_log_bpf(int onoff) { - struct ifnet *ifp; if (onoff) { - if (log_if) - return; - ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) - return; - if_initname(ifp, "ipfw", 0); - ifp->if_mtu = 65536; - ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = (void *)log_dummy; - ifp->if_ioctl = log_dummy; - ifp->if_start = ipfw_log_start; - ifp->if_output = ipfw_log_output; - ifp->if_addrlen = 6; - ifp->if_hdrlen = 14; - if_attach(ifp); - ifp->if_broadcastaddr = ipfwbroadcastaddr; - ifp->if_baudrate = IF_Mbps(10); - bpfattach(ifp, DLT_EN10MB, 14); - log_if = ifp; + LOGIF_LOCK_INIT(); + if_clone_attach(&ipfw_log_cloner); } else { - if (log_if) { - ether_ifdetach(log_if); - if_free(log_if); - } - log_if = NULL; + if_clone_detach(&ipfw_log_cloner); + LOGIF_LOCK_DESTROY(); } } #endif /* !WITHOUT_BPF */ @@ -166,9 +246,11 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, if (V_fw_verbose == 0) { #ifndef WITHOUT_BPF - - if (log_if == NULL || log_if->if_bpf == NULL) + LOGIF_RLOCK(); + if (log_if == NULL || log_if->if_bpf == NULL) { + LOGIF_RUNLOCK(); return; + } if (args->eh) /* layer2, use orig hdr */ BPF_MTAP2(log_if, args->eh, ETHER_HDR_LEN, m); @@ -177,6 +259,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, * more info in the header. */ BPF_MTAP2(log_if, "DDDDDDSSSSSS\x08\x00", ETHER_HDR_LEN, m); + LOGIF_RUNLOCK(); #endif /* !WITHOUT_BPF */ return; } diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 41bc1c5..10e3959 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5520,6 +5520,7 @@ do_a_abort: case AF_INET6: { stc.addr_type = SCTP_IPV6_ADDRESS; + memcpy(&stc.address, &src6->sin6_addr, sizeof(struct in6_addr)); stc.scope_id = in6_getscope(&src6->sin6_addr); if (sctp_is_address_on_local_host(src, vrf_id)) { stc.loopback_scope = 1; diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index c44e704..eb0bd44 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -79,7 +79,7 @@ struct nd_ifinfo { #define ND6_IFF_PERFORMNUD 0x1 #define ND6_IFF_ACCEPT_RTADV 0x2 -#define ND6_IFF_PREFER_SOURCE 0x4 /* XXX: not related to ND. */ +#define ND6_IFF_PREFER_SOURCE 0x4 /* Not used in FreeBSD. */ #define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to * DAD failure. (XXX: not ND-specific) */ diff --git a/sys/netsmb/smb_trantcp.c b/sys/netsmb/smb_trantcp.c index c898451..ce52544 100644 --- a/sys/netsmb/smb_trantcp.c +++ b/sys/netsmb/smb_trantcp.c @@ -523,8 +523,10 @@ smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap, struct thread *td) return error; getnanotime(&ts2); timespecsub(&ts2, &ts1); - if (ts2.tv_sec == 0 && ts2.tv_sec == 0) + if (ts2.tv_sec == 0) { ts2.tv_sec = 1; + ts2.tv_nsec = 0; + } nbp->nbp_timo = ts2; timespecadd(&nbp->nbp_timo, &ts2); timespecadd(&nbp->nbp_timo, &ts2); diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 88b1f20..38b7a28 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/memrange.h> #include <sys/msgbuf.h> #include <sys/mutex.h> #include <sys/pcpu.h> @@ -216,6 +217,8 @@ struct pcpu __pcpu[MAXCPU]; struct mtx icu_lock; +struct mem_range_softc mem_range_softc; + static void cpu_startup(dummy) void *dummy; diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 9de65b7..93dfb46 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -300,7 +300,7 @@ 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); +int moea_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int); boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t); int moea_page_wired_mappings(mmu_t, vm_page_t); @@ -1269,15 +1269,20 @@ moea_init(mmu_t mmu) boolean_t moea_is_referenced(mmu_t mmu, vm_page_t m) { + boolean_t rv; KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("moea_is_referenced: page %p is not managed", m)); - return (moea_query_bit(m, PTE_REF)); + rw_wlock(&pvh_global_lock); + rv = moea_query_bit(m, PTE_REF); + rw_wunlock(&pvh_global_lock); + return (rv); } boolean_t moea_is_modified(mmu_t mmu, vm_page_t m) { + boolean_t rv; KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("moea_is_modified: page %p is not managed", m)); @@ -1291,7 +1296,10 @@ moea_is_modified(mmu_t mmu, vm_page_t m) if ((m->oflags & VPO_BUSY) == 0 && (m->aflags & PGA_WRITEABLE) == 0) return (FALSE); - return (moea_query_bit(m, PTE_CHG)); + rw_wlock(&pvh_global_lock); + rv = moea_query_bit(m, PTE_CHG); + rw_wunlock(&pvh_global_lock); + return (rv); } boolean_t @@ -1313,7 +1321,9 @@ moea_clear_reference(mmu_t mmu, vm_page_t m) KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("moea_clear_reference: page %p is not managed", m)); + rw_wlock(&pvh_global_lock); moea_clear_bit(m, PTE_REF); + rw_wunlock(&pvh_global_lock); } void @@ -1333,7 +1343,9 @@ moea_clear_modify(mmu_t mmu, vm_page_t m) */ if ((m->aflags & PGA_WRITEABLE) == 0) return; + rw_wlock(&pvh_global_lock); moea_clear_bit(m, PTE_CHG); + rw_wunlock(&pvh_global_lock); } /* @@ -1400,13 +1412,17 @@ moea_remove_write(mmu_t mmu, vm_page_t m) * should be tested and standardized at some point in the future for * optimal aging of shared pages. */ -boolean_t +int moea_ts_referenced(mmu_t mmu, vm_page_t m) { + int count; KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("moea_ts_referenced: page %p is not managed", m)); - return (moea_clear_bit(m, PTE_REF)); + rw_wlock(&pvh_global_lock); + count = moea_clear_bit(m, PTE_REF); + rw_wunlock(&pvh_global_lock); + return (count); } /* @@ -1816,7 +1832,7 @@ moea_remove_all(mmu_t mmu, vm_page_t m) moea_pvo_remove(pvo, -1); PMAP_UNLOCK(pmap); } - if ((m->aflags & PGA_WRITEABLE) && moea_is_modified(mmu, m)) { + if ((m->aflags & PGA_WRITEABLE) && moea_query_bit(m, PTE_CHG)) { moea_attr_clear(m, PTE_CHG); vm_page_dirty(m); } @@ -2293,10 +2309,10 @@ moea_query_bit(vm_page_t m, int ptebit) struct pvo_entry *pvo; struct pte *pt; + rw_assert(&pvh_global_lock, RA_WLOCKED); if (moea_attr_fetch(m) & ptebit) return (TRUE); - rw_wlock(&pvh_global_lock); LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { /* @@ -2305,7 +2321,6 @@ moea_query_bit(vm_page_t m, int ptebit) */ if (pvo->pvo_pte.pte.pte_lo & ptebit) { moea_attr_save(m, ptebit); - rw_wunlock(&pvh_global_lock); return (TRUE); } } @@ -2329,13 +2344,11 @@ moea_query_bit(vm_page_t m, int ptebit) mtx_unlock(&moea_table_mutex); if (pvo->pvo_pte.pte.pte_lo & ptebit) { moea_attr_save(m, ptebit); - rw_wunlock(&pvh_global_lock); return (TRUE); } } } - rw_wunlock(&pvh_global_lock); return (FALSE); } @@ -2346,7 +2359,7 @@ moea_clear_bit(vm_page_t m, int ptebit) struct pvo_entry *pvo; struct pte *pt; - rw_wlock(&pvh_global_lock); + rw_assert(&pvh_global_lock, RA_WLOCKED); /* * Clear the cached value. @@ -2380,7 +2393,6 @@ moea_clear_bit(vm_page_t m, int ptebit) pvo->pvo_pte.pte.pte_lo &= ~ptebit; } - rw_wunlock(&pvh_global_lock); return (count); } diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index ada0833..31ca7c2 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -305,7 +305,7 @@ 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); +int moea64_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int); boolean_t moea64_page_exists_quick(mmu_t, pmap_t, vm_page_t); int moea64_page_wired_mappings(mmu_t, vm_page_t); @@ -1570,7 +1570,7 @@ moea64_remove_write(mmu_t mmu, vm_page_t m) * should be tested and standardized at some point in the future for * optimal aging of shared pages. */ -boolean_t +int moea64_ts_referenced(mmu_t mmu, vm_page_t m) { diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 8b27e6e..060a7f2 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -286,7 +286,7 @@ static void mmu_booke_init(mmu_t); static boolean_t mmu_booke_is_modified(mmu_t, vm_page_t); static boolean_t mmu_booke_is_prefaultable(mmu_t, pmap_t, vm_offset_t); static boolean_t mmu_booke_is_referenced(mmu_t, vm_page_t); -static boolean_t mmu_booke_ts_referenced(mmu_t, vm_page_t); +static int mmu_booke_ts_referenced(mmu_t, vm_page_t); static vm_offset_t mmu_booke_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int); static int mmu_booke_mincore(mmu_t, pmap_t, vm_offset_t, diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m index 887e5e4..8cd6e52 100644 --- a/sys/powerpc/powerpc/mmu_if.m +++ b/sys/powerpc/powerpc/mmu_if.m @@ -387,7 +387,7 @@ METHOD boolean_t is_referenced { * * @retval int count of referenced bits */ -METHOD boolean_t ts_referenced { +METHOD int ts_referenced { mmu_t _mmu; vm_page_t _pg; }; diff --git a/sys/sys/dtrace_bsd.h b/sys/sys/dtrace_bsd.h index eb348b2..2198b26 100644 --- a/sys/sys/dtrace_bsd.h +++ b/sys/sys/dtrace_bsd.h @@ -38,6 +38,8 @@ struct thread; struct vattr; struct vnode; struct reg; +struct devstat; +struct bio; /* * Cyclic clock function type definition used to hook the cyclic @@ -168,6 +170,23 @@ extern dtrace_nfsclient_nfs23_done_probe_func_t extern dtrace_nfsclient_nfs23_done_probe_func_t dtrace_nfscl_nfs234_done_probe; +/* IO Provider hooks, really hook into devstat */ +typedef void (*dtrace_io_start_probe_func_t)(uint32_t, struct bio *, + struct devstat *); +extern dtrace_io_start_probe_func_t dtrace_io_start_probe; + +typedef void (*dtrace_io_done_probe_func_t)(uint32_t, struct bio *, + struct devstat *); +extern dtrace_io_done_probe_func_t dtrace_io_done_probe; + +typedef void (*dtrace_io_wait_start_probe_func_t)(uint32_t, uintptr_t *, + struct devstat *); +extern dtrace_io_wait_start_probe_func_t dtrace_io_wait_start_probe; + +typedef void (*dtrace_io_wait_done_probe_func_t)(uint32_t, uintptr_t *, + struct devstat *); +extern dtrace_io_wait_done_probe_func_t dtrace_io_wait_done_probe; + /* * Functions which allow the dtrace module to check that the kernel * hooks have been compiled with sufficient space for it's private diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 0751213..612dd96 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1451,6 +1451,12 @@ retry: /* * Transfer any cached pages from orig_object to new_object. + * If swap_pager_copy() found swapped out pages within the + * specified range of orig_object, then it changed + * new_object's type to OBJT_SWAP when it transferred those + * pages to new_object. Otherwise, new_object's type + * should still be OBJT_DEFAULT and orig_object should not + * contain any cached pages within the specified range. */ if (!vm_object_cache_is_empty(orig_object)) { start = offidxstart; @@ -1811,6 +1817,9 @@ vm_object_collapse(vm_object_t object) * swap_pager_copy() can sleep, in which case * the backing_object's and object's locks are * released and reacquired. + * Since swap_pager_copy() is being asked to + * destroy the source, it will change the + * backing_object's type to OBJT_DEFAULT. */ swap_pager_copy( backing_object, |