From f1429e95c359a7e76f8385cdd47f887b7d1bbd0e Mon Sep 17 00:00:00 2001 From: emaste Date: Tue, 9 Feb 2016 22:32:24 +0000 Subject: MFC boot loader path and RBX constant deduplication r294765 (imp) Move all the separate copies of the same strings into paths.h. There's nothing machine specific about these. r294765 (imp) RBX_ defines are in rbx.h, move it there. r294847 (imp) Remove static from these two. They slipped through the cracks. r294925 (imp) Fix mistake when transitioning to the new defines with ZFS loader. I hate adding yet another define, but it is the lessor of the evil choices available. Kill another evil by removing PATH_BOOT3 and replacing it with PATH_LOADER or PATH_LOADER_ZFS as appropriate. Approved by: re (gjb) --- sys/boot/arm/at91/boot2/boot2.c | 44 +++----------------------- sys/boot/arm/ixp425/boot2/boot2.c | 42 ++----------------------- sys/boot/common/paths.h | 39 ++++++++++++++++++++++++ sys/boot/common/rbx.h | 61 +++++++++++++++++++++++++++++++++++++ sys/boot/efi/boot1/boot1.c | 11 +++---- sys/boot/i386/boot2/boot2.c | 49 +++-------------------------- sys/boot/i386/common/rbx.h | 61 ------------------------------------- sys/boot/i386/gptboot/gptboot.c | 10 ++---- sys/boot/i386/zfsboot/zfsboot.c | 10 ++---- sys/boot/pc98/boot2/boot2.c | 49 +++-------------------------- sys/boot/powerpc/boot1.chrp/boot1.c | 5 ++- sys/boot/sparc64/boot1/boot1.c | 6 ++-- 12 files changed, 130 insertions(+), 257 deletions(-) create mode 100644 sys/boot/common/paths.h create mode 100644 sys/boot/common/rbx.h delete mode 100644 sys/boot/i386/common/rbx.h diff --git a/sys/boot/arm/at91/boot2/boot2.c b/sys/boot/arm/at91/boot2/boot2.c index c3629a5..0388548 100644 --- a/sys/boot/arm/at91/boot2/boot2.c +++ b/sys/boot/arm/at91/boot2/boot2.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2008 John Hay - * Copyright (c) 2006 Warner Losh + * Copyright (c) 2006 M Warner Losh * Copyright (c) 1998 Robert Nordier * All rights reserved. * @@ -30,52 +30,16 @@ __FBSDID("$FreeBSD$"); #include "lib.h" #include "board.h" +#include "paths.h" +#include "rbx.h" -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -/* #define RBX_KDB 0x6 -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -/* #define RBX_SERIAL 0xc -h */ -/* #define RBX_CDROM 0xd -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -/* #define RBX_MUTE 0x10 -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -/* #define RBX_PAUSE 0x14 -p */ -/* #define RBX_QUIET 0x15 -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -/* #define RBX_DUAL 0x1d -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -v, -g */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | \ - OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_GDB)) - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -//#define PATH_KERNEL "/boot/kernel/kernel" +#undef PATH_KERNEL #define PATH_KERNEL "/boot/kernel/kernel.gz.tramp" extern uint32_t _end; #define NOPT 6 -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - static const char optstr[NOPT] = "agnrsv"; static const unsigned char flags[NOPT] = { RBX_ASKNAME, diff --git a/sys/boot/arm/ixp425/boot2/boot2.c b/sys/boot/arm/ixp425/boot2/boot2.c index e5f4982..93c4fe1 100644 --- a/sys/boot/arm/ixp425/boot2/boot2.c +++ b/sys/boot/arm/ixp425/boot2/boot2.c @@ -28,51 +28,13 @@ __FBSDID("$FreeBSD$"); #include #include "lib.h" - -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -/* #define RBX_KDB 0x6 -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -/* #define RBX_SERIAL 0xc -h */ -/* #define RBX_CDROM 0xd -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -/* #define RBX_MUTE 0x10 -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -/* #define RBX_PAUSE 0x14 -p */ -/* #define RBX_QUIET 0x15 -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -/* #define RBX_DUAL 0x1d -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -v, -g */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | \ - OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_GDB)) - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_KERNEL "/boot/kernel/kernel" +#include "paths.h" +#include "rbx.h" extern uint32_t _end; #define NOPT 6 -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - static const char optstr[NOPT] = "agnrsv"; static const unsigned char flags[NOPT] = { RBX_ASKNAME, diff --git a/sys/boot/common/paths.h b/sys/boot/common/paths.h new file mode 100644 index 0000000..9ed45e6 --- /dev/null +++ b/sys/boot/common/paths.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2016 M. Warner Losh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +#define PATH_DOTCONFIG "/boot.config" +#define PATH_CONFIG "/boot/config" +#define PATH_LOADER "/boot/loader" +#define PATH_LOADER_EFI "/boot/loader.efi" +#define PATH_LOADER_ZFS "/boot/zfsloader" +#define PATH_KERNEL "/boot/kernel/kernel" + +#endif /* _PATHS_H_ */ diff --git a/sys/boot/common/rbx.h b/sys/boot/common/rbx.h new file mode 100644 index 0000000..21371a5 --- /dev/null +++ b/sys/boot/common/rbx.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1998 Robert Nordier + * All rights reserved. + * + * Redistribution and use in source and binary forms are freely + * permitted provided that the above copyright notice and this + * paragraph and the following disclaimer are duplicated in all + * such forms. + * + * This software is provided "AS IS" and without any express or + * implied warranties, including, without limitation, the implied + * warranties of merchantability and fitness for a particular + * purpose. + * + * $FreeBSD$ + */ + +#ifndef _RBX_H_ +#define _RBX_H_ + +#define RBX_ASKNAME 0x0 /* -a */ +#define RBX_SINGLE 0x1 /* -s */ +/* 0x2 is reserved for log2(RB_NOSYNC). */ +/* 0x3 is reserved for log2(RB_HALT). */ +/* 0x4 is reserved for log2(RB_INITNAME). */ +#define RBX_DFLTROOT 0x5 /* -r */ +#define RBX_KDB 0x6 /* -d */ +/* 0x7 is reserved for log2(RB_RDONLY). */ +/* 0x8 is reserved for log2(RB_DUMP). */ +/* 0x9 is reserved for log2(RB_MINIROOT). */ +#define RBX_CONFIG 0xa /* -c */ +#define RBX_VERBOSE 0xb /* -v */ +#define RBX_SERIAL 0xc /* -h */ +#define RBX_CDROM 0xd /* -C */ +/* 0xe is reserved for log2(RB_POWEROFF). */ +#define RBX_GDB 0xf /* -g */ +#define RBX_MUTE 0x10 /* -m */ +/* 0x11 is reserved for log2(RB_SELFTEST). */ +/* 0x12 is reserved for boot programs. */ +/* 0x13 is reserved for boot programs. */ +#define RBX_PAUSE 0x14 /* -p */ +#define RBX_QUIET 0x15 /* -q */ +#define RBX_NOINTR 0x1c /* -n */ +/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ +#define RBX_DUAL 0x1d /* -D */ +/* 0x1f is reserved for log2(RB_BOOTINFO). */ + +/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ +#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ + OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ + OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ + OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ + OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ + OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) + +#define OPT_SET(opt) (1 << (opt)) +#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) + +extern uint32_t opts; + +#endif /* !_RBX_H_ */ diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index f046235..0aa6c5b 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -31,8 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include "boot_module.h" - -#define _PATH_LOADER "/boot/loader.efi" +#include "paths.h" static const boot_module_t *boot_modules[] = { @@ -99,13 +98,13 @@ try_load(const boot_module_t *mod) EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; - status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize); + status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize); if (status == EFI_NOT_FOUND) return; if (status != EFI_SUCCESS) { - printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER, - EFI_ERROR_CODE(status)); + printf("%s failed to load %s (%lu)\n", mod->name, + PATH_LOADER_EFI, EFI_ERROR_CODE(status)); return; } @@ -174,7 +173,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) conout->ClearScreen(conout); printf("\n>> FreeBSD EFI boot block\n"); - printf(" Loader path: %s\n\n", _PATH_LOADER); + printf(" Loader path: %s\n\n", PATH_LOADER_EFI); printf(" Initializing modules:"); for (i = 0; i < NUM_BOOT_MODULES; i++) { if (boot_modules[i] == NULL) diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c index cd384e5..401a933 100644 --- a/sys/boot/i386/boot2/boot2.c +++ b/sys/boot/i386/boot2/boot2.c @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); #include "boot2.h" #include "lib.h" +#include "paths.h" +#include "rbx.h" /* Define to 0 to omit serial support */ #ifndef SERIAL @@ -52,46 +54,6 @@ __FBSDID("$FreeBSD$"); #define SECOND 18 /* Circa that many ticks in a second. */ -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -#define RBX_KDB 0x6 /* -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -#define RBX_SERIAL 0xc /* -h */ -#define RBX_CDROM 0xd /* -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -#define RBX_MUTE 0x10 /* -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -#define RBX_PAUSE 0x14 /* -p */ -#define RBX_QUIET 0x15 /* -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -#define RBX_DUAL 0x1d /* -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ - OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ - OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ - OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_BOOT3 "/boot/loader" -#define PATH_KERNEL "/boot/kernel/kernel" - #define ARGS 0x900 #define NOPT 14 #define NDEV 3 @@ -106,9 +68,6 @@ __FBSDID("$FreeBSD$"); #define TYPE_MAXHARD TYPE_DA #define TYPE_FD 2 -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - extern uint32_t _end; static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ @@ -143,7 +102,7 @@ static struct dsk { } dsk; static char cmd[512], cmddup[512], knamebuf[1024]; static const char *kname; -static uint32_t opts; +uint32_t opts; static struct bootinfo bootinfo; #if SERIAL static int comspeed = SIOSPD; @@ -275,7 +234,7 @@ main(void) */ if (!kname) { - kname = PATH_BOOT3; + kname = PATH_LOADER; if (autoboot && !keyhit(3*SECOND)) { load(); kname = PATH_KERNEL; diff --git a/sys/boot/i386/common/rbx.h b/sys/boot/i386/common/rbx.h deleted file mode 100644 index 21371a5..0000000 --- a/sys/boot/i386/common/rbx.h +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * Copyright (c) 1998 Robert Nordier - * All rights reserved. - * - * Redistribution and use in source and binary forms are freely - * permitted provided that the above copyright notice and this - * paragraph and the following disclaimer are duplicated in all - * such forms. - * - * This software is provided "AS IS" and without any express or - * implied warranties, including, without limitation, the implied - * warranties of merchantability and fitness for a particular - * purpose. - * - * $FreeBSD$ - */ - -#ifndef _RBX_H_ -#define _RBX_H_ - -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -#define RBX_KDB 0x6 /* -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -#define RBX_SERIAL 0xc /* -h */ -#define RBX_CDROM 0xd /* -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -#define RBX_MUTE 0x10 /* -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -#define RBX_PAUSE 0x14 /* -p */ -#define RBX_QUIET 0x15 /* -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -#define RBX_DUAL 0x1d /* -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ - OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ - OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ - OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) - -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - -extern uint32_t opts; - -#endif /* !_RBX_H_ */ diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c index 0596499..5316706 100644 --- a/sys/boot/i386/gptboot/gptboot.c +++ b/sys/boot/i386/gptboot/gptboot.c @@ -37,11 +37,7 @@ __FBSDID("$FreeBSD$"); #include "util.h" #include "cons.h" #include "gpt.h" - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_BOOT3 "/boot/loader" -#define PATH_KERNEL "/boot/kernel/kernel" +#include "paths.h" #define ARGS 0x900 #define NOPT 14 @@ -180,7 +176,7 @@ main(void) if (autoboot && keyhit(3)) { if (*kname == '\0') - memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); + memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); break; } autoboot = 0; @@ -192,7 +188,7 @@ main(void) */ if (*kname != '\0') load(); - memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); + memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); load(); memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); load(); diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c index ca82c63..6fbbc6f 100644 --- a/sys/boot/i386/zfsboot/zfsboot.c +++ b/sys/boot/i386/zfsboot/zfsboot.c @@ -42,14 +42,10 @@ __FBSDID("$FreeBSD$"); #include "util.h" #include "cons.h" #include "bootargs.h" +#include "paths.h" #include "libzfs.h" -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_BOOT3 "/boot/zfsloader" -#define PATH_KERNEL "/boot/kernel/kernel" - #define ARGS 0x900 #define NOPT 14 #define NDEV 3 @@ -550,12 +546,12 @@ main(void) } /* - * Try to exec stage 3 boot loader. If interrupted by a keypress, + * Try to exec /boot/loader. If interrupted by a keypress, * or in case of failure, try to load a kernel directly instead. */ if (autoboot && !*kname) { - memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); + memcpy(kname, PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS)); if (!keyhit(3)) { load(); memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); diff --git a/sys/boot/pc98/boot2/boot2.c b/sys/boot/pc98/boot2/boot2.c index 72aae7d..bcd54f4 100644 --- a/sys/boot/pc98/boot2/boot2.c +++ b/sys/boot/pc98/boot2/boot2.c @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$"); #include "boot2.h" #include "lib.h" +#include "paths.h" +#include "rbx.h" /* Define to 0 to omit serial support */ #ifndef SERIAL @@ -54,46 +56,6 @@ __FBSDID("$FreeBSD$"); #define SECOND 1 /* Circa that many ticks in a second. */ -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -#define RBX_KDB 0x6 /* -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -#define RBX_SERIAL 0xc /* -h */ -#define RBX_CDROM 0xd /* -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -#define RBX_MUTE 0x10 /* -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -#define RBX_PAUSE 0x14 /* -p */ -#define RBX_QUIET 0x15 /* -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -#define RBX_DUAL 0x1d /* -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ - OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ - OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ - OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_BOOT3 "/boot/loader" -#define PATH_KERNEL "/boot/kernel/kernel" - #define ARGS 0x900 #define NOPT 14 #define NDEV 3 @@ -105,9 +67,6 @@ __FBSDID("$FreeBSD$"); #define TYPE_DA 1 #define TYPE_FD 2 -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - extern uint32_t _end; static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ @@ -145,7 +104,7 @@ static struct dsk { } dsk; static char cmd[512], cmddup[512], knamebuf[1024]; static const char *kname; -static uint32_t opts; +uint32_t opts; static struct bootinfo bootinfo; #if SERIAL static int comspeed = SIOSPD; @@ -414,7 +373,7 @@ main(void) */ if (!kname) { - kname = PATH_BOOT3; + kname = PATH_LOADER; if (autoboot && !keyhit(3*SECOND)) { load(); kname = PATH_KERNEL; diff --git a/sys/boot/powerpc/boot1.chrp/boot1.c b/sys/boot/powerpc/boot1.chrp/boot1.c index af22488..9c50359 100644 --- a/sys/boot/powerpc/boot1.chrp/boot1.c +++ b/sys/boot/powerpc/boot1.chrp/boot1.c @@ -23,8 +23,7 @@ __FBSDID("$FreeBSD$"); #include #include -#define _PATH_LOADER "/boot/loader" -#define _PATH_KERNEL "/boot/kernel/kernel" +#include "paths.h" #define BSIZEMAX 16384 @@ -396,7 +395,7 @@ main(int ac, char **av) char bootpath_full[255]; int i, len; - path = _PATH_LOADER; + path = PATH_LOADER; for (i = 0; i < ac; i++) { switch (av[i][0]) { case '-': diff --git a/sys/boot/sparc64/boot1/boot1.c b/sys/boot/sparc64/boot1/boot1.c index 6c43c93..d0b7380 100644 --- a/sys/boot/sparc64/boot1/boot1.c +++ b/sys/boot/sparc64/boot1/boot1.c @@ -24,8 +24,8 @@ __FBSDID("$FreeBSD$"); #include #include -#define _PATH_LOADER "/boot/loader" -#define _PATH_KERNEL "/boot/kernel/kernel" +#include "paths.h" + #define READ_BUF_SIZE 8192 typedef int putc_func_t(char c, void *arg); @@ -324,7 +324,7 @@ main(int ac, char **av) const char *path; int i; - path = _PATH_LOADER; + path = PATH_LOADER; for (i = 0; i < ac; i++) { switch (av[i][0]) { case '-': -- cgit v1.1 From cb56e836d9a9db908a5f1e021e6483e1e8aab048 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 10 Feb 2016 00:08:51 +0000 Subject: MFC 287442,287537,288944: Fix corruption of coredumps due to procstat notes changing size during coredump generation. The changes in r287442 required some reworking since the 'fo_fill_kinfo' file op does not exist in stable/10. 287442: Detect badly behaved coredump note helpers Coredump notes depend on being able to invoke dump routines twice; once in a dry-run mode to get the size of the note, and another to actually emit the note to the corefile. When a note helper emits a different length section the second time around than the length it requested the first time, the kernel produces a corrupt coredump. NT_PROCSTAT_FILES output length, when packing kinfo structs, is tied to the length of filenames corresponding to vnodes in the process' fd table via vn_fullpath. As vnodes may move around during dump, this is racy. So: - Detect badly behaved notes in putnote() and pad underfilled notes. - Add a fail point, debug.fail_point.fill_kinfo_vnode__random_path to exercise the NT_PROCSTAT_FILES corruption. It simply picks random lengths to expand or truncate paths to in fo_fill_kinfo_vnode(). - Add a sysctl, kern.coredump_pack_fileinfo, to allow users to disable kinfo packing for PROCSTAT_FILES notes. This should avoid both FILES note corruption and truncation, even if filenames change, at the cost of about 1 kiB in padding bloat per open fd. Document the new sysctl in core.5. - Fix note_procstat_files to self-limit in the 2nd pass. Since sometimes this will result in a short write, pad up to our advertised size. This addresses note corruption, at the risk of sometimes truncating the last several fd info entries. - Fix NT_PROCSTAT_FILES consumers libutil and libprocstat to grok the zero padding. 287537: Follow-up to r287442: Move sysctl to compiled-once file Avoid duplicate sysctl nodes. 288944: Fix core corruption caused by race in note_procstat_vmmap This fix is spiritually similar to r287442 and was discovered thanks to the KASSERT added in that revision. NT_PROCSTAT_VMMAP output length, when packing kinfo structs, is tied to the length of filenames corresponding to vnodes in the process' vm map via vn_fullpath. As vnodes may move during coredump, this is racy. We do not remove the race, only prevent it from causing coredump corruption. - Add a sysctl, kern.coredump_pack_vmmapinfo, to allow users to disable kinfo packing for PROCSTAT_VMMAP notes. This avoids VMMAP corruption and truncation, even if names change, at the cost of up to PATH_MAX bytes per mapped object. The new sysctl is documented in core.5. - Fix note_procstat_vmmap to self-limit in the second pass. This addresses corruption, at the cost of sometimes producing a truncated result. - Fix PROCSTAT_VMMAP consumers libutil (and libprocstat, via copy-paste) to grok the new zero padding. Approved by: re (gjb) --- lib/libprocstat/libprocstat.c | 8 +++++ lib/libutil/kinfo_getfile.c | 4 +++ lib/libutil/kinfo_getvmmap.c | 4 +++ share/man/man5/core.5 | 25 +++++++++++++- sys/kern/imgact_elf.c | 77 ++++++++++++++++++++++++++++++++++++------- sys/kern/kern_descrip.c | 40 +++++++++++++++++++--- sys/kern/kern_exec.c | 10 ++++++ sys/kern/kern_proc.c | 23 ++++++++++--- sys/sys/exec.h | 3 ++ sys/sys/user.h | 11 +++++-- 10 files changed, 181 insertions(+), 24 deletions(-) diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index 727419b..7b0722c 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -767,6 +767,8 @@ kinfo_getfile_core(struct procstat_core *core, int *cntp) eb = buf + len; while (bp < eb) { kf = (struct kinfo_file *)(uintptr_t)bp; + if (kf->kf_structsize == 0) + break; bp += kf->kf_structsize; cnt++; } @@ -782,6 +784,8 @@ kinfo_getfile_core(struct procstat_core *core, int *cntp) /* Pass 2: unpack */ while (bp < eb) { kf = (struct kinfo_file *)(uintptr_t)bp; + if (kf->kf_structsize == 0) + break; /* Copy/expand into pre-zeroed buffer */ memcpy(kp, kf, kf->kf_structsize); /* Advance to next packed record */ @@ -1863,6 +1867,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp) eb = buf + len; while (bp < eb) { kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (kv->kve_structsize == 0) + break; bp += kv->kve_structsize; cnt++; } @@ -1878,6 +1884,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp) /* Pass 2: unpack */ while (bp < eb) { kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (kv->kve_structsize == 0) + break; /* Copy/expand into pre-zeroed buffer */ memcpy(kp, kv, kv->kve_structsize); /* Advance to next packed record */ diff --git a/lib/libutil/kinfo_getfile.c b/lib/libutil/kinfo_getfile.c index 84b64db..8a5477f 100644 --- a/lib/libutil/kinfo_getfile.c +++ b/lib/libutil/kinfo_getfile.c @@ -44,6 +44,8 @@ kinfo_getfile(pid_t pid, int *cntp) eb = buf + len; while (bp < eb) { kf = (struct kinfo_file *)(uintptr_t)bp; + if (kf->kf_structsize == 0) + break; bp += kf->kf_structsize; cnt++; } @@ -59,6 +61,8 @@ kinfo_getfile(pid_t pid, int *cntp) /* Pass 2: unpack */ while (bp < eb) { kf = (struct kinfo_file *)(uintptr_t)bp; + if (kf->kf_structsize == 0) + break; /* Copy/expand into pre-zeroed buffer */ memcpy(kp, kf, kf->kf_structsize); /* Advance to next packed record */ diff --git a/lib/libutil/kinfo_getvmmap.c b/lib/libutil/kinfo_getvmmap.c index 129aa03..9d9e427 100644 --- a/lib/libutil/kinfo_getvmmap.c +++ b/lib/libutil/kinfo_getvmmap.c @@ -44,6 +44,8 @@ kinfo_getvmmap(pid_t pid, int *cntp) eb = buf + len; while (bp < eb) { kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (kv->kve_structsize == 0) + break; bp += kv->kve_structsize; cnt++; } @@ -59,6 +61,8 @@ kinfo_getvmmap(pid_t pid, int *cntp) /* Pass 2: unpack */ while (bp < eb) { kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (kv->kve_structsize == 0) + break; /* Copy/expand into pre-zeroed buffer */ memcpy(kp, kv, kv->kve_structsize); /* Advance to next packed record */ diff --git a/share/man/man5/core.5 b/share/man/man5/core.5 index e8a1653..a5fefc0 100644 --- a/share/man/man5/core.5 +++ b/share/man/man5/core.5 @@ -32,7 +32,7 @@ .\" @(#)core.5 8.3 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd November 22, 2012 +.Dd October 5, 2015 .Dt CORE 5 .Os .Sh NAME @@ -126,6 +126,29 @@ Core files will have the suffix .Em .gz appended to them. .El +.Sh NOTES +Corefiles are written with open file descriptor information as an ELF note. +By default, file paths are packed to only use as much space as needed. +However, file paths can change at any time, including during core dump, +and this can result in truncated file descriptor data. +.Pp +All file descriptor information can be preserved by disabling packing. +This potentially wastes up to PATH_MAX bytes per open fd. +Packing is disabled with +.Dl sysctl kern.coredump_pack_fileinfo=0 . +.Pp +Similarly, corefiles are written with vmmap information as an ELF note, which +contains file paths. +By default, they are packed to only use as much space as +needed. +By the same mechanism as for the open files note, these paths can also +change at any time and result in a truncated note. +.Pp +All vmmap information can be preserved by disabling packing. +Like the file information, this potentially wastes up to PATH_MAX bytes per +mapped object. +Packing is disabled with +.Dl sysctl kern.coredump_pack_vmmapinfo=0 . .Sh EXAMPLES In order to store all core images in per-user private areas under .Pa /var/coredumps , diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 394d61f..e3c08de 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1709,7 +1709,8 @@ static void __elfN(putnote)(struct note_info *ninfo, struct sbuf *sb) { Elf_Note note; - ssize_t old_len; + ssize_t old_len, sect_len; + size_t new_len, descsz, i; if (ninfo->type == -1) { ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); @@ -1728,7 +1729,33 @@ __elfN(putnote)(struct note_info *ninfo, struct sbuf *sb) return; sbuf_start_section(sb, &old_len); ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); - sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); + sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); + if (sect_len < 0) + return; + + new_len = (size_t)sect_len; + descsz = roundup(note.n_descsz, ELF_NOTE_ROUNDSIZE); + if (new_len < descsz) { + /* + * It is expected that individual note emitters will correctly + * predict their expected output size and fill up to that size + * themselves, padding in a format-specific way if needed. + * However, in case they don't, just do it here with zeros. + */ + for (i = 0; i < descsz - new_len; i++) + sbuf_putc(sb, 0); + } else if (new_len > descsz) { + /* + * We can't always truncate sb -- we may have drained some + * of it already. + */ + KASSERT(new_len == descsz, ("%s: Note type %u changed as we " + "read it (%zu > %zu). Since it is longer than " + "expected, this coredump's notes are corrupt. THIS " + "IS A BUG in the note_procstat routine for type %u.\n", + __func__, (unsigned)note.n_type, new_len, descsz, + (unsigned)note.n_type)); + } } /* @@ -1909,25 +1936,47 @@ static void note_procstat_files(void *arg, struct sbuf *sb, size_t *sizep) { struct proc *p; - size_t size; - int structsize; + size_t size, sect_sz, i; + ssize_t start_len, sect_len; + int structsize, filedesc_flags; + + if (coredump_pack_fileinfo) + filedesc_flags = KERN_FILEDESC_PACK_KINFO; + else + filedesc_flags = 0; p = (struct proc *)arg; + structsize = sizeof(struct kinfo_file); if (sb == NULL) { size = 0; sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN); sbuf_set_drain(sb, sbuf_drain_count, &size); sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); - kern_proc_filedesc_out(p, sb, -1); + kern_proc_filedesc_out(p, sb, -1, filedesc_flags); sbuf_finish(sb); sbuf_delete(sb); *sizep = size; } else { - structsize = sizeof(struct kinfo_file); + sbuf_start_section(sb, &start_len); + sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); - kern_proc_filedesc_out(p, sb, -1); + kern_proc_filedesc_out(p, sb, *sizep - sizeof(structsize), + filedesc_flags); + + sect_len = sbuf_end_section(sb, start_len, 0, 0); + if (sect_len < 0) + return; + sect_sz = sect_len; + + KASSERT(sect_sz <= *sizep, + ("kern_proc_filedesc_out did not respect maxlen; " + "requested %zu, got %zu", *sizep - sizeof(structsize), + sect_sz - sizeof(structsize))); + + for (i = 0; i < *sizep - sect_sz && sb->s_error == 0; i++) + sbuf_putc(sb, 0); } } @@ -1940,24 +1989,30 @@ note_procstat_vmmap(void *arg, struct sbuf *sb, size_t *sizep) { struct proc *p; size_t size; - int structsize; + int structsize, vmmap_flags; + + if (coredump_pack_vmmapinfo) + vmmap_flags = KERN_VMMAP_PACK_KINFO; + else + vmmap_flags = 0; p = (struct proc *)arg; + structsize = sizeof(struct kinfo_vmentry); if (sb == NULL) { size = 0; sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN); sbuf_set_drain(sb, sbuf_drain_count, &size); sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); - kern_proc_vmmap_out(p, sb); + kern_proc_vmmap_out(p, sb, -1, vmmap_flags); sbuf_finish(sb); sbuf_delete(sb); *sizep = size; } else { - structsize = sizeof(struct kinfo_vmentry); sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); - kern_proc_vmmap_out(p, sb); + kern_proc_vmmap_out(p, sb, *sizep - sizeof(structsize), + vmmap_flags); } } diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 4930e2f..7561368 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -3299,6 +3300,7 @@ struct export_fd_buf { struct sbuf *sb; ssize_t remainder; struct kinfo_file kif; + int flags; }; static int @@ -3385,9 +3387,12 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt, kif->kf_type = type; kif->kf_ref_count = refcnt; kif->kf_offset = offset; - /* Pack record size down */ - kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + - strlen(kif->kf_path) + 1; + if ((efbuf->flags & KERN_FILEDESC_PACK_KINFO) != 0) + /* Pack record size down */ + kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + + strlen(kif->kf_path) + 1; + else + kif->kf_structsize = sizeof(*kif); kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t)); if (efbuf->remainder != -1) { if (efbuf->remainder < kif->kf_structsize) { @@ -3413,7 +3418,8 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt, * Takes a locked proc as argument, and returns with the proc unlocked. */ int -kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) +kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, + int flags) { struct file *fp; struct filedesc *fdp; @@ -3448,6 +3454,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) efbuf->fdp = NULL; efbuf->sb = sb; efbuf->remainder = maxlen; + efbuf->flags = flags; if (tracevp != NULL) export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE, FREAD | FWRITE, -1, -1, NULL, efbuf); @@ -3597,7 +3604,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) return (error); } maxlen = req->oldptr != NULL ? req->oldlen : -1; - error = kern_proc_filedesc_out(p, &sb, maxlen); + error = kern_proc_filedesc_out(p, &sb, maxlen, + KERN_FILEDESC_PACK_KINFO); error2 = sbuf_finish(&sb); sbuf_delete(&sb); return (error != 0 ? error : error2); @@ -3635,6 +3643,24 @@ vntype_to_kinfo(int vtype) return (KF_VTYPE_UNKNOWN); } +static inline void +vn_fill_junk(struct kinfo_file *kif) +{ + size_t len, olen; + + /* + * Simulate vn_fullpath returning changing values for a given + * vp during e.g. coredump. + */ + len = (arc4random() % (sizeof(kif->kf_path) - 2)) + 1; + olen = strlen(kif->kf_path); + if (len < olen) + strcpy(&kif->kf_path[len - 1], "$"); + else + for (; olen < len; olen++) + strcpy(&kif->kf_path[olen], "A"); +} + static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif) { @@ -3654,6 +3680,10 @@ fill_vnode_info(struct vnode *vp, struct kinfo_file *kif) if (freepath != NULL) free(freepath, M_TEMP); + KFAIL_POINT_CODE(DEBUG_FP, fill_kinfo_vnode__random_path, + vn_fill_junk(kif); + ); + /* * Retrieve vnode attributes. */ diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index f82ffec..47ea9b0 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -102,6 +102,16 @@ SDT_PROBE_DEFINE1(proc, kernel, , exec__success, "char *"); MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); +int coredump_pack_fileinfo = 1; +SYSCTL_INT(_kern, OID_AUTO, coredump_pack_fileinfo, CTLFLAG_RWTUN, + &coredump_pack_fileinfo, 0, + "Enable file path packing in 'procstat -f' coredump notes"); + +int coredump_pack_vmmapinfo = 1; +SYSCTL_INT(_kern, OID_AUTO, coredump_pack_vmmapinfo, CTLFLAG_RWTUN, + &coredump_pack_vmmapinfo, 0, + "Enable file path packing in 'procstat -v' coredump notes"); + static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 6b60840..cfaa354 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2228,7 +2228,7 @@ next:; * Must be called with the process locked and will return unlocked. */ int -kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) +kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags) { vm_map_entry_t entry, tmp_entry; struct vattr va; @@ -2252,7 +2252,7 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) PRELE(p); return (ESRCH); } - kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK); + kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK | M_ZERO); error = 0; map = &vm->vm_map; @@ -2387,10 +2387,23 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) free(freepath, M_TEMP); /* Pack record size down */ - kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) + - strlen(kve->kve_path) + 1; + if ((flags & KERN_VMMAP_PACK_KINFO) != 0) + kve->kve_structsize = + offsetof(struct kinfo_vmentry, kve_path) + + strlen(kve->kve_path) + 1; + else + kve->kve_structsize = sizeof(*kve); kve->kve_structsize = roundup(kve->kve_structsize, sizeof(uint64_t)); + + /* Halt filling and truncate rather than exceeding maxlen */ + if (maxlen != -1 && maxlen < kve->kve_structsize) { + error = 0; + vm_map_lock_read(map); + break; + } else if (maxlen != -1) + maxlen -= kve->kve_structsize; + if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0) error = ENOMEM; vm_map_lock_read(map); @@ -2422,7 +2435,7 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) sbuf_delete(&sb); return (error); } - error = kern_proc_vmmap_out(p, &sb); + error = kern_proc_vmmap_out(p, &sb, -1, KERN_VMMAP_PACK_KINFO); error2 = sbuf_finish(&sb); sbuf_delete(&sb); return (error != 0 ? error : error2); diff --git a/sys/sys/exec.h b/sys/sys/exec.h index cccebfd..0ccba24 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -83,6 +83,9 @@ void exec_unmap_first_page(struct image_params *); int exec_register(const struct execsw *); int exec_unregister(const struct execsw *); +extern int coredump_pack_fileinfo; +extern int coredump_pack_vmmapinfo; + /* * note: name##_mod cannot be const storage because the * linker_file_sysinit() function modifies _file in the diff --git a/sys/sys/user.h b/sys/sys/user.h index 9374daf..a697b66 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -536,6 +536,11 @@ struct kinfo_sigtramp { #define KERN_PROC_NOTHREADS 0x1 #define KERN_PROC_MASK32 0x2 +/* Flags for kern_proc_filedesc_out. */ +#define KERN_FILEDESC_PACK_KINFO 0x00000001U + +/* Flags for kern_proc_vmmap_out. */ +#define KERN_VMMAP_PACK_KINFO 0x00000001U struct sbuf; /* @@ -547,9 +552,11 @@ struct sbuf; * to be locked on enter. On return the process is unlocked. */ -int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen); +int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, + int flags); int kern_proc_out(struct proc *p, struct sbuf *sb, int flags); -int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb); +int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, + int flags); int vntype_to_kinfo(int vtype); #endif /* !_KERNEL */ -- cgit v1.1 From ab8cd691029d03339e2c5ca0d056aae390b2e7ac Mon Sep 17 00:00:00 2001 From: cy Date: Wed, 10 Feb 2016 07:16:17 +0000 Subject: MFC r289421, r293037, r294773, and r294884. ntp leap-leapseconds support. r289421: Add default leap-seconds file. This should help ntp networks get the leap second date correct Updates to the file can be obtained from ftp://time.nist.gov/pub/ or ftp://tycho.usno.navy.mil/pub/ntp/. r293037: Update leap-seconds to latest. This will satisfy the ntpd leap-second version check. r294773: Add support for automatic leap-second file updates. The working copy of leapfile resides in /var/dbntpd.leap-seconds.list. /etc/ntp/leap-seconds (periodically updated from ftp://time.nist.gov/pub/ or ftp://tycho.usno.navy.mil/pub/ntp/) contains the master copy should automatic leapfile updates be disabled (default). Automatic leapfile updates are fetched from $ntp_leapfile_sources, defaulting to https://www.ietf.org/timezones/data/leap-seconds.list, within $ntp_leapfile_expiry_days (default 30 days) from leap-seconds file expiry. Automatic updates can be enabled by setting $daily_ntpd_leapfile_enable="YES" in periodic.conf. To avoid congesting the ntp leapfile source the automatic update randomized by default but can be disabled through daily_ntpd_avoid_congestion="NO" in periodic.conf. r294884: Allow specification of fetch options for ntp leap-seconds fetch. Approved by: re (gjb) --- etc/Makefile | 3 + etc/defaults/periodic.conf | 5 + etc/defaults/rc.conf | 11 ++ etc/mtree/BSD.var.dist | 2 + etc/ntp.conf | 7 ++ etc/ntp/Makefile | 10 ++ etc/ntp/leap-seconds | 221 +++++++++++++++++++++++++++++++++++ etc/periodic/daily/480.leapfile-ntpd | 28 +++++ etc/periodic/daily/Makefile | 3 +- etc/rc.d/ntpd | 67 +++++++++++ 10 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 etc/ntp/Makefile create mode 100644 etc/ntp/leap-seconds create mode 100755 etc/periodic/daily/480.leapfile-ntpd diff --git a/etc/Makefile b/etc/Makefile index 1030f5f..ffc299f 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -244,6 +244,9 @@ distribution: ${_+_}cd ${.CURDIR}/defaults; ${MAKE} install ${_+_}cd ${.CURDIR}/devd; ${MAKE} install ${_+_}cd ${.CURDIR}/gss; ${MAKE} install +.if ${MK_NTP} != "no" + ${_+_}cd ${.CURDIR}/ntp; ${MAKE} install +.endif ${_+_}cd ${.CURDIR}/periodic; ${MAKE} install .if ${MK_PKGBOOTSTRAP} != "no" ${_+_}cd ${.CURDIR}/pkg; ${MAKE} install diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf index d97bd93..487a356 100644 --- a/etc/defaults/periodic.conf +++ b/etc/defaults/periodic.conf @@ -138,6 +138,11 @@ daily_status_mail_rejects_enable="YES" # Check mail rejects daily_status_mail_rejects_logs=3 # How many logs to check daily_status_mail_rejects_shorten="NO" # Shorten output +# 480.leapfile-ntpd +daily_ntpd_leapfile_enable="NO" # Fetch NTP leapfile +daily_ntpd_avoid_congestion="YES" # Avoid congesting + # leapfile sources + # 480.status-ntpd daily_status_ntpd_enable="NO" # Check NTP status diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index da3158c..ddaf657 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -366,6 +366,17 @@ ntpd_config="/etc/ntp.conf" # ntpd(8) configuration file ntpd_sync_on_start="NO" # Sync time on ntpd startup, even if offset is high ntpd_flags="-p /var/run/ntpd.pid -f /var/db/ntpd.drift" # Flags to ntpd (if enabled). +ntp_src_leapfile="/etc/ntp/leap-seconds" + # Initial source for ntpd leapfile +ntp_db_leapfile="/var/db/ntpd.leap-seconds.list" + # Working copy (updated weekly) leapfile +ntp_leapfile_sources="https://www.ietf.org/timezones/data/leap-seconds.list" + # Source from which to fetch leapfile +ntp_leapfile_fetch_opts="-mq" # Options to use for ntp leapfile fetch, + # e.g. --no-verify-peer +ntp_leapfile_expiry_days=30 # Check for new leapfile 30 days prior to + # expiry. +ntp_leapfile_fetch_verbose="NO" # Be verbose during NTP leapfile fetch # Network Information Services (NIS) options: All need rpcbind_enable="YES" ### nis_client_enable="NO" # We're an NIS client (or NO). diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist index 2403814..4082ad4 100644 --- a/etc/mtree/BSD.var.dist +++ b/etc/mtree/BSD.var.dist @@ -46,6 +46,8 @@ .. ipf mode=0700 .. + ntp mode=0700 + .. pkg .. ports diff --git a/etc/ntp.conf b/etc/ntp.conf index ea39877..64edd93 100644 --- a/etc/ntp.conf +++ b/etc/ntp.conf @@ -77,3 +77,10 @@ restrict 127.127.1.0 # #server 127.127.1.0 #fudge 127.127.1.0 stratum 10 + +# See http://support.ntp.org/bin/view/Support/ConfiguringNTP#Section_6.14. +# for documentation regarding leapfile. Updates to the file can be obtained +# from ftp://time.nist.gov/pub/ or ftp://tycho.usno.navy.mil/pub/ntp/. +# Use either leapfile in /etc/ntp or weekly updated leapfile in /var/db. +#leapfile "/etc/ntp/leap-seconds" +leapfile "/var/db/ntpd.leap-seconds.list" diff --git a/etc/ntp/Makefile b/etc/ntp/Makefile new file mode 100644 index 0000000..f1aff4f --- /dev/null +++ b/etc/ntp/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +NO_OBJ= + +FILES= leap-seconds + +FILESDIR= /etc/ntp +FILESMODE= 644 + +.include diff --git a/etc/ntp/leap-seconds b/etc/ntp/leap-seconds new file mode 100644 index 0000000..8fa6225 --- /dev/null +++ b/etc/ntp/leap-seconds @@ -0,0 +1,221 @@ +# +# $FreeBSD$ +# +# In the following text, the symbol '#' introduces +# a comment, which continues from that symbol until +# the end of the line. A plain comment line has a +# whitespace character following the comment indicator. +# There are also special comment lines defined below. +# A special comment will always have a non-whitespace +# character in column 2. +# +# A blank line should be ignored. +# +# The following table shows the corrections that must +# be applied to compute International Atomic Time (TAI) +# from the Coordinated Universal Time (UTC) values that +# are transmitted by almost all time services. +# +# The first column shows an epoch as a number of seconds +# since 1900.0 and the second column shows the number of +# seconds that must be added to UTC to compute TAI for +# any timestamp at or after that epoch. The value on +# each line is valid from the indicated initial instant +# until the epoch given on the next one or indefinitely +# into the future if there is no next line. +# (The comment on each line shows the representation of +# the corresponding initial epoch in the usual +# day-month-year format. The epoch always begins at +# 00:00:00 UTC on the indicated day. See Note 5 below.) +# +# Important notes: +# +# 1. Coordinated Universal Time (UTC) is often referred to +# as Greenwich Mean Time (GMT). The GMT time scale is no +# longer used, and the use of GMT to designate UTC is +# discouraged. +# +# 2. The UTC time scale is realized by many national +# laboratories and timing centers. Each laboratory +# identifies its realization with its name: Thus +# UTC(NIST), UTC(USNO), etc. The differences among +# these different realizations are typically on the +# order of a few nanoseconds (i.e., 0.000 000 00x s) +# and can be ignored for many purposes. These differences +# are tabulated in Circular T, which is published monthly +# by the International Bureau of Weights and Measures +# (BIPM). See www.bipm.fr for more information. +# +# 3. The current defintion of the relationship between UTC +# and TAI dates from 1 January 1972. A number of different +# time scales were in use before than epoch, and it can be +# quite difficult to compute precise timestamps and time +# intervals in those "prehistoric" days. For more information, +# consult: +# +# The Explanatory Supplement to the Astronomical +# Ephemeris. +# or +# Terry Quinn, "The BIPM and the Accurate Measurement +# of Time," Proc. of the IEEE, Vol. 79, pp. 894-905, +# July, 1991. +# +# 4. The insertion of leap seconds into UTC is currently the +# responsibility of the International Earth Rotation Service, +# which is located at the Paris Observatory: +# +# Central Bureau of IERS +# 61, Avenue de l'Observatoire +# 75014 Paris, France. +# +# Leap seconds are announced by the IERS in its Bulletin C +# +# See hpiers.obspm.fr or www.iers.org for more details. +# +# All national laboratories and timing centers use the +# data from the BIPM and the IERS to construct their +# local realizations of UTC. +# +# Although the definition also includes the possibility +# of dropping seconds ("negative" leap seconds), this has +# never been done and is unlikely to be necessary in the +# foreseeable future. +# +# 5. If your system keeps time as the number of seconds since +# some epoch (e.g., NTP timestamps), then the algorithm for +# assigning a UTC time stamp to an event that happens during a positive +# leap second is not well defined. The official name of that leap +# second is 23:59:60, but there is no way of representing that time +# in these systems. +# Many systems of this type effectively stop the system clock for +# one second during the leap second and use a time that is equivalent +# to 23:59:59 UTC twice. For these systems, the corresponding TAI +# timestamp would be obtained by advancing to the next entry in the +# following table when the time equivalent to 23:59:59 UTC +# is used for the second time. Thus the leap second which +# occurred on 30 June 1972 at 23:59:59 UTC would have TAI +# timestamps computed as follows: +# +# ... +# 30 June 1972 23:59:59 (2287785599, first time): TAI= UTC + 10 seconds +# 30 June 1972 23:59:60 (2287785599,second time): TAI= UTC + 11 seconds +# 1 July 1972 00:00:00 (2287785600) TAI= UTC + 11 seconds +# ... +# +# If your system realizes the leap second by repeating 00:00:00 UTC twice +# (this is possible but not usual), then the advance to the next entry +# in the table must occur the second time that a time equivlent to +# 00:00:00 UTC is used. Thus, using the same example as above: +# +# ... +# 30 June 1972 23:59:59 (2287785599): TAI= UTC + 10 seconds +# 30 June 1972 23:59:60 (2287785600, first time): TAI= UTC + 10 seconds +# 1 July 1972 00:00:00 (2287785600,second time): TAI= UTC + 11 seconds +# ... +# +# in both cases the use of timestamps based on TAI produces a smooth +# time scale with no discontinuity in the time interval. +# +# This complexity would not be needed for negative leap seconds (if they +# are ever used). The UTC time would skip 23:59:59 and advance from +# 23:59:58 to 00:00:00 in that case. The TAI offset would decrease by +# 1 second at the same instant. This is a much easier situation to deal +# with, since the difficulty of unambiguously representing the epoch +# during the leap second does not arise. +# +# Questions or comments to: +# Jeff Prillaman +# Time Service Department +# US Naval Observatory +# Washington, DC +# jeffrey.prillaman@usno.navy.mil +# +# Last Update of leap second values: 31 Dec 2015 +# +# The following line shows this last update date in NTP timestamp +# format. This is the date on which the most recent change to +# the leap second data was added to the file. This line can +# be identified by the unique pair of characters in the first two +# columns as shown below. +# +#$ 3660508800 +# +# The data in this file will be updated periodically as new leap +# seconds are announced. In addition to being entered on the line +# above, the update time (in NTP format) will be added to the basic +# file name leap-seconds to form the name leap-seconds.. +# In addition, the generic name leap-seconds.list will always point to +# the most recent version of the file. +# +# This update procedure will be performed only when a new leap second +# is announced. +# +# The following entry specifies the expiration date of the data +# in this file in units of seconds since 1900.0. This expiration date +# will be changed at least twice per year whether or not a new leap +# second is announced. These semi-annual changes will be made no +# later than 1 June and 1 December of each year to indicate what +# action (if any) is to be taken on 30 June and 31 December, +# respectively. (These are the customary effective dates for new +# leap seconds.) This expiration date will be identified by a +# unique pair of characters in columns 1 and 2 as shown below. +# In the unlikely event that a leap second is announced with an +# effective date other than 30 June or 31 December, then this +# file will be edited to include that leap second as soon as it is +# announced or at least one month before the effective date +# (whichever is later). +# If an announcement by the IERS specifies that no leap second is +# scheduled, then only the expiration date of the file will +# be advanced to show that the information in the file is still +# current -- the update time stamp, the data and the name of the file +# will not change. +# +# Updated through IERS Bulletin C 50 +# File expires on: 1 Jun 2016 +# +#@ 3673728000 +# +2272060800 10 # 1 Jan 1972 +2287785600 11 # 1 Jul 1972 +2303683200 12 # 1 Jan 1973 +2335219200 13 # 1 Jan 1974 +2366755200 14 # 1 Jan 1975 +2398291200 15 # 1 Jan 1976 +2429913600 16 # 1 Jan 1977 +2461449600 17 # 1 Jan 1978 +2492985600 18 # 1 Jan 1979 +2524521600 19 # 1 Jan 1980 +2571782400 20 # 1 Jul 1981 +2603318400 21 # 1 Jul 1982 +2634854400 22 # 1 Jul 1983 +2698012800 23 # 1 Jul 1985 +2776982400 24 # 1 Jan 1988 +2840140800 25 # 1 Jan 1990 +2871676800 26 # 1 Jan 1991 +2918937600 27 # 1 Jul 1992 +2950473600 28 # 1 Jul 1993 +2982009600 29 # 1 Jul 1994 +3029443200 30 # 1 Jan 1996 +3076704000 31 # 1 Jul 1997 +3124137600 32 # 1 Jan 1999 +3345062400 33 # 1 Jan 2006 +3439756800 34 # 1 Jan 2009 +3550089600 35 # 1 Jul 2012 +3644697600 36 # 1 Jul 2015 +# +# the following special comment contains the +# hash value of the data in this file computed +# use the secure hash algorithm as specified +# by FIPS 180-1. See the files in ~/sha for +# the details of how this hash value is +# computed. Note that the hash computation +# ignores comments and whitespace characters +# in data lines. It includes the NTP values +# of both the last modification time and the +# expiration time of the file, but not the +# white space on those lines. +# the hash line is also ignored in the +# computation. +# +#h 44a44c49 35b22601 a9c7054c 8c56cf57 9b6f6ed5 +# diff --git a/etc/periodic/daily/480.leapfile-ntpd b/etc/periodic/daily/480.leapfile-ntpd new file mode 100755 index 0000000..8429824 --- /dev/null +++ b/etc/periodic/daily/480.leapfile-ntpd @@ -0,0 +1,28 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# If there is a global system configuration file, suck it in. +# +if [ -r /etc/defaults/periodic.conf ] +then + . /etc/defaults/periodic.conf + source_periodic_confs +fi + +case "$daily_ntpd_leapfile_enable" in + [Yy][Ee][Ss]) + case "$daily_ntpd_avoid_congestion" in + [Yy][Ee][Ss]) + # Avoid dogpiling + (sleep $(jot -r 1 0 86400); service ntpd fetch) & + ;; + *) + service ntpd fetch + ;; + esac + ;; +esac + +exit $rc diff --git a/etc/periodic/daily/Makefile b/etc/periodic/daily/Makefile index 593c0f6..617af49 100644 --- a/etc/periodic/daily/Makefile +++ b/etc/periodic/daily/Makefile @@ -34,7 +34,8 @@ FILES+= 130.clean-msgs .endif .if ${MK_NTP} != "no" -FILES+= 480.status-ntpd +FILES+= 480.status-ntpd \ + 480.leapfile-ntpd .endif .if ${MK_PKGTOOLS} != "no" diff --git a/etc/rc.d/ntpd b/etc/rc.d/ntpd index 3935b29..7f28358 100755 --- a/etc/rc.d/ntpd +++ b/etc/rc.d/ntpd @@ -14,6 +14,8 @@ name="ntpd" rcvar="ntpd_enable" command="/usr/sbin/${name}" pidfile="/var/run/${name}.pid" +extra_commands="fetch" +fetch_cmd="ntpd_fetch_leapfile" start_precmd="ntpd_precmd" load_rc_config $name @@ -30,6 +32,10 @@ ntpd_precmd() return 0; fi + if [ ! -f $ntp_db_leapfile ]; then + ntpd_fetch_leapfile + fi + # If running in a chroot cage, ensure that the appropriate files # exist inside the cage, as well as helper symlinks into the cage # from outside. @@ -44,10 +50,71 @@ ntpd_precmd() ( cd /dev ; /bin/pax -rw -pe clockctl "${ntpd_chrootdir}/dev" ) fi ln -fs "${ntpd_chrootdir}/var/db/ntp.drift" /var/db/ntp.drift + ln -fs "${ntpd_chrootdir}${ntp_tmp_leapfile}" ${ntp_tmp_leapfile} # Change run_rc_commands()'s internal copy of $ntpd_flags # rc_flags="-u ntpd:ntpd -i ${ntpd_chrootdir} $rc_flags" } +current_ntp_ts() { + # Seconds between 1900-01-01 and 1970-01-01 + # echo $(((70*365+17)*86400)) + ntp_to_unix=2208988800 + + echo $(($(date -u +%s)+$ntp_to_unix)) +} + +get_ntp_leapfile_ver() { + expr "$(awk '$1 == "#$" { print $2 }' "$1" 2>/dev/null)" : \ + '^\([1-9][0-9]*\)$' \| 0 +} + +get_ntp_leapfile_expiry() { + expr "$(awk '$1 == "#@" { print $2 }' "$1" 2>/dev/null)" : \ + '^\([1-9][0-9]*\)$' \| 0 +} + +ntpd_fetch_leapfile() { + local ntp_tmp_leapfile rc verbose + + if checkyesno ntp_leapfile_fetch_verbose; then + verbose=echo + else + verbose=: + fi + + ntp_tmp_leapfile="/var/run/ntpd.leap-seconds.list" + + ntp_ver_no_src=$(get_ntp_leapfile_ver $ntp_src_leapfile) + ntp_ver_no_db=$(get_ntp_leapfile_ver $ntp_db_leapfile) + $verbose ntp_src_leapfile version is $ntp_ver_no_src + $verbose ntp_db_leapfile version is $ntp_ver_no_db + + if [ "$ntp_ver_no_src" -gt "$ntp_ver_no_db" ]; then + $verbose replacing $ntp_db_leapfile with $ntp_src_leapfile + cp -p $ntp_src_leapfile $ntp_db_leapfile + ntp_ver_no_db=$ntp_ver_no_src + else + $verbose not replacing $ntp_db_leapfile with $ntp_src_leapfile + fi + ntp_leap_expiry=$(get_ntp_leapfile_expiry $ntp_db_leapfile) + ntp_leapfile_expiry_seconds=$((ntp_leapfile_expiry_days*86400)) + ntp_leap_fetch_date=$((ntp_leap_expiry-ntp_leapfile_expiry_seconds)) + if [ $(current_ntp_ts) -ge $ntp_leap_fetch_date ]; then + $verbose Within ntp leapfile expiry limit, initiating fetch + for url in $ntp_leapfile_sources ; do + $verbose fetching $url + fetch $ntp_leapfile_fetch_opts -o $ntp_tmp_leapfile $url && break + done + ntp_ver_no_tmp=$(get_ntp_leapfile_ver $ntp_tmp_leapfile) + if [ "$ntp_ver_no_tmp" -gt "$ntp_ver_no_db" ]; then + $verbose using $url as $ntp_db_leapfile + mv $ntp_tmp_leapfile $ntp_db_leapfile + else + $verbose using existing $ntp_db_leapfile + fi + fi +} + run_rc_command "$1" -- cgit v1.1 From c68557a9bd7089609250f173b1b1bdb906f8d141 Mon Sep 17 00:00:00 2001 From: allanjude Date: Wed, 10 Feb 2016 17:49:22 +0000 Subject: Catch the EFI loader up to the latest ZFS Boot Environment Menu features MFC: r294072 Move init_zfs_bootenv to sys/boot/zfs/zfs.c instead of having a copy in each loader MFC: r294073 Connect the ZFS boot environment menu to the UEFI loader MFC: r295357 Do not set vfs.root.mountfrom unnecessarily when initializing ZFS BE menu Approved by: re (marius) Relnotes: yes Sponsored by: ScaleEngine Inc. --- sys/boot/efi/loader/main.c | 33 +++++++++++++++++++++++++++++++++ sys/boot/i386/loader/main.c | 29 ----------------------------- sys/boot/userboot/userboot/main.c | 27 --------------------------- sys/boot/zfs/libzfs.h | 1 + sys/boot/zfs/zfs.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 56 deletions(-) diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index a90a87e..f796b4d 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -198,6 +198,7 @@ main(int argc, CHAR16 *argv[]) efi_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, env_nounset); + init_zfs_bootenv(zfs_fmtdev(&currdev)); break; } #endif @@ -504,6 +505,38 @@ command_lszfs(int argc, char *argv[]) } return (CMD_OK); } + +COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments", + command_reloadbe); + +static int +command_reloadbe(int argc, char *argv[]) +{ + int err; + char *root; + + if (argc > 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } + + if (argc == 2) { + err = zfs_bootenv(argv[1]); + } else { + root = getenv("zfs_be_root"); + if (root == NULL) { + return (CMD_OK); + } + err = zfs_bootenv(root); + } + + if (err != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } + + return (CMD_OK); +} #endif #ifdef EFI_ZFS_BOOT diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index be08271..6e783cd 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -69,7 +69,6 @@ static int isa_inb(int port); static void isa_outb(int port, int value); void exit(int code); #ifdef LOADER_ZFS_SUPPORT -static void init_zfs_bootenv(char *currdev); static void i386_zfs_probe(void); #endif @@ -303,34 +302,6 @@ extract_currdev(void) env_nounset); } -#ifdef LOADER_ZFS_SUPPORT -static void -init_zfs_bootenv(char *currdev) -{ - char *beroot; - - if (strlen(currdev) == 0) - return; - if(strncmp(currdev, "zfs:", 4) != 0) - return; - /* Remove the trailing : */ - currdev[strlen(currdev) - 1] = '\0'; - setenv("zfs_be_active", currdev, 1); - setenv("zfs_be_currpage", "1", 1); - /* Do not overwrite if already set */ - setenv("vfs.root.mountfrom", currdev, 0); - /* Forward past zfs: */ - currdev = strchr(currdev, ':'); - currdev++; - /* Remove the last element (current bootenv) */ - beroot = strrchr(currdev, '/'); - if (beroot != NULL) - beroot[0] = '\0'; - beroot = currdev; - setenv("zfs_be_root", beroot, 1); -} -#endif - COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int diff --git a/sys/boot/userboot/userboot/main.c b/sys/boot/userboot/userboot/main.c index e4d546a..d8e9349 100644 --- a/sys/boot/userboot/userboot/main.c +++ b/sys/boot/userboot/userboot/main.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); static void userboot_zfs_probe(void); static int userboot_zfs_found; -static void init_zfs_bootenv(char *currdev); #endif #define USERBOOT_VERSION USERBOOT_VERSION_3 @@ -200,32 +199,6 @@ extract_currdev(void) #if defined(USERBOOT_ZFS_SUPPORT) static void -init_zfs_bootenv(char *currdev) -{ - char *beroot; - - if (strlen(currdev) == 0) - return; - if(strncmp(currdev, "zfs:", 4) != 0) - return; - /* Remove the trailing : */ - currdev[strlen(currdev) - 1] = '\0'; - setenv("zfs_be_active", currdev, 1); - setenv("zfs_be_currpage", "1", 1); - /* Do not overwrite if already set */ - setenv("vfs.root.mountfrom", currdev, 0); - /* Forward past zfs: */ - currdev = strchr(currdev, ':'); - currdev++; - /* Remove the last element (current bootenv) */ - beroot = strrchr(currdev, '/'); - if (beroot != NULL) - beroot[0] = '\0'; - beroot = currdev; - setenv("zfs_be_root", beroot, 1); -} - -static void userboot_zfs_probe(void) { char devname[32]; diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h index b289849..ee64d1c 100644 --- a/sys/boot/zfs/libzfs.h +++ b/sys/boot/zfs/libzfs.h @@ -62,6 +62,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, char *zfs_fmtdev(void *vdev); int zfs_probe_dev(const char *devname, uint64_t *pool_guid); int zfs_list(const char *name); +void init_zfs_bootenv(char *currdev); int zfs_bootenv(const char *name); int zfs_belist_add(const char *name); int zfs_set_env(void); diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index c339b2d..ef79cb4 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -709,6 +709,30 @@ zfs_list(const char *name) return (zfs_list_dataset(spa, objid)); } +void +init_zfs_bootenv(char *currdev) +{ + char *beroot; + + if (strlen(currdev) == 0) + return; + if(strncmp(currdev, "zfs:", 4) != 0) + return; + /* Remove the trailing : */ + currdev[strlen(currdev) - 1] = '\0'; + setenv("zfs_be_active", currdev, 1); + setenv("zfs_be_currpage", "1", 1); + /* Forward past zfs: */ + currdev = strchr(currdev, ':'); + currdev++; + /* Remove the last element (current bootenv) */ + beroot = strrchr(currdev, '/'); + if (beroot != NULL) + beroot[0] = '\0'; + beroot = currdev; + setenv("zfs_be_root", beroot, 1); +} + int zfs_bootenv(const char *name) { @@ -779,8 +803,15 @@ int zfs_belist_add(const char *name) { + /* Skip special datasets that start with a $ character */ + if (strncmp(name, "$", 1) == 0) { + return (0); + } /* Add the boot environment to the head of the SLIST */ zfs_be = malloc(sizeof(struct zfs_be_entry)); + if (zfs_be == NULL) { + return (ENOMEM); + } zfs_be->name = name; SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries); zfs_env_count++; -- cgit v1.1 From 0c6be1966acf44df2e25af538331a5b5806edc56 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 10 Feb 2016 18:29:37 +0000 Subject: Adjust initialization of random(9) so it is usable earlier. A few existing SYSINITs expect the in-kernel PRNG (random(9)) to be useable at SI_SUB_RANDOM / SI_ORDER_ANY. However, the random(4) overhaul merged for 10.0 performs all of its initialization at SI_SUB_DRIVERS (since it is tied in with creating the /dev/random character device). This has changed in HEAD where the random initialization is split such that the in-kernel random(9) is initialized at SI_SUB_RANDOM and the supporting bits for userland random(4) (such as /dev/random) are initialized later. However, the changes in HEAD are large and invasive. Instead, this change is being directly committed to stable/10. This change moves most of the random(9)/random(4) initialization to SI_SUB_RANDOM with the exception that the creation of the harvesting kernel process and the /dev/random character device are deferred to new SYSINITs that run at SI_SUB_DRIVERS. This fixes the "random device not loaded; using insecure entropy" message output during boot on some systems. PR: 205800 Reviewed by: markm, so@ Approved by: so Approved by: re (gjb) Tested by: Mark Saad --- sys/dev/random/live_entropy_sources.c | 4 ++-- sys/dev/random/live_entropy_sources.h | 2 +- sys/dev/random/random_adaptors.c | 4 ++-- sys/dev/random/random_adaptors.h | 4 ++-- sys/dev/random/random_harvestq.c | 30 ++++++++++++++++++++++++++++-- sys/dev/random/randomdev.c | 23 +++++++++++++++++++---- sys/dev/random/randomdev_soft.c | 6 ------ 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/sys/dev/random/live_entropy_sources.c b/sys/dev/random/live_entropy_sources.c index d406ebd..d25201a 100644 --- a/sys/dev/random/live_entropy_sources.c +++ b/sys/dev/random/live_entropy_sources.c @@ -189,7 +189,7 @@ live_entropy_sources_deinit(void *unused) sx_destroy(&les_lock); } -SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, +SYSINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST, live_entropy_sources_init, NULL); -SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, +SYSUNINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST, live_entropy_sources_deinit, NULL); diff --git a/sys/dev/random/live_entropy_sources.h b/sys/dev/random/live_entropy_sources.h index 9a23070..a1eec3e 100644 --- a/sys/dev/random/live_entropy_sources.h +++ b/sys/dev/random/live_entropy_sources.h @@ -52,7 +52,7 @@ void live_entropy_sources_feed(int, event_proc_f); modevent, \ 0 \ }; \ - DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \ + DECLARE_MODULE(name, name##_mod, SI_SUB_RANDOM, \ SI_ORDER_SECOND); \ MODULE_VERSION(name, ver); \ MODULE_DEPEND(name, random, 1, 1, 1); diff --git a/sys/dev/random/random_adaptors.c b/sys/dev/random/random_adaptors.c index 4f5ad2c..d17abf7 100644 --- a/sys/dev/random/random_adaptors.c +++ b/sys/dev/random/random_adaptors.c @@ -233,9 +233,9 @@ random_adaptors_init(void *unused) SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator"); -SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, random_adaptors_init, +SYSINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST, random_adaptors_init, NULL); -SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, +SYSUNINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST, random_adaptors_deinit, NULL); static void diff --git a/sys/dev/random/random_adaptors.h b/sys/dev/random/random_adaptors.h index 4765694..b878b28 100644 --- a/sys/dev/random/random_adaptors.h +++ b/sys/dev/random/random_adaptors.h @@ -47,7 +47,7 @@ extern struct random_adaptor *random_adaptor; /* * random_adaptor's should be registered prior to - * random module (SI_SUB_DRIVERS/SI_ORDER_MIDDLE) + * random module (SI_SUB_RANDOM/SI_ORDER_MIDDLE) */ #define RANDOM_ADAPTOR_MODULE(name, modevent, ver) \ static moduledata_t name##_mod = { \ @@ -55,7 +55,7 @@ extern struct random_adaptor *random_adaptor; modevent, \ 0 \ }; \ - DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \ + DECLARE_MODULE(name, name##_mod, SI_SUB_RANDOM, \ SI_ORDER_SECOND); \ MODULE_VERSION(name, ver); \ MODULE_DEPEND(name, random, 1, 1, 1); diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c index b7b8381..2638ea3 100644 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -81,6 +81,8 @@ int random_kthread_control = 0; static struct proc *random_kthread_proc; +static event_proc_f random_cb; + #ifdef RANDOM_RWFILE static const char *entropy_files[] = { "/entropy", @@ -219,7 +221,7 @@ random_kthread(void *arg) void random_harvestq_init(event_proc_f cb) { - int error, i; + int i; struct harvest *np; /* Initialise the harvest fifos */ @@ -238,13 +240,26 @@ random_harvestq_init(event_proc_f cb) mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN); + random_cb = cb; +} + +static void +random_harvestq_start_kproc(void *arg __unused) +{ + int error; + + if (random_cb == NULL) + return; + /* Start the hash/reseed thread */ - error = kproc_create(random_kthread, cb, + error = kproc_create(random_kthread, random_cb, &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); /* RANDOM_CSPRNG_NAME */ if (error != 0) panic("Cannot create entropy maintenance thread."); } +SYSINIT(random_kthread, SI_SUB_DRIVERS, SI_ORDER_ANY, + random_harvestq_start_kproc, NULL); void random_harvestq_deinit(void) @@ -265,6 +280,17 @@ random_harvestq_deinit(void) } harvestfifo.count = 0; + /* + * Command the hash/reseed thread to end and wait for it to finish + */ + mtx_lock_spin(&harvest_mtx); + if (random_kthread_proc != NULL) { + random_kthread_control = -1; + msleep_spin((void *)&random_kthread_control, &harvest_mtx, + "term", 0); + } + mtx_unlock_spin(&harvest_mtx); + mtx_destroy(&harvest_mtx); } diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index b76cb83..a220e7f 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -175,15 +175,24 @@ random_initialize(void *p, struct random_adaptor *s) printf("random: <%s> initialized\n", s->ident); + /* mark random(4) as initialized, to avoid being called again */ + random_inited = 1; +} + +static void +random_makedev(void *arg __unused) +{ + + if (random_adaptor == NULL) + return; + /* Use an appropriately evil mode for those who are concerned * with daemons */ random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw, RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random"); make_dev_alias(random_dev, "urandom"); /* compatibility */ - - /* mark random(4) as initialized, to avoid being called again */ - random_inited = 1; } +SYSINIT(random_makedev, SI_SUB_DRIVERS, SI_ORDER_ANY, random_makedev, NULL); /* ARGSUSED */ static int @@ -229,5 +238,11 @@ random_modevent(module_t mod __unused, int type, void *data __unused) return (error); } -DEV_MODULE(random, random_modevent, NULL); +static moduledata_t random_mod = { + "random", + random_modevent, + NULL +}; + +DECLARE_MODULE(random, random_mod, SI_SUB_RANDOM, SI_ORDER_MIDDLE); MODULE_VERSION(random, 1); diff --git a/sys/dev/random/randomdev_soft.c b/sys/dev/random/randomdev_soft.c index 0929704..6badecc 100644 --- a/sys/dev/random/randomdev_soft.c +++ b/sys/dev/random/randomdev_soft.c @@ -182,12 +182,6 @@ randomdev_deinit(void) /* Deregister the randomness harvesting routine */ randomdev_deinit_harvester(); - /* - * Command the hash/reseed thread to end and wait for it to finish - */ - random_kthread_control = -1; - tsleep((void *)&random_kthread_control, 0, "term", 0); - #if defined(RANDOM_YARROW) random_yarrow_deinit_alg(); #endif -- cgit v1.1 From 9e8884f301206dff7661faacac42bef3557cc86c Mon Sep 17 00:00:00 2001 From: sobomax Date: Thu, 11 Feb 2016 00:27:04 +0000 Subject: MFC: r295159, kill foreign VCS files. Approved by: re (marius) --- contrib/libucl/tests/.gitignore | 8 -------- contrib/unbound/.gitignore | 38 -------------------------------------- 2 files changed, 46 deletions(-) delete mode 100644 contrib/libucl/tests/.gitignore delete mode 100644 contrib/unbound/.gitignore diff --git a/contrib/libucl/tests/.gitignore b/contrib/libucl/tests/.gitignore deleted file mode 100644 index 5a48681..0000000 --- a/contrib/libucl/tests/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.log -*.trs -*.plist - -test_basic -test_generate -test_schema -test_speed diff --git a/contrib/unbound/.gitignore b/contrib/unbound/.gitignore deleted file mode 100644 index 7fed8d7..0000000 --- a/contrib/unbound/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -*.lo -*.o -/.libs/ -/Makefile -/autom4te.cache/ -/config.h -/config.log -/config.status -/dnstap/dnstap_config.h -/doc/example.conf -/doc/libunbound.3 -/doc/unbound-anchor.8 -/doc/unbound-checkconf.8 -/doc/unbound-control.8 -/doc/unbound-host.1 -/doc/unbound.8 -/doc/unbound.conf.5 -/libtool -/libunbound.la -/smallapp/unbound-control-setup.sh -/unbound -/unbound-anchor -/unbound-checkconf -/unbound-control -/unbound-control-setup -/unbound-host -/unbound.h -/asynclook -/delayer -/lock-verify -/memstats -/perf -/petal -/pktview -/streamtcp -/testbound -/unittest - -- cgit v1.1 From 15873ac96fcc4e81a25d35e735a1fbae9d727360 Mon Sep 17 00:00:00 2001 From: sbruno Date: Thu, 11 Feb 2016 16:16:10 +0000 Subject: MFC r292674 Update ixgbe(4) to Intel FreeBSD Networking Group version 3.1.13-k. MFC r292571 and r292697 Add support for X552 and X550T. MFC r293334 Fix SFP module insertion post boot. MFC r293338 Fix VF handling of VLANs for Amazon Cloud. Reviewed by: erj smh ngie jeffrey.e.pieper@intel.com Approved by: re (marius) Relnotes: Yes Sponsored by: Intel Corporation and Limelight Networks Differential Revision: https://reviews.freebsd.org/D5117 --- sys/conf/files | 2 + sys/dev/ixgbe/LICENSE | 33 --- sys/dev/ixgbe/if_ix.c | 587 +++++++++++++++++++++++++++++++------------ sys/dev/ixgbe/if_ixv.c | 134 +++++----- sys/dev/ixgbe/ix_txrx.c | 123 ++++----- sys/dev/ixgbe/ixgbe.h | 36 ++- sys/dev/ixgbe/ixgbe_82598.c | 4 +- sys/dev/ixgbe/ixgbe_82599.c | 61 +++-- sys/dev/ixgbe/ixgbe_api.c | 6 +- sys/dev/ixgbe/ixgbe_api.h | 9 +- sys/dev/ixgbe/ixgbe_common.c | 64 ++--- sys/dev/ixgbe/ixgbe_dcb.c | 7 +- sys/dev/ixgbe/ixgbe_osdep.c | 88 +++++++ sys/dev/ixgbe/ixgbe_osdep.h | 38 ++- sys/dev/ixgbe/ixgbe_phy.c | 82 +++--- sys/dev/ixgbe/ixgbe_phy.h | 13 +- sys/dev/ixgbe/ixgbe_type.h | 61 +++-- sys/dev/ixgbe/ixgbe_vf.c | 2 - sys/dev/ixgbe/ixgbe_x540.c | 41 +-- sys/dev/ixgbe/ixgbe_x550.c | 373 ++++++++++++--------------- sys/dev/ixgbe/ixgbe_x550.h | 3 +- sys/modules/ix/Makefile | 2 +- sys/modules/ixv/Makefile | 2 +- 23 files changed, 1062 insertions(+), 709 deletions(-) delete mode 100644 sys/dev/ixgbe/LICENSE create mode 100644 sys/dev/ixgbe/ixgbe_osdep.c diff --git a/sys/conf/files b/sys/conf/files index 5c46c8c..b3f7f9e 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1728,6 +1728,8 @@ dev/ixgbe/ix_txrx.c optional ix inet | ixv inet | ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_phy.c optional ix inet | ixv inet | ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixgbe_osdep.c optional ix inet | ixv inet | ixgbe inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_api.c optional ix inet | ixv inet | ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_common.c optional ix inet | ixv inet | ixgbe inet \ diff --git a/sys/dev/ixgbe/LICENSE b/sys/dev/ixgbe/LICENSE deleted file mode 100644 index 394b094..0000000 --- a/sys/dev/ixgbe/LICENSE +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - - Copyright (c) 2001-2015, Intel Corporation - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of the Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -******************************************************************************/ -/*$FreeBSD$*/ diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 3c6caf7..111e731 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -46,14 +46,10 @@ #endif /********************************************************************* - * Set this to one to display debug statistics - *********************************************************************/ -int ixgbe_display_debug_stats = 0; - -/********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "3.1.0"; +char ixgbe_driver_version[] = "3.1.13-k"; + /********************************************************************* * PCI Device ID Table @@ -94,9 +90,11 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] = {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0}, /* required last entry */ {0, 0, 0, 0, 0} }; @@ -130,7 +128,7 @@ static void ixgbe_media_status(struct ifnet *, struct ifmediareq *); static int ixgbe_media_change(struct ifnet *); static void ixgbe_identify_hardware(struct adapter *); static int ixgbe_allocate_pci_resources(struct adapter *); -static void ixgbe_get_slot_info(struct ixgbe_hw *); +static void ixgbe_get_slot_info(struct adapter *); static int ixgbe_allocate_msix(struct adapter *); static int ixgbe_allocate_legacy(struct adapter *); static int ixgbe_setup_msix(struct adapter *); @@ -141,7 +139,6 @@ static void ixgbe_config_gpie(struct adapter *); static void ixgbe_config_dmac(struct adapter *); static void ixgbe_config_delay_values(struct adapter *); static void ixgbe_config_link(struct adapter *); -static void ixgbe_check_eee_support(struct adapter *); static void ixgbe_check_wol_support(struct adapter *); static int ixgbe_setup_low_power_mode(struct adapter *); static void ixgbe_rearm_queues(struct adapter *, u64); @@ -150,6 +147,7 @@ static void ixgbe_initialize_transmit_units(struct adapter *); static void ixgbe_initialize_receive_units(struct adapter *); static void ixgbe_enable_rx_drop(struct adapter *); static void ixgbe_disable_rx_drop(struct adapter *); +static void ixgbe_initialize_rss_mapping(struct adapter *); static void ixgbe_enable_intr(struct adapter *); static void ixgbe_disable_intr(struct adapter *); @@ -170,19 +168,24 @@ static void ixgbe_add_hw_stats(struct adapter *); /* Sysctl handlers */ static void ixgbe_set_sysctl_value(struct adapter *, const char *, - const char *, int *, int); + const char *, int *, int); static int ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS); static int ixgbe_set_advertise(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); +#ifdef IXGBE_DEBUG +static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); +static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); +#endif static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS); +static int ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS); /* Support for pluggable optic modules */ static bool ixgbe_sfp_probe(struct adapter *); @@ -446,9 +449,13 @@ ixgbe_attach(device_t dev) /* Allocate, clear, and link in our adapter structure */ adapter = device_get_softc(dev); - adapter->dev = adapter->osdep.dev = dev; + adapter->dev = dev; hw = &adapter->hw; +#ifdef DEV_NETMAP + adapter->init_locked = ixgbe_init_locked; + adapter->stop_locked = ixgbe_stop; +#endif /* Core Lock Init*/ IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); @@ -531,18 +538,18 @@ ixgbe_attach(device_t dev) adapter->sfp_probe = TRUE; error = 0; } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { - device_printf(dev,"Unsupported SFP+ module detected!\n"); + device_printf(dev, "Unsupported SFP+ module detected!\n"); error = EIO; goto err_late; } else if (error) { - device_printf(dev,"Unable to initialize the shared code\n"); + device_printf(dev, "Unable to initialize the shared code\n"); error = EIO; goto err_late; } /* Make sure we have a good EEPROM before we read from it */ if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) { - device_printf(dev,"The EEPROM Checksum Is Not Valid\n"); + device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); error = EIO; goto err_late; } @@ -552,24 +559,21 @@ ixgbe_attach(device_t dev) case IXGBE_ERR_EEPROM_VERSION: device_printf(dev, "This device is a pre-production adapter/" "LOM. Please be aware there may be issues associated " - "with your hardware.\n If you are experiencing problems " + "with your hardware.\nIf you are experiencing problems " "please contact your Intel or hardware representative " "who provided you with this hardware.\n"); break; case IXGBE_ERR_SFP_NOT_SUPPORTED: - device_printf(dev,"Unsupported SFP+ Module\n"); + device_printf(dev, "Unsupported SFP+ Module\n"); error = EIO; goto err_late; case IXGBE_ERR_SFP_NOT_PRESENT: - device_printf(dev,"No SFP+ Module found\n"); + device_printf(dev, "No SFP+ Module found\n"); /* falls thru */ default: break; } - /* Detect and set physical type */ - ixgbe_setup_optics(adapter); - if ((adapter->msix > 1) && (ixgbe_enable_msix)) error = ixgbe_allocate_msix(adapter); else @@ -591,11 +595,12 @@ ixgbe_attach(device_t dev) ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); /* Check PCIE slot type/speed/width */ - ixgbe_get_slot_info(hw); - + ixgbe_get_slot_info(adapter); - /* Set an initial default flow control value */ + /* Set an initial default flow control & dmac value */ adapter->fc = ixgbe_fc_full; + adapter->dmac = 0; + adapter->eee_enabled = 0; #ifdef PCI_IOV if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) { @@ -621,7 +626,6 @@ ixgbe_attach(device_t dev) /* Check for certain supported features */ ixgbe_check_wol_support(adapter); - ixgbe_check_eee_support(adapter); /* Add sysctls */ ixgbe_add_device_sysctls(adapter); @@ -682,6 +686,7 @@ ixgbe_detach(device_t dev) } #endif /* PCI_IOV */ + ether_ifdetach(adapter->ifp); /* Stop the adapter */ IXGBE_CORE_LOCK(adapter); ixgbe_setup_low_power_mode(adapter); @@ -723,7 +728,6 @@ ixgbe_detach(device_t dev) if (adapter->vlan_detach != NULL) EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); - ether_ifdetach(adapter->ifp); callout_drain(&adapter->timer); #ifdef DEV_NETMAP netmap_detach(adapter->ifp); @@ -778,10 +782,6 @@ ixgbe_suspend(device_t dev) error = ixgbe_setup_low_power_mode(adapter); - /* Save state and power down */ - pci_save_state(dev); - pci_set_powerstate(dev, PCI_POWERSTATE_D3); - IXGBE_CORE_UNLOCK(adapter); return (error); @@ -799,9 +799,6 @@ ixgbe_resume(device_t dev) IXGBE_CORE_LOCK(adapter); - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - pci_restore_state(dev); - /* Read & clear WUS register */ wus = IXGBE_READ_REG(hw, IXGBE_WUS); if (wus) @@ -820,7 +817,6 @@ ixgbe_resume(device_t dev) IXGBE_CORE_UNLOCK(adapter); - INIT_DEBUGOUT("ixgbe_resume: end"); return (0); } @@ -864,7 +860,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) ifp->if_flags |= IFF_UP; if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ixgbe_init(adapter); -#if defined(INET) +#ifdef INET if (!(ifp->if_flags & IFF_NOARP)) arp_ifinit(ifp, ifa); #endif @@ -922,10 +918,21 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) break; case SIOCSIFCAP: { - int mask = ifr->ifr_reqcap ^ ifp->if_capenable; IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)"); - if (mask & IFCAP_HWCSUM) - ifp->if_capenable ^= IFCAP_HWCSUM; + + int mask = ifr->ifr_reqcap ^ ifp->if_capenable; + if (!mask) + break; + + /* HW cannot turn these on/off separately */ + if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) { + ifp->if_capenable ^= IFCAP_RXCSUM; + ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; + } + if (mask & IFCAP_TXCSUM) + ifp->if_capenable ^= IFCAP_TXCSUM; + if (mask & IFCAP_TXCSUM_IPV6) + ifp->if_capenable ^= IFCAP_TXCSUM_IPV6; if (mask & IFCAP_TSO4) ifp->if_capenable ^= IFCAP_TSO4; if (mask & IFCAP_TSO6) @@ -938,6 +945,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; if (mask & IFCAP_VLAN_HWTSO) ifp->if_capenable ^= IFCAP_VLAN_HWTSO; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { IXGBE_CORE_LOCK(adapter); ixgbe_init_locked(adapter); @@ -981,6 +989,42 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) return (error); } +/* + * Set the various hardware offload abilities. + * + * This takes the ifnet's if_capenable flags (e.g. set by the user using + * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what + * mbuf offload flags the driver will understand. + */ +static void +ixgbe_set_if_hwassist(struct adapter *adapter) +{ + struct ifnet *ifp = adapter->ifp; + + ifp->if_hwassist = 0; +#if __FreeBSD_version >= 1000000 + if (ifp->if_capenable & IFCAP_TSO4) + ifp->if_hwassist |= CSUM_IP_TSO; + if (ifp->if_capenable & IFCAP_TSO6) + ifp->if_hwassist |= CSUM_IP6_TSO; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | + CSUM_IP_SCTP); + if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) + ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP | + CSUM_IP6_SCTP); +#else + if (ifp->if_capenable & IFCAP_TSO) + ifp->if_hwassist |= CSUM_TSO; + if (ifp->if_capenable & IFCAP_TXCSUM) { + ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); + struct ixgbe_hw *hw = &adapter->hw; + if (hw->mac.type != ixgbe_mac_82598EB) + ifp->if_hwassist |= CSUM_SCTP; + } +#endif +} + /********************************************************************* * Init entry point * @@ -1003,6 +1047,7 @@ ixgbe_init_locked(struct adapter *adapter) struct rx_ring *rxr; u32 txdctl, mhadd; u32 rxdctl, rxctrl; + int err = 0; #ifdef PCI_IOV enum ixgbe_iov_mode mode; #endif @@ -1031,17 +1076,8 @@ ixgbe_init_locked(struct adapter *adapter) ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1); hw->addr_ctrl.rar_used_count = 1; - /* Set the various hardware offload abilities */ - ifp->if_hwassist = 0; - if (ifp->if_capenable & IFCAP_TSO) - ifp->if_hwassist |= CSUM_TSO; - if (ifp->if_capenable & IFCAP_TXCSUM) { - ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); -#if __FreeBSD_version >= 800000 - if (hw->mac.type != ixgbe_mac_82598EB) - ifp->if_hwassist |= CSUM_SCTP; -#endif - } + /* Set hardware offload abilities from ifnet flags */ + ixgbe_set_if_hwassist(adapter); /* Prepare transmit descriptors and buffers */ if (ixgbe_setup_transmit_structures(adapter)) { @@ -1059,10 +1095,7 @@ ixgbe_init_locked(struct adapter *adapter) /* Setup Multicast table */ ixgbe_set_multi(adapter); - /* - ** Determine the correct mbuf pool - ** for doing jumbo frames - */ + /* Determine the correct mbuf pool, based on frame size */ if (adapter->max_frame_size <= MCLBYTES) adapter->rx_mbuf_sz = MCLBYTES; else @@ -1198,7 +1231,7 @@ ixgbe_init_locked(struct adapter *adapter) * need to be kick-started */ if (hw->phy.type == ixgbe_phy_none) { - int err = hw->phy.ops.identify(hw); + err = hw->phy.ops.identify(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { device_printf(dev, "Unsupported SFP+ module type was detected.\n"); @@ -1210,7 +1243,11 @@ ixgbe_init_locked(struct adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR); /* Configure Energy Efficient Ethernet for supported devices */ - ixgbe_setup_eee(hw, adapter->eee_enabled); + if (hw->mac.ops.setup_eee) { + err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled); + if (err) + device_printf(dev, "Error setting up EEE: %d\n", err); + } /* Config/Enable Link */ ixgbe_config_link(adapter); @@ -1280,7 +1317,7 @@ ixgbe_config_gpie(struct adapter *adapter) /* * Thermal Failure Detection (X540) - * Link Detection (X557) + * Link Detection (X552 SFP+, X552/X557-AT) */ if (hw->mac.type == ixgbe_mac_X540 || hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || @@ -1588,6 +1625,9 @@ ixgbe_msix_link(void *arg) ++adapter->link_irq; + /* Pause other interrupts */ + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); + /* First get the cause */ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS); /* Be sure the queue bits are not cleared */ @@ -1596,8 +1636,10 @@ ixgbe_msix_link(void *arg) IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr); /* Link status change */ - if (reg_eicr & IXGBE_EICR_LSC) + if (reg_eicr & IXGBE_EICR_LSC) { + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); taskqueue_enqueue(adapter->tq, &adapter->link_task); + } if (adapter->hw.mac.type != ixgbe_mac_82598EB) { #ifdef IXGBE_FDIR @@ -1611,14 +1653,14 @@ ixgbe_msix_link(void *arg) } else #endif if (reg_eicr & IXGBE_EICR_ECC) { - device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! " + device_printf(adapter->dev, "CRITICAL: ECC ERROR!! " "Please Reboot!!\n"); IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); } /* Check for over temp condition */ if (reg_eicr & IXGBE_EICR_TS) { - device_printf(adapter->dev, "\nCRITICAL: OVER TEMP!! " + device_printf(adapter->dev, "CRITICAL: OVER TEMP!! " "PHY IS SHUT DOWN!!\n"); device_printf(adapter->dev, "System shutdown required!\n"); IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); @@ -1660,6 +1702,7 @@ ixgbe_msix_link(void *arg) taskqueue_enqueue(adapter->tq, &adapter->phy_task); } + /* Re-enable other interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); return; } @@ -1753,6 +1796,7 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) ** XXX: These need to use the proper media types once ** they're added. */ +#ifndef IFM_ETH_XTYPE if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) switch (adapter->link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: @@ -1778,6 +1822,33 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; break; } +#else + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) + switch (adapter->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; + break; + case IXGBE_LINK_SPEED_2_5GB_FULL: + ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; + break; + } + else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 + || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) + switch (adapter->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; + break; + case IXGBE_LINK_SPEED_2_5GB_FULL: + ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; + break; + } +#endif /* If nothing is recognized... */ if (IFM_SUBTYPE(ifmr->ifm_active) == 0) @@ -1820,13 +1891,14 @@ ixgbe_media_change(struct ifnet * ifp) return (EINVAL); if (hw->phy.media_type == ixgbe_media_type_backplane) - return (EPERM); + return (ENODEV); /* ** We don't actually need to check against the supported ** media types of the adapter; ifmedia will take care of ** that for us. */ +#ifndef IFM_ETH_XTYPE switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: case IFM_10G_T: @@ -1852,6 +1924,33 @@ ixgbe_media_change(struct ifnet * ifp) default: goto invalid; } +#else + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_AUTO: + case IFM_10G_T: + speed |= IXGBE_LINK_SPEED_100_FULL; + case IFM_10G_LRM: + case IFM_10G_KR: + case IFM_10G_LR: + case IFM_10G_KX4: + speed |= IXGBE_LINK_SPEED_1GB_FULL; + case IFM_10G_TWINAX: + speed |= IXGBE_LINK_SPEED_10GB_FULL; + break; + case IFM_1000_T: + speed |= IXGBE_LINK_SPEED_100_FULL; + case IFM_1000_LX: + case IFM_1000_SX: + case IFM_1000_KX: + speed |= IXGBE_LINK_SPEED_1GB_FULL; + break; + case IFM_100_TX: + speed |= IXGBE_LINK_SPEED_100_FULL; + break; + default: + goto invalid; + } +#endif hw->mac.autotry_restart = TRUE; hw->mac.ops.setup_link(hw, speed, TRUE); @@ -2392,7 +2491,7 @@ ixgbe_allocate_msix(struct adapter *adapter) return (error); } #if __FreeBSD_version >= 800504 - bus_describe_intr(dev, que->res, que->tag, "que %d", i); + bus_describe_intr(dev, que->res, que->tag, "q%d", i); #endif que->msix = vector; adapter->active_queues |= (u64)(1 << que->msix); @@ -2443,8 +2542,8 @@ ixgbe_allocate_msix(struct adapter *adapter) device_get_nameunit(adapter->dev), cpu_id); #else - taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", - device_get_nameunit(adapter->dev)); + taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d", + device_get_nameunit(adapter->dev), i); #endif } @@ -2522,7 +2621,7 @@ ixgbe_setup_msix(struct adapter *adapter) } /* Figure out a reasonable auto config value */ - queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; + queues = (mp_ncpus > (msgs - 1)) ? (msgs - 1) : mp_ncpus; #ifdef RSS /* If we're doing RSS, clamp at the number of RSS buckets */ @@ -2532,6 +2631,9 @@ ixgbe_setup_msix(struct adapter *adapter) if (ixgbe_num_queues != 0) queues = ixgbe_num_queues; + /* Set max queues to 8 when autoconfiguring */ + else if ((ixgbe_num_queues == 0) && (queues > 8)) + queues = 8; /* reflect correct sysctl value */ ixgbe_num_queues = queues; @@ -2568,12 +2670,12 @@ msi: rid, adapter->msix_mem); adapter->msix_mem = NULL; } - msgs = 1; - if (pci_alloc_msi(dev, &msgs) == 0) { - device_printf(adapter->dev,"Using an MSI interrupt\n"); + msgs = 1; + if (pci_alloc_msi(dev, &msgs) == 0) { + device_printf(adapter->dev, "Using an MSI interrupt\n"); return (msgs); } - device_printf(adapter->dev,"Using a Legacy interrupt\n"); + device_printf(adapter->dev, "Using a Legacy interrupt\n"); return (0); } @@ -2589,22 +2691,24 @@ ixgbe_allocate_pci_resources(struct adapter *adapter) &rid, RF_ACTIVE); if (!(adapter->pci_mem)) { - device_printf(dev,"Unable to allocate bus resource: memory\n"); + device_printf(dev, "Unable to allocate bus resource: memory\n"); return (ENXIO); } + /* Save bus_space values for READ/WRITE_REG macros */ adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem); adapter->osdep.mem_bus_space_handle = rman_get_bushandle(adapter->pci_mem); + /* Set hw values for shared code */ adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle; + adapter->hw.back = adapter; - /* Legacy defaults */ + /* Default to 1 queue if MSI-X setup fails */ adapter->num_queues = 1; - adapter->hw.back = &adapter->osdep; /* - ** Now setup MSI or MSI/X, should + ** Now setup MSI or MSI-X, should ** return us the number of supported ** vectors. (Will be 1 for MSI) */ @@ -2729,13 +2833,22 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) */ ifp->if_hdrlen = sizeof(struct ether_vlan_header); - ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO | IFCAP_VLAN_HWCSUM; - ifp->if_capabilities |= IFCAP_JUMBO_MTU; - ifp->if_capabilities |= IFCAP_LRO; - ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING + /* Set capability flags */ + ifp->if_capabilities |= IFCAP_RXCSUM + | IFCAP_TXCSUM + | IFCAP_RXCSUM_IPV6 + | IFCAP_TXCSUM_IPV6 + | IFCAP_TSO4 + | IFCAP_TSO6 + | IFCAP_LRO + | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO + | IFCAP_VLAN_HWCSUM + | IFCAP_JUMBO_MTU | IFCAP_VLAN_MTU | IFCAP_HWSTATS; + + /* Enable the above capabilities by default */ ifp->if_capenable = ifp->if_capabilities; /* @@ -2755,9 +2868,10 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change, ixgbe_media_status); + adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw); ixgbe_add_media_types(adapter); - /* Autoselect media by default */ + /* Set autoselect media by default */ ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); return (0); @@ -2770,7 +2884,7 @@ ixgbe_add_media_types(struct adapter *adapter) device_t dev = adapter->dev; int layer; - layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); + layer = adapter->phy_layer; /* Media types with matching FreeBSD media defines */ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) @@ -2784,20 +2898,28 @@ ixgbe_add_media_types(struct adapter *adapter) layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL); - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL); - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) + if (hw->phy.multispeed_fiber) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL); + } + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); + if (hw->phy.multispeed_fiber) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); + } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); - if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) - ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); - /* - ** Other (no matching FreeBSD media type): - ** To workaround this, we'll assign these completely - ** inappropriate media types. - */ +#ifdef IFM_ETH_XTYPE + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL); + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); + if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) + ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL); +#else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { device_printf(dev, "Media supported: 10GbaseKR\n"); device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); @@ -2813,10 +2935,9 @@ ixgbe_add_media_types(struct adapter *adapter) device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL); } - if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) { - /* Someday, someone will care about you... */ +#endif + if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) device_printf(dev, "Media supported: 1000baseBX\n"); - } if (hw->device_id == IXGBE_DEV_ID_82598AT) { ifmedia_add(&adapter->media, @@ -2838,12 +2959,7 @@ ixgbe_config_link(struct adapter *adapter) sfp = ixgbe_is_sfp(hw); if (sfp) { - if (hw->phy.multispeed_fiber) { - hw->mac.ops.setup_sfp(hw); - ixgbe_enable_tx_laser(hw); - taskqueue_enqueue(adapter->tq, &adapter->msf_task); - } else - taskqueue_enqueue(adapter->tq, &adapter->mod_task); + taskqueue_enqueue(adapter->tq, &adapter->mod_task); } else { if (hw->mac.ops.check_link) err = ixgbe_check_link(hw, &adapter->link_speed, @@ -2877,7 +2993,6 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; /* Setup the Base and Length of the Tx Descriptor Ring */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { u64 tdba = txr->txdma.dma_paddr; u32 txctrl = 0; @@ -2897,12 +3012,15 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) txr->tail = IXGBE_TDT(j); /* Disable Head Writeback */ + /* + * Note: for X550 series devices, these registers are actually + * prefixed with TPH_ isntead of DCA_, but the addresses and + * fields remain the same. + */ switch (hw->mac.type) { case ixgbe_mac_82598EB: txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); break; - case ixgbe_mac_82599EB: - case ixgbe_mac_X540: default: txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); break; @@ -2912,8 +3030,6 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) case ixgbe_mac_82598EB: IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); break; - case ixgbe_mac_82599EB: - case ixgbe_mac_X540: default: IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); break; @@ -2946,7 +3062,7 @@ ixgbe_initialize_transmit_units(struct adapter *adapter) } static void -ixgbe_initialise_rss_mapping(struct adapter *adapter) +ixgbe_initialize_rss_mapping(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 reta = 0, mrqc, rss_key[10]; @@ -3081,7 +3197,6 @@ ixgbe_initialize_receive_units(struct adapter *adapter) u32 bufsz, fctrl, srrctl, rxcsum; u32 hlreg; - /* * Make sure receives are disabled while * setting up the descriptor ring @@ -3146,11 +3261,11 @@ ixgbe_initialize_receive_units(struct adapter *adapter) srrctl &= ~IXGBE_SRRCTL_DROP_EN; } - IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl); + IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); /* Setup the HW Rx Head and Tail Descriptor Pointers */ - IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); + IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); /* Set the driver rx tail address */ rxr->tail = IXGBE_RDT(rxr->me); @@ -3166,7 +3281,7 @@ ixgbe_initialize_receive_units(struct adapter *adapter) rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); - ixgbe_initialise_rss_mapping(adapter); + ixgbe_initialize_rss_mapping(adapter); if (adapter->num_queues > 1) { /* RSS and RX IPP Checksum are mutually exclusive */ @@ -3176,6 +3291,7 @@ ixgbe_initialize_receive_units(struct adapter *adapter) if (ifp->if_capenable & IFCAP_RXCSUM) rxcsum |= IXGBE_RXCSUM_PCSD; + /* This is useful for calculating UDP/IP fragment checksums */ if (!(rxcsum & IXGBE_RXCSUM_PCSD)) rxcsum |= IXGBE_RXCSUM_IPPCSE; @@ -3397,9 +3513,10 @@ ixgbe_disable_intr(struct adapter *adapter) ** the slot this adapter is plugged into. */ static void -ixgbe_get_slot_info(struct ixgbe_hw *hw) +ixgbe_get_slot_info(struct adapter *adapter) { - device_t dev = ((struct ixgbe_osdep *)hw->back)->dev; + device_t dev = adapter->dev; + struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_mac_info *mac = &hw->mac; u16 link; u32 offset; @@ -3606,12 +3723,12 @@ ixgbe_sfp_probe(struct adapter *adapter) goto out; ret = hw->phy.ops.reset(hw); if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { - device_printf(dev,"Unsupported SFP+ module detected!"); - printf(" Reload driver with supported module.\n"); + device_printf(dev, "Unsupported SFP+ module detected!"); + device_printf(dev, "Reload driver with supported module.\n"); adapter->sfp_probe = FALSE; goto out; } else - device_printf(dev,"SFP+ module detected!\n"); + device_printf(dev, "SFP+ module detected!\n"); /* We now have supported optics */ adapter->sfp_probe = FALSE; /* Set the optics type so system reports correctly */ @@ -3630,10 +3747,14 @@ static void ixgbe_handle_link(void *context, int pending) { struct adapter *adapter = context; + struct ixgbe_hw *hw = &adapter->hw; - ixgbe_check_link(&adapter->hw, + ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up, 0); ixgbe_update_link_status(adapter); + + /* Re-enable link interrupts */ + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC); } /* @@ -3644,23 +3765,66 @@ ixgbe_handle_mod(void *context, int pending) { struct adapter *adapter = context; struct ixgbe_hw *hw = &adapter->hw; + enum ixgbe_phy_type orig_type = hw->phy.type; device_t dev = adapter->dev; u32 err; + IXGBE_CORE_LOCK(adapter); + + /* Check to see if the PHY type changed */ + if (hw->phy.ops.identify) { + hw->phy.type = ixgbe_phy_unknown; + hw->phy.ops.identify(hw); + } + + if (hw->phy.type != orig_type) { + device_printf(dev, "Detected phy_type %d\n", hw->phy.type); + + if (hw->phy.type == ixgbe_phy_none) { + hw->phy.sfp_type = ixgbe_sfp_type_unknown; + goto out; + } + + /* Try to do the initialization that was skipped before */ + if (hw->phy.ops.init) + hw->phy.ops.init(hw); + if (hw->phy.ops.reset) + hw->phy.ops.reset(hw); + } + err = hw->phy.ops.identify_sfp(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { device_printf(dev, "Unsupported SFP+ module type was detected.\n"); - return; + goto out; } err = hw->mac.ops.setup_sfp(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { device_printf(dev, "Setup failure - unsupported SFP+ module type.\n"); - return; + goto out; } - taskqueue_enqueue(adapter->tq, &adapter->msf_task); + if (hw->phy.multispeed_fiber) + taskqueue_enqueue(adapter->tq, &adapter->msf_task); +out: + /* Update media type */ + switch (hw->mac.ops.get_media_type(hw)) { + case ixgbe_media_type_fiber: + adapter->optics = IFM_10G_SR; + break; + case ixgbe_media_type_copper: + adapter->optics = IFM_10G_TWINAX; + break; + case ixgbe_media_type_cx4: + adapter->optics = IFM_10G_CX4; + break; + default: + adapter->optics = 0; + break; + } + + IXGBE_CORE_UNLOCK(adapter); return; } @@ -3675,13 +3839,10 @@ ixgbe_handle_msf(void *context, int pending) struct ixgbe_hw *hw = &adapter->hw; u32 autoneg; bool negotiate; - int err; - err = hw->phy.ops.identify_sfp(hw); - if (!err) { - ixgbe_setup_optics(adapter); - INIT_DEBUGOUT1("ixgbe_sfp_probe: flags: %X\n", adapter->optics); - } + IXGBE_CORE_LOCK(adapter); + /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ + adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); autoneg = hw->phy.autoneg_advertised; if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) @@ -3689,8 +3850,10 @@ ixgbe_handle_msf(void *context, int pending) if (hw->mac.ops.setup_link) hw->mac.ops.setup_link(hw, autoneg, TRUE); + /* Adjust media types shown in ifconfig */ ifmedia_removeall(&adapter->media); ixgbe_add_media_types(adapter); + IXGBE_CORE_UNLOCK(adapter); return; } @@ -3768,18 +3931,6 @@ ixgbe_config_dmac(struct adapter *adapter) } /* - * Checks whether the adapter supports Energy Efficient Ethernet - * or not, based on device ID. - */ -static void -ixgbe_check_eee_support(struct adapter *adapter) -{ - struct ixgbe_hw *hw = &adapter->hw; - - adapter->eee_enabled = !!(hw->mac.ops.setup_eee); -} - -/* * Checks whether the adapter's ports are capable of * Wake On LAN by reading the adapter's NVM. * @@ -3797,8 +3948,8 @@ ixgbe_check_wol_support(struct adapter *adapter) ixgbe_get_device_caps(hw, &dev_caps); if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && - hw->bus.func == 0)) - adapter->wol_support = hw->wol_enabled = 1; + hw->bus.func == 0)) + adapter->wol_support = hw->wol_enabled = 1; /* Save initial wake up filter configuration */ adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); @@ -4145,14 +4296,24 @@ ixgbe_add_device_sysctls(struct adapter *adapter) CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_thermal_test, "I", "Thermal Test"); - /* for X550 devices */ +#ifdef IXGBE_DEBUG + /* testing sysctls (for all devices) */ + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state", + CTLTYPE_INT | CTLFLAG_RW, adapter, 0, + ixgbe_sysctl_power_state, "I", "PCI Power State"); + + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config", + CTLTYPE_STRING | CTLFLAG_RD, adapter, 0, + ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); +#endif + /* for X550 series devices */ if (hw->mac.type >= ixgbe_mac_X550) SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_dmac, "I", "DMA Coalesce"); - /* for X550T and X550EM backplane devices */ - if (hw->mac.ops.setup_eee) { + /* for X552 backplane devices */ + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { struct sysctl_oid *eee_node; struct sysctl_oid_list *eee_list; @@ -4180,11 +4341,15 @@ ixgbe_add_device_sysctls(struct adapter *adapter) CTLTYPE_INT | CTLFLAG_RD, adapter, 0, ixgbe_sysctl_eee_rx_lpi_status, "I", "Whether or not RX link is in LPI state"); + + SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_delay", + CTLTYPE_INT | CTLFLAG_RD, adapter, 0, + ixgbe_sysctl_eee_tx_lpi_delay, "I", + "TX LPI entry delay in microseconds"); } - /* for certain 10GBaseT devices */ - if (hw->device_id == IXGBE_DEV_ID_X550T || - hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { + /* for WoL-capable devices */ + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_wol_enable, "I", @@ -4196,7 +4361,7 @@ ixgbe_add_device_sysctls(struct adapter *adapter) "Enable/Disable Wake Up Filters"); } - /* for X550EM 10GBaseT devices */ + /* for X552/X557-AT devices */ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { struct sysctl_oid *phy_node; struct sysctl_oid_list *phy_list; @@ -4552,6 +4717,10 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) if ((error) || (req->newptr == NULL)) return (error); + /* No speed changes for backplane media */ + if (hw->phy.media_type == ixgbe_media_type_backplane) + return (ENODEV); + /* Checks to validate new value */ if (adapter->advertise == requested) /* no change */ return (0); @@ -4593,7 +4762,7 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) } /* - * The following two sysctls are for X550 BaseT devices; + * The following two sysctls are for X552/X557-AT devices; * they deal with the external PHY used in them. */ static int @@ -4692,31 +4861,22 @@ static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) { struct adapter *adapter = (struct adapter *) arg1; - struct ixgbe_hw *hw = &adapter->hw; struct ifnet *ifp = adapter->ifp; int error; - u16 oldval; + u32 newval; - oldval = adapter->dmac; - error = sysctl_handle_int(oidp, &adapter->dmac, 0, req); + newval = adapter->dmac; + error = sysctl_handle_int(oidp, &newval, 0, req); if ((error) || (req->newptr == NULL)) return (error); - switch (hw->mac.type) { - case ixgbe_mac_X550: - case ixgbe_mac_X550EM_x: - break; - default: - device_printf(adapter->dev, - "DMA Coalescing is only supported on X550 devices\n"); - return (ENODEV); - } - - switch (adapter->dmac) { + switch (newval) { case 0: /* Disabled */ + adapter->dmac = 0; break; - case 1: /* Enable and use default */ + case 1: + /* Enable and use default */ adapter->dmac = 1000; break; case 50: @@ -4728,10 +4888,10 @@ ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) case 5000: case 10000: /* Legal values - allow */ + adapter->dmac = newval; break; default: /* Do nothing, illegal value */ - adapter->dmac = oldval; return (EINVAL); } @@ -4742,6 +4902,42 @@ ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) return (0); } +#ifdef IXGBE_DEBUG +/** + * Sysctl to test power states + * Values: + * 0 - set device to D0 + * 3 - set device to D3 + * (none) - get current device power state + */ +static int +ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter = (struct adapter *) arg1; + device_t dev = adapter->dev; + int curr_ps, new_ps, error = 0; + + curr_ps = new_ps = pci_get_powerstate(dev); + + error = sysctl_handle_int(oidp, &new_ps, 0, req); + if ((error) || (req->newptr == NULL)) + return (error); + + if (new_ps == curr_ps) + return (0); + + if (new_ps == 3 && curr_ps == 0) + error = DEVICE_SUSPEND(dev); + else if (new_ps == 0 && curr_ps == 3) + error = DEVICE_RESUME(dev); + else + return (EINVAL); + + device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); + + return (error); +} +#endif /* * Sysctl to enable/disable the WoL capability, if supported by the adapter. * Values: @@ -4760,13 +4956,14 @@ ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); if ((error) || (req->newptr == NULL)) return (error); + new_wol_enabled = !!(new_wol_enabled); if (new_wol_enabled == hw->wol_enabled) return (0); if (new_wol_enabled > 0 && !adapter->wol_support) return (ENODEV); else - hw->wol_enabled = !!(new_wol_enabled); + hw->wol_enabled = new_wol_enabled; return (0); } @@ -4790,13 +4987,14 @@ ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req); if ((error) || (req->newptr == NULL)) return (error); + new_eee_enabled = !!(new_eee_enabled); if (new_eee_enabled == adapter->eee_enabled) return (0); if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee) return (ENODEV); else - adapter->eee_enabled = !!(new_eee_enabled); + adapter->eee_enabled = new_eee_enabled; /* Re-initialize hardware if it's already running */ if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -4854,6 +5052,21 @@ ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS) } /* + * Read-only sysctl indicating TX Link LPI delay + */ +static int +ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter = (struct adapter *) arg1; + struct ixgbe_hw *hw = &adapter->hw; + u32 reg; + + reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU); + + return (sysctl_handle_int(oidp, 0, reg >> 26, req)); +} + +/* * Sysctl to enable/disable the types of packets that the * adapter will wake up on upon receipt. * WUFC - Wake Up Filter Control @@ -4896,6 +5109,58 @@ ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) return (0); } +#ifdef IXGBE_DEBUG +static int +ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter = (struct adapter *)arg1; + struct ixgbe_hw *hw = &adapter->hw; + device_t dev = adapter->dev; + int error = 0, reta_size; + struct sbuf *buf; + u32 reg; + + buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); + if (!buf) { + device_printf(dev, "Could not allocate sbuf for output.\n"); + return (ENOMEM); + } + + // TODO: use sbufs to make a string to print out + /* Set multiplier for RETA setup and table size based on MAC */ + switch (adapter->hw.mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: + reta_size = 128; + break; + default: + reta_size = 32; + break; + } + + /* Print out the redirection table */ + sbuf_cat(buf, "\n"); + for (int i = 0; i < reta_size; i++) { + if (i < 32) { + reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); + sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); + } else { + reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); + sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); + } + } + + // TODO: print more config + + error = sbuf_finish(buf); + if (error) + device_printf(dev, "Error finishing sbuf: %d\n", error); + + sbuf_delete(buf); + return (0); +} +#endif /* IXGBE_DEBUG */ + /* ** Enable the hardware to drop packets when the buffer is ** full. This is useful when multiqueue,so that no single diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c index 4ac8613..914f742 100644 --- a/sys/dev/ixgbe/if_ixv.c +++ b/sys/dev/ixgbe/if_ixv.c @@ -43,7 +43,7 @@ /********************************************************************* * Driver version *********************************************************************/ -char ixv_driver_version[] = "1.4.0"; +char ixv_driver_version[] = "1.4.6-k"; /********************************************************************* * PCI Device ID Table @@ -292,9 +292,14 @@ ixv_attach(device_t dev) /* Allocate, clear, and link in our adapter structure */ adapter = device_get_softc(dev); - adapter->dev = adapter->osdep.dev = dev; + adapter->dev = dev; hw = &adapter->hw; +#ifdef DEV_NETMAP + adapter->init_locked = ixv_init_locked; + adapter->stop_locked = ixv_stop; +#endif + /* Core Lock Init*/ IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); @@ -317,7 +322,7 @@ ixv_attach(device_t dev) /* Do base PCI setup - map BAR0 */ if (ixv_allocate_pci_resources(adapter)) { - device_printf(dev, "Allocation of PCI resources failed\n"); + device_printf(dev, "ixv_allocate_pci_resources() failed!\n"); error = ENXIO; goto err_out; } @@ -357,6 +362,7 @@ ixv_attach(device_t dev) /* Allocate our TX/RX Queues */ if (ixgbe_allocate_queues(adapter)) { + device_printf(dev, "ixgbe_allocate_queues() failed!\n"); error = ENOMEM; goto err_out; } @@ -367,7 +373,7 @@ ixv_attach(device_t dev) */ error = ixgbe_init_shared_code(hw); if (error) { - device_printf(dev,"Shared Code Initialization Failure\n"); + device_printf(dev, "ixgbe_init_shared_code() failed!\n"); error = EIO; goto err_late; } @@ -375,23 +381,37 @@ ixv_attach(device_t dev) /* Setup the mailbox */ ixgbe_init_mbx_params_vf(hw); - ixgbe_reset_hw(hw); + /* Reset mbox api to 1.0 */ + error = ixgbe_reset_hw(hw); + if (error == IXGBE_ERR_RESET_FAILED) + device_printf(dev, "ixgbe_reset_hw() failure: Reset Failed!\n"); + else if (error) + device_printf(dev, "ixgbe_reset_hw() failed with error %d\n", error); + if (error) { + error = EIO; + goto err_late; + } - /* Get the Mailbox API version */ - device_printf(dev,"MBX API %d negotiation: %d\n", - ixgbe_mbox_api_11, - ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11)); + /* Negotiate mailbox API version */ + error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11); + if (error) { + device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error); + error = EIO; + goto err_late; + } error = ixgbe_init_hw(hw); if (error) { - device_printf(dev,"Hardware Initialization Failure\n"); + device_printf(dev, "ixgbe_init_hw() failed!\n"); error = EIO; goto err_late; } error = ixv_allocate_msix(adapter); - if (error) + if (error) { + device_printf(dev, "ixv_allocate_msix() failed!\n"); goto err_late; + } /* If no mac address was assigned, make a random one */ if (!ixv_check_ether_addr(hw->mac.addr)) { @@ -451,7 +471,7 @@ ixv_detach(device_t dev) /* Make sure VLANS are not using driver */ if (adapter->ifp->if_vlantrunk != NULL) { - device_printf(dev,"Vlan in use, detach first\n"); + device_printf(dev, "Vlan in use, detach first\n"); return (EBUSY); } @@ -560,13 +580,13 @@ ixv_ioctl(struct ifnet * ifp, u_long command, caddr_t data) #endif case SIOCSIFMTU: IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); - if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) { + if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) { error = EINVAL; } else { IXGBE_CORE_LOCK(adapter); ifp->if_mtu = ifr->ifr_mtu; adapter->max_frame_size = - ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; + ifp->if_mtu + IXGBE_MTU_HDR; ixv_init_locked(adapter); IXGBE_CORE_UNLOCK(adapter); } @@ -647,9 +667,9 @@ ixv_init_locked(struct adapter *adapter) struct ifnet *ifp = adapter->ifp; device_t dev = adapter->dev; struct ixgbe_hw *hw = &adapter->hw; - u32 mhadd, gpie; + int error = 0; - INIT_DEBUGOUT("ixv_init: begin"); + INIT_DEBUGOUT("ixv_init_locked: begin"); mtx_assert(&adapter->core_mtx, MA_OWNED); hw->adapter_stopped = FALSE; ixgbe_stop_adapter(hw); @@ -666,12 +686,17 @@ ixv_init_locked(struct adapter *adapter) /* Prepare transmit descriptors and buffers */ if (ixgbe_setup_transmit_structures(adapter)) { - device_printf(dev,"Could not setup transmit structures\n"); + device_printf(dev, "Could not setup transmit structures\n"); ixv_stop(adapter); return; } + /* Reset VF and renegotiate mailbox API version */ ixgbe_reset_hw(hw); + error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11); + if (error) + device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error); + ixv_initialize_transmit_units(adapter); /* Setup Multicast table */ @@ -688,7 +713,7 @@ ixv_init_locked(struct adapter *adapter) /* Prepare receive descriptors and buffers */ if (ixgbe_setup_receive_structures(adapter)) { - device_printf(dev,"Could not setup receive structures\n"); + device_printf(dev, "Could not setup receive structures\n"); ixv_stop(adapter); return; } @@ -696,12 +721,6 @@ ixv_init_locked(struct adapter *adapter) /* Configure RX settings */ ixv_initialize_receive_units(adapter); - /* Enable Enhanced MSIX mode */ - gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE); - gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME; - gpie |= IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD; - IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); - /* Set the various hardware offload abilities */ ifp->if_hwassist = 0; if (ifp->if_capenable & IFCAP_TSO4) @@ -713,19 +732,9 @@ ixv_init_locked(struct adapter *adapter) #endif } - /* Set MTU size */ - if (ifp->if_mtu > ETHERMTU) { - mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); - mhadd &= ~IXGBE_MHADD_MFS_MASK; - mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; - IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); - } - /* Set up VLAN offload and filter */ ixv_setup_vlan_support(adapter); - callout_reset(&adapter->timer, hz, ixv_local_timer, adapter); - /* Set up MSI/X routing */ ixv_configure_ivars(adapter); @@ -741,6 +750,9 @@ ixv_init_locked(struct adapter *adapter) /* Config/Enable Link */ ixv_config_link(adapter); + /* Start watchdog */ + callout_reset(&adapter->timer, hz, ixv_local_timer, adapter); + /* And now turn on interrupts */ ixv_enable_intr(adapter); @@ -1418,7 +1430,7 @@ ixv_allocate_pci_resources(struct adapter *adapter) &rid, RF_ACTIVE); if (!(adapter->pci_mem)) { - device_printf(dev,"Unable to allocate bus resource: memory\n"); + device_printf(dev, "Unable to allocate bus resource: memory\n"); return (ENXIO); } @@ -1426,12 +1438,11 @@ ixv_allocate_pci_resources(struct adapter *adapter) rman_get_bustag(adapter->pci_mem); adapter->osdep.mem_bus_space_handle = rman_get_bushandle(adapter->pci_mem); - adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle; + adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; /* Pick up the tuneable queues */ adapter->num_queues = ixv_num_queues; - - adapter->hw.back = &adapter->osdep; + adapter->hw.back = adapter; /* ** Now setup MSI/X, should @@ -1539,7 +1550,7 @@ ixv_setup_interface(device_t dev, struct adapter *adapter) ether_ifattach(ifp, adapter->hw.mac.addr); adapter->max_frame_size = - ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; + ifp->if_mtu + IXGBE_MTU_HDR_VLAN; /* * Tell the upper layer(s) we support long frames. @@ -1560,7 +1571,6 @@ ixv_setup_interface(device_t dev, struct adapter *adapter) */ ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change, ixv_media_status); - ifmedia_add(&adapter->media, IFM_ETHER | IFM_FDX, 0, NULL); ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); @@ -1571,19 +1581,11 @@ static void ixv_config_link(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - u32 autoneg, err = 0; + u32 autoneg; if (hw->mac.ops.check_link) - err = hw->mac.ops.check_link(hw, &autoneg, + hw->mac.ops.check_link(hw, &autoneg, &adapter->link_up, FALSE); - if (err) - goto out; - - if (hw->mac.ops.setup_link) - err = hw->mac.ops.setup_link(hw, - autoneg, adapter->link_up); -out: - return; } @@ -1650,7 +1652,6 @@ ixv_initialize_receive_units(struct adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; struct ifnet *ifp = adapter->ifp; u32 bufsz, rxcsum, psrtype; - int max_frame; if (ifp->if_mtu > ETHERMTU) bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; @@ -1663,9 +1664,8 @@ ixv_initialize_receive_units(struct adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); - /* Tell PF our expected packet-size */ - max_frame = ifp->if_mtu + IXGBE_MTU_HDR; - ixgbevf_rlpml_set_vf(hw, max_frame); + /* Tell PF our max_frame size */ + ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size); for (int i = 0; i < adapter->num_queues; i++, rxr++) { u64 rdba = rxr->rxdma.dma_paddr; @@ -1673,7 +1673,7 @@ ixv_initialize_receive_units(struct adapter *adapter) /* Disable the queue */ rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); - rxdctl &= ~(IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME); + rxdctl &= ~IXGBE_RXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl); for (int j = 0; j < 10; j++) { if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) & @@ -1703,17 +1703,11 @@ ixv_initialize_receive_units(struct adapter *adapter) reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), reg); - /* Setup the HW Rx Head and Tail Descriptor Pointers */ - IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), - adapter->num_rx_desc - 1); - - /* Set Rx Tail register */ + /* Capture Rx Tail register */ rxr->tail = IXGBE_VFRDT(rxr->me); /* Do the queue enabling last */ - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); - rxdctl |= IXGBE_RXDCTL_ENABLE; + rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl); for (int k = 0; k < 10; k++) { if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) & @@ -1772,7 +1766,7 @@ ixv_setup_vlan_support(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 ctrl, vid, vfta, retry; - + struct rx_ring *rxr; /* ** We get here thru init_locked, meaning @@ -1788,6 +1782,12 @@ ixv_setup_vlan_support(struct adapter *adapter) ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); ctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl); + /* + * Let Rx path know that it needs to store VLAN tag + * as part of extra mbuf info. + */ + rxr = &adapter->rx_rings[i]; + rxr->vtag_strip = TRUE; } /* @@ -1803,7 +1803,7 @@ ixv_setup_vlan_support(struct adapter *adapter) ** based on the bits set in each ** of the array ints. */ - for ( int j = 0; j < 32; j++) { + for (int j = 0; j < 32; j++) { retry = 0; if ((vfta & (1 << j)) == 0) continue; @@ -1830,10 +1830,10 @@ ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) struct adapter *adapter = ifp->if_softc; u16 index, bit; - if (ifp->if_softc != arg) /* Not our event */ + if (ifp->if_softc != arg) /* Not our event */ return; - if ((vtag == 0) || (vtag > 4095)) /* Invalid */ + if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; IXGBE_CORE_LOCK(adapter); diff --git a/sys/dev/ixgbe/ix_txrx.c b/sys/dev/ixgbe/ix_txrx.c index f70b89e..9e90e0d 100644 --- a/sys/dev/ixgbe/ix_txrx.c +++ b/sys/dev/ixgbe/ix_txrx.c @@ -80,27 +80,6 @@ static bool ixgbe_rsc_enable = FALSE; static int atr_sample_rate = 20; #endif -/* Shared PCI config read/write */ -inline u16 -ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg) -{ - u16 value; - - value = pci_read_config(((struct ixgbe_osdep *)hw->back)->dev, - reg, 2); - - return (value); -} - -inline void -ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value) -{ - pci_write_config(((struct ixgbe_osdep *)hw->back)->dev, - reg, value, 2); - - return; -} - /********************************************************************* * Local Function prototypes *********************************************************************/ @@ -188,8 +167,8 @@ ixgbe_start(struct ifnet *ifp) #else /* ! IXGBE_LEGACY_TX */ /* -** Multiqueue Transmit driver -** +** Multiqueue Transmit Entry Point +** (if_transmit function) */ int ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m) @@ -212,10 +191,14 @@ ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m) if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { #ifdef RSS if (rss_hash2bucket(m->m_pkthdr.flowid, - M_HASHTYPE_GET(m), &bucket_id) == 0) - /* TODO: spit out something if bucket_id > num_queues? */ + M_HASHTYPE_GET(m), &bucket_id) == 0) { i = bucket_id % adapter->num_queues; - else +#ifdef IXGBE_DEBUG + if (bucket_id > adapter->num_queues) + if_printf(ifp, "bucket_id (%d) > num_queues " + "(%d)\n", bucket_id, adapter->num_queues); +#endif + } else #endif i = m->m_pkthdr.flowid % adapter->num_queues; } else @@ -447,6 +430,7 @@ retry: } #endif + olinfo_status |= IXGBE_ADVTXD_CC; i = txr->next_avail_desc; for (j = 0; j < nsegs; j++) { bus_size_t seglen; @@ -741,8 +725,12 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, struct adapter *adapter = txr->adapter; struct ixgbe_adv_tx_context_desc *TXD; struct ether_vlan_header *eh; +#ifdef INET struct ip *ip; +#endif +#ifdef INET6 struct ip6_hdr *ip6; +#endif u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0; int ehdrlen, ip_hlen = 0; u16 etype; @@ -750,9 +738,11 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, int offload = TRUE; int ctxd = txr->next_avail_desc; u16 vtag = 0; + caddr_t l3d; + /* First check if TSO is to be used */ - if (mp->m_pkthdr.csum_flags & CSUM_TSO) + if (mp->m_pkthdr.csum_flags & (CSUM_IP_TSO|CSUM_IP6_TSO)) return (ixgbe_tso_setup(txr, mp, cmd_type_len, olinfo_status)); if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0) @@ -795,20 +785,38 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, if (offload == FALSE) goto no_offloads; + /* + * If the first mbuf only includes the ethernet header, jump to the next one + * XXX: This assumes the stack splits mbufs containing headers on header boundaries + * XXX: And assumes the entire IP header is contained in one mbuf + */ + if (mp->m_len == ehdrlen && mp->m_next) + l3d = mtod(mp->m_next, caddr_t); + else + l3d = mtod(mp, caddr_t) + ehdrlen; + switch (etype) { +#ifdef INET case ETHERTYPE_IP: - ip = (struct ip *)(mp->m_data + ehdrlen); + ip = (struct ip *)(l3d); ip_hlen = ip->ip_hl << 2; ipproto = ip->ip_p; type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; + /* Insert IPv4 checksum into data descriptors */ + if (mp->m_pkthdr.csum_flags & CSUM_IP) { + ip->ip_sum = 0; + *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8; + } break; +#endif +#ifdef INET6 case ETHERTYPE_IPV6: - ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); + ip6 = (struct ip6_hdr *)(l3d); ip_hlen = sizeof(struct ip6_hdr); - /* XXX-BZ this will go badly in case of ext hdrs. */ ipproto = ip6->ip6_nxt; type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6; break; +#endif default: offload = FALSE; break; @@ -816,29 +824,32 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, vlan_macip_lens |= ip_hlen; + /* No support for offloads for non-L4 next headers */ switch (ipproto) { case IPPROTO_TCP: - if (mp->m_pkthdr.csum_flags & CSUM_TCP) + if (mp->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + else + offload = false; break; - case IPPROTO_UDP: - if (mp->m_pkthdr.csum_flags & CSUM_UDP) + if (mp->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP; + else + offload = false; break; - -#if __FreeBSD_version >= 800000 case IPPROTO_SCTP: - if (mp->m_pkthdr.csum_flags & CSUM_SCTP) + if (mp->m_pkthdr.csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP)) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP; + else + offload = false; break; -#endif default: - offload = FALSE; + offload = false; break; } - if (offload) /* For the TX descriptor setup */ + if (offload) /* Insert L4 checksum into data descriptors */ *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8; no_offloads: @@ -883,7 +894,6 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, #endif struct tcphdr *th; - /* * Determine where frame payload starts. * Jump over vlan headers if already present @@ -1040,7 +1050,7 @@ ixgbe_txeof(struct tx_ring *txr) BUS_DMASYNC_POSTREAD); do { - union ixgbe_adv_tx_desc *eop= buf->eop; + union ixgbe_adv_tx_desc *eop = buf->eop; if (eop == NULL) /* No work */ break; @@ -1282,6 +1292,7 @@ ixgbe_setup_hw_rsc(struct rx_ring *rxr) rxr->hw_rsc = TRUE; } + /********************************************************************* * * Refresh mbuf buffers for RX descriptor rings @@ -1417,7 +1428,6 @@ fail: return (error); } - static void ixgbe_free_receive_ring(struct rx_ring *rxr) { @@ -1437,7 +1447,6 @@ ixgbe_free_receive_ring(struct rx_ring *rxr) } } - /********************************************************************* * * Initialize a receive ring and its buffers. @@ -1985,34 +1994,28 @@ ixgbe_rx_checksum(u32 staterr, struct mbuf * mp, u32 ptype) { u16 status = (u16) staterr; u8 errors = (u8) (staterr >> 24); - bool sctp = FALSE; + bool sctp = false; if ((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 && (ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0) - sctp = TRUE; + sctp = true; + /* IPv4 checksum */ if (status & IXGBE_RXD_STAT_IPCS) { - if (!(errors & IXGBE_RXD_ERR_IPE)) { - /* IP Checksum Good */ - mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; - mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; - - } else - mp->m_pkthdr.csum_flags = 0; + mp->m_pkthdr.csum_flags |= CSUM_L3_CALC; + /* IP Checksum Good */ + if (!(errors & IXGBE_RXD_ERR_IPE)) + mp->m_pkthdr.csum_flags |= CSUM_L3_VALID; } + /* TCP/UDP/SCTP checksum */ if (status & IXGBE_RXD_STAT_L4CS) { - u64 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); -#if __FreeBSD_version >= 800000 - if (sctp) - type = CSUM_SCTP_VALID; -#endif + mp->m_pkthdr.csum_flags |= CSUM_L4_CALC; if (!(errors & IXGBE_RXD_ERR_TCPE)) { - mp->m_pkthdr.csum_flags |= type; + mp->m_pkthdr.csum_flags |= CSUM_L4_VALID; if (!sctp) mp->m_pkthdr.csum_data = htons(0xffff); - } + } } - return; } /******************************************************************** diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index be27e36..05fddf6 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -141,12 +141,6 @@ #define DBA_ALIGN 128 /* - * This parameter controls the maximum no of times the driver will loop in - * the isr. Minimum Value = 1 - */ -#define MAX_LOOP 10 - -/* * This is the max watchdog interval, ie. the time that can * pass between any two TX clean operations, such only happening * when the TX hardware is functioning. @@ -162,9 +156,11 @@ /* These defines are used in MTU calculations */ #define IXGBE_MAX_FRAME_SIZE 9728 -#define IXGBE_MTU_HDR (ETHER_HDR_LEN + ETHER_CRC_LEN + \ +#define IXGBE_MTU_HDR (ETHER_HDR_LEN + ETHER_CRC_LEN) +#define IXGBE_MTU_HDR_VLAN (ETHER_HDR_LEN + ETHER_CRC_LEN + \ ETHER_VLAN_ENCAP_LEN) #define IXGBE_MAX_MTU (IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) +#define IXGBE_MAX_MTU_VLAN (IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR_VLAN) /* Flow control constants */ #define IXGBE_FC_PAUSE 0xFFFF @@ -181,6 +177,9 @@ * modern Intel CPUs, results in 40 bytes wasted and a significant drop * in observed efficiency of the optimization, 97.9% -> 81.8%. */ +#if __FreeBSD_version < 1002000 +#define MPKTHSIZE (sizeof(struct m_hdr) + sizeof(struct pkthdr)) +#endif #define IXGBE_RX_COPY_HDR_PADDED ((((MPKTHSIZE - 1) / 32) + 1) * 32) #define IXGBE_RX_COPY_LEN (MSIZE - IXGBE_RX_COPY_HDR_PADDED) #define IXGBE_RX_COPY_ALIGN (IXGBE_RX_COPY_HDR_PADDED - MPKTHSIZE) @@ -211,7 +210,6 @@ #define MSIX_82598_BAR 3 #define MSIX_82599_BAR 4 #define IXGBE_TSO_SIZE 262140 -#define IXGBE_TX_BUFFER_SIZE ((u32) 1514) #define IXGBE_RX_HDR 128 #define IXGBE_VFTA_SIZE 128 #define IXGBE_BR_SIZE 4096 @@ -221,8 +219,12 @@ #define IXV_EITR_DEFAULT 128 -/* Offload bits in mbuf flag */ -#if __FreeBSD_version >= 800000 +/* Supported offload bits in mbuf flag */ +#if __FreeBSD_version >= 1000000 +#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \ + CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \ + CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP) +#elif __FreeBSD_version >= 800000 #define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP) #else #define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP) @@ -243,7 +245,11 @@ #define IXGBE_LOW_LATENCY 128 #define IXGBE_AVE_LATENCY 400 #define IXGBE_BULK_LATENCY 1200 -#define IXGBE_LINK_ITR 2000 + +/* Using 1FF (the max value), the interval is ~1.05ms */ +#define IXGBE_LINK_ITR_QUANTA 0x1FF +#define IXGBE_LINK_ITR ((IXGBE_LINK_ITR_QUANTA << 3) & \ + IXGBE_EITR_ITR_INT_MASK) /* MAC type macros */ #define IXGBE_IS_X550VF(_adapter) \ @@ -449,11 +455,11 @@ struct ixgbe_vf { /* Our adapter structure */ struct adapter { - struct ifnet *ifp; struct ixgbe_hw hw; - struct ixgbe_osdep osdep; + struct device *dev; + struct ifnet *ifp; struct resource *pci_mem; struct resource *msix_mem; @@ -555,6 +561,10 @@ struct adapter { #ifdef PCI_IOV struct ixgbe_vf *vfs; #endif +#ifdef DEV_NETMAP + void (*init_locked)(struct adapter *); + void (*stop_locked)(void *); +#endif /* Misc stats maintained by the driver */ unsigned long dropped_pkts; diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c index 46e64c5..c10e23a 100644 --- a/sys/dev/ixgbe/ixgbe_82598.c +++ b/sys/dev/ixgbe/ixgbe_82598.c @@ -660,7 +660,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) { *link_up = TRUE; @@ -689,7 +689,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = TRUE; break; diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c index b38620f..109ed95 100644 --- a/sys/dev/ixgbe/ixgbe_82599.c +++ b/sys/dev/ixgbe/ixgbe_82599.c @@ -382,8 +382,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); - mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & - IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE; + mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)) + & IXGBE_FWSM_MODE_MASK); hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; @@ -1370,7 +1370,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, * Continue setup of fdirctrl register bits: * Turn perfect match filtering on * Report hash in RSS field of Rx wb descriptor - * Initialize the drop queue + * Initialize the drop queue to queue 127 * Move the flexible bytes to use the ethertype - shift 6 words * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 (0x4 * 16) filters are left @@ -1381,6 +1381,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); + if ((hw->mac.type == ixgbe_mac_X550) || + (hw->mac.type == ixgbe_mac_X550EM_x)) + fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH; if (cloud_mode) fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD << @@ -1392,6 +1395,39 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, return IXGBE_SUCCESS; } +/** + * ixgbe_set_fdir_drop_queue_82599 - Set Flow Director drop queue + * @hw: pointer to hardware structure + * @dropqueue: Rx queue index used for the dropped packets + **/ +void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue) +{ + u32 fdirctrl; + + DEBUGFUNC("ixgbe_set_fdir_drop_queue_82599"); + /* Clear init done bit and drop queue field */ + fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); + fdirctrl &= ~(IXGBE_FDIRCTRL_DROP_Q_MASK | IXGBE_FDIRCTRL_INIT_DONE); + + /* Set drop queue */ + fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT); + if ((hw->mac.type == ixgbe_mac_X550) || + (hw->mac.type == ixgbe_mac_X550EM_x)) + fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH; + + IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, + (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) | + IXGBE_FDIRCMD_CLEARHT)); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, + (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & + ~IXGBE_FDIRCMD_CLEARHT)); + IXGBE_WRITE_FLUSH(hw); + + /* write hashes and fdirctrl register, poll for completion */ + ixgbe_fdir_enable_82599(hw, fdirctrl); +} + /* * These defines allow us to quickly generate all of the necessary instructions * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION @@ -1492,16 +1528,15 @@ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, * Note that the tunnel bit in input must not be set when the hardware * tunneling support does not exist. **/ -s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, - union ixgbe_atr_hash_dword input, - union ixgbe_atr_hash_dword common, - u8 queue) +void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, + union ixgbe_atr_hash_dword input, + union ixgbe_atr_hash_dword common, + u8 queue) { u64 fdirhashcmd; u8 flow_type; bool tunnel; u32 fdircmd; - s32 err; DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599"); @@ -1523,7 +1558,7 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, break; default: DEBUGOUT(" Error on flow type input\n"); - return IXGBE_ERR_CONFIG; + return; } /* configure FDIRCMD register */ @@ -1542,15 +1577,9 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common); IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd); - err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); - if (err) { - DEBUGOUT("Flow Director command did not complete!\n"); - return err; - } - DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd); - return IXGBE_SUCCESS; + return; } #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c index 9784e3c..0f4d973 100644 --- a/sys/dev/ixgbe/ixgbe_api.c +++ b/sys/dev/ixgbe/ixgbe_api.c @@ -35,8 +35,10 @@ #include "ixgbe_api.h" #include "ixgbe_common.h" +#define IXGBE_EMPTY_PARAM + static const u32 ixgbe_mvals_base[IXGBE_MVALS_IDX_LIMIT] = { - IXGBE_MVALS_INIT() + IXGBE_MVALS_INIT(IXGBE_EMPTY_PARAM) }; static const u32 ixgbe_mvals_X540[IXGBE_MVALS_IDX_LIMIT] = { @@ -113,6 +115,7 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } + hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME; return status; } @@ -187,6 +190,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) hw->mvals = ixgbe_mvals_X540; break; case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: hw->mac.type = ixgbe_mac_X550; hw->mvals = ixgbe_mvals_X550; break; diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h index 8c2c4a8..24d5070 100644 --- a/sys/dev/ixgbe/ixgbe_api.h +++ b/sys/dev/ixgbe/ixgbe_api.h @@ -148,10 +148,10 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl); s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, bool cloud_mode); -s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, - union ixgbe_atr_hash_dword input, - union ixgbe_atr_hash_dword common, - u8 queue); +void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, + union ixgbe_atr_hash_dword input, + union ixgbe_atr_hash_dword common, + u8 queue); s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input_mask, bool cloud_mode); s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, @@ -180,6 +180,7 @@ s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val); s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); +void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue); s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val); diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index f0a0776..d67e680 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -70,7 +70,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; struct ixgbe_mac_info *mac = &hw->mac; - u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); + u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); DEBUGFUNC("ixgbe_init_ops_generic"); @@ -188,6 +188,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) case IXGBE_DEV_ID_X540T1: case IXGBE_DEV_ID_X540_BYPASS: case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: case IXGBE_DEV_ID_X550EM_X_10G_T: supported = TRUE; break; @@ -1038,7 +1039,7 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) bus->lan_id = bus->func; /* check for a port swap */ - reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); + reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); if (reg & IXGBE_FACTPS_LFS) bus->func ^= 0x1; } @@ -1164,7 +1165,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) * Check for EEPROM present first. * If not present leave as none */ - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); if (eec & IXGBE_EEC_PRES) { eeprom->type = ixgbe_eeprom_spi; @@ -1725,14 +1726,14 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) status = IXGBE_ERR_SWFW_SYNC; if (status == IXGBE_SUCCESS) { - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); /* Request EEPROM Access */ eec |= IXGBE_EEC_REQ; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); if (eec & IXGBE_EEC_GNT) break; usec_delay(5); @@ -1741,7 +1742,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) /* Release if grant not acquired */ if (!(eec & IXGBE_EEC_GNT)) { eec &= ~IXGBE_EEC_REQ; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); DEBUGOUT("Could not acquire EEPROM grant\n"); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); @@ -1752,7 +1753,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) if (status == IXGBE_SUCCESS) { /* Clear CS and SK */ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } @@ -1782,7 +1783,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); if (!(swsm & IXGBE_SWSM_SMBI)) { status = IXGBE_SUCCESS; break; @@ -1807,7 +1808,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); if (!(swsm & IXGBE_SWSM_SMBI)) status = IXGBE_SUCCESS; } @@ -1815,17 +1816,17 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) /* Now get the semaphore between SW/FW through the SWESMBI bit */ if (status == IXGBE_SUCCESS) { for (i = 0; i < timeout; i++) { - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); /* Set the SW EEPROM semaphore bit to request access */ swsm |= IXGBE_SWSM_SWESMBI; - IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); + IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); /* * If we set the bit successfully then we got the * semaphore. */ - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); if (swsm & IXGBE_SWSM_SWESMBI) break; @@ -1922,15 +1923,15 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_standby_eeprom"); - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); /* Toggle CS to flush commands */ eec |= IXGBE_EEC_CS; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); eec &= ~IXGBE_EEC_CS; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } @@ -1950,7 +1951,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); /* * Mask is used to shift "count" bits of "data" out to the EEPROM @@ -1971,7 +1972,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, else eec &= ~IXGBE_EEC_DI; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); @@ -1988,7 +1989,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, /* We leave the "DI" bit set to "0" when we leave this routine. */ eec &= ~IXGBE_EEC_DI; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); } @@ -2011,7 +2012,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) * the value of the "DO" bit. During this "shifting in" process the * "DI" bit should always be clear. */ - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); @@ -2019,7 +2020,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) data = data << 1; ixgbe_raise_eeprom_clk(hw, &eec); - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); eec &= ~(IXGBE_EEC_DI); if (eec & IXGBE_EEC_DO) @@ -2045,7 +2046,7 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) * (setting the SK bit), then delay */ *eec = *eec | IXGBE_EEC_SK; - IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } @@ -2064,7 +2065,7 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) * delay */ *eec = *eec & ~IXGBE_EEC_SK; - IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } @@ -2079,19 +2080,19 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_release_eeprom"); - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); eec |= IXGBE_EEC_CS; /* Pull CS high */ eec &= ~IXGBE_EEC_SK; /* Lower SCK */ - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); /* Stop requesting EEPROM access */ eec &= ~IXGBE_EEC_REQ; - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); @@ -3147,6 +3148,9 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + if (hw->mac.type >= ixgbe_mac_X550) + goto out; + /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. @@ -4069,7 +4073,7 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, } if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = TRUE; break; @@ -4715,7 +4719,7 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw) if (hw->mac.type < ixgbe_mac_82599EB) return FALSE; - fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); fwsm &= IXGBE_FWSM_MODE_MASK; return fwsm == IXGBE_FWSM_FW_MODE_PT; } @@ -4730,7 +4734,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw) { u32 fwsm, manc, factps; - fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) return FALSE; @@ -4739,7 +4743,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw) return FALSE; if (hw->mac.type <= ixgbe_mac_X540) { - factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); + factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); if (factps & IXGBE_FACTPS_MNGCG) return FALSE; } diff --git a/sys/dev/ixgbe/ixgbe_dcb.c b/sys/dev/ixgbe/ixgbe_dcb.c index 3659d17..437d336 100644 --- a/sys/dev/ixgbe/ixgbe_dcb.c +++ b/sys/dev/ixgbe/ixgbe_dcb.c @@ -148,6 +148,11 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw, /* Calculate credit refill ratio using multiplier */ credit_refill = min(link_percentage * min_multiplier, (u32)IXGBE_DCB_MAX_CREDIT_REFILL); + + /* Refill at least minimum credit */ + if (credit_refill < min_credit) + credit_refill = min_credit; + p->data_credits_refill = (u16)credit_refill; /* Calculate maximum credit for the TC */ @@ -158,7 +163,7 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw, * of a TC is too small, the maximum credit may not be * enough to send out a jumbo frame in data plane arbitration. */ - if (credit_max && (credit_max < min_credit)) + if (credit_max < min_credit) credit_max = min_credit; if (direction == IXGBE_DCB_TX_CONFIG) { diff --git a/sys/dev/ixgbe/ixgbe_osdep.c b/sys/dev/ixgbe/ixgbe_osdep.c new file mode 100644 index 0000000..6a4e2fc --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_osdep.c @@ -0,0 +1,88 @@ +/****************************************************************************** + + Copyright (c) 2001-2015, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ +/*$FreeBSD$*/ + +#include "ixgbe_osdep.h" +#include "ixgbe.h" + +inline device_t +ixgbe_dev_from_hw(struct ixgbe_hw *hw) +{ + return ((struct adapter *)hw->back)->dev; +} + +inline u16 +ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg) +{ + return pci_read_config(((struct adapter *)hw->back)->dev, + reg, 2); +} + +inline void +ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value) +{ + pci_write_config(((struct adapter *)hw->back)->dev, + reg, value, 2); +} + +inline u32 +ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg) +{ + return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag, + ((struct adapter *)hw->back)->osdep.mem_bus_space_handle, + reg); +} + +inline void +ixgbe_write_reg(struct ixgbe_hw *hw, u32 reg, u32 val) +{ + bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag, + ((struct adapter *)hw->back)->osdep.mem_bus_space_handle, + reg, val); +} + +inline u32 +ixgbe_read_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset) +{ + return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag, + ((struct adapter *)hw->back)->osdep.mem_bus_space_handle, + reg + (offset << 2)); +} + +inline void +ixgbe_write_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset, u32 val) +{ + bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag, + ((struct adapter *)hw->back)->osdep.mem_bus_space_handle, + reg + (offset << 2), val); +} diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index 95f6ed5c..b767e73 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -61,7 +61,7 @@ #define usec_delay(x) DELAY(x) #define msec_delay(x) DELAY(1000*(x)) -#define DBG 0 +#define DBG 0 #define MSGOUT(S, A, B) printf(S "\n", A, B) #define DEBUGFUNC(F) DEBUGOUT(F); #if DBG @@ -165,7 +165,7 @@ void prefetch(void *x) * non-overlapping regions and 32-byte padding on both src and dst. */ static __inline int -ixgbe_bcopy(void *_src, void *_dst, int l) +ixgbe_bcopy(void *restrict _src, void *restrict _dst, int l) { uint64_t *src = _src; uint64_t *dst = _dst; @@ -183,11 +183,13 @@ struct ixgbe_osdep { bus_space_tag_t mem_bus_space_tag; bus_space_handle_t mem_bus_space_handle; - struct device *dev; }; -/* These routines are needed by the shared code */ +/* These routines need struct ixgbe_hw declared */ struct ixgbe_hw; +device_t ixgbe_dev_from_hw(struct ixgbe_hw *hw); + +/* These routines are needed by the shared code */ extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32); #define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg @@ -196,26 +198,18 @@ extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, u32, u16); #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS) -#define IXGBE_READ_REG(a, reg) (\ - bus_space_read_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \ - ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \ - reg)) - -#define IXGBE_WRITE_REG(a, reg, value) (\ - bus_space_write_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \ - ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \ - reg, value)) - +extern u32 ixgbe_read_reg(struct ixgbe_hw *, u32); +#define IXGBE_READ_REG(a, reg) ixgbe_read_reg(a, reg) -#define IXGBE_READ_REG_ARRAY(a, reg, offset) (\ - bus_space_read_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \ - ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \ - (reg + ((offset) << 2)))) +extern void ixgbe_write_reg(struct ixgbe_hw *, u32, u32); +#define IXGBE_WRITE_REG(a, reg, val) ixgbe_write_reg(a, reg, val) -#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) (\ - bus_space_write_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \ - ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \ - (reg + ((offset) << 2)), value)) +extern u32 ixgbe_read_reg_array(struct ixgbe_hw *, u32, u32); +#define IXGBE_READ_REG_ARRAY(a, reg, offset) \ + ixgbe_read_reg_array(a, reg, offset) +extern void ixgbe_write_reg_array(struct ixgbe_hw *, u32, u32, u32); +#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, val) \ + ixgbe_write_reg_array(a, reg, offset, val) #endif /* _IXGBE_OS_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 88206c7..6bff172 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -508,7 +508,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; break; - case X550_PHY_ID: + case X550_PHY_ID1: + case X550_PHY_ID2: + case X550_PHY_ID3: case X540_PHY_ID: phy_type = ixgbe_phy_aq; break; @@ -830,7 +832,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) if (hw->mac.type == ixgbe_mac_X550) { if (speed & IXGBE_LINK_SPEED_5GB_FULL) { - /* Set or unset auto-negotiation 1G advertisement */ + /* Set or unset auto-negotiation 5G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, @@ -848,7 +850,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) } if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) { - /* Set or unset auto-negotiation 1G advertisement */ + /* Set or unset auto-negotiation 2.5G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, @@ -950,54 +952,70 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; /* Setup link based on the new speed settings */ - hw->phy.ops.setup_link(hw); + ixgbe_setup_phy_link(hw); return IXGBE_SUCCESS; } /** - * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities - * @hw: pointer to hardware structure - * @speed: pointer to link speed - * @autoneg: boolean auto-negotiation value + * ixgbe_get_copper_speeds_supported - Get copper link speeds from phy + * @hw: pointer to hardware structure * - * Determines the supported link capabilities by reading the PHY auto - * negotiation register. + * Determines the supported link capabilities by reading the PHY auto + * negotiation register. **/ -s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg) +static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw) { s32 status; u16 speed_ability; - DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic"); - - *speed = 0; - *autoneg = TRUE; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &speed_ability); + if (status) + return status; - if (status == IXGBE_SUCCESS) { - if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) - *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) - *speed |= IXGBE_LINK_SPEED_1GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M) - *speed |= IXGBE_LINK_SPEED_100_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL; + + switch (hw->mac.type) { + case ixgbe_mac_X550: + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL; + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL; + break; + case ixgbe_mac_X550EM_x: + hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL; + break; + default: + break; } - /* Internal PHY does not support 100 Mbps */ - if (hw->mac.type == ixgbe_mac_X550EM_x) - *speed &= ~IXGBE_LINK_SPEED_100_FULL; + return status; +} - if (hw->mac.type == ixgbe_mac_X550) { - *speed |= IXGBE_LINK_SPEED_2_5GB_FULL; - *speed |= IXGBE_LINK_SPEED_5GB_FULL; - } +/** + * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @autoneg: boolean auto-negotiation value + **/ +s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg) +{ + s32 status = IXGBE_SUCCESS; + + DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic"); + + *autoneg = TRUE; + if (!hw->phy.speeds_supported) + status = ixgbe_get_copper_speeds_supported(hw); + *speed = hw->phy.speeds_supported; return status; } diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h index fad31bd..3713e28 100644 --- a/sys/dev/ixgbe/ixgbe_phy.h +++ b/sys/dev/ixgbe/ixgbe_phy.h @@ -92,16 +92,23 @@ #define IXGBE_CS4227_GLOBAL_ID_LSB 0 #define IXGBE_CS4227_SCRATCH 2 #define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5 -#define IXGBE_CS4227_SCRATCH_VALUE 0x5aa5 -#define IXGBE_CS4227_RETRIES 5 +#define IXGBE_CS4227_RESET_PENDING 0x1357 +#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5 +#define IXGBE_CS4227_RETRIES 15 +#define IXGBE_CS4227_EFUSE_STATUS 0x0181 #define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to program speed */ #define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to program EDC */ #define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to program speed */ #define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */ +#define IXGBE_CS4227_EEPROM_STATUS 0x5001 +#define IXGBE_CS4227_EEPROM_LOAD_OK 0x0001 +#define IXGBE_CS4227_SPEED_1G 0x8000 +#define IXGBE_CS4227_SPEED_10G 0 #define IXGBE_CS4227_EDC_MODE_CX1 0x0002 #define IXGBE_CS4227_EDC_MODE_SR 0x0004 +#define IXGBE_CS4227_EDC_MODE_DIAG 0x0008 #define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */ -#define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */ +#define IXGBE_CS4227_RESET_DELAY 450 /* milliseconds */ #define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */ #define IXGBE_PE 0xE0 /* Port expander address */ #define IXGBE_PE_OUTPUT 1 /* Output register offset */ diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index 2a53952..d76cde2 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -131,6 +131,7 @@ #define IXGBE_DEV_ID_X540_BYPASS 0x155C #define IXGBE_DEV_ID_X540T1 0x1560 #define IXGBE_DEV_ID_X550T 0x1563 +#define IXGBE_DEV_ID_X550T1 0x15D1 #define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA #define IXGBE_DEV_ID_X550EM_X_KR 0x15AB #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC @@ -1544,7 +1545,9 @@ struct ixgbe_dmac_config { #define TN1010_PHY_ID 0x00A19410 #define TNX_FW_REV 0xB #define X540_PHY_ID 0x01540200 -#define X550_PHY_ID 0x01540220 +#define X550_PHY_ID1 0x01540220 +#define X550_PHY_ID2 0x01540223 +#define X550_PHY_ID3 0x01540221 #define X557_PHY_ID 0x01540240 #define AQ_FW_REV 0x20 #define QT2022_PHY_ID 0x0043A400 @@ -1937,6 +1940,7 @@ enum { * FIP (0x8914): Filter 4 * LLDP (0x88CC): Filter 5 * LACP (0x8809): Filter 6 + * FC (0x8808): Filter 7 */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_FCOE 2 @@ -1944,6 +1948,7 @@ enum { #define IXGBE_ETQF_FILTER_FIP 4 #define IXGBE_ETQF_FILTER_LLDP 5 #define IXGBE_ETQF_FILTER_LACP 6 +#define IXGBE_ETQF_FILTER_FC 7 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ #define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */ @@ -2803,7 +2808,9 @@ enum ixgbe_fdir_pballoc_type { #define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020 #define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080 #define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8 +#define IXGBE_FDIRCTRL_DROP_Q_MASK 0x00007F00 #define IXGBE_FDIRCTRL_FLEX_SHIFT 16 +#define IXGBE_FDIRCTRL_DROP_NO_MATCH 0x00008000 #define IXGBE_FDIRCTRL_FILTERMODE_SHIFT 21 #define IXGBE_FDIRCTRL_FILTERMODE_MACVLAN 0x0001 /* bit 23:21, 001b */ #define IXGBE_FDIRCTRL_FILTERMODE_CLOUD 0x0002 /* bit 23:21, 010b */ @@ -2907,6 +2914,11 @@ enum ixgbe_fdir_pballoc_type { #define FW_DISABLE_RXEN_CMD 0xDE #define FW_DISABLE_RXEN_LEN 0x1 #define FW_PHY_MGMT_REQ_CMD 0x20 +#define FW_INT_PHY_REQ_CMD 0xB +#define FW_INT_PHY_REQ_LEN 10 +#define FW_INT_PHY_REQ_READ 0 +#define FW_INT_PHY_REQ_WRITE 1 + /* Host Interface Command Structures */ struct ixgbe_hic_hdr { @@ -2975,6 +2987,21 @@ struct ixgbe_hic_disable_rxen { u16 pad3; }; +struct ixgbe_hic_internal_phy_req { + struct ixgbe_hic_hdr hdr; + u8 port_number; + u8 command_type; + u16 address; + u16 rsv1; + u32 write_data; + u16 pad; +}; + +struct ixgbe_hic_internal_phy_resp { + struct ixgbe_hic_hdr hdr; + u32 read_data; +}; + /* Transmit Descriptor - Legacy */ struct ixgbe_legacy_tx_desc { @@ -3310,6 +3337,7 @@ union ixgbe_atr_hash_dword { IXGBE_CAT(SRAMREL, m), \ IXGBE_CAT(FACTPS, m), \ IXGBE_CAT(SWSM, m), \ + IXGBE_CAT(SWFW_SYNC, m), \ IXGBE_CAT(FWSM, m), \ IXGBE_CAT(SDP0_GPIEN, m), \ IXGBE_CAT(SDP1_GPIEN, m), \ @@ -3792,6 +3820,7 @@ struct ixgbe_mac_info { u8 flags; struct ixgbe_dmac_config dmac_config; bool set_lben; + u32 max_link_up_time; }; struct ixgbe_phy_info { @@ -3806,6 +3835,7 @@ struct ixgbe_phy_info { u32 phy_semaphore_mask; bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; + ixgbe_link_speed speeds_supported; enum ixgbe_smart_speed smart_speed; bool smart_speed_active; bool multispeed_fiber; @@ -3918,15 +3948,15 @@ struct ixgbe_hw { #define IXGBE_FUSES0_300MHZ (1 << 5) #define IXGBE_FUSES0_REV1 (1 << 6) -#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P == 0) ? (0x4010) : (0x8010)) -#define IXGBE_KRM_LINK_CTRL_1(P) ((P == 0) ? (0x420C) : (0x820C)) -#define IXGBE_KRM_AN_CNTL_1(P) ((P == 0) ? (0x422C) : (0x822C)) -#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P == 0) ? (0x4634) : (0x8634)) -#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P == 0) ? (0x4638) : (0x8638)) -#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P == 0) ? (0x4B00) : (0x8B00)) -#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P == 0) ? (0x4E00) : (0x8E00)) -#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P == 0) ? (0x5520) : (0x9520)) -#define IXGBE_KRM_RX_ANA_CTL(P) ((P == 0) ? (0x5A00) : (0x9A00)) +#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) +#define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) +#define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) +#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) +#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) +#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) +#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00) +#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520) +#define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00) #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B (1 << 9) #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS (1 << 11) @@ -3960,15 +3990,6 @@ struct ixgbe_hw { #define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN (1 << 3) #define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN (1 << 31) -#define IXGBE_KX4_LINK_CNTL_1 0x4C -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX (1 << 16) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 (1 << 17) -#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX (1 << 24) -#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4 (1 << 25) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE (1 << 29) -#define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP (1 << 30) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART (1 << 31) - #define IXGBE_SB_IOSF_INDIRECT_CTRL 0x00011144 #define IXGBE_SB_IOSF_INDIRECT_DATA 0x00011148 @@ -3985,8 +4006,6 @@ struct ixgbe_hw { #define IXGBE_SB_IOSF_CTRL_BUSY_SHIFT 31 #define IXGBE_SB_IOSF_CTRL_BUSY (1 << IXGBE_SB_IOSF_CTRL_BUSY_SHIFT) #define IXGBE_SB_IOSF_TARGET_KR_PHY 0 -#define IXGBE_SB_IOSF_TARGET_KX4_PHY 1 -#define IXGBE_SB_IOSF_TARGET_KX4_PCS 2 #define IXGBE_NW_MNG_IF_SEL 0x00011178 #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24) diff --git a/sys/dev/ixgbe/ixgbe_vf.c b/sys/dev/ixgbe/ixgbe_vf.c index a00b8be..2ce4d32 100644 --- a/sys/dev/ixgbe/ixgbe_vf.c +++ b/sys/dev/ixgbe/ixgbe_vf.c @@ -225,8 +225,6 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw) if (ret_val) return ret_val; - msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; - if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) && msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK)) return IXGBE_ERR_INVALID_MAC_ADDR; diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c index ddf0674..96478ea 100644 --- a/sys/dev/ixgbe/ixgbe_x540.c +++ b/sys/dev/ixgbe/ixgbe_x540.c @@ -138,8 +138,8 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw) * ARC supported; valid only if manageability features are * enabled. */ - mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & - IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE; + mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)) + & IXGBE_FWSM_MODE_MASK); hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; @@ -356,7 +356,7 @@ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) eeprom->semaphore_delay = 10; eeprom->type = ixgbe_flash; - eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + @@ -681,8 +681,8 @@ s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) goto out; } - flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP; - IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); + flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP; + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup); status = ixgbe_poll_flash_update_done_X540(hw); if (status == IXGBE_SUCCESS) @@ -691,11 +691,11 @@ s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) DEBUGOUT("Flash update time out\n"); if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) { - flup = IXGBE_READ_REG(hw, IXGBE_EEC); + flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); if (flup & IXGBE_EEC_SEC1VAL) { flup |= IXGBE_EEC_FLUP; - IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); + IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup); } status = ixgbe_poll_flash_update_done_X540(hw); @@ -724,7 +724,7 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_poll_flash_update_done_X540"); for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) { - reg = IXGBE_READ_REG(hw, IXGBE_EEC); + reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); if (reg & IXGBE_EEC_FLUDONE) { status = IXGBE_SUCCESS; break; @@ -775,10 +775,11 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) if (ixgbe_get_swfw_sync_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; - swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw)); if (!(swfw_sync & (fwmask | swmask | hwmask))) { swfw_sync |= swmask; - IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), + swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); return IXGBE_SUCCESS; @@ -805,10 +806,10 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) */ if (ixgbe_get_swfw_sync_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; - swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw)); if (swfw_sync & (fwmask | hwmask)) { swfw_sync |= swmask; - IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); return IXGBE_SUCCESS; @@ -852,9 +853,9 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) swmask |= mask & IXGBE_GSSR_I2C_MASK; ixgbe_get_swfw_sync_semaphore(hw); - swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw)); swfw_sync &= ~swmask; - IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); @@ -881,7 +882,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); if (!(swsm & IXGBE_SWSM_SMBI)) { status = IXGBE_SUCCESS; break; @@ -892,7 +893,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) /* Now get the semaphore between SW/FW through the REGSMP bit */ if (status == IXGBE_SUCCESS) { for (i = 0; i < timeout; i++) { - swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw)); if (!(swsm & IXGBE_SWFW_REGSMP)) break; @@ -932,13 +933,13 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */ - swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw)); swsm &= ~IXGBE_SWFW_REGSMP; - IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm); + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm); - swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); swsm &= ~IXGBE_SWSM_SMBI; - IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); + IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); IXGBE_WRITE_FLUSH(hw); } diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c index 65daa17..d62035d 100644 --- a/sys/dev/ixgbe/ixgbe_x550.c +++ b/sys/dev/ixgbe/ixgbe_x550.c @@ -115,119 +115,6 @@ static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) } /** - * ixgbe_get_cs4227_status - Return CS4227 status - * @hw: pointer to hardware structure - * - * Returns error if CS4227 not successfully initialized - **/ -static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw) -{ - s32 status; - u16 value = 0; - u16 reg_slice, reg_val; - u8 retry; - - for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) { - status = ixgbe_read_cs4227(hw, IXGBE_CS4227_GLOBAL_ID_LSB, - &value); - if (status != IXGBE_SUCCESS) - return status; - if (value == IXGBE_CS4227_GLOBAL_ID_VALUE) - break; - msec_delay(IXGBE_CS4227_CHECK_DELAY); - } - if (value != IXGBE_CS4227_GLOBAL_ID_VALUE) - return IXGBE_ERR_PHY; - - status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); - if (status != IXGBE_SUCCESS) - return status; - - /* If this is the first time after power-on, check the ucode. - * Otherwise, this will disrupt link on all ports. Because we - * can only do this the first time, we must check all ports, - * not just our own. - */ - if (value != IXGBE_CS4227_SCRATCH_VALUE) { - reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB; - reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; - status = ixgbe_write_cs4227(hw, reg_slice, - reg_val); - if (status != IXGBE_SUCCESS) - return status; - - reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB; - reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; - status = ixgbe_write_cs4227(hw, reg_slice, - reg_val); - if (status != IXGBE_SUCCESS) - return status; - - reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12); - reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - status = ixgbe_write_cs4227(hw, reg_slice, - reg_val); - if (status != IXGBE_SUCCESS) - return status; - - reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12); - reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - status = ixgbe_write_cs4227(hw, reg_slice, - reg_val); - if (status != IXGBE_SUCCESS) - return status; - - msec_delay(10); - } - - /* Verify that the ucode is operational on all ports. */ - reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB; - reg_val = 0xFFFF; - status = ixgbe_read_cs4227(hw, reg_slice, ®_val); - if (status != IXGBE_SUCCESS) - return status; - if (reg_val != 0) - return IXGBE_ERR_PHY; - - reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB; - reg_val = 0xFFFF; - status = ixgbe_read_cs4227(hw, reg_slice, ®_val); - if (status != IXGBE_SUCCESS) - return status; - if (reg_val != 0) - return IXGBE_ERR_PHY; - - reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12); - reg_val = 0xFFFF; - status = ixgbe_read_cs4227(hw, reg_slice, ®_val); - if (status != IXGBE_SUCCESS) - return status; - if (reg_val != 0) - return IXGBE_ERR_PHY; - - reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12); - reg_val = 0xFFFF; - status = ixgbe_read_cs4227(hw, reg_slice, ®_val); - if (status != IXGBE_SUCCESS) - return status; - if (reg_val != 0) - return IXGBE_ERR_PHY; - - /* Set scratch for next time. */ - status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, - IXGBE_CS4227_SCRATCH_VALUE); - if (status != IXGBE_SUCCESS) - return status; - status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); - if (status != IXGBE_SUCCESS) - return status; - if (value != IXGBE_CS4227_SCRATCH_VALUE) - return IXGBE_ERR_PHY; - - return IXGBE_SUCCESS; -} - -/** * ixgbe_read_pe - Read register from port expander * @hw: pointer to hardware structure * @reg: register number to read @@ -269,13 +156,17 @@ static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) * ixgbe_reset_cs4227 - Reset CS4227 using port expander * @hw: pointer to hardware structure * + * This function assumes that the caller has acquired the proper semaphore. * Returns error code **/ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) { s32 status; + u32 retry; + u16 value; u8 reg; + /* Trigger hard reset. */ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); if (status != IXGBE_SUCCESS) return status; @@ -310,7 +201,29 @@ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) if (status != IXGBE_SUCCESS) return status; + /* Wait for the reset to complete. */ msec_delay(IXGBE_CS4227_RESET_DELAY); + for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, + &value); + if (status == IXGBE_SUCCESS && + value == IXGBE_CS4227_EEPROM_LOAD_OK) + break; + msec_delay(IXGBE_CS4227_CHECK_DELAY); + } + if (retry == IXGBE_CS4227_RETRIES) { + ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, + "CS4227 reset did not complete."); + return IXGBE_ERR_PHY; + } + + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); + if (status != IXGBE_SUCCESS || + !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { + ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, + "CS4227 EEPROM did not load successfully."); + return IXGBE_ERR_PHY; + } return IXGBE_SUCCESS; } @@ -321,29 +234,75 @@ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) **/ static void ixgbe_check_cs4227(struct ixgbe_hw *hw) { + s32 status = IXGBE_SUCCESS; u32 swfw_mask = hw->phy.phy_semaphore_mask; - s32 status; + u16 value = 0; u8 retry; for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); if (status != IXGBE_SUCCESS) { ERROR_REPORT2(IXGBE_ERROR_CAUTION, - "semaphore failed with %d\n", status); - return; + "semaphore failed with %d", status); + msec_delay(IXGBE_CS4227_CHECK_DELAY); + continue; } - status = ixgbe_get_cs4227_status(hw); - if (status == IXGBE_SUCCESS) { - hw->mac.ops.release_swfw_sync(hw, swfw_mask); - msec_delay(hw->eeprom.semaphore_delay); + + /* Get status of reset flow. */ + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); + + if (status == IXGBE_SUCCESS && + value == IXGBE_CS4227_RESET_COMPLETE) + goto out; + + if (status != IXGBE_SUCCESS || + value != IXGBE_CS4227_RESET_PENDING) + break; + + /* Reset is pending. Wait and check again. */ + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msec_delay(IXGBE_CS4227_CHECK_DELAY); + } + + /* If still pending, assume other instance failed. */ + if (retry == IXGBE_CS4227_RETRIES) { + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status != IXGBE_SUCCESS) { + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "semaphore failed with %d", status); return; } - ixgbe_reset_cs4227(hw); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); - msec_delay(hw->eeprom.semaphore_delay); } - ERROR_REPORT2(IXGBE_ERROR_CAUTION, - "Unable to initialize CS4227, err=%d\n", status); + + /* Reset the CS4227. */ + status = ixgbe_reset_cs4227(hw); + if (status != IXGBE_SUCCESS) { + ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, + "CS4227 reset failed: %d", status); + goto out; + } + + /* Reset takes so long, temporarily release semaphore in case the + * other driver instance is waiting for the reset indication. + */ + ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, + IXGBE_CS4227_RESET_PENDING); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msec_delay(10); + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status != IXGBE_SUCCESS) { + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "semaphore failed with %d", status); + return; + } + + /* Record completion for next time. */ + status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, + IXGBE_CS4227_RESET_COMPLETE); + +out: + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msec_delay(hw->eeprom.semaphore_delay); } /** @@ -452,8 +411,11 @@ s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw) hw->bus.type = ixgbe_bus_type_internal; mac->ops.get_bus_info = ixgbe_get_bus_info_X550em; - mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; - mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; + if (hw->mac.type == ixgbe_mac_X550EM_x) { + mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; + mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; + } + mac->ops.get_media_type = ixgbe_get_media_type_X550em; mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em; mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em; @@ -679,7 +641,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee) if (enable_eee) { eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); - if (hw->device_id == IXGBE_DEV_ID_X550T) { + if (hw->mac.type == ixgbe_mac_X550) { /* Advertise EEE capability */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg); @@ -717,7 +679,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee) } else { eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); - if (hw->device_id == IXGBE_DEV_ID_X550T) { + if (hw->mac.type == ixgbe_mac_X550) { /* Disable advertised EEE capability */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg); @@ -816,7 +778,7 @@ void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, **/ static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) { - u32 i, command; + u32 i, command = 0; /* Check every 10 usec to see if the address cycle completed. * The SB IOSF BUSY bit will clear when the operation is @@ -1444,8 +1406,6 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, return status; reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; - reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | - IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); @@ -1492,14 +1452,10 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) * to determine internal PHY mode. */ phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); - - /* If internal PHY mode is KR, then initialize KR link */ if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { speed = IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; - ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); } - phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; } @@ -1516,7 +1472,7 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) /* Set functions pointers based on phy type */ switch (hw->phy.type) { case ixgbe_phy_x550em_kx4: - phy->ops.setup_link = ixgbe_setup_kx4_x550em; + phy->ops.setup_link = NULL; phy->ops.read_reg = ixgbe_read_phy_reg_x550em; phy->ops.write_reg = ixgbe_write_phy_reg_x550em; break; @@ -1543,7 +1499,11 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); } - phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; + /* setup SW LPLU only for first revision */ + if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, + IXGBE_FUSES0_GROUP(0)))) + phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; + phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; phy->ops.reset = ixgbe_reset_phy_t_X550em; break; @@ -1580,9 +1540,14 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); - /* PHY ops must be identified and initialized prior to reset */ + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { + /* Config MDIO clock speed before the first MDIO PHY access */ + hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); + hlreg0 &= ~IXGBE_HLREG0_MDCSPD; + IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); + } - /* Identify PHY and related function pointers */ + /* PHY ops must be identified and initialized prior to reset */ status = hw->phy.ops.init(hw); if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) @@ -1659,13 +1624,6 @@ mac_reset_top: hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { - /* Config MDIO clock speed. */ - hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); - hlreg0 &= ~IXGBE_HLREG0_MDCSPD; - IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); - } - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) ixgbe_setup_mux_ctl(hw); @@ -1727,43 +1685,6 @@ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) } /** - * ixgbe_setup_kx4_x550em - Configure the KX4 PHY. - * @hw: pointer to hardware structure - * - * Configures the integrated KX4 PHY. - **/ -s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) -{ - s32 status; - u32 reg_val; - - status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, - IXGBE_SB_IOSF_TARGET_KX4_PCS, ®_val); - if (status) - return status; - - reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | - IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); - - reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; - - /* Advertise 10G support. */ - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) - reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; - - /* Advertise 1G support. */ - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) - reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; - - /* Restart auto-negotiation. */ - reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; - status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, - IXGBE_SB_IOSF_TARGET_KX4_PCS, reg_val); - - return status; -} - -/** * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP * @hw: pointer to hardware structure * @@ -1791,38 +1712,53 @@ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, if (ret_val != IXGBE_SUCCESS) return ret_val; - /* Configure CS4227 for LINE connection rate then type. */ - reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); - reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000; - ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, - reg_val); - - reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); - if (setup_linear) - reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; - else - reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, - reg_val); - - /* Configure CS4227 for HOST connection rate then type. */ - reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); - reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000; - ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, - reg_val); - - reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); - if (setup_linear) - reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; - else + if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { + /* Configure CS4227 LINE side to 10G SR. */ + reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + + (hw->bus.lan_id << 12); + reg_val = IXGBE_CS4227_SPEED_10G; + ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, + reg_val); + + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + + (hw->bus.lan_id << 12); reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, - reg_val); + ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, + reg_val); + + /* Configure CS4227 for HOST connection rate then type. */ + reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + + (hw->bus.lan_id << 12); + reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? + IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; + ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, + reg_val); + + reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + + (hw->bus.lan_id << 12); + if (setup_linear) + reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; + else + reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; + ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, + reg_val); - /* If internal link mode is XFI, then setup XFI internal link. */ - if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) + /* Setup XFI internal link. */ ret_val = ixgbe_setup_ixfi_x550em(hw, &speed); - + } else { + /* Configure internal PHY for KR/KX. */ + ixgbe_setup_kr_speed_x550em(hw, speed); + + /* Configure CS4227 LINE side to proper mode. */ + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + + (hw->bus.lan_id << 12); + if (setup_linear) + reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; + else + reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; + ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, + reg_val); + } return ret_val; } @@ -2743,6 +2679,10 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) u32 save_autoneg; bool link_up; + /* SW LPLU not required on later HW revisions. */ + if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))) + return IXGBE_SUCCESS; + /* If blocked by MNG FW, then don't restart AN */ if (ixgbe_check_reset_blocked(hw)) return IXGBE_SUCCESS; @@ -2924,7 +2864,7 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw) goto out; } - if (hw->phy.media_type == ixgbe_media_type_backplane) { + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { ret_val = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); @@ -2940,9 +2880,8 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw) IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); - /* Not all devices fully support AN. */ - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) - hw->fc.disable_fc_autoneg = TRUE; + /* This device does not fully support AN. */ + hw->fc.disable_fc_autoneg = TRUE; } out: diff --git a/sys/dev/ixgbe/ixgbe_x550.h b/sys/dev/ixgbe/ixgbe_x550.h index 8a544ec..b590bb7 100644 --- a/sys/dev/ixgbe/ixgbe_x550.h +++ b/sys/dev/ixgbe/ixgbe_x550.h @@ -69,7 +69,7 @@ void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 data); s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, - u32 device_type, u32 *data); + u32 device_type, u32 *data); void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw); void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw); void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap); @@ -82,7 +82,6 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw); s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw); -s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw); s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw); diff --git a/sys/modules/ix/Makefile b/sys/modules/ix/Makefile index 4b57379..2d567e4 100644 --- a/sys/modules/ix/Makefile +++ b/sys/modules/ix/Makefile @@ -5,7 +5,7 @@ KMOD = if_ix SRCS = device_if.h bus_if.h pci_if.h SRCS += opt_inet.h opt_inet6.h -SRCS += if_ix.c ix_txrx.c +SRCS += if_ix.c ix_txrx.c ixgbe_osdep.c # Shared source SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c diff --git a/sys/modules/ixv/Makefile b/sys/modules/ixv/Makefile index fd428a0..9546a3c 100644 --- a/sys/modules/ixv/Makefile +++ b/sys/modules/ixv/Makefile @@ -5,7 +5,7 @@ KMOD = if_ixv SRCS = device_if.h bus_if.h pci_if.h SRCS += opt_inet.h opt_inet6.h -SRCS += if_ixv.c ix_txrx.c +SRCS += if_ixv.c ix_txrx.c ixgbe_osdep.c # Shared source SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c -- cgit v1.1 From 0c758e8c2736b450efa6576a9b55eaac38468d8c Mon Sep 17 00:00:00 2001 From: sbruno Date: Thu, 11 Feb 2016 16:35:16 +0000 Subject: Revert sysctl description change introduced in r295008 to correctly reflect the maximum number of queues supported (8) by this driver. Submitted by: jwd Reviewed by: erj Approved by: re (gjb) Sponsored by: Intel Corporation and Limelight Networks --- sys/dev/ixgbe/if_ix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 111e731..acdef4d 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -320,7 +320,8 @@ SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0, static int ixgbe_num_queues = 0; TUNABLE_INT("hw.ix.num_queues", &ixgbe_num_queues); SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0, - "Number of queues to configure, 0 indicates autoconfigure"); + "Number of queues to configure up to a mximum of 8," + "0 indicates autoconfigure"); /* ** Number of TX descriptors per ring, -- cgit v1.1 From a174c79878d5e765a8247707098daaf3b966328f Mon Sep 17 00:00:00 2001 From: arybchik Date: Thu, 11 Feb 2016 16:39:30 +0000 Subject: MFC r295467 sfxge: implement SIOCGI2C to read information from phy modules The IOCTL is used by 'ifconfig -v' to show SFP+/QSFP+ information including inventory information and dianostics (temperature, light levels, voltage etc). Reviewed by: gnn,melifaro Approved by: re (gjb) Sponsored by: Solarflare Communications, Inc. --- sys/dev/sfxge/common/efx.h | 8 ++ sys/dev/sfxge/common/efx_mcdi.c | 212 ++++++++++++++++++++++++++++++++++++++++ sys/dev/sfxge/common/efx_mcdi.h | 8 ++ sys/dev/sfxge/common/efx_phy.c | 32 ++++++ sys/dev/sfxge/sfxge.c | 24 +++++ 5 files changed, 284 insertions(+) diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index ce70546..14374cf 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -879,6 +879,14 @@ efx_phy_media_type_get( __in efx_nic_t *enp, __out efx_phy_media_type_t *typep); +extern efx_rc_t +efx_phy_module_get_info( + __in efx_nic_t *enp, + __in uint8_t dev_addr, + __in uint8_t offset, + __in uint8_t len, + __out_bcount(len) uint8_t *data); + #if EFSYS_OPT_PHY_STATS /* START MKCONFIG GENERATED PhyHeaderStatsBlock 30ed56ad501f8e36 */ diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index 9f7a9ff..bb9d9cf 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -2078,5 +2078,217 @@ fail1: return (rc); } +/* + * Size of media information page in accordance with SFF-8472 and SFF-8436. + * It is used in MCDI interface as well. + */ +#define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80 + +static __checkReturn efx_rc_t +efx_mcdi_get_phy_media_info( + __in efx_nic_t *enp, + __in uint32_t mcdi_page, + __in uint8_t offset, + __in uint8_t len, + __out_bcount(len) uint8_t *data) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN, + MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN( + EFX_PHY_MEDIA_INFO_PAGE_SIZE))]; + efx_rc_t rc; + + EFSYS_ASSERT((uint32_t)offset + len <= EFX_PHY_MEDIA_INFO_PAGE_SIZE); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_GET_PHY_MEDIA_INFO; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = + MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE); + + MCDI_IN_SET_DWORD(req, GET_PHY_MEDIA_INFO_IN_PAGE, mcdi_page); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used != + MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE)) { + rc = EMSGSIZE; + goto fail2; + } + + if (MCDI_OUT_DWORD(req, GET_PHY_MEDIA_INFO_OUT_DATALEN) != + EFX_PHY_MEDIA_INFO_PAGE_SIZE) { + rc = EIO; + goto fail3; + } + + memcpy(data, + MCDI_OUT2(req, uint8_t, GET_PHY_MEDIA_INFO_OUT_DATA) + offset, + len); + + return (0); + +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +/* + * 2-wire device address of the base information in accordance with SFF-8472 + * Diagnostic Monitoring Interface for Optical Transceivers section + * 4 Memory Organization. + */ +#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE 0xA0 + +/* + * 2-wire device address of the digital diagnostics monitoring interface + * in accordance with SFF-8472 Diagnostic Monitoring Interface for Optical + * Transceivers section 4 Memory Organization. + */ +#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM 0xA2 + +/* + * Hard wired 2-wire device address for QSFP+ in accordance with SFF-8436 + * QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER section 7.4 Device Addressing and + * Operation. + */ +#define EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP 0xA0 + + __checkReturn efx_rc_t +efx_mcdi_phy_module_get_info( + __in efx_nic_t *enp, + __in uint8_t dev_addr, + __in uint8_t offset, + __in uint8_t len, + __out_bcount(len) uint8_t *data) +{ + efx_port_t *epp = &(enp->en_port); + efx_rc_t rc; + uint32_t mcdi_lower_page; + uint32_t mcdi_upper_page; + + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); + + /* + * Map device address to MC_CMD_GET_PHY_MEDIA_INFO pages. + * Offset plus length interface allows to access page 0 only. + * I.e. non-zero upper pages are not accessible. + * See SFF-8472 section 4 Memory Organization and SFF-8436 section 7.6 + * QSFP+ Memory Map for details on how information is structured + * and accessible. + */ + switch (epp->ep_fixed_port_type) { + case EFX_PHY_MEDIA_SFP_PLUS: + /* + * In accordance with SFF-8472 Diagnostic Monitoring + * Interface for Optical Transceivers section 4 Memory + * Organization two 2-wire addresses are defined. + */ + switch (dev_addr) { + /* Base information */ + case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE: + /* + * MCDI page 0 should be used to access lower + * page 0 (0x00 - 0x7f) at the device address 0xA0. + */ + mcdi_lower_page = 0; + /* + * MCDI page 1 should be used to access upper + * page 0 (0x80 - 0xff) at the device address 0xA0. + */ + mcdi_upper_page = 1; + break; + /* Diagnostics */ + case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM: + /* + * MCDI page 2 should be used to access lower + * page 0 (0x00 - 0x7f) at the device address 0xA2. + */ + mcdi_lower_page = 2; + /* + * MCDI page 3 should be used to access upper + * page 0 (0x80 - 0xff) at the device address 0xA2. + */ + mcdi_upper_page = 3; + break; + default: + rc = ENOTSUP; + goto fail1; + } + break; + case EFX_PHY_MEDIA_QSFP_PLUS: + switch (dev_addr) { + case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP: + /* + * MCDI page -1 should be used to access lower page 0 + * (0x00 - 0x7f). + */ + mcdi_lower_page = (uint32_t)-1; + /* + * MCDI page 0 should be used to access upper page 0 + * (0x80h - 0xff). + */ + mcdi_upper_page = 0; + break; + default: + rc = ENOTSUP; + goto fail1; + } + break; + default: + rc = ENOTSUP; + goto fail1; + } + + if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) { + uint8_t read_len = + MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset); + + rc = efx_mcdi_get_phy_media_info(enp, + mcdi_lower_page, offset, read_len, data); + if (rc != 0) + goto fail2; + + data += read_len; + len -= read_len; + + offset = 0; + } else { + offset -= EFX_PHY_MEDIA_INFO_PAGE_SIZE; + } + + if (len > 0) { + EFSYS_ASSERT3U(len, <=, EFX_PHY_MEDIA_INFO_PAGE_SIZE); + EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE); + + rc = efx_mcdi_get_phy_media_info(enp, + mcdi_upper_page, offset, len, data); + if (rc != 0) + goto fail3; + } + + return (0); + +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} #endif /* EFSYS_OPT_MCDI */ diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h index dd1d76e..a96bd77 100644 --- a/sys/dev/sfxge/common/efx_mcdi.h +++ b/sys/dev/sfxge/common/efx_mcdi.h @@ -228,6 +228,14 @@ efx_mcdi_get_loopback_modes( __in efx_nic_t *enp); #endif /* EFSYS_OPT_LOOPBACK */ +extern __checkReturn efx_rc_t +efx_mcdi_phy_module_get_info( + __in efx_nic_t *enp, + __in uint8_t dev_addr, + __in uint8_t offset, + __in uint8_t len, + __out_bcount(len) uint8_t *data); + #define MCDI_IN(_emr, _type, _ofst) \ ((_type *)((_emr).emr_in_buf + (_ofst))) diff --git a/sys/dev/sfxge/common/efx_phy.c b/sys/dev/sfxge/common/efx_phy.c index 51e1ccb..3fd4e08 100644 --- a/sys/dev/sfxge/common/efx_phy.c +++ b/sys/dev/sfxge/common/efx_phy.c @@ -560,6 +560,38 @@ efx_phy_media_type_get( *typep = epp->ep_fixed_port_type; } + __checkReturn efx_rc_t +efx_phy_module_get_info( + __in efx_nic_t *enp, + __in uint8_t dev_addr, + __in uint8_t offset, + __in uint8_t len, + __out_bcount(len) uint8_t *data) +{ + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT(data != NULL); + + if ((uint32_t)offset + len > 0xff) { + rc = EINVAL; + goto fail1; + } + + if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr, + offset, len, data)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + #if EFSYS_OPT_PHY_STATS #if EFSYS_OPT_NAMES diff --git a/sys/dev/sfxge/sfxge.c b/sys/dev/sfxge/sfxge.c index b82fba4..b112a1e 100644 --- a/sys/dev/sfxge/sfxge.c +++ b/sys/dev/sfxge/sfxge.c @@ -507,6 +507,30 @@ sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->media, command); break; +#ifdef SIOCGI2C + case SIOCGI2C: + { + struct ifi2creq i2c; + + error = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); + if (error != 0) + break; + + if (i2c.len > sizeof(i2c.data)) { + error = EINVAL; + break; + } + + SFXGE_ADAPTER_LOCK(sc); + error = efx_phy_module_get_info(sc->enp, i2c.dev_addr, + i2c.offset, i2c.len, + &i2c.data[0]); + SFXGE_ADAPTER_UNLOCK(sc); + if (error == 0) + error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); + break; + } +#endif case SIOCGPRIVATE_0: error = priv_check(curthread, PRIV_DRIVER); if (error != 0) -- cgit v1.1 From fd560f49734672a8d1c7f809460d6a57c5f396c8 Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 16:54:23 +0000 Subject: MFC r294734, r295093 & r295094 ixgbe fixes MFC r294734 Fix ixgbe compliation with DBG 1 MFC r295093 Configure ixgbe phy & gbic power MFC r295094 Fix ixgbe flow control autoneg reporting Approved by: re (marius) Sponsored by: Multiplay --- sys/dev/ixgbe/if_ix.c | 12 ++++++++++++ sys/dev/ixgbe/ixgbe_common.c | 5 ++++- sys/dev/ixgbe/ixgbe_osdep.h | 29 ++++++++++++++++++++++++++--- sys/dev/ixgbe/ixgbe_phy.c | 3 +++ sys/dev/ixgbe/ixgbe_type.h | 3 +++ sys/dev/ixgbe/ixgbe_x540.c | 3 +-- sys/dev/ixgbe/ixgbe_x550.c | 19 +++++++++++++++++-- 7 files changed, 66 insertions(+), 8 deletions(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index acdef4d..4386f5d 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -582,6 +582,12 @@ ixgbe_attach(device_t dev) if (error) goto err_late; + /* Enable the optics for 82599 SFP+ fiber */ + ixgbe_enable_tx_laser(hw); + + /* Enable power to the phy. */ + ixgbe_set_phy_power(hw, TRUE); + /* Setup OS specific network interface */ if (ixgbe_setup_interface(dev, adapter) != 0) goto err_late; @@ -1250,6 +1256,9 @@ ixgbe_init_locked(struct adapter *adapter) device_printf(dev, "Error setting up EEE: %d\n", err); } + /* Enable power to the phy. */ + ixgbe_set_phy_power(hw, TRUE); + /* Config/Enable Link */ ixgbe_config_link(adapter); @@ -3970,6 +3979,9 @@ ixgbe_setup_low_power_mode(struct adapter *adapter) mtx_assert(&adapter->core_mtx, MA_OWNED); + if (!hw->wol_enabled) + ixgbe_set_phy_power(hw, FALSE); + /* Limit power management flow to X550EM baseT */ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && hw->phy.ops.enter_lplu) { diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index d67e680..feb74f6 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -199,9 +199,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) break; } - ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, + if (!supported) { + ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Device %x does not support flow control autoneg", hw->device_id); + } + return supported; } diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index b767e73..79d1166 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -57,6 +57,15 @@ #define ASSERT(x) if(!(x)) panic("IXGBE: x") #define EWARN(H, W, S) printf(W) +enum { + IXGBE_ERROR_SOFTWARE, + IXGBE_ERROR_POLLING, + IXGBE_ERROR_INVALID_STATE, + IXGBE_ERROR_UNSUPPORTED, + IXGBE_ERROR_ARGUMENT, + IXGBE_ERROR_CAUTION, +}; + /* The happy-fun DELAY macro is defined in /usr/src/sys/i386/include/clock.h */ #define usec_delay(x) DELAY(x) #define msec_delay(x) DELAY(1000*(x)) @@ -73,9 +82,23 @@ #define DEBUGOUT5(S,A,B,C,D,E) printf(S "\n",A,B,C,D,E) #define DEBUGOUT6(S,A,B,C,D,E,F) printf(S "\n",A,B,C,D,E,F) #define DEBUGOUT7(S,A,B,C,D,E,F,G) printf(S "\n",A,B,C,D,E,F,G) - #define ERROR_REPORT1(S,A) printf(S "\n",A) - #define ERROR_REPORT2(S,A,B) printf(S "\n",A,B) - #define ERROR_REPORT3(S,A,B,C) printf(S "\n",A,B,C) + #define ERROR_REPORT1 ERROR_REPORT + #define ERROR_REPORT2 ERROR_REPORT + #define ERROR_REPORT3 ERROR_REPORT + #define ERROR_REPORT(level, format, arg...) do { \ + switch (level) { \ + case IXGBE_ERROR_SOFTWARE: \ + case IXGBE_ERROR_CAUTION: \ + case IXGBE_ERROR_POLLING: \ + case IXGBE_ERROR_INVALID_STATE: \ + case IXGBE_ERROR_UNSUPPORTED: \ + case IXGBE_ERROR_ARGUMENT: \ + device_printf(ixgbe_dev_from_hw(hw), format, ## arg); \ + break; \ + default: \ + break; \ + } \ + } while (0) #else #define DEBUGOUT(S) #define DEBUGOUT1(S,A) diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 6bff172..f5d22b2 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -2734,6 +2734,9 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) u32 status; u16 reg; + if (!on && ixgbe_mng_present(hw)) + return 0; + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index d76cde2..da03f79 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -1479,7 +1479,10 @@ struct ixgbe_dmac_config { #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK 0xFF01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG 0xFC01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_ALARM_1 0xCC00 /* Global alarm 1 */ +#define IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT 0x0010 /* device fault */ #define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL 0x4000 /* high temp failure */ +#define IXGBE_MDIO_GLOBAL_FAULT_MSG 0xC850 /* Global Fault Message */ +#define IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP 0x8007 /* high temp failure */ #define IXGBE_MDIO_GLOBAL_INT_MASK 0xD400 /* Global int mask */ #define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN 0x1000 /* autoneg vendor alarm int enable */ #define IXGBE_MDIO_GLOBAL_ALARM_1_INT 0x4 /* int in Global alarm 1 */ diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c index 96478ea..fd52ebe 100644 --- a/sys/dev/ixgbe/ixgbe_x540.c +++ b/sys/dev/ixgbe/ixgbe_x540.c @@ -82,8 +82,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw) /* PHY */ phy->ops.init = ixgbe_init_phy_ops_generic; phy->ops.reset = NULL; - if (!ixgbe_mng_present(hw)) - phy->ops.set_phy_power = ixgbe_set_copper_phy_power; + phy->ops.set_phy_power = ixgbe_set_copper_phy_power; /* MAC */ mac->ops.reset_hw = ixgbe_reset_hw_X540; diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c index d62035d..1199d38 100644 --- a/sys/dev/ixgbe/ixgbe_x550.c +++ b/sys/dev/ixgbe/ixgbe_x550.c @@ -965,7 +965,7 @@ void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf) num_qs = 4; /* 32 VFs / pools */ bitmask = 0x0000000F; break; - default: /* 64 VFs / pools */ + default: /* 64 VFs / pools */ num_qs = 2; bitmask = 0x00000003; break; @@ -1264,7 +1264,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) IXGBE_MDIO_GLOBAL_ALARM_1_INT))) return status; - /* High temperature failure alarm triggered */ + /* Global alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); @@ -1277,6 +1277,21 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* power down the PHY in case the PHY FW didn't already */ ixgbe_set_copper_phy_power(hw, FALSE); return IXGBE_ERR_OVERTEMP; + } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { + /* device fault alarm triggered */ + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + ®); + + if (status != IXGBE_SUCCESS) + return status; + + /* if device fault was due to high temp alarm handle and exit */ + if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { + /* power down the PHY in case the PHY FW didn't */ + ixgbe_set_copper_phy_power(hw, FALSE); + return IXGBE_ERR_OVERTEMP; + } } /* Vendor alarm 2 triggered */ -- cgit v1.1 From 1f678f8c8fa0e9ab39ec82b54e92b43041f7948f Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 17:31:17 +0000 Subject: MFC r295356 (Partial) Fix EFI platform build failures on arm.armeb Approved by: re (marius) Sponsored by: Multiplay --- sys/boot/common/load_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 6a88e39..e352ef7 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -856,7 +856,7 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); if (error == EOPNOTSUPP) { md.md_cval += ef->off; - md.md_data = (void *)((uintptr_t)md.md_data + ef->off); + md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off); } else if (error != 0) return (error); #endif -- cgit v1.1 From dc1aed8cd3252c89593a3505387a2d5e80c15b3f Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 17:34:26 +0000 Subject: MFC r294795 ixgbe sysctl hardware defaults Approved by: re (marius) Sponsored by: Multiplay --- sys/dev/ixgbe/if_ix.c | 134 ++++++++++++++++++++++++++++++++------------------ sys/dev/ixgbe/ixgbe.h | 1 + 2 files changed, 86 insertions(+), 49 deletions(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 4386f5d..65e868a 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -165,12 +165,14 @@ static void ixgbe_unregister_vlan(void *, struct ifnet *, u16); static void ixgbe_add_device_sysctls(struct adapter *); static void ixgbe_add_hw_stats(struct adapter *); +static int ixgbe_set_flowcntl(struct adapter *, int); +static int ixgbe_set_advertise(struct adapter *, int); /* Sysctl handlers */ static void ixgbe_set_sysctl_value(struct adapter *, const char *, const char *, int *, int); -static int ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS); -static int ixgbe_set_advertise(SYSCTL_HANDLER_ARGS); +static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); +static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); @@ -293,6 +295,16 @@ SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN, "Maximum number of sent packets to process at a time," "-1 means unlimited"); +/* Flow control setting, default to full */ +static int ixgbe_flow_control = ixgbe_fc_full; +SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, + &ixgbe_flow_control, 0, "Default flow control used for all adapters"); + +/* Advertise Speed, default to 0 (auto) */ +static int ixgbe_advertise_speed = 0; +SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, + &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); + /* ** Smart speed setting, default to on ** this only works as a compile option @@ -575,6 +587,11 @@ ixgbe_attach(device_t dev) break; } + /* hw.ix defaults init */ + ixgbe_set_advertise(adapter, ixgbe_advertise_speed); + ixgbe_set_flowcntl(adapter, ixgbe_flow_control); + adapter->enable_aim = ixgbe_enable_aim; + if ((adapter->msix > 1) && (ixgbe_enable_msix)) error = ixgbe_allocate_msix(adapter); else @@ -1569,7 +1586,7 @@ ixgbe_msix_que(void *arg) /* Do AIM now? */ - if (ixgbe_enable_aim == FALSE) + if (adapter->enable_aim == FALSE) goto no_calc; /* ** Do Adaptive Interrupt Moderation: @@ -4295,7 +4312,7 @@ ixgbe_add_device_sysctls(struct adapter *adapter) /* Sysctls for all devices */ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, - ixgbe_set_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC); + ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC); SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim", CTLFLAG_RW, @@ -4303,7 +4320,7 @@ ixgbe_add_device_sysctls(struct adapter *adapter) SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, - ixgbe_set_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED); + ixgbe_sysctl_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "thermal_test", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, @@ -4668,41 +4685,51 @@ ixgbe_set_sysctl_value(struct adapter *adapter, const char *name, ** 3 - full */ static int -ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS) +ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) { - int error, last; - struct adapter *adapter = (struct adapter *) arg1; + int error, fc; + struct adapter *adapter; + + adapter = (struct adapter *) arg1; + fc = adapter->fc; - last = adapter->fc; - error = sysctl_handle_int(oidp, &adapter->fc, 0, req); + error = sysctl_handle_int(oidp, &fc, 0, req); if ((error) || (req->newptr == NULL)) return (error); /* Don't bother if it's not changed */ - if (adapter->fc == last) + if (adapter->fc == fc) return (0); - switch (adapter->fc) { - case ixgbe_fc_rx_pause: - case ixgbe_fc_tx_pause: - case ixgbe_fc_full: - adapter->hw.fc.requested_mode = adapter->fc; - if (adapter->num_queues > 1) - ixgbe_disable_rx_drop(adapter); - break; - case ixgbe_fc_none: - adapter->hw.fc.requested_mode = ixgbe_fc_none; - if (adapter->num_queues > 1) - ixgbe_enable_rx_drop(adapter); - break; - default: - adapter->fc = last; - return (EINVAL); + return ixgbe_set_flowcntl(adapter, fc); +} + + +static int +ixgbe_set_flowcntl(struct adapter *adapter, int fc) +{ + + switch (fc) { + case ixgbe_fc_rx_pause: + case ixgbe_fc_tx_pause: + case ixgbe_fc_full: + adapter->hw.fc.requested_mode = adapter->fc; + if (adapter->num_queues > 1) + ixgbe_disable_rx_drop(adapter); + break; + case ixgbe_fc_none: + adapter->hw.fc.requested_mode = ixgbe_fc_none; + if (adapter->num_queues > 1) + ixgbe_enable_rx_drop(adapter); + break; + default: + return (EINVAL); } + adapter->fc = fc; /* Don't autoneg if forcing a value */ adapter->hw.fc.disable_fc_autoneg = TRUE; ixgbe_fc_enable(&adapter->hw); - return error; + return (0); } /* @@ -4713,31 +4740,39 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS) ** 0x4 - advertise 10G */ static int -ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) +ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) { - int error = 0, requested; - struct adapter *adapter; - device_t dev; - struct ixgbe_hw *hw; - ixgbe_link_speed speed = 0; + int error, advertise; + struct adapter *adapter; adapter = (struct adapter *) arg1; - dev = adapter->dev; - hw = &adapter->hw; + advertise = adapter->advertise; - requested = adapter->advertise; - error = sysctl_handle_int(oidp, &requested, 0, req); + error = sysctl_handle_int(oidp, &advertise, 0, req); if ((error) || (req->newptr == NULL)) return (error); + /* Checks to validate new value */ + if (adapter->advertise == advertise) /* no change */ + return (0); + + return ixgbe_set_advertise(adapter, advertise); +} + +static int +ixgbe_set_advertise(struct adapter *adapter, int advertise) +{ + device_t dev; + struct ixgbe_hw *hw; + ixgbe_link_speed speed; + + hw = &adapter->hw; + dev = adapter->dev; + /* No speed changes for backplane media */ if (hw->phy.media_type == ixgbe_media_type_backplane) return (ENODEV); - /* Checks to validate new value */ - if (adapter->advertise == requested) /* no change */ - return (0); - if (!((hw->phy.media_type == ixgbe_media_type_copper) || (hw->phy.multispeed_fiber))) { device_printf(dev, @@ -4746,13 +4781,13 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) return (EINVAL); } - if (requested < 0x1 || requested > 0x7) { + if (advertise < 0x1 || advertise > 0x7) { device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0x7\n"); return (EINVAL); } - if ((requested & 0x1) + if ((advertise & 0x1) && (hw->mac.type != ixgbe_mac_X540) && (hw->mac.type != ixgbe_mac_X550)) { device_printf(dev, "Set Advertise: 100Mb on X540/X550 only\n"); @@ -4760,18 +4795,19 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) } /* Set new value and report new advertised mode */ - if (requested & 0x1) + speed = 0; + if (advertise & 0x1) speed |= IXGBE_LINK_SPEED_100_FULL; - if (requested & 0x2) + if (advertise & 0x2) speed |= IXGBE_LINK_SPEED_1GB_FULL; - if (requested & 0x4) + if (advertise & 0x4) speed |= IXGBE_LINK_SPEED_10GB_FULL; + adapter->advertise = advertise; hw->mac.autotry_restart = TRUE; hw->mac.ops.setup_link(hw, speed, TRUE); - adapter->advertise = requested; - return (error); + return (0); } /* diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index 05fddf6..558b532 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -497,6 +497,7 @@ struct adapter { u32 optics; u32 fc; /* local flow ctrl setting */ int advertise; /* link speeds */ + bool enable_aim; /* adaptive interrupt moderation */ bool link_active; u16 max_frame_size; u16 num_segs; -- cgit v1.1 From b92c9d3353391d51dcfcf3dbc78152c3977e42e4 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 11 Feb 2016 17:55:17 +0000 Subject: MFC 295174: - Note that devctl(8) will appear in 10.3 first. - Add missing devctl_set_driver entry to namelist in devlist(3). Approved by: re (gjb) --- lib/libdevctl/devctl.3 | 7 ++++--- usr.sbin/devctl/devctl.8 | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3 index b8a84d4..7c4c74b 100644 --- a/lib/libdevctl/devctl.3 +++ b/lib/libdevctl/devctl.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 26, 2014 +.Dd February 2, 2016 .Dt DEVCTL 3 .Os .Sh NAME @@ -33,7 +33,8 @@ .Nm devctl_attach , .Nm devctl_detach , .Nm devctl_disable , -.Nm devctl_enable +.Nm devctl_enable , +.Nm devctl_set_driver .Nd device control library .Sh LIBRARY .Lb libdevctl @@ -251,4 +252,4 @@ The new device driver failed to attach. The .Nm library first appeared in -.Fx 11.0 . +.Fx 10.3 . diff --git a/usr.sbin/devctl/devctl.8 b/usr.sbin/devctl/devctl.8 index add170d..598bea1 100644 --- a/usr.sbin/devctl/devctl.8 +++ b/usr.sbin/devctl/devctl.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 5, 2015 +.Dd February 2, 2016 .Dt DEVCTL 8 .Os .Sh NAME @@ -123,4 +123,4 @@ the device will not be changed. The .Nm utility first appeared in -.Fx 11.0 . +.Fx 10.3 . -- cgit v1.1 From a4298d06ff2c7a1d71ae0e7afb0020724d8866f2 Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 17:56:09 +0000 Subject: Fix ia64 build failures in EFI platform The MFC of the recent EFI work to stable/10 caused build breakage under ia64. It was not apparent that there was EFI code outside the EFI tree as this is not the case in HEAD, however in stable/10 there is for ia64. This change does the following: * Re-enables libefi for ia64 under gcc. * Adds the ignore for unsupported pragma's when building libefi for ia64. * Adds the missing parameter to efi_handle_lookup in the ia64 loader. This is a direct commit as ia64 is no longer supported after 10.x Approved by: re (marius) Sponsored by: Multiplay --- sys/boot/efi/Makefile | 4 ++++ sys/boot/efi/libefi/Makefile | 6 ++++++ sys/boot/ia64/efi/main.c | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile index acf5a49..89a3576 100644 --- a/sys/boot/efi/Makefile +++ b/sys/boot/efi/Makefile @@ -11,5 +11,9 @@ SUBDIR+= libefi loader boot1 .endif # ${COMPILER_TYPE} != "gcc" +.if ${MACHINE_CPUARCH} == "ia64" +SUBDIR+= libefi +.endif + .include diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile index f87fbe9..880547e 100644 --- a/sys/boot/efi/libefi/Makefile +++ b/sys/boot/efi/libefi/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= efi INTERNALLIB= WARNS?= 2 @@ -7,6 +9,10 @@ WARNS?= 2 SRCS= delay.c efi_console.c efinet.c efipart.c errno.c handles.c \ libefi.c time.c +.if ${MACHINE_CPUARCH} == "ia64" +IGNORE_PRAGMA= 1 +.endif + .if ${MACHINE_ARCH} == "amd64" CFLAGS+= -fPIC -mno-red-zone .endif diff --git a/sys/boot/ia64/efi/main.c b/sys/boot/ia64/efi/main.c index ec12b42..ca99c63a 100644 --- a/sys/boot/ia64/efi/main.c +++ b/sys/boot/ia64/efi/main.c @@ -179,7 +179,8 @@ main(int argc, CHAR16 *argv[]) BS->HandleProtocol(IH, &imgid, (VOID**)&img); bzero(&currdev, sizeof(currdev)); - efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); + efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, + &currdev.d_unit, NULL); currdev.d_type = currdev.d_dev->dv_type; env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset, -- cgit v1.1 From ccc782c04f57c64aad716172eab8bfd8592306a6 Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 17:57:42 +0000 Subject: MFC r294768: Process /boot/config and /boot.config during EFI boot Approved by: re (marius) Sponsored by: Multiplay --- sys/boot/efi/boot1/boot1.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index 0aa6c5b..c326c79 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -91,13 +91,41 @@ Free(void *buf, const char *file __unused, int line __unused) void try_load(const boot_module_t *mod) { - size_t bufsize; + size_t bufsize, cmdsize; void *buf; + char *cmd; dev_info_t *dev; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; + /* + * Read in and parse the command line from /boot.config or /boot/config, + * if present. We'll pass it the next stage via a simple ASCII + * string. loader.efi has a hack for ASCII strings, so we'll use that to + * keep the size down here. We only try to read the alternate file if + * we get EFI_NOT_FOUND because all other errors mean that the boot_module + * had troubles with the filesystem. We could return early, but we'll let + * loading the actual kernel sort all that out. Since these files are + * optional, we don't report errors in trying to read them. + */ + cmd = NULL; + cmdsize = 0; + status = mod->load(PATH_DOTCONFIG, &dev, &buf, &bufsize); + if (status == EFI_NOT_FOUND) + status = mod->load(PATH_CONFIG, &dev, &buf, &bufsize); + if (status == EFI_SUCCESS) { + cmdsize = bufsize + 1; + cmd = malloc(cmdsize); + if (cmd == NULL) { + free(buf); + return; + } + memcpy(cmd, buf, bufsize); + cmd[bufsize] = '\0'; + free(buf); + } + status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize); if (status == EFI_NOT_FOUND) return; @@ -115,6 +143,9 @@ try_load(const boot_module_t *mod) return; } + if (cmd != NULL) + printf(" command args: %s\n", cmd); + if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image)) != EFI_SUCCESS) { printf("Failed to query LoadedImage provided by %s (%lu)\n", @@ -123,11 +154,16 @@ try_load(const boot_module_t *mod) } loaded_image->DeviceHandle = dev->devhandle; + loaded_image->LoadOptionsSize = cmdsize; + loaded_image->LoadOptions = cmd; if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != EFI_SUCCESS) { printf("Failed to start image provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); + free(cmd); + loaded_image->LoadOptionsSize = 0; + loaded_image->LoadOptions = NULL; return; } } -- cgit v1.1 From fb6d8160918fa75ebb43be82c3de12395262873b Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 11 Feb 2016 22:33:47 +0000 Subject: MFC r295320, r295356 (Partial) Fix EFI multi device boot support Approved by: re (marius) Sponsored by: Multiplay --- sys/boot/efi/boot1/boot1.c | 560 +++++++++++++++++++++++++++++++-------- sys/boot/efi/boot1/boot_module.h | 13 +- sys/boot/efi/boot1/ufs_module.c | 53 ++-- sys/boot/efi/boot1/zfs_module.c | 59 ++--- sys/boot/efi/include/efidevp.h | 13 +- 5 files changed, 517 insertions(+), 181 deletions(-) diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index c326c79..1161b0a 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -50,9 +50,6 @@ static const boot_module_t *boot_modules[] = void putchar(int c); EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); -static void try_load(const boot_module_t* mod); -static EFI_STATUS probe_handle(EFI_HANDLE h); - EFI_SYSTEM_TABLE *systab; EFI_BOOT_SERVICES *bs; static EFI_HANDLE *image; @@ -85,20 +82,300 @@ Free(void *buf, const char *file __unused, int line __unused) } /* - * This function only returns if it fails to load the kernel. If it - * succeeds, it simply boots the kernel. + * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match, + * FALSE otherwise. */ -void -try_load(const boot_module_t *mod) +static BOOLEAN +nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + int len; + + if (imgpath == NULL || imgpath->Type != devpath->Type || + imgpath->SubType != devpath->SubType) + return (FALSE); + + len = DevicePathNodeLength(imgpath); + if (len != DevicePathNodeLength(devpath)) + return (FALSE); + + return (memcmp(imgpath, devpath, (size_t)len) == 0); +} + +/* + * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes + * in imgpath and devpath match up to their respect occurances of a media + * node, FALSE otherwise. + */ +static BOOLEAN +device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + + if (imgpath == NULL) + return (FALSE); + + while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) { + if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) && + IsDevicePathType(devpath, MEDIA_DEVICE_PATH)) + return (TRUE); + + if (!nodes_match(imgpath, devpath)) + return (FALSE); + + imgpath = NextDevicePathNode(imgpath); + devpath = NextDevicePathNode(devpath); + } + + return (FALSE); +} + +/* + * devpath_last returns the last non-path end node in devpath. + */ +static EFI_DEVICE_PATH * +devpath_last(EFI_DEVICE_PATH *devpath) +{ + + while (!IsDevicePathEnd(NextDevicePathNode(devpath))) + devpath = NextDevicePathNode(devpath); + + return (devpath); +} + +/* + * devpath_node_str is a basic output method for a devpath node which + * only understands a subset of the available sub types. + * + * If we switch to UEFI 2.x then we should update it to use: + * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. + */ +static int +devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + + switch (devpath->Type) { + case MESSAGING_DEVICE_PATH: + switch (devpath->SubType) { + case MSG_ATAPI_DP: { + ATAPI_DEVICE_PATH *atapi; + + atapi = (ATAPI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "ata(%s,%s,0x%x)", + (atapi->PrimarySecondary == 1) ? "Sec" : "Pri", + (atapi->SlaveMaster == 1) ? "Slave" : "Master", + atapi->Lun); + } + case MSG_USB_DP: { + USB_DEVICE_PATH *usb; + + usb = (USB_DEVICE_PATH *)devpath; + return snprintf(buf, size, "usb(0x%02x,0x%02x)", + usb->ParentPortNumber, usb->InterfaceNumber); + } + case MSG_SCSI_DP: { + SCSI_DEVICE_PATH *scsi; + + scsi = (SCSI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "scsi(0x%02x,0x%02x)", + scsi->Pun, scsi->Lun); + } + case MSG_SATA_DP: { + SATA_DEVICE_PATH *sata; + + sata = (SATA_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)", + sata->HBAPortNumber, sata->PortMultiplierPortNumber, + sata->Lun); + } + default: + return snprintf(buf, size, "msg(0x%02x)", + devpath->SubType); + } + break; + case HARDWARE_DEVICE_PATH: + switch (devpath->SubType) { + case HW_PCI_DP: { + PCI_DEVICE_PATH *pci; + + pci = (PCI_DEVICE_PATH *)devpath; + return snprintf(buf, size, "pci(0x%02x,0x%02x)", + pci->Device, pci->Function); + } + default: + return snprintf(buf, size, "hw(0x%02x)", + devpath->SubType); + } + break; + case ACPI_DEVICE_PATH: { + ACPI_HID_DEVICE_PATH *acpi; + + acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath; + if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM(acpi->HID)) { + case 0x0a03: + return snprintf(buf, size, "pciroot(0x%x)", + acpi->UID); + case 0x0a08: + return snprintf(buf, size, "pcieroot(0x%x)", + acpi->UID); + case 0x0604: + return snprintf(buf, size, "floppy(0x%x)", + acpi->UID); + case 0x0301: + return snprintf(buf, size, "keyboard(0x%x)", + acpi->UID); + case 0x0501: + return snprintf(buf, size, "serial(0x%x)", + acpi->UID); + case 0x0401: + return snprintf(buf, size, "parallelport(0x%x)", + acpi->UID); + default: + return snprintf(buf, size, "acpi(pnp%04x,0x%x)", + EISA_ID_TO_NUM(acpi->HID), acpi->UID); + } + } + + return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID, + acpi->UID); + } + case MEDIA_DEVICE_PATH: + switch (devpath->SubType) { + case MEDIA_CDROM_DP: { + CDROM_DEVICE_PATH *cdrom; + + cdrom = (CDROM_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "cdrom(%x)", + cdrom->BootEntry); + } + case MEDIA_HARDDRIVE_DP: { + HARDDRIVE_DEVICE_PATH *hd; + + hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "hd(%x)", + hd->PartitionNumber); + } + default: + return snprintf(buf, size, "media(0x%02x)", + devpath->SubType); + } + case BBS_DEVICE_PATH: + return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType); + case END_DEVICE_PATH_TYPE: + return (0); + } + + return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type, + devpath->SubType); +} + +/* + * devpath_strlcat appends a text description of devpath to buf but not more + * than size - 1 characters followed by NUL-terminator. + */ +int +devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + size_t len, used; + const char *sep; + + sep = ""; + used = 0; + while (!IsDevicePathEnd(devpath)) { + len = snprintf(buf, size - used, "%s", sep); + used += len; + if (used > size) + return (used); + buf += len; + + len = devpath_node_str(buf, size - used, devpath); + used += len; + if (used > size) + return (used); + buf += len; + devpath = NextDevicePathNode(devpath); + sep = ":"; + } + + return (used); +} + +/* + * devpath_str is convenience method which returns the text description of + * devpath using a static buffer, so it isn't thread safe! + */ +char * +devpath_str(EFI_DEVICE_PATH *devpath) +{ + static char buf[256]; + + devpath_strlcat(buf, sizeof(buf), devpath); + + return buf; +} + +/* + * load_loader attempts to load the loader image data. + * + * It tries each module and its respective devices, identified by mod->probe, + * in order until a successful load occurs at which point it returns EFI_SUCCESS + * and EFI_NOT_FOUND otherwise. + * + * Only devices which have preferred matching the preferred parameter are tried. + */ +static EFI_STATUS +load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, + size_t *bufsize, BOOLEAN preferred) { - size_t bufsize, cmdsize; - void *buf; + UINTN i; + dev_info_t *dev; + const boot_module_t *mod; + + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + mod = boot_modules[i]; + for (dev = mod->devices(); dev != NULL; dev = dev->next) { + if (dev->preferred != preferred) + continue; + + if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == + EFI_SUCCESS) { + *devinfop = dev; + *modp = mod; + return (EFI_SUCCESS); + } + } + } + + return (EFI_NOT_FOUND); +} + +/* + * try_boot only returns if it fails to load the loader. If it succeeds + * it simply boots, otherwise it returns the status of last EFI call. + */ +static EFI_STATUS +try_boot() +{ + size_t bufsize, loadersize, cmdsize; + void *buf, *loaderbuf; char *cmd; dev_info_t *dev; + const boot_module_t *mod; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); + if (status != EFI_SUCCESS) { + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, + FALSE); + if (status != EFI_SUCCESS) { + printf("Failed to load '%s'\n", PATH_LOADER_EFI); + return (status); + } + } + /* * Read in and parse the command line from /boot.config or /boot/config, * if present. We'll pass it the next stage via a simple ASCII @@ -111,67 +388,183 @@ try_load(const boot_module_t *mod) */ cmd = NULL; cmdsize = 0; - status = mod->load(PATH_DOTCONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize); if (status == EFI_NOT_FOUND) - status = mod->load(PATH_CONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_CONFIG, dev, &buf, &bufsize); if (status == EFI_SUCCESS) { cmdsize = bufsize + 1; cmd = malloc(cmdsize); - if (cmd == NULL) { - free(buf); - return; - } + if (cmd == NULL) + goto errout; memcpy(cmd, buf, bufsize); cmd[bufsize] = '\0'; free(buf); + buf = NULL; } - status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize); - if (status == EFI_NOT_FOUND) - return; - - if (status != EFI_SUCCESS) { - printf("%s failed to load %s (%lu)\n", mod->name, - PATH_LOADER_EFI, EFI_ERROR_CODE(status)); - return; - } - - if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize, - &loaderhandle)) != EFI_SUCCESS) { + if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath), + loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) { printf("Failed to load image provided by %s, size: %zu, (%lu)\n", mod->name, bufsize, EFI_ERROR_CODE(status)); - return; + goto errout; } - if (cmd != NULL) - printf(" command args: %s\n", cmd); - if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image)) != EFI_SUCCESS) { printf("Failed to query LoadedImage provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - return; + goto errout; } + if (cmd != NULL) + printf(" command args: %s\n", cmd); + loaded_image->DeviceHandle = dev->devhandle; loaded_image->LoadOptionsSize = cmdsize; loaded_image->LoadOptions = cmd; + DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF(".\n"); + if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != EFI_SUCCESS) { printf("Failed to start image provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - free(cmd); loaded_image->LoadOptionsSize = 0; loaded_image->LoadOptions = NULL; - return; } + +errout: + if (cmd != NULL) + free(cmd); + if (buf != NULL) + free(buf); + if (loaderbuf != NULL) + free(loaderbuf); + + return (status); +} + +/* + * probe_handle determines if the passed handle represents a logical partition + * if it does it uses each module in order to probe it and if successful it + * returns EFI_SUCCESS. + */ +static EFI_STATUS +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred) +{ + dev_info_t *devinfo; + EFI_BLOCK_IO *blkio; + EFI_DEVICE_PATH *devpath; + EFI_STATUS status; + UINTN i; + + /* Figure out if we're dealing with an actual partition. */ + status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + DPRINTF("probing: %s\n", devpath_str(devpath)); + + status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + if (!blkio->Media->LogicalPartition) + return (EFI_UNSUPPORTED); + + *preferred = device_paths_match(imgpath, devpath); + + /* Run through each module, see if it can load this partition */ + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + + if ((status = bs->AllocatePool(EfiLoaderData, + sizeof(*devinfo), (void **)&devinfo)) != + EFI_SUCCESS) { + DPRINTF("\nFailed to allocate devinfo (%lu)\n", + EFI_ERROR_CODE(status)); + continue; + } + devinfo->dev = blkio; + devinfo->devpath = devpath; + devinfo->devhandle = h; + devinfo->devdata = NULL; + devinfo->preferred = *preferred; + devinfo->next = NULL; + + status = boot_modules[i]->probe(devinfo); + if (status == EFI_SUCCESS) + return (EFI_SUCCESS); + (void)bs->FreePool(devinfo); + } + + return (EFI_UNSUPPORTED); +} + +/* + * probe_handle_status calls probe_handle and outputs the returned status + * of the call. + */ +static void +probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) +{ + EFI_STATUS status; + BOOLEAN preferred; + + status = probe_handle(h, imgpath, &preferred); + + DPRINTF("probe: "); + switch (status) { + case EFI_UNSUPPORTED: + printf("."); + DPRINTF(" not supported\n"); + break; + case EFI_SUCCESS: + if (preferred) { + printf("%c", '*'); + DPRINTF(" supported (preferred)\n"); + } else { + printf("%c", '+'); + DPRINTF(" supported\n"); + } + break; + default: + printf("x"); + DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); + break; + } + DSTALL(500000); } EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) { EFI_HANDLE *handles; + EFI_LOADED_IMAGE *img; + EFI_DEVICE_PATH *imgpath; EFI_STATUS status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; @@ -254,20 +647,22 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) /* Scan all partitions, probing with all modules. */ nhandles = hsize / sizeof(*handles); printf(" Probing %zu block devices...", nhandles); - for (i = 0; i < nhandles; i++) { - status = probe_handle(handles[i]); - switch (status) { - case EFI_UNSUPPORTED: - printf("."); - break; - case EFI_SUCCESS: - printf("+"); - break; - default: - printf("x"); - break; - } + DPRINTF("\n"); + + /* Determine the devpath of our image so we can prefer it. */ + status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); + imgpath = NULL; + if (status == EFI_SUCCESS) { + status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, + (void **)&imgpath); + if (status != EFI_SUCCESS) + DPRINTF("Failed to get image DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath)); } + + for (i = 0; i < nhandles; i++) + probe_handle_status(handles[i], imgpath); printf(" done\n"); /* Status summary. */ @@ -278,78 +673,15 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) } } - /* Select a partition to boot by trying each module in order. */ - for (i = 0; i < NUM_BOOT_MODULES; i++) - if (boot_modules[i] != NULL) - try_load(boot_modules[i]); + try_boot(); /* If we get here, we're out of luck... */ panic("No bootable partitions found!"); } -static EFI_STATUS -probe_handle(EFI_HANDLE h) -{ - dev_info_t *devinfo; - EFI_BLOCK_IO *blkio; - EFI_DEVICE_PATH *devpath; - EFI_STATUS status; - UINTN i; - - /* Figure out if we're dealing with an actual partition. */ - status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query DevicePath (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - while (!IsDevicePathEnd(NextDevicePathNode(devpath))) - devpath = NextDevicePathNode(devpath); - - status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - if (!blkio->Media->LogicalPartition) - return (EFI_UNSUPPORTED); - - /* Run through each module, see if it can load this partition */ - for (i = 0; i < NUM_BOOT_MODULES; i++) { - if (boot_modules[i] == NULL) - continue; - - if ((status = bs->AllocatePool(EfiLoaderData, - sizeof(*devinfo), (void **)&devinfo)) != - EFI_SUCCESS) { - DPRINTF("\nFailed to allocate devinfo (%lu)\n", - EFI_ERROR_CODE(status)); - continue; - } - devinfo->dev = blkio; - devinfo->devpath = devpath; - devinfo->devhandle = h; - devinfo->devdata = NULL; - devinfo->next = NULL; - - status = boot_modules[i]->probe(devinfo); - if (status == EFI_SUCCESS) - return (EFI_SUCCESS); - (void)bs->FreePool(devinfo); - } - - return (EFI_UNSUPPORTED); -} - +/* + * add_device adds a device to the passed devinfo list. + */ void add_device(dev_info_t **devinfop, dev_info_t *devinfo) { diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h index 2c158f6..296d5a6 100644 --- a/sys/boot/efi/boot1/boot_module.h +++ b/sys/boot/efi/boot1/boot_module.h @@ -36,9 +36,11 @@ #include #ifdef EFI_DEBUG -#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#define DPRINTF(fmt, args...) printf(fmt, ##args) +#define DSTALL(d) bs->Stall(d) #else #define DPRINTF(fmt, ...) {} +#define DSTALL(d) {} #endif /* EFI device info */ @@ -48,6 +50,7 @@ typedef struct dev_info EFI_DEVICE_PATH *devpath; EFI_HANDLE *devhandle; void *devdata; + BOOLEAN preferred; struct dev_info *next; } dev_info_t; @@ -75,19 +78,21 @@ typedef struct boot_module_t /* * load should select the best out of a set of devices that probe - * indicated were loadable and load it. + * indicated were loadable and load the specified file. * * Return codes: * EFI_SUCCESS = The module can handle the device. * EFI_NOT_FOUND = The module can not handle the device. * Other = The module encountered an error. */ - EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo, + EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo, void **buf, size_t *bufsize); /* status outputs information about the probed devices. */ void (*status)(); + /* valid devices as found by probe. */ + dev_info_t *(*devices)(); } boot_module_t; /* Standard boot modules. */ @@ -107,4 +112,6 @@ extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); extern EFI_SYSTEM_TABLE *systab; extern EFI_BOOT_SERVICES *bs; +extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath); +extern char *devpath_str(EFI_DEVICE_PATH *devpath); #endif diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c index 07c7152..63087ea 100644 --- a/sys/boot/efi/boot1/ufs_module.c +++ b/sys/boot/efi/boot1/ufs_module.c @@ -93,7 +93,7 @@ probe(dev_info_t* dev) } static EFI_STATUS -try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) { ufs_ino_t ino; EFI_STATUS status; @@ -101,59 +101,46 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) ssize_t read; void *buf; - if (init_dev(dev) < 0) + DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath)); + + if (init_dev(dev) < 0) { + DPRINTF("Failed to init device\n"); return (EFI_UNSUPPORTED); + } - if ((ino = lookup(loader_path)) == 0) + if ((ino = lookup(filepath)) == 0) { + DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); return (EFI_NOT_FOUND); + } if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { - printf("Failed to read size of '%s' ino: %d\n", loader_path, - ino); + printf("Failed to read size of '%s' ino: %d\n", filepath, ino); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate read buffer (%lu)\n", - EFI_ERROR_CODE(status)); + printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", + size, filepath, EFI_ERROR_CODE(status)); return (status); } read = fsread(ino, buf, size); if ((size_t)read != size) { - printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read, + printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, size); (void)bs->FreePool(buf); return (EFI_INVALID_PARAMETER); } + DPRINTF("Load complete\n"); + *bufp = buf; *bufsize = size; return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **buf, - size_t *bufsize) -{ - dev_info_t *dev; - EFI_STATUS status; - - for (dev = devices; dev != NULL; dev = dev->next) { - status = try_load(dev, loader_path, buf, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = dev; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -176,10 +163,18 @@ status() } } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t ufs_module = { .name = "UFS", .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c index 96eec33..925f0b2 100644 --- a/sys/boot/efi/boot1/zfs_module.c +++ b/sys/boot/efi/boot1/zfs_module.c @@ -91,7 +91,7 @@ probe(dev_info_t *dev) } static EFI_STATUS -try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) { spa_t *spa; struct zfsmount zfsmount; @@ -102,32 +102,41 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs EFI_STATUS status; spa = devinfo->devdata; - if (zfs_spa_init(spa) != 0) { - /* Init failed, don't report this loudly. */ + + DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name, + devpath_str(devinfo->devpath)); + + if ((err = zfs_spa_init(spa)) != 0) { + DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if (zfs_mount(spa, 0, &zfsmount) != 0) { - /* Mount failed, don't report this loudly. */ + if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) { + DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) { + if (err == ENOENT) { + DPRINTF("Failed to find '%s' on pool '%s' (%d)\n", + filepath, spa->spa_name, err); + return (EFI_NOT_FOUND); + } + printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate load buffer for pool %s (%lu)\n", - spa->spa_name, EFI_ERROR_CODE(status)); + printf("Failed to allocate load buffer %zd for pool '%s' for '%s' " + "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status)); return (EFI_INVALID_PARAMETER); } @@ -144,26 +153,6 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **bufp, - size_t *bufsize) -{ - dev_info_t *devinfo; - EFI_STATUS status; - - for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) { - status = try_load(devinfo, loader_path, bufp, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = devinfo; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -189,11 +178,19 @@ init() zfs_init(); } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t zfs_module = { .name = "ZFS", .init = init, .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/include/efidevp.h b/sys/boot/efi/include/efidevp.h index f0f49ef..dda79de7 100644 --- a/sys/boot/efi/include/efidevp.h +++ b/sys/boot/efi/include/efidevp.h @@ -40,9 +40,7 @@ typedef struct _EFI_DEVICE_PATH { #define EFI_DP_TYPE_MASK 0x7F #define EFI_DP_TYPE_UNPACKED 0x80 -//#define END_DEVICE_PATH_TYPE 0xff #define END_DEVICE_PATH_TYPE 0x7f -//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 @@ -56,8 +54,8 @@ typedef struct _EFI_DEVICE_PATH { #define DevicePathSubType(a) ( (a)->SubType ) #define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) #define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) -//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) -#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathType(a, t) ( DevicePathType(a) == t ) +#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE) #define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) #define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) #define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) @@ -285,6 +283,13 @@ typedef struct _UART_DEVICE_PATH { #define DEVICE_PATH_MESSAGING_VT_UTF8 \ { 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} } +#define MSG_SATA_DP 0x12 +typedef struct _SATA_DEVICE_PATH { + EFI_DEVICE_PATH Header; + UINT16 HBAPortNumber; + UINT16 PortMultiplierPortNumber; + UINT16 Lun; +} SATA_DEVICE_PATH; #define MEDIA_DEVICE_PATH 0x04 -- cgit v1.1 From 33b886efb2ac471d2df861e307377ef048618ca5 Mon Sep 17 00:00:00 2001 From: imp Date: Thu, 11 Feb 2016 23:43:27 +0000 Subject: Merge from current r294767,294769,295408 r294767: Parse command line arguments in loader.fi r294769: Allow newlines to be treated as whitespace when parsing args r295408: Implement -P command line option in for EFI booting. Approved by: re@ (gjb@) --- sys/boot/efi/libefi/libefi.c | 4 +- sys/boot/efi/loader/main.c | 197 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 186 insertions(+), 15 deletions(-) diff --git a/sys/boot/efi/libefi/libefi.c b/sys/boot/efi/libefi/libefi.c index f87b89a..c76bd6c 100644 --- a/sys/boot/efi/libefi/libefi.c +++ b/sys/boot/efi/libefi/libefi.c @@ -44,7 +44,7 @@ static CHAR16 * arg_skipsep(CHAR16 *argp) { - while (*argp == ' ' || *argp == '\t') + while (*argp == ' ' || *argp == '\t' || *argp == '\n') argp++; return (argp); } @@ -53,7 +53,7 @@ static CHAR16 * arg_skipword(CHAR16 *argp) { - while (*argp && *argp != ' ' && *argp != '\t') + while (*argp && *argp != ' ' && *argp != '\t' && *argp != '\n') argp++; return (argp); } diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index f796b4d..d167af2 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include #include @@ -63,6 +65,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 inputid = SIMPLE_TEXT_INPUT_PROTOCOL; #ifdef EFI_ZFS_BOOT static void efi_zfs_probe(void); @@ -82,16 +85,108 @@ print_str16(const CHAR16 *str) printf("%c", (char)str[i]); } +static void +cp16to8(const CHAR16 *src, char *dst, size_t len) +{ + size_t i; + + for (i = 0; i < len && src[i]; i++) + dst[i] = (char)src[i]; +} + +static int +has_keyboard(void) +{ + EFI_STATUS status; + EFI_DEVICE_PATH *path; + EFI_HANDLE *hin, *hin_end, *walker; + UINTN sz; + int retval = 0; + + /* + * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and + * do the typical dance to get the right sized buffer. + */ + sz = 0; + hin = NULL; + status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0); + if (status == EFI_BUFFER_TOO_SMALL) { + hin = (EFI_HANDLE *)malloc(sz); + status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, + hin); + if (EFI_ERROR(status)) + free(hin); + } + if (EFI_ERROR(status)) + return retval; + + /* + * Look at each of the handles. If it supports the device path protocol, + * use it to get the device path for this handle. Then see if that + * device path matches either the USB device path for keyboards or the + * legacy device path for keyboards. + */ + hin_end = &hin[sz / sizeof(*hin)]; + for (walker = hin; walker < hin_end; walker++) { + status = BS->HandleProtocol(*walker, &devid, (VOID **)&path); + if (EFI_ERROR(status)) + continue; + + while (!IsDevicePathEnd(path)) { + /* + * Check for the ACPI keyboard node. All PNP3xx nodes + * are keyboards of different flavors. Note: It is + * unclear of there's always a keyboard node when + * there's a keyboard controller, or if there's only one + * when a keyboard is detected at boot. + */ + if (DevicePathType(path) == ACPI_DEVICE_PATH && + (DevicePathSubType(path) == ACPI_DP || + DevicePathSubType(path) == ACPI_EXTENDED_DP)) { + ACPI_HID_DEVICE_PATH *acpi; + + acpi = (ACPI_HID_DEVICE_PATH *)(void *)path; + if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) == 0x300 && + (acpi->HID & 0xffff) == PNP_EISA_ID_CONST) { + retval = 1; + goto out; + } + /* + * Check for USB keyboard node, if present. Unlike a + * PS/2 keyboard, these definitely only appear when + * connected to the system. + */ + } else if (DevicePathType(path) == MESSAGING_DEVICE_PATH && + DevicePathSubType(path) == MSG_USB_CLASS_DP) { + USB_CLASS_DEVICE_PATH *usb; + + usb = (USB_CLASS_DEVICE_PATH *)(void *)path; + if (usb->DeviceClass == 3 && /* HID */ + usb->DeviceSubClass == 1 && /* Boot devices */ + usb->DeviceProtocol == 1) { /* Boot keyboards */ + retval = 1; + goto out; + } + } + path = NextDevicePathNode(path); + } + } +out: + free(hin); + return retval; +} + EFI_STATUS main(int argc, CHAR16 *argv[]) { char var[128]; EFI_LOADED_IMAGE *img; EFI_GUID *guid; - int i, j, vargood, unit; + int i, j, vargood, unit, howto; struct devsw *dev; uint64_t pool_guid; UINTN k; + int has_kbd; archsw.arch_autoload = efi_autoload; archsw.arch_getdev = efi_getdev; @@ -103,6 +198,8 @@ main(int argc, CHAR16 *argv[]) archsw.arch_zfs_probe = efi_zfs_probe; #endif + has_kbd = has_keyboard(); + /* * XXX Chicken-and-egg problem; we want to have console output * early, but some console attributes may depend on reading from @@ -112,27 +209,101 @@ main(int argc, CHAR16 *argv[]) cons_probe(); /* + * Parse the args to set the console settings, etc + * boot1.efi passes these in, if it can read /boot.config or /boot/config + * or iPXE may be setup to pass these in. + * * Loop through the args, and for each one that contains an '=' that is * not the first character, add it to the environment. This allows * loader and kernel env vars to be passed on the command line. Convert * args from UCS-2 to ASCII (16 to 8 bit) as they are copied. */ + howto = 0; for (i = 1; i < argc; i++) { - vargood = 0; - for (j = 0; argv[i][j] != 0; j++) { - if (j == sizeof(var)) { - vargood = 0; - break; + if (argv[i][0] == '-') { + for (j = 1; argv[i][j] != 0; j++) { + int ch; + + ch = argv[i][j]; + switch (ch) { + case 'a': + howto |= RB_ASKNAME; + break; + case 'd': + howto |= RB_KDB; + break; + case 'D': + howto |= RB_MULTIPLE; + break; + case 'h': + howto |= RB_SERIAL; + break; + case 'm': + howto |= RB_MUTE; + break; + case 'p': + howto |= RB_PAUSE; + break; + case 'P': + if (!has_kbd) + howto |= RB_SERIAL | RB_MULTIPLE; + break; + case 'r': + howto |= RB_DFLTROOT; + break; + case 's': + howto |= RB_SINGLE; + break; + case 'S': + if (argv[i][j + 1] == 0) { + if (i + 1 == argc) { + setenv("comconsole_speed", "115200", 1); + } else { + cp16to8(&argv[i + 1][0], var, + sizeof(var)); + setenv("comconsole_speedspeed", var, 1); + } + i++; + break; + } else { + cp16to8(&argv[i][j + 1], var, + sizeof(var)); + setenv("comconsole_speed", var, 1); + break; + } + case 'v': + howto |= RB_VERBOSE; + break; + } + } + } else { + vargood = 0; + for (j = 0; argv[i][j] != 0; j++) { + if (j == sizeof(var)) { + vargood = 0; + break; + } + if (j > 0 && argv[i][j] == '=') + vargood = 1; + var[j] = (char)argv[i][j]; + } + if (vargood) { + var[j] = 0; + putenv(var); } - if (j > 0 && argv[i][j] == '=') - vargood = 1; - var[j] = (char)argv[i][j]; - } - if (vargood) { - var[j] = 0; - putenv(var); } } + for (i = 0; howto_names[i].ev != NULL; i++) + if (howto & howto_names[i].mask) + setenv(howto_names[i].ev, "YES", 1); + if (howto & RB_MULTIPLE) { + if (howto & RB_SERIAL) + setenv("console", "comconsole efi" , 1); + else + setenv("console", "efi comconsole" , 1); + } else if (howto & RB_SERIAL) { + setenv("console", "comconsole" , 1); + } if (efi_copy_init()) { printf("failed to allocate staging area\n"); -- cgit v1.1 From a3f0577ed04b6c469cd8c282522893364bebcf3f Mon Sep 17 00:00:00 2001 From: marius Date: Fri, 12 Feb 2016 00:03:39 +0000 Subject: Update stable/10 to BETA2 in preparation for 10.3-BETA2 builds. Approved by: re (implicit) --- sys/conf/newvers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 09695ce..7a52fe7 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.3" -BRANCH="BETA1" +BRANCH="BETA2" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi -- cgit v1.1