diff options
Diffstat (limited to 'sys')
126 files changed, 2736 insertions, 1836 deletions
diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index 7cc13ca..20e8f76 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -564,6 +564,19 @@ svm_vminit(struct vm *vm, pmap_t pmap) return (svm_sc); } +/* + * Collateral for a generic SVM VM-exit. + */ +static void +vm_exit_svm(struct vm_exit *vme, uint64_t code, uint64_t info1, uint64_t info2) +{ + + vme->exitcode = VM_EXITCODE_SVM; + vme->u.svm.exitcode = code; + vme->u.svm.exitinfo1 = info1; + vme->u.svm.exitinfo2 = info2; +} + static int svm_cpl(struct vmcb_state *state) { @@ -1080,6 +1093,76 @@ clear_nmi_blocking(struct svm_softc *sc, int vcpu) KASSERT(!error, ("%s: error %d setting intr_shadow", __func__, error)); } +#define EFER_MBZ_BITS 0xFFFFFFFFFFFF0200UL + +static int +svm_write_efer(struct svm_softc *sc, int vcpu, uint64_t newval, bool *retu) +{ + struct vm_exit *vme; + struct vmcb_state *state; + uint64_t changed, lma, oldval; + int error; + + state = svm_get_vmcb_state(sc, vcpu); + + oldval = state->efer; + VCPU_CTR2(sc->vm, vcpu, "wrmsr(efer) %#lx/%#lx", oldval, newval); + + newval &= ~0xFE; /* clear the Read-As-Zero (RAZ) bits */ + changed = oldval ^ newval; + + if (newval & EFER_MBZ_BITS) + goto gpf; + + /* APMv2 Table 14-5 "Long-Mode Consistency Checks" */ + if (changed & EFER_LME) { + if (state->cr0 & CR0_PG) + goto gpf; + } + + /* EFER.LMA = EFER.LME & CR0.PG */ + if ((newval & EFER_LME) != 0 && (state->cr0 & CR0_PG) != 0) + lma = EFER_LMA; + else + lma = 0; + + if ((newval & EFER_LMA) != lma) + goto gpf; + + if (newval & EFER_NXE) { + if (!vm_cpuid_capability(sc->vm, vcpu, VCC_NO_EXECUTE)) + goto gpf; + } + + /* + * XXX bhyve does not enforce segment limits in 64-bit mode. Until + * this is fixed flag guest attempt to set EFER_LMSLE as an error. + */ + if (newval & EFER_LMSLE) { + vme = vm_exitinfo(sc->vm, vcpu); + vm_exit_svm(vme, VMCB_EXIT_MSR, 1, 0); + *retu = true; + return (0); + } + + if (newval & EFER_FFXSR) { + if (!vm_cpuid_capability(sc->vm, vcpu, VCC_FFXSR)) + goto gpf; + } + + if (newval & EFER_TCE) { + if (!vm_cpuid_capability(sc->vm, vcpu, VCC_TCE)) + goto gpf; + } + + error = svm_setreg(sc, vcpu, VM_REG_GUEST_EFER, newval); + KASSERT(error == 0, ("%s: error %d updating efer", __func__, error)); + return (0); +gpf: + vm_inject_gp(sc->vm, vcpu); + return (0); +} + static int emulate_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, bool *retu) @@ -1089,7 +1172,7 @@ emulate_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, if (lapic_msr(num)) error = lapic_wrmsr(sc->vm, vcpu, num, val, retu); else if (num == MSR_EFER) - error = svm_setreg(sc, vcpu, VM_REG_GUEST_EFER, val); + error = svm_write_efer(sc, vcpu, val, retu); else error = svm_wrmsr(sc, vcpu, num, val, retu); @@ -1189,19 +1272,6 @@ nrip_valid(uint64_t exitcode) } } -/* - * Collateral for a generic SVM VM-exit. - */ -static void -vm_exit_svm(struct vm_exit *vme, uint64_t code, uint64_t info1, uint64_t info2) -{ - - vme->exitcode = VM_EXITCODE_SVM; - vme->u.svm.exitcode = code; - vme->u.svm.exitinfo1 = info1; - vme->u.svm.exitinfo2 = info2; -} - static int svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit) { diff --git a/sys/amd64/vmm/amd/svm_msr.c b/sys/amd64/vmm/amd/svm_msr.c index d3a6fe8..088751a 100644 --- a/sys/amd64/vmm/amd/svm_msr.c +++ b/sys/amd64/vmm/amd/svm_msr.c @@ -110,6 +110,10 @@ svm_rdmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t *result, int error = 0; switch (num) { + case MSR_MCG_CAP: + case MSR_MCG_STATUS: + *result = 0; + break; case MSR_MTRRcap: case MSR_MTRRdefType: case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8: @@ -135,6 +139,9 @@ svm_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, bool *retu) int error = 0; switch (num) { + case MSR_MCG_CAP: + case MSR_MCG_STATUS: + break; /* ignore writes */ case MSR_MTRRcap: vm_inject_gp(sc->vm, vcpu); break; diff --git a/sys/amd64/vmm/intel/vmx_msr.c b/sys/amd64/vmm/intel/vmx_msr.c index 526b0d1..3091f68 100644 --- a/sys/amd64/vmm/intel/vmx_msr.c +++ b/sys/amd64/vmm/intel/vmx_msr.c @@ -395,6 +395,10 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu) error = 0; switch (num) { + case MSR_MCG_CAP: + case MSR_MCG_STATUS: + *val = 0; + break; case MSR_MTRRcap: case MSR_MTRRdefType: case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8: @@ -433,6 +437,9 @@ vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu) error = 0; switch (num) { + case MSR_MCG_CAP: + case MSR_MCG_STATUS: + break; /* ignore writes */ case MSR_MTRRcap: vm_inject_gp(vmx->vm, vcpuid); break; diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 7172365..c83f3e0 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -178,14 +178,20 @@ static const struct vie_op one_byte_opcodes[256] = { .op_byte = 0x23, .op_type = VIE_OP_TYPE_AND, }, + [0x80] = { + /* Group 1 extended opcode */ + .op_byte = 0x80, + .op_type = VIE_OP_TYPE_GROUP1, + .op_flags = VIE_OP_F_IMM8, + }, [0x81] = { - /* XXX Group 1 extended opcode */ + /* Group 1 extended opcode */ .op_byte = 0x81, .op_type = VIE_OP_TYPE_GROUP1, .op_flags = VIE_OP_F_IMM, }, [0x83] = { - /* XXX Group 1 extended opcode */ + /* Group 1 extended opcode */ .op_byte = 0x83, .op_type = VIE_OP_TYPE_GROUP1, .op_flags = VIE_OP_F_IMM8, @@ -1066,9 +1072,13 @@ emulate_cmp(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, rflags2 = getcc(size, op1, op2); break; + case 0x80: case 0x81: case 0x83: /* + * 80 /7 cmp r/m8, imm8 + * REX + 80 /7 cmp r/m8, imm8 + * * 81 /7 cmp r/m16, imm16 * 81 /7 cmp r/m32, imm32 * REX.W + 81 /7 cmp r/m64, imm32 sign-extended to 64 @@ -1084,6 +1094,8 @@ emulate_cmp(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, * the status flags. * */ + if (vie->op.op_byte == 0x80) + size = 1; /* get the first operand */ error = memread(vm, vcpuid, gpa, &op1, size, arg); diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 45e08b5..525e1d9 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -230,10 +230,11 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT); /* - * Don't expose VMX, SpeedStep or TME capability. + * Don't expose VMX, SpeedStep, TME or SMX capability. * Advertise x2APIC capability and Hypervisor guest. */ regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2); + regs[2] &= ~(CPUID2_SMX); regs[2] |= CPUID2_HV; @@ -285,17 +286,20 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, * Hide thermal monitoring */ regs[3] &= ~(CPUID_ACPI | CPUID_TM); - + /* - * Machine check handling is done in the host. + * Hide the debug store capability. */ - regs[3] &= ~(CPUID_MCA | CPUID_MCE); - - /* - * Hide the debug store capability. - */ regs[3] &= ~CPUID_DS; + /* + * Advertise the Machine Check and MTRR capability. + * + * Some guest OSes (e.g. Windows) will not boot if + * these features are absent. + */ + regs[3] |= (CPUID_MCA | CPUID_MCE | CPUID_MTRR); + logical_cpus = threads_per_core * cores_per_package; regs[1] &= ~CPUID_HTT_CORES; regs[1] |= (logical_cpus & 0xff) << 16; @@ -484,3 +488,34 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, return (1); } + +bool +vm_cpuid_capability(struct vm *vm, int vcpuid, enum vm_cpuid_capability cap) +{ + bool rv; + + KASSERT(cap > 0 && cap < VCC_LAST, ("%s: invalid vm_cpu_capability %d", + __func__, cap)); + + /* + * Simply passthrough the capabilities of the host cpu for now. + */ + rv = false; + switch (cap) { + case VCC_NO_EXECUTE: + if (amd_feature & AMDID_NX) + rv = true; + break; + case VCC_FFXSR: + if (amd_feature & AMDID_FFXSR) + rv = true; + break; + case VCC_TCE: + if (amd_feature2 & AMDID2_TCE) + rv = true; + break; + default: + panic("%s: unknown vm_cpu_capability %d", __func__, cap); + } + return (rv); +} diff --git a/sys/amd64/vmm/x86.h b/sys/amd64/vmm/x86.h index 8401c15..6f99d52 100644 --- a/sys/amd64/vmm/x86.h +++ b/sys/amd64/vmm/x86.h @@ -62,4 +62,17 @@ int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); +enum vm_cpuid_capability { + VCC_NONE, + VCC_NO_EXECUTE, + VCC_FFXSR, + VCC_TCE, + VCC_LAST +}; + +/* + * Return 'true' if the capability 'cap' is enabled in this virtual cpu + * and 'false' otherwise. + */ +bool vm_cpuid_capability(struct vm *vm, int vcpuid, enum vm_cpuid_capability); #endif diff --git a/sys/arm/amlogic/aml8726/aml8726_uart.h b/sys/arm/amlogic/aml8726/aml8726_uart.h index ee63325..fbdd657 100644 --- a/sys/arm/amlogic/aml8726/aml8726_uart.h +++ b/sys/arm/amlogic/aml8726/aml8726_uart.h @@ -94,4 +94,14 @@ #define AML_UART_MISC_RECV_IRQ_CNT_MASK 0xff #define AML_UART_MISC_RECV_IRQ_CNT_SHIFT 0 +/* + * The new baud rate register is available on the + * aml8726-m6 and later. + */ +#define AML_UART_NEW_BAUD_REG 20 +#define AML_UART_NEW_BAUD_USE_XTAL_CLK (1 << 24) +#define AML_UART_NEW_BAUD_RATE_EN (1 << 23) +#define AML_UART_NEW_BAUD_RATE_MASK (0x7fffff << 0) +#define AML_UART_NEW_BAUD_RATE_SHIFT 0 + #endif /* _ARM_AMLOGIC_AML8726_UART_H */ diff --git a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c index 1dda52f..5d21fb0 100644 --- a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c +++ b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c @@ -31,8 +31,8 @@ * uarts. For example ... though UART A as a 128 byte FIFO, the * others only have a 64 byte FIFO. * - * Also, it's assumed that register 5 (the new baud rate register - * present on the aml8726-m6) has not been activated. + * Also, it's assumed that the USE_XTAL_CLK feature (available on + * the aml8726-m6 and later) has not been activated. */ #include <sys/cdefs.h> @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart_cpu_fdt.h> #include <dev/uart/uart_bus.h> +#include <arm/amlogic/aml8726/aml8726_soc.h> #include <arm/amlogic/aml8726/aml8726_uart.h> #include "uart_if.h" @@ -89,7 +90,7 @@ aml8726_uart_divisor(int rclk, int baudrate) /* integer version of (rclk / baudrate + .5) */ divisor = ((rclk << 1) + baudrate) / (baudrate << 1); - if (divisor == 0 || divisor >= 65536) + if (divisor == 0) return (0); actual_baud = rclk / divisor; @@ -109,6 +110,7 @@ aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbit { uint32_t cr; uint32_t mr; + uint32_t nbr; int divisor; cr = uart_getreg(bas, AML_UART_CONTROL_REG); @@ -147,8 +149,29 @@ aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbit /* Set baudrate. */ if (baudrate > 0 && bas->rclk != 0) { divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1; - if (divisor > 0xffff) - return (EINVAL); + + switch (aml8726_soc_hw_rev) { + case AML_SOC_HW_REV_M6: + case AML_SOC_HW_REV_M8: + case AML_SOC_HW_REV_M8B: + if (divisor > (AML_UART_NEW_BAUD_RATE_MASK >> + AML_UART_NEW_BAUD_RATE_SHIFT)) + return (EINVAL); + + nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); + nbr &= ~(AML_UART_NEW_BAUD_USE_XTAL_CLK | + AML_UART_NEW_BAUD_RATE_MASK); + nbr |= AML_UART_NEW_BAUD_RATE_EN | + (divisor << AML_UART_NEW_BAUD_RATE_SHIFT); + uart_setreg(bas, AML_UART_NEW_BAUD_REG, nbr); + + divisor = 0; + break; + default: + if (divisor > 0xffff) + return (EINVAL); + break; + } cr &= ~AML_UART_CONTROL_BAUD_MASK; cr |= (divisor & AML_UART_CONTROL_BAUD_MASK); @@ -187,7 +210,7 @@ aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits uint32_t cr; uint32_t mr; - aml8726_uart_param(bas, baudrate, databits, stopbits, parity); + (void)aml8726_uart_param(bas, baudrate, databits, stopbits, parity); cr = uart_getreg(bas, AML_UART_CONTROL_REG); /* Disable all interrupt sources. */ @@ -466,7 +489,7 @@ aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct uart_bas *bas; int baudrate, divisor, error; - uint32_t cr, mr; + uint32_t cr, mr, nbr; bas = &sc->sc_bas; uart_lock(sc->sc_hwmtx); @@ -483,6 +506,20 @@ aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) << AML_UART_CONTROL_BAUD_WIDTH) | cr; + switch (aml8726_soc_hw_rev) { + case AML_SOC_HW_REV_M6: + case AML_SOC_HW_REV_M8: + case AML_SOC_HW_REV_M8B: + nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); + if ((nbr & AML_UART_NEW_BAUD_RATE_EN) != 0) { + divisor = (nbr & AML_UART_NEW_BAUD_RATE_MASK) >> + AML_UART_NEW_BAUD_RATE_SHIFT; + } + break; + default: + break; + } + baudrate = bas->rclk / 4 / (divisor + 1); if (baudrate > 0) *(int*)data = baudrate; diff --git a/sys/arm/arm/cpufunc_asm_armv7.S b/sys/arm/arm/cpufunc_asm_armv7.S index 25f052f..7016d7e 100644 --- a/sys/arm/arm/cpufunc_asm_armv7.S +++ b/sys/arm/arm/cpufunc_asm_armv7.S @@ -266,6 +266,9 @@ END(armv7_icache_sync_all) ENTRY_NP(armv7_icache_sync_range) ldr ip, .Larmv7_icache_line_size ldr ip, [ip] + sub r3, ip, #1 /* Address need not be aligned, but */ + and r2, r0, r3 /* round length up if op spans line */ + add r1, r1, r2 /* boundary: len += addr & linemask; */ .Larmv7_sync_next: mcr CP15_DCCMVAC(r0) mcr CP15_ICIMVAU(r0) diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 9085d67..598decc 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -105,7 +105,6 @@ elf32_arm_abi_supported(struct image_params *imgp) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; -#ifdef __ARM_EABI__ /* * When configured for EABI, FreeBSD supports EABI vesions 4 and 5. */ @@ -115,17 +114,6 @@ elf32_arm_abi_supported(struct image_params *imgp) EF_ARM_EABI_VERSION(hdr->e_flags), imgp->args->fname); return (FALSE); } -#else - /* - * When configured for OABI, that's all we do, so reject EABI binaries. - */ - if (EF_ARM_EABI_VERSION(hdr->e_flags) != EF_ARM_EABI_VERSION_UNKNOWN) { - if (bootverbose) - uprintf("Attempting to execute EABI binary (rev %d) image %s", - EF_ARM_EABI_VERSION(hdr->e_flags), imgp->args->fname); - return (FALSE); - } -#endif return (TRUE); } diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index d246a87..56db9ca 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -31,7 +31,7 @@ */ /** - * Cortex-A15 (and probably A7) Generic Timer + * Cortex-A7, Cortex-A15, ARMv8 and later Generic Timer */ #include <sys/cdefs.h> diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 68d31a9..a76e18a4 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -1055,7 +1055,6 @@ kenv_next(char *cp) static void print_kenv(void) { - int len; char *cp; debugf("loader passed (static) kenv:\n"); @@ -1065,7 +1064,6 @@ print_kenv(void) } debugf(" kern_envp = 0x%08x\n", (uint32_t)kern_envp); - len = 0; for (cp = kern_envp; cp != NULL; cp = kenv_next(cp)) debugf(" %x %s\n", (uint32_t)cp, cp); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c index 2ea5b49..ab0f901 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama@peach.ne.jp> + * Copyright (C) 2013-2015 Daisuke Aoyama <aoyama@peach.ne.jp> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,21 +60,28 @@ __FBSDID("$FreeBSD$"); #define DPRINTF(fmt, ...) #endif -#define HZ2MHZ(freq) ((freq) / (1000 * 1000)) -#define MHZ2HZ(freq) ((freq) * (1000 * 1000)) -#define OFFSET2MVOLT(val) (1200 + ((val) * 25)) -#define MVOLT2OFFSET(val) (((val) - 1200) / 25) - -#define DEFAULT_ARM_FREQUENCY 700 -#define DEFAULT_CORE_FREQUENCY 250 -#define DEFAULT_SDRAM_FREQUENCY 400 -#define DEFAULT_LOWEST_FREQ 300 -#define TRANSITION_LATENCY 1000 -#define MIN_OVER_VOLTAGE -16 -#define MAX_OVER_VOLTAGE 6 -#define MSG_ERROR -999999999 -#define MHZSTEP 100 -#define HZSTEP (MHZ2HZ(MHZSTEP)) +#define HZ2MHZ(freq) ((freq) / (1000 * 1000)) +#define MHZ2HZ(freq) ((freq) * (1000 * 1000)) + +#ifdef SOC_BCM2836 +#define OFFSET2MVOLT(val) (((val) / 1000)) +#define MVOLT2OFFSET(val) (((val) * 1000)) +#define DEFAULT_ARM_FREQUENCY 600 +#define DEFAULT_LOWEST_FREQ 600 +#else +#define OFFSET2MVOLT(val) (1200 + ((val) * 25)) +#define MVOLT2OFFSET(val) (((val) - 1200) / 25) +#define DEFAULT_ARM_FREQUENCY 700 +#define DEFAULT_LOWEST_FREQ 300 +#endif +#define DEFAULT_CORE_FREQUENCY 250 +#define DEFAULT_SDRAM_FREQUENCY 400 +#define TRANSITION_LATENCY 1000 +#define MIN_OVER_VOLTAGE -16 +#define MAX_OVER_VOLTAGE 6 +#define MSG_ERROR -999999999 +#define MHZSTEP 100 +#define HZSTEP (MHZ2HZ(MHZSTEP)) #define TZ_ZEROC 2732 #define VC_LOCK(sc) do { \ @@ -1740,6 +1747,23 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets, if (min_freq > cpufreq_lowest_freq) min_freq = cpufreq_lowest_freq; +#ifdef SOC_BCM2836 + /* XXX RPi2 have only 900/600MHz */ + idx = 0; + volts = sc->min_voltage_core; + sets[idx].freq = freq; + sets[idx].volts = volts; + sets[idx].lat = TRANSITION_LATENCY; + sets[idx].dev = dev; + idx++; + if (freq != min_freq) { + sets[idx].freq = min_freq; + sets[idx].volts = volts; + sets[idx].lat = TRANSITION_LATENCY; + sets[idx].dev = dev; + idx++; + } +#else /* from freq to min_freq */ for (idx = 0; idx < *count && freq >= min_freq; idx++) { if (freq > sc->arm_min_freq) @@ -1752,7 +1776,8 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets, sets[idx].dev = dev; freq -= MHZSTEP; } - *count = ++idx; +#endif + *count = idx; return (0); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c index 3270da1..6e6cfda 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c @@ -29,46 +29,27 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/bio.h> #include <sys/bus.h> -#include <sys/conf.h> -#include <sys/endian.h> +#include <sys/consio.h> +#include <sys/fbio.h> +#include <sys/kdb.h> #include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> -#include <sys/mutex.h> -#include <sys/queue.h> -#include <sys/resource.h> -#include <sys/rman.h> -#include <sys/time.h> -#include <sys/timetc.h> -#include <sys/fbio.h> -#include <sys/consio.h> - -#include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/cpufunc.h> -#include <machine/resource.h> -#include <machine/intr.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <dev/fb/fbreg.h> #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> - -#include <dev/fb/fbreg.h> #include <dev/syscons/syscons.h> -#include <arm/broadcom/bcm2835/bcm2835_mbox.h> -#include <arm/broadcom/bcm2835/bcm2835_vcbus.h> +#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> #include "mbox_if.h" -#define BCMFB_FONT_HEIGHT 16 - struct argb { uint8_t a; uint8_t r; @@ -101,40 +82,15 @@ static u_char mouse_pointer[16] = { 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; -#define FB_WIDTH 640 -#define FB_HEIGHT 480 -#define FB_DEPTH 24 - -struct bcm_fb_config { - uint32_t xres; - uint32_t yres; - uint32_t vxres; - uint32_t vyres; - uint32_t pitch; - uint32_t bpp; - uint32_t xoffset; - uint32_t yoffset; - /* Filled by videocore */ - uint32_t base; - uint32_t screen_size; -}; +#define BCMFB_FONT_HEIGHT 16 +#define BCMFB_FONT_WIDTH 8 +#define FB_WIDTH 640 +#define FB_HEIGHT 480 +#define FB_DEPTH 24 struct bcmsc_softc { - device_t dev; - struct cdev * cdev; - struct mtx mtx; - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; - struct bcm_fb_config* fb_config; - bus_addr_t fb_config_phys; - struct intr_config_hook init_hook; - -}; - -struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; - int console; intptr_t fb_addr; intptr_t fb_paddr; @@ -149,199 +105,75 @@ struct video_adapter_softc { unsigned int ymargin; unsigned char *font; + int fbswap; int initialized; }; -static struct bcmsc_softc *bcmsc_softc; -static struct video_adapter_softc va_softc; - -#define bcm_fb_lock(_sc) mtx_lock(&(_sc)->mtx) -#define bcm_fb_unlock(_sc) mtx_unlock(&(_sc)->mtx) -#define bcm_fb_lock_assert(sc) mtx_assert(&(_sc)->mtx, MA_OWNED) +static struct bcmsc_softc bcmsc; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); -static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); static void bcmfb_update_margins(video_adapter_t *adp); static int bcmfb_configure(int); -static void -bcm_fb_init(void *arg) -{ - struct bcmsc_softc *sc = arg; - struct video_adapter_softc *va_sc = &va_softc; - int err; - volatile struct bcm_fb_config* fb_config = sc->fb_config; - phandle_t node; - pcell_t cell; - device_t mbox; - - node = ofw_bus_get_node(sc->dev); - - fb_config->xres = 0; - fb_config->yres = 0; - fb_config->bpp = 0; - - if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) - fb_config->xres = (int)fdt32_to_cpu(cell); - if (fb_config->xres == 0) - fb_config->xres = FB_WIDTH; - - if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) - fb_config->yres = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->yres == 0) - fb_config->yres = FB_HEIGHT; - - if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) - fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->bpp == 0) - fb_config->bpp = FB_DEPTH; - - fb_config->vxres = 0; - fb_config->vyres = 0; - fb_config->xoffset = 0; - fb_config->yoffset = 0; - fb_config->base = 0; - fb_config->pitch = 0; - fb_config->screen_size = 0; - - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - mbox = devclass_get_device(devclass_find("mbox"), 0); - if (mbox) { - MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); - MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); - } - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTREAD); - - if (fb_config->base != 0) { - device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", - fb_config->xres, fb_config->yres, - fb_config->vxres, fb_config->vyres, - fb_config->xoffset, fb_config->yoffset, - fb_config->bpp); - - - device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", - fb_config->pitch, fb_config->base, - fb_config->screen_size); - - va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); - va_sc->fb_paddr = fb_config->base; - va_sc->fb_size = fb_config->screen_size; - va_sc->depth = fb_config->bpp; - va_sc->stride = fb_config->pitch; - - va_sc->width = fb_config->xres; - va_sc->height = fb_config->yres; - bcmfb_update_margins(&va_sc->va); - } - else { - device_printf(sc->dev, "Failed to set framebuffer info\n"); - } - - config_intrhook_disestablish(&sc->init_hook); -} - static int bcm_fb_probe(device_t dev) { - int error = 0; + int error; if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb")) return (ENXIO); - device_set_desc(dev, "BCM2835 framebuffer device"); - error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); - return (BUS_PROBE_DEFAULT); } static int bcm_fb_attach(device_t dev) { - struct bcmsc_softc *sc = device_get_softc(dev); - int dma_size = sizeof(struct bcm_fb_config); - int err; - - if (bcmsc_softc) - return (ENXIO); + struct bcm2835_fb_config fb; + struct bcmsc_softc *sc; - bcmsc_softc = sc; - - sc->dev = dev; - mtx_init(&sc->mtx, "bcm2835fb", "fb", MTX_DEF); - - err = bus_dma_tag_create( - bus_get_dma_tag(sc->dev), - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - dma_size, 1, /* maxsize, nsegments */ - dma_size, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->dma_tag); - - err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, - 0, &sc->dma_map); - if (err) { - device_printf(dev, "cannot allocate framebuffer\n"); - goto fail; - } - - err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, - dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); - - if (err) { - device_printf(dev, "cannot load DMA map\n"); - goto fail; - } + sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter( + "bcmfb", 0)); + if (sc != NULL) + device_set_softc(dev, sc); + else + sc = device_get_softc(dev); - err = (sc_attach_unit(device_get_unit(dev), - device_get_flags(dev) | SC_AUTODETECT_KBD)); + memset(&fb, 0, sizeof(fb)); + if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0) + return (ENXIO); + fb.bpp = FB_DEPTH; + if (bcm2835_mbox_fb_init(dev, &fb) != 0) + return (ENXIO); - if (err) { + sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size); + sc->fb_paddr = fb.base; + sc->fb_size = fb.size; + sc->depth = fb.bpp; + sc->stride = fb.pitch; + sc->width = fb.xres; + sc->height = fb.yres; + bcmfb_update_margins(&sc->va); + + if (sc_attach_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) { device_printf(dev, "failed to attach syscons\n"); - goto fail; + return (ENXIO); } - /* - * We have to wait until interrupts are enabled. - * Mailbox relies on it to get data from VideoCore - */ - sc->init_hook.ich_func = bcm_fb_init; - sc->init_hook.ich_arg = sc; - - if (config_intrhook_establish(&sc->init_hook) != 0) { - device_printf(dev, "failed to establish intrhook\n"); - return (ENOMEM); - } + device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, + fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); + device_printf(dev, + "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", + sc->fbswap, fb.pitch, fb.base, fb.size); return (0); - -fail: - return (ENXIO); -} - - -static void -bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) -{ - bus_addr_t *addr; - - if (err) - return; - - addr = (bus_addr_t*)arg; - *addr = PHYS_TO_VCBUS(segs[0].ds_addr); } static device_method_t bcm_fb_methods[] = { @@ -504,13 +336,13 @@ bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink) static void bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { - video_adapter_t* adp = scp->sc->adp; - struct video_adapter_softc *sc; - int row, col; + int bytes, col, i, j, row; + struct bcmsc_softc *sc; uint8_t *addr; - int i, j, bytes; + video_adapter_t *adp; - sc = (struct video_adapter_softc *)adp; + adp = scp->sc->adp; + sc = (struct bcmsc_softc *)adp; if (scp->curs_attr.height <= 0) return; @@ -529,8 +361,7 @@ bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); - bytes = sc->depth/8; - + bytes = sc->depth / 8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { @@ -577,56 +408,80 @@ extern u_char dflt_font_16[]; static void bcmfb_update_margins(video_adapter_t *adp) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; video_info_t *vi; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; - sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; + sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; } static int bcmfb_configure(int flags) { - struct video_adapter_softc *va_sc; - - va_sc = &va_softc; - phandle_t display, root; + char bootargs[2048], *n, *p, *v; pcell_t cell; + phandle_t chosen, display, root; + struct bcmsc_softc *sc; - if (va_sc->initialized) + sc = &bcmsc; + if (sc->initialized) return (0); - va_sc->width = 0; - va_sc->height = 0; + sc->width = 0; + sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try - * to fetch data from FDT and go with defaults if failed + * to fetch data from FDT bootargs, FDT display data and + * finally go with defaults if everything else has failed. */ + chosen = OF_finddevice("/chosen"); + if (chosen != 0 && + OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { + p = bootargs; + while ((v = strsep(&p, " ")) != NULL) { + if (*v == '\0') + continue; + n = strsep(&v, "="); + if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL) + sc->width = (unsigned int)strtol(v, NULL, 0); + else if (strcmp(n, "bcm2708_fb.fbheight") == 0 && + v != NULL) + sc->height = (unsigned int)strtol(v, NULL, 0); + else if (strcmp(n, "bcm2708_fb.fbswap") == 0 && + v != NULL) + if (*v == '1') + sc->fbswap = 1; + } + } + root = OF_finddevice("/"); if ((root != 0) && (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { - if ((OF_getprop(display, "broadcom,width", - &cell, sizeof(cell))) > 0) - va_sc->width = (int)fdt32_to_cpu(cell); + if (sc->width == 0) { + if ((OF_getprop(display, "broadcom,width", + &cell, sizeof(cell))) > 0) + sc->width = (int)fdt32_to_cpu(cell); + } - if ((OF_getprop(display, "broadcom,height", - &cell, sizeof(cell))) > 0) - va_sc->height = (int)fdt32_to_cpu(cell); + if (sc->height == 0) { + if ((OF_getprop(display, "broadcom,height", + &cell, sizeof(cell))) > 0) + sc->height = (int)fdt32_to_cpu(cell); + } } - if (va_sc->width == 0) - va_sc->width = FB_WIDTH; - if (va_sc->height == 0) - va_sc->height = FB_HEIGHT; - - bcmfb_init(0, &va_sc->va, 0); + if (sc->width == 0) + sc->width = FB_WIDTH; + if (sc->height == 0) + sc->height = FB_HEIGHT; - va_sc->initialized = 1; + bcmfb_init(0, &sc->va, 0); + sc->initialized = 1; return (0); } @@ -641,20 +496,19 @@ bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) static int bcmfb_init(int unit, video_adapter_t *adp, int flags) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; video_info_t *vi; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "bcmfb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = BCMFB_FONT_HEIGHT; - vi->vi_cwidth = 8; - - vi->vi_width = sc->width/8; - vi->vi_height = sc->height/vi->vi_cheight; + vi->vi_cwidth = BCMFB_FONT_WIDTH; + vi->vi_width = sc->width / vi->vi_cwidth; + vi->vi_height = sc->height / vi->vi_cheight; /* * Clamp width/height to syscons maximums @@ -665,8 +519,7 @@ bcmfb_init(int unit, video_adapter_t *adp, int flags) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; - sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; - + sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; adp->va_window = (vm_offset_t) bcmfb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; @@ -706,8 +559,9 @@ static int bcmfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { - struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; + struct bcmsc_softc *sc; + sc = (struct bcmsc_softc *)adp; sc->font = data; return (0); @@ -780,9 +634,9 @@ static int bcmfb_blank_display(video_adapter_t *adp, int mode) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); @@ -793,9 +647,9 @@ static int bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the @@ -812,10 +666,10 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, static int bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; struct fbtype *fb; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; switch (cmd) { case FBIOGTYPE: @@ -897,16 +751,13 @@ bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, static int bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { - struct video_adapter_softc *sc; - int row; - int col; - int i, j, k; - uint8_t *addr; + int bytes, col, i, j, k, row; + struct bcmsc_softc *sc; u_char *p; - uint8_t fg, bg, color; + uint8_t *addr, fg, bg, color; uint16_t rgb; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; if (sc->fb_addr == 0) return (0); @@ -921,6 +772,7 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) fg = a & 0xf ; bg = (a >> 4) & 0xf; + bytes = sc->depth / 8; for (i = 0; i < BCMFB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) @@ -930,22 +782,32 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) switch (sc->depth) { case 32: - addr[4*j+0] = bcmfb_palette[color].r; - addr[4*j+1] = bcmfb_palette[color].g; - addr[4*j+2] = bcmfb_palette[color].b; - addr[4*j+3] = bcmfb_palette[color].a; - break; case 24: - addr[3*j] = bcmfb_palette[color].r; - addr[3*j+1] = bcmfb_palette[color].g; - addr[3*j+2] = bcmfb_palette[color].b; + if (sc->fbswap) { + addr[bytes * j + 0] = + bcmfb_palette[color].b; + addr[bytes * j + 1] = + bcmfb_palette[color].g; + addr[bytes * j + 2] = + bcmfb_palette[color].r; + } else { + addr[bytes * j + 0] = + bcmfb_palette[color].r; + addr[bytes * j + 1] = + bcmfb_palette[color].g; + addr[bytes * j + 2] = + bcmfb_palette[color].b; + } + if (sc->depth == 32) + addr[bytes * j + 3] = + bcmfb_palette[color].a; break; case 16: rgb = (bcmfb_palette[color].r >> 3) << 11; rgb |= (bcmfb_palette[color].g >> 2) << 5; rgb |= (bcmfb_palette[color].b >> 3); - addr[2*j] = rgb & 0xff; - addr[2*j + 1] = (rgb >> 8) & 0xff; + addr[bytes * j] = rgb & 0xff; + addr[bytes * j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c index f41e6e2..34a7af8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c @@ -35,170 +35,35 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/bio.h> #include <sys/bus.h> -#include <sys/conf.h> -#include <sys/endian.h> +#include <sys/fbio.h> #include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> -#include <sys/mutex.h> -#include <sys/queue.h> -#include <sys/resource.h> -#include <sys/rman.h> -#include <sys/time.h> -#include <sys/timetc.h> -#include <sys/fbio.h> -#include <sys/consio.h> - -#include <sys/kdb.h> #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/cpufunc.h> -#include <machine/fdt.h> -#include <machine/resource.h> -#include <machine/intr.h> - #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> #include <dev/fb/fbreg.h> #include <dev/vt/vt.h> +#include <dev/vt/colors/vt_termcolors.h> -#include <arm/broadcom/bcm2835/bcm2835_mbox.h> -#include <arm/broadcom/bcm2835/bcm2835_vcbus.h> +#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> #include "fb_if.h" #include "mbox_if.h" -#define FB_WIDTH 640 -#define FB_HEIGHT 480 -#define FB_DEPTH 24 - -struct bcm_fb_config { - uint32_t xres; - uint32_t yres; - uint32_t vxres; - uint32_t vyres; - uint32_t pitch; - uint32_t bpp; - uint32_t xoffset; - uint32_t yoffset; - /* Filled by videocore */ - uint32_t base; - uint32_t screen_size; -}; +#define FB_DEPTH 24 struct bcmsc_softc { - device_t dev; struct fb_info *info; - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; - struct bcm_fb_config* fb_config; - bus_addr_t fb_config_phys; - struct intr_config_hook init_hook; }; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); -static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, - int err); - -static void -bcm_fb_init(void *arg) -{ - volatile struct bcm_fb_config *fb_config; - struct bcmsc_softc *sc; - struct fb_info *info; - phandle_t node; - pcell_t cell; - device_t mbox; - device_t fbd; - int err = 0; - - sc = arg; - fb_config = sc->fb_config; - node = ofw_bus_get_node(sc->dev); - - fb_config->xres = 0; - fb_config->yres = 0; - fb_config->bpp = 0; - fb_config->vxres = 0; - fb_config->vyres = 0; - fb_config->xoffset = 0; - fb_config->yoffset = 0; - fb_config->base = 0; - fb_config->pitch = 0; - fb_config->screen_size = 0; - - if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) - fb_config->xres = (int)fdt32_to_cpu(cell); - if (fb_config->xres == 0) - fb_config->xres = FB_WIDTH; - - if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) - fb_config->yres = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->yres == 0) - fb_config->yres = FB_HEIGHT; - - if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) - fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->bpp == 0) - fb_config->bpp = FB_DEPTH; - - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - mbox = devclass_get_device(devclass_find("mbox"), 0); - if (mbox) { - MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); - MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); - } - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTREAD); - - if (fb_config->base != 0) { - device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", - fb_config->xres, fb_config->yres, - fb_config->vxres, fb_config->vyres, - fb_config->xoffset, fb_config->yoffset, - fb_config->bpp); - - device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", - fb_config->pitch, fb_config->base, - fb_config->screen_size); - - info = malloc(sizeof(struct fb_info), M_DEVBUF, - M_WAITOK | M_ZERO); - info->fb_name = device_get_nameunit(sc->dev); - info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base, - fb_config->screen_size); - info->fb_pbase = fb_config->base; - info->fb_size = fb_config->screen_size; - info->fb_bpp = info->fb_depth = fb_config->bpp; - info->fb_stride = fb_config->pitch; - info->fb_width = fb_config->xres; - info->fb_height = fb_config->yres; - - sc->info = info; - - fbd = device_add_child(sc->dev, "fbd", - device_get_unit(sc->dev)); - if (fbd == NULL) - device_printf(sc->dev, "Failed to add fbd child\n"); - else if (device_probe_and_attach(fbd) != 0) - device_printf(sc->dev, "Failed to attach fbd device\n"); - } else { - device_printf(sc->dev, "Failed to set framebuffer info\n"); - } - - config_intrhook_disestablish(&sc->init_hook); -} static int bcm_fb_probe(device_t dev) @@ -214,66 +79,82 @@ bcm_fb_probe(device_t dev) static int bcm_fb_attach(device_t dev) { - struct bcmsc_softc *sc = device_get_softc(dev); - int dma_size = sizeof(struct bcm_fb_config); - int err; - - sc->dev = dev; + char bootargs[2048], *n, *p, *v; + device_t fbd; + int fbswap; + phandle_t chosen; + struct bcm2835_fb_config fb; + struct bcmsc_softc *sc; + struct fb_info *info; - err = bus_dma_tag_create( - bus_get_dma_tag(sc->dev), - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - dma_size, 1, /* maxsize, nsegments */ - dma_size, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->dma_tag); + sc = device_get_softc(dev); + memset(&fb, 0, sizeof(fb)); + if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0) + return (ENXIO); + fb.bpp = FB_DEPTH; + if (bcm2835_mbox_fb_init(dev, &fb) != 0) + return (ENXIO); - err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, 0, - &sc->dma_map); - if (err) { - device_printf(dev, "cannot allocate framebuffer\n"); - goto fail; + info = malloc(sizeof(struct fb_info), M_DEVBUF, M_WAITOK | M_ZERO); + info->fb_name = device_get_nameunit(dev); + info->fb_vbase = (intptr_t)pmap_mapdev(fb.base, fb.size); + info->fb_pbase = fb.base; + info->fb_size = fb.size; + info->fb_bpp = info->fb_depth = fb.bpp; + info->fb_stride = fb.pitch; + info->fb_width = fb.xres; + info->fb_height = fb.yres; + sc->info = info; + + /* Newer firmware versions needs an inverted color palette. */ + fbswap = 0; + chosen = OF_finddevice("/chosen"); + if (chosen != 0 && + OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { + p = bootargs; + while ((v = strsep(&p, " ")) != NULL) { + if (*v == '\0') + continue; + n = strsep(&v, "="); + if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL) + if (*v == '1') + fbswap = 1; + } + } + if (fbswap) { + switch (info->fb_bpp) { + case 24: + vt_generate_cons_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16); + info->fb_cmsize = 16; + break; + case 32: + vt_generate_cons_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0); + info->fb_cmsize = 16; + break; + } } - err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, - dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); - - if (err) { - device_printf(dev, "cannot load DMA map\n"); - goto fail; + fbd = device_add_child(dev, "fbd", device_get_unit(dev)); + if (fbd == NULL) { + device_printf(dev, "Failed to add fbd child\n"); + free(info, M_DEVBUF); + return (ENXIO); + } else if (device_probe_and_attach(fbd) != 0) { + device_printf(dev, "Failed to attach fbd device\n"); + device_delete_child(dev, fbd); + free(info, M_DEVBUF); + return (ENXIO); } - /* - * We have to wait until interrupts are enabled. - * Mailbox relies on it to get data from VideoCore - */ - sc->init_hook.ich_func = bcm_fb_init; - sc->init_hook.ich_arg = sc; - - if (config_intrhook_establish(&sc->init_hook) != 0) { - device_printf(dev, "failed to establish intrhook\n"); - return (ENOMEM); - } + device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, + fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); + device_printf(dev, + "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", + fbswap, fb.pitch, fb.base, fb.size); return (0); - -fail: - return (ENXIO); -} - -static void -bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) -{ - bus_addr_t *addr; - - if (err) - return; - - addr = (bus_addr_t*)arg; - *addr = PHYS_TO_VCBUS(segs[0].ds_addr); } static struct fb_info * diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index af600ca..5940ad6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -318,6 +318,47 @@ bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag, return (buf); } +static int +bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys, + struct bcm2835_mbox_hdr *msg, size_t len) +{ + int idx; + struct bcm2835_mbox_tag_hdr *tag; + uint8_t *last; + + if ((uint32_t)msg_phys != resp_phys) { + device_printf(dev, "response channel mismatch\n"); + return (EIO); + } + if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) { + device_printf(dev, "mbox response error\n"); + return (EIO); + } + + /* Loop until the end tag. */ + tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1); + last = (uint8_t *)msg + len; + for (idx = 0; tag->tag != 0; idx++) { + if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) { + device_printf(dev, "tag %d response error\n", idx); + return (EIO); + } + /* Clear the response bit. */ + tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE; + + /* Next tag. */ + tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag + + sizeof(*tag) + tag->val_buf_size); + + if ((uint8_t *)tag > last) { + device_printf(dev, "mbox buffer size error\n"); + return (EIO); + } + } + + return (0); +} + int bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on) { @@ -413,3 +454,136 @@ bcm2835_mbox_get_clock_rate(device_t dev, uint32_t clock_id, uint32_t *hz) return (0); } + +int +bcm2835_mbox_fb_get_w_h(device_t dev, struct bcm2835_fb_config *fb) +{ + device_t mbox; + int err; + bus_dma_tag_t msg_tag; + bus_dmamap_t msg_map; + bus_addr_t msg_phys; + struct msg_fb_get_w_h *msg; + uint32_t reg; + + /* get mbox device */ + mbox = devclass_get_device(devclass_find("mbox"), 0); + if (mbox == NULL) { + device_printf(dev, "can't find mbox\n"); + return (ENXIO); + } + + /* Allocate memory for the message */ + msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map, + &msg_phys); + if (msg == NULL) + return (ENOMEM); + + memset(msg, 0, sizeof(*msg)); + msg->hdr.buf_size = sizeof(*msg); + msg->hdr.code = BCM2835_MBOX_CODE_REQ; + BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, GET_PHYSICAL_W_H); + msg->physical_w_h.tag_hdr.val_len = 0; + BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, GET_VIRTUAL_W_H); + msg->virtual_w_h.tag_hdr.val_len = 0; + BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET); + msg->offset.tag_hdr.val_len = 0; + msg->end_tag = 0; + + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE); + MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys); + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD); + MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, ®); + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD); + + err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg)); + if (err == 0) { + fb->xres = msg->physical_w_h.body.resp.width; + fb->yres = msg->physical_w_h.body.resp.height; + fb->vxres = msg->virtual_w_h.body.resp.width; + fb->vyres = msg->virtual_w_h.body.resp.height; + fb->xoffset = msg->offset.body.resp.x; + fb->yoffset = msg->offset.body.resp.y; + } + + bus_dmamap_unload(msg_tag, msg_map); + bus_dmamem_free(msg_tag, msg, msg_map); + bus_dma_tag_destroy(msg_tag); + + return (err); +} + +int +bcm2835_mbox_fb_init(device_t dev, struct bcm2835_fb_config *fb) +{ + device_t mbox; + int err; + bus_dma_tag_t msg_tag; + bus_dmamap_t msg_map; + bus_addr_t msg_phys; + struct msg_fb_setup *msg; + uint32_t reg; + + /* get mbox device */ + mbox = devclass_get_device(devclass_find("mbox"), 0); + if (mbox == NULL) { + device_printf(dev, "can't find mbox\n"); + return (ENXIO); + } + + /* Allocate memory for the message */ + msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map, + &msg_phys); + if (msg == NULL) + return (ENOMEM); + + memset(msg, 0, sizeof(*msg)); + msg->hdr.buf_size = sizeof(*msg); + msg->hdr.code = BCM2835_MBOX_CODE_REQ; + BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, SET_PHYSICAL_W_H); + msg->physical_w_h.body.req.width = fb->xres; + msg->physical_w_h.body.req.height = fb->yres; + BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, SET_VIRTUAL_W_H); + msg->virtual_w_h.body.req.width = fb->vxres; + msg->virtual_w_h.body.req.height = fb->vyres; + BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET); + msg->offset.body.req.x = fb->xoffset; + msg->offset.body.req.y = fb->yoffset; + BCM2835_MBOX_INIT_TAG(&msg->depth, SET_DEPTH); + msg->depth.body.req.bpp = fb->bpp; + BCM2835_MBOX_INIT_TAG(&msg->alpha, SET_ALPHA_MODE); + msg->alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; + BCM2835_MBOX_INIT_TAG(&msg->buffer, ALLOCATE_BUFFER); + msg->buffer.body.req.alignment = PAGE_SIZE; + BCM2835_MBOX_INIT_TAG(&msg->pitch, GET_PITCH); + msg->end_tag = 0; + + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE); + MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys); + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD); + MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, ®); + bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD); + + err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg)); + if (err == 0) { + fb->xres = msg->physical_w_h.body.resp.width; + fb->yres = msg->physical_w_h.body.resp.height; + fb->vxres = msg->virtual_w_h.body.resp.width; + fb->vyres = msg->virtual_w_h.body.resp.height; + fb->xoffset = msg->offset.body.resp.x; + fb->yoffset = msg->offset.body.resp.y; + fb->pitch = msg->pitch.body.resp.pitch; + fb->base = msg->buffer.body.resp.fb_address; + fb->size = msg->buffer.body.resp.fb_size; + } + + bus_dmamap_unload(msg_tag, msg_map); + bus_dmamem_free(msg_tag, msg, msg_map); + bus_dma_tag_destroy(msg_tag); + + return (err); +} diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h index 76f2a16..a425f2a 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h @@ -52,6 +52,12 @@ struct bcm2835_mbox_tag_hdr { uint32_t val_len; }; +#define BCM2835_MBOX_INIT_TAG(tag_, tagid_) do { \ + (tag_)->tag_hdr.tag = BCM2835_MBOX_TAG_##tagid_; \ + (tag_)->tag_hdr.val_buf_size = sizeof((tag_)->body); \ + (tag_)->tag_hdr.val_len = sizeof((tag_)->body.req); \ +} while (0) + #define BCM2835_MBOX_POWER_ID_EMMC 0x00000000 #define BCM2835_MBOX_POWER_ID_UART0 0x00000001 #define BCM2835_MBOX_POWER_ID_UART1 0x00000002 @@ -322,4 +328,151 @@ struct msg_get_max_temperature { uint32_t end_tag; }; +#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003 +#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003 +#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004 + +struct bcm2835_mbox_tag_fb_w_h { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t width; + uint32_t height; + } req; + struct { + uint32_t width; + uint32_t height; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005 +#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005 + +struct bcm2835_mbox_tag_depth { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t bpp; + } req; + struct { + uint32_t bpp; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007 +#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007 + +#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0 +#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1 +#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2 + +struct bcm2835_mbox_tag_alpha_mode { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t alpha; + } req; + struct { + uint32_t alpha; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009 + +struct bcm2835_mbox_tag_virtual_offset { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t x; + uint32_t y; + } req; + struct { + uint32_t x; + uint32_t y; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008 + +struct bcm2835_mbox_tag_pitch { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + uint32_t pitch; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001 + +struct bcm2835_mbox_tag_allocate_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t alignment; + } req; + struct { + uint32_t fb_address; + uint32_t fb_size; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001 + +struct bcm2835_mbox_tag_release_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + } resp; + } body; +}; + +struct bcm2835_fb_config { + uint32_t xres; + uint32_t yres; + uint32_t vxres; + uint32_t vyres; + uint32_t xoffset; + uint32_t yoffset; + uint32_t bpp; + uint32_t pitch; + uint32_t base; + uint32_t size; +}; + +struct msg_fb_get_w_h { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_fb_w_h physical_w_h; + struct bcm2835_mbox_tag_fb_w_h virtual_w_h; + struct bcm2835_mbox_tag_virtual_offset offset; + uint32_t end_tag; +}; + +int bcm2835_mbox_fb_get_w_h(device_t, struct bcm2835_fb_config *); + +struct msg_fb_setup { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_fb_w_h physical_w_h; + struct bcm2835_mbox_tag_fb_w_h virtual_w_h; + struct bcm2835_mbox_tag_virtual_offset offset; + struct bcm2835_mbox_tag_depth depth; + struct bcm2835_mbox_tag_alpha_mode alpha; + struct bcm2835_mbox_tag_allocate_buffer buffer; + struct bcm2835_mbox_tag_pitch pitch; + uint32_t end_tag; +}; + +int bcm2835_mbox_fb_init(device_t, struct bcm2835_fb_config *); + #endif /* _BCM2835_MBOX_PROP_H_ */ diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 1024a48..e950ec6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -68,15 +68,8 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif -/* DMA doesn't yet work with the bcm3826 */ -#ifdef SOC_BCM2836 -#define PIO_MODE 1 -#else -#define PIO_MODE 0 -#endif - static int bcm2835_sdhci_hs = 1; -static int bcm2835_sdhci_pio_mode = PIO_MODE; +static int bcm2835_sdhci_pio_mode = 0; TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs); TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h index cb871f2..7b79b1a 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h @@ -37,14 +37,20 @@ #define BCM2835_VCBUS_IO_BASE 0x7E000000 #define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000 +#ifdef SOC_BCM2836 +#define BCM2835_ARM_IO_BASE 0x3f000000 +#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_UNCACHED +#else #define BCM2835_ARM_IO_BASE 0x20000000 -#define BCM2835_ARM_IO_SIZE 0x02000000 +#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_CACHED +#endif +#define BCM2835_ARM_IO_SIZE 0x01000000 /* * Convert physical address to VC bus address. Should be used * when submitting address over mailbox interface */ -#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_CACHED) +#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_BASE) /* Check whether pa bellong top IO window */ #define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \ @@ -61,6 +67,6 @@ * when address is returned by VC over mailbox interface. e.g. * framebuffer base */ -#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_CACHED) +#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_BASE) #endif /* _BCM2835_VCBUS_H_ */ diff --git a/sys/arm/conf/AML8726 b/sys/arm/conf/AML8726 index 7272db4..a6b4a8e 100644 --- a/sys/arm/conf/AML8726 +++ b/sys/arm/conf/AML8726 @@ -19,43 +19,14 @@ # $FreeBSD$ ident AML8726 + +include "std.armv6" include "../amlogic/aml8726/std.aml8726" options HZ=100 options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) options LINUX_BOOT_ABI -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP index f611e09..ed4aa2d 100644 --- a/sys/arm/conf/ARMADAXP +++ b/sys/arm/conf/ARMADAXP @@ -19,6 +19,8 @@ # $FreeBSD$ ident MV-88F78XX0 + +include "std.armv6" include "../mv/armadaxp/std.mv78x60" options SOC_MV_ARMADAXP @@ -26,36 +28,7 @@ options SOC_MV_ARMADAXP makeoptions WERROR="-Werror" options HZ=1000 -#options SCHED_ULE # ULE scheduler options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/ATMEL b/sys/arm/conf/ATMEL index 572cf4a..2e8da7d 100644 --- a/sys/arm/conf/ATMEL +++ b/sys/arm/conf/ATMEL @@ -6,6 +6,7 @@ ident ATMEL +include "std.arm" include "../at91/std.atmel" # Typical values for most SoCs and board configurations. Will not work for @@ -77,10 +78,24 @@ options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. #options MAC # TrustedBSD MAC Framework #options INCLUDE_CONFIG_FILE # Include this file in kernel -# required for netbooting +# Debugging support. Always need this: +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger +options GDB # Support remote GDB +#options DEADLKRES # Enable the deadlock resolver +#options INVARIANTS # Enable calls of extra sanity checking +#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones + +# NFS root from boopt/dhcp options BOOTP -options BOOTP_COMPAT options BOOTP_NFSROOT +options BOOTP_COMPAT options BOOTP_NFSV3 options BOOTP_WIRED_TO=ate0 @@ -94,20 +109,6 @@ options NO_SWAPPING options NO_SYSCTL_DESCR options RWLOCK_NOINLINE -# Debugging support. Always need this: -options KDB # Enable kernel debugger support. -# For minimum debugger support (stable branch) use: -options KDB_TRACE # Print a stack trace for a panic. -# For full debugger support use this instead: -options DDB # Support DDB. -options GDB # Support remote GDB. -#options DEADLKRES # Enable the deadlock resolver -#options INVARIANTS # Enable calls of extra sanity checking -#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -#options WITNESS # Enable checks to detect deadlocks and cycles -#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed -#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones - # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. @@ -115,7 +116,7 @@ device bpf # Berkeley packet filter # Ethernet device mii # Minimal MII support -device ate # Atmel AT91 Ethernet friver +device ate # Atmel AT91 Ethernet driver # I2C device at91_twi # Atmel AT91 Two-wire Interface diff --git a/sys/arm/conf/AVILA b/sys/arm/conf/AVILA index cbf27a2..b356b35 100644 --- a/sys/arm/conf/AVILA +++ b/sys/arm/conf/AVILA @@ -20,6 +20,7 @@ ident AVILA +include "std.arm" include "../xscale/ixp425/std.ixp425" # NB: memory mapping is defined in std.avila include "../xscale/ixp425/std.avila" diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE index 8234533..997a62e 100644 --- a/sys/arm/conf/BEAGLEBONE +++ b/sys/arm/conf/BEAGLEBONE @@ -23,6 +23,7 @@ ident BEAGLEBONE +include "std.armv6" include "../ti/am335x/std.am335x" makeoptions MODULES_EXTRA="dtb/am335x" @@ -35,38 +36,7 @@ makeoptions MODULES_EXTRA+="opensolaris dtrace dtrace/lockstat dtrace/profile dt options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/BWCT b/sys/arm/conf/BWCT index a9e0e78..d483a00 100644 --- a/sys/arm/conf/BWCT +++ b/sys/arm/conf/BWCT @@ -21,6 +21,7 @@ ident BWCT +include "std.arm" options VERBOSE_INIT_ARM include "../at91/std.bwct" diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA index af29b23..1cf7fb9 100644 --- a/sys/arm/conf/CAMBRIA +++ b/sys/arm/conf/CAMBRIA @@ -20,6 +20,7 @@ ident CAMBRIA +include "std.arm" include "../xscale/ixp425/std.ixp435" # NB: memory mapping is defined in std.avila include "../xscale/ixp425/std.avila" diff --git a/sys/arm/conf/CNS11XXNAS b/sys/arm/conf/CNS11XXNAS index 5ba2217..d906a2b 100644 --- a/sys/arm/conf/CNS11XXNAS +++ b/sys/arm/conf/CNS11XXNAS @@ -20,6 +20,7 @@ ident CNS11XXNAS +include "std.arm" #options PHYSADDR=0x10000000 #options KERNPHYSADDR=0x10200000 #options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm diff --git a/sys/arm/conf/CRB b/sys/arm/conf/CRB index 641ba9f..f5cc932 100644 --- a/sys/arm/conf/CRB +++ b/sys/arm/conf/CRB @@ -19,6 +19,7 @@ ident CRB +include "std.arm" options PHYSADDR=0x00000000 options KERNPHYSADDR=0x00200000 options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD index 945f0ae..8f856bd 100644 --- a/sys/arm/conf/CUBIEBOARD +++ b/sys/arm/conf/CUBIEBOARD @@ -21,41 +21,11 @@ ident CUBIEBOARD +include "std.armv6" include "../allwinner/std.a10" options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/CUBIEBOARD2 b/sys/arm/conf/CUBIEBOARD2 index d370dda..15d028f 100644 --- a/sys/arm/conf/CUBIEBOARD2 +++ b/sys/arm/conf/CUBIEBOARD2 @@ -21,41 +21,11 @@ ident CUBIEBOARD2 +include "std.armv6" include "../allwinner/a20/std.a20" options HZ=100 options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/DB-78XXX b/sys/arm/conf/DB-78XXX index 4fee206..2e7fa36 100644 --- a/sys/arm/conf/DB-78XXX +++ b/sys/arm/conf/DB-78XXX @@ -5,6 +5,7 @@ # ident DB-88F78XX +include "std.arm" include "../mv/discovery/std.db78xxx" options SOC_MV_DISCOVERY diff --git a/sys/arm/conf/DB-88F5XXX b/sys/arm/conf/DB-88F5XXX index 6ccb360..7cc06a0 100644 --- a/sys/arm/conf/DB-88F5XXX +++ b/sys/arm/conf/DB-88F5XXX @@ -5,6 +5,7 @@ # ident DB-88F5XXX +include "std.arm" include "../mv/orion/std.db88f5xxx" options SOC_MV_ORION diff --git a/sys/arm/conf/DB-88F6XXX b/sys/arm/conf/DB-88F6XXX index c59f1c1..afec0e7 100644 --- a/sys/arm/conf/DB-88F6XXX +++ b/sys/arm/conf/DB-88F6XXX @@ -5,6 +5,7 @@ # ident DB-88F6XXX +include "std.arm" include "../mv/kirkwood/std.db88f6xxx" options SOC_MV_KIRKWOOD diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR index aea158c..c6308cd 100644 --- a/sys/arm/conf/DOCKSTAR +++ b/sys/arm/conf/DOCKSTAR @@ -21,6 +21,7 @@ ident DOCKSTAR +include "std.arm" include "../mv/kirkwood/std.db88f6xxx" makeoptions FDT_DTS_FILE=dockstar.dts diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001 index 0448d4f..f97b564 100644 --- a/sys/arm/conf/DREAMPLUG-1001 +++ b/sys/arm/conf/DREAMPLUG-1001 @@ -24,6 +24,7 @@ ident DREAMPLUG-1001 +include "std.arm" include "../mv/kirkwood/std.db88f6xxx" makeoptions FDT_DTS_FILE=dreamplug-1001.dts diff --git a/sys/arm/conf/EA3250 b/sys/arm/conf/EA3250 index d2d691b..bcb8276 100644 --- a/sys/arm/conf/EA3250 +++ b/sys/arm/conf/EA3250 @@ -5,6 +5,7 @@ # ident EA3250 +include "std.arm" include "../lpc/std.lpc" hints "EA3250.hints" diff --git a/sys/arm/conf/EB9200 b/sys/arm/conf/EB9200 index a5ec5eb..bf0c41b 100644 --- a/sys/arm/conf/EB9200 +++ b/sys/arm/conf/EB9200 @@ -16,6 +16,7 @@ ident EB9200 +include "std.arm" include "../at91/std.eb9200" # The AT91 platform doesn't use /boot/loader, so we have to statically wire # hints. diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX index a4690f6..81edae8 100644 --- a/sys/arm/conf/EFIKA_MX +++ b/sys/arm/conf/EFIKA_MX @@ -20,6 +20,7 @@ ident EFIKA_MX +include "std.armv6" include "../freescale/imx/std.imx51" makeoptions WITHOUT_MODULES="ahc" @@ -27,43 +28,13 @@ makeoptions WITHOUT_MODULES="ahc" options SOC_IMX51 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS #options MD_ROOT # MD is a potential root device -options NFSCL # Network Filesystem Client #options NFSD # Network Filesystem Server -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_LABEL # Provides labelization #options COMPAT_FREEBSD5 # Compatible with FreeBSD5 #options COMPAT_FREEBSD6 # Compatible with FreeBSD6 #options COMPAT_FREEBSD7 # Compatible with FreeBSD7 -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM options INCLUDE_CONFIG_FILE # Include this file in kernel -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/EP80219 b/sys/arm/conf/EP80219 index 35bcb17..6f2bef8 100644 --- a/sys/arm/conf/EP80219 +++ b/sys/arm/conf/EP80219 @@ -19,6 +19,7 @@ ident EP80219 +include "std.arm" options PHYSADDR=0xa0000000 options KERNPHYSADDR=0xa0200000 options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm diff --git a/sys/arm/conf/ETHERNUT5 b/sys/arm/conf/ETHERNUT5 index 376336a..f01ea0d 100644 --- a/sys/arm/conf/ETHERNUT5 +++ b/sys/arm/conf/ETHERNUT5 @@ -21,6 +21,7 @@ ident ETHERNUT5 +include "std.arm" include "../at91/std.ethernut5" # To statically compile in device wiring instead of /boot/device.hints diff --git a/sys/arm/conf/EXYNOS5.common b/sys/arm/conf/EXYNOS5.common index cd6e76f..2f96935 100644 --- a/sys/arm/conf/EXYNOS5.common +++ b/sys/arm/conf/EXYNOS5.common @@ -20,6 +20,7 @@ makeoptions WERROR="-Werror" +include "std.armv6" options HZ=100 options SCHED_ULE # ULE scheduler options PREEMPTION # Enable kernel thread preemption diff --git a/sys/arm/conf/GUMSTIX b/sys/arm/conf/GUMSTIX index 97d0ac7..9ba6155 100644 --- a/sys/arm/conf/GUMSTIX +++ b/sys/arm/conf/GUMSTIX @@ -19,6 +19,7 @@ # $FreeBSD$ ident GUMSTIX +include "std.arm" cpu CPU_XSCALE_PXA2X0 # This probably wants to move somewhere else. Maybe we can create a basic diff --git a/sys/arm/conf/HL200 b/sys/arm/conf/HL200 index 3c0f4e8..8d22da5 100644 --- a/sys/arm/conf/HL200 +++ b/sys/arm/conf/HL200 @@ -21,6 +21,7 @@ ident HL200 +include "std.arm" include "../at91/std.hl200" #To statically compile in device wiring instead of /boot/device.hints diff --git a/sys/arm/conf/HL201 b/sys/arm/conf/HL201 index 6a477af..4ec6da3 100644 --- a/sys/arm/conf/HL201 +++ b/sys/arm/conf/HL201 @@ -21,6 +21,7 @@ ident HL201 +include "std.arm" include "../at91/std.hl201" makeoptions MODULES_OVERRIDE="" diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53 index 9f78f30..3275bfc 100644 --- a/sys/arm/conf/IMX53 +++ b/sys/arm/conf/IMX53 @@ -20,47 +20,18 @@ ident IMX53 +include "std.armv6" include "../freescale/imx/std.imx53" options SOC_IMX53 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client #options NFSD # Network Filesystem Server -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_LABEL # Provides labelization #options COMPAT_FREEBSD5 # Compatible with FreeBSD5 #options COMPAT_FREEBSD6 # Compatible with FreeBSD6 #options COMPAT_FREEBSD7 # Compatible with FreeBSD7 -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM options INCLUDE_CONFIG_FILE # Include this file in kernel -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6 index f1baf29..5ead99b 100644 --- a/sys/arm/conf/IMX6 +++ b/sys/arm/conf/IMX6 @@ -19,45 +19,16 @@ # $FreeBSD$ ident IMX6 +include "std.armv6" include "../freescale/imx/std.imx6" options SOC_IMX6 options HZ=500 # Scheduling quantum is 2 milliseconds. options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client #options NFSD # Network Filesystem Server -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_LABEL # Provides labelization -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options INCLUDE_CONFIG_FILE # Include this file in kernel options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/IQ31244 b/sys/arm/conf/IQ31244 index 2066fb8..403a0c2 100644 --- a/sys/arm/conf/IQ31244 +++ b/sys/arm/conf/IQ31244 @@ -19,6 +19,7 @@ ident IQ31244 +include "std.arm" options PHYSADDR=0xa0000000 options KERNPHYSADDR=0xa0200000 options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm diff --git a/sys/arm/conf/KB920X b/sys/arm/conf/KB920X index 1fc23be..6d91ad8 100644 --- a/sys/arm/conf/KB920X +++ b/sys/arm/conf/KB920X @@ -22,6 +22,7 @@ ident KB920X +include "std.arm" include "../at91/std.kb920x" # The AT91 platform doesn't use /boot/loader, so we have to statically wire # hints. diff --git a/sys/arm/conf/LN2410SBC b/sys/arm/conf/LN2410SBC index b2f64a0..ae3c62a 100644 --- a/sys/arm/conf/LN2410SBC +++ b/sys/arm/conf/LN2410SBC @@ -19,6 +19,7 @@ ident LN2410SBC +include "std.arm" include "../samsung/s3c2xx0/std.ln2410sbc" #To statically compile in device wiring instead of /boot/device.hints #hints "GENERIC.hints" # Default places to look for devices. diff --git a/sys/arm/conf/NSLU b/sys/arm/conf/NSLU index e12c5a5..00a2902 100644 --- a/sys/arm/conf/NSLU +++ b/sys/arm/conf/NSLU @@ -21,6 +21,7 @@ ident NSLU +include "std.arm" # XXX What is defined in std.avila does not exactly match the following: #options PHYSADDR=0x10000000 #options KERNPHYSADDR=0x10200000 diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD index e0b5d14..e58c953 100644 --- a/sys/arm/conf/PANDABOARD +++ b/sys/arm/conf/PANDABOARD @@ -27,42 +27,12 @@ ident PANDABOARD hints "PANDABOARD.hints" +include "std.armv6" include "../ti/omap4/pandaboard/std.pandaboard" options HZ=100 options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/QILA9G20 b/sys/arm/conf/QILA9G20 index 7559c31..2f9b609 100644 --- a/sys/arm/conf/QILA9G20 +++ b/sys/arm/conf/QILA9G20 @@ -22,6 +22,7 @@ ident QILA9G20 +include "std.arm" include "../at91/std.qila9g20" #To statically compile in device wiring instead of /boot/device.hints diff --git a/sys/arm/conf/RK3188 b/sys/arm/conf/RK3188 index 64065d3..46bc334 100644 --- a/sys/arm/conf/RK3188 +++ b/sys/arm/conf/RK3188 @@ -20,41 +20,11 @@ ident RK3188 +include "std.armv6" include "../rockchip/std.rk30xx" options HZ=100 options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B index 0604a97..309a499 100644 --- a/sys/arm/conf/RPI-B +++ b/sys/arm/conf/RPI-B @@ -20,43 +20,13 @@ ident RPI-B +include "std.armv6" include "../broadcom/bcm2835/std.rpi" include "../broadcom/bcm2835/std.bcm2835" options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/RPI2 b/sys/arm/conf/RPI2 index 18d97d7..dbb67d9 100644 --- a/sys/arm/conf/RPI2 +++ b/sys/arm/conf/RPI2 @@ -1,5 +1,5 @@ # -# RPI-B -- Custom configuration for the Raspberry Pi +# RPI2 -- Custom configuration for the Raspberry Pi 2 # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: @@ -18,45 +18,15 @@ # # $FreeBSD$ -ident RPI-B +ident RPI2 +include "std.armv6" include "../broadcom/bcm2835/std.rpi" include "../broadcom/bcm2835/std.bcm2836" options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols @@ -130,8 +100,8 @@ device smsc device spibus device bcm2835_spi -#device vchiq -#device sound +device vchiq +device sound # Flattened Device Tree options FDT # Configure using FDT/DTB data diff --git a/sys/arm/conf/SAM9260EK b/sys/arm/conf/SAM9260EK index 7e88ee1..30680c5 100644 --- a/sys/arm/conf/SAM9260EK +++ b/sys/arm/conf/SAM9260EK @@ -21,6 +21,7 @@ ident SAM9260EK +include "std.arm" include "../at91/std.sam9260ek" # To statically compile in device wiring instead of /boot/device.hints @@ -72,10 +73,24 @@ options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. #options MAC # TrustedBSD MAC Framework #options INCLUDE_CONFIG_FILE # Include this file in kernel -# required for netbooting +# Debugging support. Always need this: +#options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +#options DDB # Enable the kernel debugger +#options GDB # Support remote GDB +#options DEADLKRES # Enable the deadlock resolver +#options INVARIANTS # Enable calls of extra sanity checking +#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones + +# NFS root from boopt/dhcp #options BOOTP -#options BOOTP_COMPAT #options BOOTP_NFSROOT +#options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ate0 @@ -92,20 +107,6 @@ options NO_SWAPPING options NO_SYSCTL_DESCR options RWLOCK_NOINLINE -# Debugging support. Always need this: -#options KDB # Enable kernel debugger support. -# For minimum debugger support (stable branch) use: -#options KDB_TRACE # Print a stack trace for a panic. -# For full debugger support use this instead: -#options DDB # Support DDB. -#options GDB # Support remote GDB. -#options DEADLKRES # Enable the deadlock resolver -#options INVARIANTS # Enable calls of extra sanity checking -#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -#options WITNESS # Enable checks to detect deadlocks and cycles -#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed -#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones - # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. diff --git a/sys/arm/conf/SAM9G20EK b/sys/arm/conf/SAM9G20EK index 7f3d15c..4d961c7 100644 --- a/sys/arm/conf/SAM9G20EK +++ b/sys/arm/conf/SAM9G20EK @@ -19,6 +19,7 @@ ident SAM9G20EK +include "std.arm" include "../at91/std.sam9g20ek" #To statically compile in device wiring instead of /boot/device.hints @@ -26,14 +27,10 @@ hints "SAM9G20EK.hints" makeoptions MODULES_OVERRIDE="" makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -options DDB -options KDB options SCHED_4BSD # 4BSD scheduler options INET # InterNETworking #options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme options TMPFS # Efficient memory filesystem options FFS # Berkeley Fast Filesystem #options SOFTUPDATES # Enable FFS soft updates support @@ -46,77 +43,80 @@ options NFSCL # Network Filesystem Client #options NFSD # Network Filesystem Server #options NFSLOCKD # Network Lock Manager #options NFS_ROOT # NFS usable as /, requires NFSCL -#options BOOTP_NFSROOT -#options BOOTP -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ate0 -#options BOOTP_COMPAT - -options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\" - -options ALT_BREAK_TO_DEBUGGER - #options MSDOSFS # MSDOS Filesystem #options CD9660 # ISO 9660 Filesystem #options PROCFS # Process filesystem (requires PSEUDOFS) #options PSEUDOFS # Pseudo-filesystem framework +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme #options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI #options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options MUTEX_NOINLINE -options RWLOCK_NOINLINE -options NO_FFS_SNAPSHOT -options NO_SWAPPING -# Debugging for use in -current +# Debugging support. Always need this: +options KDB # Enable kernel debugger support +options DDB # Enable the kernel debugger #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -device random -device loop -device bpf -device ether -device md +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ate0 -device uart # Serial Ports +options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\" + +# kernel/memory size reduction +options MUTEX_NOINLINE +options NO_FFS_SNAPSHOT +options NO_SWAPPING +options NO_SYSCTL_DESCR +options RWLOCK_NOINLINE + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf # Berkeley packet filter # Ethernet -device ate # Ethernet Driver -device mii +device mii # Minimal MII support +device ate # Atmel AT91 Ethernet driver option AT91_ATE_USE_RMII -device at91_twi # TWI: Two Wire Interface (EEPROM) -device at91_wdt # WDT: Watchdog timer +# I2C +device at91_twi # Atmel AT91 Two-wire Interface +device iic # I2C generic I/O device driver +device iicbus # I2C bus system +device icee -# NAND Flash - Reference design has Samsung 256MB but others possible -device nand # NAND interface on CS3 +# MMC/SD +device at91_mci # Atmel AT91 Multimedia Card Interface +options AT91_MCI_HAS_4WIRE +options AT91_MCI_SLOT_B +device mmc # MMC/SD bus +device mmcsd # MMC/SD memory card +# DataFlash # NOTE: SPI DataFlash and mci/mmc/mmcsd have hardware # confilict on this card. Use one or the other. # see board_sam9g20ek.c - -# SPI: Data Flash -#device at91_spi # SPI: -#device spibus +#device at91_spi # Atmel AT91 Serial Peripheral Interface +#device spibus # SPI bus #device at45d # at45db642 and maybe others -# MMC/SD -device at91_mci -device mmc -device mmcsd -option AT91_MCI_SLOT_B -option AT91_MCI_HAS_4WIRE - -# iic -device iic -device iicbus -device icee +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +device md # Memory "disks" # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) @@ -124,8 +124,12 @@ device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) +# Serial (COM) ports +device uart # Multi-uart driver +options ALT_BREAK_TO_DEBUGGER + # USB support -device ohci # OHCI localbus->USB interface +device ohci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" @@ -154,3 +158,9 @@ device uhid # "Human Interface Devices" #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm + +# watchdog +device at91_wdt # Atmel AT91 Watchdog Timer + +# NAND Flash - Reference design has Samsung 256MB but others possible +device nand # NAND interface on CS3 diff --git a/sys/arm/conf/SAM9X25EK b/sys/arm/conf/SAM9X25EK index 419e456..49afe99 100644 --- a/sys/arm/conf/SAM9X25EK +++ b/sys/arm/conf/SAM9X25EK @@ -21,6 +21,7 @@ ident SAM9X25EK +include "std.arm" include "../at91/std.sam9x25ek" #To statically compile in device wiring instead of /boot/device.hints diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG index 9d8ea26..e013e75 100644 --- a/sys/arm/conf/SHEEVAPLUG +++ b/sys/arm/conf/SHEEVAPLUG @@ -6,6 +6,7 @@ #NO_UNIVERSE ident SHEEVAPLUG +include "std.arm" include "../mv/kirkwood/std.db88f6xxx" options SOC_MV_KIRKWOOD diff --git a/sys/arm/conf/SN9G45 b/sys/arm/conf/SN9G45 index dec6681..bf46503 100644 --- a/sys/arm/conf/SN9G45 +++ b/sys/arm/conf/SN9G45 @@ -21,6 +21,7 @@ ident SN9G45 +include "std.arm" include "../at91/std.sn9g45" #To statically compile in device wiring instead of /boot/device.hints diff --git a/sys/arm/conf/SOCKIT.common b/sys/arm/conf/SOCKIT.common index ac71169..eb87fd6 100644 --- a/sys/arm/conf/SOCKIT.common +++ b/sys/arm/conf/SOCKIT.common @@ -18,6 +18,7 @@ # # $FreeBSD$ +include "std.armv6" include "../altera/socfpga/std.socfpga" makeoptions MODULES_OVERRIDE="" @@ -26,37 +27,6 @@ makeoptions WERROR="-Werror" options HZ=100 options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/TS7800 b/sys/arm/conf/TS7800 index 87a40d5..ab9fe5b 100644 --- a/sys/arm/conf/TS7800 +++ b/sys/arm/conf/TS7800 @@ -5,6 +5,7 @@ # ident TS7800 +include "std.arm" include "../mv/orion/std.ts7800" options SOC_MV_ORION diff --git a/sys/arm/conf/VERSATILEPB b/sys/arm/conf/VERSATILEPB index c02d18c..182e56c 100644 --- a/sys/arm/conf/VERSATILEPB +++ b/sys/arm/conf/VERSATILEPB @@ -22,6 +22,7 @@ ident VERSATILEPB machine arm armv6 cpu CPU_ARM1176 +include "std.armv6" files "../versatile/files.versatile" makeoptions MODULES_OVERRIDE="" @@ -33,38 +34,7 @@ options PHYSADDR=0x00000000 options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) options LINUX_BOOT_ABI # Process metadata passed from Linux boot loaders -options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/VIRT b/sys/arm/conf/VIRT index c4f9405..0f67b84 100644 --- a/sys/arm/conf/VIRT +++ b/sys/arm/conf/VIRT @@ -20,44 +20,12 @@ ident VIRT +include "std.armv6" include "../qemu/std.virt" options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_LABEL # Provides labelization -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev options PLATFORM -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support -options ARM_NEW_PMAP # Enable the new v6 pmap # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID index eda4815..8fb0198 100644 --- a/sys/arm/conf/VYBRID +++ b/sys/arm/conf/VYBRID @@ -19,44 +19,14 @@ # $FreeBSD$ ident VYBRID +include "std.armv6" include "../freescale/vybrid/std.vybrid" makeoptions WERROR="-Werror" options HZ=100 options SCHED_4BSD # 4BSD scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem #options NANDFS # NAND Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support #options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD index 94148f4..7c108a1 100644 --- a/sys/arm/conf/ZEDBOARD +++ b/sys/arm/conf/ZEDBOARD @@ -21,40 +21,11 @@ ident ZEDBOARD +include "std.armv6" include "../xilinx/zedboard/std.zedboard" options SCHED_ULE # ULE scheduler -options PREEMPTION # Enable kernel thread preemption -options INET # InterNETworking -options INET6 # IPv6 communications protocols -options SCTP # Stream Control Transmission Protocol -options FFS # Berkeley Fast Filesystem -options SOFTUPDATES # Enable FFS soft updates support -options UFS_ACL # Support for access control lists -options UFS_DIRHASH # Improve performance on big directories -options UFS_GJOURNAL # Enable gjournal-based UFS journaling -options QUOTA # Enable disk quotas for UFS -options NFSCL # Network Filesystem Client #options NFSSD # Network Filesystem Server -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCL -options MSDOSFS # MSDOS Filesystem -options CD9660 # ISO 9660 Filesystem -options PROCFS # Process filesystem (requires PSEUDOFS) -options PSEUDOFS # Pseudo-filesystem framework -options TMPFS # Efficient memory filesystem -options GEOM_PART_GPT # GUID Partition Tables -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE # ktrace(1) support -options SYSVSHM # SYSV-style shared memory -options SYSVMSG # SYSV-style message queues -options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) -options VFP # Enable floating point hardware support options SMP # Enable multiple cores # Debugging for use in -current diff --git a/sys/arm/conf/std.arm b/sys/arm/conf/std.arm new file mode 100644 index 0000000..88675f0 --- /dev/null +++ b/sys/arm/conf/std.arm @@ -0,0 +1,5 @@ +# Standard kernel config items for all ARMv4/v5 systems. +# +# $FreeBSD$ + + diff --git a/sys/arm/conf/std.armv6 b/sys/arm/conf/std.armv6 new file mode 100644 index 0000000..c06ceae --- /dev/null +++ b/sys/arm/conf/std.armv6 @@ -0,0 +1,38 @@ +# Standard kernel config items for all ARMv6/v7 systems. +# +# $FreeBSD$ + +options PREEMPTION # Enable kernel thread preemption +options INET # InterNETworking +options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme +options GEOM_LABEL # Provides labelization +options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support + +options ARM_NEW_PMAP # Use new pmap code. diff --git a/sys/arm/freescale/imx/imx6_anatop.c b/sys/arm/freescale/imx/imx6_anatop.c index a384501..16a09d3 100644 --- a/sys/arm/freescale/imx/imx6_anatop.c +++ b/sys/arm/freescale/imx/imx6_anatop.c @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include <arm/arm/mpcore_timervar.h> #include <arm/freescale/fsl_ocotpreg.h> #include <arm/freescale/fsl_ocotpvar.h> +#include <arm/freescale/imx/imx_ccmvar.h> #include <arm/freescale/imx/imx6_anatopreg.h> #include <arm/freescale/imx/imx6_anatopvar.h> @@ -116,12 +117,16 @@ static struct imx6_anatop_softc *imx6_anatop_sc; /* * Table of "operating points". * These are combinations of frequency and voltage blessed by Freescale. + * While the datasheet says the ARM voltage can be as low as 925mV at + * 396MHz, it also says that the ARM and SOC voltages can't differ by + * more than 200mV, and the minimum SOC voltage is 1150mV, so that + * dictates the 950mV entry in this table. */ static struct oppt { uint32_t mhz; uint32_t mv; } imx6_oppt_table[] = { -/* { 396, 925}, XXX: need functional ccm code for this speed */ + { 396, 950}, { 792, 1150}, { 852, 1225}, { 996, 1225}, @@ -158,14 +163,15 @@ imx6_anatop_write_4(bus_size_t offset, uint32_t value) static void vdd_set(struct imx6_anatop_softc *sc, int mv) { - int newtarg, oldtarg; + int newtarg, newtargSoc, oldtarg; uint32_t delay, pmureg; static boolean_t init_done = false; /* * The datasheet says VDD_PU and VDD_SOC must be equal, and VDD_ARM - * can't be more than 50mV above or 200mV below them. For now to keep - * things simple we set all three to the same value. + * can't be more than 50mV above or 200mV below them. We keep them the + * same except in the case of the lowest operating point, which is + * handled as a special case below. */ pmureg = imx6_anatop_read_4(IMX6_ANALOG_PMU_REG_CORE); @@ -180,19 +186,29 @@ vdd_set(struct imx6_anatop_softc *sc, int mv) newtarg = (mv - 700) / 25; /* + * The SOC voltage can't go below 1150mV, and thus because of the 200mV + * rule, the ARM voltage can't go below 950mV. The 950 is encoded in + * our oppt table, here we handle the SOC 1150 rule as a special case. + * (1150-700/25=18). + */ + newtargSoc = (newtarg < 18) ? 18 : newtarg; + + /* * The first time through the 3 voltages might not be equal so use a * long conservative delay. After that we need to delay 3uS for every - * 25mV step upward. No need to delay at all when lowering. + * 25mV step upward; we actually delay 6uS because empirically, it works + * and the 3uS per step recommended by the docs doesn't (3uS fails when + * going from 400->1200, but works for smaller changes). */ if (init_done) { if (newtarg == oldtarg) return; else if (newtarg > oldtarg) - delay = (newtarg - oldtarg) * 3; + delay = (newtarg - oldtarg) * 6; else delay = 0; } else { - delay = 700 / 25 * 3; + delay = (700 / 25) * 6; init_done = true; } @@ -205,7 +221,7 @@ vdd_set(struct imx6_anatop_softc *sc, int mv) pmureg |= newtarg << IMX6_ANALOG_PMU_REG0_TARG_SHIFT; pmureg |= newtarg << IMX6_ANALOG_PMU_REG1_TARG_SHIFT; - pmureg |= newtarg << IMX6_ANALOG_PMU_REG2_TARG_SHIFT; + pmureg |= newtargSoc << IMX6_ANALOG_PMU_REG2_TARG_SHIFT; imx6_anatop_write_4(IMX6_ANALOG_PMU_REG_CORE, pmureg); DELAY(delay); @@ -213,24 +229,29 @@ vdd_set(struct imx6_anatop_softc *sc, int mv) } static inline uint32_t -cpufreq_mhz_from_div(struct imx6_anatop_softc *sc, uint32_t div) +cpufreq_mhz_from_div(struct imx6_anatop_softc *sc, uint32_t corediv, + uint32_t plldiv) { - return (sc->refosc_mhz * (div / 2)); + return ((sc->refosc_mhz * (plldiv / 2)) / (corediv + 1)); } -static inline uint32_t -cpufreq_mhz_to_div(struct imx6_anatop_softc *sc, uint32_t cpu_mhz) +static inline void +cpufreq_mhz_to_div(struct imx6_anatop_softc *sc, uint32_t cpu_mhz, + uint32_t *corediv, uint32_t *plldiv) { - return (cpu_mhz / (sc->refosc_mhz / 2)); + *corediv = (cpu_mhz < 650) ? 1 : 0; + *plldiv = ((*corediv + 1) * cpu_mhz) / (sc->refosc_mhz / 2); } static inline uint32_t cpufreq_actual_mhz(struct imx6_anatop_softc *sc, uint32_t cpu_mhz) { + uint32_t corediv, plldiv; - return (cpufreq_mhz_from_div(sc, cpufreq_mhz_to_div(sc, cpu_mhz))); + cpufreq_mhz_to_div(sc, cpu_mhz, &corediv, &plldiv); + return (cpufreq_mhz_from_div(sc, corediv, plldiv)); } static struct oppt * @@ -256,7 +277,7 @@ cpufreq_nearest_oppt(struct imx6_anatop_softc *sc, uint32_t cpu_newmhz) static void cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op) { - uint32_t timeout, wrk32; + uint32_t corediv, plldiv, timeout, wrk32; /* If increasing the frequency, we must first increase the voltage. */ if (op->mhz > sc->cpu_curmhz) { @@ -272,6 +293,7 @@ cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op) * - Wait for the LOCK bit to come on; it takes ~50 loop iterations. * - Turn off bypass mode; cpu should now be running at the new speed. */ + cpufreq_mhz_to_div(sc, op->mhz, &corediv, &plldiv); imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK); imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_SET, @@ -279,7 +301,7 @@ cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op) wrk32 = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM); wrk32 &= ~IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK; - wrk32 |= cpufreq_mhz_to_div(sc, op->mhz); + wrk32 |= plldiv; imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM, wrk32); timeout = 10000; @@ -290,6 +312,7 @@ cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op) imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, IMX6_ANALOG_CCM_PLL_ARM_BYPASS); + imx_ccm_set_cacrr(corediv); /* If lowering the frequency, it is now safe to lower the voltage. */ if (op->mhz < sc->cpu_curmhz) @@ -297,7 +320,7 @@ cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op) sc->cpu_curmhz = op->mhz; /* Tell the mpcore timer that its frequency has changed. */ - arm_tmr_change_frequency( + arm_tmr_change_frequency( cpufreq_actual_mhz(sc, sc->cpu_curmhz) * 1000000 / 2); } @@ -748,11 +771,12 @@ imx6_anatop_probe(device_t dev) uint32_t imx6_get_cpu_clock() { - uint32_t div; + uint32_t corediv, plldiv; - div = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) & + corediv = imx_ccm_get_cacrr(); + plldiv = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) & IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK; - return (cpufreq_mhz_from_div(imx6_anatop_sc, div)); + return (cpufreq_mhz_from_div(imx6_anatop_sc, corediv, plldiv)); } static device_method_t imx6_anatop_methods[] = { diff --git a/sys/arm/freescale/imx/imx6_ccm.c b/sys/arm/freescale/imx/imx6_ccm.c index 8d7f14f..488c55a 100644 --- a/sys/arm/freescale/imx/imx6_ccm.c +++ b/sys/arm/freescale/imx/imx6_ccm.c @@ -320,6 +320,20 @@ imx_ccm_ahb_hz(void) return (132000000); } +uint32_t +imx_ccm_get_cacrr(void) +{ + + return (RD4(ccm_sc, CCM_CACCR)); +} + +void +imx_ccm_set_cacrr(uint32_t divisor) +{ + + WR4(ccm_sc, CCM_CACCR, divisor); +} + static device_method_t ccm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ccm_probe), diff --git a/sys/arm/freescale/imx/imx6_ccmreg.h b/sys/arm/freescale/imx/imx6_ccmreg.h index 31d92ca..85dd372 100644 --- a/sys/arm/freescale/imx/imx6_ccmreg.h +++ b/sys/arm/freescale/imx/imx6_ccmreg.h @@ -29,6 +29,7 @@ #ifndef IMX6_CCMREG_H #define IMX6_CCMREG_H +#define CCM_CACCR 0x010 #define CCM_CSCMR1 0x01C #define SSI1_CLK_SEL_S 10 #define SSI2_CLK_SEL_S 12 @@ -64,6 +65,5 @@ #define CCM_CCGR5 0x07C #define CCM_CCGR6 0x080 #define CCM_CMEOR 0x088 - #endif diff --git a/sys/arm/freescale/imx/imx_ccmvar.h b/sys/arm/freescale/imx/imx_ccmvar.h index f159437..91a3e45 100644 --- a/sys/arm/freescale/imx/imx_ccmvar.h +++ b/sys/arm/freescale/imx/imx_ccmvar.h @@ -53,4 +53,8 @@ void imx_ccm_usb_enable(device_t _usbdev); void imx_ccm_usbphy_enable(device_t _phydev); void imx_ccm_ssi_configure(device_t _ssidev); +/* Routines to get and set the arm clock root divisor register. */ +uint32_t imx_ccm_get_cacrr(void); +void imx_ccm_set_cacrr(uint32_t _divisor); + #endif diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c index bc38330..d6c6d2b 100644 --- a/sys/arm64/arm64/nexus.c +++ b/sys/arm64/arm64/nexus.c @@ -148,6 +148,10 @@ nexus_attach(device_t dev) if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) panic("nexus_probe mem_rman"); + /* Add the ofwbus device */ + /* ARM64TODO: Alternatively add acpi */ + nexus_add_child(dev, 10, "ofwbus", 0); + /* * First, deal with the children we know about already */ diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile index e611063..a955bdf 100644 --- a/sys/boot/efi/boot1/Makefile +++ b/sys/boot/efi/boot1/Makefile @@ -33,6 +33,9 @@ FILESMODE_boot1.efi= ${BINMODE} LDSCRIPT= ${.CURDIR}/../loader/arch/${MACHINE}/ldscript.${MACHINE} LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared +.if ${MACHINE_CPUARCH} == "aarch64" +CFLAGS+= -msoft-float -mgeneral-regs-only +.endif .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" CFLAGS+= -fPIC LDFLAGS+= -Wl,-znocombreloc diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile index 88ca242..d248927 100644 --- a/sys/boot/efi/libefi/Makefile +++ b/sys/boot/efi/libefi/Makefile @@ -6,6 +6,9 @@ INTERNALLIB= SRCS= delay.c efi_console.c efinet.c efipart.c errno.c handles.c \ libefi.c time.c +.if ${MACHINE_CPUARCH} == "aarch64" +CFLAGS+= -msoft-float -mgeneral-regs-only +.endif .if ${MACHINE_ARCH} == "amd64" CFLAGS+= -fPIC -mno-red-zone .endif diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile index 5585f78..06e76a9 100644 --- a/sys/boot/efi/loader/Makefile +++ b/sys/boot/efi/loader/Makefile @@ -38,6 +38,12 @@ CFLAGS+= -I${.CURDIR}/../../.. CFLAGS+= -I${.CURDIR}/../../i386/libi386 CFLAGS+= -DNO_PCI -DEFI +# make buildenv doesn't set DESTDIR, this means LIBSTAND +# will be wrong when crossbuilding. +.if exists(${.OBJDIR}/../../../../lib/libstand/libstand.a) +LIBSTAND= ${.OBJDIR}/../../../../lib/libstand/libstand.a +.endif + .if ${MK_FORTH} != "no" BOOT_FORTH= yes CFLAGS+= -DBOOT_FORTH diff --git a/sys/boot/efi/loader/arch/arm64/Makefile.inc b/sys/boot/efi/loader/arch/arm64/Makefile.inc index e5064cc..82d8cef 100644 --- a/sys/boot/efi/loader/arch/arm64/Makefile.inc +++ b/sys/boot/efi/loader/arch/arm64/Makefile.inc @@ -7,3 +7,5 @@ SRCS+= exec.c \ .PATH: ${.CURDIR}/../../arm64/libarm64 CFLAGS+=-I${.CURDIR}/../../arm64/libarm64 SRCS+= cache.c + +CFLAGS+= -msoft-float -mgeneral-regs-only diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index 93c6059..8044db5 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -59,6 +59,7 @@ EFI_GUID dxe = DXE_SERVICES_TABLE_GUID; EFI_GUID hoblist = HOB_LIST_TABLE_GUID; EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID; EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID; +EFI_GUID fdtdtb = FDT_TABLE_GUID; EFI_STATUS main(int argc, CHAR16 *argv[]) @@ -287,6 +288,8 @@ command_configuration(int argc, char *argv[]) printf("Memory Type Information Table"); else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID))) printf("Debug Image Info Table"); + else if (!memcmp(guid, &fdtdtb, sizeof(EFI_GUID))) + printf("FDT Table"); else printf("Unknown Table (%s)", guid_to_string(guid)); printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c index 44c4d21..ae1e559 100644 --- a/sys/boot/sparc64/loader/main.c +++ b/sys/boot/sparc64/loader/main.c @@ -101,7 +101,7 @@ static inline u_long itlb_get_data_sun4u(u_int, u_int); static int itlb_enter_sun4u(u_int, u_long data, vm_offset_t); static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); static void itlb_relocate_locked0_sun4u(void); -extern vm_offset_t md_load(char *, vm_offset_t *); +extern vm_offset_t md_load(char *, vm_offset_t *, vm_offset_t *); static int sparc64_autoload(void); static ssize_t sparc64_readin(const int, vm_offset_t, const size_t); static ssize_t sparc64_copyin(const void *, vm_offset_t, size_t); @@ -340,7 +340,7 @@ static int __elfN(exec)(struct preloaded_file *fp) { struct file_metadata *fmp; - vm_offset_t mdp; + vm_offset_t mdp, dtbp; Elf_Addr entry; Elf_Ehdr *e; int error; @@ -349,7 +349,7 @@ __elfN(exec)(struct preloaded_file *fp) return (EFTYPE); e = (Elf_Ehdr *)&fmp->md_data; - if ((error = md_load(fp->f_args, &mdp)) != 0) + if ((error = md_load(fp->f_args, &mdp, &dtbp)) != 0) return (error); printf("jumping to kernel entry at %#lx.\n", e->e_entry); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c index d74c2cf..cbccad3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c @@ -2010,7 +2010,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx) error = dsl_dataset_hold_obj(dp, obj, FTAG, &snap); if (error != 0) - return (error); + break; if (snap->ds_dir != origin_head->ds_dir) error = SET_ERROR(EINVAL); if (error == 0) { @@ -2020,7 +2020,11 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx) obj = dsl_dataset_phys(snap)->ds_prev_snap_obj; dsl_dataset_rele(snap, FTAG); if (error != 0) - return (error); + break; + } + if (error != 0) { + dsl_dataset_rele(origin_head, FTAG); + return (error); } } error = dsl_dataset_clone_swap_check_impl(drc->drc_ds, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h index 3fb66c8..c8e3105 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h @@ -261,10 +261,6 @@ VTOZ(vnode_t *vp) } \ } -/* Called on entry to each ZFS vnode and vfs operation that can not return EIO */ -#define ZFS_ENTER_NOERROR(zfsvfs) \ - rrm_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG) - /* Must be called before exiting the vop */ #define ZFS_EXIT(zfsvfs) rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 415db9e..5824828 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -1239,9 +1239,6 @@ zfs_domount(vfs_t *vfsp, char *osname) } vfs_mountedfrom(vfsp, osname); - /* Grab extra reference. */ - VERIFY(VFS_ROOT(vfsp, LK_EXCLUSIVE, &vp) == 0); - VOP_UNLOCK(vp, 0); if (!zfsvfs->z_issnap) zfsctl_create(zfsvfs); @@ -1819,7 +1816,7 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) znode_t *rootzp; int error; - ZFS_ENTER_NOERROR(zfsvfs); + ZFS_ENTER(zfsvfs); error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); if (error == 0) @@ -1994,7 +1991,7 @@ zfs_umount(vfs_t *vfsp, int fflag) /* * Flush all the files. */ - ret = vflush(vfsp, 1, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); + ret = vflush(vfsp, 0, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); if (ret != 0) { if (!zfsvfs->z_issnap) { zfsctl_create(zfsvfs); diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 8696b36..67210ff 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -248,7 +248,7 @@ freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfss { struct statfs *buf, *sp; struct statfs32 stat32; - size_t count, size; + size_t count, size, copycount; int error; count = uap->bufsize / sizeof(struct statfs32); @@ -256,12 +256,13 @@ freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfss error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, uap->flags); if (size > 0) { sp = buf; - while (count > 0 && error == 0) { + copycount = count; + while (copycount > 0 && error == 0) { copy_statfs(sp, &stat32); error = copyout(&stat32, uap->buf, sizeof(stat32)); sp++; uap->buf++; - count--; + copycount--; } free(buf, M_TEMP); } diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 92f4101..1a67f5c 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -43,6 +43,7 @@ dev/iicbus/ds1775.c optional ds1775 powermac dev/iicbus/max6690.c optional max6690 powermac dev/kbd/kbd.c optional sc | vt dev/nand/nfc_fsl.c optional nand mpc85xx +dev/nand/nfc_rb.c optional nand mpc85xx # ofw can be either aim or fdt: fdt case handled in files. aim only powerpc specific. dev/ofw/openfirm.c optional aim dev/ofw/openfirmio.c optional aim diff --git a/sys/conf/options b/sys/conf/options index b698717..6d2a0fa 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -692,6 +692,7 @@ ACPI_DEBUG opt_acpi.h ACPI_MAX_TASKS opt_acpi.h ACPI_MAX_THREADS opt_acpi.h ACPI_DMAR opt_acpi.h +DEV_ACPI opt_acpi.h # ISA support DEV_ISA opt_isa.h diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 1fa94f1..6f63c6e 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -81,16 +82,19 @@ static int mrsas_init_fw(struct mrsas_softc *sc); static int mrsas_setup_raidmap(struct mrsas_softc *sc); static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); static int mrsas_clear_intr(struct mrsas_softc *sc); -static int -mrsas_get_ctrl_info(struct mrsas_softc *sc, - struct mrsas_ctrl_info *ctrl_info); -static int +static int mrsas_get_ctrl_info(struct mrsas_softc *sc); +static void mrsas_update_ext_vd_details(struct mrsas_softc *sc); +static int mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd_to_abort); +static struct mrsas_softc * +mrsas_get_softc_instance(struct cdev *dev, + u_long cmd, caddr_t arg); u_int32_t mrsas_read_reg(struct mrsas_softc *sc, int offset); -u_int8_t +u_int8_t mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cmd); +void mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc); int mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr); int mrsas_init_adapter(struct mrsas_softc *sc); int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc); @@ -102,10 +106,10 @@ int mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); int mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); int mrsas_reset_ctrl(struct mrsas_softc *sc); int mrsas_wait_for_outstanding(struct mrsas_softc *sc); -int +int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); -int +int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd, int size); void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); @@ -122,17 +126,17 @@ void mrsas_teardown_intr(struct mrsas_softc *sc); void mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error); void mrsas_kill_hba(struct mrsas_softc *sc); void mrsas_aen_handler(struct mrsas_softc *sc); -void +void mrsas_write_reg(struct mrsas_softc *sc, int offset, u_int32_t value); -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi); void mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc); -void +void mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd, u_int8_t status); -void +void mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t extStatus); struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc); @@ -175,9 +179,9 @@ typedef struct mrsas_ident { } MRSAS_CTLR_ID; MRSAS_CTLR_ID device_table[] = { - {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "LSI Thunderbolt SAS Controller"}, - {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "LSI Invader SAS Controller"}, - {0x1000, MRSAS_FURY, 0xffff, 0xffff, "LSI Fury SAS Controller"}, + {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "AVAGO Thunderbolt SAS Controller"}, + {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "AVAGO Invader SAS Controller"}, + {0x1000, MRSAS_FURY, 0xffff, 0xffff, "AVAGO Fury SAS Controller"}, {0, 0, 0, 0, NULL} }; @@ -272,6 +276,7 @@ mrsas_disable_intr(struct mrsas_softc *sc) u_int32_t mask = 0xFFFFFFFF; u_int32_t status; + sc->mask_interrupts = 1; mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), mask); /* Dummy read to force pci flush */ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask)); @@ -283,6 +288,7 @@ mrsas_enable_intr(struct mrsas_softc *sc) u_int32_t mask = MFI_FUSION_ENABLE_INTERRUPT_MASK; u_int32_t status; + sc->mask_interrupts = 0; mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), ~0); status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status)); @@ -352,7 +358,7 @@ mrsas_probe(device_t dev) if ((id = mrsas_find_ident(dev)) != NULL) { if (first_ctrl) { - printf("LSI MegaRAID SAS FreeBSD mrsas driver version: %s\n", + printf("AVAGO MegaRAID SAS FreeBSD mrsas driver version: %s\n", MRSAS_VERSION); first_ctrl = 0; } @@ -460,6 +466,11 @@ mrsas_get_tunables(struct mrsas_softc *sc) */ TUNABLE_INT_FETCH("hw.mrsas.debug_level", &sc->mrsas_debug); + /* + * Grab the global variables. + */ + TUNABLE_INT_FETCH("hw.mrsas.lb_pending_cmds", &sc->lb_pending_cmds); + /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mrsas.%d.debug_level", device_get_unit(sc->mrsas_dev)); @@ -1163,6 +1174,12 @@ mrsas_free_mem(struct mrsas_softc *sc) */ if (sc->mrsas_parent_tag != NULL) bus_dma_tag_destroy(sc->mrsas_parent_tag); + + /* + * Free ctrl_info memory + */ + if (sc->ctrl_info != NULL) + free(sc->ctrl_info, M_MRSAS); } /* @@ -1231,6 +1248,43 @@ mrsas_resume(device_t dev) return (0); } +/** + * mrsas_get_softc_instance: Find softc instance based on cmd type + * + * This function will return softc instance based on cmd type. + * In some case, application fire ioctl on required management instance and + * do not provide host_no. Use cdev->si_drv1 to get softc instance for those + * case, else get the softc instance from host_no provided by application in + * user data. + */ + +static struct mrsas_softc * +mrsas_get_softc_instance(struct cdev *dev, u_long cmd, caddr_t arg) +{ + struct mrsas_softc *sc = NULL; + struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; + + if (cmd == MRSAS_IOC_GET_PCI_INFO) { + sc = dev->si_drv1; + } else { + /* + * get the Host number & the softc from data sent by the + * Application + */ + sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no]; + if ((user_ioc->host_no >= mrsas_mgmt_info.max_index) || (sc == NULL)) { + if (sc == NULL) + mrsas_dprint(sc, MRSAS_FAULT, + "There is no Controller number %d .\n", user_ioc->host_no); + else + mrsas_dprint(sc, MRSAS_FAULT, + "Invalid Controller number %d .\n", user_ioc->host_no); + } + } + + return sc; +} + /* * mrsas_ioctl: IOCtl commands entry point. * @@ -1243,19 +1297,12 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, { struct mrsas_softc *sc; int ret = 0, i = 0; + MRSAS_DRV_PCI_INFORMATION *pciDrvInfo; - struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; - - /* get the Host number & the softc from data sent by the Application */ - sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no]; - - if ((mrsas_mgmt_info.max_index == user_ioc->host_no) || (sc == NULL)) { - printf("Please check the controller number\n"); - if (sc == NULL) - printf("There is NO such Host no. %d\n", user_ioc->host_no); - + sc = mrsas_get_softc_instance(dev, cmd, arg); + if (!sc) return ENOENT; - } + if (sc->remove_in_progress) { mrsas_dprint(sc, MRSAS_INFO, "Driver remove or shutdown called.\n"); @@ -1299,6 +1346,22 @@ do_ioctl: case MRSAS_IOC_SCAN_BUS: ret = mrsas_bus_scan(sc); break; + + case MRSAS_IOC_GET_PCI_INFO: + pciDrvInfo = (MRSAS_DRV_PCI_INFORMATION *) arg; + memset(pciDrvInfo, 0, sizeof(MRSAS_DRV_PCI_INFORMATION)); + pciDrvInfo->busNumber = pci_get_bus(sc->mrsas_dev); + pciDrvInfo->deviceNumber = pci_get_slot(sc->mrsas_dev); + pciDrvInfo->functionNumber = pci_get_function(sc->mrsas_dev); + pciDrvInfo->domainID = pci_get_domain(sc->mrsas_dev); + mrsas_dprint(sc, MRSAS_INFO, "pci bus no: %d," + "pci device no: %d, pci function no: %d," + "pci domain ID: %d\n", + pciDrvInfo->busNumber, pciDrvInfo->deviceNumber, + pciDrvInfo->functionNumber, pciDrvInfo->domainID); + ret = 0; + break; + default: mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd); ret = ENOENT; @@ -1328,8 +1391,10 @@ mrsas_poll(struct cdev *dev, int poll_events, struct thread *td) } if (revents == 0) { if (poll_events & (POLLIN | POLLRDNORM)) { + mtx_lock(&sc->aen_lock); sc->mrsas_poll_waiting = 1; selrecord(td, &sc->mrsas_select); + mtx_unlock(&sc->aen_lock); } } return revents; @@ -1387,6 +1452,9 @@ mrsas_isr(void *arg) struct mrsas_softc *sc = irq_context->sc; int status = 0; + if (sc->mask_interrupts) + return; + if (!sc->msix_vectors) { status = mrsas_clear_intr(sc); if (!status) @@ -1424,7 +1492,7 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req; struct mrsas_mpt_cmd *cmd_mpt; struct mrsas_mfi_cmd *cmd_mfi; - u_int8_t arm, reply_descript_type; + u_int8_t reply_descript_type; u_int16_t smid, num_completed; u_int8_t status, extStatus; union desc_value desc_val; @@ -1462,8 +1530,7 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) device_id = cmd_mpt->ccb_ptr->ccb_h.target_id; lbinfo = &sc->load_balance_info[device_id]; if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) { - arm = lbinfo->raid1DevHandle[0] == scsi_io_req->DevHandle ? 0 : 1; - mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[arm]); + mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[cmd_mpt->pd_r1_lb]); cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG; } /* Fall thru and complete IO */ @@ -1608,8 +1675,8 @@ mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t ex static int mrsas_alloc_mem(struct mrsas_softc *sc) { - u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, chain_frame_size, - evt_detail_size, count; + u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, + chain_frame_size, evt_detail_size, count; /* * Allocate parent DMA tag @@ -1861,34 +1928,6 @@ mrsas_setup_raidmap(struct mrsas_softc *sc) { int i; - sc->drv_supported_vd_count = - MRSAS_MAX_LD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL; - sc->drv_supported_pd_count = - MRSAS_MAX_PD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL; - - if (sc->max256vdSupport) { - sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; - sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; - } else { - sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES; - sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; - } - -#if VD_EXT_DEBUG - device_printf(sc->mrsas_dev, "FW supports: max256vdSupport = %s\n", - sc->max256vdSupport ? "YES" : "NO"); - device_printf(sc->mrsas_dev, "FW supports %dVDs %dPDs\n" - "DRIVER supports %dVDs %dPDs \n", - sc->fw_supported_vd_count, sc->fw_supported_pd_count, - sc->drv_supported_vd_count, sc->drv_supported_pd_count); -#endif - - sc->old_map_sz = sizeof(MR_FW_RAID_MAP) + - (sizeof(MR_LD_SPAN_MAP) * (sc->fw_supported_vd_count - 1)); - sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT); - sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) + - (sizeof(MR_LD_SPAN_MAP) * (sc->drv_supported_vd_count - 1)); - for (i = 0; i < 2; i++) { sc->ld_drv_map[i] = (void *)malloc(sc->drv_map_sz, M_MRSAS, M_NOWAIT); @@ -1903,14 +1942,6 @@ mrsas_setup_raidmap(struct mrsas_softc *sc) } } - sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz); - - if (sc->max256vdSupport) - sc->current_map_sz = sc->new_map_sz; - else - sc->current_map_sz = sc->old_map_sz; - - for (int i = 0; i < 2; i++) { if (bus_dma_tag_create(sc->mrsas_parent_tag, 4, 0, @@ -1970,7 +2001,7 @@ ABORT: * get_pdlist, get_ld_list and max_sectors are currently not being used, it * is left here as placeholder. */ -static int +static int mrsas_init_fw(struct mrsas_softc *sc) { @@ -1978,7 +2009,6 @@ mrsas_init_fw(struct mrsas_softc *sc) u_int32_t max_sectors_1; u_int32_t max_sectors_2; u_int32_t tmp_sectors; - struct mrsas_ctrl_info *ctrl_info; u_int32_t scratch_pad_2; int msix_enable = 0; int fw_msix_count = 0; @@ -2040,23 +2070,25 @@ mrsas_init_fw(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n"); return (1); } + sc->ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT); + if (!sc->ctrl_info) { + device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n"); + return (1); + } /* * Get the controller info from FW, so that the MAX VD support * availability can be decided. */ - ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT); - if (!ctrl_info) - device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n"); - - if (mrsas_get_ctrl_info(sc, ctrl_info)) { + if (mrsas_get_ctrl_info(sc)) { device_printf(sc->mrsas_dev, "Unable to get FW ctrl_info.\n"); + return (1); } - sc->max256vdSupport = - (u_int8_t)ctrl_info->adapterOperations3.supportMaxExtLDs; + sc->secure_jbod_support = + (u_int8_t)sc->ctrl_info->adapterOperations3.supportSecurityonJBOD; + + if (sc->secure_jbod_support) + device_printf(sc->mrsas_dev, "FW supports SED \n"); - if (ctrl_info->max_lds > 64) { - sc->max256vdSupport = 1; - } if (mrsas_setup_raidmap(sc) != SUCCESS) { device_printf(sc->mrsas_dev, "Set up RAID map failed.\n"); return (1); @@ -2080,9 +2112,9 @@ mrsas_init_fw(struct mrsas_softc *sc) * calculate max_sectors_1. So the number ended up as zero always. */ tmp_sectors = 0; - max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * - ctrl_info->max_strips_per_io; - max_sectors_2 = ctrl_info->max_request_size; + max_sectors_1 = (1 << sc->ctrl_info->stripe_sz_ops.min) * + sc->ctrl_info->max_strips_per_io; + max_sectors_2 = sc->ctrl_info->max_request_size; tmp_sectors = min(max_sectors_1, max_sectors_2); sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512; @@ -2090,9 +2122,9 @@ mrsas_init_fw(struct mrsas_softc *sc) sc->max_sectors_per_req = tmp_sectors; sc->disableOnlineCtrlReset = - ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; + sc->ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; sc->UnevenSpanSupport = - ctrl_info->adapterOperations2.supportUnevenSpans; + sc->ctrl_info->adapterOperations2.supportUnevenSpans; if (sc->UnevenSpanSupport) { device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n\n", sc->UnevenSpanSupport); @@ -2102,9 +2134,6 @@ mrsas_init_fw(struct mrsas_softc *sc) else sc->fast_path_io = 0; } - if (ctrl_info) - free(ctrl_info, M_MRSAS); - return (0); } @@ -2136,7 +2165,7 @@ mrsas_init_adapter(struct mrsas_softc *sc) max_cmd = sc->max_fw_cmds; /* Determine allocation size of command frames */ - sc->reply_q_depth = ((max_cmd + 1 + 15) / 16 * 16); + sc->reply_q_depth = ((max_cmd + 1 + 15) / 16 * 16) * 2; sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd; sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth); sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1)); @@ -2281,7 +2310,9 @@ mrsas_ioc_init(struct mrsas_softc *sc) init_frame->driver_ver_lo = (bus_addr_t)sc->verbuf_phys_addr; init_frame->driver_ver_hi = 0; } + init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb = 1; init_frame->driver_operations.mfi_capabilities.support_max_255lds = 1; + init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw = 1; phys_addr = (bus_addr_t)sc->ioc_init_phys_mem + 1024; init_frame->queue_info_new_phys_addr_lo = phys_addr; init_frame->data_xfer_len = sizeof(Mpi2IOCInitRequest_t); @@ -2423,7 +2454,7 @@ mrsas_alloc_mpt_cmds(struct mrsas_softc *sc) * This functions fires the command to Firmware by writing to the * inbound_low_queue_port and inbound_high_queue_port. */ -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi) { @@ -2703,7 +2734,6 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) /* Reset not supported, kill adapter */ mrsas_dprint(sc, MRSAS_OCR, "Reset not supported, killing adapter.\n"); mrsas_kill_hba(sc); - sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; retval = FAIL; goto out; } @@ -2788,10 +2818,6 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n"); continue; } - mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); - mrsas_enable_intr(sc); - sc->adprecovery = MRSAS_HBA_OPERATIONAL; - /* Re-fire management commands */ for (j = 0; j < sc->max_fw_cmds; j++) { mpt_cmd = sc->mpt_cmd_list[j]; @@ -2821,9 +2847,18 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) memset(sc->load_balance_info, 0, sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT); + if (mrsas_get_ctrl_info(sc)) { + mrsas_kill_hba(sc); + retval = FAIL; + goto out; + } if (!mrsas_get_map_info(sc)) mrsas_sync_map_info(sc); + mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); + mrsas_enable_intr(sc); + sc->adprecovery = MRSAS_HBA_OPERATIONAL; + /* Adapter reset completed successfully */ device_printf(sc->mrsas_dev, "Reset successful\n"); retval = SUCCESS; @@ -2854,11 +2889,43 @@ out: void mrsas_kill_hba(struct mrsas_softc *sc) { + sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; + pause("mrsas_kill_hba", 1000); mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__); mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_STOP_ADP); /* Flush */ mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)); + mrsas_complete_outstanding_ioctls(sc); +} + +/** + * mrsas_complete_outstanding_ioctls Complete pending IOCTLS after kill_hba + * input: Controller softc + * + * Returns void + */ +void +mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc) +{ + int i; + struct mrsas_mpt_cmd *cmd_mpt; + struct mrsas_mfi_cmd *cmd_mfi; + u_int32_t count, MSIxIndex; + + count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; + for (i = 0; i < sc->max_fw_cmds; i++) { + cmd_mpt = sc->mpt_cmd_list[i]; + + if (cmd_mpt->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) { + cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx]; + if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) { + for (MSIxIndex = 0; MSIxIndex < count; MSIxIndex++) + mrsas_complete_mptmfi_passthru(sc, cmd_mfi, + cmd_mpt->io_request->RaidContext.status); + } + } + } } /* @@ -2945,8 +3012,7 @@ mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd) * supported by the FW. */ static int -mrsas_get_ctrl_info(struct mrsas_softc *sc, - struct mrsas_ctrl_info *ctrl_info) +mrsas_get_ctrl_info(struct mrsas_softc *sc) { int retcode = 0; struct mrsas_mfi_cmd *cmd; @@ -2979,16 +3045,60 @@ mrsas_get_ctrl_info(struct mrsas_softc *sc, dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info); if (!mrsas_issue_polled(sc, cmd)) - memcpy(ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); + memcpy(sc->ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); else retcode = 1; + mrsas_update_ext_vd_details(sc); + mrsas_free_ctlr_info_cmd(sc); mrsas_release_mfi_cmd(cmd); return (retcode); } /* + * mrsas_update_ext_vd_details : Update details w.r.t Extended VD + * input: + * sc - Controller's softc +*/ +static void +mrsas_update_ext_vd_details(struct mrsas_softc *sc) +{ + sc->max256vdSupport = + sc->ctrl_info->adapterOperations3.supportMaxExtLDs; + /* Below is additional check to address future FW enhancement */ + if (sc->ctrl_info->max_lds > 64) + sc->max256vdSupport = 1; + + sc->drv_supported_vd_count = MRSAS_MAX_LD_CHANNELS + * MRSAS_MAX_DEV_PER_CHANNEL; + sc->drv_supported_pd_count = MRSAS_MAX_PD_CHANNELS + * MRSAS_MAX_DEV_PER_CHANNEL; + if (sc->max256vdSupport) { + sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; + sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } else { + sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES; + sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } + + sc->old_map_sz = sizeof(MR_FW_RAID_MAP) + + (sizeof(MR_LD_SPAN_MAP) * + (sc->fw_supported_vd_count - 1)); + sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT); + sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) + + (sizeof(MR_LD_SPAN_MAP) * + (sc->drv_supported_vd_count - 1)); + + sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz); + + if (sc->max256vdSupport) + sc->current_map_sz = sc->new_map_sz; + else + sc->current_map_sz = sc->old_map_sz; +} + +/* * mrsas_alloc_ctlr_info_cmd: Allocates memory for controller info command * input: Adapter soft state * @@ -3763,7 +3873,7 @@ mrsas_get_ld_list(struct mrsas_softc *sc) * memory is initialized to all zeros upon successful loading of the dma * mapped memory. */ -int +int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd, int size) { @@ -3996,10 +4106,12 @@ mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) */ if ((!cmd->abort_aen) && (sc->remove_in_progress == 0)) { sc->mrsas_aen_triggered = 1; + mtx_lock(&sc->aen_lock); if (sc->mrsas_poll_waiting) { sc->mrsas_poll_waiting = 0; selwakeup(&sc->mrsas_select); } + mtx_unlock(&sc->aen_lock); } else cmd->abort_aen = 0; diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 37b6e95..1cfe89e 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Authors: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Authors: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -101,7 +102,7 @@ __FBSDID("$FreeBSD$"); */ #define BYTE_ALIGNMENT 1 #define MRSAS_MAX_NAME_LENGTH 32 -#define MRSAS_VERSION "06.705.10.02-fbsd" +#define MRSAS_VERSION "06.707.04.03-fbsd" #define MRSAS_ULONG_MAX 0xFFFFFFFFFFFFFFFF #define MRSAS_DEFAULT_TIMEOUT 0x14 /* Temporarily set */ #define DONE 0 @@ -813,9 +814,8 @@ typedef struct _MR_DRV_RAID_MAP_ALL { typedef struct _LD_LOAD_BALANCE_INFO { u_int8_t loadBalanceFlag; u_int8_t reserved1; - u_int16_t raid1DevHandle[2]; - mrsas_atomic_t scsi_pending_cmds[2]; - u_int64_t last_accessed_block[2]; + mrsas_atomic_t scsi_pending_cmds[MAX_PHYSICAL_DEVICES]; + u_int64_t last_accessed_block[MAX_PHYSICAL_DEVICES]; } LD_LOAD_BALANCE_INFO, *PLD_LOAD_BALANCE_INFO; /* SPAN_SET is info caclulated from span info from Raid map per ld */ @@ -858,6 +858,9 @@ struct IO_REQUEST_INFO { u_int8_t start_span; u_int8_t reserved; u_int64_t start_row; + /* span[7:5], arm[4:0] */ + u_int8_t span_arm; + u_int8_t pd_after_lb; }; typedef struct _MR_LD_TARGET_SYNC { @@ -1315,6 +1318,13 @@ typedef enum _REGION_TYPE { #define MRSAS_REQ_STATE_TRAN 2 #define MRSAS_REQ_STATE_COMPLETE 3 +typedef enum _MR_SCSI_CMD_TYPE { + READ_WRITE_LDIO = 0, + NON_READ_WRITE_LDIO = 1, + READ_WRITE_SYSPDIO = 2, + NON_READ_WRITE_SYSPDIO = 3, +} MR_SCSI_CMD_TYPE; + enum mrsas_req_flags { MRSAS_DIR_UNKNOWN = 0x1, MRSAS_DIR_IN = 0x2, @@ -1350,6 +1360,7 @@ struct mrsas_mpt_cmd { u_int32_t sync_cmd_idx; u_int32_t index; u_int8_t flags; + u_int8_t pd_r1_lb; u_int8_t load_balance; bus_size_t length; u_int32_t error_code; @@ -1897,9 +1908,26 @@ struct mrsas_ctrl_info { char reserved6[4]; /* 0x7E4 RESERVED FOR IOV */ struct { /* 0x7E8 */ - u_int32_t resrved:5; + u_int32_t supportPersonalityChange:2; + u_int32_t supportThermalPollInterval:1; + u_int32_t supportDisableImmediateIO:1; + u_int32_t supportT10RebuildAssist:1; u_int32_t supportMaxExtLDs:1; - u_int32_t reserved1:26; + u_int32_t supportCrashDump:1; + u_int32_t supportSwZone:1; + u_int32_t supportDebugQueue:1; + u_int32_t supportNVCacheErase:1; + u_int32_t supportForceTo512e:1; + u_int32_t supportHOQRebuild:1; + u_int32_t supportAllowedOpsforDrvRemoval:1; + u_int32_t supportDrvActivityLEDSetting:1; + u_int32_t supportNVDRAM:1; + u_int32_t supportForceFlash:1; + u_int32_t supportDisableSESMonitoring:1; + u_int32_t supportCacheBypassModes:1; + u_int32_t supportSecurityonJBOD:1; + u_int32_t discardCacheDuringLDDelete:1; + u_int32_t reserved:12; } adapterOperations3; u_int8_t pad[0x800 - 0x7EC]; /* 0x7EC */ @@ -1970,7 +1998,10 @@ typedef union _MFI_CAPABILITIES { u_int32_t support_additional_msix:1; u_int32_t support_fastpath_wb:1; u_int32_t support_max_255lds:1; - u_int32_t reserved:28; + u_int32_t support_ndrive_r1_lb:1; + u_int32_t support_core_affinity:1; + u_int32_t security_protocol_cmds_fw:1; + u_int32_t reserved:25; } mfi_capabilities; u_int32_t reg; } MFI_CAPABILITIES; @@ -2413,6 +2444,167 @@ struct mrsas_mgmt_info { int max_index; }; +#define PCI_TYPE0_ADDRESSES 6 +#define PCI_TYPE1_ADDRESSES 2 +#define PCI_TYPE2_ADDRESSES 5 + +typedef struct _MRSAS_DRV_PCI_COMMON_HEADER { + u_int16_t vendorID; + //(ro) + u_int16_t deviceID; + //(ro) + u_int16_t command; + //Device control + u_int16_t status; + u_int8_t revisionID; + //(ro) + u_int8_t progIf; + //(ro) + u_int8_t subClass; + //(ro) + u_int8_t baseClass; + //(ro) + u_int8_t cacheLineSize; + //(ro +) + u_int8_t latencyTimer; + //(ro +) + u_int8_t headerType; + //(ro) + u_int8_t bist; + //Built in self test + + union { + struct _MRSAS_DRV_PCI_HEADER_TYPE_0 { + u_int32_t baseAddresses[PCI_TYPE0_ADDRESSES]; + u_int32_t cis; + u_int16_t subVendorID; + u_int16_t subSystemID; + u_int32_t romBaseAddress; + u_int8_t capabilitiesPtr; + u_int8_t reserved1[3]; + u_int32_t reserved2; + u_int8_t interruptLine; + u_int8_t interruptPin; + //(ro) + u_int8_t minimumGrant; + //(ro) + u_int8_t maximumLatency; + //(ro) + } type0; + + /* + * PCI to PCI Bridge + */ + + struct _MRSAS_DRV_PCI_HEADER_TYPE_1 { + u_int32_t baseAddresses[PCI_TYPE1_ADDRESSES]; + u_int8_t primaryBus; + u_int8_t secondaryBus; + u_int8_t subordinateBus; + u_int8_t secondaryLatency; + u_int8_t ioBase; + u_int8_t ioLimit; + u_int16_t secondaryStatus; + u_int16_t memoryBase; + u_int16_t memoryLimit; + u_int16_t prefetchBase; + u_int16_t prefetchLimit; + u_int32_t prefetchBaseUpper32; + u_int32_t prefetchLimitUpper32; + u_int16_t ioBaseUpper16; + u_int16_t ioLimitUpper16; + u_int8_t capabilitiesPtr; + u_int8_t reserved1[3]; + u_int32_t romBaseAddress; + u_int8_t interruptLine; + u_int8_t interruptPin; + u_int16_t bridgeControl; + } type1; + + /* + * PCI to CARDBUS Bridge + */ + + struct _MRSAS_DRV_PCI_HEADER_TYPE_2 { + u_int32_t socketRegistersBaseAddress; + u_int8_t capabilitiesPtr; + u_int8_t reserved; + u_int16_t secondaryStatus; + u_int8_t primaryBus; + u_int8_t secondaryBus; + u_int8_t subordinateBus; + u_int8_t secondaryLatency; + struct { + u_int32_t base; + u_int32_t limit; + } range [PCI_TYPE2_ADDRESSES - 1]; + u_int8_t interruptLine; + u_int8_t interruptPin; + u_int16_t bridgeControl; + } type2; + } u; + +} MRSAS_DRV_PCI_COMMON_HEADER, *PMRSAS_DRV_PCI_COMMON_HEADER; + +#define MRSAS_DRV_PCI_COMMON_HEADER_SIZE sizeof(MRSAS_DRV_PCI_COMMON_HEADER) //64 bytes + +typedef struct _MRSAS_DRV_PCI_LINK_CAPABILITY { + union { + struct { + u_int32_t linkSpeed:4; + u_int32_t linkWidth:6; + u_int32_t aspmSupport:2; + u_int32_t losExitLatency:3; + u_int32_t l1ExitLatency:3; + u_int32_t rsvdp:6; + u_int32_t portNumber:8; + } bits; + + u_int32_t asUlong; + } u; +} MRSAS_DRV_PCI_LINK_CAPABILITY, *PMRSAS_DRV_PCI_LINK_CAPABILITY; + +#define MRSAS_DRV_PCI_LINK_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_CAPABILITY) + +typedef struct _MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY { + union { + struct { + u_int16_t linkSpeed:4; + u_int16_t negotiatedLinkWidth:6; + u_int16_t linkTrainingError:1; + u_int16_t linkTraning:1; + u_int16_t slotClockConfig:1; + u_int16_t rsvdZ:3; + } bits; + + u_int16_t asUshort; + } u; + u_int16_t reserved; +} MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY, *PMRSAS_DRV_PCI_LINK_STATUS_CAPABILITY; + +#define MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY) + + +typedef struct _MRSAS_DRV_PCI_CAPABILITIES { + MRSAS_DRV_PCI_LINK_CAPABILITY linkCapability; + MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY linkStatusCapability; +} MRSAS_DRV_PCI_CAPABILITIES, *PMRSAS_DRV_PCI_CAPABILITIES; + +#define MRSAS_DRV_PCI_CAPABILITIES_SIZE sizeof(MRSAS_DRV_PCI_CAPABILITIES) + +/* PCI information */ +typedef struct _MRSAS_DRV_PCI_INFORMATION { + u_int32_t busNumber; + u_int8_t deviceNumber; + u_int8_t functionNumber; + u_int8_t interruptVector; + u_int8_t reserved1; + MRSAS_DRV_PCI_COMMON_HEADER pciHeaderInfo; + MRSAS_DRV_PCI_CAPABILITIES capability; + u_int32_t domainID; + u_int8_t reserved2[28]; +} MRSAS_DRV_PCI_INFORMATION, *PMRSAS_DRV_PCI_INFORMATION; + /******************************************************************* * per-instance data ********************************************************************/ @@ -2476,6 +2668,7 @@ struct mrsas_softc { int msix_vectors; int msix_enable; uint32_t msix_reg_offset[16]; + uint8_t mask_interrupts; struct mrsas_mpt_cmd **mpt_cmd_list; struct mrsas_mfi_cmd **mfi_cmd_list; TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head; @@ -2519,6 +2712,7 @@ struct mrsas_softc { bus_dmamap_t evt_detail_dmamap; struct mrsas_evt_detail *evt_detail_mem; bus_addr_t evt_detail_phys_addr; + struct mrsas_ctrl_info *ctrl_info; bus_dma_tag_t ctlr_info_tag; bus_dmamap_t ctlr_info_dmamap; void *ctlr_info_mem; @@ -2546,9 +2740,11 @@ struct mrsas_softc { struct task ev_task; u_int32_t CurLdCount; u_int64_t reset_flags; + int lb_pending_cmds; LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; + u_int8_t secure_jbod_support; u_int8_t max256vdSupport; u_int16_t fw_supported_vd_count; u_int16_t fw_supported_pd_count; diff --git a/sys/dev/mrsas/mrsas_cam.c b/sys/dev/mrsas/mrsas_cam.c index 80ddc39..08f9002 100644 --- a/sys/dev/mrsas/mrsas_cam.c +++ b/sys/dev/mrsas/mrsas_cam.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -57,17 +58,19 @@ __FBSDID("$FreeBSD$"); * Function prototypes */ int mrsas_cam_attach(struct mrsas_softc *sc); -int mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb); +int mrsas_find_io_type(struct cam_sim *sim, union ccb *ccb); int mrsas_bus_scan(struct mrsas_softc *sc); int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim); -int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); int +mrsas_map_request(struct mrsas_softc *sc, + struct mrsas_mpt_cmd *cmd, union ccb *ccb); +int mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb); -int +int mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb, struct cam_sim *sim); -int +int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb, u_int32_t device_id, MRSAS_RAID_SCSI_IO_REQUEST * io_request); @@ -77,10 +80,10 @@ void mrsas_cam_detach(struct mrsas_softc *sc); void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd); void mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi); -void +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, @@ -89,10 +92,10 @@ static void mrsas_freeze_simq(struct mrsas_mpt_cmd *cmd, struct cam_sim *sim); static void mrsas_cam_poll(struct cam_sim *sim); static void mrsas_action(struct cam_sim *sim, union ccb *ccb); static void mrsas_scsiio_timeout(void *data); -static void +static void mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static int32_t +static int32_t mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, union ccb *ccb); struct mrsas_mpt_cmd *mrsas_get_mpt_cmd(struct mrsas_softc *sc); @@ -112,9 +115,9 @@ MR_BuildRaidContext(struct mrsas_softc *sc, extern u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); -extern u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info); +extern u_int16_t +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); extern u_int8_t megasas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, u_int64_t block, u_int32_t count); @@ -315,7 +318,11 @@ mrsas_action(struct cam_sim *sim, union ccb *ccb) ccb->cpi.version_num = 1; ccb->cpi.hba_inquiry = 0; ccb->cpi.target_sprt = 0; +#if (__FreeBSD_version >= 902001) + ccb->cpi.hba_misc = PIM_UNMAPPED; +#else ccb->cpi.hba_misc = 0; +#endif ccb->cpi.hba_eng_cnt = 0; ccb->cpi.max_lun = MRSAS_SCSI_MAX_LUNS; ccb->cpi.unit_number = cam_sim_unit(sim); @@ -323,7 +330,7 @@ mrsas_action(struct cam_sim *sim, union ccb *ccb) ccb->cpi.initiator_id = MRSAS_SCSI_INITIATOR_ID; ccb->cpi.base_transfer_speed = 150000; strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(ccb->cpi.hba_vid, "LSI", HBA_IDLEN); + strncpy(ccb->cpi.hba_vid, "AVAGO", HBA_IDLEN); strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN); ccb->cpi.transport = XPORT_SPI; ccb->cpi.transport_version = 2; @@ -378,8 +385,13 @@ mrsas_scsiio_timeout(void *data) * on OCR enable/disable property of Controller from ocr_thread * context. */ +#if (__FreeBSD_version >= 1000510) callout_reset_sbt(&cmd->cm_callout, SBT_1S * 600, 0, - mrsas_scsiio_timeout, cmd, 0); + mrsas_scsiio_timeout, cmd, 0); +#else + callout_reset(&cmd->cm_callout, (600000 * hz) / 1000, + mrsas_scsiio_timeout, cmd); +#endif sc->do_timedout_reset = 1; if (sc->ocr_thread_active) wakeup(&sc->ocr_chan); @@ -425,8 +437,8 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, } else cmd->flags = MRSAS_DIR_NONE; /* no data */ - /* For FreeBSD 10.0 and higher */ -#if (__FreeBSD_version >= 1000000) +/* For FreeBSD 9.2 and higher */ +#if (__FreeBSD_version >= 902001) /* * XXX We don't yet support physical addresses here. */ @@ -455,6 +467,11 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, if (cmd->length) cmd->data = csio->data_ptr; break; + case CAM_DATA_BIO: + cmd->length = csio->dxfer_len; + if (cmd->length) + cmd->data = csio->data_ptr; + break; default: ccb->ccb_h.status = CAM_REQ_INVALID; goto done; @@ -499,7 +516,9 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, bcopy(csio->cdb_io.cdb_bytes, cmd->io_request->CDB.CDB32, csio->cdb_len); mtx_lock(&sc->raidmap_lock); - if (mrsas_ldio_inq(sim, ccb)) { + /* Check for IO type READ-WRITE targeted for Logical Volume */ + if (mrsas_find_io_type(sim, ccb) == READ_WRITE_LDIO) { + /* Build READ-WRITE IO for Logical Volume */ if (mrsas_build_ldio(sc, cmd, ccb)) { device_printf(sc->mrsas_dev, "Build LDIO failed.\n"); mtx_unlock(&sc->raidmap_lock); @@ -530,8 +549,13 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, /* * Start timer for IO timeout. Default timeout value is 90 second. */ - callout_reset_sbt(&cmd->cm_callout, SBT_1MS * sc->mrsas_io_timeout, 0, +#if (__FreeBSD_version >= 1000510) + callout_reset_sbt(&cmd->cm_callout, SBT_1S * 600, 0, mrsas_scsiio_timeout, cmd, 0); +#else + callout_reset(&cmd->cm_callout, (600000 * hz) / 1000, + mrsas_scsiio_timeout, cmd); +#endif mrsas_atomic_inc(&sc->fw_outstanding); if (mrsas_atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater) @@ -546,20 +570,17 @@ done: } /* - * mrsas_ldio_inq: Determines if IO is read/write or inquiry + * mrsas_find_io_type: Determines if IO is read/write or inquiry * input: pointer to CAM Control Block * * This function determines if the IO is read/write or inquiry. It returns a 1 * if the IO is read/write and 0 if it is inquiry. */ -int -mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb) +int +mrsas_find_io_type(struct cam_sim *sim, union ccb *ccb) { struct ccb_scsiio *csio = &(ccb->csio); - if (cam_sim_bus(sim) == 1) - return (0); - switch (csio->cdb_io.cdb_bytes[0]) { case READ_10: case WRITE_10: @@ -569,9 +590,11 @@ mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb) case WRITE_6: case READ_16: case WRITE_16: - return 1; + return (cam_sim_bus(sim) ? + READ_WRITE_SYSPDIO : READ_WRITE_LDIO); default: - return 0; + return (cam_sim_bus(sim) ? + NON_READ_WRITE_SYSPDIO : NON_READ_WRITE_LDIO); } } @@ -677,7 +700,7 @@ mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, io_request->DataLength = cmd->length; - if (mrsas_map_request(sc, cmd) == SUCCESS) { + if (mrsas_map_request(sc, cmd, ccb) == SUCCESS) { if (cmd->sge_count > MRSAS_MAX_SGL) { device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds" "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); @@ -824,9 +847,10 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, if ((sc->load_balance_info[device_id].loadBalanceFlag) && (io_info.isRead)) { io_info.devHandle = - mrsas_get_updated_dev_handle(&sc->load_balance_info[device_id], - &io_info); + mrsas_get_updated_dev_handle(sc, + &sc->load_balance_info[device_id], &io_info); cmd->load_balance = MRSAS_LOAD_BALANCE_FLAG; + cmd->pd_r1_lb = io_info.pd_after_lb; } else cmd->load_balance = 0; cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; @@ -876,30 +900,49 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, device_id = ccb_h->target_id; map_ptr = sc->ld_drv_map[(sc->map_id & 1)]; - /* Check if this is for system PD */ + /* + * Check if this is RW for system PD or + * it's a NON RW for sys PD and there is NO secure jbod FW support + */ if (cam_sim_bus(sim) == 1 && sc->pd_list[device_id].driveState == MR_PD_STATE_SYSTEM) { - io_request->Function = 0; - io_request->DevHandle = map_ptr->raidMap.devHndlInfo[device_id]. - curDevHdl; - io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec; - io_request->RaidContext.regLockFlags = 0; - io_request->RaidContext.regLockRowLBA = 0; - io_request->RaidContext.regLockLength = 0; - io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD - << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) - io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH; - cmd->request_desc->SCSIIO.RequestFlags = - (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << - MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - cmd->request_desc->SCSIIO.DevHandle = + io_request->DevHandle = map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; + io_request->RaidContext.RAIDFlags = + MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD << + MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; cmd->request_desc->SCSIIO.MSIxIndex = sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0; + if (sc->secure_jbod_support && (mrsas_find_io_type(sim, ccb) == NON_READ_WRITE_SYSPDIO)) { + /* system pd firmware path */ + io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST; + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + } else { + /* system pd fast path */ + io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; + io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec; + io_request->RaidContext.regLockFlags = 0; + io_request->RaidContext.regLockRowLBA = 0; + io_request->RaidContext.regLockLength = 0; + + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << + MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + + /* + * NOTE - For system pd RW cmds only IoFlags will be FAST_PATH + * Because the NON RW cmds will now go via FW Queue + * and not the Exception queue + */ + if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) + io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH; + } } else { + /* FW path for SysPD or LD Non-RW (SCSI management commands) */ io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST; io_request->DevHandle = device_id; cmd->request_desc->SCSIIO.RequestFlags = @@ -911,7 +954,7 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, io_request->LUN[1] = ccb_h->target_lun & 0xF; io_request->DataLength = cmd->length; - if (mrsas_map_request(sc, cmd) == SUCCESS) { + if (mrsas_map_request(sc, cmd, ccb) == SUCCESS) { if (cmd->sge_count > sc->max_num_sge) { device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds" "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); @@ -934,20 +977,25 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, * is built in the callback. If the bus dmamap load is not successful, * cmd->error_code will contain the error code and a 1 is returned. */ -int -mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd) +int +mrsas_map_request(struct mrsas_softc *sc, + struct mrsas_mpt_cmd *cmd, union ccb *ccb) { u_int32_t retcode = 0; struct cam_sim *sim; - int flag = BUS_DMA_NOWAIT; sim = xpt_path_sim(cmd->ccb_ptr->ccb_h.path); if (cmd->data != NULL) { - mtx_lock(&sc->io_lock); /* Map data buffer into bus space */ + mtx_lock(&sc->io_lock); +#if (__FreeBSD_version >= 902001) + retcode = bus_dmamap_load_ccb(sc->data_tag, cmd->data_dmamap, ccb, + mrsas_data_load_cb, cmd, 0); +#else retcode = bus_dmamap_load(sc->data_tag, cmd->data_dmamap, cmd->data, - cmd->length, mrsas_data_load_cb, cmd, flag); + cmd->length, mrsas_data_load_cb, cmd, BUS_DMA_NOWAIT); +#endif mtx_unlock(&sc->io_lock); if (retcode) device_printf(sc->mrsas_dev, "bus_dmamap_load(): retcode = %d\n", retcode); diff --git a/sys/dev/mrsas/mrsas_fp.c b/sys/dev/mrsas/mrsas_fp.c index cd0d57f..7ae5662 100644 --- a/sys/dev/mrsas/mrsas_fp.c +++ b/sys/dev/mrsas/mrsas_fp.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -55,13 +56,13 @@ __FBSDID("$FreeBSD$"); */ u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); u_int8_t -mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, - u_int64_t block, u_int32_t count); -u_int8_t +mrsas_get_best_arm_pd(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); +u_int8_t MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); -u_int8_t +u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, RAID_CONTEXT * pRAID_Context, @@ -70,32 +71,32 @@ u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info); +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); -u_int32_t +u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error); u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); void -mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, - PLD_LOAD_BALANCE_INFO lbInfo); -void +mrsas_update_load_balance_params(struct mrsas_softc *sc, + MR_DRV_RAID_MAP_ALL * map, PLD_LOAD_BALANCE_INFO lbInfo); +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, u_int32_t ld_block_size); -static u_int16_t +static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); -static u_int16_t +static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map); static MR_LD_SPAN * MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); -static u_int8_t +static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map); static MR_SPAN_BLOCK_INFO * @@ -146,6 +147,8 @@ typedef u_int32_t REGION_LEN; #define FALSE 0 #define TRUE 1 +#define LB_PENDING_CMDS_DEFAULT 4 + /* * Related Macros @@ -376,10 +379,9 @@ MR_ValidateMapInfo(struct mrsas_softc *sc) return 1; } if (sc->UnevenSpanSupport) { - printf("Updating span set\n\n"); mr_update_span_set(drv_map, ldSpanInfo); } - mrsas_update_load_balance_params(drv_map, sc->load_balance_info); + mrsas_update_load_balance_params(sc, drv_map, sc->load_balance_info); return 0; } @@ -566,12 +568,12 @@ get_row_from_strip(struct mrsas_softc *sc, else break; } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, (unsigned long long)span_set_Strip, (unsigned long long)span_set_Row, (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, (unsigned long long)span_set->data_row_start + (unsigned long long)span_set_Row + (span_offset - 1)); return (span_set->data_row_start + span_set_Row + (span_offset - 1)); @@ -631,7 +633,7 @@ get_strip_from_row(struct mrsas_softc *sc, } } } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug - get_strip_from_row: returns invalid " "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); return -1; } @@ -679,13 +681,13 @@ get_arm_from_strip(struct mrsas_softc *sc, else break; } - mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO PRL11: get_arm_from_strip: " "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, (long unsigned int)strip, (strip_offset - span_offset)); return (strip_offset - span_offset); } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: - get_arm_from_strip: returns invalid arm" " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); return -1; @@ -723,9 +725,11 @@ get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, * This routine calculates the arm, span and block for the specified stripe and * reference in stripe using spanset * - * Inputs : Logical drive number - * stripRow: Stripe number - * stripRef: Reference in stripe + * Inputs : + * sc - HBA instance + * ld - Logical drive number + * stripRow: Stripe number + * stripRef: Reference in stripe * * Outputs : span - Span number block - Absolute Block * number in the physical disk @@ -785,6 +789,7 @@ mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripR *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; + io_info->span_arm = pRAID_Context->spanArm; return retval; } @@ -831,7 +836,7 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, else if (sc->UnevenSpanSupport) { io_info->IoforUnevenSpan = 1; } else { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," " but there is _NO_ UnevenSpanSupport\n", MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); return FALSE; @@ -858,13 +863,13 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, pdBlock, map, &error_code); if (error_code == 1) { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d. Send IO w/o region lock.\n", __func__, __LINE__); return FALSE; } } if (startlba_span == SPAN_INVALID) { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d for row 0x%llx," "start strip %llx endSrip %llx\n", __func__, __LINE__, (unsigned long long)start_row, (unsigned long long)start_strip, @@ -873,12 +878,12 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, } io_info->start_span = startlba_span; io_info->start_row = start_row; - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: Check Span number from %s %d for row 0x%llx, " " start strip 0x%llx endSrip 0x%llx span 0x%x\n", __func__, __LINE__, (unsigned long long)start_row, (unsigned long long)start_strip, (unsigned long long)endStrip, startlba_span); - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); } else { start_row = mega_div64_32(start_strip, raid->rowDataSize); @@ -1042,7 +1047,7 @@ mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) span_row_width += MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; #if SPAN_DEBUG - printf("LSI Debug span %x rowDataSize %x\n", count, + printf("AVAGO Debug span %x rowDataSize %x\n", count, MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); #endif } @@ -1097,46 +1102,38 @@ mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) /* * mrsas_update_load_balance_params: Update load balance parmas - * Inputs: map pointer - * Load balance info + * Inputs: + * sc - driver softc instance + * drv_map - driver RAID map + * lbInfo - Load balance info * * This function updates the load balance parameters for the LD config of a two * drive optimal RAID-1. */ -void -mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, - PLD_LOAD_BALANCE_INFO lbInfo) +void +mrsas_update_load_balance_params(struct mrsas_softc *sc, + MR_DRV_RAID_MAP_ALL * drv_map, PLD_LOAD_BALANCE_INFO lbInfo) { int ldCount; u_int16_t ld; - u_int32_t pd, arRef; MR_LD_RAID *raid; - for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { - ld = MR_TargetIdToLdGet(ldCount, map); - if (ld >= MAX_LOGICAL_DRIVES) { + if (sc->lb_pending_cmds > 128 || sc->lb_pending_cmds < 1) + sc->lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; + + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { + ld = MR_TargetIdToLdGet(ldCount, drv_map); + if (ld >= MAX_LOGICAL_DRIVES_EXT) { lbInfo[ldCount].loadBalanceFlag = 0; continue; } - raid = MR_LdRaidGet(ld, map); - - /* Two drive Optimal RAID 1 */ - if ((raid->level == 1) && (raid->rowSize == 2) && - (raid->spanDepth == 1) - && raid->ldState == MR_LD_STATE_OPTIMAL) { - lbInfo[ldCount].loadBalanceFlag = 1; - - /* Get the array on which this span is present */ - arRef = MR_LdSpanArrayGet(ld, 0, map); - - /* Get the PD */ - pd = MR_ArPdGet(arRef, 0, map); - /* Get dev handle from PD */ - lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); - pd = MR_ArPdGet(arRef, 1, map); - lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); - } else + raid = MR_LdRaidGet(ld, drv_map); + if ((raid->level != 1) || + (raid->ldState != MR_LD_STATE_OPTIMAL)) { lbInfo[ldCount].loadBalanceFlag = 0; + continue; + } + lbInfo[ldCount].loadBalanceFlag = 1; } } @@ -1152,7 +1149,7 @@ mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, * * Used to set the PD logical block address in CDB for FP IOs. */ -void +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, @@ -1299,6 +1296,7 @@ mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, } /* Fall through normal case, just load LBA here */ u_int8_t val = cdb[1] & 0xE0; + switch (cdb_len) { case 6: cdb[3] = (u_int8_t)(start_blk & 0xff); @@ -1332,57 +1330,94 @@ mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, } /* - * mrsas_get_best_arm: Determine the best spindle arm - * Inputs: Load balance info + * mrsas_get_best_arm_pd: Determine the best spindle arm + * Inputs: + * sc - HBA instance + * lbInfo - Load balance info + * io_info - IO request info * * This function determines and returns the best arm by looking at the * parameters of the last PD access. */ -u_int8_t -mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, - u_int64_t block, u_int32_t count) +u_int8_t +mrsas_get_best_arm_pd(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) { - u_int16_t pend0, pend1; + MR_LD_RAID *raid; + MR_DRV_RAID_MAP_ALL *drv_map; + u_int16_t pend0, pend1, ld; u_int64_t diff0, diff1; - u_int8_t bestArm; + u_int8_t bestArm, pd0, pd1, span, arm; + u_int32_t arRef, span_row_size; + + u_int64_t block = io_info->ldStartBlock; + u_int32_t count = io_info->numBlocks; + + span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) + >> RAID_CTX_SPANARM_SPAN_SHIFT); + arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); + + drv_map = sc->ld_drv_map[(sc->map_id & 1)]; + ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); + raid = MR_LdRaidGet(ld, drv_map); + span_row_size = sc->UnevenSpanSupport ? + SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; + + arRef = MR_LdSpanArrayGet(ld, span, drv_map); + pd0 = MR_ArPdGet(arRef, arm, drv_map); + pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? + (arm + 1 - span_row_size) : arm + 1, drv_map); /* get the pending cmds for the data and mirror arms */ - pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[0]); - pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[1]); + pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd0]); + pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd1]); /* Determine the disk whose head is nearer to the req. block */ - diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); - diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); - bestArm = (diff0 <= diff1 ? 0 : 1); + diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); + diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); + bestArm = (diff0 <= diff1 ? arm : arm ^ 1); - if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) + if ((bestArm == arm && pend0 > pend1 + sc->lb_pending_cmds) || + (bestArm != arm && pend1 > pend0 + sc->lb_pending_cmds)) bestArm ^= 1; /* Update the last accessed block on the correct pd */ - lbInfo->last_accessed_block[bestArm] = block + count - 1; + lbInfo->last_accessed_block[bestArm == arm ? pd0 : pd1] = block + count - 1; + io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; + io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; +#if SPAN_DEBUG + if (arm != bestArm) + printf("AVAGO Debug R1 Load balance occur - span 0x%x arm 0x%x bestArm 0x%x " + "io_info->span_arm 0x%x\n", + span, arm, bestArm, io_info->span_arm); +#endif - return bestArm; + return io_info->pd_after_lb; } /* * mrsas_get_updated_dev_handle: Get the update dev handle - * Inputs: Load balance info io_info pointer + * Inputs: + * sc - Adapter instance soft state + * lbInfo - Load balance info + * io_info - io_info pointer * * This function determines and returns the updated dev handle. */ -u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info) +u_int16_t +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) { - u_int8_t arm, old_arm; + u_int8_t arm_pd; u_int16_t devHandle; + MR_DRV_RAID_MAP_ALL *drv_map; - old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; + drv_map = sc->ld_drv_map[(sc->map_id & 1)]; /* get best new arm */ - arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); - devHandle = lbInfo->raid1DevHandle[arm]; - mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm]); + arm_pd = mrsas_get_best_arm_pd(sc, lbInfo, io_info); + devHandle = MR_PdDevHandleGet(arm_pd, drv_map); + mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); return devHandle; } @@ -1471,6 +1506,7 @@ MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; + io_info->span_arm = pRAID_Context->spanArm; return retval; } diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c index 8e2aead..3c4dbf9 100644 --- a/sys/dev/mrsas/mrsas_ioctl.c +++ b/sys/dev/mrsas/mrsas_ioctl.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -238,7 +239,7 @@ mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) } sense_ptr = (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off); - sense_ptr = ioctl_sense_mem; + *sense_ptr = ioctl_sense_phys_addr; } /* * Set the sync_cmd flag so that the ISR knows not to complete this @@ -296,13 +297,14 @@ out: /* * Release sense buffer */ - if (ioctl_sense_phys_addr) - bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); - if (ioctl_sense_mem != NULL) - bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); - if (ioctl_sense_tag != NULL) - bus_dma_tag_destroy(ioctl_sense_tag); - + if (user_ioc->sense_len) { + if (ioctl_sense_phys_addr) + bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); + if (ioctl_sense_mem != NULL) + bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); + if (ioctl_sense_tag != NULL) + bus_dma_tag_destroy(ioctl_sense_tag); + } /* * Release data buffers */ diff --git a/sys/dev/mrsas/mrsas_ioctl.h b/sys/dev/mrsas/mrsas_ioctl.h index bf05a7d..c43fc6d 100644 --- a/sys/dev/mrsas/mrsas_ioctl.h +++ b/sys/dev/mrsas/mrsas_ioctl.h @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -64,6 +65,7 @@ __FBSDID("$FreeBSD$"); * into a somewhat unique, 32-bit value. */ +#define MRSAS_IOC_GET_PCI_INFO _IOR('M', 7, MRSAS_DRV_PCI_INFORMATION) #define MRSAS_IOC_FIRMWARE_PASS_THROUGH64 _IOWR('M', 1, struct mrsas_iocpacket) #ifdef COMPAT_FREEBSD32 #define MRSAS_IOC_FIRMWARE_PASS_THROUGH32 _IOWR('M', 1, struct mrsas_iocpacket32) diff --git a/sys/dev/mrsas/mrsas_linux.c b/sys/dev/mrsas/mrsas_linux.c index 8a3db0b..15f38c5 100644 --- a/sys/dev/mrsas/mrsas_linux.c +++ b/sys/dev/mrsas/mrsas_linux.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Kashyap Desai, * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Kashyap Desai, - * Sibananda Sahu Support: freebsdraid@lsi.com + * Sibananda Sahu Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ diff --git a/sys/dev/nand/nfc_rb.c b/sys/dev/nand/nfc_rb.c new file mode 100644 index 0000000..64f888a --- /dev/null +++ b/sys/dev/nand/nfc_rb.c @@ -0,0 +1,275 @@ +/*- + * Copyright (C) 2015 Justin Hibbits + * 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. + */ + +/* RouterBoard 600/800 NAND controller driver. */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/time.h> + +#include <machine/bus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/nand/nand.h> +#include <dev/nand/nandbus.h> +#include "nfc_if.h" +#include "gpio_if.h" + +#define RB_NAND_DATA (0x00) + +struct rb_nand_softc { + struct nand_softc nand_dev; + struct resource *sc_mem; + int rid; + device_t sc_gpio; + uint32_t sc_rdy_pin; + uint32_t sc_nce_pin; + uint32_t sc_cle_pin; + uint32_t sc_ale_pin; +}; + +static int rb_nand_attach(device_t); +static int rb_nand_probe(device_t); +static int rb_nand_send_command(device_t, uint8_t); +static int rb_nand_send_address(device_t, uint8_t); +static uint8_t rb_nand_read_byte(device_t); +static void rb_nand_read_buf(device_t, void *, uint32_t); +static void rb_nand_write_buf(device_t, void *, uint32_t); +static int rb_nand_select_cs(device_t, uint8_t); +static int rb_nand_read_rnb(device_t); + +static device_method_t rb_nand_methods[] = { + DEVMETHOD(device_probe, rb_nand_probe), + DEVMETHOD(device_attach, rb_nand_attach), + + DEVMETHOD(nfc_send_command, rb_nand_send_command), + DEVMETHOD(nfc_send_address, rb_nand_send_address), + DEVMETHOD(nfc_read_byte, rb_nand_read_byte), + DEVMETHOD(nfc_read_buf, rb_nand_read_buf), + DEVMETHOD(nfc_write_buf, rb_nand_write_buf), + DEVMETHOD(nfc_select_cs, rb_nand_select_cs), + DEVMETHOD(nfc_read_rnb, rb_nand_read_rnb), + + { 0, 0 }, +}; + +static driver_t rb_nand_driver = { + "nand", + rb_nand_methods, + sizeof(struct rb_nand_softc), +}; + +static devclass_t rb_nand_devclass; +DRIVER_MODULE(rb_nand, ofwbus, rb_nand_driver, rb_nand_devclass, 0, 0); + +#if 0 +static const struct nand_ecc_data rb_ecc = { + .eccsize = 6, + .eccmode = NAND_ECC_SOFT, + .eccbytes = 6, + .eccpositions = { 8, 9, 10, 13, 14, 15 }, +}; +#endif + +static int +rb_nand_probe(device_t dev) +{ + const char *device_type; + + device_type = ofw_bus_get_type(dev); + + if (!device_type || strcmp(device_type, "rb,nand")) + return (ENXIO); + + device_set_desc(dev, "RouterBoard 333/600/800 NAND controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +rb_nand_attach(device_t dev) +{ + struct rb_nand_softc *sc; + phandle_t node; + uint32_t ale[2],cle[2],nce[2],rdy[2]; + int err; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + + if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) { + return (ENXIO); + } + if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) { + return (ENXIO); + } + if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) { + return (ENXIO); + } + if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) { + return (ENXIO); + } + + if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) { + device_printf(dev, "GPIO handles for signals must match.\n"); + return (ENXIO); + } + sc->sc_ale_pin = ale[1]; + sc->sc_cle_pin = cle[1]; + sc->sc_nce_pin = nce[1]; + sc->sc_rdy_pin = rdy[1]; + + sc->sc_gpio = OF_device_from_xref(ale[0]); + if (sc->sc_gpio == NULL) { + device_printf(dev, "No GPIO resource found!\n"); + return (ENXIO); + } + + sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, + RF_ACTIVE); + if (sc->sc_mem == NULL) { + device_printf(dev, "could not allocate resources!\n"); + return (ENXIO); + } + + nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); + + err = nandbus_create(dev); + + return (err); +} + +static int +rb_nand_send_command(device_t dev, uint8_t command) +{ + struct rb_nand_softc *sc; + + nand_debug(NDBG_DRV,"rb_nand: send command %x", command); + + sc = device_get_softc(dev); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 1); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0); + bus_write_1(sc->sc_mem, RB_NAND_DATA, command); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0); + return (0); +} + +static int +rb_nand_send_address(device_t dev, uint8_t addr) +{ + struct rb_nand_softc *sc; + + nand_debug(NDBG_DRV,"rb_nand: send address %x", addr); + + sc = device_get_softc(dev); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 1); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0); + bus_write_1(sc->sc_mem, RB_NAND_DATA, addr); + GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0); + return (0); +} + +static uint8_t +rb_nand_read_byte(device_t dev) +{ + struct rb_nand_softc *sc; + uint8_t data; + + sc = device_get_softc(dev); + data = bus_read_1(sc->sc_mem, RB_NAND_DATA); + + nand_debug(NDBG_DRV,"rb_nand: read %x", data); + + return (data); +} + +static void +rb_nand_read_buf(device_t dev, void* buf, uint32_t len) +{ + struct rb_nand_softc *sc; + + sc = device_get_softc(dev); + + bus_read_region_1(sc->sc_mem, RB_NAND_DATA, buf, len); +} + +static void +rb_nand_write_buf(device_t dev, void* buf, uint32_t len) +{ + struct rb_nand_softc *sc; + int i; + uint8_t *b = (uint8_t*)buf; + + sc = device_get_softc(dev); + + for (i = 0; i < len; i++) { +#ifdef NAND_DEBUG + if (!(i % 16)) + printf("%s", i == 0 ? "rb_nand:\n" : "\n"); + printf(" %x", b[i]); + if (i == len - 1) + printf("\n"); +#endif + bus_write_1(sc->sc_mem, RB_NAND_DATA, b[i]); + } +} + +static int +rb_nand_select_cs(device_t dev, uint8_t cs) +{ + + if (cs > 0) + return (ENODEV); + + return (0); +} + +static int +rb_nand_read_rnb(device_t dev) +{ + struct rb_nand_softc *sc; + uint32_t rdy_bit; + + sc = device_get_softc(dev); + GPIO_PIN_GET(sc->sc_gpio, sc->sc_rdy_pin, &rdy_bit); + + return (rdy_bit); /* ready */ +} diff --git a/sys/dev/ofw/ofwbus.c b/sys/dev/ofw/ofwbus.c index 6a81b6e..670abff 100644 --- a/sys/dev/ofw/ofwbus.c +++ b/sys/dev/ofw/ofwbus.c @@ -69,7 +69,9 @@ struct ofwbus_softc { struct rman sc_mem_rman; }; +#ifndef __aarch64__ static device_identify_t ofwbus_identify; +#endif static device_probe_t ofwbus_probe; static device_attach_t ofwbus_attach; static bus_alloc_resource_t ofwbus_alloc_resource; @@ -78,7 +80,9 @@ static bus_release_resource_t ofwbus_release_resource; static device_method_t ofwbus_methods[] = { /* Device interface */ +#ifndef __aarch64__ DEVMETHOD(device_identify, ofwbus_identify), +#endif DEVMETHOD(device_probe, ofwbus_probe), DEVMETHOD(device_attach, ofwbus_attach), @@ -97,6 +101,7 @@ EARLY_DRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(ofwbus, 1); +#ifndef __aarch64__ static void ofwbus_identify(driver_t *driver, device_t parent) { @@ -108,11 +113,17 @@ ofwbus_identify(driver_t *driver, device_t parent) if (device_find_child(parent, "ofwbus", -1) == NULL) BUS_ADD_CHILD(parent, 0, "ofwbus", -1); } +#endif static int ofwbus_probe(device_t dev) { +#ifdef __aarch64__ + if (OF_peer(0) == 0) + return (ENXIO); +#endif + device_set_desc(dev, "Open Firmware Device Tree"); return (BUS_PROBE_NOWILDCARD); } diff --git a/sys/dev/pccbb/pccbb_pci.c b/sys/dev/pccbb/pccbb_pci.c index 7dca418..a82afa2 100644 --- a/sys/dev/pccbb/pccbb_pci.c +++ b/sys/dev/pccbb/pccbb_pci.c @@ -502,10 +502,26 @@ cbb_chipinit(struct cbb_softc *sc) * properly initialized. * * The TI125X parts have a different register. + * + * Note: Only the lower two nibbles matter. When set + * to 0, the MFUNC{0,1} pins are GPIO, which isn't + * going to work out too well because we specifically + * program these parts to parallel interrupt signalling + * elsewhere. We preserve the upper bits of this + * register since changing them have subtle side effects + * for different variants of the card and are + * extremely difficult to exaustively test. + * + * Also, the TI 1510/1520 changed the default for the MFUNC + * register from 0x0 to 0x1000 to enable IRQSER by default. + * We want to be careful to avoid overriding that, and the + * below test will do that. Should this check prove to be + * too permissive, we should just check against 0 and 0x1000 + * and not touch it otherwise. */ mux = pci_read_config(sc->dev, CBBR_MFUNC, 4); sysctrl = pci_read_config(sc->dev, CBBR_SYSCTRL, 4); - if (mux == 0) { + if ((mux & (CBBM_MFUNC_PIN0 | CBBM_MFUNC_PIN1)) == 0) { mux = (mux & ~CBBM_MFUNC_PIN0) | CBBM_MFUNC_PIN0_INTA; if ((sysctrl & CBBM_SYSCTRL_INTRTIE) == 0) @@ -518,7 +534,8 @@ cbb_chipinit(struct cbb_softc *sc) /* * Disable zoom video. Some machines initialize this * improperly and exerpience has shown that this helps - * prevent strange behavior. + * prevent strange behavior. We don't support zoom + * video anyway, so no harm can come from this. */ pci_write_config(sc->dev, CBBR_MMCTRL, 0, 4); break; diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index e256a5d..4672e55 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -386,7 +386,7 @@ pci_iov_parse_config(struct pcicfg_iov *iov, struct pci_iov_arg *arg, if (error != 0) goto out; - config = nvlist_unpack(packed_config, arg->len); + config = nvlist_unpack(packed_config, arg->len, NV_FLAG_IGNORE_CASE); if (config == NULL) { error = EINVAL; goto out; diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index cd4cc1e..88b8961 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -522,6 +522,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(SIERRA, MC5727, 0), U3G_DEV(SIERRA, MC5727_2, 0), U3G_DEV(SIERRA, MC5728, 0), + U3G_DEV(SIERRA, MC7354, 0), U3G_DEV(SIERRA, MC8700, 0), U3G_DEV(SIERRA, MC8755, 0), U3G_DEV(SIERRA, MC8755_2, 0), diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index 0159520..c0dc79f 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -497,6 +497,7 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = { UFTDI_DEV(FTDI, SCS_DEVICE_5, 0), UFTDI_DEV(FTDI, SCS_DEVICE_6, 0), UFTDI_DEV(FTDI, SCS_DEVICE_7, 0), + UFTDI_DEV(FTDI, SCX8_USB_PHOENIX, 0), UFTDI_DEV(FTDI, SDMUSBQSS, 0), UFTDI_DEV(FTDI, SEMC_DSS20, 0), UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_JTAG_CHECK_STRING), diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c index ae4ed3a..46d08b5 100644 --- a/sys/dev/usb/serial/usb_serial.c +++ b/sys/dev/usb/serial/usb_serial.c @@ -415,8 +415,9 @@ ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) sc->sc_tty = tp; sc->sc_pps.ppscap = PPS_CAPTUREBOTH; - sc->sc_pps.mtx = sc->sc_mtx; - pps_init(&sc->sc_pps); + sc->sc_pps.driver_abi = PPS_ABI_VERSION; + sc->sc_pps.driver_mtx = sc->sc_mtx; + pps_init_abi(&sc->sc_pps); DPRINTF("ttycreate: %s\n", buf); diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index d972bdc..abe2e6f 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1872,6 +1872,7 @@ product FREECOM HDD 0xfc05 Classic SL Hard Drive product FSC E5400 0x1009 PrismGT USB 2.0 WLAN /* Future Technology Devices products */ +product FTDI SCX8_USB_PHOENIX 0x5259 SCx8 USB Phoenix interface product FTDI SERIAL_8U100AX 0x8372 8U100AX Serial product FTDI SERIAL_8U232AM 0x6001 8U232AM Serial product FTDI SERIAL_8U232AM4 0x6004 8U232AM Serial @@ -4029,6 +4030,7 @@ product SIERRA C22 0x6891 C22 product SIERRA E6892 0x6892 E6892 product SIERRA E6893 0x6893 E6893 product SIERRA MC8700 0x68A3 MC8700 +product SIERRA MC7354 0x6820 MC7354 product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA product SIERRA AC313U 0x68aa Sierra Wireless AirCard 313U product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index 9579c61..7b438c7 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -152,11 +152,14 @@ static int wpi_alloc_fwmem(struct wpi_softc *); static void wpi_free_fwmem(struct wpi_softc *); static int wpi_alloc_rx_ring(struct wpi_softc *); static void wpi_update_rx_ring(struct wpi_softc *); +static void wpi_update_rx_ring_ps(struct wpi_softc *); static void wpi_reset_rx_ring(struct wpi_softc *); static void wpi_free_rx_ring(struct wpi_softc *); static int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *, int); static void wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); +static void wpi_update_tx_ring_ps(struct wpi_softc *, + struct wpi_tx_ring *); static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static int wpi_read_eeprom(struct wpi_softc *, @@ -171,9 +174,13 @@ static int wpi_setregdomain(struct ieee80211com *, struct ieee80211_channel[]); static int wpi_read_eeprom_group(struct wpi_softc *, int); static int wpi_add_node_entry_adhoc(struct wpi_softc *); -static void wpi_node_free(struct ieee80211_node *); static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); +static void wpi_node_free(struct ieee80211_node *); +static void wpi_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, int, + int); +static void wpi_restore_node(void *, struct ieee80211_node *); +static void wpi_restore_node_table(struct wpi_softc *, struct wpi_vap *); static int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void wpi_calib_timeout(void *); static void wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *, @@ -228,6 +235,7 @@ static uint16_t wpi_get_active_dwell_time(struct wpi_softc *, static uint16_t wpi_limit_dwell(struct wpi_softc *, uint16_t); static uint16_t wpi_get_passive_dwell_time(struct wpi_softc *, struct ieee80211_channel *); +static uint32_t wpi_get_scan_pause_time(uint32_t, uint16_t); static int wpi_scan(struct wpi_softc *, struct ieee80211_channel *); static int wpi_auth(struct wpi_softc *, struct ieee80211vap *); static int wpi_config_beacon(struct wpi_vap *); @@ -516,11 +524,13 @@ wpi_attach(device_t dev) ic->ic_scan_start = wpi_scan_start; ic->ic_scan_end = wpi_scan_end; ic->ic_set_channel = wpi_set_channel; - sc->sc_scan_curchan = ic->ic_scan_curchan; ic->ic_scan_curchan = wpi_scan_curchan; ic->ic_scan_mindwell = wpi_scan_mindwell; ic->ic_setregdomain = wpi_setregdomain; + sc->sc_update_rx_ring = wpi_update_rx_ring; + sc->sc_update_tx_ring = wpi_update_tx_ring; + wpi_radiotap_attach(sc); callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); @@ -609,7 +619,12 @@ wpi_init_beacon(struct wpi_vap *wvp) cmd->ofdm_mask = 0xff; cmd->cck_mask = 0x0f; cmd->lifetime = htole32(WPI_LIFETIME_INFINITE); - cmd->flags = htole32(WPI_TX_AUTO_SEQ | WPI_TX_INSERT_TSTAMP); + + /* + * XXX WPI_TX_AUTO_SEQ seems to be ignored - workaround this issue + * XXX by using WPI_TX_NEED_ACK instead (with some side effects). + */ + cmd->flags = htole32(WPI_TX_NEED_ACK | WPI_TX_INSERT_TSTAMP); bcn->code = WPI_CMD_SET_BEACON; bcn->ac = WPI_CMD_QUEUE_NUM; @@ -643,6 +658,8 @@ wpi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, /* Override with driver methods. */ vap->iv_key_set = wpi_key_set; vap->iv_key_delete = wpi_key_delete; + wvp->wv_recv_mgmt = vap->iv_recv_mgmt; + vap->iv_recv_mgmt = wpi_recv_mgmt; wvp->wv_newstate = vap->iv_newstate; vap->iv_newstate = wpi_newstate; vap->iv_update_beacon = wpi_update_beacon; @@ -689,8 +706,6 @@ wpi_detach(device_t dev) if (ifp != NULL) { ic = ifp->if_l2com; - ieee80211_draintask(ic, &sc->sc_reinittask); - ieee80211_draintask(ic, &sc->sc_radiooff_task); ieee80211_draintask(ic, &sc->sc_radioon_task); ieee80211_draintask(ic, &sc->sc_start_task); @@ -1086,6 +1101,12 @@ fail: wpi_free_rx_ring(sc); static void wpi_update_rx_ring(struct wpi_softc *sc) { + WPI_WRITE(sc, WPI_FH_RX_WPTR, sc->rxq.cur & ~7); +} + +static void +wpi_update_rx_ring_ps(struct wpi_softc *sc) +{ struct wpi_rx_ring *ring = &sc->rxq; if (ring->update != 0) { @@ -1093,14 +1114,15 @@ wpi_update_rx_ring(struct wpi_softc *sc) return; } - if (WPI_READ(sc, WPI_UCODE_GP1) & WPI_UCODE_GP1_MAC_SLEEP) { + WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s: wakeup request\n", __func__); - - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); ring->update = 1; - } else - WPI_WRITE(sc, WPI_FH_RX_WPTR, ring->cur & ~7); + } else { + wpi_update_rx_ring(sc); + WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + } } static void @@ -1244,19 +1266,27 @@ fail: wpi_free_tx_ring(sc, ring); static void wpi_update_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) { + WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); +} + +static void +wpi_update_tx_ring_ps(struct wpi_softc *sc, struct wpi_tx_ring *ring) +{ + if (ring->update != 0) { /* Wait for INT_WAKEUP event. */ return; } - if (WPI_READ(sc, WPI_UCODE_GP1) & WPI_UCODE_GP1_MAC_SLEEP) { + WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s (%d): requesting wakeup\n", __func__, ring->qid); - - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); ring->update = 1; - } else - WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); + } else { + wpi_update_tx_ring(sc, ring); + WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + } } static void @@ -1276,6 +1306,10 @@ wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) m_freem(data->m); data->m = NULL; } + if (data->ni != NULL) { + ieee80211_free_node(data->ni); + data->ni = NULL; + } } /* Clear TX descriptors. */ memset(ring->desc, 0, ring->desc_dma.size); @@ -1651,6 +1685,72 @@ wpi_node_free(struct ieee80211_node *ni) sc->sc_node_free(ni); } +static __inline int +wpi_check_bss_filter(struct wpi_softc *sc) +{ + return (sc->rxon.filter & htole32(WPI_FILTER_BSS)) != 0; +} + +static void +wpi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, int rssi, + int nf) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct wpi_vap *wvp = WPI_VAP(vap); + uint64_t ni_tstamp, rx_tstamp; + + wvp->wv_recv_mgmt(ni, m, subtype, rssi, nf); + + if (vap->iv_opmode == IEEE80211_M_IBSS && + vap->iv_state == IEEE80211_S_RUN && + (subtype == IEEE80211_FC0_SUBTYPE_BEACON || + subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { + ni_tstamp = le64toh(ni->ni_tstamp.tsf); + rx_tstamp = le64toh(sc->rx_tstamp); + + if (ni_tstamp >= rx_tstamp) { + DPRINTF(sc, WPI_DEBUG_STATE, + "ibss merge, tsf %ju tstamp %ju\n", + (uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp); + (void) ieee80211_ibss_merge(ni); + } + } +} + +static void +wpi_restore_node(void *arg, struct ieee80211_node *ni) +{ + struct wpi_softc *sc = arg; + struct wpi_node *wn = WPI_NODE(ni); + int error; + + WPI_NT_LOCK(sc); + if (wn->id != WPI_ID_UNDEFINED) { + wn->id = WPI_ID_UNDEFINED; + if ((error = wpi_add_ibss_node(sc, ni)) != 0) { + device_printf(sc->sc_dev, + "%s: could not add IBSS node, error %d\n", + __func__, error); + } + } + WPI_NT_UNLOCK(sc); +} + +static void +wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp) +{ + struct ieee80211com *ic = sc->sc_ifp->if_l2com; + + /* Set group keys once. */ + WPI_NT_LOCK(sc); + wvp->wv_gtk = 0; + WPI_NT_UNLOCK(sc); + + ieee80211_iterate_nodes(&ic->ic_sta, wpi_restore_node, sc); + ieee80211_crypto_reload_keys(ic); +} + /** * Called by net80211 when ever there is a change to 80211 state machine */ @@ -1669,20 +1769,21 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); - if (vap->iv_state == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) { + if (vap->iv_state == IEEE80211_S_RUN && nstate < IEEE80211_S_RUN) { if ((error = wpi_set_pslevel(sc, 0, 0, 1)) != 0) { device_printf(sc->sc_dev, "%s: could not set power saving level\n", __func__); return error; } + + wpi_set_led(sc, WPI_LED_LINK, 1, 0); } switch (nstate) { case IEEE80211_S_SCAN: WPI_RXON_LOCK(sc); - if ((sc->rxon.filter & htole32(WPI_FILTER_BSS)) && - vap->iv_opmode != IEEE80211_M_STA) { + if (wpi_check_bss_filter(sc) != 0) { sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { device_printf(sc->sc_dev, @@ -1698,6 +1799,11 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* FALLTHROUGH */ case IEEE80211_S_AUTH: /* + * NB: do not optimize AUTH -> AUTH state transmission - + * this will break powersave with non-QoS AP! + */ + + /* * The node must be registered in the firmware before auth. * Also the associd must be cleared on RUN -> ASSOC * transitions. @@ -1711,13 +1817,36 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) case IEEE80211_S_RUN: /* - * RUN -> RUN transition; Just restart the timers. + * RUN -> RUN transition: + * STA mode: Just restart the timers. + * IBSS mode: Process IBSS merge. */ if (vap->iv_state == IEEE80211_S_RUN) { - WPI_RXON_LOCK(sc); - wpi_calib_timeout(sc); - WPI_RXON_UNLOCK(sc); - break; + if (vap->iv_opmode != IEEE80211_M_IBSS) { + WPI_RXON_LOCK(sc); + wpi_calib_timeout(sc); + WPI_RXON_UNLOCK(sc); + break; + } else { + /* + * Drop the BSS_FILTER bit + * (there is no another way to change bssid). + */ + WPI_RXON_LOCK(sc); + sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); + if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { + device_printf(sc->sc_dev, + "%s: could not send RXON\n", + __func__); + } + WPI_RXON_UNLOCK(sc); + + /* Restore all what was lost. */ + wpi_restore_node_table(sc, wvp); + + /* XXX set conditionally? */ + wpi_updateedca(ic); + } } /* @@ -1749,7 +1878,7 @@ wpi_calib_timeout(void *arg) { struct wpi_softc *sc = arg; - if (!(sc->rxon.filter & htole32(WPI_FILTER_BSS))) + if (wpi_check_bss_filter(sc) == 0) return; wpi_power_calibration(sc); @@ -1843,7 +1972,7 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc, goto fail1; } /* Discard frames that are too short. */ - if (len < sizeof (*wh)) { + if (len < sizeof (struct ieee80211_frame_ack)) { DPRINTF(sc, WPI_DEBUG_RECV, "%s: frame too short: %d\n", __func__, len); goto fail1; @@ -1904,7 +2033,12 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc, m->m_flags |= M_WEP; } - ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); + if (len >= sizeof(struct ieee80211_frame_min)) + ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); + else + ni = NULL; + + sc->rx_tstamp = tail->tstamp; if (ieee80211_radiotap_active(ic)) { struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1957,7 +2091,7 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) struct ieee80211vap *vap; struct ieee80211com *ic; uint32_t status = le32toh(stat->status); - int ackfailcnt = stat->ackfailcnt / 2; /* wpi_mrr_setup() */ + int ackfailcnt = stat->ackfailcnt / WPI_NTRIES_DEFAULT; KASSERT(data->ni != NULL, ("no node")); KASSERT(data->m != NULL, ("no mbuf")); @@ -1966,7 +2100,7 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) DPRINTF(sc, WPI_DEBUG_XMIT, "%s: " "qid %d idx %d retries %d btkillcnt %d rate %x duration %d " - "status %x\n", __func__, desc->qid, desc->idx, ackfailcnt, + "status %x\n", __func__, desc->qid, desc->idx, stat->ackfailcnt, stat->btkillcnt, stat->rate, le32toh(stat->duration), status); /* Unmap and free mbuf. */ @@ -1980,7 +2114,7 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) /* * Update rate control statistics for the node. */ - if ((status & 0xff) != 1) { + if (status & WPI_TX_STATUS_FAIL) { if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); @@ -1990,7 +2124,7 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); } - ieee80211_tx_complete(ni, m, (status & 0xff) != 1); + ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0); WPI_TXQ_STATE_LOCK(sc); ring->queued -= 1; @@ -2048,6 +2182,18 @@ wpi_cmd_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) } wakeup(&ring->cmd[desc->idx]); + + if (desc->type == WPI_CMD_SET_POWER_MODE) { + WPI_TXQ_LOCK(sc); + if (sc->sc_flags & WPI_PS_PATH) { + sc->sc_update_rx_ring = wpi_update_rx_ring_ps; + sc->sc_update_tx_ring = wpi_update_tx_ring_ps; + } else { + sc->sc_update_rx_ring = wpi_update_rx_ring; + sc->sc_update_tx_ring = wpi_update_tx_ring; + } + WPI_TXQ_UNLOCK(sc); + } } static void @@ -2061,7 +2207,7 @@ wpi_notif_intr(struct wpi_softc *sc) bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map, BUS_DMASYNC_POSTREAD); - hw = le32toh(sc->shared->next); + hw = le32toh(sc->shared->next) & 0xfff; hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1; while (sc->rxq.cur != hw) { @@ -2110,23 +2256,57 @@ wpi_notif_intr(struct wpi_softc *sc) { struct wpi_beacon_missed *miss = (struct wpi_beacon_missed *)(desc + 1); - uint32_t misses; + uint32_t expected, misses, received, threshold; bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); + misses = le32toh(miss->consecutive); + expected = le32toh(miss->expected); + received = le32toh(miss->received); + threshold = MAX(2, vap->iv_bmissthreshold); + + DPRINTF(sc, WPI_DEBUG_BMISS, + "%s: beacons missed %u(%u) (received %u/%u)\n", + __func__, misses, le32toh(miss->total), received, + expected); + + if (misses >= threshold || + (received == 0 && expected >= threshold)) { + WPI_RXON_LOCK(sc); + if (callout_pending(&sc->scan_timeout)) { + wpi_cmd(sc, WPI_CMD_SCAN_ABORT, NULL, + 0, 1); + } + WPI_RXON_UNLOCK(sc); + if (vap->iv_state == IEEE80211_S_RUN && + (ic->ic_flags & IEEE80211_F_SCAN) == 0) + ieee80211_beacon_miss(ic); + } - DPRINTF(sc, WPI_DEBUG_STATE, - "%s: beacons missed %d/%d\n", __func__, misses, - le32toh(miss->total)); + break; + } +#ifdef WPI_DEBUG + case WPI_BEACON_SENT: + { + struct wpi_tx_stat *stat = + (struct wpi_tx_stat *)(desc + 1); + uint64_t *tsf = (uint64_t *)(stat + 1); + uint32_t *mode = (uint32_t *)(tsf + 1); + + bus_dmamap_sync(sc->rxq.data_dmat, data->map, + BUS_DMASYNC_POSTREAD); - if (vap->iv_state == IEEE80211_S_RUN && - (ic->ic_flags & IEEE80211_F_SCAN) == 0 && - misses >= vap->iv_bmissthreshold) - ieee80211_beacon_miss(ic); + DPRINTF(sc, WPI_DEBUG_BEACON, + "beacon sent: rts %u, ack %u, btkill %u, rate %u, " + "duration %u, status %x, tsf %ju, mode %x\n", + stat->rtsfailcnt, stat->ackfailcnt, + stat->btkillcnt, stat->rate, le32toh(stat->duration), + le32toh(stat->status), *tsf, *mode); break; } +#endif case WPI_UC_READY: { struct wpi_ucode_info *uc = @@ -2163,46 +2343,53 @@ wpi_notif_intr(struct wpi_softc *sc) WPI_NT_LOCK(sc); wpi_clear_node_table(sc); WPI_NT_UNLOCK(sc); - ieee80211_runtask(ic, &sc->sc_radiooff_task); + taskqueue_enqueue(sc->sc_tq, + &sc->sc_radiooff_task); return; } break; } +#ifdef WPI_DEBUG case WPI_START_SCAN: { bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); -#ifdef WPI_DEBUG + struct wpi_start_scan *scan = (struct wpi_start_scan *)(desc + 1); DPRINTF(sc, WPI_DEBUG_SCAN, "%s: scanning channel %d status %x\n", __func__, scan->chan, le32toh(scan->status)); -#endif + break; } +#endif case WPI_STOP_SCAN: { bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); -#ifdef WPI_DEBUG + struct wpi_stop_scan *scan = (struct wpi_stop_scan *)(desc + 1); + DPRINTF(sc, WPI_DEBUG_SCAN, "scan finished nchan=%d status=%d chan=%d\n", scan->nchan, scan->status, scan->chan); -#endif + WPI_RXON_LOCK(sc); callout_stop(&sc->scan_timeout); WPI_RXON_UNLOCK(sc); - ieee80211_scan_next(vap); + if (scan->status == WPI_SCAN_ABORTED) + ieee80211_cancel_scan(vap); + else + ieee80211_scan_next(vap); break; } } if (sc->rxq.cur % 8 == 0) { /* Tell the firmware what we have processed. */ - wpi_update_rx_ring(sc); + sc->sc_update_rx_ring(sc); } } } @@ -2233,9 +2420,8 @@ wpi_wakeup_intr(struct wpi_softc *sc) wpi_update_tx_ring(sc, ring); } } - WPI_TXQ_UNLOCK(sc); - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + WPI_TXQ_UNLOCK(sc); } /* @@ -2245,8 +2431,7 @@ wpi_wakeup_intr(struct wpi_softc *sc) static void wpi_debug_registers(struct wpi_softc *sc) { -#define COUNTOF(array) (sizeof(array) / sizeof(array[0])) - int i; + size_t i; static const uint32_t csr_tbl[] = { WPI_HW_IF_CONFIG, WPI_INT, @@ -2273,7 +2458,7 @@ wpi_debug_registers(struct wpi_softc *sc) DPRINTF(sc, WPI_DEBUG_REGISTER,"%s","\n"); - for (i = 0; i < COUNTOF(csr_tbl); i++) { + for (i = 0; i < nitems(csr_tbl); i++) { DPRINTF(sc, WPI_DEBUG_REGISTER, " %-18s: 0x%08x ", wpi_get_csr_string(csr_tbl[i]), WPI_READ(sc, csr_tbl[i])); @@ -2283,7 +2468,7 @@ wpi_debug_registers(struct wpi_softc *sc) DPRINTF(sc, WPI_DEBUG_REGISTER, "\n\n"); if (wpi_nic_lock(sc) == 0) { - for (i = 0; i < COUNTOF(prph_tbl); i++) { + for (i = 0; i < nitems(prph_tbl); i++) { DPRINTF(sc, WPI_DEBUG_REGISTER, " %-18s: 0x%08x ", wpi_get_prph_string(prph_tbl[i]), wpi_prph_read(sc, prph_tbl[i])); @@ -2297,7 +2482,6 @@ wpi_debug_registers(struct wpi_softc *sc) DPRINTF(sc, WPI_DEBUG_REGISTER, "Cannot access internal registers.\n"); } -#undef COUNTOF } #endif @@ -2311,8 +2495,6 @@ wpi_fatal_intr(struct wpi_softc *sc) { struct wpi_fw_dump dump; uint32_t i, offset, count; - const uint32_t size_errmsg = - (sizeof (wpi_fw_errmsg) / sizeof ((wpi_fw_errmsg)[0])); /* Check that the error log address is valid. */ if (sc->errptr < WPI_FW_DATA_BASE || @@ -2342,7 +2524,7 @@ wpi_fatal_intr(struct wpi_softc *sc) sizeof (dump) / sizeof (uint32_t)); printf(" error type = \"%s\" (0x%08X)\n", - (dump.desc < size_errmsg) ? + (dump.desc < nitems(wpi_fw_errmsg)) ? wpi_fw_errmsg[dump.desc] : "UNKNOWN", dump.desc); printf(" error data = 0x%08X\n", @@ -2539,7 +2721,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) /* Kick TX ring. */ ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - wpi_update_tx_ring(sc, ring); + sc->sc_update_tx_ring(sc, ring); if (ring->qid < WPI_CMD_QUEUE_NUM) { /* Mark TX ring as full if we reach a certain threshold. */ @@ -2597,7 +2779,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) /* Select EDCA Access Category and TX ring for this frame. */ if (IEEE80211_QOS_HAS_SEQ(wh)) { - qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; + qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; tid = qos & IEEE80211_QOS_TID; } else { qos = 0; @@ -2658,6 +2840,8 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) flags |= WPI_TX_NEED_ACK; } + if (!IEEE80211_QOS_HAS_SEQ(wh)) + flags |= WPI_TX_AUTO_SEQ; if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) flags |= WPI_TX_MORE_FRAG; /* Cannot happen yet. */ @@ -2705,9 +2889,6 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) tx->id = wn->id; } - if (type != IEEE80211_FC0_TYPE_MGT) - tx->data_ntries = tp->maxretry; - if (k != NULL && !swcrypt) { switch (k->wk_cipher->ic_cipher) { case IEEE80211_CIPHER_AES_CCM: @@ -2729,6 +2910,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) tx->ofdm_mask = 0xff; tx->cck_mask = 0x0f; tx->rts_ntries = 7; + tx->data_ntries = tp->maxretry; tx_data.ni = ni; tx_data.m = m; @@ -2764,6 +2946,8 @@ wpi_tx_data_raw(struct wpi_softc *sc, struct mbuf *m, rate = params->ibp_rate0; flags = 0; + if (!IEEE80211_QOS_HAS_SEQ(wh)) + flags |= WPI_TX_AUTO_SEQ; if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) flags |= WPI_TX_NEED_ACK; if (params->ibp_flags & IEEE80211_BPF_RTS) @@ -3089,7 +3273,7 @@ wpi_cmd(struct wpi_softc *sc, int code, const void *buf, size_t size, /* Kick command ring. */ ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - wpi_update_tx_ring(sc, ring); + sc->sc_update_tx_ring(sc, ring); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); @@ -3125,8 +3309,8 @@ wpi_mrr_setup(struct wpi_softc *sc) /* Fallback to the immediate lower CCK rate (if any.) */ mrr.rates[i].next = (i == WPI_RIDX_CCK1) ? WPI_RIDX_CCK1 : i - 1; - /* Try one time at this rate before falling back to "next". */ - mrr.rates[i].ntries = 1; + /* Try twice at this rate before falling back to "next". */ + mrr.rates[i].ntries = WPI_NTRIES_DEFAULT; } /* OFDM rates (not used with 802.11b). */ for (i = WPI_RIDX_OFDM6; i <= WPI_RIDX_OFDM54; i++) { @@ -3138,8 +3322,8 @@ wpi_mrr_setup(struct wpi_softc *sc) ((ic->ic_curmode == IEEE80211_MODE_11A) ? WPI_RIDX_OFDM6 : WPI_RIDX_CCK2) : i - 1; - /* Try one time at this rate before falling back to "next". */ - mrr.rates[i].ntries = 1; + /* Try twice at this rate before falling back to "next". */ + mrr.rates[i].ntries = WPI_NTRIES_DEFAULT; } /* Setup MRR for control frames. */ mrr.which = htole32(WPI_MRR_CTL); @@ -3590,8 +3774,13 @@ wpi_set_pslevel(struct wpi_softc *sc, uint8_t dtim, int level, int async) pmgt = &wpi_pmgt[1][level]; memset(&cmd, 0, sizeof cmd); - if (level != 0) /* not CAM */ + WPI_TXQ_LOCK(sc); + if (level != 0) { /* not CAM */ cmd.flags |= htole16(WPI_PS_ALLOW_SLEEP); + sc->sc_flags |= WPI_PS_PATH; + } else + sc->sc_flags &= ~WPI_PS_PATH; + WPI_TXQ_UNLOCK(sc); /* Retrieve PCIe Active State Power Management (ASPM). */ reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1); if (!(reg & 0x1)) /* L0s Entry disabled. */ @@ -3644,7 +3833,7 @@ wpi_send_rxon(struct wpi_softc *sc, int assoc, int async) if (async) WPI_RXON_LOCK_ASSERT(sc); - if (assoc && (sc->rxon.filter & htole32(WPI_FILTER_BSS))) { + if (assoc && wpi_check_bss_filter(sc) != 0) { struct wpi_assoc rxon_assoc; rxon_assoc.flags = sc->rxon.flags; @@ -3710,7 +3899,7 @@ wpi_config(struct wpi_softc *sc) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t flags; + struct ieee80211_channel *c = ic->ic_curchan; int error; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -3734,9 +3923,9 @@ wpi_config(struct wpi_softc *sc) IEEE80211_ADDR_COPY(sc->rxon.myaddr, vap->iv_myaddr); /* Set default channel. */ - sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_curchan); + sc->rxon.chan = ieee80211_chan2ieee(ic, c); sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) + if (IEEE80211_IS_CHAN_2GHZ(c)) sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); sc->rxon.filter = WPI_FILTER_MULTICAST; @@ -3754,7 +3943,6 @@ wpi_config(struct wpi_softc *sc) sc->rxon.filter |= WPI_FILTER_ASSOC | WPI_FILTER_PROMISC; break; case IEEE80211_M_AHDEMO: - /* XXX workaround for passive channels selection */ sc->rxon.mode = WPI_MODE_HOSTAP; break; case IEEE80211_M_MONITOR: @@ -3770,6 +3958,14 @@ wpi_config(struct wpi_softc *sc) sc->rxon.cck_mask = 0x0f; /* not yet negotiated */ sc->rxon.ofdm_mask = 0xff; /* not yet negotiated */ + /* XXX Current configuration may be unusable. */ + if (IEEE80211_IS_CHAN_NOADHOC(c) && sc->rxon.mode == WPI_MODE_IBSS) { + device_printf(sc->sc_dev, + "%s: invalid channel (%d) selected for IBSS mode\n", + __func__, ieee80211_chan2ieee(ic, c)); + return EINVAL; + } + if ((error = wpi_send_rxon(sc, 0, 0)) != 0) { device_printf(sc->sc_dev, "%s: could not send RXON\n", __func__); @@ -3783,15 +3979,6 @@ wpi_config(struct wpi_softc *sc) return error; } - /* Disable beacon notifications (unused). */ - flags = WPI_STATISTICS_BEACON_DISABLE; - error = wpi_cmd(sc, WPI_CMD_GET_STATISTICS, &flags, sizeof flags, 1); - if (error != 0) { - device_printf(sc->sc_dev, - "could not disable beacon statistics, error %d\n", error); - return error; - } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); return 0; @@ -3813,7 +4000,7 @@ wpi_get_active_dwell_time(struct wpi_softc *sc, } /* - * Limit the total dwell time to 85% of the beacon interval. + * Limit the total dwell time. * * Returns the dwell time in milliseconds. */ @@ -3838,11 +4025,11 @@ wpi_limit_dwell(struct wpi_softc *sc, uint16_t dwell_time) if (bintval > 0) { DPRINTF(sc, WPI_DEBUG_SCAN, "%s: bintval=%d\n", __func__, bintval); - return (MIN(WPI_PASSIVE_DWELL_BASE, ((bintval * 85) / 100))); + return (MIN(dwell_time, bintval - WPI_CHANNEL_TUNE_TIME * 2)); } /* No association context? Default. */ - return (WPI_PASSIVE_DWELL_BASE); + return dwell_time; } static uint16_t @@ -3859,6 +4046,18 @@ wpi_get_passive_dwell_time(struct wpi_softc *sc, struct ieee80211_channel *c) return (wpi_limit_dwell(sc, passive)); } +static uint32_t +wpi_get_scan_pause_time(uint32_t time, uint16_t bintval) +{ + uint32_t mod = (time % bintval) * IEEE80211_DUR_TU; + uint32_t nbeacons = time / bintval; + + if (mod > WPI_PAUSE_MAX_TIME) + mod = WPI_PAUSE_MAX_TIME; + + return WPI_PAUSE_SCAN(nbeacons, mod); +} + /* * Send a scan request to the firmware. */ @@ -3877,7 +4076,7 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) struct ieee80211_rateset *rs; uint16_t dwell_active, dwell_passive; uint8_t *buf, *frm; - int buflen, error, i, nssid; + int bgscan, bintval, buflen, error, i, nssid; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -3888,10 +4087,16 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) if (callout_pending(&sc->scan_timeout)) { device_printf(sc->sc_dev, "%s: called whilst scanning!\n", __func__); + error = EAGAIN; + goto fail; + } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - - return (EAGAIN); + bgscan = wpi_check_bss_filter(sc); + bintval = vap->iv_bss->ni_intval; + if (bgscan != 0 && + bintval < WPI_QUIET_TIME_DEFAULT + WPI_CHANNEL_TUNE_TIME * 2) { + error = EOPNOTSUPP; + goto fail; } buf = malloc(WPI_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO); @@ -3908,15 +4113,19 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) * Move to the next channel if no packets are received within 10 msecs * after sending the probe request. */ - hdr->quiet_time = htole16(10); /* timeout in milliseconds */ - hdr->quiet_threshold = htole16(1); /* min # of packets */ - /* - * Max needs to be greater than active and passive and quiet! - * It's also in microseconds! - */ - hdr->max_svc = htole32(250 * IEEE80211_DUR_TU); - hdr->pause_svc = htole32((4 << 24) | - (100 * IEEE80211_DUR_TU)); /* Hardcode for now */ + hdr->quiet_time = htole16(WPI_QUIET_TIME_DEFAULT); + hdr->quiet_threshold = htole16(1); + + if (bgscan != 0) { + /* + * Max needs to be greater than active and passive and quiet! + * It's also in microseconds! + */ + hdr->max_svc = htole32(250 * IEEE80211_DUR_TU); + hdr->pause_svc = htole32(wpi_get_scan_pause_time(100, + bintval)); + } + hdr->filter = htole32(WPI_FILTER_MULTICAST | WPI_FILTER_BEACON); tx = (struct wpi_cmd_data *)(hdr + 1); @@ -3998,8 +4207,8 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) dwell_passive = wpi_get_passive_dwell_time(sc, c); /* Make sure they're valid. */ - if (dwell_passive <= dwell_active) - dwell_passive = dwell_active + 1; + if (dwell_active > dwell_passive) + dwell_active = dwell_passive; chan->active = htole16(dwell_active); chan->passive = htole16(dwell_passive); @@ -4015,6 +4224,20 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) chan->chan, IEEE80211_IS_CHAN_PASSIVE(c)); hdr->nchan++; + + if (hdr->nchan == 1 && sc->rxon.chan == chan->chan) { + /* XXX Force probe request transmission. */ + memcpy(chan + 1, chan, sizeof (struct wpi_scan_chan)); + + chan++; + + /* Reduce unnecessary delay. */ + chan->flags = 0; + chan->passive = chan->active = hdr->quiet_time; + + hdr->nchan++; + } + chan++; buflen = (uint8_t *)chan - buf; @@ -4044,6 +4267,7 @@ wpi_auth(struct wpi_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni = vap->iv_bss; + struct ieee80211_channel *c = ni->ni_chan; int error; WPI_RXON_LOCK(sc); @@ -4054,18 +4278,18 @@ wpi_auth(struct wpi_softc *sc, struct ieee80211vap *vap) sc->rxon.associd = 0; sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid); - sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan); + sc->rxon.chan = ieee80211_chan2ieee(ic, c); sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + if (IEEE80211_IS_CHAN_2GHZ(c)) sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); if (ic->ic_flags & IEEE80211_F_SHSLOT) sc->rxon.flags |= htole32(WPI_RXON_SHSLOT); if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE); - if (IEEE80211_IS_CHAN_A(ni->ni_chan)) { + if (IEEE80211_IS_CHAN_A(c)) { sc->rxon.cck_mask = 0; sc->rxon.ofdm_mask = 0x15; - } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) { + } else if (IEEE80211_IS_CHAN_B(c)) { sc->rxon.cck_mask = 0x03; sc->rxon.ofdm_mask = 0; } else { @@ -4243,6 +4467,7 @@ wpi_run(struct wpi_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni = vap->iv_bss; + struct ieee80211_channel *c = ni->ni_chan; int error; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -4254,7 +4479,7 @@ wpi_run(struct wpi_softc *sc, struct ieee80211vap *vap) } /* XXX kernel panic workaround */ - if (ni->ni_chan == IEEE80211_CHAN_ANYC) { + if (c == IEEE80211_CHAN_ANYC) { device_printf(sc->sc_dev, "%s: incomplete configuration\n", __func__); return EINVAL; @@ -4270,20 +4495,18 @@ wpi_run(struct wpi_softc *sc, struct ieee80211vap *vap) WPI_RXON_LOCK(sc); IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid); sc->rxon.associd = htole16(IEEE80211_NODE_AID(ni)); - sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan); + sc->rxon.chan = ieee80211_chan2ieee(ic, c); sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + if (IEEE80211_IS_CHAN_2GHZ(c)) sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); - /* Short preamble and slot time are negotiated when associating. */ - sc->rxon.flags &= ~htole32(WPI_RXON_SHPREAMBLE | WPI_RXON_SHSLOT); if (ic->ic_flags & IEEE80211_F_SHSLOT) sc->rxon.flags |= htole32(WPI_RXON_SHSLOT); if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE); - if (IEEE80211_IS_CHAN_A(ni->ni_chan)) { + if (IEEE80211_IS_CHAN_A(c)) { sc->rxon.cck_mask = 0; sc->rxon.ofdm_mask = 0x15; - } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) { + } else if (IEEE80211_IS_CHAN_B(c)) { sc->rxon.cck_mask = 0x03; sc->rxon.ofdm_mask = 0; } else { @@ -4619,7 +4842,7 @@ wpi_post_alive(struct wpi_softc *sc) /* NB: Runtime firmware must be up and running. */ if (!(wpi_prph_read(sc, WPI_APMG_RFKILL) & 1)) { - device_printf(sc->sc_dev, + device_printf(sc->sc_dev, "RF switch: radio disabled (%s)\n", __func__); wpi_nic_unlock(sc); return EPERM; /* :-) */ @@ -4943,7 +5166,7 @@ wpi_apm_stop_master(struct wpi_softc *sc) /* Stop busmaster DMA activity. */ WPI_SETBITS(sc, WPI_RESET, WPI_RESET_STOP_MASTER); - + if ((WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_PS_MASK) == WPI_GP_CNTRL_MAC_PS) return; /* Already asleep. */ @@ -5395,16 +5618,10 @@ wpi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) int error; WPI_RXON_LOCK(sc); - if (sc->rxon.chan != ieee80211_chan2ieee(ic, ic->ic_curchan)) { - error = wpi_scan(sc, ic->ic_curchan); - WPI_RXON_UNLOCK(sc); - if (error != 0) - ieee80211_cancel_scan(vap); - } else { - WPI_RXON_UNLOCK(sc); - /* Send probe request when associated. */ - sc->sc_scan_curchan(ss, maxdwell); - } + error = wpi_scan(sc, ic->ic_curchan); + WPI_RXON_UNLOCK(sc); + if (error != 0) + ieee80211_cancel_scan(vap); } /** diff --git a/sys/dev/wpi/if_wpi_debug.h b/sys/dev/wpi/if_wpi_debug.h index 245bf59..6b78ace 100644 --- a/sys/dev/wpi/if_wpi_debug.h +++ b/sys/dev/wpi/if_wpi_debug.h @@ -43,6 +43,7 @@ enum { WPI_DEBUG_KEY = 0x00020000, /* node key management */ WPI_DEBUG_EDCA = 0x00040000, /* WME info */ WPI_DEBUG_REGISTER = 0x00080000, /* print chipset register */ + WPI_DEBUG_BMISS = 0x00100000, /* print number of missed beacons */ WPI_DEBUG_ANY = 0xffffffff }; @@ -85,12 +86,12 @@ static const char *wpi_cmd_str(int cmd) WPI_DESC(WPI_CMD_SET_LED); WPI_DESC(WPI_CMD_SET_POWER_MODE); WPI_DESC(WPI_CMD_SCAN); + WPI_DESC(WPI_CMD_SCAN_ABORT); WPI_DESC(WPI_CMD_SET_BEACON); WPI_DESC(WPI_CMD_TXPOWER); WPI_DESC(WPI_CMD_BT_COEX); default: - KASSERT(1, ("Unknown Command: %d\n", cmd)); return "UNKNOWN CMD"; } } @@ -98,7 +99,7 @@ static const char *wpi_cmd_str(int cmd) /* * Translate CSR code to string */ -static const char *wpi_get_csr_string(int csr) +static const char *wpi_get_csr_string(size_t csr) { switch (csr) { WPI_DESC(WPI_HW_IF_CONFIG); @@ -117,12 +118,12 @@ static const char *wpi_get_csr_string(int csr) WPI_DESC(WPI_ANA_PLL); WPI_DESC(WPI_DBG_HPET_MEM); default: - KASSERT(1, ("Unknown CSR: %d\n", csr)); + KASSERT(0, ("Unknown CSR: %d\n", csr)); return "UNKNOWN CSR"; } } -static const char *wpi_get_prph_string(int prph) +static const char *wpi_get_prph_string(size_t prph) { switch (prph) { WPI_DESC(WPI_APMG_CLK_CTRL); @@ -130,7 +131,7 @@ static const char *wpi_get_prph_string(int prph) WPI_DESC(WPI_APMG_PCI_STT); WPI_DESC(WPI_APMG_RFKILL); default: - KASSERT(1, ("Unknown register: %d\n", prph)); + KASSERT(0, ("Unknown register: %d\n", prph)); return "UNKNOWN PRPH"; } } diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h index 7e60049..b0aa35c 100644 --- a/sys/dev/wpi/if_wpireg.h +++ b/sys/dev/wpi/if_wpireg.h @@ -256,6 +256,26 @@ struct wpi_tx_stat { uint8_t rate; uint32_t duration; uint32_t status; +#define WPI_TX_STATUS_SUCCESS 0x01 +#define WPI_TX_STATUS_DIRECT_DONE 0x02 +#define WPI_TX_STATUS_FAIL 0x80 +#define WPI_TX_STATUS_FAIL_SHORT_LIMIT 0x82 +#define WPI_TX_STATUS_FAIL_LONG_LIMIT 0x83 +#define WPI_TX_STATUS_FAIL_FIFO_UNDERRUN 0x84 +#define WPI_TX_STATUS_FAIL_MGMNT_ABORT 0x85 +#define WPI_TX_STATUS_FAIL_NEXT_FRAG 0x86 +#define WPI_TX_STATUS_FAIL_LIFE_EXPIRE 0x87 +#define WPI_TX_STATUS_FAIL_NODE_PS 0x88 +#define WPI_TX_STATUS_FAIL_ABORTED 0x89 +#define WPI_TX_STATUS_FAIL_BT_RETRY 0x8a +#define WPI_TX_STATUS_FAIL_NODE_INVALID 0x8b +#define WPI_TX_STATUS_FAIL_FRAG_DROPPED 0x8c +#define WPI_TX_STATUS_FAIL_TID_DISABLE 0x8d +#define WPI_TX_STATUS_FAIL_FRAME_FLUSHED 0x8e +#define WPI_TX_STATUS_FAIL_INSUFFICIENT_CF_POLL 0x8f +#define WPI_TX_STATUS_FAIL_TX_LOCKED 0x90 +#define WPI_TX_STATUS_FAIL_NO_BEACON_ON_RADAR 0x91 + } __packed; struct wpi_rx_desc { @@ -332,6 +352,7 @@ struct wpi_tx_cmd { #define WPI_CMD_SET_LED 72 #define WPI_CMD_SET_POWER_MODE 119 #define WPI_CMD_SCAN 128 +#define WPI_CMD_SCAN_ABORT 129 #define WPI_CMD_SET_BEACON 145 #define WPI_CMD_TXPOWER 151 #define WPI_CMD_BT_COEX 155 @@ -547,6 +568,8 @@ struct wpi_mrr_setup { uint8_t plcp; uint8_t flags; uint8_t ntries; +#define WPI_NTRIES_DEFAULT 2 + uint8_t next; } __packed rates[WPI_RIDX_MAX + 1]; } __packed; @@ -589,12 +612,17 @@ struct wpi_scan_hdr { uint16_t len; uint8_t reserved1; uint8_t nchan; - uint16_t quiet_time; - uint16_t quiet_threshold; + uint16_t quiet_time; /* timeout in milliseconds */ +#define WPI_QUIET_TIME_DEFAULT 10 + + uint16_t quiet_threshold; /* min # of packets */ uint16_t crc_threshold; uint16_t reserved2; uint32_t max_svc; /* background scans */ uint32_t pause_svc; /* background scans */ +#define WPI_PAUSE_MAX_TIME ((1 << 20) - 1) +#define WPI_PAUSE_SCAN(nbeacons, time) ((nbeacons << 24) | time) + uint32_t flags; uint32_t filter; @@ -630,6 +658,7 @@ struct wpi_scan_chan { #define WPI_PASSIVE_DWELL_TIME_2GHZ ( 20) #define WPI_PASSIVE_DWELL_TIME_5GHZ ( 10) #define WPI_PASSIVE_DWELL_BASE (100) +#define WPI_CHANNEL_TUNE_TIME ( 6) /* Structure for command WPI_CMD_TXPOWER. */ struct wpi_cmd_txpower { @@ -697,6 +726,9 @@ struct wpi_start_scan { struct wpi_stop_scan { uint8_t nchan; uint8_t status; +#define WPI_SCAN_COMPLETED 1 +#define WPI_SCAN_ABORTED 2 + uint8_t reserved; uint8_t chan; uint64_t tsf; diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h index 7c74825..7a65b72 100644 --- a/sys/dev/wpi/if_wpivar.h +++ b/sys/dev/wpi/if_wpivar.h @@ -121,17 +121,19 @@ struct wpi_buf { }; struct wpi_vap { - struct ieee80211vap wv_vap; + struct ieee80211vap wv_vap; - struct wpi_buf wv_bcbuf; - struct ieee80211_beacon_offsets wv_boff; - struct mtx wv_mtx; + struct wpi_buf wv_bcbuf; + struct ieee80211_beacon_offsets wv_boff; + struct mtx wv_mtx; - uint32_t wv_gtk; -#define WPI_VAP_KEY(kid) (1 << kid) + uint32_t wv_gtk; +#define WPI_VAP_KEY(kid) (1 << kid) - int (*wv_newstate)(struct ieee80211vap *, - enum ieee80211_state, int); + int (*wv_newstate)(struct ieee80211vap *, + enum ieee80211_state, int); + void (*wv_recv_mgmt)(struct ieee80211_node *, + struct mbuf *, int, int, int); }; #define WPI_VAP(vap) ((struct wpi_vap *)(vap)) @@ -164,6 +166,9 @@ struct wpi_softc { struct ifnet *sc_ifp; int sc_debug; + int sc_flags; +#define WPI_PS_PATH (1 << 0) + struct mtx sc_mtx; struct mtx tx_mtx; @@ -177,6 +182,7 @@ struct wpi_softc { uint32_t txq_active; struct wpi_rx_ring rxq; + uint64_t rx_tstamp; /* TX Thermal Callibration. */ struct callout calib_to; @@ -210,8 +216,9 @@ struct wpi_softc { struct mtx nt_mtx; void (*sc_node_free)(struct ieee80211_node *); - void (*sc_scan_curchan)(struct ieee80211_scan_state *, - unsigned long); + void (*sc_update_rx_ring)(struct wpi_softc *); + void (*sc_update_tx_ring)(struct wpi_softc *, + struct wpi_tx_ring *); struct wpi_rx_radiotap_header sc_rxtap; struct wpi_tx_radiotap_header sc_txtap; diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index 5073398..c340106 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -138,6 +138,9 @@ static struct g_part_mbr_alias { { DOSPTYP_PPCBOOT, G_PART_ALIAS_PREP_BOOT }, { DOSPTYP_VMFS, G_PART_ALIAS_VMFS }, { DOSPTYP_VMKDIAG, G_PART_ALIAS_VMKDIAG }, + { DOSPTYP_APPLE_UFS, G_PART_ALIAS_APPLE_UFS }, + { DOSPTYP_APPLE_BOOT, G_PART_ALIAS_APPLE_BOOT }, + { DOSPTYP_HFS, G_PART_ALIAS_APPLE_HFS }, }; static int diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index 998ee15..5125480 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -700,10 +700,8 @@ vpanic(const char *fmt, va_list ap) } /* - * We set stop_scheduler here and not in the block above, - * because we want to ensure that if panic has been called and - * stop_scheduler_on_panic is true, then stop_scheduler will - * always be set. Even if panic has been entered from kdb. + * Ensure that the scheduler is stopped while panicking, even if panic + * has been entered from kdb. */ td->td_stopsched = 1; #endif diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 6264c64..9dca0e8 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1468,6 +1468,17 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, * RFC 2783 PPS-API implementation. */ +/* + * Return true if the driver is aware of the abi version extensions in the + * pps_state structure, and it supports at least the given abi version number. + */ +static inline int +abi_aware(struct pps_state *pps, int vers) +{ + + return ((pps->kcmode & KCMODE_ABIFLAG) && pps->driver_abi >= vers); +} + static int pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) { @@ -1497,10 +1508,17 @@ pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) cseq = pps->ppsinfo.clear_sequence; while (aseq == pps->ppsinfo.assert_sequence && cseq == pps->ppsinfo.clear_sequence) { - if (pps->mtx != NULL) - err = msleep(pps, pps->mtx, PCATCH, "ppsfch", timo); - else + if (abi_aware(pps, 1) && pps->driver_mtx != NULL) { + if (pps->flags & PPSFLAG_MTX_SPIN) { + err = msleep_spin(pps, pps->driver_mtx, + "ppsfch", timo); + } else { + err = msleep(pps, pps->driver_mtx, PCATCH, + "ppsfch", timo); + } + } else { err = tsleep(pps, PCATCH, "ppsfch", timo); + } if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) { continue; } else if (err != 0) { @@ -1590,7 +1608,8 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) return (EINVAL); if (kapi->edge & ~pps->ppscap) return (EINVAL); - pps->kcmode = kapi->edge; + pps->kcmode = (kapi->edge & KCMODE_EDGEMASK) | + (pps->kcmode & KCMODE_ABIFLAG); return (0); #else return (EOPNOTSUPP); @@ -1611,6 +1630,18 @@ pps_init(struct pps_state *pps) #ifdef FFCLOCK pps->ppscap |= PPS_TSCLK_MASK; #endif + pps->kcmode &= ~KCMODE_ABIFLAG; +} + +void +pps_init_abi(struct pps_state *pps) +{ + + pps_init(pps); + if (pps->driver_abi > 0) { + pps->kcmode |= KCMODE_ABIFLAG; + pps->kernel_abi = PPS_ABI_VERSION; + } } void diff --git a/sys/kern/subr_nvlist.c b/sys/kern/subr_nvlist.c index f96b890..40e49ff 100644 --- a/sys/kern/subr_nvlist.c +++ b/sys/kern/subr_nvlist.c @@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$"); #endif #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) -#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE) +#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) #define NVLIST_MAGIC 0x6e766c /* "nvl" */ @@ -129,6 +129,8 @@ nvlist_create(int flags) PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); nvl = nv_malloc(sizeof(*nvl)); + if (nvl == NULL) + return (NULL); nvl->nvl_error = 0; nvl->nvl_flags = flags; nvl->nvl_parent = NULL; @@ -774,7 +776,8 @@ failed: } static nvlist_t * -nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) +nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, + int flags) { const unsigned char *ptr; nvlist_t *nvl, *retnvl, *tmpnvl; @@ -782,6 +785,8 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) size_t left; bool isbe; + PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); + left = size; ptr = buf; @@ -793,6 +798,10 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); if (ptr == NULL) goto failed; + if (nvl->nvl_flags != flags) { + ERRNO_SET(EILSEQ); + goto failed; + } while (left > 0) { ptr = nvpair_unpack(isbe, ptr, &left, &nvp); @@ -849,10 +858,10 @@ failed: } nvlist_t * -nvlist_unpack(const void *buf, size_t size) +nvlist_unpack(const void *buf, size_t size, int flags) { - return (nvlist_xunpack(buf, size, NULL, 0)); + return (nvlist_xunpack(buf, size, NULL, 0, flags)); } #ifndef _KERNEL @@ -900,7 +909,7 @@ out: } nvlist_t * -nvlist_recv(int sock) +nvlist_recv(int sock, int flags) { struct nvlist_header nvlhdr; nvlist_t *nvl, *ret; @@ -937,7 +946,7 @@ nvlist_recv(int sock) goto out; } - nvl = nvlist_xunpack(buf, size, fds, nfds); + nvl = nvlist_xunpack(buf, size, fds, nfds, flags); if (nvl == NULL) { ERRNO_SAVE(); for (i = 0; i < nfds; i++) @@ -957,7 +966,7 @@ out: } nvlist_t * -nvlist_xfer(int sock, nvlist_t *nvl) +nvlist_xfer(int sock, nvlist_t *nvl, int flags) { if (nvlist_send(sock, nvl) < 0) { @@ -965,7 +974,7 @@ nvlist_xfer(int sock, nvlist_t *nvl) return (NULL); } nvlist_destroy(nvl); - return (nvlist_recv(sock)); + return (nvlist_recv(sock, flags)); } #endif @@ -1067,10 +1076,12 @@ nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) ERRNO_SET(nvlist_error(nvl)); return; } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = EEXIST; - ERRNO_SET(nvlist_error(nvl)); - return; + if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvl->nvl_error = EEXIST; + ERRNO_SET(nvlist_error(nvl)); + return; + } } newnvp = nvpair_clone(nvp); @@ -1133,45 +1144,8 @@ nvlist_add_null(nvlist_t *nvl, const char *name) } void -nvlist_add_bool(nvlist_t *nvl, const char *name, bool value) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - ERRNO_SET(nvlist_error(nvl)); - return; - } - - nvp = nvpair_create_bool(name, value); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - ERRNO_SET(nvl->nvl_error); - } else { - nvlist_move_nvpair(nvl, nvp); - } -} - -void -nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - ERRNO_SET(nvlist_error(nvl)); - return; - } - - nvp = nvpair_create_number(name, value); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - ERRNO_SET(nvl->nvl_error); - } else { - nvlist_move_nvpair(nvl, nvp); - } -} - -void -nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) +nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, + size_t size) { nvpair_t *nvp; @@ -1180,7 +1154,7 @@ nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) return; } - nvp = nvpair_create_string(name, value); + nvp = nvpair_create_binary(name, value, size); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); @@ -1189,63 +1163,36 @@ nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) } } -void -nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - ERRNO_SET(nvlist_error(nvl)); - return; - } - nvp = nvpair_create_nvlist(name, value); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - ERRNO_SET(nvl->nvl_error); - } else { - nvlist_move_nvpair(nvl, nvp); - } +#define NVLIST_ADD(vtype, type) \ +void \ +nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ +{ \ + nvpair_t *nvp; \ + \ + if (nvlist_error(nvl) != 0) { \ + ERRNO_SET(nvlist_error(nvl)); \ + return; \ + } \ + \ + nvp = nvpair_create_##type(name, value); \ + if (nvp == NULL) { \ + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ + ERRNO_SET(nvl->nvl_error); \ + } else { \ + nvlist_move_nvpair(nvl, nvp); \ + } \ } +NVLIST_ADD(bool, bool) +NVLIST_ADD(uint64_t, number) +NVLIST_ADD(const char *, string) +NVLIST_ADD(const nvlist_t *, nvlist) #ifndef _KERNEL -void -nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - errno = nvlist_error(nvl); - return; - } - - nvp = nvpair_create_descriptor(name, value); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} +NVLIST_ADD(int, descriptor); #endif -void -nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, - size_t size) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - ERRNO_SET(nvlist_error(nvl)); - return; - } - - nvp = nvpair_create_binary(name, value, size); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - ERRNO_SET(nvl->nvl_error); - } else { - nvlist_move_nvpair(nvl, nvp); - } -} +#undef NVLIST_ADD void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) @@ -1259,11 +1206,13 @@ nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) ERRNO_SET(nvlist_error(nvl)); return; } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvpair_free(nvp); - nvl->nvl_error = EEXIST; - ERRNO_SET(nvl->nvl_error); - return; + if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvpair_free(nvp); + nvl->nvl_error = EEXIST; + ERRNO_SET(nvl->nvl_error); + return; + } } nvpair_insert(&nvl->nvl_head, nvp, nvl); diff --git a/sys/kern/subr_nvpair.c b/sys/kern/subr_nvpair.c index b0fc322..cde08e6 100644 --- a/sys/kern/subr_nvpair.c +++ b/sys/kern/subr_nvpair.c @@ -143,7 +143,8 @@ nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_list == NULL); - PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); + PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || + !nvlist_exists(nvl, nvpair_name(nvp))); TAILQ_INSERT_TAIL(head, nvp, nvp_next); nvp->nvp_list = nvl; @@ -733,7 +734,7 @@ nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize) if (nvp != NULL) { nvp->nvp_name = (char *)(nvp + 1); memcpy(nvp->nvp_name, name, namelen); - nvp->nvp_name[namelen + 1] = '\0'; + nvp->nvp_name[namelen] = '\0'; nvp->nvp_type = type; nvp->nvp_data = data; nvp->nvp_datasize = datasize; diff --git a/sys/net/if_types.h b/sys/net/if_types.h index df019e0..92e101a 100644 --- a/sys/net/if_types.h +++ b/sys/net/if_types.h @@ -254,4 +254,20 @@ typedef enum { IFT_PFLOG = 0xf6, /* PF packet filter logging */ IFT_PFSYNC = 0xf7, /* PF packet filter synchronization */ } ifType; + +/* + * Some (broken) software uses #ifdef IFT_TYPE to check whether + * an operating systems supports certain interface type. Lack of + * ifdef leads to a piece of functionality compiled out. + */ +#ifndef BURN_BRIDGES +#define IFT_BRIDGE IFT_BRIDGE +#define IFT_PPP IFT_PPP +#define IFT_PROPVIRTUAL IFT_PROPVIRTUAL +#define IFT_L2VLAN IFT_L2VLAN +#define IFT_L3IPVLAN IFT_L3IPVLAN +#define IFT_IEEE1394 IFT_IEEE1394 +#define IFT_INFINIBAND IFT_INFINIBAND +#endif + #endif /* !_NET_IF_TYPES_H_ */ diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index c1b4b51..049d952 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -229,6 +229,8 @@ adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } #endif break; + case IEEE80211_S_RUN: /* IBSS merge */ + break; default: goto invalid; } @@ -369,7 +371,10 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) /* * Validate the bssid. */ - if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) && + if (!(type == IEEE80211_FC0_TYPE_MGT && + (subtype == IEEE80211_FC0_SUBTYPE_BEACON || + subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ)) && + !IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) && !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { /* not interested in */ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, @@ -409,7 +414,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) } IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if (HAS_SEQ(type)) { + if (HAS_SEQ(type) && IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 711bac3..aa21f3b 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -355,8 +355,8 @@ wlan_##name##_modevent(module_t mod, int type, void *unused) \ case MOD_UNLOAD: \ case MOD_QUIESCE: \ if (nrefs) { \ - printf("wlan_##name: still in use (%u dynamic refs)\n",\ - nrefs); \ + printf("wlan_" #name ": still in use " \ + "(%u dynamic refs)\n", nrefs); \ return EBUSY; \ } \ if (type == MOD_UNLOAD) { \ diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 9fc4cd4..c84f9a8 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -93,6 +93,8 @@ static void node_getmimoinfo(const struct ieee80211_node *, static void _ieee80211_free_node(struct ieee80211_node *); +static void node_reclaim(struct ieee80211_node_table *nt, + struct ieee80211_node *ni); static void ieee80211_node_table_init(struct ieee80211com *ic, struct ieee80211_node_table *nt, const char *name, int inact, int keymaxix); @@ -719,9 +721,15 @@ ieee80211_sta_join1(struct ieee80211_node *selbs) IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr)); vap->iv_bss = selbs; /* NB: caller assumed to bump refcnt */ if (obss != NULL) { + struct ieee80211_node_table *nt = obss->ni_table; + copy_bss(selbs, obss); ieee80211_node_decref(obss); /* iv_bss reference */ - ieee80211_free_node(obss); /* station table reference */ + + IEEE80211_NODE_LOCK(nt); + node_reclaim(nt, obss); /* station table reference */ + IEEE80211_NODE_UNLOCK(nt); + obss = NULL; /* NB: guard against later use */ } @@ -871,7 +879,7 @@ ieee80211_sta_leave(struct ieee80211_node *ni) void ieee80211_node_deauth(struct ieee80211_node *ni, int reason) { - /* NB: bump the refcnt to be sure temporay nodes are not reclaimed */ + /* NB: bump the refcnt to be sure temporary nodes are not reclaimed */ ieee80211_ref_node(ni); if (ni->ni_associd != 0) IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, reason); @@ -1749,6 +1757,28 @@ _ieee80211_free_node(struct ieee80211_node *ni) ni->ni_ic->ic_node_free(ni); } +/* + * Clear any entry in the unicast key mapping table. + */ +static int +node_clear_keyixmap(struct ieee80211_node_table *nt, struct ieee80211_node *ni) +{ + ieee80211_keyix keyix; + + keyix = ni->ni_ucastkey.wk_rxkeyix; + if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax && + nt->nt_keyixmap[keyix] == ni) { + IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, + "%s: %p<%s> clear key map entry %u\n", + __func__, ni, ether_sprintf(ni->ni_macaddr), keyix); + nt->nt_keyixmap[keyix] = NULL; + ieee80211_node_decref(ni); + return 1; + } + + return 0; +} + void #ifdef IEEE80211_DEBUG_REFCNT ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line) @@ -1770,24 +1800,9 @@ ieee80211_free_node(struct ieee80211_node *ni) * Last reference, reclaim state. */ _ieee80211_free_node(ni); - } else if (ieee80211_node_refcnt(ni) == 1 && - nt->nt_keyixmap != NULL) { - ieee80211_keyix keyix; - /* - * Check for a last reference in the key mapping table. - */ - keyix = ni->ni_ucastkey.wk_rxkeyix; - if (keyix < nt->nt_keyixmax && - nt->nt_keyixmap[keyix] == ni) { - IEEE80211_DPRINTF(ni->ni_vap, - IEEE80211_MSG_NODE, - "%s: %p<%s> clear key map entry", __func__, - ni, ether_sprintf(ni->ni_macaddr)); - nt->nt_keyixmap[keyix] = NULL; - ieee80211_node_decref(ni); /* XXX needed? */ + } else if (ieee80211_node_refcnt(ni) == 1) + if (node_clear_keyixmap(nt, ni)) _ieee80211_free_node(ni); - } - } IEEE80211_NODE_UNLOCK(nt); } else { if (ieee80211_node_dectestref(ni)) @@ -1855,7 +1870,6 @@ ieee80211_node_delucastkey(struct ieee80211_node *ni) static void node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { - ieee80211_keyix keyix; IEEE80211_NODE_LOCK_ASSERT(nt); @@ -1870,15 +1884,7 @@ node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni) * table. We cannot depend on the mapping table entry * being cleared because the node may not be free'd. */ - keyix = ni->ni_ucastkey.wk_rxkeyix; - if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax && - nt->nt_keyixmap[keyix] == ni) { - IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, - "%s: %p<%s> clear key map entry %u\n", - __func__, ni, ether_sprintf(ni->ni_macaddr), keyix); - nt->nt_keyixmap[keyix] = NULL; - ieee80211_node_decref(ni); /* NB: don't need free */ - } + (void)node_clear_keyixmap(nt, ni); if (!ieee80211_node_dectestref(ni)) { /* * Other references are present, just remove the diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index be5106a..d2570c4 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1997,18 +1997,9 @@ in6_if2idlen(struct ifnet *ifp) { switch (ifp->if_type) { case IFT_ETHER: /* RFC2464 */ -#ifdef IFT_PROPVIRTUAL case IFT_PROPVIRTUAL: /* XXX: no RFC. treat it as ether */ -#endif -#ifdef IFT_L2VLAN case IFT_L2VLAN: /* ditto */ -#endif -#ifdef IFT_IEEE80211 case IFT_IEEE80211: /* ditto */ -#endif -#ifdef IFT_MIP - case IFT_MIP: /* ditto */ -#endif case IFT_INFINIBAND: return (64); case IFT_FDDI: /* RFC2467 */ diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 06d931b..8c25e98 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -274,9 +274,7 @@ found: case IFT_ISO88025: case IFT_ATM: case IFT_IEEE1394: -#ifdef IFT_IEEE80211 case IFT_IEEE80211: -#endif /* IEEE802/EUI64 cases - what others? */ /* IEEE1394 uses 16byte length address starting with EUI64 */ if (addrlen > 8) @@ -338,9 +336,7 @@ found: break; case IFT_GIF: -#ifdef IFT_STF case IFT_STF: -#endif /* * RFC2893 says: "SHOULD use IPv4 address as ifid source". * however, IPv4 address is not very suitable as unique diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index a344d6a..83dda1a 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -2145,12 +2145,8 @@ nd6_need_cache(struct ifnet *ifp) case IFT_ETHER: case IFT_FDDI: case IFT_IEEE1394: -#ifdef IFT_L2VLAN case IFT_L2VLAN: -#endif -#ifdef IFT_IEEE80211 case IFT_IEEE80211: -#endif case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_PROPVIRTUAL: @@ -2235,12 +2231,8 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m, switch (ifp->if_type) { case IFT_ETHER: case IFT_FDDI: -#ifdef IFT_L2VLAN case IFT_L2VLAN: -#endif -#ifdef IFT_IEEE80211 case IFT_IEEE80211: -#endif case IFT_BRIDGE: case IFT_ISO88025: ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr, diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index 4b160f7..a4ae618 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -1149,12 +1149,8 @@ nd6_ifptomac(struct ifnet *ifp) case IFT_ETHER: case IFT_FDDI: case IFT_IEEE1394: -#ifdef IFT_L2VLAN case IFT_L2VLAN: -#endif -#ifdef IFT_IEEE80211 case IFT_IEEE80211: -#endif case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_ISO88025: @@ -1549,9 +1545,7 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp) case IFT_FDDI: case IFT_ATM: case IFT_IEEE1394: -#ifdef IFT_IEEE80211 case IFT_IEEE80211: -#endif case IFT_INFINIBAND: in6 = ia->ia_addr.sin6_addr; if (in6_get_hw_ifid(ifp, &in6) == 0 && diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index ca4e0e4..f942541 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -597,19 +597,21 @@ restart: /* Pass stack buffer by default */ ta_buf_m = ta_buf; error = prepare_batch_buffer(ch, ta, tei, count, OP_ADD, &ta_buf_m); - if (error != 0) - goto cleanup; IPFW_UH_WLOCK(ch); + del_toperation_state(ch, &ts); /* Drop reference we've used in first search */ tc->no.refcnt--; + /* Check prepare_batch_buffer() error */ + if (error != 0) + goto cleanup; + /* * Check if table swap has happened. * (so table algo might be changed). * Restart operation to achieve consistent behavior. */ - del_toperation_state(ch, &ts); if (ts.modified != 0) goto restart; diff --git a/sys/ofed/include/linux/linux_idr.c b/sys/ofed/include/linux/linux_idr.c index 809e178..a692fb8 100644 --- a/sys/ofed/include/linux/linux_idr.c +++ b/sys/ofed/include/linux/linux_idr.c @@ -185,27 +185,37 @@ out: return (res); } -void * -idr_find(struct idr *idr, int id) +static inline void * +idr_find_locked(struct idr *idr, int id) { struct idr_layer *il; void *res; int layer; - res = NULL; + mtx_assert(&idr->lock, MA_OWNED); + id &= MAX_ID_MASK; - mtx_lock(&idr->lock); + res = NULL; il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) - goto out; + return (NULL); while (layer && il) { il = il->ary[idr_pos(id, layer)]; layer--; } if (il != NULL) res = il->ary[id & IDR_MASK]; -out: + return (res); +} + +void * +idr_find(struct idr *idr, int id) +{ + void *res; + + mtx_lock(&idr->lock); + res = idr_find_locked(idr, id); mtx_unlock(&idr->lock); return (res); } @@ -331,13 +341,13 @@ idr_get_new(struct idr *idr, void *ptr, int *idp) } error = 0; out: - mtx_unlock(&idr->lock); #ifdef INVARIANTS - if (error == 0 && idr_find(idr, id) != ptr) { + if (error == 0 && idr_find_locked(idr, id) != ptr) { panic("idr_get_new: Failed for idr %p, id %d, ptr %p\n", idr, id, ptr); } #endif + mtx_unlock(&idr->lock); return (error); } @@ -438,12 +448,12 @@ restart: } error = 0; out: - mtx_unlock(&idr->lock); #ifdef INVARIANTS - if (error == 0 && idr_find(idr, id) != ptr) { + if (error == 0 && idr_find_locked(idr, id) != ptr) { panic("idr_get_new_above: Failed for idr %p, id %d, ptr %p\n", idr, id, ptr); } #endif + mtx_unlock(&idr->lock); return (error); } diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index cb05ffa..5f49eb9 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -51,11 +51,13 @@ #define DOSPTYP_EXTLBA 0x0f /* DOS extended partition */ #define DOSPTYP_PPCBOOT 0x41 /* PReP/CHRP boot partition */ #define DOSPTYP_LDM 0x42 /* Win2k dynamic extended partition */ -#define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */ -#define DOSPTYP_HFS 0xaf /* HFS/HFS+ partition type */ #define DOSPTYP_LINSWP 0x82 /* Linux swap partition */ #define DOSPTYP_LINUX 0x83 /* Linux partition */ #define DOSPTYP_LINLVM 0x8e /* Linux LVM partition */ +#define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */ +#define DOSPTYP_APPLE_UFS 0xa8 /* Apple Mac OS X boot */ +#define DOSPTYP_APPLE_BOOT 0xab /* Apple Mac OS X UFS */ +#define DOSPTYP_HFS 0xaf /* HFS/HFS+ partition type */ #define DOSPTYP_PMBR 0xee /* GPT Protective MBR */ #define DOSPTYP_EFI 0xef /* EFI FAT parition */ #define DOSPTYP_VMFS 0xfb /* VMware VMFS partition */ diff --git a/sys/sys/nv.h b/sys/sys/nv.h index 5c342dc..fa5d138 100644 --- a/sys/sys/nv.h +++ b/sys/sys/nv.h @@ -64,6 +64,10 @@ typedef struct nvlist nvlist_t; * Perform case-insensitive lookups of provided names. */ #define NV_FLAG_IGNORE_CASE 0x01 +/* + * Names don't have to be unique. + */ +#define NV_FLAG_NO_UNIQUE 0x02 #if defined(_KERNEL) && defined(MALLOC_DECLARE) MALLOC_DECLARE(M_NVLIST); @@ -87,11 +91,11 @@ void nvlist_fdump(const nvlist_t *nvl, FILE *fp); size_t nvlist_size(const nvlist_t *nvl); void *nvlist_pack(const nvlist_t *nvl, size_t *sizep); -nvlist_t *nvlist_unpack(const void *buf, size_t size); +nvlist_t *nvlist_unpack(const void *buf, size_t size, int flags); int nvlist_send(int sock, const nvlist_t *nvl); -nvlist_t *nvlist_recv(int sock); -nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl); +nvlist_t *nvlist_recv(int sock, int flags); +nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl, int flags); const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); diff --git a/sys/sys/param.h b/sys/sys/param.h index 867dbf1..bc722df 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100071 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100072 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/timepps.h b/sys/sys/timepps.h index ae4b84d..d472c80 100644 --- a/sys/sys/timepps.h +++ b/sys/sys/timepps.h @@ -135,6 +135,13 @@ struct pps_kcbind_args { struct mtx; +#define KCMODE_EDGEMASK 0x03 +#define KCMODE_ABIFLAG 0x80000000 /* Internal use: abi-aware driver. */ + +#define PPS_ABI_VERSION 1 + +#define PPSFLAG_MTX_SPIN 0x01 /* Driver mtx is MTX_SPIN type. */ + struct pps_state { /* Capture information. */ struct timehands *capth; @@ -142,9 +149,6 @@ struct pps_state { unsigned capgen; unsigned capcount; - /* pointer to mutex protecting this state, if any */ - struct mtx *mtx; - /* State information. */ pps_params_t ppsparam; pps_info_t ppsinfo; @@ -153,11 +157,19 @@ struct pps_state { int ppscap; struct timecounter *ppstc; unsigned ppscount[3]; + /* + * The following fields are valid if the driver calls pps_init_abi(). + */ + uint16_t driver_abi; /* Driver sets before pps_init_abi(). */ + uint16_t kernel_abi; /* Kernel sets during pps_init_abi(). */ + struct mtx *driver_mtx; /* Optional, valid if non-NULL. */ + uint32_t flags; }; void pps_capture(struct pps_state *pps); void pps_event(struct pps_state *pps, int event); void pps_init(struct pps_state *pps); +void pps_init_abi(struct pps_state *pps); int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps); void hardpps(struct timespec *tsp, long nsec); diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 15e5b24..9a83989 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -328,17 +328,16 @@ static int nsw_wcount_async; /* limit write buffers / asynchronous */ static int nsw_wcount_async_max;/* assigned maximum */ static int nsw_cluster_max; /* maximum VOP I/O allowed */ +static int sysctl_swap_async_max(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_vm, OID_AUTO, swap_async_max, CTLTYPE_INT | CTLFLAG_RW, + NULL, 0, sysctl_swap_async_max, "I", "Maximum running async swap ops"); + static struct swblock **swhash; static int swhash_mask; static struct mtx swhash_mtx; -static int swap_async_max = 4; /* maximum in-progress async I/O's */ static struct sx sw_alloc_sx; - -SYSCTL_INT(_vm, OID_AUTO, swap_async_max, - CTLFLAG_RW, &swap_async_max, 0, "Maximum running async swap ops"); - /* * "named" and "unnamed" anon region objects. Try to reduce the overhead * of searching a named list by hashing it just a little. @@ -1350,39 +1349,6 @@ swap_pager_putpages(vm_object_t object, vm_page_t *m, int count, /* * Step 2 * - * Update nsw parameters from swap_async_max sysctl values. - * Do not let the sysop crash the machine with bogus numbers. - */ - mtx_lock(&pbuf_mtx); - if (swap_async_max != nsw_wcount_async_max) { - int n; - - /* - * limit range - */ - if ((n = swap_async_max) > nswbuf / 2) - n = nswbuf / 2; - if (n < 1) - n = 1; - swap_async_max = n; - - /* - * Adjust difference ( if possible ). If the current async - * count is too low, we may not be able to make the adjustment - * at this time. - */ - n -= nsw_wcount_async_max; - if (nsw_wcount_async + n >= 0) { - nsw_wcount_async += n; - nsw_wcount_async_max += n; - wakeup(&nsw_wcount_async); - } - } - mtx_unlock(&pbuf_mtx); - - /* - * Step 3 - * * Assign swap blocks and issue I/O. We reallocate swap on the fly. * The page is left dirty until the pageout operation completes * successfully. @@ -2835,3 +2801,40 @@ swaponvp(struct thread *td, struct vnode *vp, u_long nblks) NODEV, 0); return (0); } + +static int +sysctl_swap_async_max(SYSCTL_HANDLER_ARGS) +{ + int error, new, n; + + new = nsw_wcount_async_max; + error = sysctl_handle_int(oidp, &new, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + if (new > nswbuf / 2 || new < 1) + return (EINVAL); + + mtx_lock(&pbuf_mtx); + while (nsw_wcount_async_max != new) { + /* + * Adjust difference. If the current async count is too low, + * we will need to sqeeze our update slowly in. Sleep with a + * higher priority than getpbuf() to finish faster. + */ + n = new - nsw_wcount_async_max; + if (nsw_wcount_async + n >= 0) { + nsw_wcount_async += n; + nsw_wcount_async_max += n; + wakeup(&nsw_wcount_async); + } else { + nsw_wcount_async_max -= nsw_wcount_async; + nsw_wcount_async = 0; + msleep(&nsw_wcount_async, &pbuf_mtx, PSWP, + "swpsysctl", 0); + } + } + mtx_unlock(&pbuf_mtx); + + return (0); +} diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 2878dc3..c59f81a 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -340,16 +340,21 @@ vnode_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, *before += poff; } if (after) { - int numafter; + /* + * The BMAP vop can report a partial block in the + * 'after', but must not report blocks after EOF. + * Assert the latter, and truncate 'after' in case + * of the former. + */ + KASSERT((reqblock + *after) * pagesperblock < + roundup2(object->size, pagesperblock), + ("%s: reqblock %jd after %d size %ju", __func__, + (intmax_t )reqblock, *after, + (uintmax_t )object->size)); *after *= pagesperblock; - numafter = pagesperblock - (poff + 1); - if (IDX_TO_OFF(pindex + numafter) > - object->un_pager.vnp.vnp_size) { - numafter = - OFF_TO_IDX(object->un_pager.vnp.vnp_size) - - pindex; - } - *after += numafter; + *after += pagesperblock - (poff + 1); + if (pindex + *after >= object->size) + *after = object->size - 1 - pindex; } } else { if (before) { diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h index 60f46fb..a771fff 100644 --- a/sys/x86/include/specialreg.h +++ b/sys/x86/include/specialreg.h @@ -82,6 +82,9 @@ #define EFER_LMA 0x000000400 /* Long mode active (R) */ #define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */ #define EFER_SVM 0x000001000 /* SVM enable bit for AMD, reserved for Intel */ +#define EFER_LMSLE 0x000002000 /* Long Mode Segment Limit Enable */ +#define EFER_FFXSR 0x000004000 /* Fast FXSAVE/FSRSTOR */ +#define EFER_TCE 0x000008000 /* Translation Cache Extension */ /* * Intel Extended Features registers @@ -191,7 +194,7 @@ #define AMDID_MP 0x00080000 #define AMDID_NX 0x00100000 #define AMDID_EXT_MMX 0x00400000 -#define AMDID_FFXSR 0x01000000 +#define AMDID_FFXSR 0x02000000 #define AMDID_PAGE1GB 0x04000000 #define AMDID_RDTSCP 0x08000000 #define AMDID_LM 0x20000000 |