diff options
251 files changed, 6113 insertions, 1923 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1 index e486331..5e9b9b1 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -13,6 +13,8 @@ # -DNO_PORTSUPDATE do not update ports in ${MAKE} update # -DNO_DOCUPDATE do not update doc in ${MAKE} update # -DNO_WWWUPDATE do not update www in ${MAKE} update +# -DDB_FROM_SRC use the user/group databases in src/etc instead of +# the system database when installing. # -DNO_CTF do not run the DTrace CTF conversion tools on built objects # LOCAL_DIRS="list of dirs" to add additional dirs to the SUBDIR list # LOCAL_LIB_DIRS="list of dirs" to add additional dirs to libraries target @@ -340,12 +342,13 @@ LIB32WMAKEFLAGS+= \ LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \ -DWITHOUT_BIND -DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML -LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS +LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS \ + ${IMAKE_INSTALL} .endif -# install stage IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*} -IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 +IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \ + ${IMAKE_INSTALL} ${IMAKE_MTREE} .if empty(.MAKEFLAGS:M-n) IMAKEENV+= PATH=${STRICTTMPPATH}:${INSTALLTMP} \ LD_LIBRARY_PATH=${INSTALLTMP} \ @@ -354,6 +357,10 @@ IMAKE+= __MAKE_SHELL=${INSTALLTMP}/sh .else IMAKEENV+= PATH=${TMPPATH}:${INSTALLTMP} .endif +.if defined(DB_FROM_SRC) +IMAKE_INSTALL= INSTALL="install -N ${.CURDIR}/etc" +IMAKE_MTREE= MTREE_CMD="nmtree -N ${.CURDIR}/etc" +.endif # kernel stage KMAKEENV= ${WMAKEENV} @@ -595,9 +602,11 @@ kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries} installcheck: # -# Require DESTDIR to be set if installing for a different architecture. +# Require DESTDIR to be set if installing for a different architecture or +# using the user/group database in the source tree. # -.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE} +.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE} || \ + defined(DB_FROM_SRC) .if !make(distributeworld) installcheck: installcheck_DESTDIR installcheck_DESTDIR: @@ -608,6 +617,7 @@ installcheck_DESTDIR: .endif .endif +.if !defined(DB_FROM_SRC) # # Check for missing UIDs/GIDs. # @@ -635,6 +645,7 @@ installcheck_UGID: false; \ fi .endfor +.endif # # Required install tools to be saved in a scratch dir for safety. @@ -692,6 +703,7 @@ distributeworld installworld: installcheck done); \ cp $$libs $$progs ${INSTALLTMP} cp -R $${PATH_LOCALE:-"/usr/share/locale"} ${INSTALLTMP}/locale + rm -f ${METALOG} .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} -mkdir ${DESTDIR}/${DISTDIR}/${dist} @@ -753,7 +765,8 @@ redistribute: .endif distrib-dirs distribution: - cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} ${.TARGET} + cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ + ${IMAKE_INSTALL} ${.TARGET} # # buildkernel and installkernel @@ -1059,6 +1072,11 @@ _lex= usr.bin/lex _yacc= usr.bin/yacc .endif +.if defined(DB_FROM_SRC) && ${BOOTSTRAPPING} < 1000026 +_nmtree= lib/libnetbsd \ + usr.sbin/nmtree +.endif + .if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 _awk= usr.bin/awk .endif @@ -1120,7 +1138,8 @@ bootstrap-tools: ${_lex} \ usr.bin/xinstall \ ${_gensnmptree} \ - usr.sbin/config + usr.sbin/config \ + ${_nmtree} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 740b92d..378cc96 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -1201,12 +1201,6 @@ OLD_FILES+=usr/include/sys/linedisc.h OLD_FILES+=usr/share/man/man3/posix_openpt.3.gz # 20080725: sgtty.h removed OLD_FILES+=usr/include/sgtty.h -# 20080719: sade(8) removed on all but amd64, i386 and sparc64 -.if ${TARGET_ARCH} != "amd64" && ${TARGET_ARCH} != "i386" && \ - ${TARGET_ARCH} != "sparc64" -OLD_FILES+=usr/sbin/sade -OLD_FILES+=usr/share/man/man8/sade.8.gz -.endif # 20080706: bsdlabel(8) removed on powerpc .if ${TARGET_ARCH} == "powerpc" OLD_FILES+=sbin/bsdlabel diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c index 26cf1bd..6851fad 100644 --- a/bin/pwait/pwait.c +++ b/bin/pwait/pwait.c @@ -141,5 +141,5 @@ main(int argc, char *argv[]) nleft -= n; } - return 0; + exit(EX_OK); } diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 2e1315e..98261e9 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -624,8 +624,8 @@ evalbackcmd(union node *n, struct backcmd *result) exitstatus = 0; goto out; } + exitstatus = oexitstatus; if (is_valid_fast_cmdsubst(n)) { - exitstatus = oexitstatus; savelocalvars = localvars; localvars = NULL; forcelocal++; @@ -649,7 +649,6 @@ evalbackcmd(union node *n, struct backcmd *result) poplocalvars(); localvars = savelocalvars; } else { - exitstatus = 0; if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); jp = makejob(n, 1); diff --git a/bin/sh/exec.c b/bin/sh/exec.c index eb32403..7a6dbae 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -86,12 +86,12 @@ struct tblentry { union param param; /* definition of builtin function */ int special; /* flag for special builtin commands */ signed char cmdtype; /* index identifying command */ - char rehash; /* if set, cd done since entry created */ char cmdname[]; /* name of command */ }; static struct tblentry *cmdtable[CMDTABLESIZE]; +static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */ int exerrno = 0; /* Last exec error */ @@ -305,8 +305,6 @@ printentry(struct tblentry *cmdp, int verbose) error("internal error: cmdtype %d", cmdp->cmdtype); #endif } - if (cmdp->rehash) - out1c('*'); out1c('\n'); } @@ -323,12 +321,12 @@ find_command(const char *name, struct cmdentry *entry, int act, { struct tblentry *cmdp, loc_cmd; int idx; - int prev; char *fullname; struct stat statb; int e; int i; int spec; + int cd; /* If name contains a slash, don't use the hash table */ if (strchr(name, '/') != NULL) { @@ -337,8 +335,10 @@ find_command(const char *name, struct cmdentry *entry, int act, return; } + cd = 0; + /* If name is in the table, and not invalidated by cd, we're done */ - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) { + if ((cmdp = cmdlookup(name, 0)) != NULL) { if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC) cmdp = NULL; else @@ -359,13 +359,6 @@ find_command(const char *name, struct cmdentry *entry, int act, } /* We have to search path. */ - prev = -1; /* where to start */ - if (cmdp) { /* doing a rehash */ - if (cmdp->cmdtype == CMDBUILTIN) - prev = -1; - else - prev = cmdp->param.index; - } e = ENOENT; idx = -1; @@ -380,13 +373,8 @@ loop: goto loop; /* ignore unimplemented options */ } } - /* if rehash, don't redo absolute path names */ - if (fullname[0] == '/' && idx <= prev) { - if (idx < prev) - goto loop; - TRACE(("searchexec \"%s\": no change\n", name)); - goto success; - } + if (fullname[0] != '/') + cd = 1; if (stat(fullname, &statb) < 0) { if (errno != ENOENT && errno != ENOTDIR) e = errno; @@ -426,9 +414,6 @@ loop: goto success; } - /* We failed. If there was an entry for this command, delete it */ - if (cmdp && cmdp->cmdtype != CMDFUNCTION) - delete_cmd_entry(); if (act & DO_ERR) { if (e == ENOENT || e == ENOTDIR) outfmt(out2, "%s: not found\n", name); @@ -440,7 +425,8 @@ loop: return; success: - cmdp->rehash = 0; + if (cd) + cmdtable_cd = 1; entry->cmdtype = cmdp->cmdtype; entry->u = cmdp->param; entry->special = cmdp->special; @@ -469,22 +455,15 @@ find_builtin(const char *name, int *special) /* - * Called when a cd is done. Marks all commands so the next time they - * are executed they will be rehashed. + * Called when a cd is done. If any entry in cmdtable depends on the current + * directory, simply clear cmdtable completely. */ void hashcd(void) { - struct tblentry **pp; - struct tblentry *cmdp; - - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype == CMDNORMAL) - cmdp->rehash = 1; - } - } + if (cmdtable_cd) + clearcmdentry(); } @@ -526,6 +505,7 @@ clearcmdentry(void) } } } + cmdtable_cd = 0; INTON; } @@ -566,7 +546,6 @@ cmdlookup(const char *name, int add) + strlen(name) + 1); cmdp->next = NULL; cmdp->cmdtype = CMDUNKNOWN; - cmdp->rehash = 0; strcpy(cmdp->cmdname, name); INTON; } diff --git a/bin/sh/parser.c b/bin/sh/parser.c index ef1aa36..665b53f 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -240,9 +240,9 @@ list(int nlflag, int erflag) n2 = andor(); tok = readtoken(); if (tok == TBACKGND) { - if (n2->type == NPIPE) { + if (n2 != NULL && n2->type == NPIPE) { n2->npipe.backgnd = 1; - } else if (n2->type == NREDIR) { + } else if (n2 != NULL && n2->type == NREDIR) { n2->type = NBACKGND; } else { n3 = (union node *)stalloc(sizeof (struct nredir)); @@ -286,7 +286,8 @@ list(int nlflag, int erflag) tokpushback++; } checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (!nlflag && !erflag && tokendlist[peektoken()]) + if (!nlflag && (erflag ? peektoken() == TEOF : + tokendlist[peektoken()])) return ntop; break; case TEOF: diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 1750267..83cf7c2 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd July 15, 2012 +.Dd January 14, 2013 .Dt SH 1 .Os .Sh NAME @@ -2219,10 +2219,6 @@ The shell maintains a hash table which remembers the locations of commands. With no arguments whatsoever, the .Ic hash command prints out the contents of this table. -Entries which have not been looked at since the last -.Ic cd -command are marked with an asterisk; -it is possible for these entries to be invalid. .Pp With arguments, the .Ic hash diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c index 362a405..82941af 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c @@ -704,7 +704,9 @@ dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class) return; ASSERT(error == 0); - if ((count = ddt_object_count(ddt, type, class)) == 0) + error = ddt_object_count(ddt, type, class, &count); + ASSERT(error == 0); + if (count == 0) return; dspace = doi.doi_physical_blocks_512 << 9; diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c index 560bacd..6af5f77 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c @@ -150,6 +150,16 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t)) return (B_TRUE); } + /* + * Check any L2 cache devs + */ + if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child, + &children) == 0) { + for (c = 0; c < children; c++) + if (find_vdev_problem(child[c], func)) + return (B_TRUE); + } + return (B_FALSE); } diff --git a/contrib/file/Magdir/lua b/contrib/file/Magdir/lua index 61e69a6..fbb9f09 100644 --- a/contrib/file/Magdir/lua +++ b/contrib/file/Magdir/lua @@ -19,3 +19,4 @@ 0 string \033Lua Lua bytecode, >4 byte 0x50 version 5.0 >4 byte 0x51 version 5.1 +>4 byte 0x52 version 5.2 diff --git a/contrib/gcc/config/arm/freebsd.h b/contrib/gcc/config/arm/freebsd.h index da7ffab..0f7f38a 100644 --- a/contrib/gcc/config/arm/freebsd.h +++ b/contrib/gcc/config/arm/freebsd.h @@ -97,7 +97,7 @@ #define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)"); #else #undef SUBTARGET_CPU_DEFAULT -#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm +#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9 #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)"); #endif diff --git a/contrib/gcc/unwind-dw2.c b/contrib/gcc/unwind-dw2.c index 62c9d09..3306e06 100644 --- a/contrib/gcc/unwind-dw2.c +++ b/contrib/gcc/unwind-dw2.c @@ -1438,6 +1438,17 @@ uw_init_context_1 (struct _Unwind_Context *context, context->ra = __builtin_extract_return_addr (outer_ra); } +#if defined(__clang__) && defined(__amd64__) +/* Some versions of clang don't save and restore all callee registers, if a + __builtin_eh_return() intrinsic is used in a function. This is particularly + bad on amd64. For now, use the following ugly hack to force it to assume + those registers are clobbered, when invoking __builtin_eh_return(), so it + will emit code to save and restore them. */ +#define CLOBBER_REGS_HACK \ + __asm __volatile(" " : : : "r15", "r14", "r13", "r12", "rbx", "rdx", "rax"); +#else +#define CLOBBER_REGS_HACK +#endif /* __clang__ */ /* Install TARGET into CURRENT so that we can return to it. This is a macro because __builtin_eh_return must be invoked in the context of @@ -1448,6 +1459,7 @@ uw_init_context_1 (struct _Unwind_Context *context, { \ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ + CLOBBER_REGS_HACK \ __builtin_eh_return (offset, handler); \ } \ while (0) diff --git a/contrib/libcxxrt/atomic.h b/contrib/libcxxrt/atomic.h new file mode 100644 index 0000000..53aa26f --- /dev/null +++ b/contrib/libcxxrt/atomic.h @@ -0,0 +1,29 @@ + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +/** + * Swap macro that enforces a happens-before relationship with a corresponding + * ATOMIC_LOAD. + */ +#if __has_feature(cxx_atomic) +#define ATOMIC_SWAP(addr, val)\ + __c11_atomic_exchange((_Atomic(__typeof__(val))*)addr, val, __ATOMIC_ACQ_REL) +#elif __has_builtin(__sync_swap) +#define ATOMIC_SWAP(addr, val)\ + __sync_swap(addr, val) +#else +#define ATOMIC_SWAP(addr, val)\ + __sync_lock_test_and_set(addr, val) +#endif + +#if __has_feature(cxx_atomic) +#define ATOMIC_LOAD(addr)\ + __c11_atomic_load((_Atomic(__typeof__(*addr))*)addr, __ATOMIC_ACQUIRE) +#else +#define ATOMIC_LOAD(addr)\ + (__sync_synchronize(), *addr) +#endif diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc index fe56297..0cb2535 100644 --- a/contrib/libcxxrt/exception.cc +++ b/contrib/libcxxrt/exception.cc @@ -32,6 +32,7 @@ #include <pthread.h> #include "typeinfo.h" #include "dwarf_eh.h" +#include "atomic.h" #include "cxxabi.h" #pragma weak pthread_key_create @@ -155,6 +156,17 @@ struct __cxa_thread_info */ _Unwind_Exception *currentCleanup; /** + * Our state with respect to foreign exceptions. Usually none, set to + * caught if we have just caught an exception and rethrown if we are + * rethrowing it. + */ + enum + { + none, + caught, + rethrown + } foreign_exception_state; + /** * The public part of this structure, accessible from outside of this * module. */ @@ -308,7 +320,16 @@ static void thread_cleanup(void* thread_info) __cxa_thread_info *info = (__cxa_thread_info*)thread_info; if (info->globals.caughtExceptions) { - free_exception_list(info->globals.caughtExceptions); + // If this is a foreign exception, ask it to clean itself up. + if (info->foreign_exception_state != __cxa_thread_info::none) + { + _Unwind_Exception *e = (_Unwind_Exception*)info->globals.caughtExceptions; + e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); + } + else + { + free_exception_list(info->globals.caughtExceptions); + } } free(thread_info); } @@ -780,7 +801,8 @@ extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception) */ extern "C" void __cxa_rethrow() { - __cxa_eh_globals *globals = __cxa_get_globals(); + __cxa_thread_info *ti = thread_info_fast(); + __cxa_eh_globals *globals = &ti->globals; // Note: We don't remove this from the caught list here, because // __cxa_end_catch will be called when we unwind out of the try block. We // could probably make this faster by providing an alternative rethrow @@ -795,6 +817,15 @@ extern "C" void __cxa_rethrow() std::terminate(); } + if (ti->foreign_exception_state != __cxa_thread_info::none) + { + ti->foreign_exception_state = __cxa_thread_info::rethrown; + _Unwind_Exception *e = (_Unwind_Exception*)ex; + _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e); + report_failure(err, ex); + return; + } + assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!"); // ex->handlerCount will be decremented in __cxa_end_catch in enclosing @@ -848,9 +879,9 @@ static bool check_type_signature(__cxa_exception *ex, void *&adjustedPtr) { void *exception_ptr = (void*)(ex+1); - const std::type_info *ex_type = ex->exceptionType; + const std::type_info *ex_type = ex ? ex->exceptionType : 0; - bool is_ptr = ex_type->__is_pointer_p(); + bool is_ptr = ex ? ex_type->__is_pointer_p() : false; if (is_ptr) { exception_ptr = *(void**)exception_ptr; @@ -911,8 +942,8 @@ static handler_type check_action_record(_Unwind_Context *context, action_record = displacement ? action_record_offset_base + displacement : 0; // We only check handler types for C++ exceptions - foreign exceptions - // are only allowed for cleanup. - if (filter > 0 && 0 != ex) + // are only allowed for cleanups and catchalls. + if (filter > 0) { std::type_info *handler_type = get_type_info_entry(context, lsda, filter); if (check_type_signature(ex, handler_type, adjustedPtr)) @@ -1133,8 +1164,10 @@ extern "C" void *__cxa_begin_catch(void *e) throw() extern "C" void *__cxa_begin_catch(void *e) #endif { - // Decrement the uncaught exceptions count - __cxa_eh_globals *globals = __cxa_get_globals(); + // We can't call the fast version here, because if the first exception that + // we see is a foreign exception then we won't have called it yet. + __cxa_thread_info *ti = thread_info(); + __cxa_eh_globals *globals = &ti->globals; globals->uncaughtExceptions--; _Unwind_Exception *exceptionObject = (_Unwind_Exception*)e; @@ -1177,9 +1210,22 @@ extern "C" void *__cxa_begin_catch(void *e) { ex->handlerCount++; } + ti->foreign_exception_state = __cxa_thread_info::none; return ex->adjustedPtr; } + else + { + // If this is a foreign exception, then we need to be able to + // store it. We can't chain foreign exceptions, so we give up + // if there are already some outstanding ones. + if (globals->caughtExceptions != 0) + { + std::terminate(); + } + globals->caughtExceptions = (__cxa_exception*)exceptionObject; + ti->foreign_exception_state = __cxa_thread_info::caught; + } // exceptionObject is the pointer to the _Unwind_Exception within the // __cxa_exception. The throw object is after this return ((char*)exceptionObject + sizeof(_Unwind_Exception)); @@ -1195,10 +1241,23 @@ extern "C" void __cxa_end_catch() { // We can call the fast version here because the slow version is called in // __cxa_throw(), which must have been called before we end a catch block - __cxa_eh_globals *globals = __cxa_get_globals_fast(); + __cxa_thread_info *ti = thread_info_fast(); + __cxa_eh_globals *globals = &ti->globals; __cxa_exception *ex = globals->caughtExceptions; assert(0 != ex && "Ending catch when no exception is on the stack!"); + + if (ti->foreign_exception_state != __cxa_thread_info::none) + { + globals->caughtExceptions = 0; + if (ti->foreign_exception_state != __cxa_thread_info::rethrown) + { + _Unwind_Exception *e = (_Unwind_Exception*)ti->globals.caughtExceptions; + e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); + } + ti->foreign_exception_state = __cxa_thread_info::none; + return; + } bool deleteException = true; @@ -1328,7 +1387,7 @@ namespace std { if (thread_local_handlers) { return pathscale::set_unexpected(f); } - return __sync_lock_test_and_set(&unexpectedHandler, f); + return ATOMIC_SWAP(&terminateHandler, f); } /** * Sets the function that is called to terminate the program. @@ -1336,7 +1395,8 @@ namespace std terminate_handler set_terminate(terminate_handler f) throw() { if (thread_local_handlers) { return pathscale::set_terminate(f); } - return __sync_lock_test_and_set(&terminateHandler, f); + + return ATOMIC_SWAP(&terminateHandler, f); } /** * Terminates the program, calling a custom terminate implementation if @@ -1390,7 +1450,7 @@ namespace std { return info->unexpectedHandler; } - return unexpectedHandler; + return ATOMIC_LOAD(&unexpectedHandler); } /** * Returns the current terminate handler. @@ -1402,7 +1462,7 @@ namespace std { return info->terminateHandler; } - return terminateHandler; + return ATOMIC_LOAD(&terminateHandler); } } #ifdef __arm__ diff --git a/contrib/libcxxrt/memory.cc b/contrib/libcxxrt/memory.cc index bd7fd22..cc879e0 100644 --- a/contrib/libcxxrt/memory.cc +++ b/contrib/libcxxrt/memory.cc @@ -36,14 +36,8 @@ #include <stddef.h> #include <stdlib.h> #include "stdexcept.h" +#include "atomic.h" -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#if !__has_builtin(__sync_swap) -#define __sync_swap __sync_lock_test_and_set -#endif namespace std { @@ -67,7 +61,12 @@ namespace std __attribute__((weak)) new_handler set_new_handler(new_handler handler) { - return __sync_swap(&new_handl, handler); + return ATOMIC_SWAP(&new_handl, handler); + } + __attribute__((weak)) + new_handler get_new_handler(void) + { + return ATOMIC_LOAD(&new_handl); } } @@ -75,12 +74,17 @@ namespace std __attribute__((weak)) void* operator new(size_t size) { + if (0 == size) + { + size = 1; + } void * mem = malloc(size); while (0 == mem) { - if (0 != new_handl) + new_handler h = std::get_new_handler(); + if (0 != h) { - new_handl(); + h(); } else { @@ -95,14 +99,19 @@ void* operator new(size_t size) __attribute__((weak)) void* operator new(size_t size, const std::nothrow_t &) throw() { + if (0 == size) + { + size = 1; + } void *mem = malloc(size); while (0 == mem) { - if (0 != new_handl) + new_handler h = std::get_new_handler(); + if (0 != h) { try { - new_handl(); + h(); } catch (...) { diff --git a/contrib/libcxxrt/typeinfo.h b/contrib/libcxxrt/typeinfo.h index 8223977..a8a1a98 100644 --- a/contrib/libcxxrt/typeinfo.h +++ b/contrib/libcxxrt/typeinfo.h @@ -70,6 +70,14 @@ namespace std */ public: /** + * Returns true if this is some pointer type, false otherwise. + */ + virtual bool __is_pointer_p() const { return false; } + /** + * Returns true if this is some function type, false otherwise. + */ + virtual bool __is_function_p() const { return false; } + /** * Catch function. Allows external libraries to implement * their own basic types. This is used, for example, in the * GNUstep Objective-C runtime to allow Objective-C types to be @@ -95,14 +103,6 @@ namespace std { return false; } - /** - * Returns true if this is some pointer type, false otherwise. - */ - virtual bool __is_pointer_p() const { return false; } - /** - * Returns true if this is some function type, false otherwise. - */ - virtual bool __is_function_p() const { return false; } }; } @@ -284,7 +284,6 @@ namespace ABI_NAMESPACE /** Pointer is a pointer to a member of an incomplete class. */ __incomplete_class_mask = 0x10 }; - virtual bool __is_pointer_p() const { return true; } virtual bool __do_catch(const type_info *thrown_type, void **thrown_object, unsigned outer) const; @@ -296,6 +295,7 @@ namespace ABI_NAMESPACE struct __pointer_type_info : public __pbase_type_info { virtual ~__pointer_type_info(); + virtual bool __is_pointer_p() const { return true; } }; /** diff --git a/etc/Makefile b/etc/Makefile index c18908f..dc5f1af 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -291,25 +291,27 @@ distribution: ${DESTDIR}/etc/nsswitch.conf .endif +MTREE_CMD?= mtree + distrib-dirs: - mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.root.dist -p ${DESTDIR}/ - mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.var.dist -p ${DESTDIR}/var - mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.usr.dist -p ${DESTDIR}/usr - mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.include.dist \ + ${MTREE_CMD} -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.root.dist -p ${DESTDIR}/ + ${MTREE_CMD} -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.var.dist -p ${DESTDIR}/var + ${MTREE_CMD} -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.usr.dist -p ${DESTDIR}/usr + ${MTREE_CMD} -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.include.dist \ -p ${DESTDIR}/usr/include .if ${MK_BIND_LIBS} != "no" - mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.include.dist \ + ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.include.dist \ -p ${DESTDIR}/usr/include .endif .if ${MK_BIND_MTREE} != "no" - mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.chroot.dist \ + ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.chroot.dist \ -p ${DESTDIR}/var/named .endif .if ${MK_GROFF} != "no" - mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.groff.dist -p ${DESTDIR}/usr + ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.groff.dist -p ${DESTDIR}/usr .endif .if ${MK_SENDMAIL} != "no" - mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.sendmail.dist -p ${DESTDIR}/ + ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.sendmail.dist -p ${DESTDIR}/ .endif cd ${DESTDIR}/; rm -f ${DESTDIR}/sys; ln -s usr/src/sys sys cd ${DESTDIR}/usr/share/man/en.ISO8859-1; ln -sf ../man* . diff --git a/etc/rc.subr b/etc/rc.subr index 053f89a..9bff68b 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -290,7 +290,7 @@ _find_processes() _interpbn=${1##*/} _fp_args='_argv' _fp_match='case "$_argv" in - ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)' + ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)' else # a normal daemon _procnamebn=${_procname##*/} _fp_args='_arg0 _argv' diff --git a/include/time.h b/include/time.h index 6c9e7a9..14d6044 100644 --- a/include/time.h +++ b/include/time.h @@ -112,6 +112,7 @@ typedef __pid_t pid_t; #define CLOCK_MONOTONIC_FAST 12 /* FreeBSD-specific. */ #define CLOCK_SECOND 13 /* FreeBSD-specific. */ #define CLOCK_THREAD_CPUTIME_ID 14 +#define CLOCK_PROCESS_CPUTIME_ID 15 #endif /* !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112 */ #if !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112 diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index abface8..0bbbb33 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -40,6 +40,7 @@ SRCS+= __getosreldate.c __xuname.c \ SRCS+= pwcache.c pwcache.h .PATH: ${.CURDIR}/../../contrib/libc-vis +CFLAGS+= -I${.CURDIR}/../../contrib/libc-vis SRCS+= unvis.c vis.c MISRCS+=modf.c diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 0c6f48e..4cbf07c 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -298,6 +298,8 @@ FBSD_1.0 { ualarm; ulimit; uname; + strunvis; + strunvisx; usleep; utime; valloc; @@ -391,8 +393,6 @@ FBSD_1.3 { snvis; strnunvis; strnunvisx; - strunvis; - strunvisx; strnvis; strnvisx; strsnvis; diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c index 0031f46..f360162 100644 --- a/lib/libc/net/name6.c +++ b/lib/libc/net/name6.c @@ -200,6 +200,7 @@ static struct hostent *_hpmapv6(struct hostent *, int *); #endif static struct hostent *_hpsort(struct hostent *, res_state); +#ifdef INET6 static struct hostent *_hpreorder(struct hostent *); static int get_addrselectpolicy(struct policyhead *); static void free_addrselectpolicy(struct policyhead *); @@ -209,6 +210,7 @@ static void set_source(struct hp_order *, struct policyhead *); static int matchlen(struct sockaddr *, struct sockaddr *); static int comp_dst(const void *, const void *); static int gai_addr2scopetype(struct sockaddr *); +#endif /* * Functions defined in RFC2553 @@ -285,8 +287,10 @@ getipnodebyname(const char *name, int af, int flags, int *errp) hp = gethostbyname2(name, af); hp = _hpcopy(hp, errp); - #ifdef INET6 + if (af == AF_INET6) + hp = _hpreorder(hp); + if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) && MAPADDRENABLED(flags)) { struct hostent *hp2 = gethostbyname2(name, AF_INET); @@ -309,7 +313,7 @@ getipnodebyname(const char *name, int af, int flags, int *errp) *errp = statp->res_h_errno; statp->options = options; - return _hpreorder(_hpsort(hp, statp)); + return _hpsort(hp, statp); } struct hostent * @@ -632,6 +636,7 @@ _hpsort(struct hostent *hp, res_state statp) return hp; } +#ifdef INET6 /* * _hpreorder: sort address by default address selection */ @@ -1109,3 +1114,4 @@ gai_addr2scopetype(struct sockaddr *sa) return(-1); } } +#endif diff --git a/lib/libc/sys/chroot.2 b/lib/libc/sys/chroot.2 index 060d064..36d0364 100644 --- a/lib/libc/sys/chroot.2 +++ b/lib/libc/sys/chroot.2 @@ -92,12 +92,8 @@ system call. Any other value for .Ql kern.chroot_allow_open_directories will bypass the check for open directories -.Pp -Upon successful completion, a value of 0 is returned. -Otherwise, -a value of -1 is returned and -.Va errno -is set to indicate an error. +.Sh RETURN VALUES +.Rv -std .Sh ERRORS The .Fn chroot diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 index fe58321..33f7666 100644 --- a/lib/libedit/editline.3 +++ b/lib/libedit/editline.3 @@ -526,8 +526,6 @@ If is .Dv NULL , try -.Pa $PWD/.editrc -then .Pa $HOME/.editrc . Refer to .Xr editrc 5 diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5 index f46b874..6e04ea1 100644 --- a/lib/libedit/editrc.5 +++ b/lib/libedit/editrc.5 @@ -473,6 +473,13 @@ Move down one line. Editline extended command. .El .\" End of section automatically generated with makelist +.Sh FILES +.Bl -tag -width "~/.editrcXXX" +.It Pa ~/.editrc +User configuration file for the +.Xr editline 3 +library. +.El .Sh SEE ALSO .Xr editline 3 , .Xr regex 3 , diff --git a/lib/libradius/libradius.3 b/lib/libradius/libradius.3 index 253659c..f3ff700 100644 --- a/lib/libradius/libradius.3 +++ b/lib/libradius/libradius.3 @@ -38,7 +38,7 @@ .Ft int .Fn rad_add_server "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" .Ft int -.Fn rad_add_server_ex "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" "int dead_time" "struct in_addr bindto" +.Fn rad_add_server_ex "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" "int dead_time" "struct in_addr *bindto" .Ft "struct rad_handle *" .Fn rad_auth_open "void" .Ft void diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c index acb9767..3f7e199 100644 --- a/lib/libutil/gr_util.c +++ b/lib/libutil/gr_util.c @@ -50,8 +50,6 @@ static char group_file[PATH_MAX]; static char tempname[PATH_MAX]; static int initialized; -static const char group_line_format[] = "%s:%s:%ju:"; - /* * Initialize statics */ @@ -318,7 +316,7 @@ gr_mkdb(void) } /* - * Clean up. Preserver errno for the caller's convenience. + * Clean up. Preserves errno for the caller's convenience. */ void gr_fini(void) @@ -346,7 +344,6 @@ gr_equal(const struct group *gr1, const struct group *gr2) { int gr1_ndx; int gr2_ndx; - bool found; /* Check that the non-member information is the same. */ if (gr1->gr_name == NULL || gr2->gr_name == NULL) { @@ -367,17 +364,15 @@ gr_equal(const struct group *gr1, const struct group *gr2) if (gr1->gr_mem != gr2->gr_mem) return (false); } else { - for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; - gr1_ndx++) { - for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL; - gr2_ndx++) + for (gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++) { + for (gr2_ndx = 0;; gr2_ndx++) { + if (gr2->gr_mem[gr2_ndx] == NULL) + return (false); if (strcmp(gr1->gr_mem[gr1_ndx], gr2->gr_mem[gr2_ndx]) == 0) { - found = true; break; } - if (!found) - return (false); + } } /* Check that group2 does not have more members than group1. */ @@ -394,7 +389,10 @@ gr_equal(const struct group *gr1, const struct group *gr2) char * gr_make(const struct group *gr) { + const char *group_line_format = "%s:%s:%ju:"; + const char *sep; char *line; + char *p; size_t line_size; int ndx; @@ -409,16 +407,18 @@ gr_make(const struct group *gr) } /* Create the group line and fill it. */ - if ((line = malloc(line_size)) == NULL) + if ((line = p = malloc(line_size)) == NULL) return (NULL); - snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd, + p += sprintf(p, group_line_format, gr->gr_name, gr->gr_passwd, (uintmax_t)gr->gr_gid); - if (gr->gr_mem != NULL) + if (gr->gr_mem != NULL) { + sep = ""; for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { - strcat(line, gr->gr_mem[ndx]); - if (gr->gr_mem[ndx + 1] != NULL) - strcat(line, ","); + p = stpcpy(p, sep); + p = stpcpy(p, gr->gr_mem[ndx]); + sep = ","; } + } return (line); } diff --git a/release/generate-release.sh b/release/generate-release.sh index e0baff8..b60276a 100755 --- a/release/generate-release.sh +++ b/release/generate-release.sh @@ -160,7 +160,7 @@ build_docports() { # Could not install textproc/docproj from pkg(8) or pkg_add(1). Build # the port as final fallback. - chroot ${CHROOTDIR} /bin/sh -c 'make -C /usr/ports/textproc/docproj BATCH=yes WITH_JADETEX=no WITHOUT_X11=yes WITHOUT_PYTHON=yes install clean' || \ + chroot ${CHROOTDIR} /bin/sh -c 'make -C /usr/ports/textproc/docproj BATCH=yes WITHOUT_SVN=yes WITH_JADETEX=no WITHOUT_X11=yes WITHOUT_PYTHON=yes install clean' || \ { echo "*** Could not build the textproj/docproj port. Exiting."; exit 2; } } diff --git a/release/ia64/mkisoimages.sh b/release/ia64/mkisoimages.sh index d4a0802..55b1640 100644 --- a/release/ia64/mkisoimages.sh +++ b/release/ia64/mkisoimages.sh @@ -63,6 +63,7 @@ if [ $bootable = yes ]; then if [ -s $BASE/boot/mfsroot.gz ]; then cp $BASE/boot/mfsroot.gz $MNT/boot fi + cp $BASE/boot/color.4th $MNT/boot cp $BASE/boot/support.4th $MNT/boot cp $BASE/boot/check-password.4th $MNT/boot cp $BASE/boot/screen.4th $MNT/boot diff --git a/sbin/geom/class/raid3/geom_raid3.c b/sbin/geom/class/raid3/geom_raid3.c index 3f037cd..cd0aa65 100644 --- a/sbin/geom/class/raid3/geom_raid3.c +++ b/sbin/geom/class/raid3/geom_raid3.c @@ -76,7 +76,7 @@ struct g_command class_commands[] = { { "insert", G_FLAG_VERBOSE, NULL, { { 'h', "hardcode", NULL, G_TYPE_BOOL }, - { 'n', "number", NULL, G_TYPE_NUMBER }, + { 'n', "number", G_VAL_OPTIONAL, G_TYPE_NUMBER }, G_OPT_SENTINEL }, "[-hv] <-n number> name prov" diff --git a/sbin/geom/class/raid3/graid3.8 b/sbin/geom/class/raid3/graid3.8 index f396cc3..a82d388 100644 --- a/sbin/geom/class/raid3/graid3.8 +++ b/sbin/geom/class/raid3/graid3.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 5, 2010 +.Dd January 15, 2012 .Dt GRAID3 8 .Os .Sh NAME @@ -53,7 +53,7 @@ .Nm .Cm insert .Op Fl hv -.Fl n Ar number +.Op Fl n Ar number .Ar name .Ar prov .Nm @@ -171,6 +171,8 @@ Add the given component to the existing array, if one of the components was removed previously with the .Cm remove command or if one component is missing and will not be connected again. +If no number is given, new component will be added instead of first missed +component. .Pp Additional options include: .Bl -tag -width ".Fl h" diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index 5911a94..b4db0f1 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -473,6 +473,8 @@ static struct cmd inet6_cmds[] = { DEF_CMD("-nud", -ND6_IFF_PERFORMNUD, setnd6flags), DEF_CMD("auto_linklocal",ND6_IFF_AUTO_LINKLOCAL,setnd6flags), DEF_CMD("-auto_linklocal",-ND6_IFF_AUTO_LINKLOCAL,setnd6flags), + DEF_CMD("no_prefer_iface",ND6_IFF_NO_PREFER_IFACE,setnd6flags), + DEF_CMD("-no_prefer_iface",-ND6_IFF_NO_PREFER_IFACE,setnd6flags), DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index 80065f6..5c46452 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -58,7 +58,7 @@ static const char rcsid[] = #define MAX_SYSCTL_TRY 5 #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ - "\007NO_RADR\020DEFAULTIF" + "\007NO_RADR\010NO_PREFER_IFACE\020DEFAULTIF" static int isnd6defif(int); void setnd6flags(const char *, int, int, const struct afswtch *); diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index f4c6daa..9c74980 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd November 7, 2012 +.Dd January 10, 2013 .Dt IFCONFIG 8 .Os .Sh NAME @@ -716,6 +716,13 @@ Set a flag to enable Neighbor Unreachability Detection. .It Cm -nud Clear a flag .Cm nud . +.It Cm no_prefer_iface +Set a flag to not prefer address on the interface as candidates of the +source address for outgoing packets, even when the interface is +outgoing interface. +.It Cm -no_prefer_iface +Clear a flag +.Cm no_prefer_iface . .El .Pp The following parameters are specific to cloning diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile index 03c2ea2..e2c93cc 100644 --- a/sbin/setkey/Makefile +++ b/sbin/setkey/Makefile @@ -61,7 +61,7 @@ CLEANFILES+= scriptdump y.tab.h #SCRIPTS= scriptdump -LOCALPREFIX= /usr +LOCALPREFIX= /usr/local scriptdump: scriptdump.pl sed -e 's#@LOCALPREFIX@#${LOCALPREFIX}#' < $> > scriptdump diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index 8fad089..43592b3 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -266,7 +266,7 @@ parse(const char *string, int lineno) if (!(kind & CTLFLAG_WR)) { if (kind & CTLFLAG_TUN) { - warnx("oid '%s' is a read only tunable%p", bufp, line); + warnx("oid '%s' is a read only tunable%s", bufp, line); warnx("Tunable values are set in /boot/loader.conf"); } else warnx("oid '%s' is read only%s", bufp, line); diff --git a/share/man/man4/rl.4 b/share/man/man4/rl.4 index 4cbf6e9..583274b 100644 --- a/share/man/man4/rl.4 +++ b/share/man/man4/rl.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 22, 2010 +.Dd January 16, 2013 .Dt RL 4 .Os .Sh NAME @@ -155,6 +155,8 @@ Corega FEther CB-TXD .It Corega FEtherII CB-TXD .It +D-Link DFE-520TX (rev. C1) +.It D-Link DFE-528TX .It D-Link DFE-530TX+ diff --git a/share/man/man4/stf.4 b/share/man/man4/stf.4 index 5e32763..5e210df 100644 --- a/share/man/man4/stf.4 +++ b/share/man/man4/stf.4 @@ -190,8 +190,8 @@ The default value is shown next to each variable. .It Va net.link.stf.permit_rfc1918 : No 0 The RFC3056 requires the use of globally unique 32-bit IPv4 addresses. This sysctl variable controls the behaviour of this -requirement. When it set to not 0, -.Nm stf +requirement. When it set to not 0, +.Nm stf allows the use of private IPv4 addresses described in the RFC1918. This may be useful for an Intranet environment or when some mechanisms of network address translation (NAT) are used. diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index faa117f..4bf8c35 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,7 +1,7 @@ .\" DO NOT EDIT-- this file is automatically generated. .\" from FreeBSD: head/tools/build/options/makeman 236279 2012-05-30 02:37:20Z gjb .\" $FreeBSD$ -.Dd November 5, 2012 +.Dd January 14, 2013 .Dt SRC.CONF 5 .Os .Sh NAME @@ -804,6 +804,16 @@ Set to not build NLS catalogs. .\" from FreeBSD: head/tools/build/options/WITHOUT_NLS_CATALOGS 156932 2006-03-21 07:50:50Z ru Set to not build NLS catalog support for .Xr csh 1 . +.It Va WITH_NMTREE +.\" from FreeBSD: head/tools/build/options/WITH_NMTREE 245241 2013-01-09 21:07:08Z brooks +Set to install +.Xr nmtree 8 +as +.Xr mtree 8 . +By default +.Xr fmtree 8 +is installed as +.Xr mtree 8 . .It Va WITHOUT_NS_CACHING .\" from FreeBSD: head/tools/build/options/WITHOUT_NS_CACHING 172803 2007-10-19 14:01:25Z ru Set to disable name caching in the diff --git a/share/man/man9/vm_map_insert.9 b/share/man/man9/vm_map_insert.9 index 3a6a51f..8f3b52e 100644 --- a/share/man/man9/vm_map_insert.9 +++ b/share/man/man9/vm_map_insert.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd January 11, 2013 .Dt VM_MAP_INSERT 9 .Os .Sh NAME @@ -73,9 +73,6 @@ This function implicitly creates a new .Vt vm_map_entry by calling the internal function .Fn vm_map_entry_create . -This function may use the -.Va Giant -lock to ensure that only a single thread is present in the function. .Sh RETURN VALUES The .Fn vm_map_insert diff --git a/share/man/man9/vm_map_stack.9 b/share/man/man9/vm_map_stack.9 index dabe937..e237c06 100644 --- a/share/man/man9/vm_map_stack.9 +++ b/share/man/man9/vm_map_stack.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd January 11, 2013 .Dt VM_MAP_STACK 9 .Os .Sh NAME @@ -81,11 +81,11 @@ function calls to create its mappings. .Pp The +.Fn vm_map_stack +and .Fn vm_map_growstack -function acquires the -.Va Giant -lock, and the process lock on -.Fa p , +functions acquire the process lock on +.Fa p for the duration of the call. .Sh RETURN VALUES The diff --git a/share/misc/committers-doc.dot b/share/misc/committers-doc.dot index 0d896b3..35286e3 100644 --- a/share/misc/committers-doc.dot +++ b/share/misc/committers-doc.dot @@ -116,6 +116,7 @@ gabor -> issyl0 gabor -> ebrandi gjb -> wblock +gjb -> rene hrs -> ryusuke diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot index af20fc0..cf48d6a 100644 --- a/share/misc/committers-ports.dot +++ b/share/misc/committers-ports.dot @@ -77,6 +77,7 @@ culot [label="Frederic Culot\nculot@FreeBSD.org\n2010/10/16"] daichi [label="Daichi Goto\ndaichi@FreeBSD.org\n2002/10/17"] danfe [label="Alexey Dokuchaev\ndanfe@FreeBSD.org\n2004/08/20"] db [label="Diane Bruce\ndb@FreeBSD.org\n2007/01/18"] +dbn [label="David Naylor\ndbn@FreeBSD.org\n2013/01/14"] decke [label="Bernhard Froehlich\ndecke@FreeBSD.org\n2010/03/21"] delphij [label="Xin Li\ndelphij@FreeBSD.org\n2006/05/01"] demon [label="Dmitry Sivachenko\ndemon@FreeBSD.org\n2000/11/13"] @@ -233,6 +234,8 @@ asami -> obrien avilla -> jhale avilla -> rakuco +bdrewery -> dbn + bapt -> bdrewery bapt -> eadler bapt -> jlaffaye @@ -274,6 +277,7 @@ delphij -> rafan demon -> mat eadler -> ak +eadler -> dbn eadler -> bdrewery eadler -> gjb eadler -> tj diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index f3756e8..1361cc6 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -117,6 +117,7 @@ bruno [label="Bruno Ducrot\nbruno@FreeBSD.org\n2005/07/18"] bryanv [label="Bryan Venteicher\nbryanv@FreeBSD.org\n2012/11/03"] bschmidt [label="Bernhard Schmidt\nbschmidt@FreeBSD.org\n2010/02/06"] bz [label="Bjoern A. Zeeb\nbz@FreeBSD.org\n2004/07/27"] +carl [label="Carl Delsey\ncarl@FreeBSD.org\n2013/01/14"] cognet [label="Olivier Houchard\ncognet@FreeBSD.org\n2002/10/09"] cokane [label="Coleman Kane\ncokane@FreeBSD.org\n2000/06/19"] cperciva [label="Colin Percival\ncperciva@FreeBSD.org\n2004/01/20"] @@ -454,6 +455,8 @@ jhb -> peterj jhb -> pfg jhb -> rnoland +jimharris -> carl + jkh -> grog jkh -> imp jkh -> jlemon diff --git a/share/mk/Makefile b/share/mk/Makefile index 81f943c..2110b26 100644 --- a/share/mk/Makefile +++ b/share/mk/Makefile @@ -6,7 +6,6 @@ FILES= \ bsd.README \ bsd.arch.inc.mk \ - bsd.compat.mk \ bsd.compiler.mk \ bsd.cpu.mk \ bsd.crunchgen.mk \ diff --git a/share/mk/bsd.compat.mk b/share/mk/bsd.compat.mk deleted file mode 100644 index 6a86871..0000000 --- a/share/mk/bsd.compat.mk +++ /dev/null @@ -1,41 +0,0 @@ -# $FreeBSD$ - -.if !defined(BURN_BRIDGES) -.for oldnew in \ - NOATM:NO_ATM \ - NOCLEANDIR:NO_CLEANDIR \ - NOCRYPT:NO_CRYPT \ - NODOCCOMPRESS:NO_DOCCOMPRESS \ - NOEXTRADEPEND:NO_EXTRADEPEND \ - NOFORTH:NO_FORTH \ - NOFSCHG:NO_FSCHG \ - NOGAMES:NO_GAMES \ - NOHTML:NO_HTML \ - NOINET6:NO_INET6 \ - NOINFO:NO_INFO \ - NOINFOCOMPRESS:NO_INFOCOMPRESS \ - NOINSTALLLIB:NO_INSTALLLIB \ - NOLIBPTHREAD:NO_LIBPTHREAD \ - NOLIBTHR:NO_LIBTHR \ - NOLINT:NO_LINT \ - NOMAN:NO_MAN \ - NOMANCOMPRESS:NO_MANCOMPRESS \ - NOMLINKS:NO_MLINKS \ - NOOBJ:NO_OBJ \ - NOPAM:NO_PAM \ - NOPIC:NO_PIC \ - NOPROFILE:NO_PROFILE \ - NO_RCMNDS:NO_RCMDS \ - NOSHARE:NO_SHARE \ - NOSHARED:NO_SHARED \ - NOTAGS:NO_TAGS -.for old in ${oldnew:C/:.*//} -.for new in ${oldnew:C/.*://} -.if defined(${old}) && !defined(${new}) -.warning ${old} is deprecated in favour of ${new} -${new}= ${${old}} -.endif -.endfor -.endfor -.endfor -.endif diff --git a/share/mk/bsd.init.mk b/share/mk/bsd.init.mk index 72a6de0..f5f4c66 100644 --- a/share/mk/bsd.init.mk +++ b/share/mk/bsd.init.mk @@ -9,7 +9,6 @@ __<bsd.init.mk>__: .if exists(${.CURDIR}/../Makefile.inc) .include "${.CURDIR}/../Makefile.inc" .endif -.include <bsd.compat.mk> .include <bsd.own.mk> .MAIN: all .endif # !target(__<bsd.init.mk>__) diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index 78af8fb..24a0f92 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -216,80 +216,6 @@ WITHOUT_${var}= .endfor # -# Compat NO_* options (same as above, except their use is deprecated). -# -.if !defined(BURN_BRIDGES) -.for var in \ - ACPI \ - ATM \ - AUDIT \ - AUTHPF \ - BIND \ - BIND_DNSSEC \ - BIND_ETC \ - BIND_LIBS_LWRES \ - BIND_MTREE \ - BIND_NAMED \ - BIND_UTILS \ - BLUETOOTH \ - BOOT \ - CALENDAR \ - CPP \ - CRYPT \ - CVS \ - CXX \ - DICT \ - DYNAMICROOT \ - EXAMPLES \ - FORTH \ - FP_LIBC \ - GAMES \ - GCOV \ - GDB \ - GNU \ - GPIB \ - GROFF \ - HTML \ - INET6 \ - INFO \ - IPFILTER \ - IPX \ - KDUMP \ - KERBEROS \ - LIB32 \ - LIBPTHREAD \ - LIBTHR \ - LOCALES \ - LPR \ - MAILWRAPPER \ - NETCAT \ - NIS \ - NLS \ - NLS_CATALOGS \ - NS_CACHING \ - OPENSSH \ - OPENSSL \ - PAM \ - PF \ - RCMDS \ - RCS \ - RESCUE \ - SENDMAIL \ - SETUID_LOGIN \ - SHAREDOCS \ - SYSCONS \ - TCSH \ - TOOLCHAIN \ - USB \ - WPA_SUPPLICANT_EAPOL -.if defined(NO_${var}) -#.warning NO_${var} is deprecated in favour of WITHOUT_${var}= -WITHOUT_${var}= -.endif -.endfor -.endif # !defined(BURN_BRIDGES) - -# # Older-style variables that enabled behaviour when set. # .if defined(YES_HESIOD) @@ -431,6 +357,7 @@ __DEFAULT_NO_OPTIONS = \ ICONV \ IDEA \ INSTALL_AS_USER \ + NMTREE \ NAND \ OFED \ SHARED_TOOLCHAIN diff --git a/share/mk/sys.mk b/share/mk/sys.mk index 2f67903..8b8a5ce 100644 --- a/share/mk/sys.mk +++ b/share/mk/sys.mk @@ -346,5 +346,4 @@ OBJFORMAT?= elf .endif -.include <bsd.compat.mk> .include <bsd.cpu.mk> diff --git a/share/zoneinfo/Makefile b/share/zoneinfo/Makefile index 6de8ef5..bccea5e 100644 --- a/share/zoneinfo/Makefile +++ b/share/zoneinfo/Makefile @@ -29,6 +29,7 @@ # CLEANFILES+= yearistype +CLEANDIRS+= builddir CONTRIBDIR= ${.CURDIR}/../../contrib/tzdata/ .PATH: ${CONTRIBDIR} @@ -48,13 +49,39 @@ TZFILES+= backward systemv TZFILES:= ${TZFILES:S/^/${CONTRIBDIR}/} -all: yearistype +TZBUILDDIR= ${.OBJDIR}/builddir +TZBUILDSUBDIRS= \ + Africa \ + America/Argentina \ + America/Indiana \ + America/Kentucky \ + America/North_Dakota \ + Antarctica \ + Arctic \ + Asia \ + Atlantic \ + Australia \ + Etc \ + Europe \ + Indian \ + Pacific \ + SystemV -beforeinstall: +all: zoneinfo + +.PHONY: zoneinfo +zoneinfo: yearistype ${TDATA} + mkdir -p ${TZBUILDDIR} + cd ${TZBUILDDIR}; mkdir -p ${TZBUILDSUBDIRS} umask 022; cd ${.CURDIR}; \ - zic -D -d ${DESTDIR}/usr/share/zoneinfo -p ${POSIXRULES} \ - -u ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \ + zic -D -d ${TZBUILDDIR} -p ${POSIXRULES} -m ${NOBINMODE} \ ${LEAPFILE} -y ${.OBJDIR}/yearistype ${TZFILES} + +beforeinstall: + cd ${TZBUILDDIR} && \ + find . -type f -print -exec ${INSTALL} \ + -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \ + \{} ${DESTDIR}/usr/share/zoneinfo/\{} \; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \ ${CONTRIBDIR}/zone.tab ${DESTDIR}/usr/share/zoneinfo/ diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 48f41b3..e53f692 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -332,3 +332,11 @@ device snd_via8233 # VIA VT8233x Audio device mmc # MMC/SD bus device mmcsd # MMC/SD memory card device sdhci # Generic PCI SD Host Controller + +# VirtIO support +device virtio # Generic VirtIO bus (required) +device virtio_pci # VirtIO PCI device +device vtnet # VirtIO Ethernet device +device virtio_blk # VirtIO Block device +device virtio_scsi # VirtIO SCSI device +device virtio_balloon # VirtIO Memory Balloon device diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index 6562981..a4371f7 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -440,6 +440,15 @@ device safe # SafeNet 1141 options SAFE_DEBUG # enable debugging support: hw.safe.debug options SAFE_RNDTEST # enable rndtest support +# +# VirtIO support +device virtio # Generic VirtIO bus (required) +device virtio_pci # VirtIO PCI Interface +device vtnet # VirtIO Ethernet device +device virtio_blk # VirtIO Block device +device virtio_scsi # VirtIO SCSI device +device virtio_balloon # VirtIO Memory Balloon device + ##################################################################### # diff --git a/sys/arm/allwinner/a10_machdep.c b/sys/arm/allwinner/a10_machdep.c new file mode 100644 index 0000000..1ad9ea1 --- /dev/null +++ b/sys/arm/allwinner/a10_machdep.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c + */ + +#include "opt_ddb.h" +#include "opt_platform.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/bus.h> +#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */ +#include <machine/machdep.h> +#include <machine/pmap.h> + +#include <dev/fdt/fdt_common.h> + +/* Start of address space used for bootstrap map */ +#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000 + +void (*a10_cpu_reset)(void); + +vm_offset_t +initarm_lastaddr(void) +{ + + a10_cpu_reset = NULL; + return (DEVMAP_BOOTSTRAP_MAP_START - ARM_NOCACHE_KVA_SIZE); +} + +void +initarm_gpio_init(void) +{ +} + +void +initarm_late_init(void) +{ +} + +#define FDT_DEVMAP_MAX (1 + 2 + 1 + 1) +static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = { + { 0, 0, 0, 0, 0, } +}; + +/* + * Construct pmap_devmap[] with DT-derived config data. + */ +int +platform_devmap_init(void) +{ + int i = 0; + + fdt_devmap[i].pd_va = 0xE1C00000; + fdt_devmap[i].pd_pa = 0x01C00000; + fdt_devmap[i].pd_size = 0x00400000; /* 4 MB */ + fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE; + fdt_devmap[i].pd_cache = PTE_DEVICE; + + i++; + + pmap_devmap_bootstrap_table = &fdt_devmap[0]; + + return (0); +} + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + return (NULL); +} + +int +bus_dma_get_range_nb(void) +{ + return (0); +} + +void +cpu_reset() +{ + if (a10_cpu_reset) + (*a10_cpu_reset)(); + else + printf("no cpu_reset implementation\n"); + printf("Reset failed!\n"); + while (1); +} diff --git a/sys/arm/allwinner/aintc.c b/sys/arm/allwinner/aintc.c new file mode 100644 index 0000000..9416b9a --- /dev/null +++ b/sys/arm/allwinner/aintc.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +/** + * Interrupt controller registers + * + */ +#define SW_INT_VECTOR_REG 0x00 +#define SW_INT_BASE_ADR_REG 0x04 +#define SW_INT_PROTECTION_REG 0x08 +#define SW_INT_NMI_CTRL_REG 0x0c + +#define SW_INT_IRQ_PENDING_REG0 0x10 +#define SW_INT_IRQ_PENDING_REG1 0x14 +#define SW_INT_IRQ_PENDING_REG2 0x18 + +#define SW_INT_FIQ_PENDING_REG0 0x20 +#define SW_INT_FIQ_PENDING_REG1 0x24 +#define SW_INT_FIQ_PENDING_REG2 0x28 + +#define SW_INT_SELECT_REG0 0x30 +#define SW_INT_SELECT_REG1 0x34 +#define SW_INT_SELECT_REG2 0x38 + +#define SW_INT_ENABLE_REG0 0x40 +#define SW_INT_ENABLE_REG1 0x44 +#define SW_INT_ENABLE_REG2 0x48 + +#define SW_INT_MASK_REG0 0x50 +#define SW_INT_MASK_REG1 0x54 +#define SW_INT_MASK_REG2 0x58 + +#define SW_INT_IRQNO_ENMI 0 + +#define SW_INT_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4)) +#define SW_INT_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4)) +#define SW_INT_SELECT_REG(_b) (0x30 + ((_b) * 4)) +#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4)) +#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4)) + +struct a10_aintc_softc { + device_t sc_dev; + struct resource * aintc_res; + bus_space_tag_t aintc_bst; + bus_space_handle_t aintc_bsh; + uint8_t ver; +}; + +static struct a10_aintc_softc *a10_aintc_sc = NULL; + +#define aintc_read_4(reg) \ + bus_space_read_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg) +#define aintc_write_4(reg, val) \ + bus_space_write_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg, val) + +static int +a10_aintc_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "a10,aintc")) + return (ENXIO); + device_set_desc(dev, "A10 AINTC Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +a10_aintc_attach(device_t dev) +{ + struct a10_aintc_softc *sc = device_get_softc(dev); + int rid = 0; + int i; + + sc->sc_dev = dev; + + if (a10_aintc_sc) + return (ENXIO); + + sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (!sc->aintc_res) { + device_printf(dev, "could not allocate resource\n"); + return (ENXIO); + } + + sc->aintc_bst = rman_get_bustag(sc->aintc_res); + sc->aintc_bsh = rman_get_bushandle(sc->aintc_res); + + a10_aintc_sc = sc; + + /* Disable & clear all interrupts */ + for (i = 0; i < 3; i++) { + aintc_write_4(SW_INT_ENABLE_REG(i), 0); + aintc_write_4(SW_INT_MASK_REG(i), 0xffffffff); + } + /* enable protection mode*/ + aintc_write_4(SW_INT_PROTECTION_REG, 0x01); + + /* config the external interrupt source type*/ + aintc_write_4(SW_INT_NMI_CTRL_REG, 0x00); + + return (0); +} + +static device_method_t a10_aintc_methods[] = { + DEVMETHOD(device_probe, a10_aintc_probe), + DEVMETHOD(device_attach, a10_aintc_attach), + { 0, 0 } +}; + +static driver_t a10_aintc_driver = { + "aintc", + a10_aintc_methods, + sizeof(struct a10_aintc_softc), +}; + +static devclass_t a10_aintc_devclass; + +DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0); + +int +arm_get_next_irq(int last_irq) +{ + uint32_t value; + int i, b; + + for (i = 0; i < 3; i++) { + value = aintc_read_4(SW_INT_IRQ_PENDING_REG(i)); + for (b = 0; b < 32; b++) + if (value & (1 << b)) { + return (i * 32 + b); + } + } + + return (-1); +} + +void +arm_mask_irq(uintptr_t nb) +{ + uint32_t bit, block, value; + + bit = (nb % 32); + block = (nb / 32); + + value = aintc_read_4(SW_INT_ENABLE_REG(block)); + value &= ~(1 << bit); + aintc_write_4(SW_INT_ENABLE_REG(block), value); + + value = aintc_read_4(SW_INT_MASK_REG(block)); + value |= (1 << bit); + aintc_write_4(SW_INT_MASK_REG(block), value); +} + +void +arm_unmask_irq(uintptr_t nb) +{ + uint32_t bit, block, value; + + bit = (nb % 32); + block = (nb / 32); + + value = aintc_read_4(SW_INT_ENABLE_REG(block)); + value |= (1 << bit); + aintc_write_4(SW_INT_ENABLE_REG(block), value); + + value = aintc_read_4(SW_INT_MASK_REG(block)); + value &= ~(1 << bit); + aintc_write_4(SW_INT_MASK_REG(block), value); + + if(nb == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */ + aintc_write_4(SW_INT_IRQ_PENDING_REG(0), (1 << SW_INT_IRQNO_ENMI)); +} diff --git a/sys/arm/allwinner/bus_space.c b/sys/arm/allwinner/bus_space.c new file mode 100644 index 0000000..4cce820 --- /dev/null +++ b/sys/arm/allwinner/bus_space.c @@ -0,0 +1,113 @@ +/*- + * Copyright (C) 2012 FreeBSD Foundation + * 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 MARVELL nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(generic); +bs_protos(generic_armv4); + +struct bus_space _base_tag = { + /* cookie */ + .bs_cookie = (void *) 0, + + /* mapping/unmapping */ + .bs_map = generic_bs_map, + .bs_unmap = generic_bs_unmap, + .bs_subregion = generic_bs_subregion, + + /* allocation/deallocation */ + .bs_alloc = generic_bs_alloc, + .bs_free = generic_bs_free, + + /* barrier */ + .bs_barrier = generic_bs_barrier, + + /* read (single) */ + .bs_r_1 = generic_bs_r_1, + .bs_r_2 = generic_armv4_bs_r_2, + .bs_r_4 = generic_bs_r_4, + .bs_r_8 = NULL, + + /* read multiple */ + .bs_rm_1 = generic_bs_rm_1, + .bs_rm_2 = generic_armv4_bs_rm_2, + .bs_rm_4 = generic_bs_rm_4, + .bs_rm_8 = NULL, + + /* read region */ + .bs_rr_1 = generic_bs_rr_1, + .bs_rr_2 = generic_armv4_bs_rr_2, + .bs_rr_4 = generic_bs_rr_4, + .bs_rr_8 = NULL, + + /* write (single) */ + .bs_w_1 = generic_bs_w_1, + .bs_w_2 = generic_armv4_bs_w_2, + .bs_w_4 = generic_bs_w_4, + .bs_w_8 = NULL, + + /* write multiple */ + .bs_wm_1 = generic_bs_wm_1, + .bs_wm_2 = generic_armv4_bs_wm_2, + .bs_wm_4 = generic_bs_wm_4, + .bs_wm_8 = NULL, + + /* write region */ + .bs_wr_1 = generic_bs_wr_1, + .bs_wr_2 = generic_armv4_bs_wr_2, + .bs_wr_4 = generic_bs_wr_4, + .bs_wr_8 = NULL, + + /* set multiple */ + /* XXX not implemented */ + + /* set region */ + .bs_sr_1 = NULL, + .bs_sr_2 = generic_armv4_bs_sr_2, + .bs_sr_4 = generic_bs_sr_4, + .bs_sr_8 = NULL, + + /* copy */ + .bs_c_1 = NULL, + .bs_c_2 = generic_armv4_bs_c_2, + .bs_c_4 = NULL, + .bs_c_8 = NULL, +}; + +bus_space_tag_t fdtbus_bs_tag = &_base_tag; diff --git a/sys/arm/allwinner/common.c b/sys/arm/allwinner/common.c new file mode 100644 index 0000000..0b4e16a --- /dev/null +++ b/sys/arm/allwinner/common.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/vmparam.h> + +struct fdt_fixup_entry fdt_fixup_table[] = { + { NULL, NULL } +}; + +static int +fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, + int *pol) +{ + if (!fdt_is_compatible(node, "a10,aintc")) + return (ENXIO); + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + + return (0); +} + +fdt_pic_decode_t fdt_pic_table[] = { + &fdt_aintc_decode_ic, + NULL +}; diff --git a/sys/arm/allwinner/console.c b/sys/arm/allwinner/console.c new file mode 100644 index 0000000..52d7376 --- /dev/null +++ b/sys/arm/allwinner/console.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Simple UART console driver for Allwinner A10 */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/cons.h> +#include <sys/consio.h> +#include <sys/kernel.h> + +#ifndef A10_UART_BASE +#define A10_UART_BASE 0xe1c28000 /* UART0 */ +#endif + +#define REG_SHIFT 2 + +#define UART_DLL 0 /* Out: Divisor Latch Low */ +#define UART_DLM 1 /* Out: Divisor Latch High */ +#define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_LCR 3 /* Out: Line Control Register */ +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ +#define UART_MSR 6 /* In: Modem Status Register */ +#define UART_SCR 7 /* I/O: Scratch Register */ + +static uint32_t +uart_getreg(uint32_t *bas) +{ + return *((volatile uint32_t *)(bas)) & 0xff; +} + +static void +uart_setreg(uint32_t *bas, uint32_t val) +{ + *((volatile uint32_t *)(bas)) = val; +} + +static int +ub_getc(void) +{ + while ((uart_getreg((uint32_t *)(A10_UART_BASE + + (UART_LSR << REG_SHIFT))) & UART_LSR_DR) == 0); + __asm __volatile("nop"); + + return (uart_getreg((uint32_t *)A10_UART_BASE) & 0xff); +} + +static void +ub_putc(unsigned char c) +{ + if (c == '\n') + ub_putc('\r'); + + while ((uart_getreg((uint32_t *)(A10_UART_BASE + + (UART_LSR << REG_SHIFT))) & UART_LSR_THRE) == 0) + __asm __volatile("nop"); + + uart_setreg((uint32_t *)A10_UART_BASE, c); +} + +static cn_probe_t uart_cnprobe; +static cn_init_t uart_cninit; +static cn_term_t uart_cnterm; +static cn_getc_t uart_cngetc; +static cn_putc_t uart_cnputc; +static cn_grab_t uart_cngrab; +static cn_ungrab_t uart_cnungrab; + +static void +uart_cngrab(struct consdev *cp) +{ +} + +static void +uart_cnungrab(struct consdev *cp) +{ +} + + +static void +uart_cnprobe(struct consdev *cp) +{ + sprintf(cp->cn_name, "uart"); + cp->cn_pri = CN_NORMAL; +} + +static void +uart_cninit(struct consdev *cp) +{ + uart_setreg((uint32_t *)(A10_UART_BASE + + (UART_FCR << REG_SHIFT)), 0x06); +} + +void +uart_cnputc(struct consdev *cp, int c) +{ + ub_putc(c); +} + +int +uart_cngetc(struct consdev * cp) +{ + return ub_getc(); +} + +static void +uart_cnterm(struct consdev * cp) +{ +} + +CONSOLE_DRIVER(uart); + diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10 new file mode 100644 index 0000000..cb712d1 --- /dev/null +++ b/sys/arm/allwinner/files.a10 @@ -0,0 +1,17 @@ +# $FreeBSD$ +kern/kern_clocksource.c standard + +arm/arm/bus_space_asm_generic.S standard +arm/arm/bus_space_generic.c standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm10.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard + +arm/allwinner/timer.c standard +arm/allwinner/aintc.c standard +arm/allwinner/bus_space.c standard +arm/allwinner/common.c standard +arm/allwinner/console.c standard +arm/allwinner/a10_machdep.c standard diff --git a/sys/arm/allwinner/std.a10 b/sys/arm/allwinner/std.a10 new file mode 100644 index 0000000..f698b34 --- /dev/null +++ b/sys/arm/allwinner/std.a10 @@ -0,0 +1,21 @@ +# Allwinner A10 common options +#$FreeBSD$ + +cpu CPU_CORTEXA +machine arm armv6 +makeoption ARM_LITTLE_ENDIAN + +# Physical memory starts at 0x40200000. We assume images are loaded at +# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel' +# +# +options PHYSADDR=0x40000000 + +makeoptions KERNPHYSADDR=0x40200000 +options KERNPHYSADDR=0x40200000 +makeoptions KERNVIRTADDR=0xc0200000 +options KERNVIRTADDR=0xc0200000 + +options STARTUP_PAGETABLE_ADDR=0x48000000 + +files "../allwinner/files.a10" diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c new file mode 100644 index 0000000..3883ed1 --- /dev/null +++ b/sys/arm/allwinner/timer.c @@ -0,0 +1,341 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timeet.h> +#include <sys/timetc.h> +#include <sys/watchdog.h> +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <machine/intr.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <sys/kdb.h> + +/** + * Timer registers addr + * + */ +#define SW_TIMER_IRQ_EN_REG 0x00 +#define SW_TIMER_IRQ_STA_REG 0x04 +#define SW_TIMER0_CTRL_REG 0x10 +#define SW_TIMER0_INT_VALUE_REG 0x14 +#define SW_TIMER0_CUR_VALUE_REG 0x18 + +#define SYS_TIMER_SCAL 16 /* timer clock source pre-divsion */ +#define SYS_TIMER_CLKSRC 24000000 /* timer clock source */ +#define TMR_INTER_VAL SYS_TIMER_CLKSRC/(SYS_TIMER_SCAL * 1000) + +#define CLOCK_TICK_RATE TMR_INTER_VAL +#define INITIAL_TIMECOUNTER (0xffffffff) + +struct a10_timer_softc { + device_t sc_dev; + struct resource *res[2]; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + void *sc_ih; /* interrupt handler */ + uint32_t sc_period; + uint32_t clkfreq; + struct eventtimer et; +}; + +int a10_timer_get_timerfreq(struct a10_timer_softc *); + +#define timer_read_4(sc, reg) \ + bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg) +#define timer_write_4(sc, reg, val) \ + bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val) + +static u_int a10_timer_get_timecount(struct timecounter *); +static int a10_timer_timer_start(struct eventtimer *, + struct bintime *, struct bintime *); +static int a10_timer_timer_stop(struct eventtimer *); + +static int a10_timer_initialized = 0; +static int a10_timer_intr(void *); +static int a10_timer_probe(device_t); +static int a10_timer_attach(device_t); + +static struct timecounter a10_timer_timecounter = { + .tc_name = "a10_timer timer0", + .tc_get_timecount = a10_timer_get_timecount, + .tc_counter_mask = ~0u, + .tc_frequency = 0, + .tc_quality = 1000, +}; + +struct a10_timer_softc *a10_timer_sc = NULL; + +static struct resource_spec a10_timer_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +a10_timer_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "a10,timers")) + return (ENXIO); + + device_set_desc(dev, "Allwinner A10 timer"); + return (BUS_PROBE_DEFAULT); +} + +static int +a10_timer_attach(device_t dev) +{ + struct a10_timer_softc *sc; + int err; + uint32_t val; + uint32_t freq; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->sc_dev = dev; + sc->sc_bst = rman_get_bustag(sc->res[0]); + sc->sc_bsh = rman_get_bushandle(sc->res[0]); + + /* set interval */ + timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, TMR_INTER_VAL); + + /* set clock source to HOSC, 16 pre-division */ + val = timer_read_4(sc, SW_TIMER0_CTRL_REG); + val &= ~(0x07<<4); + val &= ~(0x03<<2); + val |= (4<<4) | (1<<2); + timer_write_4(sc, SW_TIMER0_CTRL_REG, val); + + /* set mode to auto reload */ + val = timer_read_4(sc, SW_TIMER0_CTRL_REG); + val |= (1<<1); + timer_write_4(sc, SW_TIMER0_CTRL_REG, val); + + /* Enable timer0 */ + val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG); + val |= (1<<0); + timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val); + + /* Setup and enable the timer interrupt */ + err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_intr, + NULL, sc, &sc->sc_ih); + if (err != 0) { + bus_release_resources(dev, a10_timer_spec, sc->res); + device_printf(dev, "Unable to setup the clock irq handler, " + "err = %d\n", err); + return (ENXIO); + } + freq = SYS_TIMER_CLKSRC; + + /* Set desired frequency in event timer and timecounter */ + sc->et.et_frequency = (uint64_t)freq; + sc->clkfreq = (uint64_t)freq; + sc->et.et_name = "a10_timer Eventtimer"; + sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC; + sc->et.et_quality = 1000; + sc->et.et_min_period.sec = 0; + sc->et.et_min_period.frac = + ((0x00000002LLU << 32) / sc->et.et_frequency) << 32; + sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency; + sc->et.et_max_period.frac = + ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32; + sc->et.et_start = a10_timer_timer_start; + sc->et.et_stop = a10_timer_timer_stop; + sc->et.et_priv = sc; + et_register(&sc->et); + + if (device_get_unit(dev) == 0) + a10_timer_sc = sc; + + a10_timer_timecounter.tc_frequency = (uint64_t)freq; + tc_init(&a10_timer_timecounter); + + printf("clock: hz=%d stathz = %d\n", hz, stathz); + + device_printf(sc->sc_dev, "timer clock frequency %d\n", sc->clkfreq); + + a10_timer_initialized = 1; + + return (0); +} + +static int +a10_timer_timer_start(struct eventtimer *et, struct bintime *first, + struct bintime *period) +{ + struct a10_timer_softc *sc; + uint32_t clo, count; + + sc = (struct a10_timer_softc *)et->et_priv; + + if (first != NULL) { + count = (sc->et.et_frequency * (first->frac >> 32)) >> 32; + if (first->sec != 0) + count += sc->et.et_frequency * first->sec; + + /* clear */ + timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, 0); + clo = timer_read_4(sc, SW_TIMER0_CUR_VALUE_REG); + clo += count; + timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, clo); + + return (0); + } + + return (EINVAL); +} + +static int +a10_timer_timer_stop(struct eventtimer *et) +{ + struct a10_timer_softc *sc; + uint32_t val; + + sc = (struct a10_timer_softc *)et->et_priv; + + /* clear */ + timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, 0); + + /* disable */ + val = timer_read_4(sc, SW_TIMER0_CTRL_REG); + val &= ~(1<<0); /* Disable timer0 */ + timer_write_4(sc, SW_TIMER0_CTRL_REG, val); + + sc->sc_period = 0; + + return (0); +} + +int +a10_timer_get_timerfreq(struct a10_timer_softc *sc) +{ + + return (sc->clkfreq); +} + +void +cpu_initclocks(void) +{ + cpu_initclocks_bsp(); +} + +static int +a10_timer_intr(void *arg) +{ + struct a10_timer_softc *sc; + + sc = (struct a10_timer_softc *)arg; + + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + + /* pending */ + timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1); + + return (FILTER_HANDLED); +} + +u_int +a10_timer_get_timecount(struct timecounter *tc) +{ + + if (a10_timer_sc == NULL) + return (0); + + return (timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG)); +} + +static device_method_t a10_timer_methods[] = { + DEVMETHOD(device_probe, a10_timer_probe), + DEVMETHOD(device_attach, a10_timer_attach), + + DEVMETHOD_END +}; + +static driver_t a10_timer_driver = { + "a10_timer", + a10_timer_methods, + sizeof(struct a10_timer_softc), +}; + +static devclass_t a10_timer_devclass; + +DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0); + +void +DELAY(int usec) +{ + uint32_t counter; + uint32_t val, val_temp; + int32_t nticks; + + /* Timer is not initialized yet */ + if (!a10_timer_initialized) { + for (; usec > 0; usec--) + for (counter = 200; counter > 0; counter--) + /* Prevent optimizing out the loop */ + cpufunc_nullop(); + return; + } + + val = timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG); + nticks = ((a10_timer_sc->clkfreq / 1000000 + 1) * usec); + + while (nticks > 0) { + val_temp = timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG); + if (val > val_temp) + nticks -= (val - val_temp); + else + nticks -= (val + (INITIAL_TIMECOUNTER - val_temp)); + + val = val_temp; + } +} + diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 5dc2679..1d15e27 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -1146,7 +1146,7 @@ struct cpu_functions cortexa_cpufuncs = { /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ - arm11_drain_writebuf, /* drain_writebuf */ + armv7_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ @@ -1157,7 +1157,7 @@ struct cpu_functions cortexa_cpufuncs = { cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ - arm11_context_switch, /* context_switch */ + armv7_context_switch, /* context_switch */ cortexa_setup /* cpu setup */ }; diff --git a/sys/arm/arm/locore.S b/sys/arm/arm/locore.S index ed7af25..00a61e7 100644 --- a/sys/arm/arm/locore.S +++ b/sys/arm/arm/locore.S @@ -484,12 +484,29 @@ ENTRY_NP(abort) ENTRY_NP(sigcode) mov r0, sp + + /* + * Call the sigreturn system call. + * + * We have to load r7 manually rather than using + * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is + * correct. Using the alternative places esigcode at the address + * of the data rather than the address one past the data. + */ + + ldr r7, [pc, #12] /* Load SYS_sigreturn */ swi SYS_sigreturn /* Well if that failed we better exit quick ! */ + ldr r7, [pc, #8] /* Load SYS_exit */ swi SYS_exit - b . - 8 + + /* Branch back to retry SYS_sigreturn */ + b . - 16 + + .word SYS_sigreturn + .word SYS_exit .align 0 .global _C_LABEL(esigcode) diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S index e93b948..4c422e8 100644 --- a/sys/arm/arm/swtch.S +++ b/sys/arm/arm/swtch.S @@ -79,6 +79,7 @@ */ #include "assym.s" +#include "opt_sched.h" #include <machine/asm.h> #include <machine/asmacros.h> @@ -428,6 +429,7 @@ ENTRY(cpu_switch) /* Release the old thread */ str r6, [r4, #TD_LOCK] +#if defined(SCHED_ULE) && defined(SMP) ldr r6, .Lblocked_lock GET_CURTHREAD_PTR(r3) @@ -435,6 +437,7 @@ ENTRY(cpu_switch) ldr r4, [r3, #TD_LOCK] cmp r4, r6 beq 1b +#endif /* XXXSCW: Safe to re-enable FIQs here */ diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c index 35343c8..0f1e81c 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c @@ -136,6 +136,7 @@ struct video_adapter_softc { int console; intptr_t fb_addr; + intptr_t fb_paddr; unsigned int fb_size; unsigned int height; @@ -222,6 +223,7 @@ bcm_fb_init(void *arg) fb_config->screen_size); va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); + va_sc->fb_paddr = fb_config->base; va_sc->fb_size = fb_config->screen_size; va_sc->depth = fb_config->bpp; va_sc->stride = fb_config->pitch; @@ -795,7 +797,7 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { - *paddr = sc->fb_addr + offset; + *paddr = sc->fb_paddr + offset; return (0); } @@ -805,6 +807,27 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, static int bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { + struct video_adapter_softc *sc; + struct fbtype *fb; + + sc = (struct video_adapter_softc *)adp; + + switch (cmd) { + case FBIOGTYPE: + fb = (struct fbtype *)data; + fb->fb_type = FBTYPE_PCIMISC; + fb->fb_height = sc->height; + fb->fb_width = sc->width; + fb->fb_depth = sc->depth; + if (sc->depth <= 1 || sc->depth > 8) + fb->fb_cmsize = 0; + else + fb->fb_cmsize = 1 << sc->depth; + fb->fb_size = sc->fb_size; + break; + default: + return (fb_commonioctl(adp, cmd, data)); + } return (0); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c index 7308c0f..7eff61c 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c @@ -82,11 +82,6 @@ initarm_late_init(void) pcell_t cells[2]; int len; - /* - * It seems there is no way to let syscons framework know - * that framebuffer resolution has changed. So just try - * to fetch data from FDT and go with defaults if failed - */ system = OF_finddevice("/system"); if (system != 0) { len = OF_getprop(system, "linux,serial", &cells, sizeof(cells)); diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD new file mode 100644 index 0000000..c69dfa2 --- /dev/null +++ b/sys/arm/conf/CUBIEBOARD @@ -0,0 +1,134 @@ +# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development +# platform, check out http://www.cubieboard.org +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +ident CUBIEBOARD + +include "../allwinner/std.a10" + +makeoptions MODULES_OVERRIDE="" +makeoptions WITHOUT_MODULES="ahc" + +options HZ=100 +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options PREEMPTION +options FREEBSD_BOOT_LOADER + +# Debugging +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT #Enable verbose sysinit messages +options KDB +options DDB #Enable the kernel debugger +options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +options WITNESS #Enable checks to detect deadlocks and cycles +options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed +#options DIAGNOSTIC + +# NFS support +#options NFSCL +#options NFSSERVER #Network Filesystem Server +#options NFSCLIENT #Network Filesystem Client + +# Uncomment this for NFS root +#options NFS_ROOT #NFS usable as /, requires NFSCLIENT +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=cpsw0 + +# MMC/SD/SDIO card slot support +#device mmc # mmc/sd bus +#device mmcsd # mmc/sd flash cards + +# Boot device is 2nd slice on MMC/SD card +#options ROOTDEVNAME=\"ufs:/dev/da0s2\" + +# ATA controllers +#device ahci # AHCI-compatible SATA controllers +#device ata # Legacy ATA/SATA controllers +#options ATA_CAM # Handle legacy controllers with CAM +#options ATA_STATIC_ID # Static device numbering + +# Console and misc +#device uart +#device uart_ns8250 +device pty +device snp +device md +device random # Entropy device + +# I2C support +#device iicbus +#device iic + +# GPIO +#device gpio + +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device pass + +# USB support +#device usb +#options USB_DEBUG +#options USB_REQ_DEBUG +#options USB_VERBOSE +#device uhci +#device ohci +#device ehci + +#device umass + +# Ethernet +device loop +device ether +device mii +device smscphy +#device cpsw +device bpf + +# USB ethernet support, requires miibus +device miibus + +# Flattened Device Tree +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=cubieboard.dts + diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h index 4862453..82b7d1b 100644 --- a/sys/arm/include/atomic.h +++ b/sys/arm/include/atomic.h @@ -677,6 +677,17 @@ atomic_readandclear_32(volatile u_int32_t *p) #define atomic_store_rel_long atomic_store_long #define atomic_load_acq_32 atomic_load_32 #define atomic_load_acq_long atomic_load_long +#define atomic_add_acq_long atomic_add_long +#define atomic_add_rel_long atomic_add_long +#define atomic_subtract_acq_long atomic_subtract_long +#define atomic_subtract_rel_long atomic_subtract_long +#define atomic_clear_acq_long atomic_clear_long +#define atomic_clear_rel_long atomic_clear_long +#define atomic_set_acq_long atomic_set_long +#define atomic_set_rel_long atomic_set_long +#define atomic_cmpset_acq_long atomic_cmpset_long +#define atomic_cmpset_rel_long atomic_cmpset_long +#define atomic_load_acq_long atomic_load_long #undef __with_interrupts_disabled static __inline void @@ -758,25 +769,13 @@ atomic_store_long(volatile u_long *dst, u_long src) *dst = src; } -#define atomic_add_acq_long atomic_add_long -#define atomic_add_rel_long atomic_add_long -#define atomic_subtract_acq_long atomic_subtract_long -#define atomic_subtract_rel_long atomic_subtract_long -#define atomic_clear_acq_long atomic_clear_long -#define atomic_clear_rel_long atomic_clear_long -#define atomic_set_acq_long atomic_set_long -#define atomic_set_rel_long atomic_set_long -#define atomic_cmpset_acq_long atomic_cmpset_long -#define atomic_cmpset_rel_long atomic_cmpset_long -#define atomic_load_acq_long atomic_load_long - #define atomic_clear_ptr atomic_clear_32 #define atomic_set_ptr atomic_set_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_cmpset_rel_ptr atomic_cmpset_rel_32 #define atomic_cmpset_acq_ptr atomic_cmpset_acq_32 #define atomic_store_ptr atomic_store_32 -#define atomic_store_rel_ptr atomic_store_ptr +#define atomic_store_rel_ptr atomic_store_rel_32 #define atomic_add_int atomic_add_32 #define atomic_add_acq_int atomic_add_acq_32 diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts new file mode 100644 index 0000000..185932c --- /dev/null +++ b/sys/boot/fdt/dts/cubieboard.dts @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/dts-v1/; + +/ { + model = "cubieboard"; + compatible = "cubieboard", "allwinner,a10"; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&AINTC>; + + memory { + device_type = "memory"; + reg = < 0x40000000 0x20000000 >; /* 512MB RAM */ + }; + + aliases { + soc = &SOC; + UART0 = &UART0; + }; + + SOC: a10 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + bus-frequency = <0>; + + AINTC: interrupt-controller@01c20400 { + compatible = "a10,aintc"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = < 0x01c20400 0x400 >; + }; + + timer@01c20c00 { + compatible = "a10,timers"; + reg = <0x01c20c00 0x90>; + interrupts = < 22 >; + interrupt-parent = <&AINTC>; + clock-frequency = < 24000000 >; + }; + + usb1: usb@01c1c000 { + compatible = "a10,usb-ehci", "usb-ehci"; + reg = <0x01c1c000 0x1000>; + interrupts = < 40 >; + interrupt-parent = <&AINTC>; + }; + + sata@01c18000 { + compatible = "a10,ahci"; + reg = <0x01c18000 0x1000>; + interrupts = <56>; + interrupt-parent = <&AINTC>; + }; + + UART0: serial@01c28000 { + status = "okay"; + compatible = "ns16550"; + reg = <0x01c28000 0x400>; + reg-shift = <2>; + interrupts = <1>; + interrupt-parent = <&AINTC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + }; + }; + + chosen { + bootargs = "-v"; + stdin = "UART0"; + stdout = "UART0"; + }; +}; + diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c index 0c6d077..617414e 100644 --- a/sys/boot/i386/libi386/bootinfo64.c +++ b/sys/boot/i386/libi386/bootinfo64.c @@ -134,7 +134,8 @@ bi_checkcpu(void) { char *cpu_vendor; int vendor[3]; - int eflags, regs[4]; + int eflags; + unsigned int regs[4]; /* Check for presence of "cpuid". */ eflags = read_eflags(); diff --git a/sys/boot/i386/libi386/devicename.c b/sys/boot/i386/libi386/devicename.c index 15889d3..c7705d7 100644 --- a/sys/boot/i386/libi386/devicename.c +++ b/sys/boot/i386/libi386/devicename.c @@ -128,7 +128,7 @@ i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path) goto fail; } } else { - cp = np; + cp = (char *)np; } if (*cp && (*cp != ':')) { err = EINVAL; diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c index e4ec5c0..49814dd 100644 --- a/sys/boot/i386/libi386/pxe.c +++ b/sys/boot/i386/libi386/pxe.c @@ -88,6 +88,12 @@ static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); static void pxe_netif_end(struct netif *nif); +#ifdef OLD_NFSV2 +int nfs_getrootfh(struct iodesc*, char*, u_char*); +#else +int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*); +#endif + extern struct netif_stats pxe_st[]; extern u_int16_t __bangpxeseg; extern u_int16_t __bangpxeoff; diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index ac5eba7..768332e 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -2257,11 +2257,31 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, */ mtx_unlock(&softc->ctl_lock); - if (cmd == CTL_ENABLE_PORT) + if (cmd == CTL_ENABLE_PORT) { + struct ctl_lun *lun; + + STAILQ_FOREACH(lun, &softc->lun_list, + links) { + fe->lun_enable(fe->targ_lun_arg, + lun->target, + lun->lun); + } + ctl_frontend_online(fe); - else if (cmd == CTL_DISABLE_PORT) + } else if (cmd == CTL_DISABLE_PORT) { + struct ctl_lun *lun; + ctl_frontend_offline(fe); + STAILQ_FOREACH(lun, &softc->lun_list, + links) { + fe->lun_disable( + fe->targ_lun_arg, + lun->target, + lun->lun); + } + } + mtx_lock(&softc->ctl_lock); if (cmd == CTL_SET_PORT_WWNS) diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 59357123..5dc20e5 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$"); #include <cam/ctl/ctl_error.h> typedef enum { + CTLFE_CCB_DEFAULT = 0x00, CTLFE_CCB_WAITING = 0x01 } ctlfe_ccb_types; @@ -304,10 +305,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) case AC_PATH_REGISTERED: { struct ctl_frontend *fe; struct ctlfe_softc *bus_softc; - struct ctlfe_lun_softc *lun_softc; - struct cam_path *path; struct ccb_pathinq *cpi; - cam_status status; int retval; cpi = (struct ccb_pathinq *)arg; @@ -330,7 +328,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) M_NOWAIT | M_ZERO); if (ccb == NULL) { printf("%s: unable to malloc CCB!\n", __func__); - xpt_free_path(path); return; } xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path, @@ -448,44 +445,31 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) mtx_unlock(&ctlfe_list_mtx); } - status = xpt_create_path(&path, /*periph*/ NULL, - bus_softc->path_id,CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD); - if (status != CAM_REQ_CMP) { - printf("%s: unable to create path for wildcard " - "periph\n", __func__); - break; - } - lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, - M_NOWAIT | M_ZERO); - if (lun_softc == NULL) { - xpt_print(path, "%s: unable to allocate softc for " - "wildcard periph\n", __func__); - xpt_free_path(path); - break; + break; + } + case AC_PATH_DEREGISTERED: { + struct ctlfe_softc *softc = NULL; + + mtx_lock(&ctlfe_list_mtx); + STAILQ_FOREACH(softc, &ctlfe_softc_list, links) { + if (softc->path_id == xpt_path_path_id(path)) { + STAILQ_REMOVE(&ctlfe_softc_list, softc, + ctlfe_softc, links); + break; + } } + mtx_unlock(&ctlfe_list_mtx); - lun_softc->parent_softc = bus_softc; - lun_softc->flags |= CTLFE_LUN_WILDCARD; - - status = cam_periph_alloc(ctlferegister, - ctlfeoninvalidate, - ctlfecleanup, - ctlfestart, - "ctl", - CAM_PERIPH_BIO, - path, - ctlfeasync, - 0, - lun_softc); - - xpt_free_path(path); - + if (softc != NULL) { + /* + * XXX KDM are we certain at this point that there + * are no outstanding commands for this frontend? + */ + ctl_frontend_deregister(&softc->fe); + free(softc, M_CTLFE); + } break; } - case AC_PATH_DEREGISTERED: - /* ctl_frontend_deregister() */ - break; case AC_CONTRACT: { struct ac_contract *ac; @@ -699,11 +683,14 @@ ctlfecleanup(struct cam_periph *periph) softc = (struct ctlfe_lun_softc *)periph->softc; bus_softc = softc->parent_softc; - STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc,links); + STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links); /* * XXX KDM is there anything else that needs to be done here? */ + + callout_stop(&softc->dma_callout); + free(softc, M_CTLFE); } @@ -717,6 +704,8 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) softc->ccbs_alloced++; + start_ccb->ccb_h.ccb_type = CTLFE_CCB_DEFAULT; + ccb_h = TAILQ_FIRST(&softc->work_queue); if (periph->immediate_priority <= periph->pinfo.priority) { panic("shouldn't get to the CCB waiting case!"); @@ -857,8 +846,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) /* * Datamove call, we need to setup the S/G list. - * If we pass in a S/G list, the isp(4) driver at - * least expects physical/bus addresses. */ cmd_info = (struct ctlfe_lun_cmd_info *) @@ -933,12 +920,13 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) int *ti; /* - * XXX KDM this is a temporary hack. The - * isp(4) driver can't deal with S/G lists - * with virtual pointers, so we need to - * go through and send down one virtual - * pointer at a time. + * If we have more S/G list pointers than + * will fit in the available storage in the + * cmd_info structure inside the ctl_io header, + * then we need to send down the pointers + * one element at a time. */ + sglist = (struct ctl_sg_entry *) io->scsiio.kern_data_ptr; ti = &cmd_info->cur_transfer_index; @@ -1405,13 +1393,15 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) break; default: /* - * XXX KDM the isp(4) driver doesn't really - * seem to send errors back for data - * transfers that I can tell. There is one - * case where it'll send CAM_REQ_CMP_ERR, - * but probably not that many more cases. - * So set a generic data phase error here, - * like the SXP driver sets. + * XXX KDM we probably need to figure out a + * standard set of errors that the SIM + * drivers should return in the event of a + * data transfer failure. A data phase + * error will at least point the user to a + * data transfer error of some sort. + * Hopefully the SIM printed out some + * additional information to give the user + * a clue what happened. */ io->io_hdr.port_status = 0xbad1; ctl_set_data_phase_error(&io->scsiio); @@ -1689,20 +1679,22 @@ ctlfe_onoffline(void *arg, int online) sim = bus_softc->sim; - CAM_SIM_LOCK(sim); + mtx_assert(sim->mtx, MA_OWNED); + status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); if (status != CAM_REQ_CMP) { printf("%s: unable to create path!\n", __func__); - CAM_SIM_UNLOCK(sim); return; } - CAM_SIM_UNLOCK(sim); - - ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO); + ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_NOWAIT | M_ZERO); + if (ccb == NULL) { + printf("%s: unable to malloc CCB!\n", __func__); + xpt_free_path(path); + return; + } xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE); - /* * Copan WWN format: * @@ -1720,11 +1712,9 @@ ctlfe_onoffline(void *arg, int online) ccb->ccb_h.func_code = XPT_GET_SIM_KNOB; - CAM_SIM_LOCK(sim); xpt_action(ccb); - CAM_SIM_UNLOCK(sim); if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){ #ifdef RANDOM_WWNN @@ -1822,9 +1812,6 @@ ctlfe_onoffline(void *arg, int online) else ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE; - - CAM_SIM_LOCK(sim); - xpt_action(ccb); if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { @@ -1841,8 +1828,6 @@ ctlfe_onoffline(void *arg, int online) xpt_free_path(path); - CAM_SIM_UNLOCK(sim); - free(ccb, M_TEMP); return; @@ -1851,13 +1836,111 @@ ctlfe_onoffline(void *arg, int online) static void ctlfe_online(void *arg) { + struct ctlfe_softc *bus_softc; + struct cam_path *path; + cam_status status; + struct ctlfe_lun_softc *lun_softc; + struct cam_sim *sim; + + bus_softc = (struct ctlfe_softc *)arg; + sim = bus_softc->sim; + + CAM_SIM_LOCK(sim); + + /* + * Create the wildcard LUN before bringing the port online. + */ + status = xpt_create_path(&path, /*periph*/ NULL, + bus_softc->path_id, CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD); + if (status != CAM_REQ_CMP) { + printf("%s: unable to create path for wildcard periph\n", + __func__); + CAM_SIM_UNLOCK(sim); + return; + } + + lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, + M_NOWAIT | M_ZERO); + if (lun_softc == NULL) { + xpt_print(path, "%s: unable to allocate softc for " + "wildcard periph\n", __func__); + xpt_free_path(path); + CAM_SIM_UNLOCK(sim); + return; + } + + lun_softc->parent_softc = bus_softc; + lun_softc->flags |= CTLFE_LUN_WILDCARD; + + STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, lun_softc, links); + + + status = cam_periph_alloc(ctlferegister, + ctlfeoninvalidate, + ctlfecleanup, + ctlfestart, + "ctl", + CAM_PERIPH_BIO, + path, + ctlfeasync, + 0, + lun_softc); + + if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + const struct cam_status_entry *entry; + + entry = cam_fetch_status_entry(status); + + printf("%s: CAM error %s (%#x) returned from " + "cam_periph_alloc()\n", __func__, (entry != NULL) ? + entry->status_text : "Unknown", status); + } + + xpt_free_path(path); + ctlfe_onoffline(arg, /*online*/ 1); + + CAM_SIM_UNLOCK(sim); } static void ctlfe_offline(void *arg) { + struct ctlfe_softc *bus_softc; + struct cam_path *path; + cam_status status; + struct cam_periph *periph; + struct cam_sim *sim; + + bus_softc = (struct ctlfe_softc *)arg; + sim = bus_softc->sim; + + CAM_SIM_LOCK(sim); + ctlfe_onoffline(arg, /*online*/ 0); + + /* + * Disable the wildcard LUN for this port now that we have taken + * the port offline. + */ + status = xpt_create_path(&path, /*periph*/ NULL, + bus_softc->path_id, CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD); + if (status != CAM_REQ_CMP) { + CAM_SIM_UNLOCK(sim); + printf("%s: unable to create path for wildcard periph\n", + __func__); + return; + } + + + if ((periph = cam_periph_find(path, "ctl")) != NULL) + cam_periph_invalidate(periph); + + xpt_free_path(path); + + CAM_SIM_UNLOCK(sim); } static int @@ -1890,21 +1973,17 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) bus_softc = (struct ctlfe_softc *)arg; sim = bus_softc->sim; - CAM_SIM_LOCK(sim); - - status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id, - targ_id.id, lun_id); + status = xpt_create_path_unlocked(&path, /*periph*/ NULL, + bus_softc->path_id, + targ_id.id, lun_id); /* XXX KDM need some way to return status to CTL here? */ if (status != CAM_REQ_CMP) { printf("%s: could not create path, status %#x\n", __func__, status); - CAM_SIM_UNLOCK(sim); return (1); } - CAM_SIM_UNLOCK(sim); softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO); - CAM_SIM_LOCK(sim); periph = cam_periph_find(path, "ctl"); if (periph != NULL) { @@ -1937,23 +2016,20 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) } /* - * XXX KDM we disable LUN removal here. The problem is that the isp(4) - * driver doesn't currently handle LUN removal properly. We need to keep - * enough state here at the peripheral level even after LUNs have been - * removed inside CTL. - * - * Once the isp(4) driver is fixed, this can be re-enabled. + * This will get called when the user removes a LUN to disable that LUN + * on every bus that is attached to CTL. */ static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) { -#ifdef NOTYET struct ctlfe_softc *softc; struct ctlfe_lun_softc *lun_softc; + struct cam_sim *sim; softc = (struct ctlfe_softc *)arg; + sim = softc->sim; - mtx_lock(softc->sim->mtx); + CAM_SIM_LOCK(sim); STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) { struct cam_path *path; @@ -1965,7 +2041,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) } } if (lun_softc == NULL) { - mtx_unlock(softc->sim->mtx); + CAM_SIM_UNLOCK(sim); printf("%s: can't find target %d lun %d\n", __func__, targ_id.id, lun_id); return (1); @@ -1973,8 +2049,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) cam_periph_invalidate(lun_softc->periph); - mtx_unlock(softc->sim->mtx); -#endif + CAM_SIM_UNLOCK(sim); return (0); } @@ -2139,7 +2214,7 @@ ctlfe_datamove_done(union ctl_io *io) sim = xpt_path_sim(ccb->ccb_h.path); - mtx_lock(sim->mtx); + CAM_SIM_LOCK(sim); periph = xpt_path_periph(ccb->ccb_h.path); @@ -2186,7 +2261,7 @@ ctlfe_datamove_done(union ctl_io *io) xpt_schedule(periph, /*priority*/ 1); } - mtx_unlock(sim->mtx); + CAM_SIM_UNLOCK(sim); } static void diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index d5d7156..a7c4c5b 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -581,7 +581,7 @@ cdasync(void *callback_arg, u_int32_t code, if (softc->state == CD_STATE_NORMAL && !softc->tur) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { softc->tur = 1; - xpt_schedule(periph, CAM_PRIORITY_DEV); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } } /* FALLTHROUGH */ @@ -1612,9 +1612,11 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb) xpt_action(start_ccb); } - if (bp != NULL || softc->tur) { + if (bp != NULL || softc->tur || + periph->immediate_priority != CAM_PRIORITY_NONE) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, CAM_PRIORITY_NORMAL); + xpt_schedule(periph, min(CAM_PRIORITY_NORMAL, + periph->immediate_priority)); } break; } @@ -3293,10 +3295,11 @@ cdmediapoll(void *arg) if (softc->flags & CD_FLAG_CHANGER) return; - if (softc->state == CD_STATE_NORMAL && !softc->tur) { + if (softc->state == CD_STATE_NORMAL && !softc->tur && + softc->outstanding_cmds == 0) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { softc->tur = 1; - xpt_schedule(periph, CAM_PRIORITY_DEV); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } } /* Queue us up again */ diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index adda9c9..7854215 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -863,6 +863,8 @@ static void daasync(void *callback_arg, u_int32_t code, static void dasysctlinit(void *context, int pending); static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS); static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS); +static int dadeletemethodset(struct da_softc *softc, + da_delete_methods delete_method); static periph_ctor_t daregister; static periph_dtor_t dacleanup; static periph_start_t dastart; @@ -1079,6 +1081,9 @@ daschedule(struct cam_periph *periph) struct da_softc *softc = (struct da_softc *)periph->softc; uint32_t prio; + if (softc->state != DA_STATE_NORMAL) + return; + /* Check if cam_periph_getccb() was called. */ prio = periph->immediate_priority; @@ -1423,10 +1428,10 @@ daasync(void *callback_arg, u_int32_t code, } case AC_SCSI_AEN: softc = (struct da_softc *)periph->softc; - if (softc->state == DA_STATE_NORMAL && !softc->tur) { + if (!softc->tur) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { softc->tur = 1; - xpt_schedule(periph, CAM_PRIORITY_DEV); + daschedule(periph); } } /* FALLTHROUGH */ @@ -1489,7 +1494,7 @@ dasysctlinit(void *context, int pending) */ SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW, - &softc->delete_method, 0, dadeletemethodsysctl, "A", + softc, 0, dadeletemethodsysctl, "A", "BIO_DELETE execution method"); SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW, @@ -1566,14 +1571,33 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS) } static int +dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method) +{ + + if (delete_method < 0 || delete_method > DA_DELETE_MAX) + return (EINVAL); + + softc->delete_method = delete_method; + + if (softc->delete_method > DA_DELETE_DISABLE) + softc->disk->d_flags |= DISKFLAG_CANDELETE; + else + softc->disk->d_flags &= ~DISKFLAG_CANDELETE; + + return (0); +} + +static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS) { char buf[16]; - int error; const char *p; - int i, value; + struct da_softc *softc; + int i, error, value; - value = *(int *)arg1; + softc = (struct da_softc *)arg1; + + value = softc->delete_method; if (value < 0 || value > DA_DELETE_MAX) p = "UNKNOWN"; else @@ -1585,8 +1609,7 @@ dadeletemethodsysctl(SYSCTL_HANDLER_ARGS) for (i = 0; i <= DA_DELETE_MAX; i++) { if (strcmp(buf, da_delete_method_names[i]) != 0) continue; - *(int *)arg1 = i; - return (0); + return dadeletemethodset(softc, i); } return (EINVAL); } @@ -2014,7 +2037,6 @@ out: } case DA_STATE_PROBE: { - struct ccb_scsiio *csio; struct scsi_read_capacity_data *rcap; rcap = (struct scsi_read_capacity_data *) @@ -2024,9 +2046,8 @@ out: /* da_free_periph??? */ break; } - csio = &start_ccb->csio; - scsi_read_capacity(csio, - /*retries*/4, + scsi_read_capacity(&start_ccb->csio, + /*retries*/da_retry_count, dadone, MSG_SIMPLE_Q_TAG, rcap, @@ -2039,7 +2060,6 @@ out: } case DA_STATE_PROBE2: { - struct ccb_scsiio *csio; struct scsi_read_capacity_data_long *rcaplong; rcaplong = (struct scsi_read_capacity_data_long *) @@ -2049,9 +2069,8 @@ out: /* da_free_periph??? */ break; } - csio = &start_ccb->csio; - scsi_read_capacity_16(csio, - /*retries*/ 4, + scsi_read_capacity_16(&start_ccb->csio, + /*retries*/ da_retry_count, /*cbfcnp*/ dadone, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*lba*/ 0, @@ -2060,7 +2079,7 @@ out: /*rcap_buf*/ (uint8_t *)rcaplong, /*rcap_buf_len*/ sizeof(*rcaplong), /*sense_len*/ SSD_FULL_SIZE, - /*timeout*/ 60000); + /*timeout*/ da_default_timeout * 1000); start_ccb->ccb_h.ccb_bp = NULL; start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2; xpt_action(start_ccb); @@ -2086,24 +2105,24 @@ cmd6workaround(union ccb *ccb) if (softc->delete_method == DA_DELETE_UNMAP) { xpt_print(ccb->ccb_h.path, "UNMAP is not supported, " "switching to WRITE SAME(16) with UNMAP.\n"); - softc->delete_method = DA_DELETE_WS16; + dadeletemethodset(softc, DA_DELETE_WS16); } else if (softc->delete_method == DA_DELETE_WS16) { xpt_print(ccb->ccb_h.path, "WRITE SAME(16) with UNMAP is not supported, " "disabling BIO_DELETE.\n"); - softc->delete_method = DA_DELETE_DISABLE; + dadeletemethodset(softc, DA_DELETE_DISABLE); } else if (softc->delete_method == DA_DELETE_WS10) { xpt_print(ccb->ccb_h.path, "WRITE SAME(10) with UNMAP is not supported, " "disabling BIO_DELETE.\n"); - softc->delete_method = DA_DELETE_DISABLE; + dadeletemethodset(softc, DA_DELETE_DISABLE); } else if (softc->delete_method == DA_DELETE_ZERO) { xpt_print(ccb->ccb_h.path, "WRITE SAME(10) is not supported, " "disabling BIO_DELETE.\n"); - softc->delete_method = DA_DELETE_DISABLE; + dadeletemethodset(softc, DA_DELETE_DISABLE); } else - softc->delete_method = DA_DELETE_DISABLE; + dadeletemethodset(softc, DA_DELETE_DISABLE); while ((bp = bioq_takefirst(&softc->delete_run_queue)) != NULL) bioq_disksort(&softc->delete_queue, bp); @@ -2152,6 +2171,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) struct da_softc *softc; struct ccb_scsiio *csio; u_int32_t priority; + da_ccb_state state; softc = (struct da_softc *)periph->softc; priority = done_ccb->ccb_h.pinfo.priority; @@ -2159,7 +2179,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n")); csio = &done_ccb->csio; - switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) { + state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK; + switch (state) { case DA_CCB_BUFFER_IO: case DA_CCB_DELETE: { @@ -2257,8 +2278,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) softc->outstanding_cmds); } - if ((csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) == - DA_CCB_DELETE) { + if (state == DA_CCB_DELETE) { while ((bp1 = bioq_takefirst(&softc->delete_run_queue)) != NULL) { bp1->bio_resid = bp->bio_resid; @@ -2284,7 +2304,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) rdcap = NULL; rcaplong = NULL; - if (softc->state == DA_STATE_PROBE) + if (state == DA_CCB_PROBE) rdcap =(struct scsi_read_capacity_data *)csio->data_ptr; else rcaplong = (struct scsi_read_capacity_data_long *) @@ -2297,7 +2317,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) u_int lbppbe; /* LB per physical block exponent. */ u_int lalba; /* Lowest aligned LBA. */ - if (softc->state == DA_STATE_PROBE) { + if (state == DA_CCB_PROBE) { block_size = scsi_4btoul(rdcap->length); maxsector = scsi_4btoul(rdcap->addr); lbppbe = 0; @@ -2349,7 +2369,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) rcaplong, sizeof(*rcaplong)); if ((lalba & SRC16_LBPME_A) && softc->delete_method == DA_DELETE_NONE) - softc->delete_method = DA_DELETE_UNMAP; + dadeletemethodset(softc, DA_DELETE_UNMAP); dp = &softc->params; snprintf(announce_buf, sizeof(announce_buf), "%juMB (%ju %u byte sectors: %dH %dS/T " @@ -2410,7 +2430,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) * If we tried READ CAPACITY(16) and failed, * fallback to READ CAPACITY(10). */ - if ((softc->state == DA_STATE_PROBE2) && + if ((state == DA_CCB_PROBE2) && (softc->flags & DA_FLAG_CAN_RC16) && (((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) || @@ -2490,7 +2510,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) * operation. */ xpt_release_ccb(done_ccb); - softc->state = DA_STATE_NORMAL; + softc->state = DA_STATE_NORMAL; + daschedule(periph); wakeup(&softc->disk->d_mediasize); if ((softc->flags & DA_FLAG_PROBED) == 0) { softc->flags |= DA_FLAG_PROBED; @@ -2615,7 +2636,7 @@ damediapoll(void *arg) struct cam_periph *periph = arg; struct da_softc *softc = periph->softc; - if (softc->state == DA_STATE_NORMAL && !softc->tur) { + if (!softc->tur && softc->outstanding_cmds == 0) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { softc->tur = 1; daschedule(periph); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c index ef3d0f4..885af95 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c @@ -89,12 +89,13 @@ ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class, spa_t *spa = ddt->ddt_spa; objset_t *os = ddt->ddt_os; uint64_t *objectp = &ddt->ddt_object[type][class]; + uint64_t count; char name[DDT_NAMELEN]; ddt_object_name(ddt, type, class, name); ASSERT(*objectp != 0); - ASSERT(ddt_object_count(ddt, type, class) == 0); + VERIFY(ddt_object_count(ddt, type, class, &count) == 0 && count == 0); ASSERT(ddt_histogram_empty(&ddt->ddt_histogram[type][class])); VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0); VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0); @@ -109,6 +110,7 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class) { ddt_object_t *ddo = &ddt->ddt_object_stats[type][class]; dmu_object_info_t doi; + uint64_t count; char name[DDT_NAMELEN]; int error; @@ -129,7 +131,11 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class) */ VERIFY(ddt_object_info(ddt, type, class, &doi) == 0); - ddo->ddo_count = ddt_object_count(ddt, type, class); + error = ddt_object_count(ddt, type, class, &count); + if (error) + return error; + + ddo->ddo_count = count; ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9; ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size; @@ -143,6 +149,7 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class, { ddt_object_t *ddo = &ddt->ddt_object_stats[type][class]; dmu_object_info_t doi; + uint64_t count; char name[DDT_NAMELEN]; ddt_object_name(ddt, type, class, name); @@ -155,8 +162,9 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class, * Cache DDT statistics; this is the only time they'll change. */ VERIFY(ddt_object_info(ddt, type, class, &doi) == 0); + VERIFY(ddt_object_count(ddt, type, class, &count) == 0); - ddo->ddo_count = ddt_object_count(ddt, type, class); + ddo->ddo_count = count; ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9; ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size; } @@ -213,13 +221,13 @@ ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class class, ddt->ddt_object[type][class], dde, walk)); } -uint64_t -ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class) +int +ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class, uint64_t *count) { ASSERT(ddt_object_exists(ddt, type, class)); return (ddt_ops[type]->ddt_op_count(ddt->ddt_os, - ddt->ddt_object[type][class])); + ddt->ddt_object[type][class], count)); } int @@ -1079,11 +1087,13 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg) } for (enum ddt_type type = 0; type < DDT_TYPES; type++) { - uint64_t count = 0; + uint64_t add, count = 0; for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { if (ddt_object_exists(ddt, type, class)) { ddt_object_sync(ddt, type, class, tx); - count += ddt_object_count(ddt, type, class); + VERIFY(ddt_object_count(ddt, type, class, + &add) == 0); + count += add; } } for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c index 6812aa3..f42b4dd 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c @@ -133,14 +133,11 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk) return (error); } -static uint64_t -ddt_zap_count(objset_t *os, uint64_t object) +static int +ddt_zap_count(objset_t *os, uint64_t object, uint64_t *count) { - uint64_t count = 0; - - VERIFY(zap_count(os, object, &count) == 0); - return (count); + return (zap_count(os, object, count)); } const ddt_ops_t ddt_zap_ops = { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h index 405622b..5d9747b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h @@ -163,7 +163,7 @@ typedef struct ddt_ops { dmu_tx_t *tx); int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk); - uint64_t (*ddt_op_count)(objset_t *os, uint64_t object); + int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count); } ddt_ops_t; #define DDT_NAMELEN 80 @@ -172,8 +172,8 @@ extern void ddt_object_name(ddt_t *ddt, enum ddt_type type, enum ddt_class cls, char *name); extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class cls, uint64_t *walk, ddt_entry_t *dde); -extern uint64_t ddt_object_count(ddt_t *ddt, enum ddt_type type, - enum ddt_class cls); +extern int ddt_object_count(ddt_t *ddt, enum ddt_type type, + enum ddt_class class, uint64_t *count); extern int ddt_object_info(ddt_t *ddt, enum ddt_type type, enum ddt_class cls, dmu_object_info_t *); extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 72c22dc..7f3f7a1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -2025,6 +2025,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp) err = zfs_vnode_lock(*vpp, flags); if (err != 0) *vpp = NULL; + else + (*vpp)->v_hash = ino; return (err); } diff --git a/sys/conf/files b/sys/conf/files index 24f23ee..a1bfbc7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -638,9 +638,12 @@ dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/alc/if_alc.c optional alc pci dev/ale/if_ale.c optional ale pci dev/altera/avgen/altera_avgen.c optional altera_avgen +dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt +dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen dev/altera/sdcard/altera_sdcard.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard +dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard dev/amr/amr.c optional amr dev/amr/amr_cam.c optional amrp amr @@ -1415,6 +1418,7 @@ dev/iscsi/initiator/isc_soc.c optional iscsi_initiator scbus dev/iscsi/initiator/isc_sm.c optional iscsi_initiator scbus dev/iscsi/initiator/isc_subr.c optional iscsi_initiator scbus dev/isf/isf.c optional isf +dev/isf/isf_fdt.c optional isf fdt dev/isf/isf_nexus.c optional isf dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp @@ -2276,15 +2280,6 @@ dev/utopia/idtphy.c optional utopia dev/utopia/suni.c optional utopia dev/utopia/utopia.c optional utopia dev/vge/if_vge.c optional vge -# -# virtio support -# -dev/virtio/pci/virtio_pci.c optional vtnet -dev/virtio/virtio.c optional vtnet -dev/virtio/virtqueue.c optional vtnet -dev/virtio/network/if_vtnet.c optional vtnet -dev/virtio/virtio_bus_if.m optional vtnet -dev/virtio/virtio_if.m optional vtnet dev/vkbd/vkbd.c optional vkbd dev/vr/if_vr.c optional vr pci diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a0cf1ae..f381c71 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -390,6 +390,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci dev/isci/scil/scif_sas_task_request_states.c optional isci dev/isci/scil/scif_sas_timer.c optional isci +dev/virtio/virtio.c optional virtio +dev/virtio/virtqueue.c optional virtio +dev/virtio/virtio_bus_if.m optional virtio +dev/virtio/virtio_if.m optional virtio +dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci +dev/virtio/network/if_vtnet.c optional vtnet virtio +dev/virtio/block/virtio_blk.c optional virtio_blk virtio +dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio +dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/kern_clocksource.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index d4df01d..5e2eeef 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -371,6 +371,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci dev/isci/scil/scif_sas_task_request_states.c optional isci dev/isci/scil/scif_sas_timer.c optional isci +dev/virtio/virtio.c optional virtio +dev/virtio/virtqueue.c optional virtio +dev/virtio/virtio_bus_if.m optional virtio +dev/virtio/virtio_if.m optional virtio +dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci +dev/virtio/network/if_vtnet.c optional vtnet virtio +dev/virtio/block/virtio_blk.c optional virtio_blk virtio +dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio +dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus i386/acpica/acpi_machdep.c optional acpi acpi_wakecode.o optional acpi \ dependency "$S/i386/acpica/acpi_wakecode.S assym.s" \ diff --git a/sys/conf/files.mips b/sys/conf/files.mips index 8c7a530..2dfc5dd 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -7,6 +7,7 @@ # Arch dependent files mips/mips/autoconf.c standard mips/mips/bus_space_generic.c standard +mips/mips/bus_space_fdt.c optional fdt mips/mips/busdma_machdep.c standard mips/mips/cache.c standard mips/mips/cache_mipsNN.c standard diff --git a/sys/conf/options b/sys/conf/options index 1fb3a2a..8224275 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -775,6 +775,8 @@ ATH_ENABLE_11N opt_ath.h ATH_ENABLE_DFS opt_ath.h ATH_EEPROM_FIRMWARE opt_ath.h ATH_ENABLE_RADIOTAP_VENDOR_EXT opt_ath.h +ATH_DEBUG_ALQ opt_ath.h +ATH_KTR_INTR_DEBUG opt_ath.h # options for the Atheros hal AH_SUPPORT_AR5416 opt_ah.h @@ -794,7 +796,7 @@ AH_NEED_DESC_SWAP opt_ah.h AH_USE_INIPDGAIN opt_ah.h AH_MAXCHAN opt_ah.h AH_RXCFG_SDMAMW_4BYTES opt_ah.h - +AH_INTERRUPT_DEBUGGING opt_ah.h # AR5416 and later interrupt mitigation # XXX do not use this for AR9130 AH_AR5416_INTERRUPT_MITIGATION opt_ah.h diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index baa8205..531725a 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -509,15 +509,8 @@ acpi_tz_monitor(void *Context) */ newactive = TZ_ACTIVE_NONE; for (i = TZ_NUMLEVELS - 1; i >= 0; i--) { - if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i]) { + if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i]) newactive = i; - if (sc->tz_active != newactive) { - ACPI_VPRINT(sc->tz_dev, - acpi_device_get_parent_softc(sc->tz_dev), - "_AC%d: temperature %d.%d >= setpoint %d.%d\n", i, - TZ_KELVTOC(temp), TZ_KELVTOC(sc->tz_zone.ac[i])); - } - } } /* diff --git a/sys/dev/altera/avgen/altera_avgen.c b/sys/dev/altera/avgen/altera_avgen.c index a90b546..5429c9d 100644 --- a/sys/dev/altera/avgen/altera_avgen.c +++ b/sys/dev/altera/avgen/altera_avgen.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012 Robert N. M. Watson + * Copyright (c) 2012-2013 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of @@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$"); * system-on-chip bus environments would work fine with the same code. */ +devclass_t altera_avgen_devclass; + static d_mmap_t altera_avgen_mmap; static d_read_t altera_avgen_read; static d_write_t altera_avgen_write; @@ -226,13 +228,6 @@ altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, return (0); } -static int -altera_avgen_nexus_probe(device_t dev) -{ - - device_set_desc(dev, "Generic Altera Avalon device attachment"); - return (BUS_PROBE_DEFAULT); -} static int altera_avgen_process_options(struct altera_avgen_softc *sc, @@ -321,42 +316,14 @@ altera_avgen_process_options(struct altera_avgen_softc *sc, return (0); } -static int -altera_avgen_nexus_attach(device_t dev) +int +altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio, + const char *str_mmapio, const char *str_devname, int devunit) { - struct altera_avgen_softc *sc; - const char *str_fileio, *str_mmapio; - const char *str_devname; + device_t dev = sc->avg_dev; char devname[SPECNAMELEN + 1]; - int devunit, error; - - sc = device_get_softc(dev); - sc->avg_dev = dev; - sc->avg_unit = device_get_unit(dev); + int error; - /* - * Query non-standard hints to find out what operations are permitted - * on the device, and whether it is cached. - */ - str_fileio = NULL; - str_mmapio = NULL; - str_devname = NULL; - devunit = -1; - sc->avg_width = 1; - error = resource_int_value(device_get_name(dev), device_get_unit(dev), - ALTERA_AVALON_STR_WIDTH, &sc->avg_width); - if (error != 0 && error != ENOENT) { - device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH); - return (error); - } - (void)resource_string_value(device_get_name(dev), - device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio); - (void)resource_string_value(device_get_name(dev), - device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio); - (void)resource_string_value(device_get_name(dev), - device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname); - (void)resource_int_value(device_get_name(dev), device_get_unit(dev), - ALTERA_AVALON_STR_DEVUNIT, &devunit); error = altera_avgen_process_options(sc, str_fileio, str_mmapio, str_devname, devunit); if (error) @@ -374,25 +341,15 @@ altera_avgen_nexus_attach(device_t dev) snprintf(devname, sizeof(devname), "%s%d", "avgen", sc->avg_unit); - /* Memory allocation and checking. */ - sc->avg_rid = 0; - sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->avg_rid, RF_ACTIVE); - if (sc->avg_res == NULL) { - device_printf(dev, "couldn't map memory\n"); - return (ENXIO); - } if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) { if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) { device_printf(dev, "memory region not even multiple of page size\n"); - error = ENXIO; - goto error; + return (ENXIO); } if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) { device_printf(dev, "memory region not page-aligned\n"); - error = ENXIO; - goto error; + return (ENXIO); } } @@ -409,43 +366,16 @@ altera_avgen_nexus_attach(device_t dev) GID_WHEEL, S_IRUSR | S_IWUSR, str_devname); if (sc->avg_cdev == NULL) { device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__); - error = ENXIO; - goto error; + return (ENXIO); } /* XXXRW: Slight race between make_dev(9) and here. */ sc->avg_cdev->si_drv1 = sc; return (0); - -error: - bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res); - return (error); } -static int -altera_avgen_nexus_detach(device_t dev) +void +altera_avgen_detach(struct altera_avgen_softc *sc) { - struct altera_avgen_softc *sc; - sc = device_get_softc(dev); destroy_dev(sc->avg_cdev); - bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res); - return (0); } - -static device_method_t altera_avgen_nexus_methods[] = { - DEVMETHOD(device_probe, altera_avgen_nexus_probe), - DEVMETHOD(device_attach, altera_avgen_nexus_attach), - DEVMETHOD(device_detach, altera_avgen_nexus_detach), - { 0, 0 } -}; - -static driver_t altera_avgen_nexus_driver = { - "altera_avgen", - altera_avgen_nexus_methods, - sizeof(struct altera_avgen_softc), -}; - -static devclass_t altera_avgen_devclass; - -DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass, - 0, 0); diff --git a/sys/dev/altera/avgen/altera_avgen.h b/sys/dev/altera/avgen/altera_avgen.h index c8c7947..fb25a3c 100644 --- a/sys/dev/altera/avgen/altera_avgen.h +++ b/sys/dev/altera/avgen/altera_avgen.h @@ -77,7 +77,11 @@ struct altera_avgen_softc { /* * Driver setup routines from the bus attachment/teardown. */ -int altera_avgen_attach(struct altera_avgen_softc *sc); +int altera_avgen_attach(struct altera_avgen_softc *sc, + const char *str_fileio, const char *str_mmapio, + const char *str_devname, int devunit); void altera_avgen_detach(struct altera_avgen_softc *sc); +extern devclass_t altera_avgen_devclass; + #endif /* _DEV_ALTERA_AVALON_H_ */ diff --git a/sys/dev/altera/avgen/altera_avgen_fdt.c b/sys/dev/altera/avgen/altera_avgen_fdt.c new file mode 100644 index 0000000..2762ff4 --- /dev/null +++ b/sys/dev/altera/avgen/altera_avgen_fdt.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2012-2013 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/stat.h> +#include <sys/systm.h> +#include <sys/uio.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <machine/vm.h> + +#include <vm/vm.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/altera/avgen/altera_avgen.h> + +static int +altera_avgen_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "sri-cambridge,avgen")) { + device_set_desc(dev, "Generic Altera Avalon device attachment"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +altera_avgen_fdt_attach(device_t dev) +{ + struct altera_avgen_softc *sc; + char *str_fileio, *str_mmapio; + char *str_devname; + phandle_t node; + pcell_t cell; + int devunit, error; + + sc = device_get_softc(dev); + sc->avg_dev = dev; + sc->avg_unit = device_get_unit(dev); + + /* + * Query driver-specific OpenFirmware properties to determine how to + * expose the device via /dev. + */ + str_fileio = NULL; + str_mmapio = NULL; + str_devname = NULL; + devunit = -1; + sc->avg_width = 1; + node = ofw_bus_get_node(dev); + if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0) + sc->avg_width = cell; + (void)OF_getprop_alloc(node, "sri-cambridge,fileio", sizeof(char), + (void **)&str_fileio); + (void)OF_getprop_alloc(node, "sri-cambridge,mmapio", sizeof(char), + (void **)&str_mmapio); + (void)OF_getprop_alloc(node, "sri-cambridge,devname", sizeof(char), + (void **)&str_devname); + if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0) + devunit = cell; + + /* Memory allocation and checking. */ + sc->avg_rid = 0; + sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->avg_rid, RF_ACTIVE); + if (sc->avg_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + return (ENXIO); + } + error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname, + devunit); + if (error != 0) + bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, + sc->avg_res); + if (str_fileio != NULL) + free(str_fileio, M_OFWPROP); + if (str_mmapio != NULL) + free(str_mmapio, M_OFWPROP); + if (str_devname != NULL) + free(str_devname, M_OFWPROP); + return (error); +} + +static int +altera_avgen_fdt_detach(device_t dev) +{ + struct altera_avgen_softc *sc; + + sc = device_get_softc(dev); + altera_avgen_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res); + return (0); +} + +static device_method_t altera_avgen_fdt_methods[] = { + DEVMETHOD(device_probe, altera_avgen_fdt_probe), + DEVMETHOD(device_attach, altera_avgen_fdt_attach), + DEVMETHOD(device_detach, altera_avgen_fdt_detach), + { 0, 0 } +}; + +static driver_t altera_avgen_fdt_driver = { + "altera_avgen", + altera_avgen_fdt_methods, + sizeof(struct altera_avgen_softc), +}; + +DRIVER_MODULE(avgen, simplebus, altera_avgen_fdt_driver, + altera_avgen_devclass, 0, 0); diff --git a/sys/dev/altera/avgen/altera_avgen_nexus.c b/sys/dev/altera/avgen/altera_avgen_nexus.c new file mode 100644 index 0000000..d0e4f9b --- /dev/null +++ b/sys/dev/altera/avgen/altera_avgen_nexus.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2012-2013 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/stat.h> +#include <sys/systm.h> +#include <sys/uio.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <machine/vm.h> + +#include <vm/vm.h> + +#include <dev/altera/avgen/altera_avgen.h> + +static int +altera_avgen_nexus_probe(device_t dev) +{ + + device_set_desc(dev, "Generic Altera Avalon device attachment"); + return (BUS_PROBE_DEFAULT); +} + +static int +altera_avgen_nexus_attach(device_t dev) +{ + struct altera_avgen_softc *sc; + const char *str_fileio, *str_mmapio; + const char *str_devname; + int devunit, error; + + sc = device_get_softc(dev); + sc->avg_dev = dev; + sc->avg_unit = device_get_unit(dev); + + /* + * Query non-standard hints to find out what operations are permitted + * on the device, and whether it is cached. + */ + str_fileio = NULL; + str_mmapio = NULL; + str_devname = NULL; + devunit = -1; + sc->avg_width = 1; + error = resource_int_value(device_get_name(dev), device_get_unit(dev), + ALTERA_AVALON_STR_WIDTH, &sc->avg_width); + if (error != 0 && error != ENOENT) { + device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH); + return (error); + } + (void)resource_string_value(device_get_name(dev), + device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio); + (void)resource_string_value(device_get_name(dev), + device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio); + (void)resource_string_value(device_get_name(dev), + device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname); + (void)resource_int_value(device_get_name(dev), device_get_unit(dev), + ALTERA_AVALON_STR_DEVUNIT, &devunit); + + /* Memory allocation and checking. */ + sc->avg_rid = 0; + sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->avg_rid, RF_ACTIVE); + if (sc->avg_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + return (ENXIO); + } + error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname, + devunit); + if (error != 0) + bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, + sc->avg_res); + return (error); +} + +static int +altera_avgen_nexus_detach(device_t dev) +{ + struct altera_avgen_softc *sc; + + sc = device_get_softc(dev); + altera_avgen_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res); + return (0); +} + +static device_method_t altera_avgen_nexus_methods[] = { + DEVMETHOD(device_probe, altera_avgen_nexus_probe), + DEVMETHOD(device_attach, altera_avgen_nexus_attach), + DEVMETHOD(device_detach, altera_avgen_nexus_detach), + { 0, 0 } +}; + +static driver_t altera_avgen_nexus_driver = { + "altera_avgen", + altera_avgen_nexus_methods, + sizeof(struct altera_avgen_softc), +}; + +DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass, + 0, 0); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart.h b/sys/dev/altera/jtag_uart/altera_jtag_uart.h index 1ff3bcb..5b5b29f 100644 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart.h +++ b/sys/dev/altera/jtag_uart/altera_jtag_uart.h @@ -194,4 +194,6 @@ extern u_int aju_cons_jtag_missed; int altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc); void altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc); +extern devclass_t altera_jtag_uart_devclass; + #endif /* _DEV_ALTERA_JTAG_UART_H_ */ diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c index 679ebe2..ae84597 100644 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c +++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bus.h> #include <sys/cons.h> #include <sys/endian.h> #include <sys/kdb.h> @@ -46,6 +47,8 @@ __FBSDID("$FreeBSD$"); #include <dev/altera/jtag_uart/altera_jtag_uart.h> +devclass_t altera_jtag_uart_devclass; + /* * One-byte buffer as we can't check whether the UART is readable without * actually reading from it, synchronised by a spinlock; this lock also diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c new file mode 100644 index 0000000..47f39a4 --- /dev/null +++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2012 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/bio.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/systm.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <geom/geom_disk.h> + +#include <dev/altera/jtag_uart/altera_jtag_uart.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +/* + * FDT bus attachment for Altera JTAG UARTs. + */ +static int +altera_jtag_uart_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "altera,jtag_uart-11_0")) { + device_set_desc(dev, "Altera JTAG UART"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +altera_jtag_uart_fdt_attach(device_t dev) +{ + struct altera_jtag_uart_softc *sc; + int error; + + error = 0; + sc = device_get_softc(dev); + sc->ajus_dev = dev; + sc->ajus_unit = device_get_unit(dev); + sc->ajus_mem_rid = 0; + sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->ajus_mem_rid, RF_ACTIVE); + if (sc->ajus_mem_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + error = ENXIO; + goto out; + } + + /* + * Interrupt support is optional -- if we can't allocate an IRQ, then + * we fall back on polling. + */ + sc->ajus_irq_rid = 0; + sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE); + if (sc->ajus_irq_res == NULL) + device_printf(dev, + "IRQ unavailable; selecting polled operation\n"); + error = altera_jtag_uart_attach(sc); +out: + if (error) { + if (sc->ajus_irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, + sc->ajus_irq_rid, sc->ajus_irq_res); + if (sc->ajus_mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, + sc->ajus_mem_rid, sc->ajus_mem_res); + } + return (error); +} + +static int +altera_jtag_uart_fdt_detach(device_t dev) +{ + struct altera_jtag_uart_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated", + __func__)); + + altera_jtag_uart_detach(sc); + bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid, + sc->ajus_irq_res); + bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid, + sc->ajus_mem_res); + return (0); +} + +static device_method_t altera_jtag_uart_fdt_methods[] = { + DEVMETHOD(device_probe, altera_jtag_uart_fdt_probe), + DEVMETHOD(device_attach, altera_jtag_uart_fdt_attach), + DEVMETHOD(device_detach, altera_jtag_uart_fdt_detach), + { 0, 0 } +}; + +static driver_t altera_jtag_uart_fdt_driver = { + "altera_jtag_uart", + altera_jtag_uart_fdt_methods, + sizeof(struct altera_jtag_uart_softc), +}; + +DRIVER_MODULE(altera_jtag_uart, simplebus, altera_jtag_uart_fdt_driver, + altera_jtag_uart_devclass, 0, 0); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c index 2592249..2fe772a 100644 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c +++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c @@ -137,7 +137,5 @@ static driver_t altera_jtag_uart_nexus_driver = { sizeof(struct altera_jtag_uart_softc), }; -static devclass_t altera_jtag_uart_devclass; - DRIVER_MODULE(altera_jtag_uart, nexus, altera_jtag_uart_nexus_driver, altera_jtag_uart_devclass, 0, 0); diff --git a/sys/dev/altera/sdcard/altera_sdcard.c b/sys/dev/altera/sdcard/altera_sdcard.c index 4572206..f64b9c5 100644 --- a/sys/dev/altera/sdcard/altera_sdcard.c +++ b/sys/dev/altera/sdcard/altera_sdcard.c @@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$"); * 3. Handle read-only SD Cards. * 4. Tune timeouts based on real-world SD Card speeds. */ +devclass_t altera_sdcard_devclass; void altera_sdcard_attach(struct altera_sdcard_softc *sc) diff --git a/sys/dev/altera/sdcard/altera_sdcard.h b/sys/dev/altera/sdcard/altera_sdcard.h index 4a491c4..a0029a8 100644 --- a/sys/dev/altera/sdcard/altera_sdcard.h +++ b/sys/dev/altera/sdcard/altera_sdcard.h @@ -244,4 +244,6 @@ void altera_sdcard_start(struct altera_sdcard_softc *sc); void altera_sdcard_disk_insert(struct altera_sdcard_softc *sc); void altera_sdcard_disk_remove(struct altera_sdcard_softc *sc); +extern devclass_t altera_sdcard_devclass; + #endif /* _DEV_ALTERA_SDCARD_H_ */ diff --git a/sys/dev/altera/sdcard/altera_sdcard_fdt.c b/sys/dev/altera/sdcard/altera_sdcard_fdt.c new file mode 100644 index 0000000..027ca2d --- /dev/null +++ b/sys/dev/altera/sdcard/altera_sdcard_fdt.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2012 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/bio.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/systm.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <geom/geom_disk.h> + +#include <dev/altera/sdcard/altera_sdcard.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +/* + * FDT bus attachment for the Altera SD Card IP core. + */ +static int +altera_sdcard_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "altera,sdcard_11_2011")) { + device_set_desc(dev, "Altera Secure Data Card IP Core"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +altera_sdcard_fdt_attach(device_t dev) +{ + struct altera_sdcard_softc *sc; + + sc = device_get_softc(dev); + sc->as_dev = dev; + sc->as_unit = device_get_unit(dev); + sc->as_rid = 0; + sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->as_rid, RF_ACTIVE); + if (sc->as_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + return (ENXIO); + } + altera_sdcard_attach(sc); + return (0); +} + +static int +altera_sdcard_fdt_detach(device_t dev) +{ + struct altera_sdcard_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc->as_res != NULL, ("%s: resources not allocated", + __func__)); + altera_sdcard_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res); + return (0); +} + +static device_method_t altera_sdcard_fdt_methods[] = { + DEVMETHOD(device_probe, altera_sdcard_fdt_probe), + DEVMETHOD(device_attach, altera_sdcard_fdt_attach), + DEVMETHOD(device_detach, altera_sdcard_fdt_detach), + { 0, 0 } +}; + +static driver_t altera_sdcard_fdt_driver = { + "altera_sdcardc", + altera_sdcard_fdt_methods, + sizeof(struct altera_sdcard_softc), +}; + +DRIVER_MODULE(altera_sdcard, simplebus, altera_sdcard_fdt_driver, + altera_sdcard_devclass, 0, 0); diff --git a/sys/dev/altera/sdcard/altera_sdcard_nexus.c b/sys/dev/altera/sdcard/altera_sdcard_nexus.c index e0fddcb..88abe1f 100644 --- a/sys/dev/altera/sdcard/altera_sdcard_nexus.c +++ b/sys/dev/altera/sdcard/altera_sdcard_nexus.c @@ -110,7 +110,5 @@ static driver_t altera_sdcard_nexus_driver = { sizeof(struct altera_sdcard_softc), }; -static devclass_t altera_sdcard_devclass; - DRIVER_MODULE(altera_sdcard, nexus, altera_sdcard_nexus_driver, altera_sdcard_devclass, 0, 0); diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index c96e252..5b0595c 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -1351,10 +1351,11 @@ static int ata_raid_read_metadata(device_t subdisk) { devclass_t pci_devclass = devclass_find("pci"); + devclass_t atapci_devclass = devclass_find("atapci"); devclass_t devclass=device_get_devclass(GRANDPARENT(GRANDPARENT(subdisk))); /* prioritize vendor native metadata layout if possible */ - if (devclass == pci_devclass) { + if (devclass == pci_devclass || devclass == atapci_devclass) { switch (pci_get_vendor(GRANDPARENT(device_get_parent(subdisk)))) { case ATA_HIGHPOINT_ID: if (ata_raid_hptv3_read_meta(subdisk, ata_raid_arrays)) diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index 19beffe..ddc4b6a 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -941,6 +941,8 @@ typedef struct { int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */ int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */ int32_t ss_nf_temp_data; /* temperature data taken during nf scan */ + int ss_enabled; + int ss_active; } HAL_SPECTRAL_PARAM; #define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF #define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index bd2580f..e2460ed 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -152,7 +152,6 @@ static void ath_init(void *); static void ath_stop_locked(struct ifnet *); static void ath_stop(struct ifnet *); static int ath_reset_vap(struct ieee80211vap *, u_long); -static void ath_start_queue(struct ifnet *ifp); static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); static int ath_ioctl(struct ifnet *, u_long, caddr_t); @@ -213,6 +212,14 @@ static void ath_dfs_tasklet(void *, int); static void ath_node_powersave(struct ieee80211_node *, int); static int ath_node_set_tim(struct ieee80211_node *, int); +static int ath_transmit(struct ifnet *ifp, struct mbuf *m); +static void ath_qflush(struct ifnet *ifp); + +static void ath_txq_qinit(struct ifnet *ifp); +static void ath_txq_qflush(struct ifnet *ifp); +static int ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0); +static void ath_txq_qrun(struct ifnet *ifp); + #ifdef IEEE80211_SUPPORT_TDMA #include <dev/ath/if_ath_tdma.h> #endif @@ -429,12 +436,20 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", ifp->if_xname); + sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT, + taskqueue_thread_enqueue, &sc->sc_tx_tq); + taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET, + "%s TX taskq", ifp->if_xname); + TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc); TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc); - TASK_INIT(&sc->sc_txqtask,0, ath_txq_sched_tasklet, sc); - TASK_INIT(&sc->sc_fataltask,0, ath_fatal_proc, sc); + TASK_INIT(&sc->sc_txqtask, 0, ath_txq_sched_tasklet, sc); + TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc); + + /* XXX make this a higher priority taskqueue? */ + TASK_INIT(&sc->sc_txpkttask, 0, ath_start_task, sc); /* * Allocate hardware transmit queues: one queue for @@ -554,13 +569,18 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - ifp->if_start = ath_start_queue; + /* XXX net80211 uses if_start to re-start ifnet processing */ + ifp->if_start = ath_start; + ifp->if_transmit = ath_transmit; + ifp->if_qflush = ath_qflush; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_init; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); + ath_txq_qinit(ifp); + ic->ic_ifp = ifp; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; @@ -966,16 +986,16 @@ ath_detach(struct ath_softc *sc) ath_stop(ifp); ieee80211_ifdetach(ifp->if_l2com); taskqueue_free(sc->sc_tq); + taskqueue_free(sc->sc_tx_tq); #ifdef ATH_TX99_DIAG if (sc->sc_tx99 != NULL) sc->sc_tx99->detach(sc->sc_tx99); #endif ath_rate_detach(sc->sc_rc); - #ifdef ATH_DEBUG_ALQ if_ath_alq_tidyup(&sc->sc_alq); #endif - + ath_txq_qflush(ifp); ath_spectral_detach(sc); ath_dfs_detach(sc); ath_desc_free(sc); @@ -2454,6 +2474,14 @@ ath_buf_clone(struct ath_softc *sc, const struct ath_buf *bf) tbf->bf_flags = bf->bf_flags & ~ATH_BUF_BUSY; tbf->bf_status = bf->bf_status; tbf->bf_m = bf->bf_m; + /* + * XXX Copy the node reference, the caller is responsible + * for deleting the node reference before it frees its + * buffer. + * + * XXX It's done like this so we don't call the net80211 + * code whilst having active TX queue locks held. + */ tbf->bf_node = bf->bf_node; /* will be setup by the chain/setup function */ tbf->bf_lastds = NULL; @@ -2498,13 +2526,70 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype) } static void -ath_start_queue(struct ifnet *ifp) +ath_qflush(struct ifnet *ifp) { - struct ath_softc *sc = ifp->if_softc; - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start"); + /* XXX complete/suspend TX */ + ath_txq_qflush(ifp); + + /* Unsuspend TX? */ +} + +/* + * Transmit a frame from net80211. + */ +static int +ath_transmit(struct ifnet *ifp, struct mbuf *m) +{ + struct ieee80211_node *ni; + struct ath_softc *sc = (struct ath_softc *) ifp->if_softc; + + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + + if (ath_txq_qadd(ifp, m) < 0) { + /* + * If queuing fails, the if_transmit() API makes the + * callee responsible for freeing the mbuf (rather than + * the caller, who just assumes the mbuf has been dealt + * with somehow). + * + * BUT, net80211 will free node references if if_transmit() + * fails _on encapsulated buffers_. Since drivers + * only get fully encapsulated frames from net80211 (via + * raw or otherwise APIs), we must be absolutely careful + * to not free the node ref or things will get loopy + * down the track. + * + * For tx fragments, the TX code must free whatever + * new references it created, but NOT the original + * TX node ref that was passed in. + */ + ath_freetx(m); + return (ENOBUFS); + } + + /* + * Unconditionally kick the taskqueue. + * + * Now, there's a subtle race condition possible here if we + * went down the path of only kicking the taskqueue if it + * wasn't running. If we're not absolutely, positively + * careful, we could have a small race window between + * finishing the taskqueue and clearing the TX flag, which + * would be interpreted in _this_ context as "we don't need + * to kick the TX taskqueue, as said taskqueue is already + * running." + * + * It's a problem in some of the 1GE/10GE NIC drivers. + * So until a _correct_ method for implementing this is + * drafted up and written, which avoids (potentially) + * large amounts of locking contention per-frame, let's + * just do the inefficient "kick taskqueue each time" + * method. + */ ath_tx_kick(sc); - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished"); + + return (0); } void @@ -2531,9 +2616,7 @@ ath_start_task(void *arg, int npending) sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - ATH_TX_LOCK(sc); - ath_start(sc->sc_ifp); - ATH_TX_UNLOCK(sc); + ath_txq_qrun(ifp); ATH_PCU_LOCK(sc); sc->sc_txstart_cnt--; @@ -2541,91 +2624,298 @@ ath_start_task(void *arg, int npending) ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: finished"); } -void -ath_start(struct ifnet *ifp) +/* + * Pending TX buffer chain management routines. + */ + + +/* + * Initialise the TX queue! + */ +static void +ath_txq_qinit(struct ifnet *ifp) +{ + struct ath_softc *sc = ifp->if_softc; + + TAILQ_INIT(&sc->sc_txbuf_list); +} + +/* + * Add this mbuf to the TX buffer chain. + * + * This allocates an ath_buf, links the mbuf into it, and + * appends it to the end of the TX buffer chain. + * It doesn't fill out the ath_buf in any way besides + * that. + * + * Since the mbuf may be a list of mbufs representing + * 802.11 fragments, handle allocating ath_bufs for each + * of the mbuf fragments. + * + * If we queued it, 0 is returned. Else, < 0 is returned. + * + * If <0 is returned, the sender is responsible for + * freeing the mbuf if appropriate. + */ +static int +ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) { struct ath_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; struct ath_buf *bf; - struct mbuf *m, *next; ath_bufhead frags; - int npkts = 0; + struct ieee80211_node *ni; + struct mbuf *m; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) - return; + /* XXX recursive TX completion -> TX? */ + ATH_TX_UNLOCK_ASSERT(sc); - ATH_TX_LOCK_ASSERT(sc); + /* + * We grab the node pointer, but we don't deref + * the node. The caller must be responsible for + * freeing the node reference if it decides to + * free the mbuf. + */ + ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif; - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called"); + ATH_TXBUF_LOCK(sc); + if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { + /* XXX increment counter? */ + ATH_TXBUF_UNLOCK(sc); + IF_LOCK(&ifp->if_snd); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + IF_UNLOCK(&ifp->if_snd); + return (-1); + } + ATH_TXBUF_UNLOCK(sc); - for (;;) { + /* + * Grab a TX buffer and associated resources. + */ + bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); + if (bf == NULL) { + device_printf(sc->sc_dev, + "%s: couldn't allocate a buffer\n", + __func__); + return (-1); + } + + /* Setup the initial buffer node contents */ + bf->bf_m = m0; + bf->bf_node = ni; + + /* + * Check for fragmentation. If this frame + * has been broken up verify we have enough + * buffers to send all the fragments so all + * go out or none... + */ + TAILQ_INIT(&frags); + if (m0->m_flags & M_FRAG) + DPRINTF(sc, ATH_DEBUG_XMIT, "%s: txfrag\n", __func__); + if ((m0->m_flags & M_FRAG) && + !ath_txfrag_setup(sc, &frags, m0, ni)) { + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: out of txfrag buffers\n", __func__); + sc->sc_stats.ast_tx_nofrag++; + ifp->if_oerrors++; + goto bad; + } + + /* + * Don't stuff the non-fragment frame onto the fragment + * queue. ath_txfrag_cleanup() should only be called on fragments - + * ie, the _extra_ ieee80211_node references - and not the single + * node reference already done as part of the net08211 TX call + * into the driver. + */ + + ATH_TX_LOCK(sc); + + /* + * Throw the single frame onto the queue. + */ + TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); + + /* + * Update next packet duration length if it's a fragment. + * It's needed for accurate NAV calculations (which for + * fragments include the length of the NEXT fragment.) + */ + if (m0->m_nextpkt != NULL) + bf->bf_state.bfs_nextpktlen = + m0->m_nextpkt->m_pkthdr.len; + + /* + * Append the fragments. We have to populate bf and node + * references here as although the txfrag setup code does + * create buffers and increment the node ref, it doesn't + * populate the fields for us. + */ + m = m0->m_nextpkt; + while ( (bf = TAILQ_FIRST(&frags)) != NULL) { + bf->bf_m = m; + bf->bf_node = ni; + device_printf(sc->sc_dev, "%s: adding bf=%p, m=%p, ni=%p\n", + __func__, + bf, + bf->bf_m, + bf->bf_node); + TAILQ_REMOVE(&frags, bf, bf_list); + TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); + + /* + * For duration (NAV) calculations, we need + * to know the next fragment size. + * + * XXX This isn't entirely accurate as it doesn't + * take pad bytes and such into account, but it'll do + * for fragment length / NAV calculations. + */ + if (m->m_nextpkt != NULL) + bf->bf_state.bfs_nextpktlen = + m->m_nextpkt->m_pkthdr.len; + + m = m->m_nextpkt; + } + ATH_TX_UNLOCK(sc); + + return (0); +bad: + device_printf(sc->sc_dev, "%s: bad?!\n", __func__); + bf->bf_m = NULL; + bf->bf_node = NULL; + ATH_TXBUF_LOCK(sc); + ath_returnbuf_head(sc, bf); + ath_txfrag_cleanup(sc, &frags, ni); + ATH_TXBUF_UNLOCK(sc); + return (-1); +} + +/* + * Flush the pending TX buffer chain. + */ +static void +ath_txq_qflush(struct ifnet *ifp) +{ + struct ath_softc *sc = ifp->if_softc; + ath_bufhead txlist; + struct ath_buf *bf; + + device_printf(sc->sc_dev, "%s: called\n", __func__); + TAILQ_INIT(&txlist); + + /* Grab lock */ + ATH_TX_LOCK(sc); + + /* Copy everything out of sc_txbuf_list into txlist */ + TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); + + /* Unlock */ + ATH_TX_UNLOCK(sc); + + /* Now, walk the list, freeing things */ + while ((bf = TAILQ_FIRST(&txlist)) != NULL) { + TAILQ_REMOVE(&txlist, bf, bf_list); + + if (bf->bf_node) + ieee80211_free_node(bf->bf_node); + + m_free(bf->bf_m); + + /* XXX paranoia! */ + bf->bf_m = NULL; + bf->bf_node = NULL; + + /* + * XXX Perhaps do a second pass with the TXBUF lock + * held and free them all at once? + */ ATH_TXBUF_LOCK(sc); - if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { - /* XXX increment counter? */ - ATH_TXBUF_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - break; - } + ath_returnbuf_head(sc, bf); ATH_TXBUF_UNLOCK(sc); - + } +} + +/* + * Walk the TX buffer queue and call ath_tx_start() on each + * of them. + */ +static void +ath_txq_qrun(struct ifnet *ifp) +{ + struct ath_softc *sc = ifp->if_softc; + ath_bufhead txlist; + struct ath_buf *bf, *bf_next; + struct ieee80211_node *ni; + struct mbuf *m; + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) + return; + + TAILQ_INIT(&txlist); + + /* + * Grab the frames to transmit from the tx queue + */ + + /* Copy everything out of sc_txbuf_list into txlist */ + ATH_TX_LOCK(sc); + TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); + ATH_TX_UNLOCK(sc); + + /* + * For now, the ath_tx_start() code sits behind the same lock; + * worry about serialising this in a taskqueue later. + */ + + ATH_TX_LOCK(sc); + + /* + * Attempt to transmit each frame. + * + * In the old code path - if a TX fragment fails, subsequent + * fragments in that group would be aborted. + * + * It would be nice to chain together TX fragments in this + * way so they can be aborted together. + */ + TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) { /* - * Grab a TX buffer and associated resources. + * Clear, because we're going to reuse this + * as a real ath_buf now */ - bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); - if (bf == NULL) - break; + ni = bf->bf_node; + m = bf->bf_m; + + bf->bf_node = NULL; + bf->bf_m = NULL; - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) { - ATH_TXBUF_LOCK(sc); - ath_returnbuf_head(sc, bf); - ATH_TXBUF_UNLOCK(sc); - break; - } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - npkts ++; /* - * Check for fragmentation. If this frame - * has been broken up verify we have enough - * buffers to send all the fragments so all - * go out or none... + * Remove it from the list. */ - TAILQ_INIT(&frags); - if ((m->m_flags & M_FRAG) && - !ath_txfrag_setup(sc, &frags, m, ni)) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: out of txfrag buffers\n", __func__); - sc->sc_stats.ast_tx_nofrag++; - ifp->if_oerrors++; - ath_freetx(m); - goto bad; - } - ifp->if_opackets++; - nextfrag: + TAILQ_REMOVE(&txlist, bf, bf_list); + /* - * Pass the frame to the h/w for transmission. - * Fragmented frames have each frag chained together - * with m_nextpkt. We know there are sufficient ath_buf's - * to send all the frags because of work done by - * ath_txfrag_setup. We leave m_nextpkt set while - * calling ath_tx_start so it can use it to extend the - * the tx duration to cover the subsequent frag and - * so it can reclaim all the mbufs in case of an error; - * ath_tx_start clears m_nextpkt once it commits to - * handing the frame to the hardware. + * If we fail, free this buffer and go to the next one; + * ath_tx_start() frees the mbuf but not the node + * reference. */ - next = m->m_nextpkt; if (ath_tx_start(sc, ni, bf, m)) { - bad: + /* + * XXX m is freed by ath_tx_start(); node reference + * is not! + */ + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: failed; bf=%p, ni=%p, m=%p\n", + __func__, + bf, + ni, + m); ifp->if_oerrors++; - reclaim: bf->bf_m = NULL; bf->bf_node = NULL; ATH_TXBUF_LOCK(sc); ath_returnbuf_head(sc, bf); - ath_txfrag_cleanup(sc, &frags, ni); ATH_TXBUF_UNLOCK(sc); /* * XXX todo, free the node outside of @@ -2633,37 +2923,84 @@ ath_start(struct ifnet *ifp) */ if (ni != NULL) ieee80211_free_node(ni); - continue; + } else { + /* + * Check here if the node is in power save state. + * XXX we should hold a node ref here, and release + * it after the TX has completed. + */ + ath_tx_update_tim(sc, ni, 1); + ifp->if_opackets++; } /* - * Check here if the node is in power save state. + * XXX should check for state change and flip out + * if needed. */ - ath_tx_update_tim(sc, ni, 1); + } + ATH_TX_UNLOCK(sc); - if (next != NULL) { - /* - * Beware of state changing between frags. - * XXX check sta power-save state? - */ - if (ni->ni_vap->iv_state != IEEE80211_S_RUN) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: flush fragmented packet, state %s\n", - __func__, - ieee80211_state_name[ni->ni_vap->iv_state]); - ath_freetx(next); - goto reclaim; - } - m = next; - bf = TAILQ_FIRST(&frags); - KASSERT(bf != NULL, ("no buf for txfrag")); - TAILQ_REMOVE(&frags, bf, bf_list); - goto nextfrag; + /* + * If we break out early (eg a state change) we should prepend these + * frames onto the TX queue. + */ +} + +/* + * This is now primarily used by the net80211 layer to kick-start + * queue processing. + */ +void +ath_start(struct ifnet *ifp) +{ + struct mbuf *m; + struct ath_softc *sc = ifp->if_softc; + struct ieee80211_node *ni; + int npkts = 0; + + ATH_TX_UNLOCK_ASSERT(sc); + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) + return; + + /* + * If we're below the free buffer limit, don't dequeue anything. + * The original code would not dequeue anything from the queue + * if allocating an ath_buf failed. + * + * For if_transmit, we have to either queue or drop the frame. + * So we have to try and queue it _somewhere_. + */ + for (;;) { + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) { + break; } - sc->sc_wd_timer = 5; + /* + * If we do fail here, just break out for now + * and wait until we've transmitted something + * before we attempt again? + */ + if (ath_txq_qadd(ifp, m) < 0) { + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: ath_txq_qadd failed\n", + __func__); + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + if (ni != NULL) + ieee80211_free_node(ni); + ath_freetx(m); + break; + } + npkts++; } - ATH_KTR(sc, ATH_KTR_TX, 1, "ath_start: finished; npkts=%d", npkts); + + /* + * Kick the taskqueue into activity, but only if we + * queued something. + */ + if (npkts > 0) + ath_tx_kick(sc); } static int diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index c3b101c..39604c6 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -124,9 +124,8 @@ static inline void ath_tx_kick(struct ath_softc *sc) { - ATH_TX_LOCK(sc); - ath_start(sc->sc_ifp); - ATH_TX_UNLOCK(sc); + /* XXX eventually try sc_tx_tq? */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_txpkttask); } #endif diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index 5a39d16..368c05c 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -845,6 +845,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) int16_t nf; u_int64_t tsf; int npkts = 0; + int kickpcu = 0; /* XXX we must not hold the ATH_LOCK here */ ATH_UNLOCK_ASSERT(sc); @@ -852,6 +853,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) ATH_PCU_LOCK(sc); sc->sc_rxproc_cnt++; + kickpcu = sc->sc_kickpcu; ATH_PCU_UNLOCK(sc); DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__); @@ -866,7 +868,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) * latency can jump by quite a bit, causing throughput * degredation. */ - if (npkts >= ATH_RX_MAX) + if (!kickpcu && npkts >= ATH_RX_MAX) break; bf = TAILQ_FIRST(&sc->sc_rxbuf); @@ -961,6 +963,9 @@ rx_proc_next: __func__, npkts); /* XXX rxslink? */ +#if 0 + ath_startrecv(sc); +#else /* * XXX can we hold the PCU lock here? * Are there any net80211 buffer calls involved? @@ -970,6 +975,7 @@ rx_proc_next: ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ +#endif ath_hal_intrset(ah, sc->sc_imask); sc->sc_kickpcu = 0; diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index 5de29af..abb180b 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -505,6 +505,33 @@ ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS) return 0; } +static int +ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int val = 0; + int error; + uint32_t mask = 0xffffffff; + uint32_t *sp; + uint32_t rsize; + struct ath_hal *ah = sc->sc_ah; + + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return error; + if (val == 0) + return 0; + + /* Do a hang check */ + if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS, + &mask, sizeof(mask), + (void *) &sp, &rsize)) + return (0); + device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp); + + val = 0; + return 0; +} #ifdef ATH_DEBUG_ALQ static int @@ -661,6 +688,10 @@ ath_sysctlattach(struct ath_softc *sc) "forcebstuck", CTLTYPE_INT | CTLFLAG_RW, sc, 0, ath_sysctl_forcebstuck, "I", ""); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "hangcheck", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_hangcheck, "I", ""); + if (ath_hal_hasintmit(ah)) { SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0, diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 263e69c..1b1cbe6 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -1124,7 +1124,11 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) dur = rt->info[rix].lpAckDuration; if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { dur += dur; /* additional SIFS+ACK */ - KASSERT(bf->bf_m->m_nextpkt != NULL, ("no fragment")); + if (bf->bf_state.bfs_nextpktlen == 0) { + device_printf(sc->sc_dev, + "%s: next txfrag len=0?\n", + __func__); + } /* * Include the size of next fragment so NAV is * updated properly. The last fragment uses only @@ -1135,7 +1139,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) * first fragment! */ dur += ath_hal_computetxtime(ah, rt, - bf->bf_m->m_nextpkt->m_pkthdr.len, + bf->bf_state.bfs_nextpktlen, rix, shortPreamble); } if (isfrag) { diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 2e170a3..53f087a 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -279,6 +279,8 @@ struct ath_buf { int32_t bfs_keyix; /* crypto key index */ int32_t bfs_txantenna; /* TX antenna config */ + uint16_t bfs_nextpktlen; /* length of next frag pkt */ + /* Make this an 8 bit value? */ enum ieee80211_protmode bfs_protmode; @@ -494,6 +496,13 @@ struct ath_softc { struct ath_tx_methods sc_tx; struct ath_tx_edma_fifo sc_txedma[HAL_NUM_TX_QUEUES]; + /* + * This is (currently) protected by the TX queue lock; + * it should migrate to a separate lock later + * so as to minimise contention. + */ + ath_bufhead sc_txbuf_list; + int sc_rx_statuslen; int sc_tx_desclen; int sc_tx_statuslen; @@ -514,6 +523,7 @@ struct ath_softc { struct mtx sc_tx_mtx; /* TX access mutex */ char sc_tx_mtx_name[32]; struct taskqueue *sc_tq; /* private task queue */ + struct taskqueue *sc_tx_tq; /* private TX task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ struct ath_ratectrl *sc_rc; /* tx rate control support */ struct ath_tx99 *sc_tx99; /* tx99 adjunct state */ @@ -660,6 +670,7 @@ struct ath_softc { struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ struct task sc_txtask; /* tx int processing */ struct task sc_txqtask; /* tx proc processing */ + struct task sc_txpkttask; /* tx frame processing */ struct ath_descdma sc_txcompdma; /* TX EDMA completion */ struct mtx sc_txcomplock; /* TX EDMA completion lock */ diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c index e58ffc7..199fcb1 100644 --- a/sys/dev/atkbdc/atkbd.c +++ b/sys/dev/atkbdc/atkbd.c @@ -66,7 +66,7 @@ static timeout_t atkbd_timeout; static void atkbd_shutdown_final(void *v); int -atkbd_probe_unit(int unit, int ctlr, int irq, int flags) +atkbd_probe_unit(device_t dev, int irq, int flags) { keyboard_switch_t *sw; int args[2]; @@ -76,27 +76,29 @@ atkbd_probe_unit(int unit, int ctlr, int irq, int flags) if (sw == NULL) return ENXIO; - args[0] = ctlr; + args[0] = device_get_unit(device_get_parent(dev)); args[1] = irq; - error = (*sw->probe)(unit, args, flags); + error = (*sw->probe)(device_get_unit(dev), args, flags); if (error) return error; return 0; } int -atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags) +atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags) { keyboard_switch_t *sw; int args[2]; int error; + int unit; sw = kbd_get_switch(ATKBD_DRIVER_NAME); if (sw == NULL) return ENXIO; /* reset, initialize and enable the device */ - args[0] = ctlr; + unit = device_get_unit(dev); + args[0] = device_get_unit(device_get_parent(dev)); args[1] = irq; *kbd = NULL; error = (*sw->probe)(unit, args, flags); @@ -401,7 +403,7 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) bcopy(&key_map, keymap, sizeof(key_map)); bcopy(&accent_map, accmap, sizeof(accent_map)); bcopy(fkey_tab, fkeymap, - imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); + imin(fkeymap_size * sizeof(fkeymap[0]), sizeof(fkey_tab))); kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); kbd->kb_data = (void *)state; @@ -424,8 +426,8 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; if (KBD_HAS_DEVICE(kbd) - && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) - && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { + && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) + && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { kbd_unregister(kbd); error = ENXIO; goto bad; @@ -485,8 +487,7 @@ atkbd_intr(keyboard_t *kbd, void *arg) * The keyboard was not detected before; * it must have been reconnected! */ - init_keyboard(state->kbdc, &kbd->kb_type, - kbd->kb_config); + init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config); KBD_FOUND_DEVICE(kbd); atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); get_typematic(kbd); @@ -645,7 +646,7 @@ next_code: goto next_code; } break; - case 0xE0: /* 0xE0 prefix */ + case 0xE0: /* 0xE0 prefix */ state->ks_prefix = 0; switch (keycode) { case 0x1C: /* right enter key */ @@ -655,57 +656,57 @@ next_code: keycode = 0x5A; break; case 0x35: /* keypad divide key */ - keycode = 0x5B; - break; + keycode = 0x5B; + break; case 0x37: /* print scrn key */ - keycode = 0x5C; - break; + keycode = 0x5C; + break; case 0x38: /* right alt key (alt gr) */ - keycode = 0x5D; - break; + keycode = 0x5D; + break; case 0x46: /* ctrl-pause/break on AT 101 (see below) */ keycode = 0x68; - break; + break; case 0x47: /* grey home key */ - keycode = 0x5E; - break; + keycode = 0x5E; + break; case 0x48: /* grey up arrow key */ - keycode = 0x5F; - break; + keycode = 0x5F; + break; case 0x49: /* grey page up key */ - keycode = 0x60; - break; + keycode = 0x60; + break; case 0x4B: /* grey left arrow key */ - keycode = 0x61; - break; + keycode = 0x61; + break; case 0x4D: /* grey right arrow key */ - keycode = 0x62; - break; + keycode = 0x62; + break; case 0x4F: /* grey end key */ - keycode = 0x63; - break; + keycode = 0x63; + break; case 0x50: /* grey down arrow key */ - keycode = 0x64; - break; + keycode = 0x64; + break; case 0x51: /* grey page down key */ - keycode = 0x65; - break; + keycode = 0x65; + break; case 0x52: /* grey insert key */ - keycode = 0x66; - break; + keycode = 0x66; + break; case 0x53: /* grey delete key */ - keycode = 0x67; - break; - /* the following 3 are only used on the MS "Natural" keyboard */ + keycode = 0x67; + break; + /* the following 3 are only used on the MS "Natural" keyboard */ case 0x5b: /* left Window key */ - keycode = 0x69; - break; + keycode = 0x69; + break; case 0x5c: /* right Window key */ - keycode = 0x6a; - break; + keycode = 0x6a; + break; case 0x5d: /* menu key */ - keycode = 0x6b; - break; + keycode = 0x6b; + break; case 0x5e: /* power key */ keycode = 0x6d; break; @@ -716,10 +717,10 @@ next_code: keycode = 0x6f; break; default: /* ignore everything else */ - goto next_code; + goto next_code; } break; - case 0xE1: /* 0xE1 prefix */ + case 0xE1: /* 0xE1 prefix */ /* * The pause/break key on the 101 keyboard produces: * E1-1D-45 E1-9D-C5 @@ -728,10 +729,10 @@ next_code: */ state->ks_prefix = 0; if (keycode == 0x1D) - state->ks_prefix = 0x1D; + state->ks_prefix = 0x1D; goto next_code; /* NOT REACHED */ - case 0x1D: /* pause / break */ + case 0x1D: /* pause / break */ state->ks_prefix = 0; if (keycode != 0x45) goto next_code; @@ -743,7 +744,7 @@ next_code: switch (keycode) { case 0x37: /* *(numpad)/print screen */ if (state->ks_flags & SHIFTS) - keycode = 0x5c; /* print screen */ + keycode = 0x5c; /* print screen */ break; case 0x45: /* num lock/pause */ if (state->ks_flags & CTLS) @@ -1177,7 +1178,7 @@ get_kbd_echo(KBDC kbdc) */ return ENXIO; } - + return 0; } @@ -1275,7 +1276,7 @@ init_keyboard(KBDC kbdc, int *type, int flags) } if (bootverbose) printf("atkbd: the current kbd controller command byte %04x\n", - c); + c); #if 0 /* override the keyboard lock switch */ c |= KBD_OVERRIDE_KBD_LOCK; @@ -1415,52 +1416,49 @@ init_keyboard(KBDC kbdc, int *type, int flags) static int write_kbd(KBDC kbdc, int command, int data) { - int s; + int s; - /* prevent the timeout routine from polling the keyboard */ - if (!kbdc_lock(kbdc, TRUE)) - return EBUSY; + /* prevent the timeout routine from polling the keyboard */ + if (!kbdc_lock(kbdc, TRUE)) + return EBUSY; - /* disable the keyboard and mouse interrupt */ - s = spltty(); + /* disable the keyboard and mouse interrupt */ + s = spltty(); #if 0 - c = get_controller_command_byte(kbdc); - if ((c == -1) - || !set_controller_command_byte(kbdc, - kbdc_get_device_mask(kbdc), - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { - /* CONTROLLER ERROR */ - kbdc_lock(kbdc, FALSE); + c = get_controller_command_byte(kbdc); + if ((c == -1) + || !set_controller_command_byte(kbdc, + kbdc_get_device_mask(kbdc), + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { + /* CONTROLLER ERROR */ + kbdc_lock(kbdc, FALSE); + splx(s); + return EIO; + } + /* + * Now that the keyboard controller is told not to generate + * the keyboard and mouse interrupts, call `splx()' to allow + * the other tty interrupts. The clock interrupt may also occur, + * but the timeout routine (`scrn_timer()') will be blocked + * by the lock flag set via `kbdc_lock()' + */ splx(s); - return EIO; - } - /* - * Now that the keyboard controller is told not to generate - * the keyboard and mouse interrupts, call `splx()' to allow - * the other tty interrupts. The clock interrupt may also occur, - * but the timeout routine (`scrn_timer()') will be blocked - * by the lock flag set via `kbdc_lock()' - */ - splx(s); #endif - - if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) - send_kbd_command(kbdc, KBDC_ENABLE_KBD); - + if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) + send_kbd_command(kbdc, KBDC_ENABLE_KBD); #if 0 - /* restore the interrupts */ - if (!set_controller_command_byte(kbdc, - kbdc_get_device_mask(kbdc), + /* restore the interrupts */ + if (!set_controller_command_byte(kbdc, kbdc_get_device_mask(kbdc), c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { - /* CONTROLLER ERROR */ - } + /* CONTROLLER ERROR */ + } #else - splx(s); + splx(s); #endif - kbdc_lock(kbdc, FALSE); + kbdc_lock(kbdc, FALSE); - return 0; + return 0; } static int diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c index 8181820..dd0a9d6 100644 --- a/sys/dev/atkbdc/atkbd_atkbdc.c +++ b/sys/dev/atkbdc/atkbd_atkbdc.c @@ -104,9 +104,7 @@ atkbdprobe(device_t dev) bus_release_resource(dev, SYS_RES_IRQ, rid, res); /* probe the device */ - return atkbd_probe_unit(device_get_unit(dev), - device_get_unit(device_get_parent(dev)), - irq, flags); + return atkbd_probe_unit(dev, irq, flags); } static int @@ -124,9 +122,7 @@ atkbdattach(device_t dev) rid = KBDC_RID_KBD; irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid); flags = device_get_flags(dev); - error = atkbd_attach_unit(device_get_unit(dev), &kbd, - device_get_unit(device_get_parent(dev)), - irq, flags); + error = atkbd_attach_unit(dev, &kbd, irq, flags); if (error) return error; diff --git a/sys/dev/atkbdc/atkbdreg.h b/sys/dev/atkbdc/atkbdreg.h index cf7ee6b..3d09e44 100644 --- a/sys/dev/atkbdc/atkbdreg.h +++ b/sys/dev/atkbdc/atkbdreg.h @@ -39,9 +39,8 @@ #ifdef _KERNEL -int atkbd_probe_unit(int unit, int ctlr, int irq, int flags); -int atkbd_attach_unit(int unit, keyboard_t **kbd, - int ctlr, int irq, int flags); +int atkbd_probe_unit(device_t dev, int irq, int flags); +int atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags); #endif diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index 3291f03..a3f0a4a 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -1203,13 +1203,21 @@ ciss_identify_adapter(struct ciss_softc *sc) /* XXX only really required for old 5300 adapters? */ sc->ciss_flags |= CISS_FLAG_BMIC_ABORT; + /* + * Earlier controller specs do not contain these config + * entries, so assume that a 0 means its old and assign + * these values to the defaults that were established + * when this driver was developed for them + */ + if (sc->ciss_cfg->max_logical_supported == 0) + sc->ciss_cfg->max_logical_supported = CISS_MAX_LOGICAL; + if (sc->ciss_cfg->max_physical_supported == 0) + sc->ciss_cfg->max_physical_supported = CISS_MAX_PHYSICAL; /* print information */ if (bootverbose) { -#if 0 /* XXX proxy volumes??? */ ciss_printf(sc, " %d logical drive%s configured\n", sc->ciss_id->configured_logical_drives, (sc->ciss_id->configured_logical_drives == 1) ? "" : "s"); -#endif ciss_printf(sc, " firmware %4.4s\n", sc->ciss_id->running_firmware_revision); ciss_printf(sc, " %d SCSI channels\n", sc->ciss_id->scsi_bus_count); @@ -1232,6 +1240,9 @@ ciss_identify_adapter(struct ciss_softc *sc) "\20\1ultra2\2ultra3\10fibre1\11fibre2\n"); ciss_printf(sc, " server name '%.16s'\n", sc->ciss_cfg->server_name); ciss_printf(sc, " heartbeat 0x%x\n", sc->ciss_cfg->heartbeat); + ciss_printf(sc, " max logical logical volumes: %d\n", sc->ciss_cfg->max_logical_supported); + ciss_printf(sc, " max physical disks supported: %d\n", sc->ciss_cfg->max_physical_supported); + ciss_printf(sc, " max physical disks per logical volume: %d\n", sc->ciss_cfg->max_physical_per_logical); } out: @@ -1319,7 +1330,7 @@ ciss_report_luns(struct ciss_softc *sc, int opcode, int nunits) break; case CISS_CMD_STATUS_DATA_OVERRUN: ciss_printf(sc, "WARNING: more units than driver limit (%d)\n", - CISS_MAX_LOGICAL); + sc->ciss_cfg->max_logical_supported); break; default: ciss_printf(sc, "error detecting logical drive configuration (%s)\n", @@ -1353,7 +1364,7 @@ ciss_init_logical(struct ciss_softc *sc) debug_called(1); cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS, - CISS_MAX_LOGICAL); + sc->ciss_cfg->max_logical_supported); if (cll == NULL) { error = ENXIO; goto out; @@ -1361,9 +1372,9 @@ ciss_init_logical(struct ciss_softc *sc) /* sanity-check reply */ ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address)); - if ((ndrives < 0) || (ndrives > CISS_MAX_LOGICAL)) { + if ((ndrives < 0) || (ndrives > sc->ciss_cfg->max_logical_supported)) { ciss_printf(sc, "adapter claims to report absurd number of logical drives (%d > %d)\n", - ndrives, CISS_MAX_LOGICAL); + ndrives, sc->ciss_cfg->max_logical_supported); error = ENXIO; goto out; } @@ -1386,19 +1397,20 @@ ciss_init_logical(struct ciss_softc *sc) for (i = 0; i <= sc->ciss_max_logical_bus; i++) { sc->ciss_logical[i] = - malloc(CISS_MAX_LOGICAL * sizeof(struct ciss_ldrive), + malloc(sc->ciss_cfg->max_logical_supported * + sizeof(struct ciss_ldrive), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); if (sc->ciss_logical[i] == NULL) { error = ENXIO; goto out; } - for (j = 0; j < CISS_MAX_LOGICAL; j++) + for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) sc->ciss_logical[i][j].cl_status = CISS_LD_NONEXISTENT; } - for (i = 0; i < CISS_MAX_LOGICAL; i++) { + for (i = 0; i < sc->ciss_cfg->max_logical_supported; i++) { if (i < ndrives) { struct ciss_ldrive *ld; int bus, target; @@ -1440,7 +1452,7 @@ ciss_init_physical(struct ciss_softc *sc) target = 0; cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS, - CISS_MAX_PHYSICAL); + sc->ciss_cfg->max_physical_supported); if (cll == NULL) { error = ENXIO; goto out; @@ -1983,7 +1995,7 @@ ciss_free(struct ciss_softc *sc) bus_dma_tag_destroy(sc->ciss_parent_dmat); if (sc->ciss_logical) { for (i = 0; i <= sc->ciss_max_logical_bus; i++) { - for (j = 0; j < CISS_MAX_LOGICAL; j++) { + for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) { if (sc->ciss_logical[i][j].cl_ldrive) free(sc->ciss_logical[i][j].cl_ldrive, CISS_MALLOC_CLASS); if (sc->ciss_logical[i][j].cl_lstatus) @@ -2966,9 +2978,9 @@ ciss_cam_action(struct cam_sim *sim, union ccb *ccb) cpi->hba_inquiry = PI_TAG_ABLE; /* XXX is this correct? */ cpi->target_sprt = 0; cpi->hba_misc = 0; - cpi->max_target = CISS_MAX_LOGICAL; + cpi->max_target = sc->ciss_cfg->max_logical_supported; cpi->max_lun = 0; /* 'logical drive' channel only */ - cpi->initiator_id = CISS_MAX_LOGICAL; + cpi->initiator_id = sc->ciss_cfg->max_logical_supported; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "msmith@freebsd.org", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); @@ -3879,7 +3891,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc) * drive address. */ cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS, - CISS_MAX_LOGICAL); + sc->ciss_cfg->max_logical_supported); if (cll == NULL) return; @@ -3890,7 +3902,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc) * firmware. */ for (i = 0; i < sc->ciss_max_logical_bus; i++) { - for (j = 0; j < CISS_MAX_LOGICAL; j++) { + for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) { ld = &sc->ciss_logical[i][j]; if (ld->cl_update == 0) @@ -4059,7 +4071,7 @@ ciss_notify_hotplug(struct ciss_softc *sc, struct ciss_notify *cn) * Rescan the physical lun list for new items */ cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS, - CISS_MAX_PHYSICAL); + sc->ciss_cfg->max_physical_supported); if (cll == NULL) { ciss_printf(sc, "Warning, cannot get physical lun list\n"); break; @@ -4307,7 +4319,7 @@ ciss_print_adapter(struct ciss_softc *sc) "\20\1notify_ok\2control_open\3aborting\4running\21fake_synch\22bmic_abort\n"); for (i = 0; i < sc->ciss_max_logical_bus; i++) { - for (j = 0; j < CISS_MAX_LOGICAL; j++) { + for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) { ciss_printf(sc, "LOGICAL DRIVE %d: ", i); ciss_print_ldrive(sc, &sc->ciss_logical[i][j]); } diff --git a/sys/dev/ciss/cissreg.h b/sys/dev/ciss/cissreg.h index feae826..4a3349f 100644 --- a/sys/dev/ciss/cissreg.h +++ b/sys/dev/ciss/cissreg.h @@ -425,6 +425,15 @@ struct ciss_config_table #define CISS_DRIVER_DAUGHTER_ATTACHED (1<<8) #define CISS_DRIVER_SCSI_PREFETCH (1<<9) u_int32_t max_sg_length; /* 31 in older firmware */ +/* + * these fields appear in OpenCISS Spec 1.06 + * http://cciss.sourceforge.net/#docs + */ + u_int32_t max_logical_supported; + u_int32_t max_physical_supported; + u_int32_t max_physical_per_logical; + u_int32_t max_perfomant_mode_cmds; + u_int32_t max_block_fetch_count; } __packed; /* diff --git a/sys/dev/ciss/cissvar.h b/sys/dev/ciss/cissvar.h index d109b7a..e89e4e9 100644 --- a/sys/dev/ciss/cissvar.h +++ b/sys/dev/ciss/cissvar.h @@ -45,8 +45,11 @@ typedef STAILQ_HEAD(, ciss_request) cr_qhead_t; /* * Maximum number of logical drives we support. + * If the controller does not indicate a maximum + * value. This is a compatibiliy value to support + * older ciss controllers (e.g. model 6i) */ -#define CISS_MAX_LOGICAL 63 +#define CISS_MAX_LOGICAL 16 /* * Maximum number of physical devices we support. diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index c1d8a6b..e4724c7 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -158,6 +158,16 @@ enum { }; enum { + /* flags understood by begin_synchronized_op */ + HOLD_LOCK = (1 << 0), + SLEEP_OK = (1 << 1), + INTR_OK = (1 << 2), + + /* flags understood by end_synchronized_op */ + LOCK_HELD = HOLD_LOCK, +}; + +enum { /* adapter flags */ FULL_INIT_DONE = (1 << 0), FW_OK = (1 << 1), @@ -174,11 +184,11 @@ enum { PORT_SYSCTL_CTX = (1 << 2), }; -#define IS_DOOMED(pi) (pi->flags & DOOMED) -#define SET_DOOMED(pi) do {pi->flags |= DOOMED;} while (0) -#define IS_BUSY(sc) (sc->flags & CXGBE_BUSY) -#define SET_BUSY(sc) do {sc->flags |= CXGBE_BUSY;} while (0) -#define CLR_BUSY(sc) do {sc->flags &= ~CXGBE_BUSY;} while (0) +#define IS_DOOMED(pi) ((pi)->flags & DOOMED) +#define SET_DOOMED(pi) do {(pi)->flags |= DOOMED;} while (0) +#define IS_BUSY(sc) ((sc)->flags & CXGBE_BUSY) +#define SET_BUSY(sc) do {(sc)->flags |= CXGBE_BUSY;} while (0) +#define CLR_BUSY(sc) do {(sc)->flags &= ~CXGBE_BUSY;} while (0) struct port_info { device_t dev; @@ -591,6 +601,11 @@ struct adapter { an_handler_t an_handler __aligned(CACHE_LINE_SIZE); fw_msg_handler_t fw_msg_handler[4]; /* NUM_FW6_TYPES */ cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */ + +#ifdef INVARIANTS + const char *last_op; + const void *last_op_thr; +#endif }; #define ADAPTER_LOCK(sc) mtx_lock(&(sc)->sc_lock) @@ -598,6 +613,12 @@ struct adapter { #define ADAPTER_LOCK_ASSERT_OWNED(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED) #define ADAPTER_LOCK_ASSERT_NOTOWNED(sc) mtx_assert(&(sc)->sc_lock, MA_NOTOWNED) +/* XXX: not bulletproof, but much better than nothing */ +#define ASSERT_SYNCHRONIZED_OP(sc) \ + KASSERT(IS_BUSY(sc) && \ + (mtx_owned(&(sc)->sc_lock) || sc->last_op_thr == curthread), \ + ("%s: operation not synchronized.", __func__)) + #define PORT_LOCK(pi) mtx_lock(&(pi)->pi_lock) #define PORT_UNLOCK(pi) mtx_unlock(&(pi)->pi_lock) #define PORT_LOCK_ASSERT_OWNED(pi) mtx_assert(&(pi)->pi_lock, MA_OWNED) @@ -751,6 +772,8 @@ int t4_register_cpl_handler(struct adapter *, int, cpl_handler_t); int t4_register_an_handler(struct adapter *, an_handler_t); int t4_register_fw_msg_handler(struct adapter *, int, fw_msg_handler_t); int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *); +int begin_synchronized_op(struct adapter *, struct port_info *, int, char *); +void end_synchronized_op(struct adapter *, int); /* t4_sge.c */ void t4_sge_modload(void); diff --git a/sys/dev/cxgbe/common/jhash.h b/sys/dev/cxgbe/common/jhash.h deleted file mode 100644 index 4546b7b..0000000 --- a/sys/dev/cxgbe/common/jhash.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef _JHASH_H -#define _JHASH_H - -/* jhash.h: Jenkins hash support. - * - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) - * - * http://burtleburtle.net/bob/hash/ - * - * These are the credits from Bob's sources: - * - * lookup2.c, by Bob Jenkins, December 1996, Public Domain. - * hash(), hash2(), hash3, and mix() are externally useful functions. - * Routines to test the hash are included if SELF_TEST is defined. - * You can use this free for any purpose. It has no warranty. - * - * $FreeBSD$ - */ - -/* NOTE: Arguments are modified. */ -#define __jhash_mix(a, b, c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<<8); \ - c -= a; c -= b; c ^= (b>>13); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<16); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>3); \ - b -= c; b -= a; b ^= (a<<10); \ - c -= a; c -= b; c ^= (b>>15); \ -} - -/* The golden ration: an arbitrary value */ -#define JHASH_GOLDEN_RATIO 0x9e3779b9 - -/* The most generic version, hashes an arbitrary sequence - * of bytes. No alignment or length assumptions are made about - * the input key. - */ -static inline u32 jhash(const void *key, u32 length, u32 initval) -{ - u32 a, b, c, len; - const u8 *k = key; - - len = length; - a = b = JHASH_GOLDEN_RATIO; - c = initval; - - while (len >= 12) { - a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); - b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); - c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); - - __jhash_mix(a,b,c); - - k += 12; - len -= 12; - } - - c += length; - switch (len) { - case 11: c += ((u32)k[10]<<24); - case 10: c += ((u32)k[9]<<16); - case 9 : c += ((u32)k[8]<<8); - case 8 : b += ((u32)k[7]<<24); - case 7 : b += ((u32)k[6]<<16); - case 6 : b += ((u32)k[5]<<8); - case 5 : b += k[4]; - case 4 : a += ((u32)k[3]<<24); - case 3 : a += ((u32)k[2]<<16); - case 2 : a += ((u32)k[1]<<8); - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - -/* A special optimized version that handles 1 or more of u32s. - * The length parameter here is the number of u32s in the key. - */ -static inline u32 jhash2(u32 *k, u32 length, u32 initval) -{ - u32 a, b, c, len; - - a = b = JHASH_GOLDEN_RATIO; - c = initval; - len = length; - - while (len >= 3) { - a += k[0]; - b += k[1]; - c += k[2]; - __jhash_mix(a, b, c); - k += 3; len -= 3; - } - - c += length * 4; - - switch (len) { - case 2 : b += k[1]; - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - - -/* A special ultra-optimized versions that knows they are hashing exactly - * 3, 2 or 1 word(s). - * - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally - * done at the end is not done here. - */ -static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) -{ - a += JHASH_GOLDEN_RATIO; - b += JHASH_GOLDEN_RATIO; - c += initval; - - __jhash_mix(a, b, c); - - return c; -} - -static inline u32 jhash_2words(u32 a, u32 b, u32 initval) -{ - return jhash_3words(a, b, 0, initval); -} - -static inline u32 jhash_1word(u32 a, u32 initval) -{ - return jhash_3words(a, 0, 0, initval); -} - -#endif /* _JHASH_H */ diff --git a/sys/dev/cxgbe/firmware/t4fw_cfg.txt b/sys/dev/cxgbe/firmware/t4fw_cfg.txt index bf6a9a1..2a9db62 100644 --- a/sys/dev/cxgbe/firmware/t4fw_cfg.txt +++ b/sys/dev/cxgbe/firmware/t4fw_cfg.txt @@ -56,7 +56,7 @@ [function "4"] wx_caps = all r_caps = all - nvi = 54 + nvi = 32 niqflint = 256 nethctrl = 128 neq = 256 @@ -74,8 +74,8 @@ # Each entry in these categories takes 4 cells each. nhash will use the # TCAM iff there is room left (that is, the rest don't add up to 2048). nroute = 32 - nclip = 0 # needed only for IPv6 offload - nfilter = 1488 + nclip = 32 + nfilter = 1456 nserver = 512 nhash = 16384 @@ -137,7 +137,7 @@ [fini] version = 0x1 - checksum = 0x162df193 + checksum = 0xfdebb6ef # # $FreeBSD$ # diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h index ced15a6..55ac71b 100644 --- a/sys/dev/cxgbe/offload.h +++ b/sys/dev/cxgbe/offload.h @@ -54,16 +54,20 @@ OPCODE_TID(w) = htonl(MK_OPCODE_TID(cpl, tid)); \ } while (0) +TAILQ_HEAD(stid_head, stid_region); +struct listen_ctx; + +struct stid_region { + TAILQ_ENTRY(stid_region) link; + int used; /* # of stids used by this region */ + int free; /* # of contiguous stids free right after this region */ +}; + /* * Max # of ATIDs. The absolute HW max is 16K but we keep it lower. */ #define MAX_ATIDS 8192U -union serv_entry { - void *data; - union serv_entry *next; -}; - union aopen_entry { void *data; union aopen_entry *next; @@ -75,34 +79,33 @@ union aopen_entry { */ struct tid_info { void **tid_tab; - unsigned int ntids; - - union serv_entry *stid_tab; - unsigned int nstids; - unsigned int stid_base; - + u_int ntids; + u_int tids_in_use; + + struct mtx stid_lock __aligned(CACHE_LINE_SIZE); + struct listen_ctx **stid_tab; + u_int nstids; + u_int stid_base; + u_int stids_in_use; + u_int nstids_free_head; /* # of available stids at the begining */ + struct stid_head stids; + + struct mtx atid_lock __aligned(CACHE_LINE_SIZE); union aopen_entry *atid_tab; - unsigned int natids; - - struct filter_entry *ftid_tab; - unsigned int nftids; - unsigned int ftid_base; - unsigned int ftids_in_use; - - struct mtx atid_lock; + u_int natids; union aopen_entry *afree; - unsigned int atids_in_use; - - struct mtx stid_lock; - union serv_entry *sfree; - unsigned int stids_in_use; + u_int atids_in_use; - unsigned int tids_in_use; + struct mtx ftid_lock __aligned(CACHE_LINE_SIZE); + struct filter_entry *ftid_tab; + u_int nftids; + u_int ftid_base; + u_int ftids_in_use; }; struct t4_range { - unsigned int start; - unsigned int size; + u_int start; + u_int size; }; struct t4_virt_res { /* virtualized HW resources */ @@ -114,6 +117,7 @@ struct t4_virt_res { /* virtualized HW resources */ struct t4_range qp; struct t4_range cq; struct t4_range ocq; + struct t4_range l2t; }; #ifdef TCP_OFFLOAD diff --git a/sys/dev/cxgbe/t4_l2t.c b/sys/dev/cxgbe/t4_l2t.c index dd8748e..dcff5e8 100644 --- a/sys/dev/cxgbe/t4_l2t.c +++ b/sys/dev/cxgbe/t4_l2t.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include "common/common.h" -#include "common/jhash.h" #include "common/t4_msg.h" #include "t4_l2t.h" @@ -78,7 +77,7 @@ t4_alloc_l2e(struct l2t_data *d) return (NULL); /* there's definitely a free entry */ - for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e) + for (e = d->rover, end = &d->l2tab[d->l2t_size]; e != end; ++e) if (atomic_load_acq_int(&e->refcnt) == 0) goto found; @@ -115,6 +114,7 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync) { struct wrqe *wr; struct cpl_l2t_write_req *req; + int idx = e->idx + sc->vres.l2t.start; mtx_assert(&e->lock, MA_OWNED); @@ -124,10 +124,10 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync) req = wrtod(wr); INIT_TP_WR(req, 0); - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx | + OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, idx | V_SYNC_WR(sync) | V_TID_QID(sc->sge.fwq.abs_id))); req->params = htons(V_L2T_W_PORT(e->lport) | V_L2T_W_NOREPLY(!sync)); - req->l2t_idx = htons(e->idx); + req->l2t_idx = htons(idx); req->vlan = htons(e->vlan); memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); @@ -183,18 +183,24 @@ t4_l2t_set_switching(struct adapter *sc, struct l2t_entry *e, uint16_t vlan, int t4_init_l2t(struct adapter *sc, int flags) { - int i; + int i, l2t_size; struct l2t_data *d; - d = malloc(sizeof(*d), M_CXGBE, M_ZERO | flags); + l2t_size = sc->vres.l2t.size; + if (l2t_size < 2) /* At least 1 bucket for IP and 1 for IPv6 */ + return (EINVAL); + + d = malloc(sizeof(*d) + l2t_size * sizeof (struct l2t_entry), M_CXGBE, + M_ZERO | flags); if (!d) return (ENOMEM); + d->l2t_size = l2t_size; d->rover = d->l2tab; - atomic_store_rel_int(&d->nfree, L2T_SIZE); + atomic_store_rel_int(&d->nfree, l2t_size); rw_init(&d->lock, "L2T"); - for (i = 0; i < L2T_SIZE; i++) { + for (i = 0; i < l2t_size; i++) { struct l2t_entry *e = &d->l2tab[i]; e->idx = i; @@ -215,7 +221,7 @@ t4_free_l2t(struct l2t_data *d) { int i; - for (i = 0; i < L2T_SIZE; i++) + for (i = 0; i < d->l2t_size; i++) mtx_destroy(&d->l2tab[i].lock); rw_destroy(&d->lock); free(d, M_CXGBE); @@ -229,11 +235,11 @@ do_l2t_write_rpl(struct sge_iq *iq, const struct rss_header *rss, { const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1); unsigned int tid = GET_TID(rpl); - unsigned int idx = tid & (L2T_SIZE - 1); + unsigned int idx = tid % L2T_SIZE; if (__predict_false(rpl->status != CPL_ERR_NONE)) { log(LOG_ERR, - "Unexpected L2T_WRITE_RPL status %u for entry %u\n", + "Unexpected L2T_WRITE_RPL (%u) for entry at hw_idx %u\n", rpl->status, idx); return (EINVAL); } @@ -269,7 +275,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS) struct l2t_entry *e; struct sbuf *sb; int rc, i, header = 0; - char ip[60]; + char ip[INET6_ADDRSTRLEN]; if (l2t == NULL) return (ENXIO); @@ -283,7 +289,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS) return (ENOMEM); e = &l2t->l2tab[0]; - for (i = 0; i < L2T_SIZE; i++, e++) { + for (i = 0; i < l2t->l2t_size; i++, e++) { mtx_lock(&e->lock); if (e->state == L2T_STATE_UNUSED) goto skip; @@ -295,11 +301,15 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS) } if (e->state == L2T_STATE_SWITCHING) ip[0] = 0; - else - snprintf(ip, sizeof(ip), "%s", - inet_ntoa(*(struct in_addr *)&e->addr)); + else { + inet_ntop(e->ipv6 ? AF_INET6 : AF_INET, &e->addr[0], + &ip[0], sizeof(ip)); + } - /* XXX: e->ifp may not be around */ + /* + * XXX: e->ifp may not be around. + * XXX: IPv6 addresses may not align properly in the output. + */ sbuf_printf(sb, "\n%4u %-15s %02x:%02x:%02x:%02x:%02x:%02x %4d" " %u %2u %c %5u %s", e->idx, ip, e->dmac[0], e->dmac[1], e->dmac[2], diff --git a/sys/dev/cxgbe/t4_l2t.h b/sys/dev/cxgbe/t4_l2t.h index 6927b81..c60eef1 100644 --- a/sys/dev/cxgbe/t4_l2t.h +++ b/sys/dev/cxgbe/t4_l2t.h @@ -60,7 +60,7 @@ enum { struct l2t_entry { uint16_t state; /* entry state */ uint16_t idx; /* entry index */ - uint32_t addr; /* next hop IP address */ + uint32_t addr[4]; /* next hop IP or IPv6 address */ struct ifnet *ifp; /* outgoing interface */ uint16_t smt_idx; /* SMT index */ uint16_t vlan; /* VLAN TCI (id: 0-11, prio: 13-15) */ @@ -70,15 +70,17 @@ struct l2t_entry { struct mtx lock; volatile int refcnt; /* entry reference count */ uint16_t hash; /* hash bucket the entry is on */ + uint8_t ipv6; /* entry is for an IPv6 address */ uint8_t lport; /* associated offload logical port */ uint8_t dmac[ETHER_ADDR_LEN]; /* next hop's MAC address */ }; struct l2t_data { struct rwlock lock; + u_int l2t_size; volatile int nfree; /* number of free entries */ struct l2t_entry *rover;/* starting point for next allocation */ - struct l2t_entry l2tab[L2T_SIZE]; + struct l2t_entry l2tab[]; }; diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index aeaa4d2..726de9f 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -284,9 +284,7 @@ static int get_params__post_init(struct adapter *); static void t4_set_desc(struct adapter *); static void build_medialist(struct port_info *); static int update_mac_settings(struct port_info *, int); -static int cxgbe_init_locked(struct port_info *); static int cxgbe_init_synchronized(struct port_info *); -static int cxgbe_uninit_locked(struct port_info *); static int cxgbe_uninit_synchronized(struct port_info *); static int setup_intr_handlers(struct adapter *); static int adapter_full_init(struct adapter *); @@ -348,6 +346,7 @@ static void clear_filter(struct filter_entry *); static int set_filter_wr(struct adapter *, int); static int del_filter_wr(struct adapter *, int); static int get_sge_context(struct adapter *, struct t4_sge_context *); +static int load_fw(struct adapter *, struct t4_data *); static int read_card_mem(struct adapter *, struct t4_mem_range *); static int read_i2c(struct adapter *, struct t4_i2c_data *); #ifdef TCP_OFFLOAD @@ -820,6 +819,8 @@ t4_detach(device_t dev) mtx_destroy(&sc->sc_lock); } + if (mtx_initialized(&sc->tids.ftid_lock)) + mtx_destroy(&sc->tids.ftid_lock); if (mtx_initialized(&sc->sfl_lock)) mtx_destroy(&sc->sfl_lock); @@ -918,6 +919,10 @@ cxgbe_detach(device_t dev) while (IS_BUSY(sc)) mtx_sleep(&sc->flags, &sc->sc_lock, 0, "t4detach", 0); SET_BUSY(sc); +#ifdef INVARIANTS + sc->last_op = "t4detach"; + sc->last_op_thr = curthread; +#endif ADAPTER_UNLOCK(sc); if (pi->vlan_c) @@ -939,7 +944,7 @@ cxgbe_detach(device_t dev) ADAPTER_LOCK(sc); CLR_BUSY(sc); - wakeup_one(&sc->flags); + wakeup(&sc->flags); ADAPTER_UNLOCK(sc); return (0); @@ -951,9 +956,10 @@ cxgbe_init(void *arg) struct port_info *pi = arg; struct adapter *sc = pi->adapter; - ADAPTER_LOCK(sc); - cxgbe_init_locked(pi); /* releases adapter lock */ - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + if (begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4init") != 0) + return; + cxgbe_init_synchronized(pi); + end_synchronized_op(sc, 0); } static int @@ -967,81 +973,56 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data) switch (cmd) { case SIOCSIFMTU: - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); - if (rc) { -fail: - ADAPTER_UNLOCK(sc); - return (rc); - } - mtu = ifr->ifr_mtu; - if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO)) { - rc = EINVAL; - } else { - ifp->if_mtu = mtu; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - t4_update_fl_bufsize(ifp); - PORT_LOCK(pi); - rc = update_mac_settings(pi, XGMAC_MTU); - PORT_UNLOCK(pi); - } + if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO)) + return (EINVAL); + + rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4mtu"); + if (rc) + return (rc); + ifp->if_mtu = mtu; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + t4_update_fl_bufsize(ifp); + rc = update_mac_settings(pi, XGMAC_MTU); } - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, 0); break; case SIOCSIFFLAGS: - ADAPTER_LOCK(sc); - if (IS_DOOMED(pi)) { - rc = ENXIO; - goto fail; - } + rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4flg"); + if (rc) + return (rc); + if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { flags = pi->if_flags; if ((ifp->if_flags ^ flags) & (IFF_PROMISC | IFF_ALLMULTI)) { - if (IS_BUSY(sc)) { - rc = EBUSY; - goto fail; - } - PORT_LOCK(pi); rc = update_mac_settings(pi, XGMAC_PROMISC | XGMAC_ALLMULTI); - PORT_UNLOCK(pi); } - ADAPTER_UNLOCK(sc); } else - rc = cxgbe_init_locked(pi); + rc = cxgbe_init_synchronized(pi); pi->if_flags = ifp->if_flags; } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) - rc = cxgbe_uninit_locked(pi); - else - ADAPTER_UNLOCK(sc); - - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + rc = cxgbe_uninit_synchronized(pi); + end_synchronized_op(sc, 0); break; case SIOCADDMULTI: - case SIOCDELMULTI: /* these two can be called with a mutex held :-( */ - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); + case SIOCDELMULTI: /* these two are called with a mutex held :-( */ + rc = begin_synchronized_op(sc, pi, HOLD_LOCK, "t4multi"); if (rc) - goto fail; - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - PORT_LOCK(pi); + return (rc); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) rc = update_mac_settings(pi, XGMAC_MCADDRS); - PORT_UNLOCK(pi); - } - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, LOCK_HELD); break; case SIOCSIFCAP: - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); + rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4cap"); if (rc) - goto fail; + return (rc); mask = ifr->ifr_reqcap ^ ifp->if_capenable; if (mask & IFCAP_TXCSUM) { @@ -1122,11 +1103,8 @@ fail: #endif if (mask & IFCAP_VLAN_HWTAGGING) { ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - PORT_LOCK(pi); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) rc = update_mac_settings(pi, XGMAC_VLANEX); - PORT_UNLOCK(pi); - } } if (mask & IFCAP_VLAN_MTU) { ifp->if_capenable ^= IFCAP_VLAN_MTU; @@ -1141,7 +1119,8 @@ fail: #ifdef VLAN_CAPABILITIES VLAN_CAPABILITIES(ifp); #endif - ADAPTER_UNLOCK(sc); +fail: + end_synchronized_op(sc, 0); break; case SIOCSIFMEDIA: @@ -1887,7 +1866,9 @@ get_params__post_init(struct adapter *sc) param[1] = FW_PARAM_PFVF(EQ_START); param[2] = FW_PARAM_PFVF(FILTER_START); param[3] = FW_PARAM_PFVF(FILTER_END); - rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 4, param, val); + param[4] = FW_PARAM_PFVF(L2T_START); + param[5] = FW_PARAM_PFVF(L2T_END); + rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query parameters (post_init): %d.\n", rc); @@ -1898,6 +1879,11 @@ get_params__post_init(struct adapter *sc) sc->sge.eq_start = val[1]; sc->tids.ftid_base = val[2]; sc->tids.nftids = val[3] - val[2] + 1; + sc->vres.l2t.start = val[4]; + sc->vres.l2t.size = val[5] - val[4] + 1; + KASSERT(sc->vres.l2t.size <= L2T_SIZE, + ("%s: L2 table size (%u) larger than expected (%u)", + __func__, sc->vres.l2t.size, L2T_SIZE)); /* get capabilites */ bzero(&caps, sizeof(caps)); @@ -2111,7 +2097,7 @@ update_mac_settings(struct port_info *pi, int flags) struct adapter *sc = pi->adapter; int mtu = -1, promisc = -1, allmulti = -1, vlanex = -1; - PORT_LOCK_ASSERT_OWNED(pi); + ASSERT_SYNCHRONIZED_OP(sc); KASSERT(flags, ("%s: not told what to update.", __func__)); if (flags & XGMAC_MTU) @@ -2213,39 +2199,74 @@ mcfail: return (rc); } -static int -cxgbe_init_locked(struct port_info *pi) +int +begin_synchronized_op(struct adapter *sc, struct port_info *pi, int flags, + char *wmesg) { - struct adapter *sc = pi->adapter; - int rc = 0; + int rc, pri; + +#ifdef WITNESS + /* the caller thinks it's ok to sleep, but is it really? */ + if (flags & SLEEP_OK) + pause("t4slptst", 1); +#endif + + if (INTR_OK) + pri = PCATCH; + else + pri = 0; + + ADAPTER_LOCK(sc); + for (;;) { + + if (pi && IS_DOOMED(pi)) { + rc = ENXIO; + goto done; + } + + if (!IS_BUSY(sc)) { + rc = 0; + break; + } - ADAPTER_LOCK_ASSERT_OWNED(sc); + if (!(flags & SLEEP_OK)) { + rc = EBUSY; + goto done; + } - while (!IS_DOOMED(pi) && IS_BUSY(sc)) { - if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4init", 0)) { + if (mtx_sleep(&sc->flags, &sc->sc_lock, pri, wmesg, 0)) { rc = EINTR; goto done; } } - if (IS_DOOMED(pi)) { - rc = ENXIO; - goto done; - } - KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__)); - /* Give up the adapter lock, port init code can sleep. */ + KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__)); SET_BUSY(sc); - ADAPTER_UNLOCK(sc); - - rc = cxgbe_init_synchronized(pi); +#ifdef INVARIANTS + sc->last_op = wmesg; + sc->last_op_thr = curthread; +#endif done: - ADAPTER_LOCK(sc); + if (!(flags & HOLD_LOCK) || rc) + ADAPTER_UNLOCK(sc); + + return (rc); +} + +void +end_synchronized_op(struct adapter *sc, int flags) +{ + + if (flags & LOCK_HELD) + ADAPTER_LOCK_ASSERT_OWNED(sc); + else + ADAPTER_LOCK(sc); + KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__)); CLR_BUSY(sc); - wakeup_one(&sc->flags); + wakeup(&sc->flags); ADAPTER_UNLOCK(sc); - return (rc); } static int @@ -2255,7 +2276,7 @@ cxgbe_init_synchronized(struct port_info *pi) struct ifnet *ifp = pi->ifp; int rc = 0; - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + ASSERT_SYNCHRONIZED_OP(sc); if (isset(&sc->open_device_map, pi->port_id)) { KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, @@ -2271,9 +2292,7 @@ cxgbe_init_synchronized(struct port_info *pi) ((rc = port_full_init(pi)) != 0)) return (rc); /* error message displayed already */ - PORT_LOCK(pi); rc = update_mac_settings(pi, XGMAC_ALL); - PORT_UNLOCK(pi); if (rc) goto done; /* error message displayed already */ @@ -2291,7 +2310,9 @@ cxgbe_init_synchronized(struct port_info *pi) /* all ok */ setbit(&sc->open_device_map, pi->port_id); + PORT_LOCK(pi); ifp->if_drv_flags |= IFF_DRV_RUNNING; + PORT_UNLOCK(pi); callout_reset(&pi->tick, hz, cxgbe_tick, pi); done: @@ -2301,39 +2322,6 @@ done: return (rc); } -static int -cxgbe_uninit_locked(struct port_info *pi) -{ - struct adapter *sc = pi->adapter; - int rc; - - ADAPTER_LOCK_ASSERT_OWNED(sc); - - while (!IS_DOOMED(pi) && IS_BUSY(sc)) { - if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4uninit", 0)) { - rc = EINTR; - goto done; - } - } - if (IS_DOOMED(pi)) { - rc = ENXIO; - goto done; - } - KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__)); - SET_BUSY(sc); - ADAPTER_UNLOCK(sc); - - rc = cxgbe_uninit_synchronized(pi); - - ADAPTER_LOCK(sc); - KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__)); - CLR_BUSY(sc); - wakeup_one(&sc->flags); -done: - ADAPTER_UNLOCK(sc); - return (rc); -} - /* * Idempotent. */ @@ -2344,7 +2332,7 @@ cxgbe_uninit_synchronized(struct port_info *pi) struct ifnet *ifp = pi->ifp; int rc; - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + ASSERT_SYNCHRONIZED_OP(sc); /* * Disable the VI so that all its data in either direction is discarded @@ -2360,7 +2348,9 @@ cxgbe_uninit_synchronized(struct port_info *pi) } clrbit(&sc->open_device_map, pi->port_id); + PORT_LOCK(pi); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + PORT_UNLOCK(pi); pi->link_cfg.link_ok = 0; pi->link_cfg.speed = 0; @@ -2539,7 +2529,7 @@ port_full_init(struct port_info *pi) struct sge_rxq *rxq; int rc, i; - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + ASSERT_SYNCHRONIZED_OP(sc); KASSERT((pi->flags & PORT_INIT_DONE) == 0, ("%s: PORT_INIT_DONE already", __func__)); @@ -3524,6 +3514,8 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS) struct port_info *pi = arg1; struct adapter *sc = pi->adapter; int idx, rc, i; + struct sge_rxq *rxq; + uint8_t v; idx = pi->tmr_idx; @@ -3534,25 +3526,23 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS) if (idx < 0 || idx >= SGE_NTIMERS) return (EINVAL); - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); - if (rc == 0) { - struct sge_rxq *rxq; - uint8_t v; + rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4tmr"); + if (rc) + return (rc); - v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1); - for_each_rxq(pi, i, rxq) { + v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1); + for_each_rxq(pi, i, rxq) { #ifdef atomic_store_rel_8 - atomic_store_rel_8(&rxq->iq.intr_params, v); + atomic_store_rel_8(&rxq->iq.intr_params, v); #else - rxq->iq.intr_params = v; + rxq->iq.intr_params = v; #endif - } - pi->tmr_idx = idx; } + pi->tmr_idx = idx; - ADAPTER_UNLOCK(sc); - return (rc); + end_synchronized_op(sc, LOCK_HELD); + return (0); } static int @@ -3571,15 +3561,17 @@ sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS) if (idx < -1 || idx >= SGE_NCOUNTERS) return (EINVAL); - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); - if (rc == 0 && pi->flags & PORT_INIT_DONE) - rc = EBUSY; /* cannot be changed once the queues are created */ + rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4pktc"); + if (rc) + return (rc); - if (rc == 0) + if (pi->flags & PORT_INIT_DONE) + rc = EBUSY; /* cannot be changed once the queues are created */ + else pi->pktc_idx = idx; - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, LOCK_HELD); return (rc); } @@ -3599,15 +3591,17 @@ sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS) if (qsize < 128 || (qsize & 7)) return (EINVAL); - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); - if (rc == 0 && pi->flags & PORT_INIT_DONE) - rc = EBUSY; /* cannot be changed once the queues are created */ + rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4rxqs"); + if (rc) + return (rc); - if (rc == 0) + if (pi->flags & PORT_INIT_DONE) + rc = EBUSY; /* cannot be changed once the queues are created */ + else pi->qsize_rxq = qsize; - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, LOCK_HELD); return (rc); } @@ -3624,18 +3618,21 @@ sysctl_qsize_txq(SYSCTL_HANDLER_ARGS) if (rc != 0 || req->newptr == NULL) return (rc); - if (qsize < 128) + /* bufring size must be powerof2 */ + if (qsize < 128 || !powerof2(qsize)) return (EINVAL); - ADAPTER_LOCK(sc); - rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0); - if (rc == 0 && pi->flags & PORT_INIT_DONE) - rc = EBUSY; /* cannot be changed once the queues are created */ + rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4txqs"); + if (rc) + return (rc); - if (rc == 0) + if (pi->flags & PORT_INIT_DONE) + rc = EBUSY; /* cannot be changed once the queues are created */ + else pi->qsize_txq = qsize; - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, LOCK_HELD); return (rc); } @@ -4674,8 +4671,14 @@ fspec_to_fconf(struct t4_filter_specification *fs) static int get_filter_mode(struct adapter *sc, uint32_t *mode) { + int rc; uint32_t fconf; + rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4getfm"); + if (rc) + return (rc); + t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1, A_TP_VLAN_PRI_MAP); @@ -4687,6 +4690,7 @@ get_filter_mode(struct adapter *sc, uint32_t *mode) *mode = fconf_to_mode(sc->filter_mode); + end_synchronized_op(sc, LOCK_HELD); return (0); } @@ -4698,11 +4702,10 @@ set_filter_mode(struct adapter *sc, uint32_t mode) fconf = mode_to_fconf(mode); - ADAPTER_LOCK(sc); - if (IS_BUSY(sc)) { - rc = EAGAIN; - goto done; - } + rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4setfm"); + if (rc) + return (rc); if (sc->tids.ftids_in_use > 0) { rc = EBUSY; @@ -4725,7 +4728,7 @@ set_filter_mode(struct adapter *sc, uint32_t mode) #endif done: - ADAPTER_UNLOCK(sc); + end_synchronized_op(sc, LOCK_HELD); return (rc); } @@ -4746,18 +4749,18 @@ get_filter_hits(struct adapter *sc, uint32_t fid) static int get_filter(struct adapter *sc, struct t4_filter *t) { - int i, nfilters = sc->tids.nftids; + int i, rc, nfilters = sc->tids.nftids; struct filter_entry *f; - ADAPTER_LOCK_ASSERT_OWNED(sc); - - if (IS_BUSY(sc)) - return (EAGAIN); + rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK, + "t4getf"); + if (rc) + return (rc); if (sc->tids.ftids_in_use == 0 || sc->tids.ftid_tab == NULL || t->idx >= nfilters) { t->idx = 0xffffffff; - return (0); + goto done; } f = &sc->tids.ftid_tab[t->idx]; @@ -4772,11 +4775,13 @@ get_filter(struct adapter *sc, struct t4_filter *t) t->hits = UINT64_MAX; t->fs = f->fs; - return (0); + goto done; } } t->idx = 0xffffffff; +done: + end_synchronized_op(sc, LOCK_HELD); return (0); } @@ -4785,40 +4790,58 @@ set_filter(struct adapter *sc, struct t4_filter *t) { unsigned int nfilters, nports; struct filter_entry *f; - int i; + int i, rc; - ADAPTER_LOCK_ASSERT_OWNED(sc); + rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setf"); + if (rc) + return (rc); nfilters = sc->tids.nftids; nports = sc->params.nports; - if (nfilters == 0) - return (ENOTSUP); + if (nfilters == 0) { + rc = ENOTSUP; + goto done; + } - if (!(sc->flags & FULL_INIT_DONE)) - return (EAGAIN); + if (!(sc->flags & FULL_INIT_DONE)) { + rc = EAGAIN; + goto done; + } - if (t->idx >= nfilters) - return (EINVAL); + if (t->idx >= nfilters) { + rc = EINVAL; + goto done; + } /* Validate against the global filter mode */ - if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode) - return (E2BIG); + if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode) { + rc = E2BIG; + goto done; + } - if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) - return (EINVAL); + if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) { + rc = EINVAL; + goto done; + } - if (t->fs.val.iport >= nports) - return (EINVAL); + if (t->fs.val.iport >= nports) { + rc = EINVAL; + goto done; + } /* Can't specify an iq if not steering to it */ - if (!t->fs.dirsteer && t->fs.iq) - return (EINVAL); + if (!t->fs.dirsteer && t->fs.iq) { + rc = EINVAL; + goto done; + } /* IPv6 filter idx must be 4 aligned */ if (t->fs.type == 1 && - ((t->idx & 0x3) || t->idx + 4 >= nfilters)) - return (EINVAL); + ((t->idx & 0x3) || t->idx + 4 >= nfilters)) { + rc = EINVAL; + goto done; + } if (sc->tids.ftid_tab == NULL) { KASSERT(sc->tids.ftids_in_use == 0, @@ -4827,17 +4850,24 @@ set_filter(struct adapter *sc, struct t4_filter *t) sc->tids.ftid_tab = malloc(sizeof (struct filter_entry) * nfilters, M_CXGBE, M_NOWAIT | M_ZERO); - if (sc->tids.ftid_tab == NULL) - return (ENOMEM); + if (sc->tids.ftid_tab == NULL) { + rc = ENOMEM; + goto done; + } + mtx_init(&sc->tids.ftid_lock, "T4 filters", 0, MTX_DEF); } for (i = 0; i < 4; i++) { f = &sc->tids.ftid_tab[t->idx + i]; - if (f->pending || f->valid) - return (EBUSY); - if (f->locked) - return (EPERM); + if (f->pending || f->valid) { + rc = EBUSY; + goto done; + } + if (f->locked) { + rc = EPERM; + goto done; + } if (t->fs.type == 0) break; @@ -4846,7 +4876,27 @@ set_filter(struct adapter *sc, struct t4_filter *t) f = &sc->tids.ftid_tab[t->idx]; f->fs = t->fs; - return set_filter_wr(sc, t->idx); + rc = set_filter_wr(sc, t->idx); +done: + end_synchronized_op(sc, 0); + + if (rc == 0) { + mtx_lock(&sc->tids.ftid_lock); + for (;;) { + if (f->pending == 0) { + rc = f->valid ? 0 : EIO; + break; + } + + if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock, + PCATCH, "t4setfw", 0)) { + rc = EINPROGRESS; + break; + } + } + mtx_unlock(&sc->tids.ftid_lock); + } + return (rc); } static int @@ -4854,37 +4904,67 @@ del_filter(struct adapter *sc, struct t4_filter *t) { unsigned int nfilters; struct filter_entry *f; + int rc; - ADAPTER_LOCK_ASSERT_OWNED(sc); - - if (IS_BUSY(sc)) - return (EAGAIN); + rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4delf"); + if (rc) + return (rc); nfilters = sc->tids.nftids; - if (nfilters == 0) - return (ENOTSUP); + if (nfilters == 0) { + rc = ENOTSUP; + goto done; + } if (sc->tids.ftid_tab == NULL || sc->tids.ftids_in_use == 0 || - t->idx >= nfilters) - return (EINVAL); + t->idx >= nfilters) { + rc = EINVAL; + goto done; + } - if (!(sc->flags & FULL_INIT_DONE)) - return (EAGAIN); + if (!(sc->flags & FULL_INIT_DONE)) { + rc = EAGAIN; + goto done; + } f = &sc->tids.ftid_tab[t->idx]; - if (f->pending) - return (EBUSY); - if (f->locked) - return (EPERM); + if (f->pending) { + rc = EBUSY; + goto done; + } + if (f->locked) { + rc = EPERM; + goto done; + } if (f->valid) { t->fs = f->fs; /* extra info for the caller */ - return del_filter_wr(sc, t->idx); + rc = del_filter_wr(sc, t->idx); } - return (0); +done: + end_synchronized_op(sc, 0); + + if (rc == 0) { + mtx_lock(&sc->tids.ftid_lock); + for (;;) { + if (f->pending == 0) { + rc = f->valid ? EIO : 0; + break; + } + + if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock, + PCATCH, "t4delfw", 0)) { + rc = EINPROGRESS; + break; + } + } + mtx_unlock(&sc->tids.ftid_lock); + } + + return (rc); } static void @@ -4904,7 +4984,7 @@ set_filter_wr(struct adapter *sc, int fidx) struct fw_filter_wr *fwr; unsigned int ftid; - ADAPTER_LOCK_ASSERT_OWNED(sc); + ASSERT_SYNCHRONIZED_OP(sc); if (f->fs.newdmac || f->fs.newvlan) { /* This filter needs an L2T entry; allocate one. */ @@ -5007,8 +5087,6 @@ del_filter_wr(struct adapter *sc, int fidx) struct fw_filter_wr *fwr; unsigned int ftid; - ADAPTER_LOCK_ASSERT_OWNED(sc); - ftid = sc->tids.ftid_base + fidx; wr = alloc_wrqe(sizeof(*fwr), &sc->sge.mgmtq); @@ -5039,8 +5117,10 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) unsigned int rc = G_COOKIE(rpl->cookie); struct filter_entry *f = &sc->tids.ftid_tab[idx]; - ADAPTER_LOCK(sc); + mtx_lock(&sc->tids.ftid_lock); if (rc == FW_FILTER_WR_FLT_ADDED) { + KASSERT(f->pending, ("%s: filter[%u] isn't pending.", + __func__, idx)); f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff; f->pending = 0; /* asynchronous setup completed */ f->valid = 1; @@ -5055,7 +5135,8 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) clear_filter(f); sc->tids.ftids_in_use--; } - ADAPTER_UNLOCK(sc); + wakeup(&sc->tids.ftid_tab); + mtx_unlock(&sc->tids.ftid_lock); } return (0); @@ -5064,29 +5145,63 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) static int get_sge_context(struct adapter *sc, struct t4_sge_context *cntxt) { - int rc = EINVAL; + int rc; if (cntxt->cid > M_CTXTQID) - return (rc); + return (EINVAL); if (cntxt->mem_id != CTXT_EGRESS && cntxt->mem_id != CTXT_INGRESS && cntxt->mem_id != CTXT_FLM && cntxt->mem_id != CTXT_CNM) - return (rc); + return (EINVAL); if (sc->flags & FW_OK) { - ADAPTER_LOCK(sc); /* Avoid parallel t4_wr_mbox */ - rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, cntxt->mem_id, - &cntxt->data[0]); - ADAPTER_UNLOCK(sc); + rc = begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4ctxt"); + if (rc == 0) { + rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, + cntxt->mem_id, &cntxt->data[0]); + end_synchronized_op(sc, LOCK_HELD); + if (rc == 0) + return (0); + } } - if (rc != 0) { - /* Read via firmware failed or wasn't even attempted */ + /* + * Read via firmware failed or wasn't even attempted. Read directly via + * the backdoor. + */ + rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id, + &cntxt->data[0]); + return (rc); +} + +static int +load_fw(struct adapter *sc, struct t4_data *fw) +{ + int rc; + uint8_t *fw_data; - rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id, - &cntxt->data[0]); + rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldfw"); + if (rc) + return (rc); + + if (sc->flags & FULL_INIT_DONE) { + rc = EBUSY; + goto done; } + fw_data = malloc(fw->len, M_CXGBE, M_WAITOK); + if (fw_data == NULL) { + rc = ENOMEM; + goto done; + } + + rc = copyin(fw->data, fw_data, fw->len); + if (rc == 0) + rc = -t4_load_fw(sc, fw_data, fw->len); + + free(fw_data, M_CXGBE); +done: + end_synchronized_op(sc, 0); return (rc); } @@ -5173,8 +5288,6 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd) { int rc; - ADAPTER_LOCK_ASSERT_OWNED(sc); /* for mbox */ - if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports) return (EINVAL); @@ -5183,8 +5296,12 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd) return (ENOTSUP); } + rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd"); + if (rc) + return (rc); rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr, i2cd->offset, &i2cd->data[0]); + end_synchronized_op(sc, 0); return (rc); } @@ -5354,48 +5471,25 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, rc = set_filter_mode(sc, *(uint32_t *)data); break; case CHELSIO_T4_GET_FILTER: - ADAPTER_LOCK(sc); rc = get_filter(sc, (struct t4_filter *)data); - ADAPTER_UNLOCK(sc); break; case CHELSIO_T4_SET_FILTER: - ADAPTER_LOCK(sc); rc = set_filter(sc, (struct t4_filter *)data); - ADAPTER_UNLOCK(sc); break; case CHELSIO_T4_DEL_FILTER: - ADAPTER_LOCK(sc); rc = del_filter(sc, (struct t4_filter *)data); - ADAPTER_UNLOCK(sc); break; case CHELSIO_T4_GET_SGE_CONTEXT: rc = get_sge_context(sc, (struct t4_sge_context *)data); break; - case CHELSIO_T4_LOAD_FW: { - struct t4_data *fw = (struct t4_data *)data; - uint8_t *fw_data; - - if (sc->flags & FULL_INIT_DONE) - return (EBUSY); - - fw_data = malloc(fw->len, M_CXGBE, M_NOWAIT); - if (fw_data == NULL) - return (ENOMEM); - - rc = copyin(fw->data, fw_data, fw->len); - if (rc == 0) - rc = -t4_load_fw(sc, fw_data, fw->len); - - free(fw_data, M_CXGBE); + case CHELSIO_T4_LOAD_FW: + rc = load_fw(sc, (struct t4_data *)data); break; - } case CHELSIO_T4_GET_MEM: rc = read_card_mem(sc, (struct t4_mem_range *)data); break; case CHELSIO_T4_GET_I2C: - ADAPTER_LOCK(sc); rc = read_i2c(sc, (struct t4_i2c_data *)data); - ADAPTER_UNLOCK(sc); break; case CHELSIO_T4_CLEAR_STATS: { u_int port_id = *(uint32_t *)data; @@ -5420,16 +5514,16 @@ toe_capability(struct port_info *pi, int enable) int rc; struct adapter *sc = pi->adapter; - ADAPTER_LOCK_ASSERT_OWNED(sc); + ASSERT_SYNCHRONIZED_OP(sc); if (!is_offload(sc)) return (ENODEV); if (enable) { if (!(sc->flags & FULL_INIT_DONE)) { - log(LOG_WARNING, - "You must enable a cxgbe interface first\n"); - return (EAGAIN); + rc = cxgbe_init_synchronized(pi); + if (rc) + return (rc); } if (isset(&sc->offload_map, pi->port_id)) @@ -5518,6 +5612,8 @@ t4_activate_uld(struct adapter *sc, int id) int rc = EAGAIN; struct uld_info *ui; + ASSERT_SYNCHRONIZED_OP(sc); + mtx_lock(&t4_uld_list_lock); SLIST_FOREACH(ui, &t4_uld_list, link) { @@ -5540,6 +5636,8 @@ t4_deactivate_uld(struct adapter *sc, int id) int rc = EINVAL; struct uld_info *ui; + ASSERT_SYNCHRONIZED_OP(sc); + mtx_lock(&t4_uld_list_lock); SLIST_FOREACH(ui, &t4_uld_list, link) { diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c index 8d36b1e..b46b5ce 100644 --- a/sys/dev/cxgbe/tom/t4_connect.c +++ b/sys/dev/cxgbe/tom/t4_connect.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" +#include "opt_inet6.h" #ifdef TCP_OFFLOAD #include <sys/param.h> @@ -220,10 +221,9 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss, * Options2 for active open. */ static uint32_t -calc_opt2a(struct socket *so) +calc_opt2a(struct socket *so, struct toepcb *toep) { struct tcpcb *tp = so_sototcpcb(so); - struct toepcb *toep = tp->t_toe; struct port_info *pi = toep->port; struct adapter *sc = pi->adapter; uint32_t opt2 = 0; @@ -260,6 +260,12 @@ t4_init_connect_cpl_handlers(struct adapter *sc) t4_register_cpl_handler(sc, CPL_ACT_OPEN_RPL, do_act_open_rpl); } +#define DONT_OFFLOAD_ACTIVE_OPEN(x) do { \ + reason = __LINE__; \ + rc = (x); \ + goto failed; \ +} while (0) + /* * active open (soconnect). * @@ -275,20 +281,19 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt, struct sockaddr *nam) { struct adapter *sc = tod->tod_softc; + struct tom_data *td = tod_td(tod); struct toepcb *toep = NULL; struct wrqe *wr = NULL; - struct cpl_act_open_req *cpl; - struct l2t_entry *e = NULL; struct ifnet *rt_ifp = rt->rt_ifp; struct port_info *pi; - int atid = -1, mtu_idx, rscale, qid_atid, rc = ENOMEM; + int mtu_idx, rscale, qid_atid, rc, isipv6; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp = intotcpcb(inp); + int reason; INP_WLOCK_ASSERT(inp); - - if (nam->sa_family != AF_INET) - CXGBE_UNIMPLEMENTED("IPv6 connect"); + KASSERT(nam->sa_family == AF_INET || nam->sa_family == AF_INET6, + ("%s: dest addr %p has family %u", __func__, nam, nam->sa_family)); if (rt_ifp->if_type == IFT_ETHER) pi = rt_ifp->if_softc; @@ -297,30 +302,29 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt, pi = ifp->if_softc; } else if (rt_ifp->if_type == IFT_IEEE8023ADLAG) - return (ENOSYS); /* XXX: implement lagg support */ + DONT_OFFLOAD_ACTIVE_OPEN(ENOSYS); /* XXX: implement lagg+TOE */ else - return (ENOTSUP); + DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP); toep = alloc_toepcb(pi, -1, -1, M_NOWAIT); if (toep == NULL) - goto failed; + DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM); - atid = alloc_atid(sc, toep); - if (atid < 0) - goto failed; + toep->tid = alloc_atid(sc, toep); + if (toep->tid < 0) + DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM); - e = t4_l2t_get(pi, rt_ifp, + toep->l2te = t4_l2t_get(pi, rt_ifp, rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway : nam); - if (e == NULL) - goto failed; + if (toep->l2te == NULL) + DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM); - wr = alloc_wrqe(sizeof(*cpl), toep->ctrlq); + isipv6 = nam->sa_family == AF_INET6; + wr = alloc_wrqe(isipv6 ? sizeof(struct cpl_act_open_req6) : + sizeof(struct cpl_act_open_req), toep->ctrlq); if (wr == NULL) - goto failed; - cpl = wrtod(wr); + DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM); - toep->tid = atid; - toep->l2te = e; if (sc->tt.ddp && (so->so_options & SO_NO_DDP) == 0) set_tcpddp_ulp_mode(toep); else @@ -330,8 +334,6 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt, toep->rx_credits = min(select_rcv_wnd(so) >> 10, M_RCV_BUFSIZ); SOCKBUF_UNLOCK(&so->so_rcv); - offload_socket(so, toep); - /* * The kernel sets request_r_scale based on sb_max whereas we need to * take hardware's MAX_RCV_WND into account too. This is normally a @@ -342,39 +344,78 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt, else rscale = 0; mtu_idx = find_best_mtu_idx(sc, &inp->inp_inc, 0); - qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | atid; - - INIT_TP_WR(cpl, 0); - OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid)); - inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port, &cpl->peer_ip, - &cpl->peer_port); - cpl->opt0 = calc_opt0(so, pi, e, mtu_idx, rscale, toep->rx_credits, - toep->ulp_mode); - cpl->params = select_ntuple(pi, e, sc->filter_mode); - cpl->opt2 = calc_opt2a(so); + qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | toep->tid; + + if (isipv6) { + struct cpl_act_open_req6 *cpl = wrtod(wr); + + if ((inp->inp_vflag & INP_IPV6) == 0) { + /* XXX think about this a bit more */ + log(LOG_ERR, + "%s: time to think about AF_INET6 + vflag 0x%x.\n", + __func__, inp->inp_vflag); + DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP); + } + + toep->ce = hold_lip(td, &inp->in6p_laddr); + if (toep->ce == NULL) + DONT_OFFLOAD_ACTIVE_OPEN(ENOENT); + + INIT_TP_WR(cpl, 0); + OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, + qid_atid)); + + cpl->local_port = inp->inp_lport; + cpl->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0]; + cpl->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8]; + cpl->peer_port = inp->inp_fport; + cpl->peer_ip_hi = *(uint64_t *)&inp->in6p_faddr.s6_addr[0]; + cpl->peer_ip_lo = *(uint64_t *)&inp->in6p_faddr.s6_addr[8]; + cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale, + toep->rx_credits, toep->ulp_mode); + cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode); + cpl->opt2 = calc_opt2a(so, toep); + } else { + struct cpl_act_open_req *cpl = wrtod(wr); + + INIT_TP_WR(cpl, 0); + OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + qid_atid)); + inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port, + &cpl->peer_ip, &cpl->peer_port); + cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale, + toep->rx_credits, toep->ulp_mode); + cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode); + cpl->opt2 = calc_opt2a(so, toep); + } CTR5(KTR_CXGBE, "%s: atid %u (%s), toep %p, inp %p", __func__, toep->tid, tcpstates[tp->t_state], toep, inp); - rc = t4_l2t_send(sc, wr, e); + offload_socket(so, toep); + rc = t4_l2t_send(sc, wr, toep->l2te); if (rc == 0) { toep->flags |= TPF_CPL_PENDING; return (0); } undo_offload_socket(so); + reason = __LINE__; failed: - CTR5(KTR_CXGBE, "%s: FAILED, atid %d, toep %p, l2te %p, wr %p", - __func__, atid, toep, e, wr); + CTR3(KTR_CXGBE, "%s: not offloading (%d), rc %d", __func__, reason, rc); - if (e) - t4_l2t_release(e); if (wr) free_wrqe(wr); - if (atid >= 0) - free_atid(sc, atid); - if (toep) + + if (toep) { + if (toep->tid >= 0) + free_atid(sc, toep->tid); + if (toep->l2te) + t4_l2t_release(toep->l2te); + if (toep->ce) + release_lip(td, toep->ce); free_toepcb(toep); + } return (rc); } diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index 523f7f3..4ca1e97 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" +#include "opt_inet6.h" #ifdef TCP_OFFLOAD #include <sys/param.h> @@ -50,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet6/scope6_var.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #define TCPSTATES @@ -63,9 +66,9 @@ __FBSDID("$FreeBSD$"); #include "tom/t4_tom.h" /* stid services */ -static int alloc_stid(struct adapter *, void *); -static void *lookup_stid(struct adapter *, int); -static void free_stid(struct adapter *, int); +static int alloc_stid(struct adapter *, struct listen_ctx *, int); +static struct listen_ctx *lookup_stid(struct adapter *, int); +static void free_stid(struct adapter *, struct listen_ctx *); /* lctx services */ static struct listen_ctx *alloc_lctx(struct adapter *, struct inpcb *, @@ -81,45 +84,105 @@ static inline void save_qids_in_mbuf(struct mbuf *, struct port_info *); static inline void get_qids_from_mbuf(struct mbuf *m, int *, int *); static void send_reset_synqe(struct toedev *, struct synq_entry *); -/* XXX: won't work for IPv6 */ static int -alloc_stid(struct adapter *sc, void *ctx) +alloc_stid(struct adapter *sc, struct listen_ctx *lctx, int isipv6) { struct tid_info *t = &sc->tids; - int stid = -1; + u_int stid, n, f, mask; + struct stid_region *sr = &lctx->stid_region; + + /* + * An IPv6 server needs 2 naturally aligned stids (1 stid = 4 cells) in + * the TCAM. The start of the stid region is properly aligned (the chip + * requires each region to be 128-cell aligned). + */ + n = isipv6 ? 2 : 1; + mask = n - 1; + KASSERT((t->stid_base & mask) == 0 && (t->nstids & mask) == 0, + ("%s: stid region (%u, %u) not properly aligned. n = %u", + __func__, t->stid_base, t->nstids, n)); mtx_lock(&t->stid_lock); - if (t->sfree) { - union serv_entry *p = t->sfree; - - stid = p - t->stid_tab; - stid += t->stid_base; - t->sfree = p->next; - p->data = ctx; - t->stids_in_use++; + if (n > t->nstids - t->stids_in_use) { + mtx_unlock(&t->stid_lock); + return (-1); } + + if (t->nstids_free_head >= n) { + /* + * This allocation will definitely succeed because the region + * starts at a good alignment and we just checked we have enough + * stids free. + */ + f = t->nstids_free_head & mask; + t->nstids_free_head -= n + f; + stid = t->nstids_free_head; + TAILQ_INSERT_HEAD(&t->stids, sr, link); + } else { + struct stid_region *s; + + stid = t->nstids_free_head; + TAILQ_FOREACH(s, &t->stids, link) { + stid += s->used + s->free; + f = stid & mask; + if (n <= s->free - f) { + stid -= n + f; + s->free -= n + f; + TAILQ_INSERT_AFTER(&t->stids, s, sr, link); + goto allocated; + } + } + + if (__predict_false(stid != t->nstids)) { + panic("%s: stids TAILQ (%p) corrupt." + " At %d instead of %d at the end of the queue.", + __func__, &t->stids, stid, t->nstids); + } + + mtx_unlock(&t->stid_lock); + return (-1); + } + +allocated: + sr->used = n; + sr->free = f; + t->stids_in_use += n; + t->stid_tab[stid] = lctx; mtx_unlock(&t->stid_lock); - return (stid); + + KASSERT(((stid + t->stid_base) & mask) == 0, + ("%s: EDOOFUS.", __func__)); + return (stid + t->stid_base); } -static void * +static struct listen_ctx * lookup_stid(struct adapter *sc, int stid) { struct tid_info *t = &sc->tids; - return (t->stid_tab[stid - t->stid_base].data); + return (t->stid_tab[stid - t->stid_base]); } static void -free_stid(struct adapter *sc, int stid) +free_stid(struct adapter *sc, struct listen_ctx *lctx) { struct tid_info *t = &sc->tids; - union serv_entry *p = &t->stid_tab[stid - t->stid_base]; + struct stid_region *sr = &lctx->stid_region; + struct stid_region *s; + + KASSERT(sr->used > 0, ("%s: nonsense free (%d)", __func__, sr->used)); mtx_lock(&t->stid_lock); - p->next = t->sfree; - t->sfree = p; - t->stids_in_use--; + s = TAILQ_PREV(sr, stid_head, link); + if (s != NULL) + s->free += sr->used + sr->free; + else + t->nstids_free_head += sr->used + sr->free; + KASSERT(t->stids_in_use >= sr->used, + ("%s: stids_in_use (%u) < stids being freed (%u)", __func__, + t->stids_in_use, sr->used)); + t->stids_in_use -= sr->used; + TAILQ_REMOVE(&t->stids, sr, link); mtx_unlock(&t->stid_lock); } @@ -134,7 +197,7 @@ alloc_lctx(struct adapter *sc, struct inpcb *inp, struct port_info *pi) if (lctx == NULL) return (NULL); - lctx->stid = alloc_stid(sc, lctx); + lctx->stid = alloc_stid(sc, lctx, inp->inp_vflag & INP_IPV6); if (lctx->stid < 0) { free(lctx, M_CXGBE); return (NULL); @@ -167,7 +230,7 @@ free_lctx(struct adapter *sc, struct listen_ctx *lctx) CTR4(KTR_CXGBE, "%s: stid %u, lctx %p, inp %p", __func__, lctx->stid, lctx, lctx->inp); - free_stid(sc, lctx->stid); + free_stid(sc, lctx); free(lctx, M_CXGBE); return (in_pcbrele_wlocked(inp)); @@ -339,7 +402,7 @@ create_server(struct adapter *sc, struct listen_ctx *lctx) { struct wrqe *wr; struct cpl_pass_open_req *req; - struct in_conninfo *inc = &lctx->inp->inp_inc; + struct inpcb *inp = lctx->inp; wr = alloc_wrqe(sizeof(*req), lctx->ctrlq); if (wr == NULL) { @@ -350,9 +413,9 @@ create_server(struct adapter *sc, struct listen_ctx *lctx) INIT_TP_WR(req, 0); OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, lctx->stid)); - req->local_port = inc->inc_lport; + req->local_port = inp->inp_lport; req->peer_port = 0; - req->local_ip = inc->inc_laddr.s_addr; + req->local_ip = inp->inp_laddr.s_addr; req->peer_ip = 0; req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan)); req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) | @@ -363,6 +426,36 @@ create_server(struct adapter *sc, struct listen_ctx *lctx) } static int +create_server6(struct adapter *sc, struct listen_ctx *lctx) +{ + struct wrqe *wr; + struct cpl_pass_open_req6 *req; + struct inpcb *inp = lctx->inp; + + wr = alloc_wrqe(sizeof(*req), lctx->ctrlq); + if (wr == NULL) { + log(LOG_ERR, "%s: allocation failure", __func__); + return (ENOMEM); + } + req = wrtod(wr); + + INIT_TP_WR(req, 0); + OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ6, lctx->stid)); + req->local_port = inp->inp_lport; + req->peer_port = 0; + req->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0]; + req->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8]; + req->peer_ip_hi = 0; + req->peer_ip_lo = 0; + req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan)); + req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) | + F_SYN_RSS_ENABLE | V_SYN_RSS_QUEUE(lctx->ofld_rxq->iq.abs_id)); + + t4_wrq_tx(sc, wr); + return (0); +} + +static int destroy_server(struct adapter *sc, struct listen_ctx *lctx) { struct wrqe *wr; @@ -398,13 +491,10 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp) struct port_info *pi; struct inpcb *inp = tp->t_inpcb; struct listen_ctx *lctx; - int i; + int i, rc; INP_WLOCK_ASSERT(inp); - if ((inp->inp_vflag & INP_IPV4) == 0) - return (0); - #if 0 ADAPTER_LOCK(sc); if (IS_BUSY(sc)) { @@ -421,8 +511,9 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp) goto done; /* no port that's UP with IFCAP_TOE enabled */ /* - * Find a running port with IFCAP_TOE4. We'll use the first such port's - * queues to send the passive open and receive the reply to it. + * Find a running port with IFCAP_TOE (4 or 6). We'll use the first + * such port's queues to send the passive open and receive the reply to + * it. * * XXX: need a way to mark a port in use by offload. if_cxgbe should * then reject any attempt to bring down such a port (and maybe reject @@ -430,7 +521,7 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp) */ for_each_port(sc, i) { if (isset(&sc->open_device_map, i) && - sc->port[i]->ifp->if_capenable & IFCAP_TOE4) + sc->port[i]->ifp->if_capenable & IFCAP_TOE) break; } KASSERT(i < sc->params.nports, @@ -449,12 +540,17 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp) } listen_hash_add(sc, lctx); - CTR5(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p", __func__, - lctx->stid, tcpstates[tp->t_state], lctx, inp); + CTR6(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p vflag 0x%x", + __func__, lctx->stid, tcpstates[tp->t_state], lctx, inp, + inp->inp_vflag); - if (create_server(sc, lctx) != 0) { - log(LOG_ERR, "%s: %s failed to create hw listener.\n", __func__, - device_get_nameunit(sc->dev)); + if (inp->inp_vflag & INP_IPV6) + rc = create_server6(sc, lctx); + else + rc = create_server(sc, lctx); + if (rc != 0) { + log(LOG_ERR, "%s: %s failed to create hw listener: %d.\n", + __func__, device_get_nameunit(sc->dev), rc); (void) listen_hash_del(sc, inp); inp = release_lctx(sc, lctx); /* can't be freed, host stack has a reference */ @@ -558,7 +654,7 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m) struct l2t_entry *e; struct tcpopt to; struct ip *ip = mtod(m, struct ip *); - struct tcphdr *th = (void *)(ip + 1); + struct tcphdr *th; wr = (struct wrqe *)atomic_readandclear_ptr(&synqe->wr); if (wr == NULL) { @@ -566,6 +662,10 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m) return (EALREADY); } + if (ip->ip_v == IPVERSION) + th = (void *)(ip + 1); + else + th = (void *)((struct ip6_hdr *)ip + 1); bzero(&to, sizeof(to)); tcp_dooptions(&to, (void *)(th + 1), (th->th_off << 2) - sizeof(*th), TO_SYN); @@ -608,7 +708,7 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss, lctx->flags &= ~LCTX_RPL_PENDING; if (status != CPL_ERR_NONE) - log(LOG_ERR, "listener with stid %u failed: %d", stid, status); + log(LOG_ERR, "listener (stid %u) failed: %d\n", stid, status); #ifdef INVARIANTS /* @@ -678,7 +778,7 @@ do_close_server_rpl(struct sge_iq *iq, const struct rss_header *rss, CTR3(KTR_CXGBE, "%s: stid %u, status %u", __func__, stid, status); if (status != CPL_ERR_NONE) { - log(LOG_ERR, "%s: failed (%u) to close listener for stid %u", + log(LOG_ERR, "%s: failed (%u) to close listener for stid %u\n", __func__, status, stid); return (status); } @@ -936,21 +1036,29 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc, const struct cpl_pass_accept_req *cpl = mtod(m, const void *); const struct ether_header *eh; unsigned int hlen = be32toh(cpl->hdr_len); - const struct ip *ip; + uintptr_t l3hdr; const struct tcphdr *tcp; eh = (const void *)(cpl + 1); - ip = (const void *)((uintptr_t)eh + G_ETH_HDR_LEN(hlen)); - tcp = (const void *)((uintptr_t)ip + G_IP_HDR_LEN(hlen)); + l3hdr = ((uintptr_t)eh + G_ETH_HDR_LEN(hlen)); + tcp = (const void *)(l3hdr + G_IP_HDR_LEN(hlen)); if (inc) { bzero(inc, sizeof(*inc)); - inc->inc_faddr = ip->ip_src; - inc->inc_laddr = ip->ip_dst; inc->inc_fport = tcp->th_sport; inc->inc_lport = tcp->th_dport; - if (ip->ip_v == 6) + if (((struct ip *)l3hdr)->ip_v == IPVERSION) { + const struct ip *ip = (const void *)l3hdr; + + inc->inc_faddr = ip->ip_src; + inc->inc_laddr = ip->ip_dst; + } else { + const struct ip6_hdr *ip6 = (const void *)l3hdr; + inc->inc_flags |= INC_ISIPV6; + inc->inc6_faddr = ip6->ip6_src; + inc->inc6_laddr = ip6->ip6_dst; + } } if (th) { @@ -959,6 +1067,105 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc, } } +static int +ifnet_has_ip6(struct ifnet *ifp, struct in6_addr *ip6) +{ + struct ifaddr *ifa; + struct sockaddr_in6 *sin6; + int found = 0; + struct in6_addr in6 = *ip6; + + /* Just as in ip6_input */ + if (in6_clearscope(&in6) || in6_clearscope(&in6)) + return (0); + in6_setscope(&in6, ifp, NULL); + + if_addr_rlock(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + sin6 = (void *)ifa->ifa_addr; + if (sin6->sin6_family != AF_INET6) + continue; + + if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &in6)) { + found = 1; + break; + } + } + if_addr_runlock(ifp); + + return (found); +} + +static struct l2t_entry * +get_l2te_for_nexthop(struct port_info *pi, struct ifnet *ifp, + struct in_conninfo *inc) +{ + struct rtentry *rt; + struct l2t_entry *e; + struct sockaddr_in6 sin6; + struct sockaddr *dst = (void *)&sin6; + + if (inc->inc_flags & INC_ISIPV6) { + dst->sa_len = sizeof(struct sockaddr_in6); + dst->sa_family = AF_INET6; + ((struct sockaddr_in6 *)dst)->sin6_addr = inc->inc6_faddr; + + if (IN6_IS_ADDR_LINKLOCAL(&inc->inc6_laddr)) { + /* no need for route lookup */ + e = t4_l2t_get(pi, ifp, dst); + return (e); + } + } else { + dst->sa_len = sizeof(struct sockaddr_in); + dst->sa_family = AF_INET; + ((struct sockaddr_in *)dst)->sin_addr = inc->inc_faddr; + } + + rt = rtalloc1(dst, 0, 0); + if (rt == NULL) + return (NULL); + else { + struct sockaddr *nexthop; + + RT_UNLOCK(rt); + if (rt->rt_ifp != ifp) + e = NULL; + else { + if (rt->rt_flags & RTF_GATEWAY) + nexthop = rt->rt_gateway; + else + nexthop = dst; + e = t4_l2t_get(pi, ifp, nexthop); + } + RTFREE(rt); + } + + return (e); +} + +static int +ifnet_has_ip(struct ifnet *ifp, struct in_addr in) +{ + struct ifaddr *ifa; + struct sockaddr_in *sin; + int found = 0; + + if_addr_rlock(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + sin = (void *)ifa->ifa_addr; + if (sin->sin_family != AF_INET) + continue; + + if (sin->sin_addr.s_addr == in.s_addr) { + found = 1; + break; + } + } + if_addr_runlock(ifp); + + return (found); +} + #define REJECT_PASS_ACCEPT() do { \ reject_reason = __LINE__; \ goto reject; \ @@ -994,10 +1201,8 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, struct tcphdr th; struct tcpopt to; struct port_info *pi; - struct ifnet *ifp, *ifp_vlan = NULL; + struct ifnet *hw_ifp, *ifp; struct l2t_entry *e = NULL; - struct rtentry *rt; - struct sockaddr_in nam; int rscale, mtu_idx, rx_credits, rxqid, ulp_mode; struct synq_entry *synqe = NULL; int reject_reason; @@ -1017,31 +1222,24 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, t4opt_to_tcpopt(&cpl->tcpopt, &to); pi = sc->port[G_SYN_INTF(be16toh(cpl->l2info))]; - ifp = pi->ifp; - m->m_pkthdr.rcvif = ifp; - tod = TOEDEV(ifp); + hw_ifp = pi->ifp; /* the cxgbeX ifnet */ + m->m_pkthdr.rcvif = hw_ifp; + tod = TOEDEV(hw_ifp); /* - * Don't offload if the interface that received the SYN doesn't have - * IFCAP_TOE enabled. - */ - if ((ifp->if_capenable & IFCAP_TOE4) == 0) - REJECT_PASS_ACCEPT(); - - /* Don't offload IPv6 connections. XXX: add IPv6 support */ - if (inc.inc_flags & INC_ISIPV6) - REJECT_PASS_ACCEPT(); - - /* - * Don't offload if the SYN had a VLAN tag and the vid doesn't match - * anything on this interface. + * Figure out if there is a pseudo interface (vlan, lagg, etc.) + * involved. Don't offload if the SYN had a VLAN tag and the vid + * doesn't match anything on this interface. + * + * XXX: lagg support, lagg + vlan support. */ vid = EVL_VLANOFTAG(be16toh(cpl->vlan)); if (vid != 0xfff) { - ifp_vlan = VLAN_DEVAT(ifp, vid); - if (ifp_vlan == NULL) + ifp = VLAN_DEVAT(hw_ifp, vid); + if (ifp == NULL) REJECT_PASS_ACCEPT(); - } + } else + ifp = hw_ifp; /* * Don't offload if the peer requested a TCP option that's not known to @@ -1050,31 +1248,36 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, if (cpl->tcpopt.unknown) REJECT_PASS_ACCEPT(); - /* - * Don't offload if the outgoing interface for the route back to the - * peer is not the same as the interface that received the SYN. - * XXX: too restrictive. - */ - nam.sin_len = sizeof(nam); - nam.sin_family = AF_INET; - nam.sin_addr = inc.inc_faddr; - rt = rtalloc1((struct sockaddr *)&nam, 0, 0); - if (rt == NULL) - REJECT_PASS_ACCEPT(); - else { - struct sockaddr *nexthop; + if (inc.inc_flags & INC_ISIPV6) { - RT_UNLOCK(rt); - nexthop = rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway : - (struct sockaddr *)&nam; - if (rt->rt_ifp == ifp || - (ifp_vlan != NULL && rt->rt_ifp == ifp_vlan)) - e = t4_l2t_get(pi, rt->rt_ifp, nexthop); - RTFREE(rt); - if (e == NULL) - REJECT_PASS_ACCEPT(); /* no l2te, or ifp mismatch */ + /* Don't offload if the ifcap isn't enabled */ + if ((ifp->if_capenable & IFCAP_TOE6) == 0) + REJECT_PASS_ACCEPT(); + + /* + * SYN must be directed to an IP6 address on this ifnet. This + * is more restrictive than in6_localip. + */ + if (!ifnet_has_ip6(ifp, &inc.inc6_laddr)) + REJECT_PASS_ACCEPT(); + } else { + + /* Don't offload if the ifcap isn't enabled */ + if ((ifp->if_capenable & IFCAP_TOE4) == 0) + REJECT_PASS_ACCEPT(); + + /* + * SYN must be directed to an IP address on this ifnet. This + * is more restrictive than in_localip. + */ + if (!ifnet_has_ip(ifp, inc.inc_laddr)) + REJECT_PASS_ACCEPT(); } + e = get_l2te_for_nexthop(pi, ifp, &inc); + if (e == NULL) + REJECT_PASS_ACCEPT(); + synqe = mbuf_to_synqe(m); if (synqe == NULL) REJECT_PASS_ACCEPT(); @@ -1166,7 +1369,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, */ m = m_dup(synqe->syn, M_NOWAIT); if (m) - m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.rcvif = hw_ifp; remove_tid(sc, synqe->tid); free(wr, M_CXGBE); @@ -1216,7 +1419,7 @@ reject: m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR); m->m_pkthdr.csum_data = 0xffff; - ifp->if_input(ifp, m); + hw_ifp->if_input(hw_ifp, m); } return (reject_reason); diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c index 330172d..d46eeaf 100644 --- a/sys/dev/cxgbe/tom/t4_tom.c +++ b/sys/dev/cxgbe/tom/t4_tom.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" +#include "opt_inet6.h" #include <sys/param.h> #include <sys/types.h> @@ -40,10 +41,14 @@ __FBSDID("$FreeBSD$"); #include <sys/domain.h> #include <sys/socket.h> #include <sys/socketvar.h> +#include <net/if.h> #include <netinet/in.h> #include <netinet/in_pcb.h> +#include <netinet/in_var.h> #include <netinet/ip.h> +#include <netinet/ip6.h> #include <netinet/tcp_var.h> +#include <netinet6/scope6_var.h> #define TCPSTATES #include <netinet/tcp_fsm.h> #include <netinet/toecore.h> @@ -58,6 +63,9 @@ __FBSDID("$FreeBSD$"); static struct protosw ddp_protosw; static struct pr_usrreqs ddp_usrreqs; +static struct protosw ddp6_protosw; +static struct pr_usrreqs ddp6_usrreqs; + /* Module ops */ static int t4_tom_mod_load(void); static int t4_tom_mod_unload(void); @@ -77,6 +85,11 @@ static void queue_tid_release(struct adapter *, int); static void release_offload_resources(struct toepcb *); static int alloc_tid_tabs(struct tid_info *); static void free_tid_tabs(struct tid_info *); +static int add_lip(struct adapter *, struct in6_addr *); +static int delete_lip(struct adapter *, struct in6_addr *); +static struct clip_entry *search_lip(struct tom_data *, struct in6_addr *); +static void init_clip_table(struct adapter *, struct tom_data *); +static void destroy_clip_table(struct adapter *, struct tom_data *); static void free_tom_data(struct adapter *, struct tom_data *); struct toepcb * @@ -170,8 +183,12 @@ offload_socket(struct socket *so, struct toepcb *toep) sb = &so->so_rcv; SOCKBUF_LOCK(sb); sb->sb_flags |= SB_NOCOALESCE; - if (toep->ulp_mode == ULP_MODE_TCPDDP) - so->so_proto = &ddp_protosw; + if (toep->ulp_mode == ULP_MODE_TCPDDP) { + if (inp->inp_vflag & INP_IPV6) + so->so_proto = &ddp6_protosw; + else + so->so_proto = &ddp_protosw; + } SOCKBUF_UNLOCK(sb); /* Update TCP PCB */ @@ -237,8 +254,8 @@ release_offload_resources(struct toepcb *toep) KASSERT(!(toep->flags & TPF_ATTACHED), ("%s: %p is still attached.", __func__, toep)); - CTR4(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p)", - __func__, toep, tid, toep->l2te); + CTR5(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p, ce %p)", + __func__, toep, tid, toep->l2te, toep->ce); if (toep->ulp_mode == ULP_MODE_TCPDDP) release_ddp_resources(toep); @@ -251,6 +268,9 @@ release_offload_resources(struct toepcb *toep) release_tid(sc, tid, toep->ctrlq); } + if (toep->ce) + release_lip(td, toep->ce); + mtx_lock(&td->toep_list_lock); TAILQ_REMOVE(&td->toep_list, toep, link); mtx_unlock(&td->toep_list_lock); @@ -394,7 +414,7 @@ int find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss) { unsigned short *mtus = &sc->params.mtus[0]; - int i = 0, mss; + int i, mss, n; KASSERT(inc != NULL || pmss > 0, ("%s: at least one of inc/pmss must be specified", __func__)); @@ -403,8 +423,13 @@ find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss) if (pmss > 0 && mss > pmss) mss = pmss; - while (i < NMTUS - 1 && mtus[i + 1] <= mss + 40) - ++i; + if (inc->inc_flags & INC_ISIPV6) + n = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); + else + n = sizeof(struct ip) + sizeof(struct tcphdr); + + for (i = 0; i < NMTUS - 1 && mtus[i + 1] <= mss + n; i++) + continue; return (i); } @@ -513,6 +538,15 @@ select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode) return (htobe32(ntuple)); } +void +set_tcpddp_ulp_mode(struct toepcb *toep) +{ + + toep->ulp_mode = ULP_MODE_TCPDDP; + toep->ddp_flags = DDP_OK; + toep->ddp_score = DDP_LOW_SCORE; +} + static int alloc_tid_tabs(struct tid_info *t) { @@ -536,12 +570,10 @@ alloc_tid_tabs(struct tid_info *t) t->atid_tab[t->natids - 1].next = NULL; mtx_init(&t->stid_lock, "stid lock", NULL, MTX_DEF); - t->stid_tab = (union serv_entry *)&t->atid_tab[t->natids]; - t->sfree = t->stid_tab; + t->stid_tab = (struct listen_ctx **)&t->atid_tab[t->natids]; t->stids_in_use = 0; - for (i = 1; i < t->nstids; i++) - t->stid_tab[i - 1].next = &t->stid_tab[i]; - t->stid_tab[t->nstids - 1].next = NULL; + TAILQ_INIT(&t->stids); + t->nstids_free_head = t->nstids; atomic_store_rel_int(&t->tids_in_use, 0); @@ -567,9 +599,157 @@ free_tid_tabs(struct tid_info *t) mtx_destroy(&t->stid_lock); } +static int +add_lip(struct adapter *sc, struct in6_addr *lip) +{ + struct fw_clip_cmd c; + + ASSERT_SYNCHRONIZED_OP(sc); + /* mtx_assert(&td->clip_table_lock, MA_OWNED); */ + + memset(&c, 0, sizeof(c)); + c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_WRITE); + c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c)); + c.ip_hi = *(uint64_t *)&lip->s6_addr[0]; + c.ip_lo = *(uint64_t *)&lip->s6_addr[8]; + + return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c)); +} + +static int +delete_lip(struct adapter *sc, struct in6_addr *lip) +{ + struct fw_clip_cmd c; + + ASSERT_SYNCHRONIZED_OP(sc); + /* mtx_assert(&td->clip_table_lock, MA_OWNED); */ + + memset(&c, 0, sizeof(c)); + c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_READ); + c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c)); + c.ip_hi = *(uint64_t *)&lip->s6_addr[0]; + c.ip_lo = *(uint64_t *)&lip->s6_addr[8]; + + return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c)); +} + +static struct clip_entry * +search_lip(struct tom_data *td, struct in6_addr *lip) +{ + struct clip_entry *ce; + + mtx_assert(&td->clip_table_lock, MA_OWNED); + + TAILQ_FOREACH(ce, &td->clip_table, link) { + if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip)) + return (ce); + } + + return (NULL); +} + +struct clip_entry * +hold_lip(struct tom_data *td, struct in6_addr *lip) +{ + struct clip_entry *ce; + + mtx_lock(&td->clip_table_lock); + ce = search_lip(td, lip); + if (ce != NULL) + ce->refcount++; + mtx_unlock(&td->clip_table_lock); + + return (ce); +} + +void +release_lip(struct tom_data *td, struct clip_entry *ce) +{ + + mtx_lock(&td->clip_table_lock); + KASSERT(search_lip(td, &ce->lip) == ce, + ("%s: CLIP entry %p p not in CLIP table.", __func__, ce)); + KASSERT(ce->refcount > 0, + ("%s: CLIP entry %p has refcount 0", __func__, ce)); + --ce->refcount; + mtx_unlock(&td->clip_table_lock); +} + +static void +init_clip_table(struct adapter *sc, struct tom_data *td) +{ + struct in6_ifaddr *ia; + struct in6_addr *lip, tlip; + struct clip_entry *ce; + + ASSERT_SYNCHRONIZED_OP(sc); + + mtx_init(&td->clip_table_lock, "CLIP table lock", NULL, MTX_DEF); + TAILQ_INIT(&td->clip_table); + + IN6_IFADDR_RLOCK(); + TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { + lip = &ia->ia_addr.sin6_addr; + + KASSERT(!IN6_IS_ADDR_MULTICAST(lip), + ("%s: mcast address in in6_ifaddr list", __func__)); + + if (IN6_IS_ADDR_LOOPBACK(lip)) + continue; + if (IN6_IS_SCOPE_EMBED(lip)) { + /* Remove the embedded scope */ + tlip = *lip; + lip = &tlip; + in6_clearscope(lip); + } + /* + * XXX: how to weed out the link local address for the loopback + * interface? It's fe80::1 usually (always?). + */ + + mtx_lock(&td->clip_table_lock); + if (search_lip(td, lip) == NULL) { + ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT); + memcpy(&ce->lip, lip, sizeof(ce->lip)); + ce->refcount = 0; + if (add_lip(sc, lip) == 0) + TAILQ_INSERT_TAIL(&td->clip_table, ce, link); + else + free(ce, M_CXGBE); + } + mtx_unlock(&td->clip_table_lock); + } + IN6_IFADDR_RUNLOCK(); +} + +static void +destroy_clip_table(struct adapter *sc, struct tom_data *td) +{ + struct clip_entry *ce, *ce_temp; + + if (mtx_initialized(&td->clip_table_lock)) { + mtx_lock(&td->clip_table_lock); + TAILQ_FOREACH_SAFE(ce, &td->clip_table, link, ce_temp) { + KASSERT(ce->refcount == 0, + ("%s: CLIP entry %p still in use (%d)", __func__, + ce, ce->refcount)); + TAILQ_REMOVE(&td->clip_table, ce, link); + delete_lip(sc, &ce->lip); + free(ce, M_CXGBE); + } + mtx_unlock(&td->clip_table_lock); + mtx_destroy(&td->clip_table_lock); + } +} + static void free_tom_data(struct adapter *sc, struct tom_data *td) { + + ASSERT_SYNCHRONIZED_OP(sc); + KASSERT(TAILQ_EMPTY(&td->toep_list), ("%s: TOE PCB list is not empty.", __func__)); KASSERT(td->lctx_count == 0, @@ -578,6 +758,7 @@ free_tom_data(struct adapter *sc, struct tom_data *td) t4_uninit_l2t_cpl_handlers(sc); t4_uninit_cpl_io_handlers(sc); t4_uninit_ddp(sc, td); + destroy_clip_table(sc, td); if (td->listen_mask != 0) hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask); @@ -602,7 +783,7 @@ t4_tom_activate(struct adapter *sc) struct toedev *tod; int i, rc; - ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */ + ASSERT_SYNCHRONIZED_OP(sc); /* per-adapter softc for TOM */ td = malloc(sizeof(*td), M_CXGBE, M_ZERO | M_NOWAIT); @@ -623,8 +804,12 @@ t4_tom_activate(struct adapter *sc) if (rc != 0) goto done; + /* DDP page pods and CPL handlers */ t4_init_ddp(sc, td); + /* CLIP table for IPv6 offload */ + init_clip_table(sc, td); + /* CPL handlers */ t4_init_connect_cpl_handlers(sc); t4_init_l2t_cpl_handlers(sc); @@ -668,7 +853,7 @@ t4_tom_deactivate(struct adapter *sc) int rc = 0; struct tom_data *td = sc->tom_softc; - ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */ + ASSERT_SYNCHRONIZED_OP(sc); if (td == NULL) return (0); /* XXX. KASSERT? */ @@ -700,17 +885,24 @@ static int t4_tom_mod_load(void) { int rc; - struct protosw *tcp_protosw; + struct protosw *tcp_protosw, *tcp6_protosw; tcp_protosw = pffindproto(PF_INET, IPPROTO_TCP, SOCK_STREAM); if (tcp_protosw == NULL) return (ENOPROTOOPT); - bcopy(tcp_protosw, &ddp_protosw, sizeof(ddp_protosw)); bcopy(tcp_protosw->pr_usrreqs, &ddp_usrreqs, sizeof(ddp_usrreqs)); ddp_usrreqs.pru_soreceive = t4_soreceive_ddp; ddp_protosw.pr_usrreqs = &ddp_usrreqs; + tcp6_protosw = pffindproto(PF_INET6, IPPROTO_TCP, SOCK_STREAM); + if (tcp6_protosw == NULL) + return (ENOPROTOOPT); + bcopy(tcp6_protosw, &ddp6_protosw, sizeof(ddp6_protosw)); + bcopy(tcp6_protosw->pr_usrreqs, &ddp6_usrreqs, sizeof(ddp6_usrreqs)); + ddp6_usrreqs.pru_soreceive = t4_soreceive_ddp; + ddp6_protosw.pr_usrreqs = &ddp6_usrreqs; + rc = t4_register_uld(&tom_uld_info); if (rc != 0) t4_tom_mod_unload(); @@ -721,11 +913,14 @@ t4_tom_mod_load(void) static void tom_uninit(struct adapter *sc, void *arg __unused) { + if (begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4tomun")) + return; + /* Try to free resources (works only if no port has IFCAP_TOE) */ - ADAPTER_LOCK(sc); if (sc->flags & TOM_INIT_DONE) t4_deactivate_uld(sc, ULD_TOM); - ADAPTER_UNLOCK(sc); + + end_synchronized_op(sc, LOCK_HELD); } static int diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h index 9549b0b..17c79a9 100644 --- a/sys/dev/cxgbe/tom/t4_tom.h +++ b/sys/dev/cxgbe/tom/t4_tom.h @@ -109,6 +109,7 @@ struct toepcb { struct sge_ofld_rxq *ofld_rxq; struct sge_wrq *ctrlq; struct l2t_entry *l2te; /* L2 table entry used by this connection */ + struct clip_entry *ce; /* CLIP table entry used by this tid */ int tid; /* Connection identifier */ unsigned int tx_credits;/* tx WR credits (in 16 byte units) remaining */ unsigned int sb_cc; /* last noted value of so_rcv->sb_cc */ @@ -140,15 +141,6 @@ struct flowc_tx_params { #define DDP_LOW_SCORE 1 #define DDP_HIGH_SCORE 3 -static inline void -set_tcpddp_ulp_mode(struct toepcb *toep) -{ - - toep->ulp_mode = ULP_MODE_TCPDDP; - toep->ddp_flags = DDP_OK; - toep->ddp_score = DDP_LOW_SCORE; -} - /* * Compressed state for embryonic connections for a listener. Barely fits in * 64B, try not to grow it further. @@ -174,6 +166,7 @@ struct listen_ctx { LIST_ENTRY(listen_ctx) link; /* listen hash linkage */ volatile int refcount; int stid; + struct stid_region stid_region; int flags; struct inpcb *inp; /* listening socket's inp */ struct sge_wrq *ctrlq; @@ -183,6 +176,12 @@ struct listen_ctx { TAILQ_HEAD(ppod_head, ppod_region); +struct clip_entry { + TAILQ_ENTRY(clip_entry) link; + struct in6_addr lip; /* local IPv6 address */ + u_int refcount; +}; + struct tom_data { struct toedev tod; @@ -200,6 +199,9 @@ struct tom_data { int nppods_free; /* # of available ppods */ int nppods_free_head; /* # of available ppods at the begining */ struct ppod_head ppods; + + struct mtx clip_table_lock; + TAILQ_HEAD(, clip_entry) clip_table; }; static inline struct tom_data * @@ -233,6 +235,9 @@ int select_rcv_wscale(void); uint64_t calc_opt0(struct socket *, struct port_info *, struct l2t_entry *, int, int, int, int); uint32_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t); +void set_tcpddp_ulp_mode(struct toepcb *); +struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *); +void release_lip(struct tom_data *, struct clip_entry *); /* t4_connect.c */ void t4_init_connect_cpl_handlers(struct adapter *); diff --git a/sys/dev/cxgbe/tom/t4_tom_l2t.c b/sys/dev/cxgbe/tom/t4_tom_l2t.c index ffe64c5..7a75394 100644 --- a/sys/dev/cxgbe/tom/t4_tom_l2t.c +++ b/sys/dev/cxgbe/tom/t4_tom_l2t.c @@ -27,6 +27,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" +#include "opt_inet6.h" #ifdef TCP_OFFLOAD #include <sys/param.h> @@ -34,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <sys/fnv_hash.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/rwlock.h> @@ -48,28 +50,89 @@ __FBSDID("$FreeBSD$"); #include <netinet/toecore.h> #include "common/common.h" -#include "common/jhash.h" #include "common/t4_msg.h" #include "tom/t4_tom_l2t.h" #include "tom/t4_tom.h" #define VLAN_NONE 0xfff -#define SA(x) ((struct sockaddr *)(x)) -#define SIN(x) ((struct sockaddr_in *)(x)) -#define SINADDR(x) (SIN(x)->sin_addr.s_addr) - static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e) { + if (atomic_fetchadd_int(&e->refcnt, 1) == 0) /* 0 -> 1 transition */ atomic_subtract_int(&d->nfree, 1); } -static inline unsigned int -arp_hash(const uint32_t key, int ifindex) +static inline u_int +l2_hash(struct l2t_data *d, const struct sockaddr *sa, int ifindex) { - return jhash_2words(key, ifindex, 0) & (L2T_SIZE - 1); + u_int hash, half = d->l2t_size / 2, start = 0; + const void *key; + size_t len; + + KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6, + ("%s: sa %p has unexpected sa_family %d", __func__, sa, + sa->sa_family)); + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const void *)sa; + + key = &sin->sin_addr; + len = sizeof(sin->sin_addr); + } else { + const struct sockaddr_in6 *sin6 = (const void *)sa; + + key = &sin6->sin6_addr; + len = sizeof(sin6->sin6_addr); + start = half; + } + + hash = fnv_32_buf(key, len, FNV1_32_INIT); + hash = fnv_32_buf(&ifindex, sizeof(ifindex), hash); + hash %= half; + + return (hash + start); +} + +static inline int +l2_cmp(const struct sockaddr *sa, struct l2t_entry *e) +{ + + KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6, + ("%s: sa %p has unexpected sa_family %d", __func__, sa, + sa->sa_family)); + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const void *)sa; + + return (e->addr[0] != sin->sin_addr.s_addr); + } else { + const struct sockaddr_in6 *sin6 = (const void *)sa; + + return (memcmp(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr))); + } +} + +static inline void +l2_store(const struct sockaddr *sa, struct l2t_entry *e) +{ + + KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6, + ("%s: sa %p has unexpected sa_family %d", __func__, sa, + sa->sa_family)); + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const void *)sa; + + e->addr[0] = sin->sin_addr.s_addr; + e->ipv6 = 0; + } else { + const struct sockaddr_in6 *sin6 = (const void *)sa; + + memcpy(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr)); + e->ipv6 = 1; + } } /* @@ -100,7 +163,7 @@ send_pending(struct adapter *sc, struct l2t_entry *e) static void resolution_failed_for_wr(struct wrqe *wr) { - log(LOG_ERR, "%s: leaked work request %p, wr_len %d", __func__, wr, + log(LOG_ERR, "%s: leaked work request %p, wr_len %d\n", __func__, wr, wr->wr_len); /* free(wr, M_CXGBE); */ @@ -175,15 +238,25 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e) struct tom_data *td = sc->tom_softc; struct toedev *tod = &td->tod; struct sockaddr_in sin = {0}; + struct sockaddr_in6 sin6 = {0}; + struct sockaddr *sa; uint8_t dmac[ETHER_ADDR_LEN]; uint16_t vtag = VLAN_NONE; int rc; - sin.sin_family = AF_INET; - sin.sin_len = sizeof(struct sockaddr_in); - SINADDR(&sin) = e->addr; + if (e->ipv6 == 0) { + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_addr.s_addr = e->addr[0]; + sa = (void *)&sin; + } else { + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(struct sockaddr_in6); + memcpy(&sin6.sin6_addr, &e->addr[0], sizeof(e->addr)); + sa = (void *)&sin6; + } - rc = toe_l2_resolve(tod, e->ifp, SA(&sin), dmac, &vtag); + rc = toe_l2_resolve(tod, e->ifp, sa, dmac, &vtag); if (rc == EWOULDBLOCK) return (rc); @@ -263,7 +336,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss, struct adapter *sc = iq->adapter; const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1); unsigned int tid = GET_TID(rpl); - unsigned int idx = tid & (L2T_SIZE - 1); + unsigned int idx = tid % L2T_SIZE; int rc; rc = do_l2t_write_rpl(iq, rss, m); @@ -271,7 +344,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss, return (rc); if (tid & F_SYNC_WR) { - struct l2t_entry *e = &sc->l2t->l2tab[idx]; + struct l2t_entry *e = &sc->l2t->l2tab[idx - sc->vres.l2t.start]; mtx_lock(&e->lock); if (e->state != L2T_STATE_SWITCHING) { @@ -310,21 +383,22 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa) { struct l2t_entry *e; struct l2t_data *d = pi->adapter->l2t; - uint32_t addr = SINADDR(sa); - int hash = arp_hash(addr, ifp->if_index); - unsigned int smt_idx = pi->port_id; + u_int hash, smt_idx = pi->port_id; - if (sa->sa_family != AF_INET) - return (NULL); /* XXX: no IPv6 support right now */ + KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6, + ("%s: sa %p has unexpected sa_family %d", __func__, sa, + sa->sa_family)); #ifndef VLAN_TAG if (ifp->if_type == IFT_L2VLAN) return (NULL); #endif + hash = l2_hash(d, sa, ifp->if_index); rw_wlock(&d->lock); for (e = d->l2tab[hash].first; e; e = e->next) { - if (e->addr == addr && e->ifp == ifp && e->smt_idx == smt_idx) { + if (l2_cmp(sa, e) == 0 && e->ifp == ifp && + e->smt_idx == smt_idx) { l2t_hold(d, e); goto done; } @@ -338,7 +412,7 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa) d->l2tab[hash].first = e; e->state = L2T_STATE_RESOLVING; - e->addr = addr; + l2_store(sa, e); e->ifp = ifp; e->smt_idx = smt_idx; e->hash = hash; @@ -368,14 +442,14 @@ t4_l2_update(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa, struct adapter *sc = tod->tod_softc; struct l2t_entry *e; struct l2t_data *d = sc->l2t; - uint32_t addr = SINADDR(sa); - int hash = arp_hash(addr, ifp->if_index); + u_int hash; KASSERT(d != NULL, ("%s: no L2 table", __func__)); + hash = l2_hash(d, sa, ifp->if_index); rw_rlock(&d->lock); for (e = d->l2tab[hash].first; e; e = e->next) { - if (e->addr == addr && e->ifp == ifp) { + if (l2_cmp(sa, e) == 0 && e->ifp == ifp) { mtx_lock(&e->lock); if (atomic_load_acq_int(&e->refcnt)) goto found; diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 8eb3011..efcbdfd 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -4330,8 +4330,8 @@ fail: * the rings that completed, the failing case will have * cleaned up for itself. 'i' is the endpoint. */ - for (int j = 0; j > i; ++j) { - rxr = &adapter->rx_rings[i]; + for (int j = 0; j < i; ++j) { + rxr = &adapter->rx_rings[j]; IGB_RX_LOCK(rxr); igb_free_receive_ring(rxr); IGB_RX_UNLOCK(rxr); diff --git a/sys/dev/fdt/fdt_mips.c b/sys/dev/fdt/fdt_mips.c index 0e6828e..4df31d8 100644 --- a/sys/dev/fdt/fdt_mips.c +++ b/sys/dev/fdt/fdt_mips.c @@ -49,8 +49,26 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; +/* + * For PIC-free boards, provide a PIC decoder to be used with mips4k CP0 + * interrupt control directly. + */ +static int +fdt_pic_decode_mips4k_cp0(phandle_t node, pcell_t *intr, int *interrupt, + int *trig, int *pol) +{ + + if (!fdt_is_compatible(node, "mips,mips4k")) + return (ENXIO); + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + + return (0); +} + fdt_pic_decode_t fdt_pic_table[] = { - NULL, - NULL, + &fdt_pic_decode_mips4k_cp0, NULL }; diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 9e82a34..2f2f05a 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -3022,7 +3022,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) } nevent = 0; - for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) { + for (ev = PMC_EV_SOFT_FIRST; (int)ev <= PMC_EV_SOFT_LAST; ev++) { ps = pmc_soft_ev_acquire(ev); if (ps == NULL) continue; diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c index c3d2dec..dac3612 100644 --- a/sys/dev/hwpmc/hwpmc_soft.c +++ b/sys/dev/hwpmc/hwpmc_soft.c @@ -116,7 +116,7 @@ soft_allocate_pmc(int cpu, int ri, struct pmc *pm, return (EPERM); ev = pm->pm_event; - if (ev < PMC_EV_SOFT_FIRST || ev > PMC_EV_SOFT_LAST) + if ((int)ev < PMC_EV_SOFT_FIRST || (int)ev > PMC_EV_SOFT_LAST) return (EINVAL); /* Check if event is registered. */ diff --git a/sys/dev/isf/isf.c b/sys/dev/isf/isf.c index e537799..eaaad15 100644 --- a/sys/dev/isf/isf.c +++ b/sys/dev/isf/isf.c @@ -150,6 +150,7 @@ static void isf_task(void *arg); * physical package, due to variable block size support in the StrataFlash * part. */ +devclass_t isf_devclass; static uint16_t isf_read_reg(struct isf_softc *sc, uint16_t reg) diff --git a/sys/dev/isf/isf.h b/sys/dev/isf/isf.h index f5cdc08..bfcca07 100644 --- a/sys/dev/isf/isf.h +++ b/sys/dev/isf/isf.h @@ -89,6 +89,8 @@ struct isf_softc { int isf_attach(struct isf_softc *sc); void isf_detach(struct isf_softc *sc); + +extern devclass_t isf_devclass; #endif /* _KERNEL */ #endif /* _DEV_ISF_H_ */ diff --git a/sys/dev/isf/isf_fdt.c b/sys/dev/isf/isf_fdt.c new file mode 100644 index 0000000..f4c20a2 --- /dev/null +++ b/sys/dev/isf/isf_fdt.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2012 Robert N. M. Watson + * Copyright (c) 2012 SRI International + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/bio.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/systm.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <geom/geom_disk.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/isf/isf.h> + +/* + * FDT bus attachment for the Intel Strata Flash devices. + */ +static int +isf_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "intel,strataflash")) { + device_set_desc(dev, "Intel StrataFlash NOR flash device"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +isf_fdt_attach(device_t dev) +{ + int error; + struct isf_softc *sc; + + sc = device_get_softc(dev); + sc->isf_dev = dev; + sc->isf_unit = device_get_unit(dev); + sc->isf_rid = 0; + sc->isf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->isf_rid, RF_ACTIVE); + if (sc->isf_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + return (ENXIO); + } + error = isf_attach(sc); + if (error) + bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, + sc->isf_res); + return (error); +} + +static int +isf_fdt_detach(device_t dev) +{ + struct isf_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc->isf_res != NULL, ("%s: resources not allocated", + __func__)); + isf_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, sc->isf_res); + return (0); +} + +static device_method_t isf_fdt_methods[] = { + DEVMETHOD(device_probe, isf_fdt_probe), + DEVMETHOD(device_attach, isf_fdt_attach), + DEVMETHOD(device_detach, isf_fdt_detach), + { 0, 0 } +}; + +static driver_t isf_fdt_driver = { + "isf", + isf_fdt_methods, + sizeof(struct isf_softc), +}; + +DRIVER_MODULE(isf, simplebus, isf_fdt_driver, isf_devclass, 0, 0); diff --git a/sys/dev/isf/isf_nexus.c b/sys/dev/isf/isf_nexus.c index af2f874..7631453 100644 --- a/sys/dev/isf/isf_nexus.c +++ b/sys/dev/isf/isf_nexus.c @@ -115,6 +115,4 @@ static driver_t isf_nexus_driver = { sizeof(struct isf_softc), }; -static devclass_t isf_devclass; - DRIVER_MODULE(isf, nexus, isf_nexus_driver, isf_devclass, 0, 0); diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c index 7b93306..d7bfb63 100644 --- a/sys/dev/puc/puc.c +++ b/sys/dev/puc/puc.c @@ -622,7 +622,7 @@ puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, if (cookiep == NULL || res != port->p_ires) return (EINVAL); /* We demand that serdev devices use filter_only interrupts. */ - if (ihand != NULL) + if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL) return (ENXIO); if (rman_get_device(port->p_ires) != originator) return (ENXIO); diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index b644f94..7d0450c 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> +#include <machine/atomic.h> #ifdef __sparc64__ #include <dev/ofw/openfirm.h> @@ -136,7 +137,7 @@ typedef u_int32_t u32; #elif defined __sparc64__ #define MEMORY_BARRIER() __asm__ volatile("membar #Sync" : : : "memory") #elif defined __arm__ -#define MEMORY_BARRIER() __do_dmb() +#define MEMORY_BARRIER() dmb() #else #error "Not supported platform" #endif @@ -3426,7 +3427,6 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp) /* * Check against our hardware limits, or bugs :). */ - if (fak < 0) {fak = 0; ret = -1;} if (fak > 2) {fak = 2; ret = -1;} /* diff --git a/sys/dev/terasic/de4led/terasic_de4led.c b/sys/dev/terasic/de4led/terasic_de4led.c index 1fb92d2..bcef7af 100644 --- a/sys/dev/terasic/de4led/terasic_de4led.c +++ b/sys/dev/terasic/de4led/terasic_de4led.c @@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$"); #include <dev/led/led.h> #include <dev/terasic/de4led/terasic_de4led.h> +devclass_t terasic_de4led_devclass; + static void terasic_de4led_update(struct terasic_de4led_softc *sc) { diff --git a/sys/dev/terasic/de4led/terasic_de4led.h b/sys/dev/terasic/de4led/terasic_de4led.h index 89461d1..4475e9b 100644 --- a/sys/dev/terasic/de4led/terasic_de4led.h +++ b/sys/dev/terasic/de4led/terasic_de4led.h @@ -72,4 +72,6 @@ struct terasic_de4led_softc { void terasic_de4led_attach(struct terasic_de4led_softc *sc); void terasic_de4led_detach(struct terasic_de4led_softc *sc); +extern devclass_t terasic_de4led_devclass; + #endif /* _DEV_TERASIC_DE4LED_H_ */ diff --git a/sys/dev/terasic/de4led/terasic_de4led_fdt.c b/sys/dev/terasic/de4led/terasic_de4led_fdt.c new file mode 100644 index 0000000..0888d6d --- /dev/null +++ b/sys/dev/terasic/de4led/terasic_de4led_fdt.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2012 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/bio.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/systm.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/terasic/de4led/terasic_de4led.h> + +/* + * Nexus bus attachment for the 8-element LED on the Terasic DE-4 FPGA board, + * which is hooked up to the processor via a memory-mapped Avalon bus. + */ +static int +terasic_de4led_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "sri-cambridge,de4led")) { + device_set_desc(dev, "Terasic DE4 8-element LED"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +terasic_de4led_fdt_attach(device_t dev) +{ + struct terasic_de4led_softc *sc; + + sc = device_get_softc(dev); + sc->tdl_dev = dev; + sc->tdl_unit = device_get_unit(dev); + sc->tdl_rid = 0; + sc->tdl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->tdl_rid, RF_ACTIVE); + if (sc->tdl_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + return (ENXIO); + } + terasic_de4led_attach(sc); + return (0); +} + +static int +terasic_de4led_fdt_detach(device_t dev) +{ + struct terasic_de4led_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc->tdl_res != NULL, ("%s: resources not allocated", + __func__)); + terasic_de4led_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->tdl_rid, sc->tdl_res); + return (0); +} + +static device_method_t terasic_de4led_fdt_methods[] = { + DEVMETHOD(device_probe, terasic_de4led_fdt_probe), + DEVMETHOD(device_attach, terasic_de4led_fdt_attach), + DEVMETHOD(device_detach, terasic_de4led_fdt_detach), + { 0, 0 } +}; + +static driver_t terasic_de4led_fdt_driver = { + "terasic_de4led", + terasic_de4led_fdt_methods, + sizeof(struct terasic_de4led_softc), +}; + +DRIVER_MODULE(terasic_de4led, simplebus, terasic_de4led_fdt_driver, + terasic_de4led_devclass, 0, 0); diff --git a/sys/dev/terasic/de4led/terasic_de4led_nexus.c b/sys/dev/terasic/de4led/terasic_de4led_nexus.c index 92da503..870d412 100644 --- a/sys/dev/terasic/de4led/terasic_de4led_nexus.c +++ b/sys/dev/terasic/de4led/terasic_de4led_nexus.c @@ -106,7 +106,5 @@ static driver_t terasic_de4led_nexus_driver = { sizeof(struct terasic_de4led_softc), }; -static devclass_t terasic_de4led_devclass; - DRIVER_MODULE(terasic_de4led, nexus, terasic_de4led_nexus_driver, terasic_de4led_devclass, 0, 0); diff --git a/sys/dev/terasic/mtl/terasic_mtl.c b/sys/dev/terasic/mtl/terasic_mtl.c index 48e60c7..5305172 100644 --- a/sys/dev/terasic/mtl/terasic_mtl.c +++ b/sys/dev/terasic/mtl/terasic_mtl.c @@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$"); * attached as they may be called even if the attach routine hasn't been, on * an error. */ + +devclass_t terasic_mtl_devclass; + int terasic_mtl_attach(struct terasic_mtl_softc *sc) { diff --git a/sys/dev/terasic/mtl/terasic_mtl.h b/sys/dev/terasic/mtl/terasic_mtl.h index ae41067..e07bbf4 100644 --- a/sys/dev/terasic/mtl/terasic_mtl.h +++ b/sys/dev/terasic/mtl/terasic_mtl.h @@ -159,6 +159,8 @@ struct terasic_mtl_softc { int terasic_mtl_attach(struct terasic_mtl_softc *sc); void terasic_mtl_detach(struct terasic_mtl_softc *sc); +extern devclass_t terasic_mtl_devclass; + /* * Sub-driver setup routines. */ diff --git a/sys/dev/terasic/mtl/terasic_mtl_fdt.c b/sys/dev/terasic/mtl/terasic_mtl_fdt.c new file mode 100644 index 0000000..7ffffb2 --- /dev/null +++ b/sys/dev/terasic/mtl/terasic_mtl_fdt.c @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2012-2013 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/consio.h> /* struct vt_mode */ +#include <sys/fbio.h> /* video_adapter_t */ +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/systm.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/terasic/mtl/terasic_mtl.h> + +static int +terasic_mtl_fdt_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "sri-cambridge,mtl")) { + device_set_desc(dev, "Terasic Multi-touch LCD (MTL)"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +terasic_mtl_fdt_attach(device_t dev) +{ + struct terasic_mtl_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->mtl_dev = dev; + sc->mtl_unit = device_get_unit(dev); + + /* + * FDT allows multiple memory resources to be defined for a device; + * query them in the order registers, pixel buffer, text buffer. + * However, we need to sanity-check that they are page-aligned and + * page-sized, so we may still abort. + */ + sc->mtl_reg_rid = 0; + sc->mtl_reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->mtl_reg_rid, RF_ACTIVE); + if (sc->mtl_reg_res == NULL) { + device_printf(dev, "couldn't map register memory\n"); + error = ENXIO; + goto error; + } + if (rman_get_start(sc->mtl_reg_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper register address"); + error = ENXIO; + goto error; + } + if (rman_get_size(sc->mtl_reg_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper register size"); + error = ENXIO; + goto error; + } + device_printf(sc->mtl_dev, "registers at mem %p-%p\n", + (void *)rman_get_start(sc->mtl_reg_res), + (void *)(rman_get_start(sc->mtl_reg_res) + + rman_get_size(sc->mtl_reg_res))); + + sc->mtl_pixel_rid = 1; + sc->mtl_pixel_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->mtl_pixel_rid, RF_ACTIVE); + if (sc->mtl_pixel_res == NULL) { + device_printf(dev, "couldn't map pixel memory\n"); + error = ENXIO; + goto error; + } + if (rman_get_start(sc->mtl_pixel_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper pixel address"); + error = ENXIO; + goto error; + } + if (rman_get_size(sc->mtl_pixel_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper pixel size"); + error = ENXIO; + goto error; + } + device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n", + (void *)rman_get_start(sc->mtl_pixel_res), + (void *)(rman_get_start(sc->mtl_pixel_res) + + rman_get_size(sc->mtl_pixel_res))); + + sc->mtl_text_rid = 2; + sc->mtl_text_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->mtl_text_rid, RF_ACTIVE); + if (sc->mtl_text_res == NULL) { + device_printf(dev, "couldn't map text memory\n"); + error = ENXIO; + goto error; + } + if (rman_get_start(sc->mtl_text_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper text address"); + error = ENXIO; + goto error; + } + if (rman_get_size(sc->mtl_text_res) % PAGE_SIZE != 0) { + device_printf(dev, "improper text size"); + error = ENXIO; + goto error; + } + device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n", + (void *)rman_get_start(sc->mtl_text_res), + (void *)(rman_get_start(sc->mtl_text_res) + + rman_get_size(sc->mtl_text_res))); + + error = terasic_mtl_attach(sc); + if (error == 0) + return (0); +error: + if (sc->mtl_text_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid, + sc->mtl_text_res); + if (sc->mtl_pixel_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid, + sc->mtl_pixel_res); + if (sc->mtl_reg_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid, + sc->mtl_reg_res); + return (error); +} + +static int +terasic_mtl_fdt_detach(device_t dev) +{ + struct terasic_mtl_softc *sc; + + sc = device_get_softc(dev); + terasic_mtl_detach(sc); + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid, + sc->mtl_text_res); + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid, + sc->mtl_pixel_res); + bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid, + sc->mtl_reg_res); + return (0); +} + +static device_method_t terasic_mtl_fdt_methods[] = { + DEVMETHOD(device_probe, terasic_mtl_fdt_probe), + DEVMETHOD(device_attach, terasic_mtl_fdt_attach), + DEVMETHOD(device_detach, terasic_mtl_fdt_detach), + { 0, 0 } +}; + +static driver_t terasic_mtl_fdt_driver = { + "terasic_mtl", + terasic_mtl_fdt_methods, + sizeof(struct terasic_mtl_softc), +}; + +DRIVER_MODULE(mtl, simplebus, terasic_mtl_fdt_driver, terasic_mtl_devclass, 0, + 0); diff --git a/sys/dev/terasic/mtl/terasic_mtl_nexus.c b/sys/dev/terasic/mtl/terasic_mtl_nexus.c index 4a6f2ba..2dff7db 100644 --- a/sys/dev/terasic/mtl/terasic_mtl_nexus.c +++ b/sys/dev/terasic/mtl/terasic_mtl_nexus.c @@ -190,7 +190,5 @@ static driver_t terasic_mtl_nexus_driver = { sizeof(struct terasic_mtl_softc), }; -static devclass_t terasic_mtl_devclass; - DRIVER_MODULE(mtl, nexus, terasic_mtl_nexus_driver, terasic_mtl_devclass, 0, 0); diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 45ac8fc..7a3e955 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -995,13 +995,12 @@ ukbd_probe(device_t dev) if (uaa->info.bInterfaceClass != UICLASS_HID) return (ENXIO); + if (usb_test_quirk(uaa, UQ_KBD_IGNORE)) + return (ENXIO); + if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) && - (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) { - if (usb_test_quirk(uaa, UQ_KBD_IGNORE)) - return (ENXIO); - else - return (BUS_PROBE_DEFAULT); - } + (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) + return (BUS_PROBE_DEFAULT); error = usbd_req_get_hid_desc(uaa->device, NULL, &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); @@ -1009,23 +1008,20 @@ ukbd_probe(device_t dev) if (error) return (ENXIO); - /* - * NOTE: we currently don't support USB mouse and USB keyboard - * on the same USB endpoint. - */ - if (hid_is_collection(d_ptr, d_len, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) { - /* most likely a mouse */ - error = ENXIO; - } else if (hid_is_collection(d_ptr, d_len, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) { - if (usb_test_quirk(uaa, UQ_KBD_IGNORE)) + if (hid_is_keyboard(d_ptr, d_len)) { + if (hid_is_mouse(d_ptr, d_len)) { + /* + * NOTE: We currently don't support USB mouse + * and USB keyboard on the same USB endpoint. + * Let "ums" driver win. + */ error = ENXIO; - else + } else { error = BUS_PROBE_DEFAULT; - } else + } + } else { error = ENXIO; - + } free(d_ptr, M_TEMP); return (error); } diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c index c20c986..52e1b53 100644 --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -368,9 +368,7 @@ ums_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); void *d_ptr; - struct hid_data *hd; - struct hid_item hi; - int error, mdepth, found; + int error; uint16_t d_len; DPRINTFN(11, "\n"); @@ -394,44 +392,13 @@ ums_probe(device_t dev) if (error) return (ENXIO); - hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); - if (hd == NULL) - return (0); - mdepth = 0; - found = 0; - while (hid_get_item(hd, &hi)) { - switch (hi.kind) { - case hid_collection: - if (mdepth != 0) - mdepth++; - else if (hi.collection == 1 && - hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) - mdepth++; - break; - case hid_endcollection: - if (mdepth != 0) - mdepth--; - break; - case hid_input: - if (mdepth == 0) - break; - if (hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && - (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) - found++; - if (hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && - (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) - found++; - break; - default: - break; - } - } - hid_end_parse(hd); + if (hid_is_mouse(d_ptr, d_len)) + error = BUS_PROBE_DEFAULT; + else + error = ENXIO; + free(d_ptr, M_TEMP); - return (found ? BUS_PROBE_DEFAULT : ENXIO); + return (error); } static void diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c index b8f07aa..b1f4d74 100644 --- a/sys/dev/usb/quirk/usb_quirk.c +++ b/sys/dev/usb/quirk/usb_quirk.c @@ -799,7 +799,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, } if (x == USB_SUB_QUIRKS_MAX) { /* all quirk entries are unused - release */ - memset(pqe, 0, sizeof(pqe)); + memset(pqe, 0, sizeof(*pqe)); } mtx_unlock(&usb_quirk_mtx); return (0); /* success */ diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index dc670d66..f2c3a45 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -356,6 +356,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(NOVATEL, V740, 0), U3G_DEV(NOVATEL, X950D, 0), U3G_DEV(NOVATEL, XU870, 0), + U3G_DEV(MOTOROLA2, MB886, U3GINIT_SCSIEJECT), U3G_DEV(OPTION, E6500, 0), U3G_DEV(OPTION, E6501, 0), U3G_DEV(OPTION, E6601, 0), diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index 48ae389..0785940 100644 --- a/sys/dev/usb/storage/umass.c +++ b/sys/dev/usb/storage/umass.c @@ -2251,8 +2251,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) /*ascq*/ 0x00, /*extra args*/ SSD_ELEM_NONE); ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | - CAM_AUTOSNS_VALID; + ccb->ccb_h.status = + CAM_SCSI_STATUS_ERROR | + CAM_AUTOSNS_VALID | + CAM_DEV_QFRZN; + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); goto done; } @@ -2512,7 +2515,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, * recovered. We return an error to CAM and let CAM * retry the command if necessary. */ - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN; xpt_done(ccb); break; } @@ -2575,8 +2579,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, * usual. */ + xpt_freeze_devq(ccb->ccb_h.path, 1); ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; + | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; #if 0 @@ -2587,17 +2592,18 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, /* the rest of the command was filled in at attach */ - if (umass_std_transform(sc, ccb, + if ((sc->sc_transform)(sc, &sc->cam_scsi_test_unit_ready.opcode, - sizeof(sc->cam_scsi_test_unit_ready))) { + sizeof(sc->cam_scsi_test_unit_ready)) == 1) { umass_command_start(sc, DIR_NONE, NULL, 0, ccb->ccb_h.timeout, &umass_cam_quirk_cb, ccb); + break; } - break; } else { + xpt_freeze_devq(ccb->ccb_h.path, 1); ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; + | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; } xpt_done(ccb); @@ -2606,15 +2612,16 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, default: DPRINTF(sc, UDMASS_SCSI, "Autosense failed, " "status %d\n", status); - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN; xpt_done(ccb); } } /* * This completion code just handles the fact that we sent a test-unit-ready - * after having previously failed a READ CAPACITY with CHECK_COND. Even - * though this command succeeded, we have to tell CAM to retry. + * after having previously failed a READ CAPACITY with CHECK_COND. The CCB + * status for CAM is already set earlier. */ static void umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, @@ -2623,9 +2630,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, DPRINTF(sc, UDMASS_SCSI, "Test unit ready " "returned status %d\n", status); - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; xpt_done(ccb); } @@ -2914,7 +2918,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb, xpt_done(ccb); return (0); } else if (retval == 0) { - ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN; xpt_done(ccb); return (0); } diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c index 6552546..c201bb4 100644 --- a/sys/dev/usb/usb_hid.c +++ b/sys/dev/usb/usb_hid.c @@ -845,3 +845,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, } return (USB_ERR_NORMAL_COMPLETION); } + +/*------------------------------------------------------------------------* + * hid_is_mouse + * + * This function will decide if a USB descriptor belongs to a USB mouse. + * + * Return values: + * Zero: Not a USB mouse. + * Else: Is a USB mouse. + *------------------------------------------------------------------------*/ +int +hid_is_mouse(const void *d_ptr, uint16_t d_len) +{ + struct hid_data *hd; + struct hid_item hi; + int mdepth; + int found; + + hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); + if (hd == NULL) + return (0); + + mdepth = 0; + found = 0; + + while (hid_get_item(hd, &hi)) { + switch (hi.kind) { + case hid_collection: + if (mdepth != 0) + mdepth++; + else if (hi.collection == 1 && + hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) + mdepth++; + break; + case hid_endcollection: + if (mdepth != 0) + mdepth--; + break; + case hid_input: + if (mdepth == 0) + break; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + break; + default: + break; + } + } + hid_end_parse(hd); + return (found); +} + +/*------------------------------------------------------------------------* + * hid_is_keyboard + * + * This function will decide if a USB descriptor belongs to a USB keyboard. + * + * Return values: + * Zero: Not a USB keyboard. + * Else: Is a USB keyboard. + *------------------------------------------------------------------------*/ +int +hid_is_keyboard(const void *d_ptr, uint16_t d_len) +{ + if (hid_is_collection(d_ptr, d_len, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) + return (1); + return (0); +} diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 0cd43ef..bd30dbf 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -2939,6 +2939,7 @@ product MOTOROLA2 A41XV32X 0x2a22 A41x/V32x Mobile Phones product MOTOROLA2 E398 0x4810 E398 Mobile Phone product MOTOROLA2 USBLAN 0x600c USBLAN product MOTOROLA2 USBLAN2 0x6027 USBLAN +product MOTOROLA2 MB886 0x710f MB886 Mobile Phone (Atria HD) product MOTOROLA4 RT2770 0x9031 RT2770 product MOTOROLA4 RT3070 0x9032 RT3070 diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h index f40232a..f6c447c 100644 --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -242,5 +242,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb( usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index); +int hid_is_mouse(const void *d_ptr, uint16_t d_len); +int hid_is_keyboard(const void *d_ptr, uint16_t d_len); #endif /* _KERNEL */ #endif /* _USB_HID_H_ */ diff --git a/sys/dev/wbwd/wbwd.c b/sys/dev/wbwd/wbwd.c index dfd8f3c..484b5bf 100644 --- a/sys/dev/wbwd/wbwd.c +++ b/sys/dev/wbwd/wbwd.c @@ -179,6 +179,12 @@ struct winbond_vendor_device_id { .device_rev = 0x73, .descr = "Winbond 83627DHG-P", }, + { + .vendor_id = 0x5ca3, + .device_id = 0xc3, + .device_rev = 0x33, + .descr = "Nuvoton WPCM450RA0BX", + }, }; static void @@ -596,6 +602,9 @@ wb_probe_enable(device_t dev, int probe) goto cleanup; } + if (dev_id == 0xff && dev_rev == 0xff) + goto cleanup; + for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) { if (wb_devs[j].device_id == dev_id && wb_devs[j].device_rev == dev_rev) { @@ -605,6 +614,16 @@ wb_probe_enable(device_t dev, int probe) break; } } + + if (!found) { + if (probe && dev != NULL) { + device_set_desc(dev, "Unknown Winbond/Nuvoton model"); + device_printf(dev, "DevID 0x%02x DevRev 0x%02x, " + "please report this.\n", dev_id, dev_rev); + } + found++; + } + if (probe && found && bootverbose && dev != NULL) device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x" " CR26 0x%02x (probing)\n", device_get_desc(dev), diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index 6640c1f..cce95b2 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -767,12 +767,18 @@ tryagain: if (stat == RPC_SUCCESS) { error = 0; } else if (stat == RPC_TIMEDOUT) { + NFSINCRGLOBAL(newnfsstats.rpctimeouts); error = ETIMEDOUT; } else if (stat == RPC_VERSMISMATCH) { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EOPNOTSUPP; } else if (stat == RPC_PROGVERSMISMATCH) { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EPROTONOSUPPORT; + } else if (stat == RPC_INTR) { + error = EINTR; } else { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EACCES; } if (error) { diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 95aa7bd..efc0786 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -1998,7 +1998,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, struct statfs fs; struct nfsfsinfo fsinf; struct timespec temptime; - struct timeval curtime; NFSACL_T *aclp, *naclp = NULL; #ifdef QUOTA struct dqblk dqb; @@ -2412,8 +2411,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, retnum += NFSX_V4TIME; break; case NFSATTRBIT_TIMEACCESSSET: - NFSGETTIME(&curtime); - if (vap->va_atime.tv_sec != curtime.tv_sec) { + if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) { NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME); *tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT); txdr_nfsv4time(&vap->va_atime, tl); @@ -2442,8 +2440,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, retnum += NFSX_V4TIME; break; case NFSATTRBIT_TIMEMODIFYSET: - NFSGETTIME(&curtime); - if (vap->va_mtime.tv_sec != curtime.tv_sec) { + if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) { NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME); *tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT); txdr_nfsv4time(&vap->va_mtime, tl); diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index 145ff63..152f13f 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -789,7 +789,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap, *tl = newnfs_false; } if (vap->va_atime.tv_sec != VNOVAL) { - if (vap->va_atime.tv_sec != curtime.tv_sec) { + if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) { NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); txdr_nfsv3time(&vap->va_atime, tl); @@ -802,7 +802,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap, *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); } if (vap->va_mtime.tv_sec != VNOVAL) { - if (vap->va_mtime.tv_sec != curtime.tv_sec) { + if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) { NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); txdr_nfsv3time(&vap->va_mtime, tl); diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 0b72249..90e56ea 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -46,9 +46,6 @@ #include <fs/nullfs/null.h> -#define LOG2_SIZEVNODE 8 /* log2(sizeof struct vnode) */ -#define NNULLNODECACHE 16 - /* * Null layer cache: * Each cache entry holds a reference to the lower vnode @@ -57,12 +54,11 @@ * alias is removed the lower vnode is vrele'd. */ -#define NULL_NHASH(vp) \ - (&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash]) +#define NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask]) static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl; -static u_long null_node_hash; -struct mtx null_hashmtx; +static struct mtx null_hashmtx; +static u_long null_hash_mask; static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table"); MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part"); @@ -77,8 +73,8 @@ nullfs_init(vfsp) struct vfsconf *vfsp; { - NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */ - null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash); + null_node_hashtbl = hashinit(desiredvnodes, M_NULLFSHASH, + &null_hash_mask); mtx_init(&null_hashmtx, "nullhs", NULL, MTX_DEF); return (0); } @@ -89,7 +85,7 @@ nullfs_uninit(vfsp) { mtx_destroy(&null_hashmtx); - hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_node_hash); + hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_hash_mask); return (0); } diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 5abfa49..3724e0a 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -67,15 +67,6 @@ static vfs_vget_t nullfs_vget; static vfs_extattrctl_t nullfs_extattrctl; static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp; -/* Mount options that we support. */ -static const char *nullfs_opts[] = { - "cache", - "export", - "from", - "target", - NULL -}; - /* * Mount null layer */ @@ -97,8 +88,6 @@ nullfs_mount(struct mount *mp) return (EPERM); if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); - if (vfs_filteropt(mp->mnt_optnew, nullfs_opts)) - return (EINVAL); /* * Update is a no-op diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index cc35d81..f59865f 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -740,6 +740,14 @@ null_reclaim(struct vop_reclaim_args *ap) vp->v_object = NULL; vp->v_vnlock = &vp->v_lock; VI_UNLOCK(vp); + + /* + * If we were opened for write, we leased one write reference + * to the lower vnode. If this is a reclamation due to the + * forced unmount, undo the reference now. + */ + if (vp->v_writecount > 0) + VOP_ADD_WRITECOUNT(lowervp, -1); vput(lowervp); free(xp, M_NULLFSNODE); diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c index 4581430..a3c996c 100644 --- a/sys/geom/journal/g_journal.c +++ b/sys/geom/journal/g_journal.c @@ -2976,7 +2976,7 @@ g_journal_do_switch(struct g_class *classp) g_journal_switch_wait(sc); mtx_unlock(&sc->sc_mtx); - vfs_write_resume(mp); + vfs_write_resume(mp, 0); next: mtx_lock(&mountlist_mtx); vfs_unbusy(mp); diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 17271dd..d77dee9 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -81,7 +81,8 @@ SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, sync_requests, CTLFLAG_RDTUN, G_MIRROR_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \ } while (0) -static eventhandler_tag g_mirror_pre_sync = NULL; +static eventhandler_tag g_mirror_post_sync = NULL; +static int g_mirror_shutdown = 0; static int g_mirror_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp); @@ -815,7 +816,7 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw) return (0); if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) { timeout = g_mirror_idletime - (time_uptime - sc->sc_last_write); - if (timeout > 0) + if (!g_mirror_shutdown && timeout > 0) return (timeout); } sc->sc_idle = 1; @@ -2821,7 +2822,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace) error = ENXIO; goto end; } - if (dcw == 0 && !sc->sc_idle) + if (dcw == 0) g_mirror_idle(sc, dcw); if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) { if (acr > 0 || acw > 0 || ace > 0) { @@ -3232,7 +3233,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, } static void -g_mirror_shutdown_pre_sync(void *arg, int howto) +g_mirror_shutdown_post_sync(void *arg, int howto) { struct g_class *mp; struct g_geom *gp, *gp2; @@ -3242,6 +3243,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto) mp = arg; DROP_GIANT(); g_topology_lock(); + g_mirror_shutdown = 1; LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { if ((sc = gp->softc) == NULL) continue; @@ -3250,6 +3252,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto) continue; g_topology_unlock(); sx_xlock(&sc->sc_lock); + g_mirror_idle(sc, -1); g_cancel_event(sc); error = g_mirror_destroy(sc, G_MIRROR_DESTROY_DELAYED); if (error != 0) @@ -3264,9 +3267,9 @@ static void g_mirror_init(struct g_class *mp) { - g_mirror_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync, - g_mirror_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST); - if (g_mirror_pre_sync == NULL) + g_mirror_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync, + g_mirror_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST); + if (g_mirror_post_sync == NULL) G_MIRROR_DEBUG(0, "Warning! Cannot register shutdown event."); } @@ -3274,8 +3277,8 @@ static void g_mirror_fini(struct g_class *mp) { - if (g_mirror_pre_sync != NULL) - EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_mirror_pre_sync); + if (g_mirror_post_sync != NULL) + EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_mirror_post_sync); } DECLARE_GEOM_CLASS(g_mirror_class, g_mirror); diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c index 19b6d9b..91d14c3 100644 --- a/sys/geom/raid/g_raid.c +++ b/sys/geom/raid/g_raid.c @@ -163,6 +163,8 @@ g_raid_disk_state2str(int state) return ("NONE"); case G_RAID_DISK_S_OFFLINE: return ("OFFLINE"); + case G_RAID_DISK_S_DISABLED: + return ("DISABLED"); case G_RAID_DISK_S_FAILED: return ("FAILED"); case G_RAID_DISK_S_STALE_FAILED: @@ -535,7 +537,9 @@ g_raid_report_disk_state(struct g_raid_disk *disk) if (disk->d_consumer == NULL) return; - if (disk->d_state == G_RAID_DISK_S_FAILED || + if (disk->d_state == G_RAID_DISK_S_DISABLED) { + s = G_STATE_ACTIVE; /* XXX */ + } else if (disk->d_state == G_RAID_DISK_S_FAILED || disk->d_state == G_RAID_DISK_S_STALE_FAILED) { s = G_STATE_FAILED; } else { diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h index 20b0822..183edff6 100644 --- a/sys/geom/raid/g_raid.h +++ b/sys/geom/raid/g_raid.h @@ -140,11 +140,12 @@ struct g_raid_event { }; #define G_RAID_DISK_S_NONE 0x00 /* State is unknown. */ #define G_RAID_DISK_S_OFFLINE 0x01 /* Missing disk placeholder. */ -#define G_RAID_DISK_S_FAILED 0x02 /* Failed. */ -#define G_RAID_DISK_S_STALE_FAILED 0x03 /* Old failed. */ -#define G_RAID_DISK_S_SPARE 0x04 /* Hot-spare. */ -#define G_RAID_DISK_S_STALE 0x05 /* Old disk, unused now. */ -#define G_RAID_DISK_S_ACTIVE 0x06 /* Operational. */ +#define G_RAID_DISK_S_DISABLED 0x02 /* Disabled. */ +#define G_RAID_DISK_S_FAILED 0x03 /* Failed. */ +#define G_RAID_DISK_S_STALE_FAILED 0x04 /* Old failed. */ +#define G_RAID_DISK_S_SPARE 0x05 /* Hot-spare. */ +#define G_RAID_DISK_S_STALE 0x06 /* Old disk, unused now. */ +#define G_RAID_DISK_S_ACTIVE 0x07 /* Operational. */ #define G_RAID_DISK_E_DISCONNECTED 0x01 diff --git a/sys/geom/raid/md_intel.c b/sys/geom/raid/md_intel.c index 12122b0..eeb42d5 100644 --- a/sys/geom/raid/md_intel.c +++ b/sys/geom/raid/md_intel.c @@ -98,6 +98,9 @@ struct intel_raid_vol { uint8_t cng_master_disk; uint16_t cache_policy; uint8_t cng_state; +#define INTEL_CNGST_UPDATED 0 +#define INTEL_CNGST_NEEDS_UPDATE 1 +#define INTEL_CNGST_MASTER_MISSING 2 uint8_t cng_sub_state; uint32_t filler_0[10]; @@ -130,6 +133,7 @@ struct intel_raid_disk { #define INTEL_F_ASSIGNED 0x02 #define INTEL_F_FAILED 0x04 #define INTEL_F_ONLINE 0x08 +#define INTEL_F_DISABLED 0x80 uint32_t owner_cfg_num; uint32_t sectors_hi; uint32_t filler[3]; @@ -162,18 +166,33 @@ struct intel_raid_conf { #define INTEL_ATTR_RAID1E 0x00000008 #define INTEL_ATTR_RAID5 0x00000010 #define INTEL_ATTR_RAIDCNG 0x00000020 +#define INTEL_ATTR_EXT_STRIP 0x00000040 +#define INTEL_ATTR_NVM_CACHE 0x02000000 +#define INTEL_ATTR_2TB_DISK 0x04000000 +#define INTEL_ATTR_BBM 0x08000000 +#define INTEL_ATTR_NVM_CACHE2 0x10000000 #define INTEL_ATTR_2TB 0x20000000 #define INTEL_ATTR_PM 0x40000000 #define INTEL_ATTR_CHECKSUM 0x80000000 uint8_t total_disks; uint8_t total_volumes; - uint8_t dummy_2[2]; - uint32_t filler_0[39]; + uint8_t error_log_pos; + uint8_t dummy_2[1]; + uint32_t cache_size; + uint32_t orig_config_id; + uint32_t pwr_cycle_count; + uint32_t bbm_log_size; + uint32_t filler_0[35]; struct intel_raid_disk disk[1]; /* total_disks entries. */ /* Here goes total_volumes of struct intel_raid_vol. */ } __packed; +#define INTEL_ATTR_SUPPORTED ( INTEL_ATTR_RAID0 | INTEL_ATTR_RAID1 | \ + INTEL_ATTR_RAID10 | INTEL_ATTR_RAID1E | INTEL_ATTR_RAID5 | \ + INTEL_ATTR_RAIDCNG | INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | \ + INTEL_ATTR_2TB | INTEL_ATTR_PM | INTEL_ATTR_CHECKSUM ) + #define INTEL_MAX_MD_SIZE(ndisks) \ (sizeof(struct intel_raid_conf) + \ sizeof(struct intel_raid_disk) * (ndisks - 1) + \ @@ -187,9 +206,17 @@ struct g_raid_md_intel_perdisk { struct intel_raid_disk pd_disk_meta; }; +struct g_raid_md_intel_pervolume { + int pv_volume_pos; + int pv_cng; + int pv_cng_man_sync; + int pv_cng_master_disk; +}; + struct g_raid_md_intel_object { struct g_raid_md_object mdio_base; uint32_t mdio_config_id; + uint32_t mdio_orig_config_id; uint32_t mdio_generation; struct intel_raid_conf *mdio_meta; struct callout mdio_start_co; /* STARTING state timer. */ @@ -206,6 +233,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_intel; static g_raid_md_write_t g_raid_md_write_intel; static g_raid_md_fail_disk_t g_raid_md_fail_disk_intel; static g_raid_md_free_disk_t g_raid_md_free_disk_intel; +static g_raid_md_free_volume_t g_raid_md_free_volume_intel; static g_raid_md_free_t g_raid_md_free_intel; static kobj_method_t g_raid_md_intel_methods[] = { @@ -216,6 +244,7 @@ static kobj_method_t g_raid_md_intel_methods[] = { KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel), KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_intel), KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel), + KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_intel), KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel), { 0, 0 } }; @@ -354,29 +383,45 @@ g_raid_md_intel_print(struct intel_raid_conf *meta) printf("config_size 0x%08x\n", meta->config_size); printf("config_id 0x%08x\n", meta->config_id); printf("generation 0x%08x\n", meta->generation); + printf("error_log_size %d\n", meta->error_log_size); printf("attributes 0x%08x\n", meta->attributes); printf("total_disks %u\n", meta->total_disks); printf("total_volumes %u\n", meta->total_volumes); - printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags\n"); + printf("error_log_pos %u\n", meta->error_log_pos); + printf("cache_size %u\n", meta->cache_size); + printf("orig_config_id 0x%08x\n", meta->orig_config_id); + printf("pwr_cycle_count %u\n", meta->pwr_cycle_count); + printf("bbm_log_size %u\n", meta->bbm_log_size); + printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags owner\n"); for (i = 0; i < meta->total_disks; i++ ) { - printf(" %d <%.16s> %u %u 0x%08x 0x%08x\n", i, + printf(" %d <%.16s> %u %u 0x%08x 0x%08x %08x\n", i, meta->disk[i].serial, meta->disk[i].sectors, - meta->disk[i].sectors_hi, - meta->disk[i].id, meta->disk[i].flags); + meta->disk[i].sectors_hi, meta->disk[i].id, + meta->disk[i].flags, meta->disk[i].owner_cfg_num); } for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); printf(" ****** Volume %d ******\n", i); printf(" name %.16s\n", mvol->name); printf(" total_sectors %ju\n", mvol->total_sectors); - printf(" state %u\n", mvol->state); + printf(" state 0x%08x\n", mvol->state); printf(" reserved %u\n", mvol->reserved); + printf(" migr_priority %u\n", mvol->migr_priority); + printf(" num_sub_vols %u\n", mvol->num_sub_vols); + printf(" tid %u\n", mvol->tid); + printf(" cng_master_disk %u\n", mvol->cng_master_disk); + printf(" cache_policy %u\n", mvol->cache_policy); + printf(" cng_state %u\n", mvol->cng_state); + printf(" cng_sub_state %u\n", mvol->cng_sub_state); printf(" curr_migr_unit %u\n", mvol->curr_migr_unit); printf(" curr_migr_unit_hi %u\n", mvol->curr_migr_unit_hi); printf(" checkpoint_id %u\n", mvol->checkpoint_id); printf(" migr_state %u\n", mvol->migr_state); printf(" migr_type %u\n", mvol->migr_type); printf(" dirty %u\n", mvol->dirty); + printf(" fs_state %u\n", mvol->fs_state); + printf(" verify_errors %u\n", mvol->verify_errors); + printf(" bad_blocks %u\n", mvol->bad_blocks); for (j = 0; j < (mvol->migr_state ? 2 : 1); j++) { printf(" *** Map %d ***\n", j); @@ -432,7 +477,7 @@ intel_meta_read(struct g_consumer *cp) struct g_provider *pp; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; - struct intel_raid_map *mmap; + struct intel_raid_map *mmap, *mmap1; char *buf; int error, i, j, k, left, size; uint32_t checksum, *ptr; @@ -525,6 +570,23 @@ badsize: } } + g_raid_md_intel_print(meta); + + if (strncmp(meta->version, INTEL_VERSION_1300, 6) > 0) { + G_RAID_DEBUG(1, "Intel unsupported version: '%.6s'", + meta->version); + free(meta, M_MD_INTEL); + return (NULL); + } + + if (strncmp(meta->version, INTEL_VERSION_1300, 6) >= 0 && + (meta->attributes & ~INTEL_ATTR_SUPPORTED) != 0) { + G_RAID_DEBUG(1, "Intel unsupported attributes: 0x%08x", + meta->attributes & ~INTEL_ATTR_SUPPORTED); + free(meta, M_MD_INTEL); + return (NULL); + } + /* Validate disk indexes. */ for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); @@ -547,16 +609,39 @@ badsize: /* Validate migration types. */ for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); + /* Deny unknown migration types. */ if (mvol->migr_state && mvol->migr_type != INTEL_MT_INIT && mvol->migr_type != INTEL_MT_REBUILD && mvol->migr_type != INTEL_MT_VERIFY && + mvol->migr_type != INTEL_MT_GEN_MIGR && mvol->migr_type != INTEL_MT_REPAIR) { G_RAID_DEBUG(1, "Intel metadata has unsupported" " migration type %d", mvol->migr_type); free(meta, M_MD_INTEL); return (NULL); } + /* Deny general migrations except SINGLE->RAID1. */ + if (mvol->migr_state && + mvol->migr_type == INTEL_MT_GEN_MIGR) { + mmap = intel_get_map(mvol, 0); + mmap1 = intel_get_map(mvol, 1); + if (mmap1->total_disks != 1 || + mmap->type != INTEL_T_RAID1 || + mmap->total_disks != 2 || + mmap->offset != mmap1->offset || + mmap->disk_sectors != mmap1->disk_sectors || + mmap->total_domains != mmap->total_disks || + mmap->offset_hi != mmap1->offset_hi || + mmap->disk_sectors_hi != mmap1->disk_sectors_hi || + (mmap->disk_idx[0] != mmap1->disk_idx[0] && + mmap->disk_idx[0] != mmap1->disk_idx[1])) { + G_RAID_DEBUG(1, "Intel metadata has unsupported" + " variant of general migration"); + free(meta, M_MD_INTEL); + return (NULL); + } + } } return (meta); @@ -633,7 +718,7 @@ intel_meta_write_spare(struct g_consumer *cp, struct intel_raid_disk *d) memcpy(&meta->version[0], INTEL_VERSION_1000, sizeof(INTEL_VERSION_1000) - 1); meta->config_size = INTEL_MAX_MD_SIZE(1); - meta->config_id = arc4random(); + meta->config_id = meta->orig_config_id = arc4random(); meta->generation = 1; meta->total_disks = 1; meta->disk[0] = *d; @@ -699,9 +784,11 @@ static struct g_raid_volume * g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id) { struct g_raid_volume *mvol; + struct g_raid_md_intel_pervolume *pv; TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) { - if ((intptr_t)(mvol->v_md_data) == id) + pv = mvol->v_md_data; + if (pv->pv_volume_pos == id) break; } return (mvol); @@ -715,11 +802,12 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk) struct g_raid_disk *olddisk, *tmpdisk; struct g_raid_md_object *md; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd, *oldpd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; struct intel_raid_map *mmap0, *mmap1; - int disk_pos, resurrection = 0; + int disk_pos, resurrection = 0, migr_global, i; sc = disk->d_softc; md = sc->sc_md; @@ -733,7 +821,8 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk) if (disk_pos < 0) { G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk"); /* Failed stale disk is useless for us. */ - if (pd->pd_disk_meta.flags & INTEL_F_FAILED) { + if ((pd->pd_disk_meta.flags & INTEL_F_FAILED) && + !(pd->pd_disk_meta.flags & INTEL_F_DISABLED)) { g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE_FAILED); return (0); } @@ -824,7 +913,10 @@ nofit: } /* Welcome the new disk. */ - if (resurrection) + if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) && + !(pd->pd_disk_meta.flags & INTEL_F_SPARE)) + g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED); + else if (resurrection) g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE); else if (meta->disk[disk_pos].flags & INTEL_F_FAILED) g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED); @@ -833,15 +925,27 @@ nofit: else g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE); TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) { - mvol = intel_get_volume(meta, - (uintptr_t)(sd->sd_volume->v_md_data)); + pv = sd->sd_volume->v_md_data; + mvol = intel_get_volume(meta, pv->pv_volume_pos); mmap0 = intel_get_map(mvol, 0); if (mvol->migr_state) mmap1 = intel_get_map(mvol, 1); else mmap1 = mmap0; - if (resurrection) { + migr_global = 1; + for (i = 0; i < mmap0->total_disks; i++) { + if ((mmap0->disk_idx[i] & INTEL_DI_RBLD) == 0 && + (mmap1->disk_idx[i] & INTEL_DI_RBLD) != 0) + migr_global = 0; + } + + if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) && + !(pd->pd_disk_meta.flags & INTEL_F_SPARE)) { + /* Disabled disk, useless. */ + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_NONE); + } else if (resurrection) { /* Stale disk, almost same as new. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NEW); @@ -850,7 +954,8 @@ nofit: g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_FAILED); } else if (mvol->migr_state == 0) { - if (mmap0->status == INTEL_S_UNINITIALIZED) { + if (mmap0->status == INTEL_S_UNINITIALIZED && + (!pv->pv_cng || pv->pv_cng_master_disk != disk_pos)) { /* Freshly created uninitialized volume. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_UNINITIALIZED); @@ -858,7 +963,8 @@ nofit: /* Freshly inserted disk. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NEW); - } else if (mvol->dirty) { + } else if (mvol->dirty && (!pv->pv_cng || + pv->pv_cng_master_disk != disk_pos)) { /* Dirty volume (unclean shutdown). */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_STALE); @@ -885,7 +991,13 @@ nofit: sd->sd_volume->v_strip_size * mmap0->total_domains; } - } else if (mvol->dirty) { + } else if (mvol->migr_type == INTEL_MT_INIT && + migr_global) { + /* Freshly created uninitialized volume. */ + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_UNINITIALIZED); + } else if (mvol->dirty && (!pv->pv_cng || + pv->pv_cng_master_disk != disk_pos)) { /* Dirty volume (unclean shutdown). */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_STALE); @@ -900,7 +1012,8 @@ nofit: /* Freshly inserted disk. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NEW); - } else if (mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) { + } else if ((mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) || + migr_global) { /* Resyncing disk. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_RESYNC); @@ -921,6 +1034,16 @@ nofit: g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE); } + } else if (mvol->migr_type == INTEL_MT_GEN_MIGR) { + if ((mmap1->disk_idx[0] & INTEL_DI_IDX) != disk_pos) { + /* Freshly inserted disk. */ + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_NEW); + } else { + /* Up to date disk. */ + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_ACTIVE); + } } g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW, G_RAID_EVENT_SUBDISK); @@ -929,7 +1052,8 @@ nofit: /* Update status of our need for spare. */ if (mdi->mdio_started) { mdi->mdio_incomplete = - (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) < + (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) + + g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) < meta->total_disks); } @@ -961,7 +1085,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc) update = 0; do { /* Make sure we miss anything. */ - na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE); + na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) + + g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED); if (na == meta->total_disks) break; @@ -973,7 +1098,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc) TAILQ_FOREACH(disk, &sc->sc_disks, d_next) { if (disk->d_state == G_RAID_DISK_S_STALE) { update += g_raid_md_intel_start_disk(disk); - if (disk->d_state == G_RAID_DISK_S_ACTIVE) + if (disk->d_state == G_RAID_DISK_S_ACTIVE || + disk->d_state == G_RAID_DISK_S_DISABLED) break; } } @@ -997,8 +1123,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc) } /* Update status of our need for spare. */ - mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) < - meta->total_disks); + mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) + + g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) < meta->total_disks); /* Request retaste hoping to find spare. */ if (mdi->mdio_incomplete) { @@ -1014,6 +1140,7 @@ g_raid_md_intel_start(struct g_raid_softc *sc) { struct g_raid_md_object *md; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; @@ -1031,8 +1158,14 @@ g_raid_md_intel_start(struct g_raid_softc *sc) for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); mmap = intel_get_map(mvol, 0); - vol = g_raid_create_volume(sc, mvol->name, -1); - vol->v_md_data = (void *)(intptr_t)i; + vol = g_raid_create_volume(sc, mvol->name, mvol->tid - 1); + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = i; + pv->pv_cng = (mvol->state & INTEL_ST_CLONE_N_GO) != 0; + pv->pv_cng_man_sync = (mvol->state & INTEL_ST_CLONE_MAN_SYNC) != 0; + if (mvol->cng_master_disk < mmap->total_disks) + pv->pv_cng_master_disk = mvol->cng_master_disk; + vol->v_md_data = pv; vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE; if (mmap->type == INTEL_T_RAID0) vol->v_raid_level = G_RAID_VOLUME_RL_RAID0; @@ -1186,7 +1319,7 @@ g_raid_md_create_intel(struct g_raid_md_object *md, struct g_class *mp, char name[16]; mdi = (struct g_raid_md_intel_object *)md; - mdi->mdio_config_id = arc4random(); + mdi->mdio_config_id = mdi->mdio_orig_config_id = arc4random(); mdi->mdio_generation = 0; snprintf(name, sizeof(name), "Intel-%08x", mdi->mdio_config_id); sc = g_raid_create_node(mp, name, md); @@ -1294,8 +1427,6 @@ g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp, goto fail1; } - /* Metadata valid. Print it. */ - g_raid_md_intel_print(meta); G_RAID_DEBUG(1, "Intel disk position %d", disk_pos); spare = meta->disk[disk_pos].flags & INTEL_F_SPARE; @@ -1333,6 +1464,7 @@ search: } else { /* Not found matching node -- create one. */ result = G_RAID_MD_TASTE_NEW; mdi->mdio_config_id = meta->config_id; + mdi->mdio_orig_config_id = meta->orig_config_id; snprintf(name, sizeof(name), "Intel-%08x", meta->config_id); sc = g_raid_create_node(mp, name, md); md->mdo_softc = sc; @@ -1450,6 +1582,7 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md, struct g_raid_subdisk *sd; struct g_raid_disk *disk; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct g_consumer *cp; struct g_provider *pp; @@ -1621,7 +1754,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md, /* We have all we need, create things: volume, ... */ mdi->mdio_started = 1; vol = g_raid_create_volume(sc, volname, -1); - vol->v_md_data = (void *)(intptr_t)0; + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = 0; + vol->v_md_data = pv; vol->v_raid_level = level; vol->v_raid_level_qualifier = qual; vol->v_strip_size = strip; @@ -1814,7 +1949,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md, /* We have all we need, create things: volume, ... */ vol = g_raid_create_volume(sc, volname, -1); - vol->v_md_data = (void *)(intptr_t)i; + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = i; + vol->v_md_data = pv; vol->v_raid_level = level; vol->v_raid_level_qualifier = qual; vol->v_strip_size = strip; @@ -2105,6 +2242,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, struct g_raid_subdisk *sd; struct g_raid_disk *disk; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; @@ -2133,9 +2271,14 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, pd->pd_disk_meta.flags = INTEL_F_ONLINE | INTEL_F_ASSIGNED; } else if (disk->d_state == G_RAID_DISK_S_FAILED) { - pd->pd_disk_meta.flags = INTEL_F_FAILED | INTEL_F_ASSIGNED; + pd->pd_disk_meta.flags = INTEL_F_FAILED | + INTEL_F_ASSIGNED; + } else if (disk->d_state == G_RAID_DISK_S_DISABLED) { + pd->pd_disk_meta.flags = INTEL_F_FAILED | + INTEL_F_ASSIGNED | INTEL_F_DISABLED; } else { - pd->pd_disk_meta.flags = INTEL_F_ASSIGNED; + if (!(pd->pd_disk_meta.flags & INTEL_F_DISABLED)) + pd->pd_disk_meta.flags = INTEL_F_ASSIGNED; if (pd->pd_disk_meta.id != 0xffffffff) { pd->pd_disk_meta.id = 0xffffffff; len = strlen(pd->pd_disk_meta.serial); @@ -2151,6 +2294,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, memcpy(&meta->intel_id[0], INTEL_MAGIC, sizeof(INTEL_MAGIC) - 1); meta->config_size = INTEL_MAX_MD_SIZE(numdisks); meta->config_id = mdi->mdio_config_id; + meta->orig_config_id = mdi->mdio_orig_config_id; meta->generation = mdi->mdio_generation; meta->attributes = INTEL_ATTR_CHECKSUM; meta->total_disks = numdisks; @@ -2159,18 +2303,21 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, if (pd->pd_disk_pos < 0) continue; meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta; + if (pd->pd_disk_meta.sectors_hi != 0) + meta->attributes |= INTEL_ATTR_2TB_DISK; } /* Fill volumes and maps. */ vi = 0; version = INTEL_VERSION_1000; TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) { + pv = vol->v_md_data; if (vol->v_stopping) continue; mvol = intel_get_volume(meta, vi); /* New metadata may have different volumes order. */ - vol->v_md_data = (void *)(intptr_t)vi; + pv->pv_volume_pos = vi; for (sdi = 0; sdi < vol->v_disks_count; sdi++) { sd = &vol->v_subdisks[sdi]; @@ -2187,21 +2334,23 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, meta->attributes |= INTEL_ATTR_RAID1; else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5) meta->attributes |= INTEL_ATTR_RAID5; - else + else if ((vol->v_disks_count & 1) == 0) meta->attributes |= INTEL_ATTR_RAID10; - - if (meta->attributes & INTEL_ATTR_2TB) - cv = INTEL_VERSION_1300; -// else if (dev->status == DEV_CLONE_N_GO) -// cv = INTEL_VERSION_1206; + else + meta->attributes |= INTEL_ATTR_RAID1E; + if (pv->pv_cng) + meta->attributes |= INTEL_ATTR_RAIDCNG; + if (vol->v_strip_size > 131072) + meta->attributes |= INTEL_ATTR_EXT_STRIP; + + if (pv->pv_cng) + cv = INTEL_VERSION_1206; else if (vol->v_disks_count > 4) cv = INTEL_VERSION_1204; else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5) cv = INTEL_VERSION_1202; else if (vol->v_disks_count > 2) cv = INTEL_VERSION_1201; - else if (vi > 0) - cv = INTEL_VERSION_1200; else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1) cv = INTEL_VERSION_1100; else @@ -2211,6 +2360,22 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name)); mvol->total_sectors = vol->v_mediasize / sectorsize; + mvol->state = (INTEL_ST_READ_COALESCING | + INTEL_ST_WRITE_COALESCING); + mvol->tid = vol->v_global_id + 1; + if (pv->pv_cng) { + mvol->state |= INTEL_ST_CLONE_N_GO; + if (pv->pv_cng_man_sync) + mvol->state |= INTEL_ST_CLONE_MAN_SYNC; + mvol->cng_master_disk = pv->pv_cng_master_disk; + if (vol->v_subdisks[pv->pv_cng_master_disk].sd_state == + G_RAID_SUBDISK_S_NONE) + mvol->cng_state = INTEL_CNGST_MASTER_MISSING; + else if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL) + mvol->cng_state = INTEL_CNGST_NEEDS_UPDATE; + else + mvol->cng_state = INTEL_CNGST_UPDATED; + } /* Check for any recovery in progress. */ state = G_RAID_SUBDISK_S_ACTIVE; @@ -2305,7 +2470,8 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, mmap1->disk_idx[sdi] |= INTEL_DI_RBLD; } if ((sd->sd_state == G_RAID_SUBDISK_S_NONE || - sd->sd_state == G_RAID_SUBDISK_S_FAILED) && + sd->sd_state == G_RAID_SUBDISK_S_FAILED || + sd->sd_state == G_RAID_SUBDISK_S_REBUILD) && mmap0->failed_disk_num == 0xff) { mmap0->failed_disk_num = sdi; if (mvol->migr_state) @@ -2315,7 +2481,10 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol, vi++; } meta->total_volumes = vi; - if (strcmp(version, INTEL_VERSION_1300) != 0) + if (vi > 1 || meta->attributes & + (INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | INTEL_ATTR_2TB)) + version = INTEL_VERSION_1300; + if (strcmp(version, INTEL_VERSION_1300) < 0) meta->attributes &= INTEL_ATTR_CHECKSUM; memcpy(&meta->version[0], version, sizeof(INTEL_VERSION_1000) - 1); @@ -2403,6 +2572,18 @@ g_raid_md_free_disk_intel(struct g_raid_md_object *md, } static int +g_raid_md_free_volume_intel(struct g_raid_md_object *md, + struct g_raid_volume *vol) +{ + struct g_raid_md_intel_pervolume *pv; + + pv = (struct g_raid_md_intel_pervolume *)vol->v_md_data; + free(pv, M_MD_INTEL); + vol->v_md_data = NULL; + return (0); +} + +static int g_raid_md_free_intel(struct g_raid_md_object *md) { struct g_raid_md_intel_object *mdi; diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c index 711e9e1..927cb31 100644 --- a/sys/geom/raid3/g_raid3.c +++ b/sys/geom/raid3/g_raid3.c @@ -104,7 +104,8 @@ SYSCTL_UINT(_kern_geom_raid3_stat, OID_AUTO, parity_mismatch, CTLFLAG_RD, G_RAID3_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \ } while (0) -static eventhandler_tag g_raid3_pre_sync = NULL; +static eventhandler_tag g_raid3_post_sync = NULL; +static int g_raid3_shutdown = 0; static int g_raid3_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp); @@ -876,7 +877,7 @@ g_raid3_idle(struct g_raid3_softc *sc, int acw) return (0); if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) { timeout = g_raid3_idletime - (time_uptime - sc->sc_last_write); - if (timeout > 0) + if (!g_raid3_shutdown && timeout > 0) return (timeout); } sc->sc_idle = 1; @@ -3098,7 +3099,7 @@ g_raid3_access(struct g_provider *pp, int acr, int acw, int ace) error = ENXIO; goto end; } - if (dcw == 0 && !sc->sc_idle) + if (dcw == 0) g_raid3_idle(sc, dcw); if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROYING) != 0) { if (acr > 0 || acw > 0 || ace > 0) { @@ -3544,7 +3545,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, } static void -g_raid3_shutdown_pre_sync(void *arg, int howto) +g_raid3_shutdown_post_sync(void *arg, int howto) { struct g_class *mp; struct g_geom *gp, *gp2; @@ -3554,6 +3555,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto) mp = arg; DROP_GIANT(); g_topology_lock(); + g_raid3_shutdown = 1; LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { if ((sc = gp->softc) == NULL) continue; @@ -3562,6 +3564,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto) continue; g_topology_unlock(); sx_xlock(&sc->sc_lock); + g_raid3_idle(sc, -1); g_cancel_event(sc); error = g_raid3_destroy(sc, G_RAID3_DESTROY_DELAYED); if (error != 0) @@ -3576,9 +3579,9 @@ static void g_raid3_init(struct g_class *mp) { - g_raid3_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync, - g_raid3_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST); - if (g_raid3_pre_sync == NULL) + g_raid3_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync, + g_raid3_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST); + if (g_raid3_post_sync == NULL) G_RAID3_DEBUG(0, "Warning! Cannot register shutdown event."); } @@ -3586,8 +3589,8 @@ static void g_raid3_fini(struct g_class *mp) { - if (g_raid3_pre_sync != NULL) - EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_raid3_pre_sync); + if (g_raid3_post_sync != NULL) + EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_raid3_post_sync); } DECLARE_GEOM_CLASS(g_raid3_class, g_raid3); diff --git a/sys/geom/raid3/g_raid3_ctl.c b/sys/geom/raid3/g_raid3_ctl.c index 952ac2b..b3a42ff 100644 --- a/sys/geom/raid3/g_raid3_ctl.c +++ b/sys/geom/raid3/g_raid3_ctl.c @@ -404,7 +404,7 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) u_char *sector; off_t compsize; intmax_t *no; - int *hardcode, *nargs, error; + int *hardcode, *nargs, error, autono; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { @@ -425,11 +425,10 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No 'arg%u' argument.", 1); return; } - no = gctl_get_paraml(req, "number", sizeof(*no)); - if (no == NULL) { - gctl_error(req, "No '%s' argument.", "no"); - return; - } + if (gctl_get_param(req, "number", NULL) != NULL) + no = gctl_get_paraml(req, "number", sizeof(*no)); + else + no = NULL; if (strncmp(name, "/dev/", 5) == 0) name += 5; g_topology_lock(); @@ -465,16 +464,30 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No such device: %s.", name); goto end; } - if (*no >= sc->sc_ndisks) { - sx_xunlock(&sc->sc_lock); - gctl_error(req, "Invalid component number."); - goto end; - } - disk = &sc->sc_disks[*no]; - if (disk->d_state != G_RAID3_DISK_STATE_NODISK) { - sx_xunlock(&sc->sc_lock); - gctl_error(req, "Component %jd is already connected.", *no); - goto end; + if (no != NULL) { + if (*no < 0 || *no >= sc->sc_ndisks) { + sx_xunlock(&sc->sc_lock); + gctl_error(req, "Invalid component number."); + goto end; + } + disk = &sc->sc_disks[*no]; + if (disk->d_state != G_RAID3_DISK_STATE_NODISK) { + sx_xunlock(&sc->sc_lock); + gctl_error(req, "Component %jd is already connected.", + *no); + goto end; + } + } else { + disk = NULL; + for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++) + if (sc->sc_disks[autono].d_state == + G_RAID3_DISK_STATE_NODISK) + disk = &sc->sc_disks[autono]; + if (disk == NULL) { + sx_xunlock(&sc->sc_lock); + gctl_error(req, "No disconnected components."); + goto end; + } } if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) { sx_xunlock(&sc->sc_lock); diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 3a808ba..819379e 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -346,3 +346,11 @@ device snd_via8233 # VIA VT8233x Audio device mmc # MMC/SD bus device mmcsd # MMC/SD memory card device sdhci # Generic PCI SD Host Controller + +# VirtIO support +device virtio # Generic VirtIO bus (required) +device virtio_pci # VirtIO PCI device +device vtnet # VirtIO Ethernet device +device virtio_blk # VirtIO Block device +device virtio_scsi # VirtIO SCSI device +device virtio_balloon # VirtIO Memory Balloon device diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 1868595..95ccd4e 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -771,6 +771,15 @@ device glxiic # AMD Geode LX CS5536 System Management Bus # device glxsb # AMD Geode LX Security Block +# +# VirtIO support +device virtio # Generic VirtIO bus (required) +device virtio_pci # VirtIO PCI Interface +device vtnet # VirtIO Ethernet device +device virtio_blk # VirtIO Block device +device virtio_scsi # VirtIO SCSI device +device virtio_balloon # VirtIO Memory Balloon device + ##################################################################### # diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c index fe10a87..7671615 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -161,6 +161,7 @@ static const char *const vm_bnames[] = { "Bochs", /* Bochs */ "Xen", /* Xen */ "BHYVE", /* bhyve */ + "Seabios", /* KVM */ NULL }; @@ -169,6 +170,7 @@ static const char *const vm_pnames[] = { "Virtual Machine", /* Microsoft VirtualPC */ "VirtualBox", /* Sun xVM VirtualBox */ "Parallels Virtual Platform", /* Parallels VM */ + "KVM", /* KVM */ NULL }; @@ -324,8 +326,11 @@ init_param2(long physpages) /* * XXX: Does the callout wheel have to be so big? + * + * Clip callout to result of previous function of maxusers maximum + * 384. This is still huge, but acceptable. */ - ncallout = 16 + maxproc + maxfiles; + ncallout = imin(16 + maxproc + maxfiles, 18508); TUNABLE_INT_FETCH("kern.ncallout", &ncallout); /* diff --git a/sys/kern/vfs_hash.c b/sys/kern/vfs_hash.c index aad22e0..0271e49 100644 --- a/sys/kern/vfs_hash.c +++ b/sys/kern/vfs_hash.c @@ -54,11 +54,18 @@ vfs_hashinit(void *dummy __unused) /* Must be SI_ORDER_SECOND so desiredvnodes is available */ SYSINIT(vfs_hash, SI_SUB_VFS, SI_ORDER_SECOND, vfs_hashinit, NULL); +u_int +vfs_hash_index(struct vnode *vp) +{ + + return (vp->v_hash + vp->v_mount->mnt_hashseed); +} + static struct vfs_hash_head * -vfs_hash_index(const struct mount *mp, u_int hash) +vfs_hash_bucket(const struct mount *mp, u_int hash) { - return(&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]); + return (&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]); } int @@ -69,7 +76,7 @@ vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, s while (1) { mtx_lock(&vfs_hash_mtx); - LIST_FOREACH(vp, vfs_hash_index(mp, hash), v_hashlist) { + LIST_FOREACH(vp, vfs_hash_bucket(mp, hash), v_hashlist) { if (vp->v_hash != hash) continue; if (vp->v_mount != mp) @@ -113,7 +120,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru while (1) { mtx_lock(&vfs_hash_mtx); LIST_FOREACH(vp2, - vfs_hash_index(vp->v_mount, hash), v_hashlist) { + vfs_hash_bucket(vp->v_mount, hash), v_hashlist) { if (vp2->v_hash != hash) continue; if (vp2->v_mount != vp->v_mount) @@ -138,7 +145,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru } vp->v_hash = hash; - LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist); + LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist); mtx_unlock(&vfs_hash_mtx); return (0); } @@ -149,7 +156,7 @@ vfs_hash_rehash(struct vnode *vp, u_int hash) mtx_lock(&vfs_hash_mtx); LIST_REMOVE(vp, v_hashlist); - LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist); + LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist); vp->v_hash = hash; mtx_unlock(&vfs_hash_mtx); } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 7c243b6..1c26368 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -279,6 +279,8 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW, #define VSHOULDFREE(vp) (!((vp)->v_iflag & VI_FREE) && !(vp)->v_holdcnt) #define VSHOULDBUSY(vp) (((vp)->v_iflag & VI_FREE) && (vp)->v_holdcnt) +/* Shift count for (uintptr_t)vp to initialize vp->v_hash. */ +static int vnsz2log; /* * Initialize the vnode management data structures. @@ -293,6 +295,7 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW, static void vntblinit(void *dummy __unused) { + u_int i; int physvnodes, virtvnodes; /* @@ -332,6 +335,9 @@ vntblinit(void *dummy __unused) syncer_maxdelay = syncer_mask + 1; mtx_init(&sync_mtx, "Syncer mtx", NULL, MTX_DEF); cv_init(&sync_wakeup, "syncer"); + for (i = 1; i <= sizeof(struct vnode); i <<= 1) + vnsz2log++; + vnsz2log--; } SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vntblinit, NULL); @@ -1067,6 +1073,14 @@ alloc: } rangelock_init(&vp->v_rl); + /* + * For the filesystems which do not use vfs_hash_insert(), + * still initialize v_hash to have vfs_hash_index() useful. + * E.g., nullfs uses vfs_hash_index() on the lower vnode for + * its own hashing. + */ + vp->v_hash = (uintptr_t)vp >> vnsz2log; + *vpp = vp; return (0); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index bbe837a..203989d 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1642,7 +1642,7 @@ vfs_write_suspend(mp) else MNT_IUNLOCK(mp); if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0) - vfs_write_resume(mp); + vfs_write_resume(mp, 0); return (error); } @@ -1650,7 +1650,7 @@ vfs_write_suspend(mp) * Request a filesystem to resume write operations. */ void -vfs_write_resume_flags(struct mount *mp, int flags) +vfs_write_resume(struct mount *mp, int flags) { MNT_ILOCK(mp); @@ -1677,13 +1677,6 @@ vfs_write_resume_flags(struct mount *mp, int flags) } } -void -vfs_write_resume(struct mount *mp) -{ - - vfs_write_resume_flags(mp, 0); -} - /* * Implement kqueues for files by translating it to vnode operation. */ diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c index f2ef5a7..98fcb85a 100644 --- a/sys/mips/beri/beri_machdep.c +++ b/sys/mips/beri/beri_machdep.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <sys/cpu.h> #include <sys/cons.h> #include <sys/exec.h> +#include <sys/linker.h> #include <sys/ucontext.h> #include <sys/proc.h> #include <sys/kdb.h> @@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpuregs.h> #include <machine/hwfunc.h> #include <machine/md_var.h> +#include <machine/metadata.h> #include <machine/pmap.h> #include <machine/trap.h> @@ -87,17 +89,6 @@ mips_init(void) { int i; -#ifdef FDT -#ifndef FDT_DTB_STATIC -#error "mips_init with FDT requires FDT_DTB_STATIC" -#endif - - if (OF_install(OFW_FDT, 0) == FALSE) - while (1); - if (OF_init(&fdt_static_dtb) != 0) - while (1); -#endif - for (i = 0; i < 10; i++) { phys_avail[i] = 0; } @@ -146,6 +137,10 @@ platform_start(__register_t a0, __register_t a1, __register_t a2, char **argv = (char **)a1; char **envp = (char **)a2; unsigned int memsize = a3; +#ifdef FDT + vm_offset_t dtbp; + void *kmdp; +#endif int i; /* clear the BSS and SBSS segments */ @@ -156,6 +151,33 @@ platform_start(__register_t a0, __register_t a1, __register_t a2, mips_pcpu0_init(); +#ifdef FDT + /* + * Find the dtb passed in by the boot loader (currently fictional). + */ + kmdp = preload_search_by_type("elf kernel"); + if (kmdp != NULL) + dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); + else + dtbp = (vm_offset_t)NULL; + +#if defined(FDT_DTB_STATIC) + /* + * In case the device tree blob was not retrieved (from metadata) try + * to use the statically embedded one. + */ + if (dtbp == (vm_offset_t)NULL) + dtbp = (vm_offset_t)&fdt_static_dtb; +#else +#error "Non-static FDT not yet supported on BERI" +#endif + + if (OF_install(OFW_FDT, 0) == FALSE) + while (1); + if (OF_init(&fdt_static_dtb) != 0) + while (1); +#endif + /* * XXXRW: We have no way to compare wallclock time to cycle rate on * BERI, so for now assume we run at the MALTA default (100MHz). diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri index 02a27f8..6794793 100644 --- a/sys/mips/beri/files.beri +++ b/sys/mips/beri/files.beri @@ -1,10 +1,13 @@ # $FreeBSD$ dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart +dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart dev/terasic/de4led/terasic_de4led.c optional terasic_de4led +dev/terasic/de4led/terasic_de4led_fdt.c optional terasic_de4led fdt dev/terasic/de4led/terasic_de4led_nexus.c optional terasic_de4led dev/terasic/mtl/terasic_mtl.c optional terasic_mtl +dev/terasic/mtl/terasic_mtl_fdt.c optional terasic_mtl fdt dev/terasic/mtl/terasic_mtl_nexus.c optional terasic_mtl dev/terasic/mtl/terasic_mtl_pixel.c optional terasic_mtl dev/terasic/mtl/terasic_mtl_reg.c optional terasic_mtl diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h index b904a5d..6825b23 100644 --- a/sys/mips/include/bus.h +++ b/sys/mips/include/bus.h @@ -728,6 +728,8 @@ void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \ */ DECLARE_BUS_SPACE_PROTOTYPES(generic); extern bus_space_tag_t mips_bus_space_generic; +extern bus_space_tag_t mips_bus_space_fdt; + /* Special bus space for RMI processors */ #if defined(CPU_RMI) || defined (CPU_NLM) extern bus_space_tag_t rmi_bus_space; diff --git a/sys/mips/include/fdt.h b/sys/mips/include/fdt.h index 3b20a72..2f1fda5 100644 --- a/sys/mips/include/fdt.h +++ b/sys/mips/include/fdt.h @@ -51,7 +51,7 @@ #if defined(CPU_RMI) || defined(CPU_NLM) #define fdtbus_bs_tag rmi_uart_bus_space #else -#define fdtbus_bs_tag NULL +#define fdtbus_bs_tag mips_bus_space_fdt #endif #endif /* _MACHINE_FDT_H_ */ diff --git a/sys/mips/include/metadata.h b/sys/mips/include/metadata.h index 84e6f87..779c2f6 100644 --- a/sys/mips/include/metadata.h +++ b/sys/mips/include/metadata.h @@ -30,5 +30,6 @@ #define _MACHINE_METADATA_H_ #define MODINFOMD_SMAP 0x1001 +#define MODINFOMD_DTBP 0x1002 #endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/mips/include/vmparam.h b/sys/mips/include/vmparam.h index aa0a5d7..ef97336 100644 --- a/sys/mips/include/vmparam.h +++ b/sys/mips/include/vmparam.h @@ -130,10 +130,11 @@ #endif /* - * Ceiling on amount of kmem_map kva space. + * Ceiling on the amount of kmem_map KVA space: 40% of the entire KVA space. */ #ifndef VM_KMEM_SIZE_MAX -#define VM_KMEM_SIZE_MAX (200 * 1024 * 1024) +#define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \ + VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5) #endif /* initial pagein size of beginning of executable file */ diff --git a/sys/mips/mips/bus_space_fdt.c b/sys/mips/mips/bus_space_fdt.c new file mode 100644 index 0000000..38efea1 --- /dev/null +++ b/sys/mips/mips/bus_space_fdt.c @@ -0,0 +1,212 @@ +/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ +/*- + * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $ + * + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter + * $FreeBSD$ + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/ktr.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> + +#include <machine/bus.h> +#include <machine/cache.h> + +static int fdt_bs_map(void *, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); + +static struct bus_space fdt_space = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + fdt_bs_map, + generic_bs_unmap, + generic_bs_subregion, + + /* allocation/deallocation */ + generic_bs_alloc, + generic_bs_free, + + /* barrier */ + generic_bs_barrier, + + /* read (single) */ + generic_bs_r_1, + generic_bs_r_2, + generic_bs_r_4, + generic_bs_r_8, + + /* read multiple */ + generic_bs_rm_1, + generic_bs_rm_2, + generic_bs_rm_4, + generic_bs_rm_8, + + /* read region */ + generic_bs_rr_1, + generic_bs_rr_2, + generic_bs_rr_4, + generic_bs_rr_8, + + /* write (single) */ + generic_bs_w_1, + generic_bs_w_2, + generic_bs_w_4, + generic_bs_w_8, + + /* write multiple */ + generic_bs_wm_1, + generic_bs_wm_2, + generic_bs_wm_4, + generic_bs_wm_8, + + /* write region */ + generic_bs_wr_1, + generic_bs_wr_2, + generic_bs_wr_4, + generic_bs_wr_8, + + /* set multiple */ + generic_bs_sm_1, + generic_bs_sm_2, + generic_bs_sm_4, + generic_bs_sm_8, + + /* set region */ + generic_bs_sr_1, + generic_bs_sr_2, + generic_bs_sr_4, + generic_bs_sr_8, + + /* copy */ + generic_bs_c_1, + generic_bs_c_2, + generic_bs_c_4, + generic_bs_c_8, + + /* read (single) stream */ + generic_bs_r_1, + generic_bs_r_2, + generic_bs_r_4, + generic_bs_r_8, + + /* read multiple stream */ + generic_bs_rm_1, + generic_bs_rm_2, + generic_bs_rm_4, + generic_bs_rm_8, + + /* read region stream */ + generic_bs_rr_1, + generic_bs_rr_2, + generic_bs_rr_4, + generic_bs_rr_8, + + /* write (single) stream */ + generic_bs_w_1, + generic_bs_w_2, + generic_bs_w_4, + generic_bs_w_8, + + /* write multiple stream */ + generic_bs_wm_1, + generic_bs_wm_2, + generic_bs_wm_4, + generic_bs_wm_8, + + /* write region stream */ + generic_bs_wr_1, + generic_bs_wr_2, + generic_bs_wr_4, + generic_bs_wr_8, +}; + +/* generic bus_space tag */ +bus_space_tag_t mips_bus_space_fdt = &fdt_space; + +static int +fdt_bs_map(void *t __unused, bus_addr_t addr, bus_size_t size __unused, + int flags __unused, bus_space_handle_t *bshp) +{ + + *bshp = MIPS_PHYS_TO_DIRECT_UNCACHED(addr); + return (0); +} diff --git a/sys/modules/cxgbe/tom/Makefile b/sys/modules/cxgbe/tom/Makefile index 72721be..d02afd4 100644 --- a/sys/modules/cxgbe/tom/Makefile +++ b/sys/modules/cxgbe/tom/Makefile @@ -10,15 +10,20 @@ CXGBE = ${.CURDIR}/../../../dev/cxgbe KMOD = t4_tom SRCS = t4_tom.c t4_connect.c t4_listen.c t4_cpl_io.c t4_tom_l2t.c t4_ddp.c SRCS+= device_if.h bus_if.h pci_if.h -SRCS+= opt_inet.h +SRCS+= opt_inet.h opt_inet6.h CFLAGS+= -I${CXGBE} .if !defined(KERNBUILDDIR) .if ${MK_INET_SUPPORT} != "no" opt_inet.h: - echo "#define INET 1" > ${.TARGET} - echo "#define TCP_OFFLOAD 1" >> ${.TARGET} + @echo "#define INET 1" > ${.TARGET} + @echo "#define TCP_OFFLOAD 1" >> ${.TARGET} +.endif + +.if ${MK_INET6_SUPPORT} != "no" +opt_inet6.h: + @echo "#define INET6 1" > ${.TARGET} .endif .endif diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index 558e1f3..31bc578 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -416,6 +416,8 @@ pwrsave_flushq(struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_psq_head *qhead; struct ifnet *parent, *ifp; + struct mbuf *parent_q = NULL, *ifp_q = NULL; + struct mbuf *m; IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, "flush ps queue, %u packets queued", psq->psq_len); @@ -427,8 +429,7 @@ pwrsave_flushq(struct ieee80211_node *ni) parent = vap->iv_ic->ic_ifp; /* XXX need different driver interface */ /* XXX bypasses q max and OACTIVE */ - IF_PREPEND_LIST(&parent->if_snd, qhead->head, qhead->tail, - qhead->len); + parent_q = qhead->head; qhead->head = qhead->tail = NULL; qhead->len = 0; } else @@ -439,8 +440,7 @@ pwrsave_flushq(struct ieee80211_node *ni) ifp = vap->iv_ifp; /* XXX need different driver interface */ /* XXX bypasses q max and OACTIVE */ - IF_PREPEND_LIST(&ifp->if_snd, qhead->head, qhead->tail, - qhead->len); + ifp_q = qhead->head; qhead->head = qhead->tail = NULL; qhead->len = 0; } else @@ -450,10 +450,34 @@ pwrsave_flushq(struct ieee80211_node *ni) /* NB: do this outside the psq lock */ /* XXX packets might get reordered if parent is OACTIVE */ - if (parent != NULL) - if_start(parent); - if (ifp != NULL) - if_start(ifp); + /* parent frames, should be encapsulated */ + if (parent != NULL) { + while (parent_q != NULL) { + m = parent_q; + parent_q = m->m_nextpkt; + /* must be encapsulated */ + KASSERT((m->m_flags & M_ENCAP), + ("%s: parentq with non-M_ENCAP frame!\n", + __func__)); + /* + * For encaped frames, we need to free the node + * reference upon failure. + */ + if (parent->if_transmit(parent, m) != 0) + ieee80211_free_node(ni); + } + } + + /* VAP frames, aren't encapsulated */ + if (ifp != NULL) { + while (ifp_q != NULL) { + m = ifp_q; + ifp_q = m->m_nextpkt; + KASSERT((!(m->m_flags & M_ENCAP)), + ("%s: vapq with M_ENCAP frame!\n", __func__)); + (void) ifp->if_transmit(ifp, m); + } + } } /* diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index b943eb6..48444c1 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -119,6 +119,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0, /* max idle probes */ int tcp_maxpersistidle; +static int tcp_rexmit_drop_options = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW, + &tcp_rexmit_drop_options, 0, + "Drop TCP options from 3rd and later retransmitted SYN"); + static int per_cpu_timers = 0; SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW, &per_cpu_timers , 0, "run tcp timers on all cpus"); @@ -595,7 +600,8 @@ tcp_timer_rexmt(void * xtp) * header compression code which trashes TCP segments containing * unknown-to-them TCP options. */ - if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3)) + if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) && + (tp->t_rxtshift == 3)) tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT); /* * If we backed off this far, our srtt estimate is probably bogus. diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index fb7e6f0..8d04c46 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -383,10 +383,12 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, */ /* Rule 5: Prefer outgoing interface */ - if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp) - NEXT(5); - if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp) - REPLACE(5); + if (!(ND_IFINFO(ifp)->flags & ND6_IFF_NO_PREFER_IFACE)) { + if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp) + NEXT(5); + if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp) + REPLACE(5); + } /* * Rule 6: Prefer matching label diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 1655a6c..94202e1 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -86,6 +86,7 @@ struct nd_ifinfo { #define ND6_IFF_DONT_SET_IFROUTE 0x10 #define ND6_IFF_AUTO_LINKLOCAL 0x20 #define ND6_IFF_NO_RADR 0x40 +#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */ #define ND6_CREATE LLE_CREATE #define ND6_EXCLUSIVE LLE_EXCLUSIVE diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c index 74d034e..b6479a1 100644 --- a/sys/netinet6/scope6.c +++ b/sys/netinet6/scope6.c @@ -336,7 +336,6 @@ scope6_addr2default(struct in6_addr *addr) int sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok) { - struct ifnet *ifp; u_int32_t zoneid; if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok) @@ -351,15 +350,11 @@ sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok) * zone IDs assuming a one-to-one mapping between interfaces * and links. */ - if (V_if_index < zoneid) - return (ENXIO); - ifp = ifnet_byindex(zoneid); - if (ifp == NULL) /* XXX: this can happen for some OS */ + if (V_if_index < zoneid || ifnet_byindex(zoneid) == NULL) return (ENXIO); /* XXX assignment to 16bit from 32bit variable */ sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff); - sin6->sin6_scope_id = 0; } @@ -425,59 +420,30 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id) * interface. */ if (IN6_IS_ADDR_LOOPBACK(in6)) { - if (!(ifp->if_flags & IFF_LOOPBACK)) { + if (!(ifp->if_flags & IFF_LOOPBACK)) return (EINVAL); - } else { - if (ret_id != NULL) - *ret_id = 0; /* there's no ambiguity */ - return (0); + } else { + scope = in6_addrscope(in6); + if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL || + scope == IPV6_ADDR_SCOPE_LINKLOCAL) { + /* + * Currently we use interface indeces as the + * zone IDs for interface-local and link-local + * scopes. + */ + zoneid = ifp->if_index; + in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */ + } else if (scope != IPV6_ADDR_SCOPE_GLOBAL) { + IF_AFDATA_RLOCK(ifp); + sid = SID(ifp); + zoneid = sid->s6id_list[scope]; + IF_AFDATA_RUNLOCK(ifp); } } - if (ret_id == NULL && !IN6_IS_SCOPE_EMBED(in6)) - return (0); - - IF_AFDATA_RLOCK(ifp); - - sid = SID(ifp); - -#ifdef DIAGNOSTIC - if (sid == NULL) { /* should not happen */ - panic("in6_setscope: scope array is NULL"); - /* NOTREACHED */ - } -#endif - - scope = in6_addrscope(in6); - switch (scope) { - case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */ - zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL]; - break; - - case IPV6_ADDR_SCOPE_LINKLOCAL: - zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]; - break; - - case IPV6_ADDR_SCOPE_SITELOCAL: - zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]; - break; - - case IPV6_ADDR_SCOPE_ORGLOCAL: - zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]; - break; - - default: - zoneid = 0; /* XXX: treat as global. */ - break; - } - IF_AFDATA_RUNLOCK(ifp); - if (ret_id != NULL) *ret_id = zoneid; - if (IN6_IS_SCOPE_EMBED(in6)) - in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */ - return (0); } diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c index 0e4a83e..731e2ea 100644 --- a/sys/nfsclient/nfs_krpc.c +++ b/sys/nfsclient/nfs_krpc.c @@ -549,14 +549,21 @@ tryagain: */ if (stat == RPC_SUCCESS) error = 0; - else if (stat == RPC_TIMEDOUT) + else if (stat == RPC_TIMEDOUT) { + nfsstats.rpctimeouts++; error = ETIMEDOUT; - else if (stat == RPC_VERSMISMATCH) + } else if (stat == RPC_VERSMISMATCH) { + nfsstats.rpcinvalid++; error = EOPNOTSUPP; - else if (stat == RPC_PROGVERSMISMATCH) + } else if (stat == RPC_PROGVERSMISMATCH) { + nfsstats.rpcinvalid++; error = EPROTONOSUPPORT; - else + } else if (stat == RPC_INTR) { + error = EINTR; + } else { + nfsstats.rpcinvalid++; error = EACCES; + } if (error) goto nfsmout; @@ -572,6 +579,7 @@ tryagain: if (error == ENOMEM) { m_freem(mrep); AUTH_DESTROY(auth); + nfsstats.rpcinvalid++; return (error); } diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index fd83794..3723223 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -1110,7 +1110,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb, *tl = nfs_false; } if (va->va_atime.tv_sec != VNOVAL) { - if (va->va_atime.tv_sec != time_second) { + if ((va->va_vaflags & VA_UTIMES_NULL) == 0) { tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); txdr_nfsv3time(&va->va_atime, tl); @@ -1123,7 +1123,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb, *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); } if (va->va_mtime.tv_sec != VNOVAL) { - if (va->va_mtime.tv_sec != time_second) { + if ((va->va_vaflags & VA_UTIMES_NULL) == 0) { tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); txdr_nfsv3time(&va->va_mtime, tl); diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c index 5efb983..e424294 100644 --- a/sys/pc98/cbus/pckbd.c +++ b/sys/pc98/cbus/pckbd.c @@ -77,9 +77,9 @@ DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0); static bus_addr_t pckbd_iat[] = {0, 2}; -static int pckbd_probe_unit(int unit, int port, int irq, +static int pckbd_probe_unit(device_t dev, int port, int irq, int flags); -static int pckbd_attach_unit(int unit, keyboard_t **kbd, +static int pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags); static timeout_t pckbd_timeout; @@ -103,7 +103,7 @@ pckbdprobe(device_t dev) return ENXIO; isa_load_resourcev(res, pckbd_iat, 2); - error = pckbd_probe_unit(device_get_unit(dev), + error = pckbd_probe_unit(dev, isa_get_port(dev), (1 << isa_get_irq(dev)), device_get_flags(dev)); @@ -128,7 +128,7 @@ pckbdattach(device_t dev) return ENXIO; isa_load_resourcev(res, pckbd_iat, 2); - error = pckbd_attach_unit(device_get_unit(dev), &kbd, + error = pckbd_attach_unit(dev, &kbd, isa_get_port(dev), (1 << isa_get_irq(dev)), device_get_flags(dev)); @@ -164,7 +164,7 @@ pckbd_isa_intr(void *arg) } static int -pckbd_probe_unit(int unit, int port, int irq, int flags) +pckbd_probe_unit(device_t dev, int port, int irq, int flags) { keyboard_switch_t *sw; int args[2]; @@ -176,24 +176,26 @@ pckbd_probe_unit(int unit, int port, int irq, int flags) args[0] = port; args[1] = irq; - error = (*sw->probe)(unit, args, flags); + error = (*sw->probe)(device_get_unit(dev), args, flags); if (error) return error; return 0; } static int -pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags) +pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags) { keyboard_switch_t *sw; int args[2]; int error; + int unit; sw = kbd_get_switch(DRIVER_NAME); if (sw == NULL) return ENXIO; /* reset, initialize and enable the device */ + unit = device_get_unit(dev); args[0] = port; args[1] = irq; *kbd = NULL; diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 98e3352..4f91d1f 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -148,6 +148,8 @@ static const struct rl_type rl_devs[] = { "Delta Electronics 8139 10/100BaseTX" }, { ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139, "Addtron Technology 8139 10/100BaseTX" }, + { DLINK_VENDORID, DLINK_DEVICEID_520TX_REVC1, RL_8139, + "D-Link DFE-520TX (rev. C1) 10/100BaseTX" }, { DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139, "D-Link DFE-530TX+ 10/100BaseTX" }, { DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139, diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h index 7822ce3..be89c4f5 100644 --- a/sys/pci/if_rlreg.h +++ b/sys/pci/if_rlreg.h @@ -1048,6 +1048,11 @@ struct rl_softc { #define DLINK_DEVICEID_530TXPLUS 0x1300 /* + * D-Link DFE-520TX rev. C1 device ID + */ +#define DLINK_DEVICEID_520TX_REVC1 0x4200 + +/* * D-Link DFE-5280T device ID */ #define DLINK_DEVICEID_528T 0x4300 diff --git a/sys/sys/bufobj.h b/sys/sys/bufobj.h index 3934553..79bef84 100644 --- a/sys/sys/bufobj.h +++ b/sys/sys/bufobj.h @@ -89,12 +89,7 @@ struct buf_ops { struct bufobj { struct mtx bo_mtx; /* Mutex which protects "i" things */ - struct bufv bo_clean; /* i Clean buffers */ - struct bufv bo_dirty; /* i Dirty buffers */ - long bo_numoutput; /* i Writes in progress */ - u_int bo_flag; /* i Flags */ struct buf_ops *bo_ops; /* - Buffer operations */ - int bo_bsize; /* - Block size for i/o */ struct vm_object *bo_object; /* v Place to store VM object */ LIST_ENTRY(bufobj) bo_synclist; /* S dirty vnode list */ void *bo_private; /* private pointer */ @@ -103,6 +98,11 @@ struct bufobj { * XXX: only to keep the syncer working * XXX: for now. */ + struct bufv bo_clean; /* i Clean buffers */ + struct bufv bo_dirty; /* i Dirty buffers */ + long bo_numoutput; /* i Writes in progress */ + u_int bo_flag; /* i Flags */ + int bo_bsize; /* - Block size for i/o */ }; /* diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 6444b07..22742c9 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -396,7 +396,7 @@ extern uma_zone_t zone_ext_refcnt; static __inline struct mbuf *m_getcl(int how, short type, int flags); static __inline struct mbuf *m_get(int how, short type); static __inline struct mbuf *m_get2(int how, short type, int flags, - int size); + u_int size); static __inline struct mbuf *m_gethdr(int how, short type); static __inline struct mbuf *m_getjcl(int how, short type, int flags, int size); @@ -548,7 +548,7 @@ m_getcl(int how, short type, int flags) * XXX: This is rather large, should be real function maybe. */ static __inline struct mbuf * -m_get2(int how, short type, int flags, int size) +m_get2(int how, short type, int flags, u_int size) { struct mb_args args; struct mbuf *m, *n; diff --git a/sys/sys/param.h b/sys/sys/param.h index d7a74f2..e1d647b 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -48,9 +48,9 @@ * __FreeBSD_version numbers are documented in the Porter's Handbook. * If you bump the version for any reason, you should update the documentation * there. - * Currently this lives here: + * Currently this lives here in the doc/ repository: * - * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml + * head/en_US.ISO8859-1/books/porters-handbook/book.xml * * scheme is: <major><two digit minor>Rxx * 'R' is in the range 0 to 4 if this is a release branch or @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000025 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000026 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index f487f37..b54dc04 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -99,7 +99,6 @@ struct vnode { * Fields which define the identity of the vnode. These fields are * owned by the filesystem (XXX: and vgone() ?) */ - enum vtype v_type; /* u vnode type */ const char *v_tag; /* u type of underlying data */ struct vop_vector *v_op; /* u vnode operations vector */ void *v_data; /* u private data for fs */ @@ -122,10 +121,10 @@ struct vnode { } v_un; /* - * vfs_hash: (mount + inode) -> vnode hash. + * vfs_hash: (mount + inode) -> vnode hash. The hash value + * itself is grouped with other int fields, to avoid padding. */ LIST_ENTRY(vnode) v_hashlist; - u_int v_hash; /* * VFS_namecache stuff @@ -135,24 +134,11 @@ struct vnode { struct namecache *v_cache_dd; /* c Cache entry for .. vnode */ /* - * clustering stuff - */ - daddr_t v_cstart; /* v start block of cluster */ - daddr_t v_lasta; /* v last allocation */ - daddr_t v_lastw; /* v last write */ - int v_clen; /* v length of cur. cluster */ - - /* * Locking */ struct lock v_lock; /* u (if fs don't have one) */ struct mtx v_interlock; /* lock for "i" things */ struct lock *v_vnlock; /* u pointer to vnode lock */ - int v_holdcnt; /* i prevents recycling. */ - int v_usecount; /* i ref count of users */ - u_int v_iflag; /* i vnode flags (see below) */ - u_int v_vflag; /* v vnode flags */ - int v_writecount; /* v ref count of writers */ /* * The machinery of being a vnode @@ -167,6 +153,22 @@ struct vnode { struct label *v_label; /* MAC label for vnode */ struct lockf *v_lockf; /* Byte-level advisory lock list */ struct rangelock v_rl; /* Byte-range lock */ + + /* + * clustering stuff + */ + daddr_t v_cstart; /* v start block of cluster */ + daddr_t v_lasta; /* v last allocation */ + daddr_t v_lastw; /* v last write */ + int v_clen; /* v length of cur. cluster */ + + int v_holdcnt; /* i prevents recycling. */ + int v_usecount; /* i ref count of users */ + u_int v_iflag; /* i vnode flags (see below) */ + u_int v_vflag; /* v vnode flags */ + int v_writecount; /* v ref count of writers */ + u_int v_hash; + enum vtype v_type; /* u vnode type */ }; #endif /* defined(_KERNEL) || defined(_KVM_VNODE) */ @@ -703,8 +705,7 @@ int vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio); int vfs_cache_lookup(struct vop_lookup_args *ap); void vfs_timestamp(struct timespec *); -void vfs_write_resume(struct mount *mp); -void vfs_write_resume_flags(struct mount *mp, int flags); +void vfs_write_resume(struct mount *mp, int flags); int vfs_write_suspend(struct mount *mp); int vop_stdbmap(struct vop_bmap_args *); int vop_stdfsync(struct vop_fsync_args *); @@ -813,6 +814,7 @@ int fifo_printinfo(struct vnode *); typedef int vfs_hash_cmp_t(struct vnode *vp, void *arg); int vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg); +u_int vfs_hash_index(struct vnode *vp); int vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg); void vfs_hash_rehash(struct vnode *vp, u_int hash); void vfs_hash_remove(struct vnode *vp); diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 5f67ae5..0c653c2 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -687,7 +687,7 @@ out1: /* * Resume operation on filesystem. */ - vfs_write_resume_flags(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR); + vfs_write_resume(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR); if (collectsnapstats && starttime.tv_sec > 0) { nanotime(&endtime); timespecsub(&endtime, &starttime); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 4ee16ab..16fe134 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2802,7 +2802,7 @@ journal_unsuspend(struct ufsmount *ump) jblocks->jb_suspended = 0; FREE_LOCK(&lk); mp->mnt_susp_owner = curthread; - vfs_write_resume(mp); + vfs_write_resume(mp, 0); ACQUIRE_LOCK(&lk); return (1); } diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c index 9d8e2c1..3198c1a 100644 --- a/sys/ufs/ffs/ffs_suspend.c +++ b/sys/ufs/ffs/ffs_suspend.c @@ -252,7 +252,7 @@ ffs_susp_dtor(void *data) */ mp->mnt_susp_owner = curthread; - vfs_write_resume(mp); + vfs_write_resume(mp, 0); vfs_unbusy(mp); ump->um_writesuspended = 0; diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 83ae202..0204613 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -292,7 +292,7 @@ ffs_mount(struct mount *mp) error = ffs_flushfiles(mp, flags, td); } if (error) { - vfs_write_resume(mp); + vfs_write_resume(mp, 0); return (error); } if (fs->fs_pendingblocks != 0 || @@ -309,7 +309,7 @@ ffs_mount(struct mount *mp) if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) { fs->fs_ronly = 0; fs->fs_clean = 0; - vfs_write_resume(mp); + vfs_write_resume(mp, 0); return (error); } if (MOUNTEDSOFTDEP(mp)) @@ -330,7 +330,7 @@ ffs_mount(struct mount *mp) * Allow the writers to note that filesystem * is ro now. */ - vfs_write_resume(mp); + vfs_write_resume(mp, 0); } if ((mp->mnt_flag & MNT_RELOAD) && (error = ffs_reload(mp, td, 0)) != 0) @@ -1294,10 +1294,8 @@ ffs_unmount(mp, mntflags) goto fail; } } - if (susp) { - vfs_write_resume(mp); - vn_start_write(NULL, &mp, V_WAIT); - } + if (susp) + vfs_write_resume(mp, VR_START_WRITE); DROP_GIANT(); g_topology_lock(); if (ump->um_fsckpid > 0) { @@ -1329,10 +1327,8 @@ ffs_unmount(mp, mntflags) return (error); fail: - if (susp) { - vfs_write_resume(mp); - vn_start_write(NULL, &mp, V_WAIT); - } + if (susp) + vfs_write_resume(mp, VR_START_WRITE); #ifdef UFS_EXTATTR if (e_restart) { ufs_extattr_uepm_init(&ump->um_extattr); diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index ba70571..809c32c 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -158,6 +158,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, object1->pg_color = color; object1->handle = handle; object1->un_pager.devp.ops = ops; + object1->un_pager.devp.dev = handle; TAILQ_INIT(&object1->un_pager.devp.devp_pglist); mtx_lock(&dev_pager_mtx); object = vm_pager_object_lookup(&dev_pager_object_list, handle); @@ -235,7 +236,7 @@ dev_pager_dealloc(object) vm_page_t m; VM_OBJECT_UNLOCK(object); - object->un_pager.devp.ops->cdev_pg_dtor(object->handle); + object->un_pager.devp.ops->cdev_pg_dtor(object->un_pager.devp.dev); mtx_lock(&dev_pager_mtx); TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index f87e5b9..26de826 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -726,12 +726,6 @@ vmspace_resident_count(struct vmspace *vmspace) return pmap_resident_count(vmspace_pmap(vmspace)); } -long -vmspace_wired_count(struct vmspace *vmspace) -{ - return pmap_wired_count(vmspace_pmap(vmspace)); -} - /* * vm_map_create: * @@ -3281,8 +3275,7 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, } if (!old_mlock && map->flags & MAP_WIREFUTURE) { - if (ptoa(vmspace_wired_count(curproc->p_vmspace)) + - init_ssize > lmemlim) { + if (ptoa(pmap_wired_count(map->pmap)) + init_ssize > lmemlim) { vm_map_unlock(map); return (KERN_NO_SPACE); } @@ -3505,8 +3498,7 @@ Retry: grow_amount = limit - ctob(vm->vm_ssize); #endif if (!old_mlock && map->flags & MAP_WIREFUTURE) { - if (ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount > - lmemlim) { + if (ptoa(pmap_wired_count(map->pmap)) + grow_amount > lmemlim) { vm_map_unlock_read(map); rv = KERN_NO_SPACE; goto out; @@ -3514,7 +3506,7 @@ Retry: #ifdef RACCT PROC_LOCK(p); if (racct_set(p, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount)) { + ptoa(pmap_wired_count(map->pmap)) + grow_amount)) { PROC_UNLOCK(p); vm_map_unlock_read(map); rv = KERN_NO_SPACE; @@ -3645,7 +3637,7 @@ out: KASSERT(error == 0, ("decreasing RACCT_VMEM failed")); if (!old_mlock) { error = racct_set(p, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(p->p_vmspace))); + ptoa(pmap_wired_count(map->pmap))); KASSERT(error == 0, ("decreasing RACCT_MEMLOCK failed")); } error = racct_set(p, RACCT_STACK, ctob(vm->vm_ssize)); diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index b3b1ad4..135b555 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -298,7 +298,6 @@ void vm_map_wait_busy(vm_map_t map); _vm_map_lock_downgrade(map, LOCK_FILE, LOCK_LINE) long vmspace_resident_count(struct vmspace *vmspace); -long vmspace_wired_count(struct vmspace *vmspace); #endif /* _KERNEL */ diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 16f331a..05bb8ae 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -1038,6 +1038,7 @@ sys_mlock(td, uap) struct proc *proc; vm_offset_t addr, end, last, start; vm_size_t npages, size; + vm_map_t map; unsigned long nsize; int error; @@ -1055,8 +1056,9 @@ sys_mlock(td, uap) if (npages > vm_page_max_wired) return (ENOMEM); proc = td->td_proc; + map = &proc->p_vmspace->vm_map; PROC_LOCK(proc); - nsize = ptoa(npages + vmspace_wired_count(proc->p_vmspace)); + nsize = ptoa(npages + pmap_wired_count(map->pmap)); if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); return (ENOMEM); @@ -1071,13 +1073,13 @@ sys_mlock(td, uap) if (error != 0) return (ENOMEM); #endif - error = vm_map_wire(&proc->p_vmspace->vm_map, start, end, + error = vm_map_wire(map, start, end, VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); #ifdef RACCT if (error != KERN_SUCCESS) { PROC_LOCK(proc); racct_set(proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(proc->p_vmspace))); + ptoa(pmap_wired_count(map->pmap))); PROC_UNLOCK(proc); } #endif @@ -1151,7 +1153,7 @@ sys_mlockall(td, uap) if (error != KERN_SUCCESS) { PROC_LOCK(td->td_proc); racct_set(td->td_proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(td->td_proc->p_vmspace))); + ptoa(pmap_wired_count(map->pmap))); PROC_UNLOCK(td->td_proc); } #endif @@ -1485,16 +1487,15 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, return (ENOMEM); } if (!old_mlock && map->flags & MAP_WIREFUTURE) { - if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) + - size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { + if (ptoa(pmap_wired_count(map->pmap)) + size > + lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { racct_set_force(td->td_proc, RACCT_VMEM, map->size); PROC_UNLOCK(td->td_proc); return (ENOMEM); } error = racct_set(td->td_proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) + - size); + ptoa(pmap_wired_count(map->pmap)) + size); if (error != 0) { racct_set_force(td->td_proc, RACCT_VMEM, map->size); diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index b584239..8134752 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -136,6 +136,7 @@ struct vm_object { struct { TAILQ_HEAD(, vm_page) devp_pglist; struct cdev_pager_ops *ops; + struct cdev *dev; } devp; /* diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c index d6da08b..edb6ecc 100644 --- a/sys/vm/vm_unix.c +++ b/sys/vm/vm_unix.c @@ -76,6 +76,7 @@ sys_obreak(td, uap) struct obreak_args *uap; { struct vmspace *vm = td->td_proc->p_vmspace; + vm_map_t map = &vm->vm_map; vm_offset_t new, old, base; rlim_t datalim, lmemlim, vmemlim; int prot, rv; @@ -90,7 +91,7 @@ sys_obreak(td, uap) do_map_wirefuture = FALSE; new = round_page((vm_offset_t)uap->nsize); - vm_map_lock(&vm->vm_map); + vm_map_lock(map); base = round_page((vm_offset_t) vm->vm_daddr); old = base + ctob(vm->vm_dsize); @@ -103,7 +104,7 @@ sys_obreak(td, uap) error = ENOMEM; goto done; } - if (new > vm_map_max(&vm->vm_map)) { + if (new > vm_map_max(map)) { error = ENOMEM; goto done; } @@ -117,14 +118,14 @@ sys_obreak(td, uap) goto done; } if (new > old) { - if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) { - if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) + + if (!old_mlock && map->flags & MAP_WIREFUTURE) { + if (ptoa(pmap_wired_count(map->pmap)) + (new - old) > lmemlim) { error = ENOMEM; goto done; } } - if (vm->vm_map.size + (new - old) > vmemlim) { + if (map->size + (new - old) > vmemlim) { error = ENOMEM; goto done; } @@ -137,22 +138,21 @@ sys_obreak(td, uap) goto done; } error = racct_set(td->td_proc, RACCT_VMEM, - vm->vm_map.size + (new - old)); + map->size + (new - old)); if (error != 0) { racct_set_force(td->td_proc, RACCT_DATA, old - base); PROC_UNLOCK(td->td_proc); error = ENOMEM; goto done; } - if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) { + if (!old_mlock && map->flags & MAP_WIREFUTURE) { error = racct_set(td->td_proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) + - (new - old)); + ptoa(pmap_wired_count(map->pmap)) + (new - old)); if (error != 0) { racct_set_force(td->td_proc, RACCT_DATA, old - base); racct_set_force(td->td_proc, RACCT_VMEM, - vm->vm_map.size); + map->size); PROC_UNLOCK(td->td_proc); error = ENOMEM; goto done; @@ -167,17 +167,15 @@ sys_obreak(td, uap) prot |= VM_PROT_EXECUTE; #endif #endif - rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new, - prot, VM_PROT_ALL, 0); + rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0); if (rv != KERN_SUCCESS) { #ifdef RACCT PROC_LOCK(td->td_proc); racct_set_force(td->td_proc, RACCT_DATA, old - base); - racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size); - if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) { + racct_set_force(td->td_proc, RACCT_VMEM, map->size); + if (!old_mlock && map->flags & MAP_WIREFUTURE) { racct_set_force(td->td_proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count( - td->td_proc->p_vmspace))); + ptoa(pmap_wired_count(map->pmap))); } PROC_UNLOCK(td->td_proc); #endif @@ -194,13 +192,13 @@ sys_obreak(td, uap) * * XXX If the pages cannot be wired, no error is returned. */ - if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { + if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { if (bootverbose) printf("obreak: MAP_WIREFUTURE set\n"); do_map_wirefuture = TRUE; } } else if (new < old) { - rv = vm_map_delete(&vm->vm_map, new, old); + rv = vm_map_delete(map, new, old); if (rv != KERN_SUCCESS) { error = ENOMEM; goto done; @@ -209,19 +207,19 @@ sys_obreak(td, uap) #ifdef RACCT PROC_LOCK(td->td_proc); racct_set_force(td->td_proc, RACCT_DATA, new - base); - racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size); - if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) { + racct_set_force(td->td_proc, RACCT_VMEM, map->size); + if (!old_mlock && map->flags & MAP_WIREFUTURE) { racct_set_force(td->td_proc, RACCT_MEMLOCK, - ptoa(vmspace_wired_count(td->td_proc->p_vmspace))); + ptoa(pmap_wired_count(map->pmap))); } PROC_UNLOCK(td->td_proc); #endif } done: - vm_map_unlock(&vm->vm_map); + vm_map_unlock(map); if (do_map_wirefuture) - (void) vm_map_wire(&vm->vm_map, old, new, + (void) vm_map_wire(map, old, new, VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); return (error); diff --git a/tools/build/Makefile b/tools/build/Makefile index 76493f7..b9b548e 100644 --- a/tools/build/Makefile +++ b/tools/build/Makefile @@ -21,6 +21,22 @@ config.h: ${.CURDIR}/../../lib/libmagic/config.h grep -v HAVE_GETLINE ${.ALLSRC} > ${.TARGET} .endif +_WITH_PWCACHEDB!= grep -c pwcache_groupdb /usr/include/pwd.h || true +.if ${_WITH_PWCACHEDB} == 0 +.PATH: ${.CURDIR}/../../contrib/libc-pwcache +CFLAGS+= -I${.CURDIR}/../../contrib/libc-pwcache \ + -I${.CURDIR}/../../lib/libc/include +SRCS+= pwcache.c +.endif + +_WITH_STRSVIS!= grep -c strsvis /usr/include/vis.h || true +.if ${_WITH_STRSVIS} == 0 +.PATH: ${.CURDIR}/../../contrib/libc-vis +SRCS+= vis.c +CFLAGS+= -I${.CURDIR}/../../contrib/libc-vis \ + -I${.CURDIR}/../../lib/libc/include +.endif + .if empty(SRCS) SRCS= dummy.c .endif diff --git a/tools/build/options/WITH_NMTREE b/tools/build/options/WITH_NMTREE new file mode 100644 index 0000000..cbaa873 --- /dev/null +++ b/tools/build/options/WITH_NMTREE @@ -0,0 +1,9 @@ +.\" $FreeBSD$ +Set to install +.Xr nmtree 8 +as +.Xr mtree 8 . +By default +.Xr fmtree 8 +is installed as +.Xr mtree 8 . diff --git a/tools/regression/bin/sh/execution/subshell1.0 b/tools/regression/bin/sh/execution/subshell1.0 new file mode 100644 index 0000000..347806e --- /dev/null +++ b/tools/regression/bin/sh/execution/subshell1.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +(eval "cd / +v=$(printf %0100000d 1) +echo \${#v}") +echo end diff --git a/tools/regression/bin/sh/execution/subshell1.0.stdout b/tools/regression/bin/sh/execution/subshell1.0.stdout new file mode 100644 index 0000000..8c71af3 --- /dev/null +++ b/tools/regression/bin/sh/execution/subshell1.0.stdout @@ -0,0 +1,2 @@ +100000 +end diff --git a/tools/regression/bin/sh/execution/subshell2.0 b/tools/regression/bin/sh/execution/subshell2.0 new file mode 100644 index 0000000..3216449 --- /dev/null +++ b/tools/regression/bin/sh/execution/subshell2.0 @@ -0,0 +1,10 @@ +# $FreeBSD$ + +f() { + x=2 +} +( + x=1 + f + [ "$x" = 2 ] +) diff --git a/tools/regression/bin/sh/execution/subshell3.0 b/tools/regression/bin/sh/execution/subshell3.0 new file mode 100644 index 0000000..9a87acb --- /dev/null +++ b/tools/regression/bin/sh/execution/subshell3.0 @@ -0,0 +1,4 @@ +# $FreeBSD$ + +(false; exit) && exit 3 +exit 0 diff --git a/tools/regression/bin/sh/execution/subshell4.0 b/tools/regression/bin/sh/execution/subshell4.0 new file mode 100644 index 0000000..b39edb1 --- /dev/null +++ b/tools/regression/bin/sh/execution/subshell4.0 @@ -0,0 +1,3 @@ +# $FreeBSD$ + +(eval "set v=1"; false) && echo bad; : diff --git a/tools/regression/bin/sh/expansion/cmdsubst14.0 b/tools/regression/bin/sh/expansion/cmdsubst14.0 new file mode 100644 index 0000000..bdbbb82 --- /dev/null +++ b/tools/regression/bin/sh/expansion/cmdsubst14.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +! v=`false + +` diff --git a/tools/regression/bin/sh/expansion/cmdsubst15.0 b/tools/regression/bin/sh/expansion/cmdsubst15.0 new file mode 100644 index 0000000..31d85d4 --- /dev/null +++ b/tools/regression/bin/sh/expansion/cmdsubst15.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +! v=`false; + +` diff --git a/tools/regression/bin/sh/expansion/cmdsubst16.0 b/tools/regression/bin/sh/expansion/cmdsubst16.0 new file mode 100644 index 0000000..71df562 --- /dev/null +++ b/tools/regression/bin/sh/expansion/cmdsubst16.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +f() { return 3; } +f +[ `echo $?` = 3 ] diff --git a/tools/regression/bin/sh/expansion/cmdsubst17.0 b/tools/regression/bin/sh/expansion/cmdsubst17.0 new file mode 100644 index 0000000..8c29e83 --- /dev/null +++ b/tools/regression/bin/sh/expansion/cmdsubst17.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +f() { return 3; } +f +[ `echo $?; :` = 3 ] diff --git a/tools/regression/bin/sh/parser/empty-braces1.0 b/tools/regression/bin/sh/parser/empty-braces1.0 new file mode 100644 index 0000000..5ab443c --- /dev/null +++ b/tools/regression/bin/sh/parser/empty-braces1.0 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +# Unfortunately, some scripts depend on the extension of allowing an empty +# pair of braces. + +{ } & +wait $! diff --git a/tools/tools/ath/athspectral/athspectral.c b/tools/tools/ath/athspectral/athspectral.c index 8e6962a..7bdfa2b 100644 --- a/tools/tools/ath/athspectral/athspectral.c +++ b/tools/tools/ath/athspectral/athspectral.c @@ -187,6 +187,29 @@ spectral_stop(struct spectralhandler *spectral) err(1, spectral->atd.ad_name); } +static void +spectral_enable_at_reset(struct spectralhandler *spectral, int val) +{ + int v = val; + + spectral->atd.ad_id = SPECTRAL_CONTROL_ENABLE_AT_RESET + | ATH_DIAG_IN; + + /* + * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag + * and debug + */ + spectral->atd.ad_out_data = NULL; + spectral->atd.ad_out_size = 0; + spectral->atd.ad_in_data = (caddr_t) &v; + spectral->atd.ad_in_size = sizeof(v); + + printf("%s: val=%d\n", __func__, v); + + if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) + err(1, spectral->atd.ad_name); +} + static int spectral_set_param(struct spectralhandler *spectral, const char *param, const char *val) @@ -258,6 +281,7 @@ usage(const char *progname) printf("\tset <param> <value>:\t\tSet spectral parameter\n"); printf("\tstart: Start spectral scan\n"); printf("\tstop: Stop spectral scan\n"); + printf("\tenable_at_reset <0|1>: enable reporting upon channel reset\n"); } int @@ -312,6 +336,12 @@ main(int argc, char *argv[]) spectral_start(&spectral); } else if (strcasecmp(argv[1], "stop") == 0) { spectral_stop(&spectral); + } else if (strcasecmp(argv[1], "enable_at_reset") == 0) { + if (argc < 3) { + usage(progname); + exit(127); + } + spectral_enable_at_reset(&spectral, atoi(argv[2])); } else { usage(progname); exit(127); diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index 810f47b..f7f449b 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -165,6 +165,7 @@ 05/22 Clive Tong-I Lin <clive@FreeBSD.org> born in Changhua, Taiwan, Republic of China, 1978 05/22 Michael Bushkov <bushman@FreeBSD.org> born in Rostov-on-Don, Russian Federation, 1985 05/22 Rui Paulo <rpaulo@FreeBSD.org> born in Evora, Portugal, 1986 +05/22 David Naylor <dbn@FreeBSD.org> born in Johannesburg, South Africa, 1988 05/23 Munechika Sumikawa <sumikawa@FreeBSD.org> born in Osaka, Osaka, Japan, 1972 05/24 Duncan McLennan Barclay <dmlb@FreeBSD.org> born in London, Middlesex, United Kingdom, 1970 05/24 Oliver Lehmann <oliver@FreeBSD.org> born in Karlsburg, Germany, 1981 diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c index b0cee6b..934e292 100644 --- a/usr.bin/procstat/procstat.c +++ b/usr.bin/procstat/procstat.c @@ -216,8 +216,8 @@ main(int argc, char *argv[]) argv += optind; /* We require that either 0 or 1 mode flags be set. */ - tmp = bflag + cflag + eflag + fflag + (kflag ? 1 : 0) + lflag + sflag + - tflag + vflag + xflag; + tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + + lflag + sflag + tflag + vflag + xflag; if (!(tmp == 0 || tmp == 1)) usage(); diff --git a/usr.bin/stdbuf/stdbuf.c b/usr.bin/stdbuf/stdbuf.c index 3831b5e..4346cc8 100644 --- a/usr.bin/stdbuf/stdbuf.c +++ b/usr.bin/stdbuf/stdbuf.c @@ -39,7 +39,7 @@ extern char *__progname; static void usage(int s) { - + fprintf(stderr, "Usage: %s [-e 0|L|<sz>] [-i 0|L|<sz>] [-o 0|L|<sz>] " "<cmd> [args ...]\n", __progname); exit(s); @@ -72,8 +72,8 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; - if (argc < 2) - usage(0); + if (argc == 0) + exit(0); if (ibuf != NULL && setenv("_STDBUF_I", ibuf, 1) == -1) warn("Failed to set environment variable: %s=%s", @@ -94,7 +94,7 @@ main(int argc, char *argv[]) if (i < 0 || putenv(preload1) == -1) warn("Failed to set environment variable: LD_PRELOAD"); - + preload0 = getenv("LD_32_PRELOAD"); if (preload0 == NULL) i = asprintf(&preload1, "LD_32_PRELOAD=" LIBSTDBUF32); diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile index e6ff88e..2a2aace 100644 --- a/usr.bin/xinstall/Makefile +++ b/usr.bin/xinstall/Makefile @@ -3,6 +3,14 @@ PROG= xinstall PROGNAME= install +SRCS= xinstall.c getid.c MAN= install.1 +.PATH: ${.CURDIR}/../../contrib/mtree +CFLAGS+= -I${.CURDIR}/../../contrib/mtree +CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd + +DPADD+= ${LIBUTIL} +LDADD+= -lutil + .include <bsd.prog.mk> diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1 index 1c7c415..01b58dc 100644 --- a/usr.bin/xinstall/install.1 +++ b/usr.bin/xinstall/install.1 @@ -41,6 +41,7 @@ .Op Fl f Ar flags .Op Fl g Ar group .Op Fl m Ar mode +.Op Fl N Ar dbdir .Op Fl o Ar owner .Ar file1 file2 .Nm @@ -49,6 +50,7 @@ .Op Fl f Ar flags .Op Fl g Ar group .Op Fl m Ar mode +.Op Fl N Ar dbdir .Op Fl o Ar owner .Ar file1 ... fileN directory .Nm @@ -56,6 +58,7 @@ .Op Fl v .Op Fl g Ar group .Op Fl m Ar mode +.Op Fl N Ar dbdir .Op Fl o Ar owner .Ar directory ... .Sh DESCRIPTION @@ -124,6 +127,18 @@ The default mode is set to rwxr-xr-x (0755). The specified mode may be either an octal or symbolic value; see .Xr chmod 1 for a description of possible mode values. +.It Fl N +Use the user database text file +.Pa master.passwd +and group database text file +.Pa group +from +.Ar dbdir , +rather than using the results from the system's +.Xr getpwnam 3 +and +.Xr getgrnam 3 +(and related) library calls. .It Fl o Specify an owner. A numeric UID is allowed. @@ -231,6 +246,8 @@ The default was changed to copy in .Xr mv 1 , .Xr strip 1 , .Xr mmap 2 , +.Xr getgrnam 3 , +.Xr getpwnam 3 , .Xr chown 8 .Sh HISTORY The diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 583348a..74f9d20 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$"); #include <sysexits.h> #include <unistd.h> +#include "mtree.h" + /* Bootstrap aid - this doesn't exist in most older releases */ #ifndef MAP_FAILED #define MAP_FAILED ((void *)-1) /* from <sys/mman.h> */ @@ -74,8 +76,6 @@ __FBSDID("$FreeBSD$"); #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) #define BACKUP_SUFFIX ".old" -static struct passwd *pp; -static struct group *gp; static gid_t gid; static uid_t uid; static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, @@ -89,7 +89,7 @@ static int create_newfile(const char *, int, struct stat *); static int create_tempfile(const char *, char *, size_t); static void install(const char *, const char *, u_long, u_int); static void install_dir(char *); -static u_long numeric_id(const char *, const char *); +static int parseid(const char *, id_t *); static void strip(const char *); static int trymmap(int); static void usage(void); @@ -107,7 +107,7 @@ main(int argc, char *argv[]) iflags = 0; group = owner = NULL; - while ((ch = getopt(argc, argv, "B:bCcdf:g:Mm:o:pSsv")) != -1) + while ((ch = getopt(argc, argv, "B:bCcdf:g:Mm:N:o:pSsv")) != -1) switch((char)ch) { case 'B': suffix = optarg; @@ -143,6 +143,11 @@ main(int argc, char *argv[]) mode = getmode(set, 0); free(set); break; + case 'N': + if (!setup_getid(optarg)) + err(1, "Unable to use user and group " + "databases in `%s'", optarg); + break; case 'o': owner = optarg; break; @@ -186,18 +191,22 @@ main(int argc, char *argv[]) /* get group and owner id's */ if (group != NULL) { - if ((gp = getgrnam(group)) != NULL) - gid = gp->gr_gid; - else - gid = (gid_t)numeric_id(group, "group"); + if (gid_from_group(group, &gid) == -1) { + id_t id; + if (!parseid(group, &id)) + errx(1, "unknown group %s", group); + gid = id; + } } else gid = (gid_t)-1; if (owner != NULL) { - if ((pp = getpwnam(owner)) != NULL) - uid = pp->pw_uid; - else - uid = (uid_t)numeric_id(owner, "user"); + if (uid_from_user(owner, &uid) == -1) { + id_t id; + if (!parseid(owner, &id)) + errx(1, "unknown user %s", owner); + uid = id; + } } else uid = (uid_t)-1; @@ -244,23 +253,19 @@ main(int argc, char *argv[]) /* NOTREACHED */ } -static u_long -numeric_id(const char *name, const char *type) +/* + * parseid -- + * parse uid or gid from arg into id, returning non-zero if successful + */ +static int +parseid(const char *name, id_t *id) { - u_long val; - char *ep; - - /* - * XXX - * We know that uid_t's and gid_t's are unsigned longs. - */ + char *ep; errno = 0; - val = strtoul(name, &ep, 10); - if (errno) - err(EX_NOUSER, "%s", name); - if (*ep != '\0') - errx(EX_NOUSER, "unknown %s %s", type, name); - return (val); + *id = (id_t)strtoul(name, &ep, 10); + if (errno || *ep != '\0') + return (0); + return (1); } /* @@ -786,10 +791,11 @@ usage(void) { (void)fprintf(stderr, "usage: install [-bCcMpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n" -" [-o owner] file1 file2\n" +" [-N dbdir] [-o owner] file1 file2\n" " install [-bCcMpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n" -" [-o owner] file1 ... fileN directory\n" -" install -d [-v] [-g group] [-m mode] [-o owner] directory ...\n"); +" [-N dbdir] [-o owner] file1 ... fileN directory\n" +" install -d [-v] [-g group] [-m mode] [-N dbdir] [-o owner]\n" +" directory ...\n"); exit(EX_USAGE); /* NOTREACHED */ } diff --git a/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig index 436b8a4..07b73fe 100755 --- a/usr.sbin/bsdconfig/bsdconfig +++ b/usr.sbin/bsdconfig/bsdconfig @@ -192,6 +192,7 @@ dialog_menu_main() --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_exit_bsdconfig\" \ --help-button \ + --help-label \"\$msg_help\" \ ${USE_XDIALOG:+--help \"\"} \ --menu \"\$prompt\" $size $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD diff --git a/usr.sbin/bsdconfig/console/ttys b/usr.sbin/bsdconfig/console/ttys index e1650da..3f9945e 100755 --- a/usr.sbin/bsdconfig/console/ttys +++ b/usr.sbin/bsdconfig/console/ttys @@ -192,7 +192,7 @@ while :; do err=$( ttys_set_type "$consterm" 2>&1 ) [ "$err" ] || break - f_show_msg "%s" "$err" + f_dialog_msgbox "$err" done exit $SUCCESS diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr index f77a5e7..23ac83b 100644 --- a/usr.sbin/bsdconfig/networking/share/device.subr +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -343,6 +343,7 @@ f_dialog_menu_netdev_edit() --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --help-button \ + --help-label \"\$msg_help\" \ ${USE_XDIALOG:+--help \"\"} \ --menu \"\$prompt\" $size \ $menu_list \ @@ -455,9 +456,8 @@ f_dialog_menu_netdev_edit() # Re/Apply the settings if desired # if [ ! "$dhcp" ]; then - f_dialog_yesno "Would you like to bring the $interface" \ - "interface up right now?" - if [ $? -eq $SUCCESS ]; then + if f_yesno "$msg_bring_interface_up" "$interface" + then f_show_info "$msg_bring_interface_up" "$interface" local dr="$( f_sysrc_get defaultrouter )" err diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr index 959c7df..b276059 100644 --- a/usr.sbin/bsdconfig/networking/share/hostname.subr +++ b/usr.sbin/bsdconfig/networking/share/hostname.subr @@ -201,10 +201,8 @@ f_dialog_input_hostname() f_show_msg "$msg_activate_hostname_x11warning" \ "$( hostname )" "$hostname" else - f_dialog_yesno "$( - printf "$msg_activate_hostname" \ - "$( hostname )" "$hostname" \ - )" \ + f_yesno "$msg_activate_hostname" \ + "$( hostname )" "$hostname" \ && hostname "$hostname" fi fi diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr index 3990c03..4207ab2 100644 --- a/usr.sbin/bsdconfig/networking/share/routing.subr +++ b/usr.sbin/bsdconfig/networking/share/routing.subr @@ -129,11 +129,8 @@ f_dialog_input_defaultrouter() # if [ "$( f_route_get_default )" != "$defaultrouter" ]; then f_dialog_clear - f_dialog_yesno "$( - printf "$msg_activate_default_router" \ - "$( f_route_get_default )" "$defaultrouter" - )" - + f_yesno "$msg_activate_default_router" \ + "$( f_route_get_default )" "$defaultrouter" if [ $? -eq $SUCCESS ]; then local err diff --git a/usr.sbin/bsdconfig/password/password b/usr.sbin/bsdconfig/password/password index 6b9e57d..50d963d 100755 --- a/usr.sbin/bsdconfig/password/password +++ b/usr.sbin/bsdconfig/password/password @@ -72,7 +72,7 @@ f_mustberoot_init if f_dialog_input_password; then err=$( echo "$pw_password" | pw usermod $USER_ROOT -h 0 2>&1 ) || f_die $? "%s" "$err" - f_show_msg "$msg_password_changed" + f_dialog_msgbox "$msg_password_changed" fi return $SUCCESS diff --git a/usr.sbin/bsdconfig/password/share/password.subr b/usr.sbin/bsdconfig/password/share/password.subr index bf83df7..f4ebaab9 100644 --- a/usr.sbin/bsdconfig/password/share/password.subr +++ b/usr.sbin/bsdconfig/password/share/password.subr @@ -108,13 +108,13 @@ f_dialog_input_password() # Check for NULL entry if ! [ "$_password1" -o "$_password2" ]; then - f_show_msg "$msg_password_is_empty" + f_dialog_msgbox "$msg_password_is_empty" continue fi # Check for password mismatch if [ "$_password1" != "$_password2" ]; then - f_show_msg "$msg_passwords_do_not_match" + f_dialog_msgbox "$msg_passwords_do_not_match" continue fi diff --git a/usr.sbin/bsdconfig/security/kern_securelevel b/usr.sbin/bsdconfig/security/kern_securelevel index 67fd1aa..42594c6 100755 --- a/usr.sbin/bsdconfig/security/kern_securelevel +++ b/usr.sbin/bsdconfig/security/kern_securelevel @@ -78,6 +78,7 @@ dialog_menu_main() --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --help-button \ + --help-label \"\$msg_help\" \ ${USE_XDIALOG:+--help \"\"} \ --menu \"\$prompt\" $size \ $menu_list \ diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr index 05531aa..c66a54f 100644 --- a/usr.sbin/bsdconfig/share/common.subr +++ b/usr.sbin/bsdconfig/share/common.subr @@ -214,6 +214,50 @@ f_show_msg() fi } + +# f_yesno $fmt [ $opts ... ] +# +# Display a message in a dialog yes/no box using printf(1) syntax. +# +f_yesno() +{ + local msg + msg=$( printf "$@" ) + + # + # Use f_dialog_yesno from dialog.subr if possible, otherwise fall + # back to dialog(1) (without options, making it obvious when using + # un-aided system dialog). + # + if f_have f_dialog_yesno; then + f_dialog_yesno "$msg" + else + dialog --yesno "$msg" 0 0 + fi +} + +# f_noyes $fmt [ $opts ... ] +# +# Display a message in a dialog yes/no box using printf(1) syntax. +# NOTE: THis is just like the f_yesno function except "No" is default. +# +f_noyes() +{ + local msg + msg=$( printf "$@" ) + + # + # Use f_dialog_noyes from dialog.subr if possible, otherwise fall + # back to dialog(1) (without options, making it obvious when using + # un-aided system dialog). + # + if f_have f_dialog_noyes; then + f_dialog_noyes "$msg" + else + dialog --defaultno --yesno "$msg" 0 0 + fi +} + # f_show_help $file # # Display a language help-file. Automatically takes $LANG and $LC_ALL into diff --git a/usr.sbin/bsdconfig/share/mustberoot.subr b/usr.sbin/bsdconfig/share/mustberoot.subr index ebce9c1..2ead592 100644 --- a/usr.sbin/bsdconfig/share/mustberoot.subr +++ b/usr.sbin/bsdconfig/share/mustberoot.subr @@ -128,7 +128,7 @@ f_become_root_via_sudo() 1) # Always try sudo(8) when run as $user local err if ! err=$( touch "$checkpath" 2>&1 ); then - f_show_msg "%s" "$err" + f_dialog_msgbox "$err" else f_show_msg "$msg_created_path" "$checkpath" fi diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr index f63a5f8..235f6dc 100644 --- a/usr.sbin/bsdconfig/share/variable.subr +++ b/usr.sbin/bsdconfig/share/variable.subr @@ -118,7 +118,7 @@ f_variable_set_defaults() # # Dump a list of registered/advertised variables and their respective values to # $VARIABLE_DUMPFILE. Returns success unless the file couldn't be written. If -# an error occurs, it is displayed using f_show_msg() (from common.subr). +# an error occurs, it is displayed using f_dialog_msgbox() (from dialog.subr). # f_dump_variables() { @@ -131,7 +131,7 @@ f_dump_variables() printf "%s='%s'\n" "$var" "$value" done > "$VARIABLE_DUMPFILE" ) 2>&1 ); then - f_show_msg "%s" "$err" + f_dialog_msgbox "$err" return $FAILURE fi } diff --git a/usr.sbin/bsdconfig/startup/misc b/usr.sbin/bsdconfig/startup/misc index 626697a..37bb80f 100755 --- a/usr.sbin/bsdconfig/startup/misc +++ b/usr.sbin/bsdconfig/startup/misc @@ -307,14 +307,14 @@ while :; do ?" [X] "*) err=$( f_sysrc_set apm_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set apm_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_startup_dirs") dialog_input_value \ "$msg_startup_dirs_desc" \ "$( f_sysrc_get local_startup )" if [ $? -eq $SUCCESS ]; then err=$( f_sysrc_set local_startup "$value" ) || - f_show_msg "%s\n" "$err" + f_dialog_msgbox "$err\n" fi ;; ?" ["?"] $msg_named") @@ -322,14 +322,14 @@ while :; do ?" [X] "*) err=$( f_sysrc_set named_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set named_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_named_flags") dialog_input_value \ "$msg_named_flags_desc" \ "$( f_sysrc_get named_flags )" if [ $? -eq $SUCCESS ]; then err=$( f_sysrc_set named_flags "$value" ) || - f_show_msg "%s\n" "$err" + f_dialog_msgbox "$err\n" fi ;; ?" ["?"] $msg_nis_client") @@ -339,14 +339,14 @@ while :; do err=$( f_sysrc_set nis_client_enable YES 2>&1 ) \ && err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_nis_domainname") dialog_input_value \ "$msg_nis_domainname_desc" \ "$( f_sysrc_get nisdomainname )" if [ $? -eq $SUCCESS ]; then err=$( f_sysrc_set nisdomainname "$value" ) || - f_show_msg "%s\n" "$err" + f_dialog_msgbox "$err\n" fi ;; ?" ["?"] $msg_nis_server") @@ -356,31 +356,31 @@ while :; do err=$( f_sysrc_set nis_server_enable YES 2>&1 ) \ && err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_accounting") case "$mtag" in ?" [X] "*) err=$( f_sysrc_set accounting_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set accounting_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_lpd") case "$mtag" in ?" [X] "*) err=$( f_sysrc_set lpd_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set lpd_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_sco") case "$mtag" in ?" [X] "*) err=$( f_sysrc_set ibcs2_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set ibcs2_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; ?" ["?"] $msg_svr4") case "$mtag" in ?" [X] "*) err=$( f_sysrc_set svr4_enable NO 2>&1 ) ;; ?" [ ] "*) err=$( f_sysrc_set svr4_enable YES 2>&1 ) ;; esac - [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;; + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;; esac done diff --git a/usr.sbin/bsdconfig/startup/rcdelete b/usr.sbin/bsdconfig/startup/rcdelete index 02ec049..578b13e 100755 --- a/usr.sbin/bsdconfig/startup/rcdelete +++ b/usr.sbin/bsdconfig/startup/rcdelete @@ -210,9 +210,7 @@ dialog_menu_delete() [ $# -ge 1 ] || return $FAILURE if [ $# -eq 1 ]; then - msg=$( printf "$msg_are_you_sure_you_want_to_delete" \ - "$delete_vars" ) - f_dialog_noyes "$msg" + f_noyes "$msg_are_you_sure_you_want_to_delete" "$delete_vars" return $? fi @@ -320,7 +318,7 @@ while :; do for var in $delete_vars; do err=$( f_sysrc_delete $var 2>&1 ) if [ $? -ne $SUCCESS ]; then - f_show_msg "%s\n" "$err" + f_dialog_msgbox "$err\n" break fi done diff --git a/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar index 8f27b51..d7ced9e 100755 --- a/usr.sbin/bsdconfig/startup/rcvar +++ b/usr.sbin/bsdconfig/startup/rcvar @@ -194,7 +194,7 @@ while :; do esac err=$( f_sysrc_set "$rcvar" "$value" 2>&1 ) || - f_show_msg "$err" + f_dialog_msgbox "$err" esac done diff --git a/usr.sbin/bsdconfig/startup/share/rcconf.subr b/usr.sbin/bsdconfig/startup/share/rcconf.subr index 8878d2c..12eafd9 100644 --- a/usr.sbin/bsdconfig/startup/share/rcconf.subr +++ b/usr.sbin/bsdconfig/startup/share/rcconf.subr @@ -432,14 +432,14 @@ f_dialog_input_rcvar() # Check for invalid entry (1of2) if ! echo "$_input" | grep -q "^[[:alpha:]_]"; then - f_show_msg "$msg_rcvar_must_start_with" + f_dialog_msgbox "$msg_rcvar_must_start_with" continue fi # Check for invalid entry (2of2) if ! echo "$_input" | grep -q "^[[:alpha:]_][[:alnum:]_]*$" then - f_show_msg "$msg_rcvar_contains_invalid_chars" + f_dialog_msgbox "$msg_rcvar_contains_invalid_chars" continue fi diff --git a/usr.sbin/bsdconfig/startup/share/rcedit.subr b/usr.sbin/bsdconfig/startup/share/rcedit.subr index a9cba88..cb4a411 100644 --- a/usr.sbin/bsdconfig/startup/share/rcedit.subr +++ b/usr.sbin/bsdconfig/startup/share/rcedit.subr @@ -78,8 +78,7 @@ f_dialog_rcedit() f_dprintf "%s: [%s]->[%s]" "$var" "$cur_val" "$_input" - err=$( f_sysrc_set "$var" "$_input" 2>&1 ) || - f_show_msg "$err" + err=$( f_sysrc_set "$var" "$_input" 2>&1 ) || f_dialog_msgbox "$err" } ############################################################ MAIN diff --git a/usr.sbin/bsdconfig/usermgmt/groupinput b/usr.sbin/bsdconfig/usermgmt/groupinput index 83d0c1d..c459224 100755 --- a/usr.sbin/bsdconfig/usermgmt/groupinput +++ b/usr.sbin/bsdconfig/usermgmt/groupinput @@ -63,10 +63,10 @@ save_changes() err=$( pw groupdel "$group_name" 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_group_deleted" + f_dialog_msgbox "$msg_group_deleted" ;; Add) local cmd="pw groupadd -n '$group_name'" @@ -82,10 +82,10 @@ save_changes() err=$( eval $cmd 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_group_added" + f_dialog_msgbox "$msg_group_added" ;; Edit/View) local cmd="pw groupmod -n '$group_name'" @@ -101,10 +101,10 @@ save_changes() err=$( eval $cmd 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_group_updated" + f_dialog_msgbox "$msg_group_updated" ;; esac diff --git a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr index 4b47392..278e0a4 100644 --- a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr +++ b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr @@ -134,13 +134,13 @@ f_dialog_input_group_name() # Check for NULL entry if [ ! "$_input" ]; then - f_show_msg "$msg_group_is_empty" + f_dialog_msgbox "$msg_group_is_empty" continue fi # Check for invalid entry if ! echo "$_input" | grep -q "^[[:alpha:]]"; then - f_show_msg "$msg_group_must_start_with_letter" + f_dialog_msgbox "$msg_group_must_start_with_letter" continue fi @@ -229,7 +229,7 @@ f_dialog_input_group_password() # Check for password mismatch if [ "$_password1" != "$_password2" ]; then - f_show_msg "$msg_group_passwords_do_not_match" + f_dialog_msgbox "$msg_group_passwords_do_not_match" continue fi diff --git a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr index d0b5fe3..e0281ed 100644 --- a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr +++ b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr @@ -239,13 +239,13 @@ f_dialog_input_name() # Check for NULL entry if [ ! "$_input" ]; then - f_show_msg "$msg_login_is_empty" + f_dialog_msgbox "$msg_login_is_empty" continue fi # Check for invalid entry if ! echo "$_input" | grep -q "^[[:alpha:]]"; then - f_show_msg "$msg_login_must_start_with_letter" + f_dialog_msgbox "$msg_login_must_start_with_letter" continue fi @@ -334,7 +334,7 @@ f_dialog_input_password() # Check for password mismatch if [ "$_password1" != "$_password2" ]; then - f_show_msg "$msg_passwords_do_not_match" + f_dialog_msgbox "$msg_passwords_do_not_match" continue fi @@ -589,7 +589,7 @@ f_dialog_input_change() # Taint-check the user's input if ! f_isinteger "$ret_days"; then - f_show_msg "$msg_invalid_number_of_days" + f_dialog_msgbox "$msg_invalid_number_of_days" continue fi @@ -616,7 +616,8 @@ f_dialog_input_change() # Taint-check the user's input if ! f_isinteger "${_input:-0}"; then - f_show_msg "$msg_invalid_number_of_seconds" + f_dialog_msgbox \ + "$msg_invalid_number_of_seconds" continue fi @@ -773,7 +774,7 @@ f_dialog_input_expire() # Taint-check the user's input if ! f_isinteger "$ret_days"; then - f_show_msg "$msg_invalid_number_of_days" + f_dialog_msgbox "$msg_invalid_number_of_days" continue fi @@ -800,7 +801,8 @@ f_dialog_input_expire() # Taint-check the user's input if ! f_isinteger "${_input:-0}"; then - f_show_msg "$msg_invalid_number_of_seconds" + f_dialog_msgbox \ + "$msg_invalid_number_of_seconds" continue fi diff --git a/usr.sbin/bsdconfig/usermgmt/userinput b/usr.sbin/bsdconfig/usermgmt/userinput index 36c43e1..ad62a09 100755 --- a/usr.sbin/bsdconfig/usermgmt/userinput +++ b/usr.sbin/bsdconfig/usermgmt/userinput @@ -81,22 +81,22 @@ save_changes() err=$( pw userdel -u "$pw_uid" 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_login_deleted" + f_dialog_msgbox "$msg_login_deleted" if [ "$pw_group_delete" = "$msg_yes" ] && f_quietly pw groupshow -g "$pw_gid" then err=$( pw groupdel -g "$pw_gid" 2>&1 ) || - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" fi if [ "$pw_home_delete" = "$msg_yes" ]; then f_dialog_info "$msg_deleting_home_directory" err=$( rm -Rf "$pw_home_dir" 2>&1 ) || - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" fi ;; Add) @@ -119,26 +119,26 @@ save_changes() err=$( eval $cmd 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_login_added" + f_dialog_msgbox "$msg_login_added" if [ "$pw_home_create" = "$msg_yes" ]; then err=$( mkdir -p "$pw_home_dir" 2>&1 ) if [ $? -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" elif [ -e "$pw_home_dir" ]; then err=$( chown -R "$pw_uid:$pw_gid" \ "$pw_home_dir" 2>&1 ) - [ $? -eq $SUCCESS ] || f_show_msg \ - "%s %s\n" "$msg_warning" "$err" + [ $? -eq $SUCCESS ] || + f_dialog_msgbox "$msg_warning $err\n" fi fi if [ "$pw_dotfiles_create" = "$msg_yes" ]; then err=$( copy_dotfiles 2>&1 ) || - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" fi user="$pw_name" @@ -165,26 +165,26 @@ save_changes() err=$( eval $cmd 2>&1 ) retval=$? if [ $retval -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_error" "$err" + f_dialog_msgbox "$msg_error $err\n" return $retval fi - f_show_msg "$msg_login_updated" + f_dialog_msgbox "$msg_login_updated" if [ "$pw_home_create" = "$msg_yes" ]; then err=$( mkdir -p "$pw_home_dir" ) if [ $? -ne $SUCCESS ]; then - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" elif [ -e "$pw_home_dir" ]; then err=$( chown -R "$pw_uid:$pw_gid" \ "$pw_home_dir" 2>&1 ) - [ $? -eq $SUCCESS ] || f_show_msg \ - "%s %s\n" "$msg_warning" "$err" + [ $? -eq $SUCCESS ] || + f_dialog_msgbox "$msg_warning $err\n" fi fi if [ "$pw_dotfiles_create" = "$msg_yes" ]; then err=$( copy_dotfiles 2>&1 ) || - f_show_msg "%s %s\n" "$msg_warning" "$err" + f_dialog_msgbox "$msg_warning $err\n" fi ;; esac diff --git a/usr.sbin/bsdconfig/usermgmt/usermgmt b/usr.sbin/bsdconfig/usermgmt/usermgmt index 5b69efd..5376bde 100755 --- a/usr.sbin/bsdconfig/usermgmt/usermgmt +++ b/usr.sbin/bsdconfig/usermgmt/usermgmt @@ -88,6 +88,7 @@ dialog_menu_main() --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --help-button \ + --help-label \"\$msg_help\" \ ${USE_XDIALOG:+--help \"\"} \ --menu \"\" $size $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD diff --git a/usr.sbin/bsdinstall/partedit/sade.8 b/usr.sbin/bsdinstall/partedit/sade.8 index 8b2af49..441ddc0 100644 --- a/usr.sbin/bsdinstall/partedit/sade.8 +++ b/usr.sbin/bsdinstall/partedit/sade.8 @@ -56,7 +56,7 @@ in the post-installation environment. A program called .Nm first appeared in -.Fx 6.3 +.Fx 6.3 as a utility encapsulating features from the .Xr sysinstall 8 installer. It was replaced in diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services index 52aa57e..a4cfd46 100755 --- a/usr.sbin/bsdinstall/scripts/services +++ b/usr.sbin/bsdinstall/scripts/services @@ -45,7 +45,7 @@ DAEMONS=$(dialog --backtitle "FreeBSD Installer" \ sshd "Secure shell daemon" ${sshd_enable:-off} \ moused "PS/2 mouse pointer on console" ${moused_enable:-off} \ ntpd "Synchronize system and network time" ${ntpd_enable:-off} \ - powerd "Adjust CPU frequency dynamically" ${powerd_enable:-off} \ + powerd "Adjust CPU frequency dynamically if supported" ${powerd_enable:-off} \ 2>&1 1>&3) exec 3>&- diff --git a/usr.sbin/cpucontrol/intel.c b/usr.sbin/cpucontrol/intel.c index 15ac939..96ab704 100644 --- a/usr.sbin/cpucontrol/intel.c +++ b/usr.sbin/cpucontrol/intel.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include <fcntl.h> #include <err.h> +#include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -266,7 +267,9 @@ matched: args.size = data_size; error = ioctl(devfd, CPUCTL_UPDATE, &args); if (error < 0) { + error = errno; fprintf(stderr, "failed.\n"); + errno = error; WARN(0, "ioctl()"); goto fail; } diff --git a/usr.sbin/cpucontrol/via.c b/usr.sbin/cpucontrol/via.c index 71ae406..d17e31f 100644 --- a/usr.sbin/cpucontrol/via.c +++ b/usr.sbin/cpucontrol/via.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include <fcntl.h> #include <err.h> +#include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -203,7 +204,9 @@ via_update(const char *dev, const char *path) args.size = data_size; error = ioctl(devfd, CPUCTL_UPDATE, &args); if (error < 0) { + error = errno; fprintf(stderr, "failed.\n"); + errno = error; WARN(0, "ioctl()"); goto fail; } diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile index cbc4fd9..c378455 100644 --- a/usr.sbin/mtree/Makefile +++ b/usr.sbin/mtree/Makefile @@ -1,10 +1,12 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include <bsd.own.mk> + .PATH: ${.CURDIR}/../../usr.bin/cksum -PROG= mtree -MAN= mtree.8 mtree.5 +PROG= fmtree +MAN= fmtree.8 mtree.5 SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c SRCS+= specspec.c @@ -12,4 +14,14 @@ CFLAGS+= -DMD5 -DSHA1 -DRMD160 -DSHA256 DPADD= ${LIBMD} LDADD= -lmd +.if ${MK_NMTREE} == "no" +LINKS= ${BINDIR}/fmtree ${BINDIR}/mtree +MLINKS= fmtree.8 mtree.8 +.endif + +CLEANFILES+= fmtree.8 + +fmtree.8: mtree.8 + cp ${.ALLSRC} ${.TARGET} + .include <bsd.prog.mk> diff --git a/usr.sbin/ndp/ndp.8 b/usr.sbin/ndp/ndp.8 index 9eabfe4..223cfba 100644 --- a/usr.sbin/ndp/ndp.8 +++ b/usr.sbin/ndp/ndp.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 9, 2012 +.Dd Jan 10, 2013 .Dt NDP 8 .Os .\" @@ -192,6 +192,15 @@ on This flag is set by .Va net.inet6.ip6.auto_linklocal sysctl variable. +.It Ic no_prefer_iface +The address on the outgoing interface is preferred by source addess +selection rule. +If this flag is set, stop treating the address on the +.Ar interface +as special even when the +.Ar interface +is outgoing interface. +The default value of this flag is off. .It Ic disabled Disable IPv6 operation on the interface. When disabled, the interface discards any IPv6 packets diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c index b50ddb7..866da76 100644 --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -982,6 +982,9 @@ ifinfo(ifname, argc, argv) #ifdef ND6_IFF_AUTO_LINKLOCAL SETFLAG("auto_linklocal", ND6_IFF_AUTO_LINKLOCAL); #endif +#ifdef ND6_IFF_NO_PREFER_IFACE + SETFLAG("no_prefer_iface", ND6_IFF_NO_PREFER_IFACE); +#endif SETVALUE("basereachable", ND.basereachable); SETVALUE("retrans", ND.retrans); SETVALUE("curhlim", ND.chlim); @@ -1055,6 +1058,10 @@ ifinfo(ifname, argc, argv) if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL)) printf("auto_linklocal "); #endif +#ifdef ND6_IFF_NO_PREFER_IFACE + if ((ND.flags & ND6_IFF_NO_PREFER_IFACE)) + printf("no_prefer_iface "); +#endif } putc('\n', stdout); #undef ND diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile index 58e46ea..1b8cc01 100644 --- a/usr.sbin/nmtree/Makefile +++ b/usr.sbin/nmtree/Makefile @@ -20,6 +20,13 @@ LIBNETBSD= ${LIBNETBSDDIR}/libnetbsd.a DPADD+= ${LIBNETBSD} LDADD+= ${LIBNETBSD} +.if ${MK_NMTREE} != "no" +LINKS= ${BINDIR}/nmtree ${BINDIR}/mtree +MLINKS= nmtree.8 mtree.8 +.endif + +CLEANFILES+= nmtree.8 + nmtree.8: mtree.8 cp ${.ALLSRC} ${.TARGET} diff --git a/usr.sbin/pkg/dns_utils.c b/usr.sbin/pkg/dns_utils.c index e88bf98..239be90 100644 --- a/usr.sbin/pkg/dns_utils.c +++ b/usr.sbin/pkg/dns_utils.c @@ -66,10 +66,9 @@ dns_getsrvinfo(const char *zone) p += len + NS_QFIXEDSZ; } - res = malloc(sizeof(struct dns_srvinfo) * ancount); + res = calloc(ancount, sizeof(struct dns_srvinfo)); if (res == NULL) return (NULL); - memset(res, 0, sizeof(struct dns_srvinfo) * ancount); n = 0; while (ancount > 0 && p < end) { diff --git a/usr.sbin/pw/pw_log.c b/usr.sbin/pw/pw_log.c index f16274f..b774423 100644 --- a/usr.sbin/pw/pw_log.c +++ b/usr.sbin/pw/pw_log.c @@ -47,7 +47,6 @@ pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...) } if (logfile != NULL) { va_list argp; - int l; time_t now = time(NULL); struct tm *t = localtime(&now); char nfmt[256]; @@ -57,7 +56,6 @@ pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...) name = "unknown"; /* ISO 8601 International Standard Date format */ strftime(nfmt, sizeof nfmt, "%Y-%m-%d %T ", t); - l = strlen(nfmt); sprintf(nfmt + strlen(nfmt), "[%s:%s%s] %s\n", name, Which[which], Modes[mode], fmt); va_start(argp, fmt); vfprintf(logfile, nfmt, argp); |