diff --git a/Makefile.inc1 b/Makefile.inc1 index dc6c721caf60..be497d2b90fb 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -543,8 +543,8 @@ HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCXXFLAGS} ${XCFLAGS}" \ CPP="${XCPP} ${XCFLAGS}" \ - AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \ - OBJCOPY="${XOBJCOPY}" \ + AS="${XAS}" AR="${XAR}" LD="${XLD}" LLVM_LINK="${XLLVM_LINK}" \ + NM=${XNM} OBJCOPY="${XOBJCOPY}" \ RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \ SIZE="${XSIZE}" diff --git a/contrib/hyperv/tools/hv_kvp_daemon.c b/contrib/hyperv/tools/hv_kvp_daemon.c index 9b9e3a6feb92..50bd27628b30 100644 --- a/contrib/hyperv/tools/hv_kvp_daemon.c +++ b/contrib/hyperv/tools/hv_kvp_daemon.c @@ -52,9 +52,10 @@ #include #include #include +#include #include "hv_kvp.h" - +#include "hv_utilreg.h" typedef uint8_t __u8; typedef uint16_t __u16; typedef uint32_t __u32; @@ -684,18 +685,16 @@ kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer) */ kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); - /* * Retrieve the IPV6 address of default gateway. */ - snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name); + snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }'", if_name); /* * Execute the command to gather gateway IPV6 info. */ kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); - /* * we just invoke an external script to get the DNS info. * @@ -782,11 +781,11 @@ kvp_process_ip_address(void *addrp, } if ((length - *offset) < addr_length + 1) { - return (HV_KVP_E_FAIL); + return (EINVAL); } if (str == NULL) { strlcpy(buffer, "inet_ntop failed\n", length); - return (HV_KVP_E_FAIL); + return (errno); } if (*offset == 0) { strlcpy(buffer, tmp, length); @@ -832,7 +831,7 @@ kvp_get_ip_info(int family, char *if_name, int op, if (getifaddrs(&ifap)) { strlcpy(buffer, "getifaddrs failed\n", buffer_length); - return (HV_KVP_E_FAIL); + return (errno); } curp = ifap; @@ -924,7 +923,6 @@ kvp_get_ip_info(int family, char *if_name, int op, /* * Collect other ip configuration info. */ - kvp_get_ipconfig_info(if_name, ip_buffer); } @@ -954,7 +952,7 @@ kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3) ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); if (ret < 0) { - return (HV_KVP_E_FAIL); + return (EIO); } return (0); @@ -979,7 +977,7 @@ kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) if (file == NULL) { KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); - return (HV_KVP_E_FAIL); + return (errno); } /* @@ -988,7 +986,7 @@ kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) mac_addr = kvp_if_name_to_mac(if_name); if (mac_addr == NULL) { - error = HV_KVP_E_FAIL; + error = EINVAL; goto kvp_set_ip_info_error; } /* MAC Address */ @@ -1091,28 +1089,30 @@ kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused) { struct hv_kvp_ipaddr_value *ip_val; char *if_name; + int error = 0; assert(op_msg != NULL); KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); ip_val = &op_msg->body.kvp_ip_val; - op_msg->hdr.error = HV_KVP_S_OK; + op_msg->hdr.error = HV_S_OK; if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id); if (if_name == NULL) { /* No interface found with the mac address. */ - op_msg->hdr.error = HV_KVP_E_FAIL; + op_msg->hdr.error = HV_E_FAIL; goto kvp_op_getipinfo_done; } - op_msg->hdr.error = kvp_get_ip_info(0, if_name, + error = kvp_get_ip_info(0, if_name, HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2)); - + if (error) + op_msg->hdr.error = HV_E_FAIL; free(if_name); kvp_op_getipinfo_done: - return(op_msg->hdr.error); + return (error); } @@ -1121,25 +1121,27 @@ kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused) { struct hv_kvp_ipaddr_value *ip_val; char *if_name; + int error = 0; assert(op_msg != NULL); KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); ip_val = &op_msg->body.kvp_ip_val; - op_msg->hdr.error = HV_KVP_S_OK; + op_msg->hdr.error = HV_S_OK; if_name = (char *)ip_val->adapter_id; if (if_name == NULL) { /* No adapter provided. */ - op_msg->hdr.error = HV_KVP_GUID_NOTFOUND; + op_msg->hdr.error = HV_GUID_NOTFOUND; goto kvp_op_setipinfo_done; } - op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val); - + error = kvp_set_ip_info(if_name, ip_val); + if (error) + op_msg->hdr.error = HV_E_FAIL; kvp_op_setipinfo_done: - return(op_msg->hdr.error); + return (error); } @@ -1154,7 +1156,7 @@ kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) assert(op_hdlr != NULL); op_pool = op_msg->hdr.kvp_hdr.pool; - op_msg->hdr.error = HV_KVP_S_OK; + op_msg->hdr.error = HV_S_OK; switch(op_hdlr->kvp_op_key) { case HV_KVP_OP_SET: @@ -1198,8 +1200,7 @@ kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) } if (error != 0) - op_msg->hdr.error = HV_KVP_S_CONT; - + op_msg->hdr.error = HV_S_CONT; return(error); } @@ -1216,7 +1217,7 @@ kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) op = op_msg->hdr.kvp_hdr.operation; op_pool = op_msg->hdr.kvp_hdr.pool; - op_msg->hdr.error = HV_KVP_S_OK; + op_msg->hdr.error = HV_S_OK; /* * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate @@ -1229,7 +1230,7 @@ kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) HV_KVP_EXCHANGE_MAX_KEY_SIZE, op_msg->body.kvp_enum_data.data.msg_value.value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { - op_msg->hdr.error = HV_KVP_S_CONT; + op_msg->hdr.error = HV_S_CONT; error = -1; } goto kvp_op_enumerate_done; @@ -1298,12 +1299,14 @@ kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n", op_msg->body.kvp_enum_data.index); #endif - op_msg->hdr.error = HV_KVP_S_CONT; + op_msg->hdr.error = HV_S_CONT; error = -1; break; } kvp_op_enumerate_done: + if (error != 0) + op_msg->hdr.error = HV_S_CONT; return(error); } @@ -1496,10 +1499,13 @@ main(int argc, char *argv[]) */ error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, (void *)&kvp_op_hdlrs[op]); - if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT) - KVP_LOG(LOG_WARNING, - "Operation failed OP = %d, error = 0x%x\n", - op, error); + if (error != 0) { + assert(hv_msg->hdr.error != HV_S_OK); + if (hv_msg->hdr.error != HV_S_CONT) + KVP_LOG(LOG_WARNING, + "Operation failed OP = %d, error = 0x%x\n", + op, error); + } } /* diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c index d371f47c48dd..9c9f56228ea5 100644 --- a/crypto/openssh/kex.c +++ b/crypto/openssh/kex.c @@ -468,6 +468,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt) if (kex == NULL) return SSH_ERR_INVALID_ARGUMENT; + ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; diff --git a/etc/Makefile b/etc/Makefile index b41a806a41e3..fe518d283d19 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -459,7 +459,7 @@ distrib-dirs: ${MTREES:N/*} distrib-cleanup .PHONY .endif etc-examples-install: ${META_DEPS} - cd ${.CURDIR}; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + cd ${.CURDIR}; ${INSTALL} ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 \ ${BIN1} ${BIN2} nsmb.conf opieaccess \ ${DESTDIR}${SHAREDIR}/examples/etc diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index 3a7bdeb6d4a8..6e336ee6065e 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -78,6 +78,8 @@ .. ssl .. + syslog.d + .. zfs .. .. diff --git a/etc/syslog.conf b/etc/syslog.conf index e65db5347bc5..a137bdcae65f 100644 --- a/etc/syslog.conf +++ b/etc/syslog.conf @@ -34,3 +34,5 @@ cron.* /var/log/cron !ppp *.* /var/log/ppp.log !* +include /etc/syslog.d +include /usr/local/etc/syslog.d diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile index fba02ed935df..6c32c367829f 100644 --- a/gnu/lib/libgcc/Makefile +++ b/gnu/lib/libgcc/Makefile @@ -397,11 +397,11 @@ _libinstall: _lib-eh-install _lib-eh-install: .if ${MK_INSTALLLIB} != "no" - ${INSTALL} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ + ${INSTALL} ${TAG_ARGS} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ ${_INSTALLFLAGS} libgcc_eh.a ${DESTDIR}${LIBDIR} .endif .if ${MK_PROFILE} != "no" - ${INSTALL} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ + ${INSTALL} ${TAG_ARGS} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ ${_INSTALLFLAGS} libgcc_eh_p.a ${DESTDIR}${LIBDIR} .endif diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c index fcbce98b451e..045b847bd29a 100644 --- a/lib/libc/locale/collate.c +++ b/lib/libc/locale/collate.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include "un-namespace.h" +#include "endian.h" #include "collate.h" #include "setlocale.h" #include "ldpart.h" @@ -160,7 +161,7 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) if ((info->directive_count < 1) || (info->directive_count >= COLL_WEIGHTS_MAX) || - ((chains = info->chain_count) < 0)) { + ((chains = BSWAP(info->chain_count)) < 0)) { (void) munmap(map, sbuf.st_size); errno = EINVAL; return (_LDP_ERROR); @@ -168,9 +169,9 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) + (sizeof (collate_chain_t) * chains) + - (sizeof (collate_large_t) * info->large_count); + (sizeof (collate_large_t) * BSWAP(info->large_count)); for (z = 0; z < info->directive_count; z++) { - i += sizeof (collate_subst_t) * info->subst_count[z]; + i += sizeof (collate_subst_t) * BSWAP(info->subst_count[z]); } if (i != (sbuf.st_size - (TMP - map))) { (void) munmap(map, sbuf.st_size); @@ -183,9 +184,9 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1); for (z = 0; z < info->directive_count; z++) { - if (info->subst_count[z] > 0) { + if (BSWAP(info->subst_count[z]) > 0) { table->subst_table[z] = (void *)TMP; - TMP += info->subst_count[z] * sizeof (collate_subst_t); + TMP += BSWAP(info->subst_count[z]) * sizeof (collate_subst_t); } else { table->subst_table[z] = NULL; } @@ -196,7 +197,7 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) TMP += chains * sizeof (collate_chain_t); } else table->chain_pri_table = NULL; - if (info->large_count > 0) + if (BSWAP(info->large_count) > 0) table->large_pri_table = (void *)TMP; else table->large_pri_table = NULL; @@ -209,7 +210,7 @@ static const int32_t * substsearch(struct xlocale_collate *table, const wchar_t key, int pass) { const collate_subst_t *p; - int n = table->info->subst_count[pass]; + int n = BSWAP(table->info->subst_count[pass]); if (n == 0) return (NULL); @@ -221,7 +222,8 @@ substsearch(struct xlocale_collate *table, const wchar_t key, int pass) return (NULL); p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY); - assert(p->key == key); + assert(BSWAP(p->key) == key); + return (p->pri); } @@ -229,7 +231,7 @@ static collate_chain_t * chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) { int low = 0; - int high = table->info->chain_count - 1;; + int high = BSWAP(table->info->chain_count) - 1; int next, compar, l; collate_chain_t *p; collate_chain_t *tab = table->chain_pri_table; @@ -240,7 +242,7 @@ chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) while (low <= high) { next = (low + high) / 2; p = tab + next; - compar = *key - *p->str; + compar = *key - le16toh(*p->str); if (compar == 0) { l = wcsnlen(p->str, COLLATE_STR_LEN); compar = wcsncmp(key, p->str, l); @@ -261,7 +263,7 @@ static collate_large_t * largesearch(struct xlocale_collate *table, const wchar_t key) { int low = 0; - int high = table->info->large_count - 1; + int high = BSWAP(table->info->large_count) - 1; int next, compar; collate_large_t *p; collate_large_t *tab = table->large_pri_table; @@ -272,7 +274,7 @@ largesearch(struct xlocale_collate *table, const wchar_t key) while (low <= high) { next = (low + high) / 2; p = tab + next; - compar = key - p->val; + compar = key - BSWAP(p->val); if (compar == 0) return (p); if (compar > 0) @@ -337,15 +339,15 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, * Character is a small (8-bit) character. * We just look these up directly for speed. */ - *pri = table->char_pri_table[*t].pri[which]; + *pri = BSWAP(table->char_pri_table[*t].pri[which]); - } else if ((table->info->large_count > 0) && + } else if ((BSWAP(table->info->large_count) > 0) && ((match = largesearch(table, *t)) != NULL)) { /* * Character was found in the extended table. */ - *pri = match->pri.pri[which]; + *pri = BSWAP(match->pri.pri[which]); } else { /* @@ -355,7 +357,7 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, /* Mask off sign bit to prevent ordering confusion. */ *pri = (*t & COLLATE_MAX_PRIORITY); } else { - *pri = table->info->undef_pri[which]; + *pri = BSWAP(table->info->undef_pri[which]); } /* No substitutions for undefined characters! */ return; @@ -374,9 +376,9 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, * code ensures this for us. */ if ((sptr = substsearch(table, *pri, which)) != NULL) { - if ((*pri = *sptr) > 0) { + if ((*pri = BSWAP(*sptr)) > 0) { sptr++; - *state = *sptr ? sptr : NULL; + *state = BSWAP(*sptr) ? sptr : NULL; } } @@ -518,7 +520,7 @@ static int xfrm(struct xlocale_collate *table, unsigned char *p, int pri, int pass) { /* we use unsigned to ensure zero fill on right shift */ - uint32_t val = (uint32_t)table->info->pri_count[pass]; + uint32_t val = BSWAP((uint32_t)table->info->pri_count[pass]); int nc = 0; while (val) { @@ -678,7 +680,7 @@ __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len) e = -1; if (*str <= UCHAR_MAX) e = table->char_pri_table[*str].pri[0]; - else if (table->info->large_count > 0) { + else if (BSWAP(table->info->large_count) > 0) { collate_large_t *match_large; match_large = largesearch(table, *str); if (match_large) @@ -688,7 +690,7 @@ __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len) return (1); return (e > 0 ? e : 0); } - if (table->info->chain_count > 0) { + if (BSWAP(table->info->chain_count) > 0) { wchar_t name[COLLATE_STR_LEN]; collate_chain_t *match_chain; int clen; diff --git a/lib/libc/locale/endian.h b/lib/libc/locale/endian.h new file mode 100644 index 000000000000..d3b822788688 --- /dev/null +++ b/lib/libc/locale/endian.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were 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. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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$ + */ + +#include + +/* + * We assume locale files were generated on EL machine + * (e.g. during cross build on amd64 host), but used on EB + * machine (e.g. MIPS64EB), so convert it to host endianness. + * + * TODO: detect host endianness on the build machine and use + * correct macros here. + */ + +#if BYTE_ORDER == BIG_ENDIAN && defined(__mips__) +#define BSWAP(x) le32toh(x) +#else +#define BSWAP(x) x +#endif diff --git a/lib/libc/locale/rune.c b/lib/libc/locale/rune.c index 00ef19b781fa..0b835f34ba07 100644 --- a/lib/libc/locale/rune.c +++ b/lib/libc/locale/rune.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include "un-namespace.h" +#include "endian.h" #include "runefile.h" _RuneLocale * @@ -107,29 +108,29 @@ _Read_RuneMagi(const char *fname) } runetype_ext_ranges = (_FileRuneEntry *)variable; - variable = runetype_ext_ranges + frl->runetype_ext_nranges; + variable = runetype_ext_ranges + BSWAP(frl->runetype_ext_nranges); if (variable > lastp) { goto invalid; } maplower_ext_ranges = (_FileRuneEntry *)variable; - variable = maplower_ext_ranges + frl->maplower_ext_nranges; + variable = maplower_ext_ranges + BSWAP(frl->maplower_ext_nranges); if (variable > lastp) { goto invalid; } mapupper_ext_ranges = (_FileRuneEntry *)variable; - variable = mapupper_ext_ranges + frl->mapupper_ext_nranges; + variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); if (variable > lastp) { goto invalid; } frr = runetype_ext_ranges; - for (x = 0; x < frl->runetype_ext_nranges; ++x) { + for (x = 0; x < BSWAP(frl->runetype_ext_nranges); ++x) { uint32_t *types; - if (frr[x].map == 0) { - int len = frr[x].max - frr[x].min + 1; + if (BSWAP(frr[x].map) == 0) { + int len = BSWAP(frr[x].max) - BSWAP(frr[x].min) + 1; types = variable; variable = types + len; runetype_ext_len += len; @@ -139,7 +140,7 @@ _Read_RuneMagi(const char *fname) } } - if ((char *)variable + frl->variable_len > (char *)lastp) { + if ((char *)variable + BSWAP(frl->variable_len) > (char *)lastp) { goto invalid; } @@ -147,10 +148,10 @@ _Read_RuneMagi(const char *fname) * Convert from disk format to host format. */ data = malloc(sizeof(_RuneLocale) + - (frl->runetype_ext_nranges + frl->maplower_ext_nranges + - frl->mapupper_ext_nranges) * sizeof(_RuneEntry) + + (BSWAP(frl->runetype_ext_nranges) + BSWAP(frl->maplower_ext_nranges) + + BSWAP(frl->mapupper_ext_nranges)) * sizeof(_RuneEntry) + runetype_ext_len * sizeof(*rr->__types) + - frl->variable_len); + BSWAP(frl->variable_len)); if (data == NULL) { saverr = errno; munmap(fdata, sb.st_size); @@ -164,15 +165,15 @@ _Read_RuneMagi(const char *fname) memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic)); memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); - rl->__variable_len = frl->variable_len; - rl->__runetype_ext.__nranges = frl->runetype_ext_nranges; - rl->__maplower_ext.__nranges = frl->maplower_ext_nranges; - rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges; + rl->__variable_len = BSWAP(frl->variable_len); + rl->__runetype_ext.__nranges = BSWAP(frl->runetype_ext_nranges); + rl->__maplower_ext.__nranges = BSWAP(frl->maplower_ext_nranges); + rl->__mapupper_ext.__nranges = BSWAP(frl->mapupper_ext_nranges); for (x = 0; x < _CACHED_RUNES; ++x) { - rl->__runetype[x] = frl->runetype[x]; - rl->__maplower[x] = frl->maplower[x]; - rl->__mapupper[x] = frl->mapupper[x]; + rl->__runetype[x] = BSWAP(frl->runetype[x]); + rl->__maplower[x] = BSWAP(frl->maplower[x]); + rl->__mapupper[x] = BSWAP(frl->mapupper[x]); } rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; @@ -187,15 +188,15 @@ _Read_RuneMagi(const char *fname) rl->__variable = rl->__mapupper_ext.__ranges + rl->__mapupper_ext.__nranges; - variable = mapupper_ext_ranges + frl->mapupper_ext_nranges; + variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); frr = runetype_ext_ranges; rr = rl->__runetype_ext.__ranges; for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { uint32_t *types; - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); if (rr[x].__map == 0) { int len = rr[x].__max - rr[x].__min + 1; types = variable; @@ -211,17 +212,17 @@ _Read_RuneMagi(const char *fname) frr = maplower_ext_ranges; rr = rl->__maplower_ext.__ranges; for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); } frr = mapupper_ext_ranges; rr = rl->__mapupper_ext.__ranges; for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); } memcpy(rl->__variable, variable, rl->__variable_len); diff --git a/lib/msun/ld80/k_expl.h b/lib/msun/ld80/k_expl.h index 9b081faf0331..1c2213e023da 100644 --- a/lib/msun/ld80/k_expl.h +++ b/lib/msun/ld80/k_expl.h @@ -75,140 +75,140 @@ static const struct { double hi; double lo; } tbl[INTERVALS] = { - 0x1p+0, 0x0p+0, + { 0x1p+0, 0x0p+0 }, /* * XXX hi is rounded down, and the formatting is not quite normal. * But I rather like both. The 0x1.*p format is good for 4N+1 * mantissa bits. Rounding down makes the lo terms positive, * so that the columnar formatting can be simpler. */ - 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54, - 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53, - 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53, - 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55, - 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53, - 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57, - 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54, - 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54, - 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54, - 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59, - 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53, - 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53, - 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53, - 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53, - 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55, - 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53, - 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53, - 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55, - 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53, - 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54, - 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53, - 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55, - 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55, - 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54, - 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55, - 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55, - 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53, - 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55, - 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53, - 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54, - 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56, - 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55, - 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55, - 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54, - 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53, - 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53, - 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53, - 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53, - 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53, - 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55, - 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53, - 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53, - 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53, - 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59, - 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54, - 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56, - 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54, - 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56, - 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54, - 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53, - 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53, - 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53, - 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53, - 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54, - 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55, - 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54, - 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60, - 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54, - 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53, - 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53, - 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53, - 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53, - 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57, - 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53, - 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53, - 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53, - 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53, - 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53, - 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53, - 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53, - 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54, - 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53, - 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54, - 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56, - 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53, - 0x1.82589994cce12p+0, 0x1.159f115f56694p-53, - 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53, - 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53, - 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54, - 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54, - 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53, - 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55, - 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53, - 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53, - 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53, - 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53, - 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53, - 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56, - 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56, - 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53, - 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54, - 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53, - 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54, - 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54, - 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53, - 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54, - 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53, - 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53, - 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53, - 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53, - 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53, - 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55, - 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53, - 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55, - 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54, - 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54, - 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56, - 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56, - 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53, - 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53, - 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53, - 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55, - 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53, - 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54, - 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54, - 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53, - 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53, - 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55, - 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54, - 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53, - 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53, - 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54, - 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54, - 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54, - 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53, - 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55, - 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 + { 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54 }, + { 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53 }, + { 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53 }, + { 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55 }, + { 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53 }, + { 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57 }, + { 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54 }, + { 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54 }, + { 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54 }, + { 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59 }, + { 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53 }, + { 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53 }, + { 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53 }, + { 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53 }, + { 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55 }, + { 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53 }, + { 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53 }, + { 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55 }, + { 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53 }, + { 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54 }, + { 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53 }, + { 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55 }, + { 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55 }, + { 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54 }, + { 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55 }, + { 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55 }, + { 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53 }, + { 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55 }, + { 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53 }, + { 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54 }, + { 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56 }, + { 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55 }, + { 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55 }, + { 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54 }, + { 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53 }, + { 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53 }, + { 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53 }, + { 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53 }, + { 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53 }, + { 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55 }, + { 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53 }, + { 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53 }, + { 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53 }, + { 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59 }, + { 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54 }, + { 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56 }, + { 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54 }, + { 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56 }, + { 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54 }, + { 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53 }, + { 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53 }, + { 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53 }, + { 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53 }, + { 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54 }, + { 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55 }, + { 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54 }, + { 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60 }, + { 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54 }, + { 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53 }, + { 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53 }, + { 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53 }, + { 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53 }, + { 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57 }, + { 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53 }, + { 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53 }, + { 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53 }, + { 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53 }, + { 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53 }, + { 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53 }, + { 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53 }, + { 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54 }, + { 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53 }, + { 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54 }, + { 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56 }, + { 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53 }, + { 0x1.82589994cce12p+0, 0x1.159f115f56694p-53 }, + { 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53 }, + { 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53 }, + { 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54 }, + { 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54 }, + { 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53 }, + { 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55 }, + { 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53 }, + { 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53 }, + { 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53 }, + { 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53 }, + { 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53 }, + { 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56 }, + { 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56 }, + { 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53 }, + { 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54 }, + { 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53 }, + { 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54 }, + { 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54 }, + { 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53 }, + { 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54 }, + { 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53 }, + { 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53 }, + { 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53 }, + { 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53 }, + { 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53 }, + { 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55 }, + { 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53 }, + { 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55 }, + { 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54 }, + { 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54 }, + { 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56 }, + { 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56 }, + { 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53 }, + { 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53 }, + { 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53 }, + { 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55 }, + { 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53 }, + { 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54 }, + { 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54 }, + { 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53 }, + { 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53 }, + { 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55 }, + { 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54 }, + { 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53 }, + { 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53 }, + { 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54 }, + { 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54 }, + { 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54 }, + { 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53 }, + { 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55 }, + { 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 } }; /* diff --git a/lib/msun/ld80/s_logl.c b/lib/msun/ld80/s_logl.c index 3a35753299b1..e0daed740de8 100644 --- a/lib/msun/ld80/s_logl.c +++ b/lib/msun/ld80/s_logl.c @@ -152,135 +152,135 @@ static const struct { * mainly to minimize the size of the table. Using all 24 bits * in a float for it automatically satisfies the above constraints. */ - 0x800000.0p-23, 0, 0, - 0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6675.0p-84, - 0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83718.0p-84, - 0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173698.0p-83, - 0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e79.0p-82, - 0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82, - 0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a1076.0p-83, - 0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb9589.0p-82, - 0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c5.0p-91, - 0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560e.0p-81, - 0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d503.0p-82, - 0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83, - 0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da9a.0p-81, - 0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83, - 0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251af0.0p-85, - 0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d5.0p-84, - 0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e676.0p-81, - 0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f42.0p-82, - 0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6b00.0p-80, - 0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83, - 0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82, - 0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80, - 0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c47.0p-82, - 0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e569.0p-81, - 0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba936770.0p-84, - 0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d32.0p-80, - 0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b7.0p-81, - 0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06.0p-80, - 0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82, - 0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d6866.0p-81, - 0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae55.0p-80, - 0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc45954.0p-81, - 0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d.0p-81, - 0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df842.0p-85, - 0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe.0p-87, - 0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa69.0p-81, - 0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb3283.0p-80, - 0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e.0p-79, - 0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f46.0p-79, - 0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a.0p-81, - 0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de9.0p-79, - 0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5148.0p-81, - 0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba4.0p-79, - 0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b731.0p-80, - 0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81, - 0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79, - 0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c566.0p-79, - 0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb24.0p-81, - 0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698.0p-81, - 0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123616.0p-82, - 0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b2.0p-80, - 0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a424234.0p-79, - 0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83, - 0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770634.0p-79, - 0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b152.0p-82, - 0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f09.0p-80, - 0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad89.0p-79, - 0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf.0p-79, - 0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab90486409.0p-80, - 0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333.0p-79, - 0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80, - 0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c9.0p-80, - 0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79, - 0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a87.0p-81, - 0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3cb.0p-79, - 0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d.0p-81, - 0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81, - 0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79, - 0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b61.0p-80, - 0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a3.0p-80, - 0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82, - 0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80, - 0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f57.0p-80, - 0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80, - 0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d4.0p-80, - 0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd.0p-79, - 0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f730190.0p-79, - 0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cd.0p-80, - 0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d.0p-81, - 0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af2.0p-79, - 0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84, - 0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade0.0p-79, - 0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1.0p-79, - 0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c53.0p-79, - 0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f.0p-78, - 0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e5.0p-81, - 0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b.0p-79, - 0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb8287.0p-78, - 0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9c.0p-78, - 0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f0.0p-79, - 0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd6.0p-80, - 0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de.0p-78, - 0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78, - 0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79, - 0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79, - 0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f77.0p-78, - 0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80, - 0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d7.0p-79, - 0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3237.0p-79, - 0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d.0p-79, - 0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c337.0p-79, - 0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf3.0p-78, - 0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79, - 0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507c.0p-78, - 0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e98.0p-79, - 0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78, - 0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f952.0p-78, - 0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe.0p-78, - 0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576b.0p-78, - 0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a2.0p-79, - 0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79, - 0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f.0p-81, - 0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79, - 0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d20.0p-78, - 0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c01.0p-79, - 0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541ad.0p-79, - 0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4572.0p-78, - 0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c.0p-80, - 0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d74936.0p-80, - 0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce53266.0p-79, - 0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d2.0p-79, - 0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b36.0p-80, - 0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3.0p-79, - 0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80, - 0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80, - 0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a83.0p-81, - 0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b.0p-78, - 0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a198.0p-78, - 0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c39.0p-81, + { 0x800000.0p-23, 0, 0 }, + { 0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6675.0p-84 }, + { 0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83718.0p-84 }, + { 0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173698.0p-83 }, + { 0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e79.0p-82 }, + { 0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82 }, + { 0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a1076.0p-83 }, + { 0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb9589.0p-82 }, + { 0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c5.0p-91 }, + { 0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560e.0p-81 }, + { 0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d503.0p-82 }, + { 0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83 }, + { 0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da9a.0p-81 }, + { 0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83 }, + { 0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251af0.0p-85 }, + { 0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d5.0p-84 }, + { 0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e676.0p-81 }, + { 0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f42.0p-82 }, + { 0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6b00.0p-80 }, + { 0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83 }, + { 0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82 }, + { 0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80 }, + { 0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c47.0p-82 }, + { 0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e569.0p-81 }, + { 0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba936770.0p-84 }, + { 0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d32.0p-80 }, + { 0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b7.0p-81 }, + { 0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06.0p-80 }, + { 0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82 }, + { 0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d6866.0p-81 }, + { 0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae55.0p-80 }, + { 0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc45954.0p-81 }, + { 0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d.0p-81 }, + { 0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df842.0p-85 }, + { 0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe.0p-87 }, + { 0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa69.0p-81 }, + { 0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb3283.0p-80 }, + { 0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e.0p-79 }, + { 0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f46.0p-79 }, + { 0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a.0p-81 }, + { 0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de9.0p-79 }, + { 0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5148.0p-81 }, + { 0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba4.0p-79 }, + { 0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b731.0p-80 }, + { 0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81 }, + { 0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79 }, + { 0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c566.0p-79 }, + { 0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb24.0p-81 }, + { 0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698.0p-81 }, + { 0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123616.0p-82 }, + { 0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b2.0p-80 }, + { 0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a424234.0p-79 }, + { 0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83 }, + { 0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770634.0p-79 }, + { 0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b152.0p-82 }, + { 0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f09.0p-80 }, + { 0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad89.0p-79 }, + { 0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf.0p-79 }, + { 0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab90486409.0p-80 }, + { 0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333.0p-79 }, + { 0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80 }, + { 0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c9.0p-80 }, + { 0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79 }, + { 0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a87.0p-81 }, + { 0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3cb.0p-79 }, + { 0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d.0p-81 }, + { 0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81 }, + { 0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79 }, + { 0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b61.0p-80 }, + { 0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a3.0p-80 }, + { 0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82 }, + { 0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80 }, + { 0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f57.0p-80 }, + { 0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80 }, + { 0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d4.0p-80 }, + { 0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd.0p-79 }, + { 0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f730190.0p-79 }, + { 0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cd.0p-80 }, + { 0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d.0p-81 }, + { 0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af2.0p-79 }, + { 0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84 }, + { 0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade0.0p-79 }, + { 0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1.0p-79 }, + { 0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c53.0p-79 }, + { 0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f.0p-78 }, + { 0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e5.0p-81 }, + { 0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b.0p-79 }, + { 0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb8287.0p-78 }, + { 0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9c.0p-78 }, + { 0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f0.0p-79 }, + { 0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd6.0p-80 }, + { 0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de.0p-78 }, + { 0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78 }, + { 0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79 }, + { 0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79 }, + { 0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f77.0p-78 }, + { 0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80 }, + { 0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d7.0p-79 }, + { 0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3237.0p-79 }, + { 0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d.0p-79 }, + { 0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c337.0p-79 }, + { 0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf3.0p-78 }, + { 0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79 }, + { 0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507c.0p-78 }, + { 0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e98.0p-79 }, + { 0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78 }, + { 0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f952.0p-78 }, + { 0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe.0p-78 }, + { 0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576b.0p-78 }, + { 0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a2.0p-79 }, + { 0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79 }, + { 0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f.0p-81 }, + { 0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79 }, + { 0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d20.0p-78 }, + { 0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c01.0p-79 }, + { 0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541ad.0p-79 }, + { 0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4572.0p-78 }, + { 0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c.0p-80 }, + { 0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d74936.0p-80 }, + { 0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce53266.0p-79 }, + { 0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d2.0p-79 }, + { 0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b36.0p-80 }, + { 0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3.0p-79 }, + { 0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80 }, + { 0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80 }, + { 0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a83.0p-81 }, + { 0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b.0p-78 }, + { 0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a198.0p-78 }, + { 0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c39.0p-81 }, }; #ifdef USE_UTAB @@ -288,135 +288,135 @@ static const struct { float H; /* 1 + i/INTERVALS (exact) */ float E; /* H(i) * G(i) - 1 (exact) */ } U[TSIZE] = { - 0x800000.0p-23, 0, - 0x810000.0p-23, -0x800000.0p-37, - 0x820000.0p-23, -0x800000.0p-35, - 0x830000.0p-23, -0x900000.0p-34, - 0x840000.0p-23, -0x800000.0p-33, - 0x850000.0p-23, -0xc80000.0p-33, - 0x860000.0p-23, -0xa00000.0p-36, - 0x870000.0p-23, 0x940000.0p-33, - 0x880000.0p-23, 0x800000.0p-35, - 0x890000.0p-23, -0xc80000.0p-34, - 0x8a0000.0p-23, 0xe00000.0p-36, - 0x8b0000.0p-23, 0x900000.0p-33, - 0x8c0000.0p-23, -0x800000.0p-35, - 0x8d0000.0p-23, -0xe00000.0p-33, - 0x8e0000.0p-23, 0x880000.0p-33, - 0x8f0000.0p-23, -0xa80000.0p-34, - 0x900000.0p-23, -0x800000.0p-35, - 0x910000.0p-23, 0x800000.0p-37, - 0x920000.0p-23, 0x900000.0p-35, - 0x930000.0p-23, 0xd00000.0p-35, - 0x940000.0p-23, 0xe00000.0p-35, - 0x950000.0p-23, 0xc00000.0p-35, - 0x960000.0p-23, 0xe00000.0p-36, - 0x970000.0p-23, -0x800000.0p-38, - 0x980000.0p-23, -0xc00000.0p-35, - 0x990000.0p-23, -0xd00000.0p-34, - 0x9a0000.0p-23, 0x880000.0p-33, - 0x9b0000.0p-23, 0xe80000.0p-35, - 0x9c0000.0p-23, -0x800000.0p-35, - 0x9d0000.0p-23, 0xb40000.0p-33, - 0x9e0000.0p-23, 0x880000.0p-34, - 0x9f0000.0p-23, -0xe00000.0p-35, - 0xa00000.0p-23, 0x800000.0p-33, - 0xa10000.0p-23, -0x900000.0p-36, - 0xa20000.0p-23, -0xb00000.0p-33, - 0xa30000.0p-23, -0xa00000.0p-36, - 0xa40000.0p-23, 0x800000.0p-33, - 0xa50000.0p-23, -0xf80000.0p-35, - 0xa60000.0p-23, 0x880000.0p-34, - 0xa70000.0p-23, -0x900000.0p-33, - 0xa80000.0p-23, -0x800000.0p-35, - 0xa90000.0p-23, 0x900000.0p-34, - 0xaa0000.0p-23, 0xa80000.0p-33, - 0xab0000.0p-23, -0xac0000.0p-34, - 0xac0000.0p-23, -0x800000.0p-37, - 0xad0000.0p-23, 0xf80000.0p-35, - 0xae0000.0p-23, 0xf80000.0p-34, - 0xaf0000.0p-23, -0xac0000.0p-33, - 0xb00000.0p-23, -0x800000.0p-33, - 0xb10000.0p-23, -0xb80000.0p-34, - 0xb20000.0p-23, -0x800000.0p-34, - 0xb30000.0p-23, -0xb00000.0p-35, - 0xb40000.0p-23, -0x800000.0p-35, - 0xb50000.0p-23, -0xe00000.0p-36, - 0xb60000.0p-23, -0x800000.0p-35, - 0xb70000.0p-23, -0xb00000.0p-35, - 0xb80000.0p-23, -0x800000.0p-34, - 0xb90000.0p-23, -0xb80000.0p-34, - 0xba0000.0p-23, -0x800000.0p-33, - 0xbb0000.0p-23, -0xac0000.0p-33, - 0xbc0000.0p-23, 0x980000.0p-33, - 0xbd0000.0p-23, 0xbc0000.0p-34, - 0xbe0000.0p-23, 0xe00000.0p-36, - 0xbf0000.0p-23, -0xb80000.0p-35, - 0xc00000.0p-23, -0x800000.0p-33, - 0xc10000.0p-23, 0xa80000.0p-33, - 0xc20000.0p-23, 0x900000.0p-34, - 0xc30000.0p-23, -0x800000.0p-35, - 0xc40000.0p-23, -0x900000.0p-33, - 0xc50000.0p-23, 0x820000.0p-33, - 0xc60000.0p-23, 0x800000.0p-38, - 0xc70000.0p-23, -0x820000.0p-33, - 0xc80000.0p-23, 0x800000.0p-33, - 0xc90000.0p-23, -0xa00000.0p-36, - 0xca0000.0p-23, -0xb00000.0p-33, - 0xcb0000.0p-23, 0x840000.0p-34, - 0xcc0000.0p-23, -0xd00000.0p-34, - 0xcd0000.0p-23, 0x800000.0p-33, - 0xce0000.0p-23, -0xe00000.0p-35, - 0xcf0000.0p-23, 0xa60000.0p-33, - 0xd00000.0p-23, -0x800000.0p-35, - 0xd10000.0p-23, 0xb40000.0p-33, - 0xd20000.0p-23, -0x800000.0p-35, - 0xd30000.0p-23, 0xaa0000.0p-33, - 0xd40000.0p-23, -0xe00000.0p-35, - 0xd50000.0p-23, 0x880000.0p-33, - 0xd60000.0p-23, -0xd00000.0p-34, - 0xd70000.0p-23, 0x9c0000.0p-34, - 0xd80000.0p-23, -0xb00000.0p-33, - 0xd90000.0p-23, -0x800000.0p-38, - 0xda0000.0p-23, 0xa40000.0p-33, - 0xdb0000.0p-23, -0xdc0000.0p-34, - 0xdc0000.0p-23, 0xc00000.0p-35, - 0xdd0000.0p-23, 0xca0000.0p-33, - 0xde0000.0p-23, -0xb80000.0p-34, - 0xdf0000.0p-23, 0xd00000.0p-35, - 0xe00000.0p-23, 0xc00000.0p-33, - 0xe10000.0p-23, -0xf40000.0p-34, - 0xe20000.0p-23, 0x800000.0p-37, - 0xe30000.0p-23, 0x860000.0p-33, - 0xe40000.0p-23, -0xc80000.0p-33, - 0xe50000.0p-23, -0xa80000.0p-34, - 0xe60000.0p-23, 0xe00000.0p-36, - 0xe70000.0p-23, 0x880000.0p-33, - 0xe80000.0p-23, -0xe00000.0p-33, - 0xe90000.0p-23, -0xfc0000.0p-34, - 0xea0000.0p-23, -0x800000.0p-35, - 0xeb0000.0p-23, 0xe80000.0p-35, - 0xec0000.0p-23, 0x900000.0p-33, - 0xed0000.0p-23, 0xe20000.0p-33, - 0xee0000.0p-23, -0xac0000.0p-33, - 0xef0000.0p-23, -0xc80000.0p-34, - 0xf00000.0p-23, -0x800000.0p-35, - 0xf10000.0p-23, 0x800000.0p-35, - 0xf20000.0p-23, 0xb80000.0p-34, - 0xf30000.0p-23, 0x940000.0p-33, - 0xf40000.0p-23, 0xc80000.0p-33, - 0xf50000.0p-23, -0xf20000.0p-33, - 0xf60000.0p-23, -0xc80000.0p-33, - 0xf70000.0p-23, -0xa20000.0p-33, - 0xf80000.0p-23, -0x800000.0p-33, - 0xf90000.0p-23, -0xc40000.0p-34, - 0xfa0000.0p-23, -0x900000.0p-34, - 0xfb0000.0p-23, -0xc80000.0p-35, - 0xfc0000.0p-23, -0x800000.0p-35, - 0xfd0000.0p-23, -0x900000.0p-36, - 0xfe0000.0p-23, -0x800000.0p-37, - 0xff0000.0p-23, -0x800000.0p-39, - 0x800000.0p-22, 0, + { 0x800000.0p-23, 0 }, + { 0x810000.0p-23, -0x800000.0p-37 }, + { 0x820000.0p-23, -0x800000.0p-35 }, + { 0x830000.0p-23, -0x900000.0p-34 }, + { 0x840000.0p-23, -0x800000.0p-33 }, + { 0x850000.0p-23, -0xc80000.0p-33 }, + { 0x860000.0p-23, -0xa00000.0p-36 }, + { 0x870000.0p-23, 0x940000.0p-33 }, + { 0x880000.0p-23, 0x800000.0p-35 }, + { 0x890000.0p-23, -0xc80000.0p-34 }, + { 0x8a0000.0p-23, 0xe00000.0p-36 }, + { 0x8b0000.0p-23, 0x900000.0p-33 }, + { 0x8c0000.0p-23, -0x800000.0p-35 }, + { 0x8d0000.0p-23, -0xe00000.0p-33 }, + { 0x8e0000.0p-23, 0x880000.0p-33 }, + { 0x8f0000.0p-23, -0xa80000.0p-34 }, + { 0x900000.0p-23, -0x800000.0p-35 }, + { 0x910000.0p-23, 0x800000.0p-37 }, + { 0x920000.0p-23, 0x900000.0p-35 }, + { 0x930000.0p-23, 0xd00000.0p-35 }, + { 0x940000.0p-23, 0xe00000.0p-35 }, + { 0x950000.0p-23, 0xc00000.0p-35 }, + { 0x960000.0p-23, 0xe00000.0p-36 }, + { 0x970000.0p-23, -0x800000.0p-38 }, + { 0x980000.0p-23, -0xc00000.0p-35 }, + { 0x990000.0p-23, -0xd00000.0p-34 }, + { 0x9a0000.0p-23, 0x880000.0p-33 }, + { 0x9b0000.0p-23, 0xe80000.0p-35 }, + { 0x9c0000.0p-23, -0x800000.0p-35 }, + { 0x9d0000.0p-23, 0xb40000.0p-33 }, + { 0x9e0000.0p-23, 0x880000.0p-34 }, + { 0x9f0000.0p-23, -0xe00000.0p-35 }, + { 0xa00000.0p-23, 0x800000.0p-33 }, + { 0xa10000.0p-23, -0x900000.0p-36 }, + { 0xa20000.0p-23, -0xb00000.0p-33 }, + { 0xa30000.0p-23, -0xa00000.0p-36 }, + { 0xa40000.0p-23, 0x800000.0p-33 }, + { 0xa50000.0p-23, -0xf80000.0p-35 }, + { 0xa60000.0p-23, 0x880000.0p-34 }, + { 0xa70000.0p-23, -0x900000.0p-33 }, + { 0xa80000.0p-23, -0x800000.0p-35 }, + { 0xa90000.0p-23, 0x900000.0p-34 }, + { 0xaa0000.0p-23, 0xa80000.0p-33 }, + { 0xab0000.0p-23, -0xac0000.0p-34 }, + { 0xac0000.0p-23, -0x800000.0p-37 }, + { 0xad0000.0p-23, 0xf80000.0p-35 }, + { 0xae0000.0p-23, 0xf80000.0p-34 }, + { 0xaf0000.0p-23, -0xac0000.0p-33 }, + { 0xb00000.0p-23, -0x800000.0p-33 }, + { 0xb10000.0p-23, -0xb80000.0p-34 }, + { 0xb20000.0p-23, -0x800000.0p-34 }, + { 0xb30000.0p-23, -0xb00000.0p-35 }, + { 0xb40000.0p-23, -0x800000.0p-35 }, + { 0xb50000.0p-23, -0xe00000.0p-36 }, + { 0xb60000.0p-23, -0x800000.0p-35 }, + { 0xb70000.0p-23, -0xb00000.0p-35 }, + { 0xb80000.0p-23, -0x800000.0p-34 }, + { 0xb90000.0p-23, -0xb80000.0p-34 }, + { 0xba0000.0p-23, -0x800000.0p-33 }, + { 0xbb0000.0p-23, -0xac0000.0p-33 }, + { 0xbc0000.0p-23, 0x980000.0p-33 }, + { 0xbd0000.0p-23, 0xbc0000.0p-34 }, + { 0xbe0000.0p-23, 0xe00000.0p-36 }, + { 0xbf0000.0p-23, -0xb80000.0p-35 }, + { 0xc00000.0p-23, -0x800000.0p-33 }, + { 0xc10000.0p-23, 0xa80000.0p-33 }, + { 0xc20000.0p-23, 0x900000.0p-34 }, + { 0xc30000.0p-23, -0x800000.0p-35 }, + { 0xc40000.0p-23, -0x900000.0p-33 }, + { 0xc50000.0p-23, 0x820000.0p-33 }, + { 0xc60000.0p-23, 0x800000.0p-38 }, + { 0xc70000.0p-23, -0x820000.0p-33 }, + { 0xc80000.0p-23, 0x800000.0p-33 }, + { 0xc90000.0p-23, -0xa00000.0p-36 }, + { 0xca0000.0p-23, -0xb00000.0p-33 }, + { 0xcb0000.0p-23, 0x840000.0p-34 }, + { 0xcc0000.0p-23, -0xd00000.0p-34 }, + { 0xcd0000.0p-23, 0x800000.0p-33 }, + { 0xce0000.0p-23, -0xe00000.0p-35 }, + { 0xcf0000.0p-23, 0xa60000.0p-33 }, + { 0xd00000.0p-23, -0x800000.0p-35 }, + { 0xd10000.0p-23, 0xb40000.0p-33 }, + { 0xd20000.0p-23, -0x800000.0p-35 }, + { 0xd30000.0p-23, 0xaa0000.0p-33 }, + { 0xd40000.0p-23, -0xe00000.0p-35 }, + { 0xd50000.0p-23, 0x880000.0p-33 }, + { 0xd60000.0p-23, -0xd00000.0p-34 }, + { 0xd70000.0p-23, 0x9c0000.0p-34 }, + { 0xd80000.0p-23, -0xb00000.0p-33 }, + { 0xd90000.0p-23, -0x800000.0p-38 }, + { 0xda0000.0p-23, 0xa40000.0p-33 }, + { 0xdb0000.0p-23, -0xdc0000.0p-34 }, + { 0xdc0000.0p-23, 0xc00000.0p-35 }, + { 0xdd0000.0p-23, 0xca0000.0p-33 }, + { 0xde0000.0p-23, -0xb80000.0p-34 }, + { 0xdf0000.0p-23, 0xd00000.0p-35 }, + { 0xe00000.0p-23, 0xc00000.0p-33 }, + { 0xe10000.0p-23, -0xf40000.0p-34 }, + { 0xe20000.0p-23, 0x800000.0p-37 }, + { 0xe30000.0p-23, 0x860000.0p-33 }, + { 0xe40000.0p-23, -0xc80000.0p-33 }, + { 0xe50000.0p-23, -0xa80000.0p-34 }, + { 0xe60000.0p-23, 0xe00000.0p-36 }, + { 0xe70000.0p-23, 0x880000.0p-33 }, + { 0xe80000.0p-23, -0xe00000.0p-33 }, + { 0xe90000.0p-23, -0xfc0000.0p-34 }, + { 0xea0000.0p-23, -0x800000.0p-35 }, + { 0xeb0000.0p-23, 0xe80000.0p-35 }, + { 0xec0000.0p-23, 0x900000.0p-33 }, + { 0xed0000.0p-23, 0xe20000.0p-33 }, + { 0xee0000.0p-23, -0xac0000.0p-33 }, + { 0xef0000.0p-23, -0xc80000.0p-34 }, + { 0xf00000.0p-23, -0x800000.0p-35 }, + { 0xf10000.0p-23, 0x800000.0p-35 }, + { 0xf20000.0p-23, 0xb80000.0p-34 }, + { 0xf30000.0p-23, 0x940000.0p-33 }, + { 0xf40000.0p-23, 0xc80000.0p-33 }, + { 0xf50000.0p-23, -0xf20000.0p-33 }, + { 0xf60000.0p-23, -0xc80000.0p-33 }, + { 0xf70000.0p-23, -0xa20000.0p-33 }, + { 0xf80000.0p-23, -0x800000.0p-33 }, + { 0xf90000.0p-23, -0xc40000.0p-34 }, + { 0xfa0000.0p-23, -0x900000.0p-34 }, + { 0xfb0000.0p-23, -0xc80000.0p-35 }, + { 0xfc0000.0p-23, -0x800000.0p-35 }, + { 0xfd0000.0p-23, -0x900000.0p-36 }, + { 0xfe0000.0p-23, -0x800000.0p-37 }, + { 0xff0000.0p-23, -0x800000.0p-39 }, + { 0x800000.0p-22, 0 }, }; #endif /* USE_UTAB */ diff --git a/libexec/ftpd/blacklist.c b/libexec/ftpd/blacklist.c index b66a1cd60403..85f90b5352d7 100644 --- a/libexec/ftpd/blacklist.c +++ b/libexec/ftpd/blacklist.c @@ -37,16 +37,20 @@ #include static struct blacklist *blstate; +extern int use_blacklist; void blacklist_init(void) { - blstate = blacklist_open(); + + if (use_blacklist) + blstate = blacklist_open(); } void blacklist_notify(int action, int fd, char *msg) { + if (blstate == NULL) return; (void)blacklist_r(blstate, action, fd, msg); diff --git a/libexec/ftpd/blacklist_client.h b/libexec/ftpd/blacklist_client.h index 596b2bc71a0f..7ac6fd11ed27 100644 --- a/libexec/ftpd/blacklist_client.h +++ b/libexec/ftpd/blacklist_client.h @@ -28,5 +28,26 @@ /* $FreeBSD$ */ -void blacklist_notify(int, int, char *); +#ifndef BLACKLIST_CLIENT_H +#define BLACKLIST_CLIENT_H + +enum { + BLACKLIST_AUTH_OK = 0, + BLACKLIST_AUTH_FAIL +}; + +#ifdef USE_BLACKLIST void blacklist_init(void); +void blacklist_notify(int, int, char *); + +#define BLACKLIST_INIT() blacklist_init() +#define BLACKLIST_NOTIFY(x, y, z) blacklist_notify(x, y, z) + +#else + +#define BLACKLIST_INIT() +#define BLACKLIST_NOTIFY(x, y, z) + +#endif + +#endif /* BLACKLIST_CLIENT_H */ diff --git a/libexec/ftpd/ftpd.8 b/libexec/ftpd/ftpd.8 index 50565e9cd5e1..0cd62899189c 100644 --- a/libexec/ftpd/ftpd.8 +++ b/libexec/ftpd/ftpd.8 @@ -36,7 +36,7 @@ .Nd Internet File Transfer Protocol server .Sh SYNOPSIS .Nm -.Op Fl 468ADdEhMmOoRrSUvW +.Op Fl 468ABDdEhMmOoRrSUvW .Op Fl l Op Fl l .Op Fl a Ar address .Op Fl P Ar port @@ -95,6 +95,14 @@ When .Fl D is specified, accept connections only on the specified .Ar address . +.It Fl B +With this option set, +.Nm +sends authentication success and failure messages to the +.Xr blacklistd 8 +daemon. If this option is not specified, no communcation with the +.Xr blacklistd 8 +daemon is attempted. .It Fl D With this option set, .Nm diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 16c7523b7a0c..95682d5ceb54 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -144,6 +144,7 @@ int noretr = 0; /* RETR command is disabled. */ int noguestretr = 0; /* RETR command is disabled for anon users. */ int noguestmkd = 0; /* MKD command is disabled for anon users. */ int noguestmod = 1; /* anon users may not modify existing files. */ +int use_blacklist = 0; off_t file_size; off_t byte_count; @@ -305,7 +306,7 @@ main(int argc, char *argv[], char **envp) openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); while ((ch = getopt(argc, argv, - "468a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { + "468a:ABdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { switch (ch) { case '4': family = (family == AF_INET6) ? AF_UNSPEC : AF_INET; @@ -327,6 +328,14 @@ main(int argc, char *argv[], char **envp) anon_only = 1; break; + case 'B': +#ifdef USE_BLACKLIST + use_blacklist = 1; +#else + syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support"); +#endif + break; + case 'd': ftpdebug++; break; @@ -644,9 +653,7 @@ main(int argc, char *argv[], char **envp) reply(220, "%s FTP server (%s) ready.", hostname, version); else reply(220, "FTP server ready."); -#ifdef USE_BLACKLIST - blacklist_init(); -#endif + BLACKLIST_INIT(); for (;;) (void) yyparse(); /* NOTREACHED */ @@ -1422,9 +1429,7 @@ pass(char *passwd) */ if (rval) { reply(530, "Login incorrect."); -#ifdef USE_BLACKLIST - blacklist_notify(1, STDIN_FILENO, "Login incorrect"); -#endif + BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Login incorrect"); if (logging) { syslog(LOG_NOTICE, "FTP LOGIN FAILED FROM %s", @@ -1441,12 +1446,9 @@ pass(char *passwd) exit(0); } return; + } else { + BLACKLIST_NOTIFY(BLACKLIST_AUTH_OK, STDIN_FILENO, "Login successful"); } -#ifdef USE_BLACKLIST - else { - blacklist_notify(0, STDIN_FILENO, "Login successful"); - } -#endif } login_attempts = 0; /* this time successful */ if (setegid(pw->pw_gid) < 0) { diff --git a/release/arm64/make-memstick.sh b/release/arm64/make-memstick.sh index d47fad0079ea..760f362a0d18 100755 --- a/release/arm64/make-memstick.sh +++ b/release/arm64/make-memstick.sh @@ -10,6 +10,8 @@ # $FreeBSD$ # +set -e + PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH @@ -31,10 +33,6 @@ fi echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local makefs -B little -o label=FreeBSD_Install ${2}.part ${1} -if [ $? -ne 0 ]; then - echo "makefs failed" - exit 1 -fi rm ${1}/etc/fstab rm ${1}/etc/rc.conf.local diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index 22de624f7280..f91888702cdb 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -2716,11 +2716,6 @@ printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) static void printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) { -#define MATCHOUI(field, oui, string) \ -do { \ - if (memcmp(field, oui, 4) == 0) \ - printf("%s", string); \ -} while (0) printf("%s", tag); if (verbose) { @@ -2754,7 +2749,6 @@ do { \ printf(" FORM:0x%x CAPS:0x%x>", mconf->conf_form, mconf->conf_cap); } -#undef MATCHOUI } static void diff --git a/share/examples/Makefile b/share/examples/Makefile index acb50c75f7e5..7bf606c91818 100644 --- a/share/examples/Makefile +++ b/share/examples/Makefile @@ -250,7 +250,7 @@ copies: symlinks: .for i in ${LDIRS} rm -rf ${DESTDIR}${BINDIR}/$i - ln -s ${.CURDIR}/$i ${DESTDIR}${BINDIR}/$i + ${INSTALL} ${TAG_ARGS} -l s ${.CURDIR}/$i ${DESTDIR}${BINDIR}/$i .endfor etc-examples: diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index 0126a020e999..1fab97cf9e8d 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -78,7 +78,7 @@ CTFFLAGS+= -g # prefer .s to a .c, add .po, remove stuff not used in the BSD libraries # .pico used for PIC object files -.SUFFIXES: .out .o .po .pico .S .asm .s .c .cc .cpp .cxx .C .f .y .l .ln +.SUFFIXES: .out .o .bc .ll .po .pico .S .asm .s .c .cc .cpp .cxx .C .f .y .l .ln .if !defined(PICFLAG) .if ${MACHINE_CPUARCH} == "sparc64" @@ -199,6 +199,18 @@ lib${LIB_PRIVATE}${LIB}_p.a: ${POBJS} ${RANLIB} ${RANLIBFLAGS} ${.TARGET} .endif +.if defined(LLVM_LINK) +BCOBJS= ${OBJS:.o=.bco} ${STATICOBJS:.o=.bco} +LLOBJS= ${OBJS:.o=.llo} ${STATICOBJS:.o=.llo} +CLEANFILES+= ${BCOBJS} ${LLOBJS} + +lib${LIB_PRIVATE}${LIB}.bc: ${BCOBJS} + ${LLVM_LINK} -o ${.TARGET} ${BCOBJS} + +lib${LIB_PRIVATE}${LIB}.ll: ${LLOBJS} + ${LLVM_LINK} -S -o ${.TARGET} ${LLOBJS} +.endif + .if defined(SHLIB_NAME) || \ defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB) SOBJS+= ${OBJS:.o=.pico} diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index deb78a3ded89..43cfb1271a5a 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -4,7 +4,7 @@ .include .include -.SUFFIXES: .out .o .c .cc .cpp .cxx .C .m .y .l .ln .s .S .asm +.SUFFIXES: .out .o .bc .c .cc .cpp .cxx .C .m .y .l .ll .ln .s .S .asm # XXX The use of COPTS in modern makefiles is discouraged. .if defined(COPTS) @@ -147,6 +147,19 @@ ${PROGNAME}.debug: ${PROG_FULL} ${OBJCOPY} --only-keep-debug ${PROG_FULL} ${.TARGET} .endif +.if defined(LLVM_LINK) +# LLVM bitcode / textual IR representations of the program +BCOBJS= ${OBJS:.o=.bco} +LLOBJS= ${OBJS:.o=.llo} + +${PROG_FULL}.bc: ${BCOBJS} + ${LLVM_LINK} -o ${.TARGET} ${BCOBJS} + +${PROG_FULL}.ll: ${LLOBJS} + ${LLVM_LINK} -S -o ${.TARGET} ${LLOBJS} + +.endif # defined(LLVM_LINK) + .if ${MK_MAN} != "no" && !defined(MAN) && \ !defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \ !defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \ @@ -166,14 +179,14 @@ all: all-man .endif .if defined(PROG) -CLEANFILES+= ${PROG} +CLEANFILES+= ${PROG} ${PROG}.bc ${PROG}.ll .if ${MK_DEBUG_FILES} != "no" -CLEANFILES+= ${PROG_FULL} ${PROGNAME}.debug +CLEANFILES+= ${PROG_FULL} ${PROG_FULL}.bc ${PROGNAME}.debug ${PROG_FULL}.ll .endif .endif .if defined(OBJS) -CLEANFILES+= ${OBJS} +CLEANFILES+= ${OBJS} ${BCOBJS} ${LLOBJS} .endif .include diff --git a/share/mk/sys.mk b/share/mk/sys.mk index cc4a1feb61bb..2c3743342018 100644 --- a/share/mk/sys.mk +++ b/share/mk/sys.mk @@ -231,6 +231,8 @@ LINTLIBFLAGS ?= -cghapbxu -C ${LIB} MAKE ?= make .if !defined(%POSIX) +LLVM_LINK ?= llvm-link + LORDER ?= lorder NM ?= nm diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index d727d5349f00..bbb2beca5413 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -83,7 +83,9 @@ options RCTL # Resource limits options KDB # Enable kernel debugger support. options KDB_TRACE # Print a stack trace for a panic. # For full debugger support use (turn off in stable branch): +options BUF_TRACKING # Track buffer history options DDB # Support DDB. +options FULL_BUF_TRACKING # Track more buffer history options GDB # Support remote GDB. options DEADLKRES # Enable the deadlock resolver options INVARIANTS # Enable calls of extra sanity checking diff --git a/sys/amd64/conf/GENERIC-NODEBUG b/sys/amd64/conf/GENERIC-NODEBUG index be8e6af34382..6d4e4b05206f 100644 --- a/sys/amd64/conf/GENERIC-NODEBUG +++ b/sys/amd64/conf/GENERIC-NODEBUG @@ -34,5 +34,7 @@ nooptions INVARIANTS nooptions INVARIANT_SUPPORT nooptions WITNESS nooptions WITNESS_SKIPSPIN +nooptions BUF_TRACKING nooptions DEADLKRES +nooptions FULL_BUF_TRACKING diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index fb55b38309ee..5ac2fa8fd415 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -500,7 +500,8 @@ pmap_set_tex(void) /* Add shareable bits for normal memory in SMP case. */ #ifdef SMP - prrr |= PRRR_NS1; + if (ARM_USE_MP_EXTENSIONS) + prrr |= PRRR_NS1; #endif cp15_prrr_set(prrr); cp15_nmrr_set(nmrr); diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC index dfc1b31bd021..53f1c09a04c2 100644 --- a/sys/arm/conf/GENERIC +++ b/sys/arm/conf/GENERIC @@ -21,6 +21,7 @@ ident GENERIC cpu CPU_CORTEXA_MP +cpu CPU_CORTEXA8 machine arm armv6 makeoptions CONF_CFLAGS="-march=armv7a" @@ -37,6 +38,8 @@ files "../broadcom/bcm2835/files.bcm2836" files "../broadcom/bcm2835/files.bcm283x" files "../nvidia/tegra124/files.tegra124" files "../qemu/files.qemu" +files "../ti/files.ti" +files "../ti/am335x/files.am335x" options SOC_ALLWINNER_A20 options SOC_ALLWINNER_A31 @@ -44,6 +47,7 @@ options SOC_ALLWINNER_A31S options SOC_ALLWINNER_A83T options SOC_ALLWINNER_H3 options SOC_BCM2836 +options SOC_TI_AM335X options SCHED_ULE # ULE scheduler options SMP # Enable multiple cores @@ -66,6 +70,9 @@ device cpufreq options INTRNG device gic +# PMU support (for CCNT). +device pmu + # ARM Generic Timer device generic_timer @@ -113,9 +120,14 @@ device axp81x # AXP813/818 Power Management Unit device bcm2835_bsc device icee device sy8106a # SY8106A Buck Regulator +device ti_i2c +device am335x_pmic # AM335x Power Management IC (TPC65217) +device am335x_rtc # RTC support (power management only) +#define am335x_dmtpps # Pulse Per Second capture driver # GPIO device gpio +device gpiobacklight device gpioled device gpioregulator @@ -128,6 +140,16 @@ device aw_cir # SPI device spibus device bcm2835_spi +device ti_spi + +# ADC support +device ti_adc + +# Watchdog support +# If we don't enable the watchdog driver, the BealeBone could potentially +# reboot automatically because the boot loader might have enabled the +# watchdog. +device ti_wdt device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) @@ -141,11 +163,16 @@ device usb device ohci device ehci device dwcotg # DWC OTG controller +device musb device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" device ukbd # Allow keyboard like HIDs to control console +# Device mode support and USFS template +device usb_template # Control of the gadget +device usfs + # Ethernet device loop device ether @@ -176,6 +203,12 @@ device vchiq # Pinmux device fdt_pinctrl +# TI Programmable Realtime Unit support +device ti_pruss + +# Mailbox support +device ti_mbox + # Extensible Firmware Interface options EFI diff --git a/sys/arm/freescale/imx/files.imx5 b/sys/arm/freescale/imx/files.imx5 index aaea85116bb7..c2214c188a14 100644 --- a/sys/arm/freescale/imx/files.imx5 +++ b/sys/arm/freescale/imx/files.imx5 @@ -32,7 +32,7 @@ arm/freescale/imx/imx51_ccm.c standard dev/ata/chipsets/ata-fsl.c optional imxata # SDHCI/MMC -arm/freescale/imx/imx_sdhci.c optional sdhci +dev/sdhci/fsl_sdhci.c optional sdhci # USB OH3 controller (1 OTG, 3 EHCI) arm/freescale/imx/imx_nop_usbphy.c optional ehci diff --git a/sys/arm/freescale/imx/files.imx6 b/sys/arm/freescale/imx/files.imx6 index de4ff6edb54e..6fb8e2f8abad 100644 --- a/sys/arm/freescale/imx/files.imx6 +++ b/sys/arm/freescale/imx/files.imx6 @@ -32,7 +32,7 @@ arm/freescale/imx/imx6_ipu.c optional vt # # Optional devices. # -arm/freescale/imx/imx_sdhci.c optional sdhci +dev/sdhci/fsl_sdhci.c optional sdhci arm/freescale/imx/imx_wdog.c optional imxwdt diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index e11e0f766fbb..db1505609e7d 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -45,6 +45,21 @@ #define CPU_ASID_KERNEL 0 +#if __ARM_ARCH >= 7 +#if !defined(SMP) +/* No SMP so no need to use the MP extensions */ +#define ARM_USE_MP_EXTENSIONS 0 +#elif defined(CPU_CORTEXA8) && \ + (defined(CPU_CORTEXA_MP) || defined(CPU_KRAIT) || defined(CPU_MV_PJ4B)) +#define ARM_USE_MP_EXTENSIONS (cpuinfo.mp_ext != 0) +#elif defined(CPU_CORTEXA8) +#define ARM_USE_MP_EXTENSIONS 0 +#else +#define ARM_USE_MP_EXTENSIONS 1 +#endif +#endif /* __ARM_ARCH >= 7 */ + + void dcache_wbinv_poc_all(void); /* !!! NOT SMP coherent function !!! */ vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t); vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t); @@ -111,15 +126,15 @@ fname(uint64_t reg) \ /* TLB */ _WF0(_CP15_TLBIALL, CP15_TLBIALL) /* Invalidate entire unified TLB */ -#if __ARM_ARCH >= 7 && defined SMP +#if __ARM_ARCH >= 7 _WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS) /* Invalidate entire unified TLB IS */ #endif _WF1(_CP15_TLBIASID, CP15_TLBIASID(%0)) /* Invalidate unified TLB by ASID */ -#if __ARM_ARCH >= 7 && defined SMP +#if __ARM_ARCH >= 7 _WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0)) /* Invalidate unified TLB by ASID IS */ #endif _WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0)) /* Invalidate unified TLB by MVA, all ASID */ -#if __ARM_ARCH >= 7 && defined SMP +#if __ARM_ARCH >= 7 _WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0)) /* Invalidate unified TLB by MVA, all ASID IS */ #endif _WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0)) /* Invalidate unified TLB by MVA */ @@ -129,7 +144,7 @@ _WF1(_CP15_TTB_SET, CP15_TTBR0(%0)) /* Cache and Branch predictor */ _WF0(_CP15_BPIALL, CP15_BPIALL) /* Branch predictor invalidate all */ -#if __ARM_ARCH >= 7 && defined SMP +#if __ARM_ARCH >= 7 _WF0(_CP15_BPIALLIS, CP15_BPIALLIS) /* Branch predictor invalidate all IS */ #endif _WF1(_CP15_BPIMVA, CP15_BPIMVA(%0)) /* Branch predictor invalidate by MVA */ @@ -143,7 +158,7 @@ _WF1(_CP15_DCCSW, CP15_DCCSW(%0)) /* Data cache clean by set/way */ _WF1(_CP15_DCIMVAC, CP15_DCIMVAC(%0)) /* Data cache invalidate by MVA PoC */ _WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */ _WF0(_CP15_ICIALLU, CP15_ICIALLU) /* Instruction cache invalidate all PoU */ -#if __ARM_ARCH >= 7 && defined SMP +#if __ARM_ARCH >= 7 _WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS) /* Instruction cache invalidate all PoU IS */ #endif _WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0)) /* Instruction cache invalidate */ @@ -345,20 +360,14 @@ tlb_flush_range_local(vm_offset_t va, vm_size_t size) } /* Broadcasting operations. */ -#if __ARM_ARCH >= 7 && defined SMP - -#if defined(CPU_CORTEXA8) -#define ARM_HAVE_MP_EXTENSIONS (cpuinfo.mp_ext != 0) -#else -#define ARM_HAVE_MP_EXTENSIONS 1 -#endif +#if __ARM_ARCH >= 7 static __inline void tlb_flush_all(void) { dsb(); - if (ARM_HAVE_MP_EXTENSIONS) + if (ARM_USE_MP_EXTENSIONS) _CP15_TLBIALLIS(); else _CP15_TLBIALL(); @@ -370,7 +379,7 @@ tlb_flush_all_ng(void) { dsb(); - if (ARM_HAVE_MP_EXTENSIONS) + if (ARM_USE_MP_EXTENSIONS) _CP15_TLBIASIDIS(CPU_ASID_KERNEL); else _CP15_TLBIASID(CPU_ASID_KERNEL); @@ -384,7 +393,7 @@ tlb_flush(vm_offset_t va) KASSERT((va & PAGE_MASK) == 0, ("%s: va %#x not aligned", __func__, va)); dsb(); - if (ARM_HAVE_MP_EXTENSIONS) + if (ARM_USE_MP_EXTENSIONS) _CP15_TLBIMVAAIS(va); else _CP15_TLBIMVA(va | CPU_ASID_KERNEL); @@ -401,7 +410,7 @@ tlb_flush_range(vm_offset_t va, vm_size_t size) size)); dsb(); - if (ARM_HAVE_MP_EXTENSIONS) { + if (ARM_USE_MP_EXTENSIONS) { for (; va < eva; va += PAGE_SIZE) _CP15_TLBIMVAAIS(va); } else { @@ -410,14 +419,14 @@ tlb_flush_range(vm_offset_t va, vm_size_t size) } dsb(); } -#else /* SMP */ +#else /* __ARM_ARCH < 7 */ #define tlb_flush_all() tlb_flush_all_local() #define tlb_flush_all_ng() tlb_flush_all_ng_local() #define tlb_flush(va) tlb_flush_local(va) #define tlb_flush_range(va, size) tlb_flush_range_local(va, size) -#endif /* SMP */ +#endif /* __ARM_ARCH < 7 */ /* * Cache maintenance operations. @@ -431,8 +440,8 @@ icache_sync(vm_offset_t va, vm_size_t size) dsb(); va &= ~cpuinfo.dcache_line_mask; -#if __ARM_ARCH >= 7 && defined SMP - if (ARM_HAVE_MP_EXTENSIONS) { +#if __ARM_ARCH >= 7 + if (ARM_USE_MP_EXTENSIONS) { for ( ; va < eva; va += cpuinfo.dcache_line_size) _CP15_DCCMVAU(va); } else @@ -442,8 +451,8 @@ icache_sync(vm_offset_t va, vm_size_t size) _CP15_DCCMVAC(va); } dsb(); -#if __ARM_ARCH >= 7 && defined SMP - if (ARM_HAVE_MP_EXTENSIONS) +#if __ARM_ARCH >= 7 + if (ARM_USE_MP_EXTENSIONS) _CP15_ICIALLUIS(); else #endif @@ -456,8 +465,8 @@ icache_sync(vm_offset_t va, vm_size_t size) static __inline void icache_inv_all(void) { -#if __ARM_ARCH >= 7 && defined SMP - if (ARM_HAVE_MP_EXTENSIONS) +#if __ARM_ARCH >= 7 + if (ARM_USE_MP_EXTENSIONS) _CP15_ICIALLUIS(); else #endif @@ -470,8 +479,8 @@ icache_inv_all(void) static __inline void bpb_inv_all(void) { -#if __ARM_ARCH >= 7 && defined SMP - if (ARM_HAVE_MP_EXTENSIONS) +#if __ARM_ARCH >= 7 + if (ARM_USE_MP_EXTENSIONS) _CP15_BPIALLIS(); else #endif @@ -488,8 +497,8 @@ dcache_wb_pou(vm_offset_t va, vm_size_t size) dsb(); va &= ~cpuinfo.dcache_line_mask; -#if __ARM_ARCH >= 7 && defined SMP - if (ARM_HAVE_MP_EXTENSIONS) { +#if __ARM_ARCH >= 7 + if (ARM_USE_MP_EXTENSIONS) { for ( ; va < eva; va += cpuinfo.dcache_line_size) _CP15_DCCMVAU(va); } else diff --git a/sys/arm/include/sysreg.h b/sys/arm/include/sysreg.h index f3fab5b225cc..479a26afb054 100644 --- a/sys/arm/include/sysreg.h +++ b/sys/arm/include/sysreg.h @@ -140,7 +140,7 @@ /* * CP15 C7 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */ #define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */ @@ -205,7 +205,7 @@ /* * CP15 C8 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */ #define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */ diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index 56f9510ab84e..032b4ca6a591 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -357,10 +357,12 @@ efinet_dev_print(int verbose) for (unit = 0, h = efi_find_handle(&efinet_dev, 0); h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) { printf(" %s%d:", efinet_dev.dv_name, unit); - text = efi_devpath_name(efi_lookup_devpath(h)); - if (text != NULL) { - printf(" %S", text); - efi_free_devpath_name(text); + if (verbose) { + text = efi_devpath_name(efi_lookup_devpath(h)); + if (text != NULL) { + printf(" %S", text); + efi_free_devpath_name(text); + } } if (pager_output("\n")) break; diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 9ec266e84cc1..b638ab1dba9f 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -744,6 +744,9 @@ struct ccb_scsiio { #define CAM_TAG_ACTION_NONE 0x00 u_int tag_id; /* tag id from initator (target mode) */ u_int init_id; /* initiator id of who selected */ +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + struct bio *bio; /* Associated bio */ +#endif }; static __inline uint8_t * @@ -1335,6 +1338,9 @@ cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, csio->sense_len = sense_len; csio->cdb_len = cdb_len; csio->tag_action = tag_action; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + csio->bio = NULL; +#endif } static __inline void diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 942a6c30376f..ae4134504b9c 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1427,6 +1427,11 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig, union ccb *orig_ccb = ccb; int error, recoveryccb; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (ccb->ccb_h.func_code == XPT_SCSI_IO && ccb->csio.bio != NULL) + biotrack(ccb->csio.bio, __func__); +#endif + periph = xpt_path_periph(ccb->ccb_h.path); recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone); if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) { diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index cfca7807c781..34018052ed60 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -4471,6 +4472,12 @@ xpt_done(union ccb *done_ccb) struct cam_doneq *queue; int run, hash; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (done_ccb->ccb_h.func_code == XPT_SCSI_IO && + done_ccb->csio.bio != NULL) + biotrack(done_ccb->csio.bio, __func__); +#endif + CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done: func= %#x %s status %#x\n", done_ccb->ccb_h.func_code, @@ -5189,6 +5196,16 @@ xpt_done_process(struct ccb_hdr *ccb_h) struct cam_devq *devq; struct mtx *mtx = NULL; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + struct ccb_scsiio *csio; + + if (ccb_h->func_code == XPT_SCSI_IO) { + csio = &((union ccb *)ccb_h)->csio; + if (csio->bio != NULL) + biotrack(csio->bio, __func__); + } +#endif + if (ccb_h->flags & CAM_HIGH_POWER) { struct highpowerlist *hphead; struct cam_ed *device; diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 977ac8d6252b..16d8ef7b07ca 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -2949,6 +2949,8 @@ dastart(struct cam_periph *periph, union ccb *start_ccb) void *data_ptr; int rw_op; + biotrack(bp, __func__); + if (bp->bio_cmd == BIO_WRITE) { softc->flags |= DA_FLAG_DIRTY; rw_op = SCSI_RW_WRITE; @@ -2976,6 +2978,9 @@ dastart(struct cam_periph *periph, union ccb *start_ccb) /*dxfer_len*/ bp->bio_bcount, /*sense_len*/SSD_FULL_SIZE, da_default_timeout * 1000); +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + start_ccb->csio.bio = bp; +#endif break; } case BIO_FLUSH: @@ -4008,6 +4013,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n")); csio = &done_ccb->csio; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (csio->bio != NULL) + biotrack(csio->bio, __func__); +#endif state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK; switch (state) { case DA_CCB_BUFFER_IO: @@ -4106,6 +4115,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) } } + biotrack(bp, __func__); LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); if (LIST_EMPTY(&softc->pending_ccbs)) softc->flags |= DA_FLAG_WAS_OTAG; @@ -5219,6 +5229,11 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) struct cam_periph *periph; int error, error_code, sense_key, asc, ascq; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (ccb->csio.bio != NULL) + biotrack(ccb->csio.bio, __func__); +#endif + periph = xpt_path_periph(ccb->ccb_h.path); softc = (struct da_softc *)periph->softc; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h index 1642da08197f..8887aa8d925f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h @@ -405,6 +405,7 @@ extern itx_t *zil_itx_create(uint64_t txtype, size_t lrsize); extern void zil_itx_destroy(itx_t *itx); extern void zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx); +extern void zil_async_to_sync(zilog_t *zilog, uint64_t oid); extern void zil_commit(zilog_t *zilog, uint64_t oid); extern int zil_vdev_offline(const char *osname, void *txarg); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c index dbff8bd66dbd..6d58078a5d9f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c @@ -90,8 +90,6 @@ SYSCTL_INT(_vfs_zfs_trim, OID_AUTO, enabled, CTLFLAG_RDTUN, &zfs_trim_enabled, 0 static kmem_cache_t *zil_lwb_cache; -static void zil_async_to_sync(zilog_t *zilog, uint64_t foid); - #define LWB_EMPTY(lwb) ((BP_GET_LSIZE(&lwb->lwb_blk) - \ sizeof (zil_chain_t)) == (lwb->lwb_sz - lwb->lwb_nused)) @@ -1421,7 +1419,7 @@ zil_get_commit_list(zilog_t *zilog) /* * Move the async itxs for a specified object to commit into sync lists. */ -static void +void zil_async_to_sync(zilog_t *zilog, uint64_t foid) { uint64_t otxg, txg; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index 4965dde36f43..908de12a46ce 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -169,6 +169,7 @@ typedef struct zvol_state { uint32_t zv_open_count[OTYPCNT]; /* open counts */ #endif uint32_t zv_total_opens; /* total open count */ + uint32_t zv_sync_cnt; /* synchronous open count */ zilog_t *zv_zilog; /* ZIL handle */ list_t zv_extents; /* List of extents for dump */ znode_t zv_znode; /* for range locking */ @@ -1441,7 +1442,9 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t resid, BP_ZERO(&lr->lr_blkptr); itx->itx_private = zv; - itx->itx_sync = sync; + + if (!sync && (zv->zv_sync_cnt == 0)) + itx->itx_sync = B_FALSE; zil_itx_assign(zilog, itx, tx); @@ -1674,7 +1677,7 @@ zvol_strategy(struct bio *bp) if (error != 0) { dmu_tx_abort(tx); } else { - zvol_log_truncate(zv, tx, off, resid, B_TRUE); + zvol_log_truncate(zv, tx, off, resid, sync); dmu_tx_commit(tx); error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, off, resid); @@ -2083,7 +2086,7 @@ zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len, lr->lr_offset = off; lr->lr_length = len; - itx->itx_sync = sync; + itx->itx_sync = (sync || zv->zv_sync_cnt != 0); zil_itx_assign(zilog, itx, tx); } @@ -3075,6 +3078,11 @@ zvol_d_open(struct cdev *dev, int flags, int fmt, struct thread *td) #endif zv->zv_total_opens++; + if (flags & (FSYNC | FDSYNC)) { + zv->zv_sync_cnt++; + if (zv->zv_sync_cnt == 1) + zil_async_to_sync(zv->zv_zilog, ZVOL_OBJ); + } mutex_exit(&zfsdev_state_lock); return (err); out: @@ -3105,6 +3113,8 @@ zvol_d_close(struct cdev *dev, int flags, int fmt, struct thread *td) * You may get multiple opens, but only one close. */ zv->zv_total_opens--; + if (flags & (FSYNC | FDSYNC)) + zv->zv_sync_cnt--; if (zv->zv_total_opens == 0) zvol_last_close(zv); @@ -3118,9 +3128,9 @@ zvol_d_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct threa { zvol_state_t *zv; rl_t *rl; - off_t offset, length, chunk; + off_t offset, length; int i, error; - u_int u; + boolean_t sync; zv = dev->si_drv2; @@ -3158,15 +3168,17 @@ zvol_d_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct threa dmu_tx_t *tx = dmu_tx_create(zv->zv_objset); error = dmu_tx_assign(tx, TXG_WAIT); if (error != 0) { + sync = FALSE; dmu_tx_abort(tx); } else { - zvol_log_truncate(zv, tx, offset, length, B_TRUE); + sync = (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS); + zvol_log_truncate(zv, tx, offset, length, sync); dmu_tx_commit(tx); error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length); } zfs_range_unlock(rl); - if (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) + if (sync) zil_commit(zv->zv_zilog, ZVOL_OBJ); break; case DIOCGSTRIPESIZE: diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 5b699a08120a..a601dafe8a79 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -293,7 +293,7 @@ dev/hwpmc/hwpmc_tsc.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_rndis.c optional hyperv -dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv +dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 42962548a36a..d2637b1951e6 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -250,7 +250,7 @@ dev/hwpmc/hwpmc_tsc.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_rndis.c optional hyperv -dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv +dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 7ccc3a6ae2fb..e34dcf525b59 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -63,6 +63,7 @@ dev/ofw/ofw_subr.c optional aim powerpc dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac +dev/sdhci/fsl_sdhci.c optional mpc85xx sdhci dev/sec/sec.c optional sec mpc85xx dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac dev/sound/macio/davbus.c optional snd_davbus powermac @@ -137,7 +138,6 @@ powerpc/mpc85xx/atpic.c optional mpc85xx isa powerpc/mpc85xx/ds1553_bus_fdt.c optional ds1553 fdt powerpc/mpc85xx/ds1553_core.c optional ds1553 powerpc/mpc85xx/fsl_diu.c optional mpc85xx diu -powerpc/mpc85xx/fsl_sdhc.c optional mpc85xx sdhc powerpc/mpc85xx/i2c.c optional iicbus fdt powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/lbc.c optional mpc85xx diff --git a/sys/conf/options b/sys/conf/options index 9004832b1b36..79f71a8e487c 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -50,12 +50,14 @@ TWA_FLASH_FIRMWARE opt_twa.h # Debugging options. ALT_BREAK_TO_DEBUGGER opt_kdb.h BREAK_TO_DEBUGGER opt_kdb.h +BUF_TRACKING opt_global.h DDB DDB_BUFR_SIZE opt_ddb.h DDB_CAPTURE_DEFAULTBUFSIZE opt_ddb.h DDB_CAPTURE_MAXBUFSIZE opt_ddb.h DDB_CTF opt_ddb.h DDB_NUMSYM opt_ddb.h +FULL_BUF_TRACKING opt_global.h GDB KDB opt_global.h KDB_TRACE opt_kdb.h diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 7a985a7343c1..e5462fae7b48 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -1062,27 +1062,15 @@ doopen(struct psm_softc *sc, int command_byte) */ if (sc->hw.model == MOUSE_MODEL_GENERIC) { if (tap_enabled > 0) { - /* - * Enable tap & drag gestures. We use a Mode Byte - * and clear the DisGest bit (see §2.5 of Synaptics - * TouchPad Interfacing Guide). - */ VLOG(2, (LOG_DEBUG, "psm%d: enable tap and drag gestures\n", sc->unit)); - mouse_ext_command(sc->kbdc, 0x00); - set_mouse_sampling_rate(sc->kbdc, 20); + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); } else if (tap_enabled == 0) { - /* - * Disable tap & drag gestures. We use a Mode Byte - * and set the DisGest bit (see §2.5 of Synaptics - * TouchPad Interfacing Guide). - */ VLOG(2, (LOG_DEBUG, "psm%d: disable tap and drag gestures\n", sc->unit)); - mouse_ext_command(sc->kbdc, 0x04); - set_mouse_sampling_rate(sc->kbdc, 20); + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); } } @@ -5364,6 +5352,24 @@ static int synaptics_preferred_mode(struct psm_softc *sc) { int mode_byte; + /* Check if we are in relative mode */ + if (sc->hw.model != MOUSE_MODEL_SYNAPTICS) { + if (tap_enabled == 0) + /* + * Disable tap & drag gestures. We use a Mode Byte + * and set the DisGest bit (see §2.5 of Synaptics + * TouchPad Interfacing Guide). + */ + return (0x04); + else + /* + * Enable tap & drag gestures. We use a Mode Byte + * and clear the DisGest bit (see §2.5 of Synaptics + * TouchPad Interfacing Guide). + */ + return (0x00); + } + mode_byte = 0xc4; /* request wmode where available */ @@ -5382,10 +5388,10 @@ synaptics_set_mode(struct psm_softc *sc, int mode_byte) { /* * Enable advanced gestures mode if supported and we are not entering - * passthrough mode. + * passthrough or relative mode. */ if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) && - !(mode_byte & (1 << 5))) { + sc->hw.model == MOUSE_MODEL_SYNAPTICS && !(mode_byte & (1 << 5))) { mouse_ext_command(sc->kbdc, 3); set_mouse_sampling_rate(sc->kbdc, 0xc8); } @@ -5698,6 +5704,9 @@ enable_synaptics(struct psm_softc *sc, enum probearg arg) if (!synaptics_support) return (FALSE); + /* Set mouse type just now for synaptics_set_mode() */ + sc->hw.model = MOUSE_MODEL_SYNAPTICS; + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); if (trackpoint_support && synhw.capPassthrough) { diff --git a/sys/dev/bhnd/bhnd_debug.h b/sys/dev/bhnd/bhnd_debug.h index dfe0bd2623dd..2591bb9a0743 100644 --- a/sys/dev/bhnd/bhnd_debug.h +++ b/sys/dev/bhnd/bhnd_debug.h @@ -70,8 +70,6 @@ #include -#include "opt_global.h" - #define BHND_ERROR_LEVEL 0x00 #define BHND_ERROR_MSG "ERROR" #define BHND_WARN_LEVEL 0x10 diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index 08a37c8ad1f0..d801f17cd057 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -57,7 +57,7 @@ static d_ioctl_t cpuctl_ioctl; #define CPUCTL_VERSION 1 -#ifdef DEBUG +#ifdef CPUCTL_DEBUG # define DPRINTF(format,...) printf(format, __VA_ARGS__); #else # define DPRINTF(...) @@ -377,13 +377,24 @@ update_intel(int cpu, cpuctl_update_args_t *args, struct thread *td) return (ret); } +/* + * NB: MSR 0xc0010020, MSR_K8_UCODE_UPDATE, is not documented by AMD. + * Coreboot, illumos and Linux source code was used to understand + * its workings. + */ +static void +amd_ucode_wrmsr(void *ucode_ptr) +{ + uint32_t tmp[4]; + + wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)ucode_ptr); + do_cpuid(0, tmp); +} + static int update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) { - void *ptr = NULL; - uint32_t tmp[4]; - int is_bound = 0; - int oldcpu; + void *ptr; int ret; if (args->size == 0 || args->data == NULL) { @@ -394,41 +405,23 @@ update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) DPRINTF("[cpuctl,%d]: firmware image too large", __LINE__); return (EINVAL); } + /* - * XXX Might not require contignous address space - needs check + * 16 byte alignment required. Rely on the fact that + * malloc(9) always returns the pointer aligned at least on + * the size of the allocation. */ - ptr = contigmalloc(args->size, M_CPUCTL, 0, 0, 0xffffffff, 16, 0); - if (ptr == NULL) { - DPRINTF("[cpuctl,%d]: cannot allocate %zd bytes of memory", - __LINE__, args->size); - return (ENOMEM); - } + ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK); if (copyin(args->data, ptr, args->size) != 0) { DPRINTF("[cpuctl,%d]: copyin %p->%p of %zd bytes failed", __LINE__, args->data, ptr, args->size); ret = EFAULT; goto fail; } - oldcpu = td->td_oncpu; - is_bound = cpu_sched_is_bound(td); - set_cpu(cpu, td); - critical_enter(); - - /* - * Perform update. - */ - wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)ptr); - - /* - * Serialize instruction flow. - */ - do_cpuid(0, tmp); - critical_exit(); - restore_cpu(oldcpu, is_bound, td); + smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, ptr); ret = 0; fail: - if (ptr != NULL) - contigfree(ptr, args->size, M_CPUCTL); + free(ptr, M_CPUCTL); return (ret); } diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 7e2690eae084..9df560ad3199 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -365,7 +365,6 @@ MODULE_DEPEND(em, netmap, 1, 1, 1); #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) -#define M_TSO_LEN 66 #define MAX_INTS_PER_SEC 8000 #define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index f35685645935..73b8d81f2790 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -44,15 +44,4 @@ struct hyperv_guid { int hyperv_guid2str(const struct hyperv_guid *, char *, size_t); -/** - * @brief Get physical address from virtual - */ -static inline unsigned long -hv_get_phys_addr(void *virt) -{ - unsigned long ret; - ret = (vtophys(virt) | ((vm_offset_t) virt & PAGE_MASK)); - return (ret); -} - #endif /* _HYPERV_H_ */ diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index 4dd0a9a39b19..6c7e99304754 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -146,8 +146,6 @@ int vmbus_chan_gpadl_disconnect(struct vmbus_channel *chan, void vmbus_chan_cpu_set(struct vmbus_channel *chan, int cpu); void vmbus_chan_cpu_rr(struct vmbus_channel *chan); -struct vmbus_channel * - vmbus_chan_cpu2chan(struct vmbus_channel *chan, int cpu); void vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on); struct vmbus_channel ** diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/if_hn.c similarity index 90% rename from sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c rename to sys/dev/hyperv/netvsc/if_hn.c index 6e2fb28ab380..e9f530af8b1e 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/if_hn.c @@ -59,62 +59,41 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include -#include -#include -#include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include #include #include -#include #include +#include +#include +#include #include -#include +#include #include +#include + +#include +#include -#include -#include -#include -#include -#include -#include #include - -#include +#include +#include +#include #include -#include +#include +#include #include #include #include -#include +#include #include #include #include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include #include #include @@ -129,24 +108,13 @@ __FBSDID("$FreeBSD$"); #include "vmbus_if.h" -/* Short for Hyper-V network interface */ -#define NETVSC_DEVNAME "hn" +#define HN_IFSTART_SUPPORT -/* - * It looks like offset 0 of buf is reserved to hold the softc pointer. - * The sc pointer evidently not needed, and is not presently populated. - * The packet offset is where the netvsc_packet starts in the buffer. - */ -#define HV_NV_SC_PTR_OFFSET_IN_BUF 0 -#define HV_NV_PACKET_OFFSET_IN_BUF 16 +#define HN_RING_CNT_DEF_MAX 8 /* YYY should get it from the underlying channel */ #define HN_TX_DESC_CNT 512 -#define HN_LROENT_CNT_DEF 128 - -#define HN_RING_CNT_DEF_MAX 8 - #define HN_RNDIS_PKT_LEN \ (sizeof(struct rndis_packet_msg) + \ HN_RNDIS_PKTINFO_SIZE(HN_NDIS_HASH_VALUE_SIZE) + \ @@ -166,50 +134,9 @@ __FBSDID("$FreeBSD$"); #define HN_EARLY_TXEOF_THRESH 8 -#define HN_RXINFO_VLAN 0x0001 -#define HN_RXINFO_CSUM 0x0002 -#define HN_RXINFO_HASHINF 0x0004 -#define HN_RXINFO_HASHVAL 0x0008 -#define HN_RXINFO_ALL \ - (HN_RXINFO_VLAN | \ - HN_RXINFO_CSUM | \ - HN_RXINFO_HASHINF | \ - HN_RXINFO_HASHVAL) - #define HN_PKTBUF_LEN_DEF (16 * 1024) -struct hn_txdesc { -#ifndef HN_USE_TXDESC_BUFRING - SLIST_ENTRY(hn_txdesc) link; -#endif - struct mbuf *m; - struct hn_tx_ring *txr; - int refs; - uint32_t flags; /* HN_TXD_FLAG_ */ - struct hn_nvs_sendctx send_ctx; - uint32_t chim_index; - int chim_size; - - bus_dmamap_t data_dmap; - - bus_addr_t rndis_pkt_paddr; - struct rndis_packet_msg *rndis_pkt; - bus_dmamap_t rndis_pkt_dmap; -}; - -#define HN_TXD_FLAG_ONLIST 0x1 -#define HN_TXD_FLAG_DMAMAP 0x2 - -#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff -#define HN_NDIS_RXCSUM_INFO_INVALID 0 -#define HN_NDIS_HASH_INFO_INVALID 0 - -struct hn_rxinfo { - uint32_t vlan_info; - uint32_t csum_info; - uint32_t hash_info; - uint32_t hash_value; -}; +#define HN_LROENT_CNT_DEF 128 #define HN_LRO_LENLIM_MULTIRX_DEF (12 * ETHERMTU) #define HN_LRO_LENLIM_DEF (25 * ETHERMTU) @@ -220,8 +147,8 @@ struct hn_rxinfo { #define HN_LOCK_INIT(sc) \ sx_init(&(sc)->hn_lock, device_get_nameunit((sc)->hn_dev)) -#define HN_LOCK_ASSERT(sc) sx_assert(&(sc)->hn_lock, SA_XLOCKED) #define HN_LOCK_DESTROY(sc) sx_destroy(&(sc)->hn_lock) +#define HN_LOCK_ASSERT(sc) sx_assert(&(sc)->hn_lock, SA_XLOCKED) #define HN_LOCK(sc) sx_xlock(&(sc)->hn_lock) #define HN_UNLOCK(sc) sx_xunlock(&(sc)->hn_lock) @@ -232,199 +159,282 @@ struct hn_rxinfo { #define HN_CSUM_IP6_HWASSIST(sc) \ ((sc)->hn_tx_ring[0].hn_csum_assist & HN_CSUM_IP6_MASK) -/* - * Globals - */ +struct hn_txdesc { +#ifndef HN_USE_TXDESC_BUFRING + SLIST_ENTRY(hn_txdesc) link; +#endif + struct mbuf *m; + struct hn_tx_ring *txr; + int refs; + uint32_t flags; /* HN_TXD_FLAG_ */ + struct hn_nvs_sendctx send_ctx; + uint32_t chim_index; + int chim_size; + + bus_dmamap_t data_dmap; + + bus_addr_t rndis_pkt_paddr; + struct rndis_packet_msg *rndis_pkt; + bus_dmamap_t rndis_pkt_dmap; +}; + +#define HN_TXD_FLAG_ONLIST 0x0001 +#define HN_TXD_FLAG_DMAMAP 0x0002 + +struct hn_rxinfo { + uint32_t vlan_info; + uint32_t csum_info; + uint32_t hash_info; + uint32_t hash_value; +}; + +#define HN_RXINFO_VLAN 0x0001 +#define HN_RXINFO_CSUM 0x0002 +#define HN_RXINFO_HASHINF 0x0004 +#define HN_RXINFO_HASHVAL 0x0008 +#define HN_RXINFO_ALL \ + (HN_RXINFO_VLAN | \ + HN_RXINFO_CSUM | \ + HN_RXINFO_HASHINF | \ + HN_RXINFO_HASHVAL) + +#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff +#define HN_NDIS_RXCSUM_INFO_INVALID 0 +#define HN_NDIS_HASH_INFO_INVALID 0 + +static int hn_probe(device_t); +static int hn_attach(device_t); +static int hn_detach(device_t); +static int hn_shutdown(device_t); +static void hn_chan_callback(struct vmbus_channel *, + void *); + +static void hn_init(void *); +static int hn_ioctl(struct ifnet *, u_long, caddr_t); +#ifdef HN_IFSTART_SUPPORT +static void hn_start(struct ifnet *); +#endif +static int hn_transmit(struct ifnet *, struct mbuf *); +static void hn_xmit_qflush(struct ifnet *); +static int hn_ifmedia_upd(struct ifnet *); +static void hn_ifmedia_sts(struct ifnet *, + struct ifmediareq *); + +static int hn_rndis_rxinfo(const void *, int, + struct hn_rxinfo *); +static void hn_rndis_rx_data(struct hn_rx_ring *, + const void *, int); +static void hn_rndis_rx_status(struct hn_softc *, + const void *, int); + +static void hn_nvs_handle_notify(struct hn_softc *, + const struct vmbus_chanpkt_hdr *); +static void hn_nvs_handle_comp(struct hn_softc *, + struct vmbus_channel *, + const struct vmbus_chanpkt_hdr *); +static void hn_nvs_handle_rxbuf(struct hn_rx_ring *, + struct vmbus_channel *, + const struct vmbus_chanpkt_hdr *); +static void hn_nvs_ack_rxbuf(struct hn_rx_ring *, + struct vmbus_channel *, uint64_t); + +#if __FreeBSD_version >= 1100099 +static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS); +#endif +static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS); +#if __FreeBSD_version < 1100095 +static int hn_rx_stat_int_sysctl(SYSCTL_HANDLER_ARGS); +#else +static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS); +#endif +static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS); + +static void hn_stop(struct hn_softc *); +static void hn_init_locked(struct hn_softc *); +static int hn_chan_attach(struct hn_softc *, + struct vmbus_channel *); +static void hn_chan_detach(struct hn_softc *, + struct vmbus_channel *); +static int hn_attach_subchans(struct hn_softc *); +static void hn_detach_allchans(struct hn_softc *); +static void hn_chan_rollup(struct hn_rx_ring *, + struct hn_tx_ring *); +static void hn_set_ring_inuse(struct hn_softc *, int); +static int hn_synth_attach(struct hn_softc *, int); +static void hn_synth_detach(struct hn_softc *); +static int hn_synth_alloc_subchans(struct hn_softc *, + int *); +static void hn_suspend(struct hn_softc *); +static void hn_suspend_data(struct hn_softc *); +static void hn_suspend_mgmt(struct hn_softc *); +static void hn_resume(struct hn_softc *); +static void hn_resume_data(struct hn_softc *); +static void hn_resume_mgmt(struct hn_softc *); +static void hn_suspend_mgmt_taskfunc(void *, int); +static void hn_chan_drain(struct vmbus_channel *); + +static void hn_update_link_status(struct hn_softc *); +static void hn_change_network(struct hn_softc *); +static void hn_link_taskfunc(void *, int); +static void hn_netchg_init_taskfunc(void *, int); +static void hn_netchg_status_taskfunc(void *, int); +static void hn_link_status(struct hn_softc *); + +static int hn_create_rx_data(struct hn_softc *, int); +static void hn_destroy_rx_data(struct hn_softc *); +static int hn_check_iplen(const struct mbuf *, int); +static int hn_set_rxfilter(struct hn_softc *); +static int hn_rss_reconfig(struct hn_softc *); +static void hn_rss_ind_fixup(struct hn_softc *, int); +static int hn_rxpkt(struct hn_rx_ring *, const void *, + int, const struct hn_rxinfo *); + +static int hn_tx_ring_create(struct hn_softc *, int); +static void hn_tx_ring_destroy(struct hn_tx_ring *); +static int hn_create_tx_data(struct hn_softc *, int); +static void hn_fixup_tx_data(struct hn_softc *); +static void hn_destroy_tx_data(struct hn_softc *); +static void hn_txdesc_dmamap_destroy(struct hn_txdesc *); +static int hn_encap(struct hn_tx_ring *, + struct hn_txdesc *, struct mbuf **); +static int hn_txpkt(struct ifnet *, struct hn_tx_ring *, + struct hn_txdesc *); +static void hn_set_chim_size(struct hn_softc *, int); +static void hn_set_tso_maxsize(struct hn_softc *, int, int); +static bool hn_tx_ring_pending(struct hn_tx_ring *); +static void hn_tx_ring_qflush(struct hn_tx_ring *); +static void hn_resume_tx(struct hn_softc *, int); +static int hn_get_txswq_depth(const struct hn_tx_ring *); +static void hn_txpkt_done(struct hn_nvs_sendctx *, + struct hn_softc *, struct vmbus_channel *, + const void *, int); +static int hn_txpkt_sglist(struct hn_tx_ring *, + struct hn_txdesc *); +static int hn_txpkt_chim(struct hn_tx_ring *, + struct hn_txdesc *); +static int hn_xmit(struct hn_tx_ring *, int); +static void hn_xmit_taskfunc(void *, int); +static void hn_xmit_txeof(struct hn_tx_ring *); +static void hn_xmit_txeof_taskfunc(void *, int); +#ifdef HN_IFSTART_SUPPORT +static int hn_start_locked(struct hn_tx_ring *, int); +static void hn_start_taskfunc(void *, int); +static void hn_start_txeof(struct hn_tx_ring *); +static void hn_start_txeof_taskfunc(void *, int); +#endif SYSCTL_NODE(_hw, OID_AUTO, hn, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Hyper-V network interface"); /* Trust tcp segements verification on host side. */ -static int hn_trust_hosttcp = 1; +static int hn_trust_hosttcp = 1; SYSCTL_INT(_hw_hn, OID_AUTO, trust_hosttcp, CTLFLAG_RDTUN, &hn_trust_hosttcp, 0, "Trust tcp segement verification on host side, " "when csum info is missing (global setting)"); /* Trust udp datagrams verification on host side. */ -static int hn_trust_hostudp = 1; +static int hn_trust_hostudp = 1; SYSCTL_INT(_hw_hn, OID_AUTO, trust_hostudp, CTLFLAG_RDTUN, &hn_trust_hostudp, 0, "Trust udp datagram verification on host side, " "when csum info is missing (global setting)"); /* Trust ip packets verification on host side. */ -static int hn_trust_hostip = 1; +static int hn_trust_hostip = 1; SYSCTL_INT(_hw_hn, OID_AUTO, trust_hostip, CTLFLAG_RDTUN, &hn_trust_hostip, 0, "Trust ip packet verification on host side, " "when csum info is missing (global setting)"); /* Limit TSO burst size */ -static int hn_tso_maxlen = IP_MAXPACKET; +static int hn_tso_maxlen = IP_MAXPACKET; SYSCTL_INT(_hw_hn, OID_AUTO, tso_maxlen, CTLFLAG_RDTUN, &hn_tso_maxlen, 0, "TSO burst limit"); /* Limit chimney send size */ -static int hn_tx_chimney_size = 0; +static int hn_tx_chimney_size = 0; SYSCTL_INT(_hw_hn, OID_AUTO, tx_chimney_size, CTLFLAG_RDTUN, &hn_tx_chimney_size, 0, "Chimney send packet size limit"); /* Limit the size of packet for direct transmission */ -static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF; +static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF; SYSCTL_INT(_hw_hn, OID_AUTO, direct_tx_size, CTLFLAG_RDTUN, &hn_direct_tx_size, 0, "Size of the packet for direct transmission"); +/* # of LRO entries per RX ring */ #if defined(INET) || defined(INET6) #if __FreeBSD_version >= 1100095 -static int hn_lro_entry_count = HN_LROENT_CNT_DEF; +static int hn_lro_entry_count = HN_LROENT_CNT_DEF; SYSCTL_INT(_hw_hn, OID_AUTO, lro_entry_count, CTLFLAG_RDTUN, &hn_lro_entry_count, 0, "LRO entry count"); #endif #endif -static int hn_share_tx_taskq = 0; +/* Use shared TX taskqueue */ +static int hn_share_tx_taskq = 0; SYSCTL_INT(_hw_hn, OID_AUTO, share_tx_taskq, CTLFLAG_RDTUN, &hn_share_tx_taskq, 0, "Enable shared TX taskqueue"); -static struct taskqueue *hn_tx_taskq; - #ifndef HN_USE_TXDESC_BUFRING -static int hn_use_txdesc_bufring = 0; +static int hn_use_txdesc_bufring = 0; #else -static int hn_use_txdesc_bufring = 1; +static int hn_use_txdesc_bufring = 1; #endif SYSCTL_INT(_hw_hn, OID_AUTO, use_txdesc_bufring, CTLFLAG_RD, &hn_use_txdesc_bufring, 0, "Use buf_ring for TX descriptors"); -static int hn_bind_tx_taskq = -1; +/* Bind TX taskqueue to the target CPU */ +static int hn_bind_tx_taskq = -1; SYSCTL_INT(_hw_hn, OID_AUTO, bind_tx_taskq, CTLFLAG_RDTUN, &hn_bind_tx_taskq, 0, "Bind TX taskqueue to the specified cpu"); -static int hn_use_if_start = 0; +#ifdef HN_IFSTART_SUPPORT +/* Use ifnet.if_start instead of ifnet.if_transmit */ +static int hn_use_if_start = 0; SYSCTL_INT(_hw_hn, OID_AUTO, use_if_start, CTLFLAG_RDTUN, &hn_use_if_start, 0, "Use if_start TX method"); +#endif -static int hn_chan_cnt = 0; +/* # of channels to use */ +static int hn_chan_cnt = 0; SYSCTL_INT(_hw_hn, OID_AUTO, chan_cnt, CTLFLAG_RDTUN, &hn_chan_cnt, 0, "# of channels to use; each channel has one RX ring and one TX ring"); -static int hn_tx_ring_cnt = 0; +/* # of transmit rings to use */ +static int hn_tx_ring_cnt = 0; SYSCTL_INT(_hw_hn, OID_AUTO, tx_ring_cnt, CTLFLAG_RDTUN, &hn_tx_ring_cnt, 0, "# of TX rings to use"); -static int hn_tx_swq_depth = 0; +/* Software TX ring deptch */ +static int hn_tx_swq_depth = 0; SYSCTL_INT(_hw_hn, OID_AUTO, tx_swq_depth, CTLFLAG_RDTUN, &hn_tx_swq_depth, 0, "Depth of IFQ or BUFRING"); +/* Enable sorted LRO, and the depth of the per-channel mbuf queue */ #if __FreeBSD_version >= 1100095 -static u_int hn_lro_mbufq_depth = 0; +static u_int hn_lro_mbufq_depth = 0; SYSCTL_UINT(_hw_hn, OID_AUTO, lro_mbufq_depth, CTLFLAG_RDTUN, &hn_lro_mbufq_depth, 0, "Depth of LRO mbuf queue"); #endif -static u_int hn_cpu_index; +static u_int hn_cpu_index; /* next CPU for channel */ +static struct taskqueue *hn_tx_taskq; /* shared TX taskqueue */ -/* - * Forward declarations - */ -static void hn_stop(struct hn_softc *sc); -static void hn_init_locked(struct hn_softc *sc); -static void hn_init(void *xsc); -static int hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); -static int hn_start_locked(struct hn_tx_ring *txr, int len); -static void hn_start(struct ifnet *ifp); -static void hn_start_txeof(struct hn_tx_ring *); -static int hn_ifmedia_upd(struct ifnet *ifp); -static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); -#if __FreeBSD_version >= 1100099 -static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS); -#endif -static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS); -#if __FreeBSD_version < 1100095 -static int hn_rx_stat_int_sysctl(SYSCTL_HANDLER_ARGS); -#else -static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS); -#endif -static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_check_iplen(const struct mbuf *, int); -static int hn_create_tx_ring(struct hn_softc *, int); -static void hn_destroy_tx_ring(struct hn_tx_ring *); -static int hn_create_tx_data(struct hn_softc *, int); -static void hn_fixup_tx_data(struct hn_softc *); -static void hn_destroy_tx_data(struct hn_softc *); -static void hn_start_taskfunc(void *, int); -static void hn_start_txeof_taskfunc(void *, int); -static void hn_link_taskfunc(void *, int); -static void hn_netchg_init_taskfunc(void *, int); -static void hn_netchg_status_taskfunc(void *, int); -static void hn_suspend_mgmt_taskfunc(void *, int); -static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); -static int hn_create_rx_data(struct hn_softc *sc, int); -static void hn_destroy_rx_data(struct hn_softc *sc); -static void hn_set_chim_size(struct hn_softc *, int); -static void hn_set_tso_maxsize(struct hn_softc *, int, int); -static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *); -static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *); -static int hn_attach_subchans(struct hn_softc *); -static void hn_detach_allchans(struct hn_softc *); -static void hn_chan_callback(struct vmbus_channel *chan, void *xrxr); -static void hn_chan_rollup(struct hn_rx_ring *, struct hn_tx_ring *); -static void hn_set_ring_inuse(struct hn_softc *, int); -static int hn_synth_attach(struct hn_softc *, int); -static void hn_synth_detach(struct hn_softc *); -static bool hn_tx_ring_pending(struct hn_tx_ring *); -static void hn_suspend(struct hn_softc *); -static void hn_suspend_data(struct hn_softc *); -static void hn_suspend_mgmt(struct hn_softc *); -static void hn_resume(struct hn_softc *); -static void hn_resume_data(struct hn_softc *); -static void hn_resume_mgmt(struct hn_softc *); -static void hn_rx_drain(struct vmbus_channel *); -static void hn_tx_resume(struct hn_softc *, int); -static void hn_tx_ring_qflush(struct hn_tx_ring *); -static int netvsc_detach(device_t dev); -static void hn_link_status(struct hn_softc *); -static int hn_sendpkt_rndis_sglist(struct hn_tx_ring *, struct hn_txdesc *); -static int hn_sendpkt_rndis_chim(struct hn_tx_ring *, struct hn_txdesc *); -static int hn_set_rxfilter(struct hn_softc *); -static void hn_link_status_update(struct hn_softc *); -static void hn_network_change(struct hn_softc *); - -static int hn_rndis_rxinfo(const void *, int, struct hn_rxinfo *); -static void hn_rndis_rx_data(struct hn_rx_ring *, const void *, int); -static void hn_rndis_rx_status(struct hn_softc *, const void *, int); - -static void hn_nvs_handle_notify(struct hn_softc *sc, - const struct vmbus_chanpkt_hdr *pkt); -static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, - const struct vmbus_chanpkt_hdr *pkt); -static void hn_nvs_handle_rxbuf(struct hn_rx_ring *rxr, - struct vmbus_channel *chan, - const struct vmbus_chanpkt_hdr *pkthdr); -static void hn_nvs_ack_rxbuf(struct hn_rx_ring *, struct vmbus_channel *, - uint64_t); - -static int hn_transmit(struct ifnet *, struct mbuf *); -static void hn_xmit_qflush(struct ifnet *); -static int hn_xmit(struct hn_tx_ring *, int); -static void hn_xmit_txeof(struct hn_tx_ring *); -static void hn_xmit_taskfunc(void *, int); -static void hn_xmit_txeof_taskfunc(void *, int); - -static const uint8_t hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = { +static const uint8_t +hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = { 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, @@ -432,6 +442,27 @@ static const uint8_t hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = { 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa }; +static device_method_t hn_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, hn_probe), + DEVMETHOD(device_attach, hn_attach), + DEVMETHOD(device_detach, hn_detach), + DEVMETHOD(device_shutdown, hn_shutdown), + DEVMETHOD_END +}; + +static driver_t hn_driver = { + "hn", + hn_methods, + sizeof(struct hn_softc) +}; + +static devclass_t hn_devclass; + +DRIVER_MODULE(hn, vmbus, hn_driver, hn_devclass, 0, 0); +MODULE_VERSION(hn, 1); +MODULE_DEPEND(hn, vmbus, 1, 1, 1); + #if __FreeBSD_version >= 1100099 static void hn_set_lro_lenlim(struct hn_softc *sc, int lenlim) @@ -444,7 +475,7 @@ hn_set_lro_lenlim(struct hn_softc *sc, int lenlim) #endif static int -hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd) +hn_txpkt_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd) { KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID && @@ -454,7 +485,7 @@ hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd) } static int -hn_sendpkt_rndis_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd) +hn_txpkt_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd) { struct hn_nvs_rndis rndis; @@ -516,6 +547,80 @@ hn_chim_free(struct hn_softc *sc, uint32_t chim_idx) atomic_clear_long(&sc->hn_chim_bmap[idx], mask); } +#if defined(INET6) || defined(INET) +/* + * NOTE: If this function failed, the m_head would be freed. + */ +static __inline struct mbuf * +hn_tso_fixup(struct mbuf *m_head) +{ + struct ether_vlan_header *evl; + struct tcphdr *th; + int ehlen; + + KASSERT(M_WRITABLE(m_head), ("TSO mbuf not writable")); + +#define PULLUP_HDR(m, len) \ +do { \ + if (__predict_false((m)->m_len < (len))) { \ + (m) = m_pullup((m), (len)); \ + if ((m) == NULL) \ + return (NULL); \ + } \ +} while (0) + + PULLUP_HDR(m_head, sizeof(*evl)); + evl = mtod(m_head, struct ether_vlan_header *); + if (evl->evl_encap_proto == ntohs(ETHERTYPE_VLAN)) + ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + else + ehlen = ETHER_HDR_LEN; + +#ifdef INET + if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { + struct ip *ip; + int iphlen; + + PULLUP_HDR(m_head, ehlen + sizeof(*ip)); + ip = mtodo(m_head, ehlen); + iphlen = ip->ip_hl << 2; + + PULLUP_HDR(m_head, ehlen + iphlen + sizeof(*th)); + th = mtodo(m_head, ehlen + iphlen); + + ip->ip_len = 0; + ip->ip_sum = 0; + th->th_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, htons(IPPROTO_TCP)); + } +#endif +#if defined(INET6) && defined(INET) + else +#endif +#ifdef INET6 + { + struct ip6_hdr *ip6; + + PULLUP_HDR(m_head, ehlen + sizeof(*ip6)); + ip6 = mtodo(m_head, ehlen); + if (ip6->ip6_nxt != IPPROTO_TCP) { + m_freem(m_head); + return (NULL); + } + + PULLUP_HDR(m_head, ehlen + sizeof(*ip6) + sizeof(*th)); + th = mtodo(m_head, ehlen + sizeof(*ip6)); + + ip6->ip6_plen = 0; + th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); + } +#endif + return (m_head); + +#undef PULLUP_HDR +} +#endif /* INET6 || INET */ + static int hn_set_rxfilter(struct hn_softc *sc) { @@ -653,13 +758,10 @@ static const struct hyperv_guid g_net_vsc_device_type = { 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} }; -/* - * Standard probe entry point. - * - */ static int -netvsc_probe(device_t dev) +hn_probe(device_t dev) { + if (VMBUS_PROBE_GUID(device_get_parent(dev), dev, &g_net_vsc_device_type) == 0) { device_set_desc(dev, "Hyper-V Network Interface"); @@ -668,14 +770,8 @@ netvsc_probe(device_t dev) return ENXIO; } -/* - * Standard attach entry point. - * - * Called when the driver is loaded. It allocates needed resources, - * and initializes the "hardware" and software. - */ static int -netvsc_attach(device_t dev) +hn_attach(device_t dev) { struct hn_softc *sc = device_get_softc(dev); struct sysctl_oid_list *child; @@ -759,10 +855,12 @@ netvsc_attach(device_t dev) tx_ring_cnt = hn_tx_ring_cnt; if (tx_ring_cnt <= 0 || tx_ring_cnt > ring_cnt) tx_ring_cnt = ring_cnt; +#ifdef HN_IFSTART_SUPPORT if (hn_use_if_start) { /* ifnet.if_start only needs one TX ring. */ tx_ring_cnt = 1; } +#endif /* * Set the leader CPU for channels. @@ -858,6 +956,7 @@ netvsc_attach(device_t dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = hn_ioctl; ifp->if_init = hn_init; +#ifdef HN_IFSTART_SUPPORT if (hn_use_if_start) { int qdepth = hn_get_txswq_depth(&sc->hn_tx_ring[0]); @@ -865,7 +964,9 @@ netvsc_attach(device_t dev) IFQ_SET_MAXLEN(&ifp->if_snd, qdepth); ifp->if_snd.ifq_drv_maxlen = qdepth - 1; IFQ_SET_READY(&ifp->if_snd); - } else { + } else +#endif + { ifp->if_transmit = hn_transmit; ifp->if_qflush = hn_xmit_qflush; } @@ -917,18 +1018,18 @@ netvsc_attach(device_t dev) * Kick off link status check. */ sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; - hn_link_status_update(sc); + hn_update_link_status(sc); return (0); failed: if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) hn_synth_detach(sc); - netvsc_detach(dev); + hn_detach(dev); return (error); } static int -netvsc_detach(device_t dev) +hn_detach(device_t dev) { struct hn_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->hn_ifp; @@ -967,12 +1068,10 @@ netvsc_detach(device_t dev) return (0); } -/* - * Standard shutdown entry point - */ static int -netvsc_shutdown(device_t dev) +hn_shutdown(device_t dev) { + return (0); } @@ -1037,7 +1136,7 @@ hn_netchg_status_taskfunc(void *xsc, int pending __unused) } static void -hn_link_status_update(struct hn_softc *sc) +hn_update_link_status(struct hn_softc *sc) { if (sc->hn_mgmt_taskq != NULL) @@ -1045,7 +1144,7 @@ hn_link_status_update(struct hn_softc *sc) } static void -hn_network_change(struct hn_softc *sc) +hn_change_network(struct hn_softc *sc) { if (sc->hn_mgmt_taskq != NULL) @@ -1197,7 +1296,7 @@ hn_txeof(struct hn_tx_ring *txr) } static void -hn_tx_done(struct hn_nvs_sendctx *sndc, struct hn_softc *sc, +hn_txpkt_done(struct hn_nvs_sendctx *sndc, struct hn_softc *sc, struct vmbus_channel *chan, const void *data __unused, int dlen __unused) { struct hn_txdesc *txd = sndc->hn_cbarg; @@ -1295,15 +1394,28 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) struct mbuf *m_head = *m_head0; struct rndis_packet_msg *pkt; uint32_t *pi_data; + void *chim = NULL; int pktlen; - /* - * extension points to the area reserved for the - * rndis_filter_packet, which is placed just after - * the netvsc_packet (and rppi struct, if present; - * length is updated later). - */ pkt = txd->rndis_pkt; + if (m_head->m_pkthdr.len + HN_RNDIS_PKT_LEN < txr->hn_chim_size) { + /* + * This packet is small enough to fit into a chimney sending + * buffer. Try allocating one chimney sending buffer now. + */ + txr->hn_tx_chimney_tried++; + txd->chim_index = hn_chim_alloc(txr->hn_sc); + if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) { + chim = txr->hn_sc->hn_chim + + (txd->chim_index * txr->hn_sc->hn_chim_szmax); + /* + * Directly fill the chimney sending buffer w/ the + * RNDIS packet message. + */ + pkt = chim; + } + } + pkt->rm_type = REMOTE_NDIS_PACKET_MSG; pkt->rm_len = sizeof(*pkt) + m_head->m_pkthdr.len; pkt->rm_dataoffset = sizeof(*pkt); @@ -1333,32 +1445,10 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { #if defined(INET6) || defined(INET) - struct ether_vlan_header *eh; - int ether_len; - - /* - * XXX need m_pullup and use mtodo - */ - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) - ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; - else - ether_len = ETHER_HDR_LEN; - pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN, NDIS_LSO2_INFO_SIZE, NDIS_PKTINFO_TYPE_LSO); #ifdef INET if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { - struct ip *ip = - (struct ip *)(m_head->m_data + ether_len); - unsigned long iph_len = ip->ip_hl << 2; - struct tcphdr *th = - (struct tcphdr *)((caddr_t)ip + iph_len); - - ip->ip_len = 0; - ip->ip_sum = 0; - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htons(IPPROTO_TCP)); *pi_data = NDIS_LSO2_INFO_MAKEIPV4(0, m_head->m_pkthdr.tso_segsz); } @@ -1368,12 +1458,6 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) #endif #ifdef INET6 { - struct ip6_hdr *ip6 = (struct ip6_hdr *) - (m_head->m_data + ether_len); - struct tcphdr *th = (struct tcphdr *)(ip6 + 1); - - ip6->ip6_plen = 0; - th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); *pi_data = NDIS_LSO2_INFO_MAKEIPV6(0, m_head->m_pkthdr.tso_segsz); } @@ -1404,26 +1488,25 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) pkt->rm_pktinfooffset = hn_rndis_pktmsg_offset(pkt->rm_pktinfooffset); /* - * Chimney send, if the packet could fit into one chimney buffer. + * Fast path: Chimney sending. */ - if (pkt->rm_len < txr->hn_chim_size) { - txr->hn_tx_chimney_tried++; - txd->chim_index = hn_chim_alloc(txr->hn_sc); - if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) { - uint8_t *dest = txr->hn_sc->hn_chim + - (txd->chim_index * txr->hn_sc->hn_chim_szmax); + if (chim != NULL) { + KASSERT(txd->chim_index != HN_NVS_CHIM_IDX_INVALID, + ("chimney buffer is not used")); + KASSERT(pkt == chim, ("RNDIS pkt not in chimney buffer")); - memcpy(dest, pkt, pktlen); - dest += pktlen; - m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); + m_copydata(m_head, 0, m_head->m_pkthdr.len, + ((uint8_t *)chim) + pktlen); - txd->chim_size = pkt->rm_len; - txr->hn_gpa_cnt = 0; - txr->hn_tx_chimney++; - txr->hn_sendpkt = hn_sendpkt_rndis_chim; - goto done; - } + txd->chim_size = pkt->rm_len; + txr->hn_gpa_cnt = 0; + txr->hn_tx_chimney++; + txr->hn_sendpkt = hn_txpkt_chim; + goto done; } + KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID, + ("chimney buffer is used")); + KASSERT(pkt == txd->rndis_pkt, ("RNDIS pkt not in txdesc")); error = hn_txdesc_dmamap_load(txr, txd, &m_head, segs, &nsegs); if (error) { @@ -1467,12 +1550,12 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) txd->chim_index = HN_NVS_CHIM_IDX_INVALID; txd->chim_size = 0; - txr->hn_sendpkt = hn_sendpkt_rndis_sglist; + txr->hn_sendpkt = hn_txpkt_sglist; done: txd->m = m_head; /* Set the completion routine */ - hn_nvs_sendctx_init(&txd->send_ctx, hn_tx_done, txd); + hn_nvs_sendctx_init(&txd->send_ctx, hn_txpkt_done, txd); return 0; } @@ -1483,7 +1566,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) * associated w/ the txd will _not_ be freed. */ static int -hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) +hn_txpkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) { int error, send_failed = 0; @@ -1496,7 +1579,10 @@ hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) if (!error) { ETHER_BPF_MTAP(ifp, txd->m); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - if (!hn_use_if_start) { +#ifdef HN_IFSTART_SUPPORT + if (!hn_use_if_start) +#endif + { if_inc_counter(ifp, IFCOUNTER_OBYTES, txd->m->m_pkthdr.len); if (txd->m->m_flags & M_MCAST) @@ -1545,71 +1631,6 @@ hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) return error; } -/* - * Start a transmit of one or more packets - */ -static int -hn_start_locked(struct hn_tx_ring *txr, int len) -{ - struct hn_softc *sc = txr->hn_sc; - struct ifnet *ifp = sc->hn_ifp; - - KASSERT(hn_use_if_start, - ("hn_start_locked is called, when if_start is disabled")); - KASSERT(txr == &sc->hn_tx_ring[0], ("not the first TX ring")); - mtx_assert(&txr->hn_tx_lock, MA_OWNED); - - if (__predict_false(txr->hn_suspended)) - return 0; - - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) - return 0; - - while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { - struct hn_txdesc *txd; - struct mbuf *m_head; - int error; - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) - break; - - if (len > 0 && m_head->m_pkthdr.len > len) { - /* - * This sending could be time consuming; let callers - * dispatch this packet sending (and sending of any - * following up packets) to tx taskqueue. - */ - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - return 1; - } - - txd = hn_txdesc_get(txr); - if (txd == NULL) { - txr->hn_no_txdescs++; - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); - break; - } - - error = hn_encap(txr, txd, &m_head); - if (error) { - /* Both txd and m_head are freed */ - continue; - } - - error = hn_send_pkt(ifp, txr, txd); - if (__predict_false(error)) { - /* txd is freed, but m_head is not */ - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); - break; - } - } - return 0; -} - /* * Append the specified data to the indicated mbuf chain, * Extend the mbuf chain if the new data does not fit in @@ -2114,64 +2135,6 @@ hn_stop(struct hn_softc *sc) sc->hn_tx_ring[i].hn_oactive = 0; } -/* - * FreeBSD transmit entry point - */ -static void -hn_start(struct ifnet *ifp) -{ - struct hn_softc *sc = ifp->if_softc; - struct hn_tx_ring *txr = &sc->hn_tx_ring[0]; - - if (txr->hn_sched_tx) - goto do_sched; - - if (mtx_trylock(&txr->hn_tx_lock)) { - int sched; - - sched = hn_start_locked(txr, txr->hn_direct_tx_size); - mtx_unlock(&txr->hn_tx_lock); - if (!sched) - return; - } -do_sched: - taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_tx_task); -} - -static void -hn_start_txeof(struct hn_tx_ring *txr) -{ - struct hn_softc *sc = txr->hn_sc; - struct ifnet *ifp = sc->hn_ifp; - - KASSERT(txr == &sc->hn_tx_ring[0], ("not the first TX ring")); - - if (txr->hn_sched_tx) - goto do_sched; - - if (mtx_trylock(&txr->hn_tx_lock)) { - int sched; - - atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); - sched = hn_start_locked(txr, txr->hn_direct_tx_size); - mtx_unlock(&txr->hn_tx_lock); - if (sched) { - taskqueue_enqueue(txr->hn_tx_taskq, - &txr->hn_tx_task); - } - } else { -do_sched: - /* - * Release the OACTIVE earlier, with the hope, that - * others could catch up. The task will clear the - * flag again with the hn_tx_lock to avoid possible - * races. - */ - atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); - taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_txeof_task); - } -} - static void hn_init_locked(struct hn_softc *sc) { @@ -2195,7 +2158,7 @@ hn_init_locked(struct hn_softc *sc) sc->hn_tx_ring[i].hn_oactive = 0; /* Clear TX 'suspended' bit. */ - hn_tx_resume(sc, sc->hn_tx_ring_inuse); + hn_resume_tx(sc, sc->hn_tx_ring_inuse); /* Everything is ready; unleash! */ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING); @@ -2211,20 +2174,6 @@ hn_init(void *xsc) HN_UNLOCK(sc); } -#ifdef LATER -/* - * - */ -static void -hn_watchdog(struct ifnet *ifp) -{ - - if_printf(ifp, "watchdog timeout -- resetting\n"); - hn_init(ifp->if_softc); /* XXX */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); -} -#endif - #if __FreeBSD_version >= 1100099 static int @@ -2906,7 +2855,7 @@ hn_destroy_rx_data(struct hn_softc *sc) } static int -hn_create_tx_ring(struct hn_softc *sc, int id) +hn_tx_ring_create(struct hn_softc *sc, int id) { struct hn_tx_ring *txr = &sc->hn_tx_ring[id]; device_t dev = sc->hn_dev; @@ -2933,11 +2882,14 @@ hn_create_tx_ring(struct hn_softc *sc, int id) txr->hn_tx_taskq = sc->hn_tx_taskq; +#ifdef HN_IFSTART_SUPPORT if (hn_use_if_start) { txr->hn_txeof = hn_start_txeof; TASK_INIT(&txr->hn_tx_task, 0, hn_start_taskfunc, txr); TASK_INIT(&txr->hn_txeof_task, 0, hn_start_txeof_taskfunc, txr); - } else { + } else +#endif + { int br_depth; txr->hn_txeof = hn_xmit_txeof; @@ -3074,7 +3026,10 @@ hn_create_tx_ring(struct hn_softc *sc, int id) SYSCTL_ADD_INT(ctx, child, OID_AUTO, "txdesc_avail", CTLFLAG_RD, &txr->hn_txdesc_avail, 0, "# of available TX descs"); - if (!hn_use_if_start) { +#ifdef HN_IFSTART_SUPPORT + if (!hn_use_if_start) +#endif + { SYSCTL_ADD_INT(ctx, child, OID_AUTO, "oactive", CTLFLAG_RD, &txr->hn_oactive, 0, "over active"); @@ -3103,7 +3058,7 @@ hn_txdesc_dmamap_destroy(struct hn_txdesc *txd) } static void -hn_destroy_tx_ring(struct hn_tx_ring *txr) +hn_tx_ring_destroy(struct hn_tx_ring *txr) { struct hn_txdesc *txd; @@ -3179,7 +3134,7 @@ hn_create_tx_data(struct hn_softc *sc, int ring_cnt) for (i = 0; i < sc->hn_tx_ring_cnt; ++i) { int error; - error = hn_create_tx_ring(sc, i); + error = hn_tx_ring_create(sc, i); if (error) return error; } @@ -3325,7 +3280,7 @@ hn_destroy_tx_data(struct hn_softc *sc) return; for (i = 0; i < sc->hn_tx_ring_cnt; ++i) - hn_destroy_tx_ring(&sc->hn_tx_ring[i]); + hn_tx_ring_destroy(&sc->hn_tx_ring[i]); free(sc->hn_tx_ring, M_DEVBUF); sc->hn_tx_ring = NULL; @@ -3334,6 +3289,8 @@ hn_destroy_tx_data(struct hn_softc *sc) sc->hn_tx_ring_inuse = 0; } +#ifdef HN_IFSTART_SUPPORT + static void hn_start_taskfunc(void *xtxr, int pending __unused) { @@ -3344,6 +3301,99 @@ hn_start_taskfunc(void *xtxr, int pending __unused) mtx_unlock(&txr->hn_tx_lock); } +static int +hn_start_locked(struct hn_tx_ring *txr, int len) +{ + struct hn_softc *sc = txr->hn_sc; + struct ifnet *ifp = sc->hn_ifp; + + KASSERT(hn_use_if_start, + ("hn_start_locked is called, when if_start is disabled")); + KASSERT(txr == &sc->hn_tx_ring[0], ("not the first TX ring")); + mtx_assert(&txr->hn_tx_lock, MA_OWNED); + + if (__predict_false(txr->hn_suspended)) + return 0; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return 0; + + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { + struct hn_txdesc *txd; + struct mbuf *m_head; + int error; + + IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); + if (m_head == NULL) + break; + + if (len > 0 && m_head->m_pkthdr.len > len) { + /* + * This sending could be time consuming; let callers + * dispatch this packet sending (and sending of any + * following up packets) to tx taskqueue. + */ + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); + return 1; + } + +#if defined(INET6) || defined(INET) + if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { + m_head = hn_tso_fixup(m_head); + if (__predict_false(m_head == NULL)) { + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + continue; + } + } +#endif + + txd = hn_txdesc_get(txr); + if (txd == NULL) { + txr->hn_no_txdescs++; + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); + atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); + break; + } + + error = hn_encap(txr, txd, &m_head); + if (error) { + /* Both txd and m_head are freed */ + continue; + } + + error = hn_txpkt(ifp, txr, txd); + if (__predict_false(error)) { + /* txd is freed, but m_head is not */ + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); + atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); + break; + } + } + return 0; +} + +static void +hn_start(struct ifnet *ifp) +{ + struct hn_softc *sc = ifp->if_softc; + struct hn_tx_ring *txr = &sc->hn_tx_ring[0]; + + if (txr->hn_sched_tx) + goto do_sched; + + if (mtx_trylock(&txr->hn_tx_lock)) { + int sched; + + sched = hn_start_locked(txr, txr->hn_direct_tx_size); + mtx_unlock(&txr->hn_tx_lock); + if (!sched) + return; + } +do_sched: + taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_tx_task); +} + static void hn_start_txeof_taskfunc(void *xtxr, int pending __unused) { @@ -3355,6 +3405,42 @@ hn_start_txeof_taskfunc(void *xtxr, int pending __unused) mtx_unlock(&txr->hn_tx_lock); } +static void +hn_start_txeof(struct hn_tx_ring *txr) +{ + struct hn_softc *sc = txr->hn_sc; + struct ifnet *ifp = sc->hn_ifp; + + KASSERT(txr == &sc->hn_tx_ring[0], ("not the first TX ring")); + + if (txr->hn_sched_tx) + goto do_sched; + + if (mtx_trylock(&txr->hn_tx_lock)) { + int sched; + + atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); + sched = hn_start_locked(txr, txr->hn_direct_tx_size); + mtx_unlock(&txr->hn_tx_lock); + if (sched) { + taskqueue_enqueue(txr->hn_tx_taskq, + &txr->hn_tx_task); + } + } else { +do_sched: + /* + * Release the OACTIVE earlier, with the hope, that + * others could catch up. The task will clear the + * flag again with the hn_tx_lock to avoid possible + * races. + */ + atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); + taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_txeof_task); + } +} + +#endif /* HN_IFSTART_SUPPORT */ + static int hn_xmit(struct hn_tx_ring *txr, int len) { @@ -3363,8 +3449,10 @@ hn_xmit(struct hn_tx_ring *txr, int len) struct mbuf *m_head; mtx_assert(&txr->hn_tx_lock, MA_OWNED); +#ifdef HN_IFSTART_SUPPORT KASSERT(hn_use_if_start == 0, ("hn_xmit is called, when if_start is enabled")); +#endif if (__predict_false(txr->hn_suspended)) return 0; @@ -3401,7 +3489,7 @@ hn_xmit(struct hn_tx_ring *txr, int len) continue; } - error = hn_send_pkt(ifp, txr, txd); + error = hn_txpkt(ifp, txr, txd); if (__predict_false(error)) { /* txd is freed, but m_head is not */ drbr_putback(ifp, txr->hn_mbuf_br, m_head); @@ -3422,6 +3510,20 @@ hn_transmit(struct ifnet *ifp, struct mbuf *m) struct hn_tx_ring *txr; int error, idx = 0; +#if defined(INET6) || defined(INET) + /* + * Perform TSO packet header fixup now, since the TSO + * packet header should be cache-hot. + */ + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + m = hn_tso_fixup(m); + if (__predict_false(m == NULL)) { + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + return EIO; + } + } +#endif + /* * Select the TX ring based on flowid */ @@ -3924,7 +4026,7 @@ hn_set_ring_inuse(struct hn_softc *sc, int ring_cnt) } static void -hn_rx_drain(struct vmbus_channel *chan) +hn_chan_drain(struct vmbus_channel *chan) { while (!vmbus_chan_rx_empty(chan) || !vmbus_chan_tx_empty(chan)) @@ -3979,9 +4081,9 @@ hn_suspend_data(struct hn_softc *sc) if (subch != NULL) { for (i = 0; i < nsubch; ++i) - hn_rx_drain(subch[i]); + hn_chan_drain(subch[i]); } - hn_rx_drain(sc->hn_prichan); + hn_chan_drain(sc->hn_prichan); if (subch != NULL) vmbus_subchan_rel(subch, nsubch); @@ -4026,7 +4128,7 @@ hn_suspend(struct hn_softc *sc) } static void -hn_tx_resume(struct hn_softc *sc, int tx_ring_cnt) +hn_resume_tx(struct hn_softc *sc, int tx_ring_cnt) { int i; @@ -4059,9 +4161,12 @@ hn_resume_data(struct hn_softc *sc) * since hn_tx_ring_inuse can be changed after * hn_suspend_data(). */ - hn_tx_resume(sc, sc->hn_tx_ring_cnt); + hn_resume_tx(sc, sc->hn_tx_ring_cnt); - if (!hn_use_if_start) { +#ifdef HN_IFSTART_SUPPORT + if (!hn_use_if_start) +#endif + { /* * Flush unused drbrs, since hn_tx_ring_inuse may be * reduced. @@ -4097,9 +4202,9 @@ hn_resume_mgmt(struct hn_softc *sc) * detection. */ if (sc->hn_link_flags & HN_LINK_FLAG_NETCHG) - hn_network_change(sc); + hn_change_network(sc); else - hn_link_status_update(sc); + hn_update_link_status(sc); } static void @@ -4126,7 +4231,7 @@ hn_rndis_rx_status(struct hn_softc *sc, const void *data, int dlen) switch (msg->rm_status) { case RNDIS_STATUS_MEDIA_CONNECT: case RNDIS_STATUS_MEDIA_DISCONNECT: - hn_link_status_update(sc); + hn_update_link_status(sc); break; case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: @@ -4146,7 +4251,7 @@ hn_rndis_rx_status(struct hn_softc *sc, const void *data, int dlen) if_printf(sc->hn_ifp, "network changed, change %u\n", change); } - hn_network_change(sc); + hn_change_network(sc); break; default: @@ -4661,25 +4766,3 @@ hn_tx_taskq_destroy(void *arg __unused) } SYSUNINIT(hn_txtq_destroy, SI_SUB_DRIVERS, SI_ORDER_SECOND, hn_tx_taskq_destroy, NULL); - -static device_method_t netvsc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, netvsc_probe), - DEVMETHOD(device_attach, netvsc_attach), - DEVMETHOD(device_detach, netvsc_detach), - DEVMETHOD(device_shutdown, netvsc_shutdown), - - { 0, 0 } -}; - -static driver_t netvsc_driver = { - NETVSC_DEVNAME, - netvsc_methods, - sizeof(struct hn_softc) -}; - -static devclass_t netvsc_devclass; - -DRIVER_MODULE(hn, vmbus, netvsc_driver, netvsc_devclass, 0, 0); -MODULE_VERSION(hn, 1); -MODULE_DEPEND(hn, vmbus, 1, 1, 1); diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index 593b4226bc52..643d61829810 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$"); /* hv_kvp defines */ #define BUFFERSIZE sizeof(struct hv_kvp_msg) -#define KVP_SUCCESS 0 -#define KVP_ERROR 1 #define kvp_hdr hdr.kvp_hdr #define KVP_FWVER_MAJOR 3 @@ -480,7 +478,7 @@ hv_kvp_convert_usermsg_to_hostmsg(struct hv_kvp_msg *umsg, struct hv_kvp_msg *hm case HV_KVP_OP_SET_IP_INFO: case HV_KVP_OP_SET: case HV_KVP_OP_DELETE: - return (KVP_SUCCESS); + return (0); case HV_KVP_OP_ENUMERATE: host_exchg_data = &hmsg->body.kvp_enum_data.data; @@ -501,9 +499,9 @@ hv_kvp_convert_usermsg_to_hostmsg(struct hv_kvp_msg *umsg, struct hv_kvp_msg *hm host_exchg_data->value_type = HV_REG_SZ; if ((hkey_len < 0) || (hvalue_len < 0)) - return (HV_KVP_E_FAIL); + return (EINVAL); - return (KVP_SUCCESS); + return (0); case HV_KVP_OP_GET: host_exchg_data = &hmsg->body.kvp_get.data; @@ -519,12 +517,12 @@ hv_kvp_convert_usermsg_to_hostmsg(struct hv_kvp_msg *umsg, struct hv_kvp_msg *hm host_exchg_data->value_type = HV_REG_SZ; if ((hkey_len < 0) || (hvalue_len < 0)) - return (HV_KVP_E_FAIL); + return (EINVAL); - return (KVP_SUCCESS); + return (0); default: - return (HV_KVP_E_FAIL); + return (EINVAL); } } @@ -533,16 +531,13 @@ hv_kvp_convert_usermsg_to_hostmsg(struct hv_kvp_msg *umsg, struct hv_kvp_msg *hm * Send the response back to the host. */ static void -hv_kvp_respond_host(hv_kvp_sc *sc, int error) +hv_kvp_respond_host(hv_kvp_sc *sc, uint32_t error) { struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp; hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *) &sc->rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)]; - if (error) - error = HV_KVP_E_FAIL; - hv_icmsg_hdrp->status = error; hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; @@ -612,8 +607,10 @@ hv_kvp_process_request(void *context, int pending) error = vmbus_ic_negomsg(&sc->util_sc, kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER); /* XXX handle vmbus_ic_negomsg failure. */ - hv_kvp_respond_host(sc, error); - + if (!error) + hv_kvp_respond_host(sc, HV_S_OK); + else + hv_kvp_respond_host(sc, HV_E_FAIL); /* * It is ok to not acquire the mutex before setting * req_in_progress here because negotiation is the @@ -657,7 +654,7 @@ hv_kvp_process_request(void *context, int pending) */ if (hv_kvp_req_in_progress(sc)) { hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__); - hv_kvp_respond_host(sc, HV_KVP_E_FAIL); + hv_kvp_respond_host(sc, HV_E_FAIL); sc->req_in_progress = false; } @@ -737,9 +734,9 @@ hv_kvp_dev_daemon_read(struct cdev *dev, struct uio *uio, int ioflag __unused) struct hv_kvp_msg *hv_kvp_dev_buf; hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1; - /* Check hv_kvp daemon registration status*/ + /* Read is not allowed util registering is done. */ if (!sc->register_done) - return (KVP_ERROR); + return (EPERM); sema_wait(&sc->dev_sema); @@ -789,7 +786,7 @@ hv_kvp_dev_daemon_write(struct cdev *dev, struct uio *uio, int ioflag __unused) } else { hv_kvp_log_info("%s, KVP Registration Failed\n", __func__); - return (KVP_ERROR); + return (EINVAL); } } else { @@ -799,10 +796,15 @@ hv_kvp_dev_daemon_write(struct cdev *dev, struct uio *uio, int ioflag __unused) struct hv_kvp_msg *hmsg = sc->host_kvp_msg; struct hv_kvp_msg *umsg = &sc->daemon_kvp_msg; - hv_kvp_convert_usermsg_to_hostmsg(umsg, hmsg); - hv_kvp_respond_host(sc, KVP_SUCCESS); + error = hv_kvp_convert_usermsg_to_hostmsg(umsg, hmsg); + hv_kvp_respond_host(sc, umsg->hdr.error); wakeup(sc); sc->req_in_progress = false; + if (umsg->hdr.error != HV_S_OK) + hv_kvp_log_info("%s, Error 0x%x from daemon\n", + __func__, umsg->hdr.error); + if (error) + hv_kvp_log_info("%s, Error from convert\n", __func__); } sc->daemon_busy = false; @@ -865,7 +867,7 @@ hv_kvp_attach(device_t dev) child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_kvp_log", - CTLFLAG_RW, &hv_kvp_log, 0, "Hyperv KVP service log level"); + CTLFLAG_RWTUN, &hv_kvp_log, 0, "Hyperv KVP service log level"); TASK_INIT(&sc->task, 0, hv_kvp_process_request, sc); diff --git a/sys/dev/hyperv/utilities/hv_kvp.h b/sys/dev/hyperv/utilities/hv_kvp.h index c391da0d5a5d..a94e67110f21 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.h +++ b/sys/dev/hyperv/utilities/hv_kvp.h @@ -144,19 +144,6 @@ enum hv_kvp_exchg_pool { HV_KVP_POOL_COUNT /* Number of pools, must be last. */ }; - -/* - * Some Hyper-V status codes. - */ -#define HV_KVP_S_OK 0x00000000 -#define HV_KVP_E_FAIL 0x80004005 -#define HV_KVP_S_CONT 0x80070103 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 -#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F -#define HV_INVALIDARG 0x80070057 -#define HV_KVP_GUID_NOTFOUND 0x80041002 - #define ADDR_FAMILY_NONE 0x00 #define ADDR_FAMILY_IPV4 0x01 #define ADDR_FAMILY_IPV6 0x02 diff --git a/sys/dev/hyperv/utilities/hv_utilreg.h b/sys/dev/hyperv/utilities/hv_utilreg.h index 9358776409ee..b29c0f99204f 100644 --- a/sys/dev/hyperv/utilities/hv_utilreg.h +++ b/sys/dev/hyperv/utilities/hv_utilreg.h @@ -29,10 +29,17 @@ #ifndef _HV_UTILREG_H_ #define _HV_UTILREG_H_ -#define HV_S_OK 0x00000000 -#define HV_E_FAIL 0x80004005 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 +/* + * Some Hyper-V status codes. + */ +#define HV_S_OK 0x00000000 +#define HV_E_FAIL 0x80004005 +#define HV_S_CONT 0x80070103 +#define HV_ERROR_NOT_SUPPORTED 0x80070032 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7 +#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F +#define HV_INVALIDARG 0x80070057 +#define HV_GUID_NOTFOUND 0x80041002 /* * Common defines for Hyper-V ICs diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index 1a86efdaf09e..1cd5f2b0ac97 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chan.c +++ b/sys/dev/hyperv/vmbus/vmbus_chan.c @@ -926,28 +926,28 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, int vmbus_chan_recv_pkt(struct vmbus_channel *chan, - struct vmbus_chanpkt_hdr *pkt0, int *pktlen0) + struct vmbus_chanpkt_hdr *pkt, int *pktlen0) { - struct vmbus_chanpkt_hdr pkt; - int error, pktlen; + int error, pktlen, pkt_hlen; - error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); + pkt_hlen = sizeof(*pkt); + error = vmbus_rxbr_peek(&chan->ch_rxbr, pkt, pkt_hlen); if (error) return (error); - if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { - vmbus_chan_printf(chan, "invalid hlen %u\n", pkt.cph_hlen); + if (__predict_false(pkt->cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { + vmbus_chan_printf(chan, "invalid hlen %u\n", pkt->cph_hlen); /* XXX this channel is dead actually. */ return (EIO); } - if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { + if (__predict_false(pkt->cph_hlen > pkt->cph_tlen)) { vmbus_chan_printf(chan, "invalid hlen %u and tlen %u\n", - pkt.cph_hlen, pkt.cph_tlen); + pkt->cph_hlen, pkt->cph_tlen); /* XXX this channel is dead actually. */ return (EIO); } - pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen); + pktlen = VMBUS_CHANPKT_GETLEN(pkt->cph_tlen); if (*pktlen0 < pktlen) { /* Return the size of this packet. */ *pktlen0 = pktlen; @@ -955,8 +955,12 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan, } *pktlen0 = pktlen; - /* Include packet header */ - error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0); + /* + * Skip the fixed-size packet header, which has been filled + * by the above vmbus_rxbr_peek(). + */ + error = vmbus_rxbr_read(&chan->ch_rxbr, pkt + 1, + pktlen - pkt_hlen, pkt_hlen); KASSERT(!error, ("vmbus_rxbr_read failed")); return (0); @@ -1530,65 +1534,6 @@ vmbus_chan_destroy_all(struct vmbus_softc *sc) } } -/* - * The channel whose vcpu binding is closest to the currect vcpu will - * be selected. - * If no multi-channel, always select primary channel. - */ -struct vmbus_channel * -vmbus_chan_cpu2chan(struct vmbus_channel *prichan, int cpu) -{ - struct vmbus_channel *sel, *chan; - uint32_t vcpu, sel_dist; - - KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpuid %d", cpu)); - if (TAILQ_EMPTY(&prichan->ch_subchans)) - return prichan; - - vcpu = VMBUS_PCPU_GET(prichan->ch_vmbus, vcpuid, cpu); - -#define CHAN_VCPU_DIST(ch, vcpu) \ - (((ch)->ch_vcpuid > (vcpu)) ? \ - ((ch)->ch_vcpuid - (vcpu)) : ((vcpu) - (ch)->ch_vcpuid)) - -#define CHAN_SELECT(ch) \ -do { \ - sel = ch; \ - sel_dist = CHAN_VCPU_DIST(ch, vcpu); \ -} while (0) - - CHAN_SELECT(prichan); - - mtx_lock(&prichan->ch_subchan_lock); - TAILQ_FOREACH(chan, &prichan->ch_subchans, ch_sublink) { - uint32_t dist; - - KASSERT(chan->ch_stflags & VMBUS_CHAN_ST_OPENED, - ("chan%u is not opened", chan->ch_id)); - - if (chan->ch_vcpuid == vcpu) { - /* Exact match; done */ - CHAN_SELECT(chan); - break; - } - - dist = CHAN_VCPU_DIST(chan, vcpu); - if (sel_dist <= dist) { - /* Far or same distance; skip */ - continue; - } - - /* Select the closer channel. */ - CHAN_SELECT(chan); - } - mtx_unlock(&prichan->ch_subchan_lock); - -#undef CHAN_SELECT -#undef CHAN_VCPU_DIST - - return sel; -} - struct vmbus_channel ** vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt) { diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c index 87eee02ebe33..65e93cd32018 100644 --- a/sys/dev/ichiic/ig4_iic.c +++ b/sys/dev/ichiic/ig4_iic.c @@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$"); /* - * Intel fourth generation mobile cpus integrated I2C device, smbus driver. + * Intel fourth generation mobile cpus integrated I2C device. * * See ig4_reg.h for datasheet reference and notes. * See ig4_var.h for locking semantics. @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -236,18 +235,13 @@ data_read(ig4iic_softc_t *sc) * the target address for when the controller later issues a START. */ static void -set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op) +set_slave_addr(ig4iic_softc_t *sc, uint8_t slave) { uint32_t tar; uint32_t ctl; int use_10bit; - use_10bit = sc->use_10bit; - if (trans_op & SMB_TRANS_7BIT) - use_10bit = 0; - if (trans_op & SMB_TRANS_10BIT) - use_10bit = 1; - + use_10bit = 0; if (sc->slave_valid && sc->last_slave == slave && sc->use_10bit == use_10bit) { return; @@ -290,209 +284,13 @@ set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op) sc->last_slave = slave; } -/* - * Issue START with byte command, possible count, and a variable length - * read or write buffer, then possible turn-around read. The read also - * has a possible count received. - * - * For SMBUS - - * - * Quick: START+ADDR+RD/WR STOP - * - * Normal: START+ADDR+WR CMD DATA..DATA STOP - * - * START+ADDR+RD CMD - * RESTART+ADDR RDATA..RDATA STOP - * (can also be used for I2C transactions) - * - * Process Call: START+ADDR+WR CMD DATAL DATAH - * RESTART+ADDR+RD RDATAL RDATAH STOP - * - * Block: START+ADDR+RD CMD - * RESTART+ADDR+RD RCOUNT DATA... STOP - * - * START+ADDR+WR CMD - * RESTART+ADDR+WR WCOUNT DATA... STOP - * - * For I2C - basically, no *COUNT fields, possibly no *CMD field. If the - * sender needs to issue a 2-byte command it will incorporate it - * into the write buffer and also set NOCMD. - * - * Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically - * by the controller at the beginning of a command sequence or on a data - * direction turn-around, and we only need to tell it when to issue the STOP. - */ -static int -smb_transaction(ig4iic_softc_t *sc, char cmd, int op, - char *wbuf, int wcount, char *rbuf, int rcount, int *actualp) -{ - int error; - int unit; - uint32_t last; - - /* - * Debugging - dump registers - */ - if (ig4_dump) { - unit = device_get_unit(sc->dev); - if (ig4_dump & (1 << unit)) { - ig4_dump &= ~(1 << unit); - ig4iic_dump(sc); - } - } - - /* - * Issue START or RESTART with next data byte, clear any previous - * abort condition that may have been holding the txfifo in reset. - */ - last = IG4_DATA_RESTART; - reg_read(sc, IG4_REG_CLR_TX_ABORT); - if (actualp) - *actualp = 0; - - /* - * Issue command if not told otherwise (smbus). - */ - if ((op & SMB_TRANS_NOCMD) == 0) { - error = wait_status(sc, IG4_STATUS_TX_NOTFULL); - if (error) - goto done; - last |= (u_char)cmd; - if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) - last |= IG4_DATA_STOP; - reg_write(sc, IG4_REG_DATA_CMD, last); - last = 0; - } - - /* - * Clean out any previously received data. - */ - if (sc->rpos != sc->rnext && - (op & SMB_TRANS_NOREPORT) == 0) { - device_printf(sc->dev, - "discarding %d bytes of spurious data\n", - sc->rnext - sc->rpos); - } - sc->rpos = 0; - sc->rnext = 0; - - /* - * If writing and not told otherwise, issue the write count (smbus). - */ - if (wcount && (op & SMB_TRANS_NOCNT) == 0) { - error = wait_status(sc, IG4_STATUS_TX_NOTFULL); - if (error) - goto done; - last |= (u_char)cmd; - reg_write(sc, IG4_REG_DATA_CMD, last); - last = 0; - } - - /* - * Bulk write (i2c) - */ - while (wcount) { - error = wait_status(sc, IG4_STATUS_TX_NOTFULL); - if (error) - goto done; - last |= (u_char)*wbuf; - if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) - last |= IG4_DATA_STOP; - reg_write(sc, IG4_REG_DATA_CMD, last); - --wcount; - ++wbuf; - last = 0; - } - - /* - * Issue reads to xmit FIFO (strange, I know) to tell the controller - * to clock in data. At the moment just issue one read ahead to - * pipeline the incoming data. - * - * NOTE: In the case of NOCMD and wcount == 0 we still issue a - * RESTART here, even if the data direction has not changed - * from the previous CHAINing call. This we force the RESTART. - * (A new START is issued automatically by the controller in - * the other nominal cases such as a data direction change or - * a previous STOP was issued). - * - * If this will be the last byte read we must also issue the STOP - * at the end of the read. - */ - if (rcount) { - last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD; - if (rcount == 1 && - (op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) == - SMB_TRANS_NOCNT) { - last |= IG4_DATA_STOP; - } - reg_write(sc, IG4_REG_DATA_CMD, last); - last = IG4_DATA_COMMAND_RD; - } - - /* - * Bulk read (i2c) and count field handling (smbus) - */ - while (rcount) { - /* - * Maintain a pipeline by queueing the allowance for the next - * read before waiting for the current read. - */ - if (rcount > 1) { - if (op & SMB_TRANS_NOCNT) - last = (rcount == 2) ? IG4_DATA_STOP : 0; - else - last = 0; - reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD | - last); - } - error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY); - if (error) { - if ((op & SMB_TRANS_NOREPORT) == 0) { - device_printf(sc->dev, - "rx timeout addr 0x%02x\n", - sc->last_slave); - } - goto done; - } - last = data_read(sc); - - if (op & SMB_TRANS_NOCNT) { - *rbuf = (u_char)last; - ++rbuf; - --rcount; - if (actualp) - ++*actualp; - } else { - /* - * Handle count field (smbus), which is not part of - * the rcount'ed buffer. The first read data in a - * bulk transfer is the count. - * - * XXX if rcount is loaded as 0 how do I generate a - * STOP now without issuing another RD or WR? - */ - if (rcount > (u_char)last) - rcount = (u_char)last; - op |= SMB_TRANS_NOCNT; - } - } - error = 0; -done: - /* XXX wait for xmit buffer to become empty */ - last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE); - - return (error); -} - /* * IICBUS API FUNCTIONS */ static int ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave) { - /* XXX 10-bit address support? */ - set_slave_addr(sc, slave >> 1, 0); + set_slave_addr(sc, slave >> 1); return (0); } @@ -706,7 +504,7 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) /* TODO handle speed configuration? */ if (oldaddr != NULL) *oldaddr = sc->last_slave << 1; - set_slave_addr(sc, addr >> 1, 0); + set_slave_addr(sc, addr >> 1); if (addr == IIC_UNKNOWN) sc->slave_valid = false; @@ -716,8 +514,6 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) } /* - * SMBUS API FUNCTIONS - * * Called from ig4iic_pci_attach/detach() */ int @@ -836,7 +632,6 @@ ig4iic_start(void *xdev) config_intrhook_disestablish(&sc->enum_hook); - /* Attach us to the smbus */ error = bus_generic_attach(sc->dev); if (error) { device_printf(sc->dev, @@ -844,8 +639,6 @@ ig4iic_start(void *xdev) } } - - int ig4iic_detach(ig4iic_softc_t *sc) { @@ -874,276 +667,6 @@ ig4iic_detach(ig4iic_softc_t *sc) return (0); } -int -ig4iic_smb_callback(device_t dev, int index, void *data) -{ - int error; - - switch (index) { - case SMB_REQUEST_BUS: - error = 0; - break; - case SMB_RELEASE_BUS: - error = 0; - break; - default: - error = SMB_EABORT; - break; - } - - return (error); -} - -/* - * Quick command. i.e. START + cmd + R/W + STOP and no data. It is - * unclear to me how I could implement this with the intel i2c controller - * because the controller sends STARTs and STOPs automatically with data. - */ -int -ig4iic_smb_quick(device_t dev, u_char slave, int how) -{ - - return (SMB_ENOTSUPP); -} - -/* - * Incremental send byte without stop (?). It is unclear why the slave - * address is specified if this presumably is used in combination with - * ig4iic_smb_quick(). - * - * (Also, how would this work anyway? Issue the last byte with writeb()?) - */ -int -ig4iic_smb_sendb(device_t dev, u_char slave, char byte) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - uint32_t cmd; - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - cmd = byte; - if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) { - reg_write(sc, IG4_REG_DATA_CMD, cmd); - error = 0; - } else { - error = SMB_ETIMEOUT; - } - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * Incremental receive byte without stop (?). It is unclear why the slave - * address is specified if this presumably is used in combination with - * ig4iic_smb_quick(). - */ -int -ig4iic_smb_recvb(device_t dev, u_char slave, char *byte) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD); - if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) { - *byte = data_read(sc); - error = 0; - } else { - *byte = 0; - error = SMB_ETIMEOUT; - } - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * Write command and single byte in transaction. - */ -int -ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, - &byte, 1, NULL, 0, NULL); - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * Write command and single word in transaction. - */ -int -ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - char buf[2]; - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - buf[0] = word & 0xFF; - buf[1] = word >> 8; - error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, - buf, 2, NULL, 0, NULL); - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * write command and read single byte in transaction. - */ -int -ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, - NULL, 0, byte, 1, NULL); - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * write command and read word in transaction. - */ -int -ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - char buf[2]; - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, - NULL, 0, buf, 2, NULL)) == 0) { - *word = (u_char)buf[0] | ((u_char)buf[1] << 8); - } - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -/* - * write command and word and read word in transaction - */ -int -ig4iic_smb_pcall(device_t dev, u_char slave, char cmd, - short sdata, short *rdata) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - char rbuf[2]; - char wbuf[2]; - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - wbuf[0] = sdata & 0xFF; - wbuf[1] = sdata >> 8; - if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, - wbuf, 2, rbuf, 2, NULL)) == 0) { - *rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8); - } - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -int -ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd, - u_char wcount, char *buf) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - error = smb_transaction(sc, cmd, 0, - buf, wcount, NULL, 0, NULL); - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -int -ig4iic_smb_bread(device_t dev, u_char slave, char cmd, - u_char *countp_char, char *buf) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int rcount = *countp_char; - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, 0); - error = smb_transaction(sc, cmd, 0, - NULL, 0, buf, rcount, &rcount); - *countp_char = rcount; - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - -int -ig4iic_smb_trans(device_t dev, int slave, char cmd, int op, - char *wbuf, int wcount, char *rbuf, int rcount, - int *actualp) -{ - ig4iic_softc_t *sc = device_get_softc(dev); - int error; - - sx_xlock(&sc->call_lock); - mtx_lock(&sc->io_lock); - - set_slave_addr(sc, slave, op); - error = smb_transaction(sc, cmd, op, - wbuf, wcount, rbuf, rcount, actualp); - - mtx_unlock(&sc->io_lock); - sx_xunlock(&sc->call_lock); - return (error); -} - /* * Interrupt Operation, see ig4_var.h for locking semantics. */ diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c index 0d796e5980d7..0dd551fc60ed 100644 --- a/sys/dev/ichiic/ig4_pci.c +++ b/sys/dev/ichiic/ig4_pci.c @@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$"); /* - * Intel fourth generation mobile cpus integrated I2C device, smbus driver. + * Intel fourth generation mobile cpus integrated I2C device. * * See ig4_reg.h for datasheet reference and notes. */ @@ -59,11 +59,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include "smbus_if.h" - #include #include @@ -167,20 +164,6 @@ static device_method_t ig4iic_pci_methods[] = { DEVMETHOD(device_attach, ig4iic_pci_attach), DEVMETHOD(device_detach, ig4iic_pci_detach), - /* SMBus methods from ig4_smb.c */ - DEVMETHOD(smbus_callback, ig4iic_smb_callback), - DEVMETHOD(smbus_quick, ig4iic_smb_quick), - DEVMETHOD(smbus_sendb, ig4iic_smb_sendb), - DEVMETHOD(smbus_recvb, ig4iic_smb_recvb), - DEVMETHOD(smbus_writeb, ig4iic_smb_writeb), - DEVMETHOD(smbus_writew, ig4iic_smb_writew), - DEVMETHOD(smbus_readb, ig4iic_smb_readb), - DEVMETHOD(smbus_readw, ig4iic_smb_readw), - DEVMETHOD(smbus_pcall, ig4iic_smb_pcall), - DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite), - DEVMETHOD(smbus_bread, ig4iic_smb_bread), - DEVMETHOD(smbus_trans, ig4iic_smb_trans), - DEVMETHOD(iicbus_transfer, ig4iic_transfer), DEVMETHOD(iicbus_reset, ig4iic_reset), DEVMETHOD(iicbus_callback, iicbus_null_callback), @@ -199,6 +182,5 @@ static devclass_t ig4iic_pci_devclass; DRIVER_MODULE_ORDERED(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0, SI_ORDER_ANY); MODULE_DEPEND(ig4iic, pci, 1, 1, 1); -MODULE_DEPEND(ig4iic, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); MODULE_DEPEND(ig4iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); MODULE_VERSION(ig4iic, 1); diff --git a/sys/dev/ichiic/ig4_reg.h b/sys/dev/ichiic/ig4_reg.h index 33976c0daf43..f1288dee9e4e 100644 --- a/sys/dev/ichiic/ig4_reg.h +++ b/sys/dev/ichiic/ig4_reg.h @@ -47,14 +47,14 @@ * I am also using the linux driver code as a reference to help resolve any * issues that come. These will be specifically documented in the code. * - * Please see protocol notes in section 5.21. This controller is an I2C - * master only and cannot act as a slave. The IO voltage should be set by - * the BIOS. Standard (100Kb/s) and Fast (400Kb/s) and fast mode plus - * (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT supported. + * This controller is an I2C master only and cannot act as a slave. The IO + * voltage should be set by the BIOS. Standard (100Kb/s) and Fast (400Kb/s) + * and fast mode plus (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT + * supported. */ -#ifndef _BUS_SMBUS_INTELGEN4_IG4_REG_H_ -#define _BUS_SMBUS_INTELGEN4_IG4_REG_H_ +#ifndef _ICHIIC_IG4_REG_H_ +#define _ICHIIC_IG4_REG_H_ /* * 22.2 MMIO registers can be accessed through BAR0 in PCI mode or through @@ -619,4 +619,4 @@ #define IG4_SWLTR_SNOOP_VALUE_DECODE(v) ((v) & 0x3F) #define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F) -#endif +#endif /* _ICHIIC_IG4_REG_H_ */ diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h index b35f2f97296f..dcfdc0490463 100644 --- a/sys/dev/ichiic/ig4_var.h +++ b/sys/dev/ichiic/ig4_var.h @@ -35,13 +35,12 @@ * $FreeBSD$ */ -#ifndef _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ -#define _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ +#ifndef _ICHIIC_IG4_VAR_H_ +#define _ICHIIC_IG4_VAR_H_ #include "bus_if.h" #include "device_if.h" #include "pci_if.h" -#include "smbus_if.h" #include "iicbus_if.h" #define IG4_RBUFSIZE 128 @@ -75,12 +74,12 @@ struct ig4iic_softc { /* * Locking semantics: * - * Functions implementing the smbus interface that interact + * Functions implementing the icbus interface that interact * with the controller acquire an exclusive lock on call_lock * to prevent interleaving of calls to the interface and a lock on * io_lock right afterwards, to synchronize controller I/O activity. - * - * The interrupt handler can only read data while no ig4iic_smb_* call + * + * The interrupt handler can only read data while no iicbus call * is in progress or while io_lock is dropped during mtx_sleep in * wait_status and set_controller. It is safe to drop io_lock in those * places, because the interrupt handler only accesses those registers: @@ -91,7 +90,7 @@ struct ig4iic_softc { * * Locking outside of those places is required to make the content * of rpos/rnext predictable (e.g. whenever data_read is called and in - * smb_transaction). + * ig4iic_transfer). */ struct sx call_lock; struct mtx io_lock; @@ -103,20 +102,8 @@ typedef struct ig4iic_softc ig4iic_softc_t; int ig4iic_attach(ig4iic_softc_t *sc); int ig4iic_detach(ig4iic_softc_t *sc); -/* SMBus methods */ -extern smbus_callback_t ig4iic_smb_callback; -extern smbus_quick_t ig4iic_smb_quick; -extern smbus_sendb_t ig4iic_smb_sendb; -extern smbus_recvb_t ig4iic_smb_recvb; -extern smbus_writeb_t ig4iic_smb_writeb; -extern smbus_writew_t ig4iic_smb_writew; -extern smbus_readb_t ig4iic_smb_readb; -extern smbus_readw_t ig4iic_smb_readw; -extern smbus_pcall_t ig4iic_smb_pcall; -extern smbus_bwrite_t ig4iic_smb_bwrite; -extern smbus_bread_t ig4iic_smb_bread; -extern smbus_trans_t ig4iic_smb_trans; +/* iicbus methods */ extern iicbus_transfer_t ig4iic_transfer; extern iicbus_reset_t ig4iic_reset; -#endif +#endif /* _ICHIIC_IG4_VAR_H_ */ diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index 21723b28f471..68c207a953f6 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$"); #define BUS_SPACE_MAXADDR_40BIT 0xFFFFFFFFFFULL #endif #define IOAT_REFLK (&ioat->submit_lock) -#define IOAT_SHRINK_PERIOD (10 * hz) static int ioat_probe(device_t device); static int ioat_attach(device_t device); @@ -82,23 +81,14 @@ static void ioat_process_events(struct ioat_softc *ioat); static inline uint32_t ioat_get_active(struct ioat_softc *ioat); static inline uint32_t ioat_get_ring_space(struct ioat_softc *ioat); static void ioat_free_ring(struct ioat_softc *, uint32_t size, - struct ioat_descriptor **); -static void ioat_free_ring_entry(struct ioat_softc *ioat, - struct ioat_descriptor *desc); -static struct ioat_descriptor *ioat_alloc_ring_entry(struct ioat_softc *, - int mflags); + struct ioat_descriptor *); static int ioat_reserve_space(struct ioat_softc *, uint32_t, int mflags); -static struct ioat_descriptor *ioat_get_ring_entry(struct ioat_softc *ioat, +static union ioat_hw_descriptor *ioat_get_descriptor(struct ioat_softc *, + uint32_t index); +static struct ioat_descriptor *ioat_get_ring_entry(struct ioat_softc *, uint32_t index); -static struct ioat_descriptor **ioat_prealloc_ring(struct ioat_softc *, - uint32_t size, boolean_t need_dscr, int mflags); -static int ring_grow(struct ioat_softc *, uint32_t oldorder, - struct ioat_descriptor **); -static int ring_shrink(struct ioat_softc *, uint32_t oldorder, - struct ioat_descriptor **); static void ioat_halted_debug(struct ioat_softc *, uint32_t); static void ioat_poll_timer_callback(void *arg); -static void ioat_shrink_timer_callback(void *arg); static void dump_descriptor(void *hw_desc); static void ioat_submit_single(struct ioat_softc *ioat); static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg, @@ -135,6 +125,10 @@ int g_ioat_debug_level = 0; SYSCTL_INT(_hw_ioat, OID_AUTO, debug_level, CTLFLAG_RWTUN, &g_ioat_debug_level, 0, "Set log level (0-3) for ioat(4). Higher is more verbose."); +unsigned g_ioat_ring_order = 13; +SYSCTL_UINT(_hw_ioat, OID_AUTO, ring_order, CTLFLAG_RDTUN, &g_ioat_ring_order, + 0, "Set IOAT ring order. (1 << this) == ring size."); + /* * OS <-> Driver interface structures */ @@ -336,7 +330,6 @@ ioat_detach(device_t device) ioat_teardown_intr(ioat); callout_drain(&ioat->poll_timer); - callout_drain(&ioat->shrink_timer); pci_disable_busmaster(device); @@ -354,7 +347,12 @@ ioat_detach(device_t device) bus_dma_tag_destroy(ioat->comp_update_tag); } - bus_dma_tag_destroy(ioat->hw_desc_tag); + if (ioat->hw_desc_ring != NULL) { + bus_dmamap_unload(ioat->hw_desc_tag, ioat->hw_desc_map); + bus_dmamem_free(ioat->hw_desc_tag, ioat->hw_desc_ring, + ioat->hw_desc_map); + bus_dma_tag_destroy(ioat->hw_desc_tag); + } return (0); } @@ -388,8 +386,8 @@ ioat_start_channel(struct ioat_softc *ioat) /* Submit 'NULL' operation manually to avoid quiescing flag */ desc = ioat_get_ring_entry(ioat, ioat->head); + hw_desc = &ioat_get_descriptor(ioat, ioat->head)->dma; dmadesc = &desc->bus_dmadesc; - hw_desc = desc->u.dma; dmadesc->callback_fn = NULL; dmadesc->callback_arg = NULL; @@ -426,9 +424,10 @@ static int ioat3_attach(device_t device) { struct ioat_softc *ioat; - struct ioat_descriptor **ring; - struct ioat_descriptor *next; + struct ioat_descriptor *ring; struct ioat_dma_hw_descriptor *dma_hw_desc; + void *hw_desc; + size_t ringsz; int i, num_descriptors; int error; uint8_t xfercap; @@ -453,7 +452,6 @@ ioat3_attach(device_t device) mtx_init(&ioat->submit_lock, "ioat_submit", NULL, MTX_DEF); mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF); callout_init(&ioat->poll_timer, 1); - callout_init(&ioat->shrink_timer, 1); TASK_INIT(&ioat->reset_task, 0, ioat_reset_hw_task, ioat); /* Establish lock order for Witness */ @@ -462,7 +460,6 @@ ioat3_attach(device_t device) mtx_unlock(&ioat->cleanup_lock); mtx_unlock(&ioat->submit_lock); - ioat->is_resize_pending = FALSE; ioat->is_submitter_processing = FALSE; ioat->is_completion_pending = FALSE; ioat->is_reset_pending = FALSE; @@ -484,37 +481,42 @@ ioat3_attach(device_t device) if (error != 0) return (error); - ioat->ring_size_order = IOAT_MIN_ORDER; - + ioat->ring_size_order = g_ioat_ring_order; num_descriptors = 1 << ioat->ring_size_order; + ringsz = sizeof(struct ioat_dma_hw_descriptor) * num_descriptors; - bus_dma_tag_create(bus_get_dma_tag(ioat->device), 0x40, 0x0, - BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, NULL, NULL, - sizeof(struct ioat_dma_hw_descriptor), 1, - sizeof(struct ioat_dma_hw_descriptor), 0, NULL, NULL, - &ioat->hw_desc_tag); + error = bus_dma_tag_create(bus_get_dma_tag(ioat->device), + 2 * 1024 * 1024, 0x0, BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, + NULL, NULL, ringsz, 1, ringsz, 0, NULL, NULL, &ioat->hw_desc_tag); + if (error != 0) + return (error); + + error = bus_dmamem_alloc(ioat->hw_desc_tag, &hw_desc, + BUS_DMA_ZERO | BUS_DMA_WAITOK, &ioat->hw_desc_map); + if (error != 0) + return (error); + + error = bus_dmamap_load(ioat->hw_desc_tag, ioat->hw_desc_map, hw_desc, + ringsz, ioat_dmamap_cb, &ioat->hw_desc_bus_addr, BUS_DMA_WAITOK); + if (error) + return (error); + + ioat->hw_desc_ring = hw_desc; ioat->ring = malloc(num_descriptors * sizeof(*ring), M_IOAT, M_ZERO | M_WAITOK); ring = ioat->ring; for (i = 0; i < num_descriptors; i++) { - ring[i] = ioat_alloc_ring_entry(ioat, M_WAITOK); - if (ring[i] == NULL) - return (ENOMEM); - - ring[i]->id = i; + memset(&ring[i].bus_dmadesc, 0, sizeof(ring[i].bus_dmadesc)); + ring[i].id = i; } - for (i = 0; i < num_descriptors - 1; i++) { - next = ring[i + 1]; - dma_hw_desc = ring[i]->u.dma; - - dma_hw_desc->next = next->hw_desc_bus_addr; + for (i = 0; i < num_descriptors; i++) { + dma_hw_desc = &ioat->hw_desc_ring[i].dma; + dma_hw_desc->next = RING_PHYS_ADDR(ioat, i + 1); } - ring[i]->u.dma->next = ring[0]->hw_desc_bus_addr; - ioat->head = ioat->hw_head = 0; ioat->tail = 0; ioat->last_seen = 0; @@ -680,6 +682,12 @@ ioat_process_events(struct ioat_softc *ioat) comp_update = *ioat->comp_update; status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK; + if (status < ioat->hw_desc_bus_addr || + status >= ioat->hw_desc_bus_addr + (1 << ioat->ring_size_order) * + sizeof(struct ioat_generic_hw_descriptor)) + panic("Bogus completion address %jx (channel %u)", + (uintmax_t)status, ioat->chan_idx); + if (status == ioat->last_seen) { /* * If we landed in process_events and nothing has been @@ -690,8 +698,7 @@ ioat_process_events(struct ioat_softc *ioat) CTR4(KTR_IOAT, "%s channel=%u hw_status=0x%lx last_seen=0x%lx", __func__, ioat->chan_idx, comp_update, ioat->last_seen); - desc = ioat_get_ring_entry(ioat, ioat->tail - 1); - while (desc->hw_desc_bus_addr != status) { + while (RING_PHYS_ADDR(ioat, ioat->tail - 1) != status) { desc = ioat_get_ring_entry(ioat, ioat->tail); dmadesc = &desc->bus_dmadesc; CTR5(KTR_IOAT, "channel=%u completing desc idx %u (%p) ok cb %p(%p)", @@ -708,7 +715,7 @@ ioat_process_events(struct ioat_softc *ioat) ioat->chan_idx, ioat->head, ioat->tail, ioat_get_active(ioat)); if (completed != 0) { - ioat->last_seen = desc->hw_desc_bus_addr; + ioat->last_seen = RING_PHYS_ADDR(ioat, ioat->tail - 1); ioat->stats.descriptors_processed += completed; } @@ -725,8 +732,6 @@ ioat_process_events(struct ioat_softc *ioat) pending = (ioat_get_active(ioat) != 0); if (!pending && ioat->is_completion_pending) { ioat->is_completion_pending = FALSE; - callout_reset(&ioat->shrink_timer, IOAT_SHRINK_PERIOD, - ioat_shrink_timer_callback, ioat); callout_stop(&ioat->poll_timer); } mtx_unlock(&ioat->submit_lock); @@ -781,8 +786,6 @@ ioat_process_events(struct ioat_softc *ioat) if (ioat->is_completion_pending) { ioat->is_completion_pending = FALSE; - callout_reset(&ioat->shrink_timer, IOAT_SHRINK_PERIOD, - ioat_shrink_timer_callback, ioat); callout_stop(&ioat->poll_timer); } @@ -964,7 +967,6 @@ ioat_release(bus_dmaengine_t dmaengine) ioat->is_completion_pending = TRUE; callout_reset(&ioat->poll_timer, 1, ioat_poll_timer_callback, ioat); - callout_stop(&ioat->shrink_timer); } mtx_unlock(&ioat->submit_lock); } @@ -998,7 +1000,7 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op, return (NULL); desc = ioat_get_ring_entry(ioat, ioat->head); - hw_desc = desc->u.generic; + hw_desc = &ioat_get_descriptor(ioat, ioat->head)->generic; hw_desc->u.control_raw = 0; hw_desc->u.control_generic.op = op; @@ -1034,7 +1036,7 @@ ioat_null(bus_dmaengine_t dmaengine, bus_dmaengine_callback_t callback_fn, if (desc == NULL) return (NULL); - hw_desc = desc->u.dma; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma; hw_desc->u.control.null = 1; ioat_submit_single(ioat); return (&desc->bus_dmadesc); @@ -1062,7 +1064,7 @@ ioat_copy(bus_dmaengine_t dmaengine, bus_addr_t dst, if (desc == NULL) return (NULL); - hw_desc = desc->u.dma; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma; if (g_ioat_debug_level >= 3) dump_descriptor(hw_desc); @@ -1100,7 +1102,7 @@ ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_addr_t dst1, if (desc == NULL) return (NULL); - hw_desc = desc->u.dma; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma; if (src2 != src1 + PAGE_SIZE) { hw_desc->u.control.src_page_break = 1; hw_desc->next_src_addr = src2; @@ -1177,7 +1179,7 @@ ioat_copy_crc(bus_dmaengine_t dmaengine, bus_addr_t dst, bus_addr_t src, if (desc == NULL) return (NULL); - hw_desc = desc->u.crc32; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->crc32; if ((flags & DMA_CRC_INLINE) == 0) hw_desc->crc_address = crcptr; @@ -1256,7 +1258,7 @@ ioat_crc(bus_dmaengine_t dmaengine, bus_addr_t src, bus_size_t len, if (desc == NULL) return (NULL); - hw_desc = desc->u.crc32; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->crc32; if ((flags & DMA_CRC_INLINE) == 0) hw_desc->crc_address = crcptr; @@ -1304,7 +1306,7 @@ ioat_blockfill(bus_dmaengine_t dmaengine, bus_addr_t dst, uint64_t fillpattern, if (desc == NULL) return (NULL); - hw_desc = desc->u.fill; + hw_desc = &ioat_get_descriptor(ioat, desc->id)->fill; if (g_ioat_debug_level >= 3) dump_descriptor(hw_desc); @@ -1329,60 +1331,6 @@ ioat_get_ring_space(struct ioat_softc *ioat) return ((1 << ioat->ring_size_order) - ioat_get_active(ioat) - 1); } -static struct ioat_descriptor * -ioat_alloc_ring_entry(struct ioat_softc *ioat, int mflags) -{ - struct ioat_generic_hw_descriptor *hw_desc; - struct ioat_descriptor *desc; - int error, busdmaflag; - - error = ENOMEM; - hw_desc = NULL; - - if ((mflags & M_WAITOK) != 0) - busdmaflag = BUS_DMA_WAITOK; - else - busdmaflag = BUS_DMA_NOWAIT; - - desc = malloc(sizeof(*desc), M_IOAT, mflags); - if (desc == NULL) - goto out; - - bus_dmamem_alloc(ioat->hw_desc_tag, (void **)&hw_desc, - BUS_DMA_ZERO | busdmaflag, &ioat->hw_desc_map); - if (hw_desc == NULL) - goto out; - - memset(&desc->bus_dmadesc, 0, sizeof(desc->bus_dmadesc)); - desc->u.generic = hw_desc; - - error = bus_dmamap_load(ioat->hw_desc_tag, ioat->hw_desc_map, hw_desc, - sizeof(*hw_desc), ioat_dmamap_cb, &desc->hw_desc_bus_addr, - busdmaflag); - if (error) - goto out; - -out: - if (error) { - ioat_free_ring_entry(ioat, desc); - return (NULL); - } - return (desc); -} - -static void -ioat_free_ring_entry(struct ioat_softc *ioat, struct ioat_descriptor *desc) -{ - - if (desc == NULL) - return; - - if (desc->u.generic) - bus_dmamem_free(ioat->hw_desc_tag, desc->u.generic, - ioat->hw_desc_map); - free(desc, M_IOAT); -} - /* * Reserves space in this IOAT descriptor ring by ensuring enough slots remain * for 'num_descs'. @@ -1402,8 +1350,6 @@ ioat_free_ring_entry(struct ioat_softc *ioat, struct ioat_descriptor *desc) static int ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) { - struct ioat_descriptor **new_ring; - uint32_t order; boolean_t dug; int error; @@ -1411,7 +1357,7 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) error = 0; dug = FALSE; - if (num_descs < 1 || num_descs >= (1 << IOAT_MAX_ORDER)) { + if (num_descs < 1 || num_descs >= (1 << ioat->ring_size_order)) { error = EINVAL; goto out; } @@ -1428,8 +1374,7 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) CTR3(KTR_IOAT, "%s channel=%u starved (%u)", __func__, ioat->chan_idx, num_descs); - if (!dug && !ioat->is_submitter_processing && - (1 << ioat->ring_size_order) > num_descs) { + if (!dug && !ioat->is_submitter_processing) { ioat->is_submitter_processing = TRUE; mtx_unlock(&ioat->submit_lock); @@ -1446,46 +1391,15 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) continue; } - order = ioat->ring_size_order; - if (ioat->is_resize_pending || order == IOAT_MAX_ORDER) { - if ((mflags & M_WAITOK) != 0) { - CTR2(KTR_IOAT, "%s channel=%u blocking on completions", - __func__, ioat->chan_idx); - msleep(&ioat->tail, &ioat->submit_lock, 0, - "ioat_rsz", 0); - continue; - } - + if ((mflags & M_WAITOK) == 0) { error = EAGAIN; break; } - - ioat->is_resize_pending = TRUE; - for (;;) { - mtx_unlock(&ioat->submit_lock); - - new_ring = ioat_prealloc_ring(ioat, 1 << (order + 1), - TRUE, mflags); - - mtx_lock(&ioat->submit_lock); - KASSERT(ioat->ring_size_order == order, - ("is_resize_pending should protect order")); - - if (new_ring == NULL) { - KASSERT((mflags & M_WAITOK) == 0, - ("allocation failed")); - error = EAGAIN; - break; - } - - error = ring_grow(ioat, order, new_ring); - if (error == 0) - break; - } - ioat->is_resize_pending = FALSE; - wakeup(&ioat->tail); - if (error) - break; + CTR2(KTR_IOAT, "%s channel=%u blocking on completions", + __func__, ioat->chan_idx); + msleep(&ioat->tail, &ioat->submit_lock, 0, + "ioat_full", 0); + continue; } out: @@ -1495,49 +1409,11 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) return (error); } -static struct ioat_descriptor ** -ioat_prealloc_ring(struct ioat_softc *ioat, uint32_t size, boolean_t need_dscr, - int mflags) -{ - struct ioat_descriptor **ring; - uint32_t i; - int error; - - KASSERT(size > 0 && powerof2(size), ("bogus size")); - - ring = malloc(size * sizeof(*ring), M_IOAT, M_ZERO | mflags); - if (ring == NULL) - return (NULL); - - if (need_dscr) { - error = ENOMEM; - for (i = size / 2; i < size; i++) { - ring[i] = ioat_alloc_ring_entry(ioat, mflags); - if (ring[i] == NULL) - goto out; - ring[i]->id = i; - } - } - error = 0; - -out: - if (error != 0 && ring != NULL) { - ioat_free_ring(ioat, size, ring); - ring = NULL; - } - return (ring); -} - static void ioat_free_ring(struct ioat_softc *ioat, uint32_t size, - struct ioat_descriptor **ring) + struct ioat_descriptor *ring) { - uint32_t i; - for (i = 0; i < size; i++) { - if (ring[i] != NULL) - ioat_free_ring_entry(ioat, ring[i]); - } free(ring, M_IOAT); } @@ -1545,188 +1421,20 @@ static struct ioat_descriptor * ioat_get_ring_entry(struct ioat_softc *ioat, uint32_t index) { - return (ioat->ring[index % (1 << ioat->ring_size_order)]); + return (&ioat->ring[index % (1 << ioat->ring_size_order)]); } -static int -ring_grow(struct ioat_softc *ioat, uint32_t oldorder, - struct ioat_descriptor **newring) +static union ioat_hw_descriptor * +ioat_get_descriptor(struct ioat_softc *ioat, uint32_t index) { - struct ioat_descriptor *tmp, *next; - struct ioat_dma_hw_descriptor *hw; - uint32_t oldsize, newsize, head, tail, i, end; - int error; - CTR2(KTR_IOAT, "%s channel=%u", __func__, ioat->chan_idx); - - mtx_assert(&ioat->submit_lock, MA_OWNED); - - if (oldorder != ioat->ring_size_order || oldorder >= IOAT_MAX_ORDER) { - error = EINVAL; - goto out; - } - - oldsize = (1 << oldorder); - newsize = (1 << (oldorder + 1)); - - mtx_lock(&ioat->cleanup_lock); - - head = ioat->head & (oldsize - 1); - tail = ioat->tail & (oldsize - 1); - - /* Copy old descriptors to new ring */ - for (i = 0; i < oldsize; i++) - newring[i] = ioat->ring[i]; - - /* - * If head has wrapped but tail hasn't, we must swap some descriptors - * around so that tail can increment directly to head. - */ - if (head < tail) { - for (i = 0; i <= head; i++) { - tmp = newring[oldsize + i]; - - newring[oldsize + i] = newring[i]; - newring[oldsize + i]->id = oldsize + i; - - newring[i] = tmp; - newring[i]->id = i; - } - head += oldsize; - } - - KASSERT(head >= tail, ("invariants")); - - /* Head didn't wrap; we only need to link in oldsize..newsize */ - if (head < oldsize) { - i = oldsize - 1; - end = newsize; - } else { - /* Head did wrap; link newhead..newsize and 0..oldhead */ - i = head; - end = newsize + (head - oldsize) + 1; - } - - /* - * Fix up hardware ring, being careful not to trample the active - * section (tail -> head). - */ - for (; i < end; i++) { - KASSERT((i & (newsize - 1)) < tail || - (i & (newsize - 1)) >= head, ("trampling snake")); - - next = newring[(i + 1) & (newsize - 1)]; - hw = newring[i & (newsize - 1)]->u.dma; - hw->next = next->hw_desc_bus_addr; - } - -#ifdef INVARIANTS - for (i = 0; i < newsize; i++) { - next = newring[(i + 1) & (newsize - 1)]; - hw = newring[i & (newsize - 1)]->u.dma; - - KASSERT(hw->next == next->hw_desc_bus_addr, - ("mismatch at i:%u (oldsize:%u); next=%p nextaddr=0x%lx" - " (tail:%u)", i, oldsize, next, next->hw_desc_bus_addr, - tail)); - } -#endif - - free(ioat->ring, M_IOAT); - ioat->ring = newring; - ioat->ring_size_order = oldorder + 1; - ioat->tail = tail; - ioat->head = head; - error = 0; - - mtx_unlock(&ioat->cleanup_lock); -out: - if (error) - ioat_free_ring(ioat, (1 << (oldorder + 1)), newring); - return (error); -} - -static int -ring_shrink(struct ioat_softc *ioat, uint32_t oldorder, - struct ioat_descriptor **newring) -{ - struct ioat_dma_hw_descriptor *hw; - struct ioat_descriptor *ent, *next; - uint32_t oldsize, newsize, current_idx, new_idx, i; - int error; - - CTR2(KTR_IOAT, "%s channel=%u", __func__, ioat->chan_idx); - - mtx_assert(&ioat->submit_lock, MA_OWNED); - - if (oldorder != ioat->ring_size_order || oldorder <= IOAT_MIN_ORDER) { - error = EINVAL; - goto out_unlocked; - } - - oldsize = (1 << oldorder); - newsize = (1 << (oldorder - 1)); - - mtx_lock(&ioat->cleanup_lock); - - /* Can't shrink below current active set! */ - if (ioat_get_active(ioat) >= newsize) { - error = ENOMEM; - goto out; - } - - /* - * Copy current descriptors to the new ring, dropping the removed - * descriptors. - */ - for (i = 0; i < newsize; i++) { - current_idx = (ioat->tail + i) & (oldsize - 1); - new_idx = (ioat->tail + i) & (newsize - 1); - - newring[new_idx] = ioat->ring[current_idx]; - newring[new_idx]->id = new_idx; - } - - /* Free deleted descriptors */ - for (i = newsize; i < oldsize; i++) { - ent = ioat_get_ring_entry(ioat, ioat->tail + i); - ioat_free_ring_entry(ioat, ent); - } - - /* Fix up hardware ring. */ - hw = newring[(ioat->tail + newsize - 1) & (newsize - 1)]->u.dma; - next = newring[(ioat->tail + newsize) & (newsize - 1)]; - hw->next = next->hw_desc_bus_addr; - -#ifdef INVARIANTS - for (i = 0; i < newsize; i++) { - next = newring[(i + 1) & (newsize - 1)]; - hw = newring[i & (newsize - 1)]->u.dma; - - KASSERT(hw->next == next->hw_desc_bus_addr, - ("mismatch at i:%u (newsize:%u); next=%p nextaddr=0x%lx " - "(tail:%u)", i, newsize, next, next->hw_desc_bus_addr, - ioat->tail)); - } -#endif - - free(ioat->ring, M_IOAT); - ioat->ring = newring; - ioat->ring_size_order = oldorder - 1; - error = 0; - -out: - mtx_unlock(&ioat->cleanup_lock); -out_unlocked: - if (error) - ioat_free_ring(ioat, (1 << (oldorder - 1)), newring); - return (error); + return (&ioat->hw_desc_ring[index % (1 << ioat->ring_size_order)]); } static void ioat_halted_debug(struct ioat_softc *ioat, uint32_t chanerr) { - struct ioat_descriptor *desc; + union ioat_hw_descriptor *desc; ioat_log_message(0, "Channel halted (%b)\n", (int)chanerr, IOAT_CHANERR_STR); @@ -1735,11 +1443,11 @@ ioat_halted_debug(struct ioat_softc *ioat, uint32_t chanerr) mtx_assert(&ioat->cleanup_lock, MA_OWNED); - desc = ioat_get_ring_entry(ioat, ioat->tail + 0); - dump_descriptor(desc->u.raw); + desc = ioat_get_descriptor(ioat, ioat->tail + 0); + dump_descriptor(desc); - desc = ioat_get_ring_entry(ioat, ioat->tail + 1); - dump_descriptor(desc->u.raw); + desc = ioat_get_descriptor(ioat, ioat->tail + 1); + dump_descriptor(desc); } static void @@ -1753,55 +1461,6 @@ ioat_poll_timer_callback(void *arg) ioat_process_events(ioat); } -static void -ioat_shrink_timer_callback(void *arg) -{ - struct ioat_descriptor **newring; - struct ioat_softc *ioat; - uint32_t order; - - ioat = arg; - ioat_log_message(1, "%s\n", __func__); - - /* Slowly scale the ring down if idle. */ - mtx_lock(&ioat->submit_lock); - - /* Don't run while the hardware is being reset. */ - if (ioat->resetting) { - mtx_unlock(&ioat->submit_lock); - return; - } - - order = ioat->ring_size_order; - if (ioat->is_completion_pending || ioat->is_resize_pending || - order == IOAT_MIN_ORDER) { - mtx_unlock(&ioat->submit_lock); - goto out; - } - ioat->is_resize_pending = TRUE; - mtx_unlock(&ioat->submit_lock); - - newring = ioat_prealloc_ring(ioat, 1 << (order - 1), FALSE, - M_NOWAIT); - - mtx_lock(&ioat->submit_lock); - KASSERT(ioat->ring_size_order == order, - ("resize_pending protects order")); - - if (newring != NULL && !ioat->is_completion_pending) - ring_shrink(ioat, order, newring); - else if (newring != NULL) - ioat_free_ring(ioat, (1 << (order - 1)), newring); - - ioat->is_resize_pending = FALSE; - mtx_unlock(&ioat->submit_lock); - -out: - if (ioat->ring_size_order > IOAT_MIN_ORDER) - callout_reset(&ioat->shrink_timer, IOAT_SHRINK_PERIOD, - ioat_shrink_timer_callback, ioat); -} - /* * Support Functions */ @@ -1946,7 +1605,7 @@ ioat_reset_hw(struct ioat_softc *ioat) ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN); ioat_write_chancmp(ioat, ioat->comp_update_bus_addr); - ioat_write_chainaddr(ioat, ioat->ring[0]->hw_desc_bus_addr); + ioat_write_chainaddr(ioat, RING_PHYS_ADDR(ioat, 0)); error = 0; CTR2(KTR_IOAT, "%s channel=%u configured channel", __func__, ioat->chan_idx); @@ -2128,8 +1787,6 @@ ioat_setup_sysctl(device_t device) SYSCTL_ADD_UQUAD(ctx, state, OID_AUTO, "last_completion", CTLFLAG_RD, ioat->comp_update, "HW addr of last completion"); - SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_resize_pending", CTLFLAG_RD, - &ioat->is_resize_pending, 0, "resize pending"); SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_submitter_processing", CTLFLAG_RD, &ioat->is_submitter_processing, 0, "submitter processing"); @@ -2307,16 +1964,8 @@ DB_SHOW_COMMAND(ioat, db_show_ioat) db_printf(" c_lock: %p\n", sc->poll_timer.c_lock); db_printf(" c_flags: 0x%x\n", (unsigned)sc->poll_timer.c_flags); - db_printf(" shrink_timer:\n"); - db_printf(" c_time: %ju\n", (uintmax_t)sc->shrink_timer.c_time); - db_printf(" c_arg: %p\n", sc->shrink_timer.c_arg); - db_printf(" c_func: %p\n", sc->shrink_timer.c_func); - db_printf(" c_lock: %p\n", sc->shrink_timer.c_lock); - db_printf(" c_flags: 0x%x\n", (unsigned)sc->shrink_timer.c_flags); - db_printf(" quiescing: %d\n", (int)sc->quiescing); db_printf(" destroying: %d\n", (int)sc->destroying); - db_printf(" is_resize_pending: %d\n", (int)sc->is_resize_pending); db_printf(" is_submitter_processing: %d\n", (int)sc->is_submitter_processing); db_printf(" is_completion_pending: %d\n", (int)sc->is_completion_pending); @@ -2331,34 +1980,37 @@ DB_SHOW_COMMAND(ioat, db_show_ioat) db_printf(" ring_size_order: %u\n", sc->ring_size_order); db_printf(" last_seen: 0x%lx\n", sc->last_seen); db_printf(" ring: %p\n", sc->ring); + db_printf(" descriptors: %p\n", sc->hw_desc_ring); + db_printf(" descriptors (phys): 0x%jx\n", + (uintmax_t)sc->hw_desc_bus_addr); db_printf(" ring[%u] (tail):\n", sc->tail % (1 << sc->ring_size_order)); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->tail)->id); db_printf(" addr: 0x%lx\n", - ioat_get_ring_entry(sc, sc->tail)->hw_desc_bus_addr); + RING_PHYS_ADDR(sc, sc->tail)); db_printf(" next: 0x%lx\n", - ioat_get_ring_entry(sc, sc->tail)->u.generic->next); + ioat_get_descriptor(sc, sc->tail)->generic.next); db_printf(" ring[%u] (head - 1):\n", (sc->head - 1) % (1 << sc->ring_size_order)); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head - 1)->id); db_printf(" addr: 0x%lx\n", - ioat_get_ring_entry(sc, sc->head - 1)->hw_desc_bus_addr); + RING_PHYS_ADDR(sc, sc->head - 1)); db_printf(" next: 0x%lx\n", - ioat_get_ring_entry(sc, sc->head - 1)->u.generic->next); + ioat_get_descriptor(sc, sc->head - 1)->generic.next); db_printf(" ring[%u] (head):\n", (sc->head) % (1 << sc->ring_size_order)); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head)->id); db_printf(" addr: 0x%lx\n", - ioat_get_ring_entry(sc, sc->head)->hw_desc_bus_addr); + RING_PHYS_ADDR(sc, sc->head)); db_printf(" next: 0x%lx\n", - ioat_get_ring_entry(sc, sc->head)->u.generic->next); + ioat_get_descriptor(sc, sc->head)->generic.next); for (idx = 0; idx < (1 << sc->ring_size_order); idx++) if ((*sc->comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK) - == ioat_get_ring_entry(sc, idx)->hw_desc_bus_addr) + == RING_PHYS_ADDR(sc, idx)) db_printf(" ring[%u] == hardware tail\n", idx); db_printf(" cleanup_lock: "); diff --git a/sys/dev/ioat/ioat_internal.h b/sys/dev/ioat/ioat_internal.h index 419b1fdba270..0ed05fc677f4 100644 --- a/sys/dev/ioat/ioat_internal.h +++ b/sys/dev/ioat/ioat_internal.h @@ -413,19 +413,7 @@ struct bus_dmadesc { struct ioat_descriptor { struct bus_dmadesc bus_dmadesc; - union { - struct ioat_generic_hw_descriptor *generic; - struct ioat_dma_hw_descriptor *dma; - struct ioat_fill_hw_descriptor *fill; - struct ioat_crc32_hw_descriptor *crc32; - struct ioat_xor_hw_descriptor *xor; - struct ioat_xor_ext_hw_descriptor *xor_ext; - struct ioat_pq_hw_descriptor *pq; - struct ioat_pq_ext_hw_descriptor *pq_ext; - struct ioat_raw_hw_descriptor *raw; - } u; uint32_t id; - bus_addr_t hw_desc_bus_addr; }; /* Unused by this driver at this time. */ @@ -487,7 +475,6 @@ struct ioat_softc { boolean_t quiescing; boolean_t destroying; boolean_t is_submitter_processing; - boolean_t is_resize_pending; boolean_t is_completion_pending; /* submit_lock */ boolean_t is_reset_pending; boolean_t is_channel_running; @@ -501,7 +488,22 @@ struct ioat_softc { uint32_t ring_size_order; bus_addr_t last_seen; - struct ioat_descriptor **ring; + struct ioat_descriptor *ring; + + union ioat_hw_descriptor { + struct ioat_generic_hw_descriptor generic; + struct ioat_dma_hw_descriptor dma; + struct ioat_fill_hw_descriptor fill; + struct ioat_crc32_hw_descriptor crc32; + struct ioat_xor_hw_descriptor xor; + struct ioat_xor_ext_hw_descriptor xor_ext; + struct ioat_pq_hw_descriptor pq; + struct ioat_pq_ext_hw_descriptor pq_ext; + struct ioat_raw_hw_descriptor raw; + } *hw_desc_ring; + bus_addr_t hw_desc_bus_addr; +#define RING_PHYS_ADDR(sc, i) (sc)->hw_desc_bus_addr + \ + (((i) % (1 << (sc)->ring_size_order)) * sizeof(struct ioat_dma_hw_descriptor)) struct mtx cleanup_lock; volatile uint32_t refcnt; diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index 19d8a5b08f0f..854c9e5a697d 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -5071,18 +5071,6 @@ iwm_nic_error(struct iwm_softc *sc) } #endif -#define SYNC_RESP_STRUCT(_var_, _pkt_) \ -do { \ - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);\ - _var_ = (void *)((_pkt_)+1); \ -} while (/*CONSTCOND*/0) - -#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_) \ -do { \ - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);\ - _ptr_ = (void *)((_pkt_)+1); \ -} while (/*CONSTCOND*/0) - #define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT); /* @@ -5105,12 +5093,12 @@ iwm_notif_intr(struct iwm_softc *sc) */ while (sc->rxq.cur != hw) { struct iwm_rx_ring *ring = &sc->rxq; - struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur]; + struct iwm_rx_data *data = &ring->data[ring->cur]; struct iwm_rx_packet *pkt; struct iwm_cmd_response *cresp; int qid, idx, code; - bus_dmamap_sync(sc->rxq.data_dmat, data->map, + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); pkt = mtod(data->m, struct iwm_rx_packet *); @@ -5120,7 +5108,7 @@ iwm_notif_intr(struct iwm_softc *sc) code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code); IWM_DPRINTF(sc, IWM_DEBUG_INTR, "rx packet qid=%d idx=%d type=%x %d %d\n", - pkt->hdr.qid & ~0x80, pkt->hdr.idx, code, sc->rxq.cur, hw); + pkt->hdr.qid & ~0x80, pkt->hdr.idx, code, ring->cur, hw); /* * randomly get these from the firmware, no idea why. @@ -5152,7 +5140,7 @@ iwm_notif_intr(struct iwm_softc *sc) /* XXX look at mac_id to determine interface ID */ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - SYNC_RESP_STRUCT(resp, pkt); + resp = (void *)pkt->data; missed = le32toh(resp->consec_missed_beacons); IWM_DPRINTF(sc, IWM_DEBUG_BEACON | IWM_DEBUG_STATE, @@ -5192,7 +5180,7 @@ iwm_notif_intr(struct iwm_softc *sc) struct iwm_mvm_alive_resp_v3 *resp3; if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) { - SYNC_RESP_STRUCT(resp1, pkt); + resp1 = (void *)pkt->data; sc->sc_uc.uc_error_event_table = le32toh(resp1->error_event_table_ptr); sc->sc_uc.uc_log_event_table @@ -5205,7 +5193,7 @@ iwm_notif_intr(struct iwm_softc *sc) } if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) { - SYNC_RESP_STRUCT(resp2, pkt); + resp2 = (void *)pkt->data; sc->sc_uc.uc_error_event_table = le32toh(resp2->error_event_table_ptr); sc->sc_uc.uc_log_event_table @@ -5220,7 +5208,7 @@ iwm_notif_intr(struct iwm_softc *sc) } if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) { - SYNC_RESP_STRUCT(resp3, pkt); + resp3 = (void *)pkt->data; sc->sc_uc.uc_error_event_table = le32toh(resp3->error_event_table_ptr); sc->sc_uc.uc_log_event_table @@ -5240,7 +5228,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_CALIB_RES_NOTIF_PHY_DB: { struct iwm_calib_res_notif_phy_db *phy_db_notif; - SYNC_RESP_STRUCT(phy_db_notif, pkt); + phy_db_notif = (void *)pkt->data; iwm_phy_db_set_section(sc, phy_db_notif); @@ -5248,7 +5236,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_STATISTICS_NOTIFICATION: { struct iwm_notif_statistics *stats; - SYNC_RESP_STRUCT(stats, pkt); + stats = (void *)pkt->data; memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats)); sc->sc_noise = iwm_get_noise(sc, &stats->rx.general); break; } @@ -5256,8 +5244,6 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_NVM_ACCESS_CMD: case IWM_MCC_UPDATE_CMD: if (sc->sc_wantresp == ((qid << 16) | idx)) { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); memcpy(sc->sc_cmd_resp, pkt, sizeof(sc->sc_cmd_resp)); } @@ -5265,7 +5251,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_MCC_CHUB_UPDATE_CMD: { struct iwm_mcc_chub_notif *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; sc->sc_fw_mcc[0] = (notif->mcc & 0xff00) >> 8; sc->sc_fw_mcc[1] = notif->mcc & 0xff; @@ -5298,7 +5284,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_LQ_CMD: case IWM_BT_CONFIG: case IWM_REPLY_THERMAL_MNG_BACKOFF: - SYNC_RESP_STRUCT(cresp, pkt); + cresp = (void *)pkt->data; if (sc->sc_wantresp == ((qid << 16) | idx)) { memcpy(sc->sc_cmd_resp, pkt, sizeof(*pkt)+sizeof(*cresp)); @@ -5316,20 +5302,20 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_SCAN_OFFLOAD_COMPLETE: { struct iwm_periodic_scan_complete *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; break; } case IWM_SCAN_ITERATION_COMPLETE: { struct iwm_lmac_scan_complete_notif *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task); break; } case IWM_SCAN_COMPLETE_UMAC: { struct iwm_umac_scan_complete *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan complete, status=0x%x\n", @@ -5342,7 +5328,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_SCAN_ITERATION_COMPLETE_UMAC: { struct iwm_umac_scan_iter_complete_notif *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan iteration " "complete, status=0x%x, %d channels scanned\n", @@ -5353,7 +5339,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_REPLY_ERROR: { struct iwm_error_resp *resp; - SYNC_RESP_STRUCT(resp, pkt); + resp = (void *)pkt->data; device_printf(sc->sc_dev, "firmware error 0x%x, cmd 0x%x\n", @@ -5364,7 +5350,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_TIME_EVENT_NOTIFICATION: { struct iwm_time_event_notif *notif; - SYNC_RESP_STRUCT(notif, pkt); + notif = (void *)pkt->data; IWM_DPRINTF(sc, IWM_DEBUG_INTR, "TE notif status = 0x%x action = 0x%x\n", @@ -5377,7 +5363,7 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_SCD_QUEUE_CFG: { struct iwm_scd_txq_cfg_rsp *rsp; - SYNC_RESP_STRUCT(rsp, pkt); + rsp = (void *)pkt->data; IWM_DPRINTF(sc, IWM_DEBUG_CMD, "queue cfg token=0x%x sta_id=%d " @@ -5893,6 +5879,8 @@ iwm_attach(device_t dev) IEEE80211_C_SHPREAMBLE /* short preamble supported */ // IEEE80211_C_BGSCAN /* capable of bg scanning */ ; + /* Advertise full-offload scanning */ + ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD; for (i = 0; i < nitems(sc->sc_phyctxt); i++) { sc->sc_phyctxt[i].id = i; sc->sc_phyctxt[i].color = 0; diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 9e84290a69a3..b6124ba03915 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1376,6 +1376,7 @@ mpr_get_tunables(struct mpr_softc *sc) sc->max_io_pages = MPR_MAXIO_PAGES; sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; + sc->use_phynum = 1; /* * Grab the global variables. @@ -1387,6 +1388,7 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.max_io_pages", &sc->max_io_pages); TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); + TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", @@ -1421,6 +1423,10 @@ mpr_get_tunables(struct mpr_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time", device_get_unit(sc->mpr_dev)); TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.use_phy_num", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum); } static void @@ -1510,6 +1516,10 @@ mpr_setup_sysctl(struct mpr_softc *sc) OID_AUTO, "spinup_wait_time", CTLFLAG_RD, &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " "spinup after SATA ID error"); + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0, + "Use the phy number for enumeration"); } int diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 640338a19d37..84fa2aff53d7 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -757,13 +757,24 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ } } - id = mpr_mapping_get_sas_id(sc, sas_address, handle); + /* + * use_phynum: + * 1 - use the PhyNum field as a fallback to the mapping logic + * 0 - never use the PhyNum field + * -1 - only use the PhyNum field + */ + id = MPR_MAP_BAD_ID; + if (sc->use_phynum != -1) + id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { - printf("failure at %s:%d/%s()! Could not get ID for device " - "with handle 0x%04x\n", __FILE__, __LINE__, __func__, - handle); - error = ENXIO; - goto out; + if ((sc->use_phynum == 0) + || ((id = config_page.PhyNum) > sassc->maxtargets)) { + mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! " + "Could not get ID for device with handle 0x%04x\n", + __FILE__, __LINE__, __func__, handle); + error = ENXIO; + goto out; + } } if (mprsas_check_id(sassc, id) != 0) { @@ -772,9 +783,16 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ goto out; } + targ = &sassc->targets[id]; + if (targ->handle != 0x0) { + mpr_dprint(sc, MPR_MAPPING, "Attempting to reuse target id " + "%d handle 0x%04x\n", id, targ->handle); + error = ENXIO; + goto out; + } + mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); - targ = &sassc->targets[id]; targ->devinfo = device_info; targ->devname = le32toh(config_page.DeviceName.High); targ->devname = (targ->devname << 32) | diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index b3a61f4935ff..0a9ccb61f378 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -271,6 +271,7 @@ struct mpr_softc { uint16_t chain_seg_size; u_int enable_ssu; int spinup_wait_time; + int use_phynum; uint64_t chain_alloc_fail; struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 7f9cf0ba4449..1357da8627bf 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1353,6 +1353,7 @@ mps_get_tunables(struct mps_softc *sc) sc->max_io_pages = MPS_MAXIO_PAGES; sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD; sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; + sc->use_phynum = 1; /* * Grab the global variables. @@ -1364,6 +1365,7 @@ mps_get_tunables(struct mps_softc *sc) TUNABLE_INT_FETCH("hw.mps.max_io_pages", &sc->max_io_pages); TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu); TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time); + TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level", @@ -1398,6 +1400,10 @@ mps_get_tunables(struct mps_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time", device_get_unit(sc->mps_dev)); TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.use_phy_num", + device_get_unit(sc->mps_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum); } static void @@ -1495,6 +1501,10 @@ mps_setup_sysctl(struct mps_softc *sc) SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, mps_mapping_encl_dump, "A", "Enclosure Table Dump"); + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0, + "Use the phy number for enumeration"); } int diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index 2f23612204f3..2ff4389a1a25 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -1872,6 +1872,10 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) } } +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (csio->bio != NULL) + biotrack(csio->bio, __func__); +#endif callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, mpssas_scsiio_timeout, cm, 0); @@ -2125,6 +2129,11 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + if (ccb->csio.bio != NULL) + biotrack(ccb->csio.bio, __func__); +#endif + if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) { TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); if (cm->cm_reply != NULL) diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index c04a78af0b2c..0a614e01e115 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -669,13 +669,24 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ } } - id = mps_mapping_get_sas_id(sc, sas_address, handle); + /* + * use_phynum: + * 1 - use the PhyNum field as a fallback to the mapping logic + * 0 - never use the PhyNum field + * -1 - only use the PhyNum field + */ + id = MPS_MAP_BAD_ID; + if (sc->use_phynum != -1) + id = mps_mapping_get_sas_id(sc, sas_address, handle); if (id == MPS_MAP_BAD_ID) { - printf("failure at %s:%d/%s()! Could not get ID for device " - "with handle 0x%04x\n", __FILE__, __LINE__, __func__, - handle); - error = ENXIO; - goto out; + if ((sc->use_phynum == 0) + || ((id = config_page.PhyNum) > sassc->maxtargets)) { + mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! " + "Could not get ID for device with handle 0x%04x\n", + __FILE__, __LINE__, __func__, handle); + error = ENXIO; + goto out; + } } if (mpssas_check_id(sassc, id) != 0) { @@ -684,9 +695,16 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ goto out; } + targ = &sassc->targets[id]; + if (targ->handle != 0x0) { + mps_dprint(sc, MPS_MAPPING, "Attempting to reuse target id " + "%d handle 0x%04x\n", id, targ->handle); + error = ENXIO; + goto out; + } + mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); - targ = &sassc->targets[id]; targ->devinfo = device_info; targ->devname = le32toh(config_page.DeviceName.High); targ->devname = (targ->devname << 32) | diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index f3a8929b131e..d8cda89dfc12 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -285,6 +285,7 @@ struct mps_softc { int chain_free_lowwater; u_int enable_ssu; int spinup_wait_time; + int use_phynum; uint64_t chain_alloc_fail; struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; diff --git a/sys/arm/freescale/imx/imx_sdhci.c b/sys/dev/sdhci/fsl_sdhci.c similarity index 79% rename from sys/arm/freescale/imx/imx_sdhci.c rename to sys/dev/sdhci/fsl_sdhci.c index 39c9508c7711..b691756c8b7b 100644 --- a/sys/arm/freescale/imx/imx_sdhci.c +++ b/sys/dev/sdhci/fsl_sdhci.c @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD$"); /* - * SDHCI driver glue for Freescale i.MX SoC family. + * SDHCI driver glue for Freescale i.MX SoC and QorIQ families. * * This supports both eSDHC (earlier SoCs) and uSDHC (more recent SoCs). */ @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -52,9 +53,11 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __arm__ #include #include +#endif #include #include @@ -66,7 +69,7 @@ __FBSDID("$FreeBSD$"); #include #include "sdhci_if.h" -struct imx_sdhci_softc { +struct fsl_sdhci_softc { device_t dev; struct resource * mem_res; struct resource * irq_res; @@ -88,8 +91,8 @@ struct imx_sdhci_softc { #define R1BFIX_AC12 2 /* Wait for busy after auto command 12. */ #define HWTYPE_NONE 0 /* Hardware not recognized/supported. */ -#define HWTYPE_ESDHC 1 /* imx5x and earlier. */ -#define HWTYPE_USDHC 2 /* imx6. */ +#define HWTYPE_ESDHC 1 /* fsl5x and earlier. */ +#define HWTYPE_USDHC 2 /* fsl6. */ /* * Freescale-specific registers, or in some cases the layout of bits within the @@ -146,7 +149,6 @@ struct imx_sdhci_softc { #define SDHC_PROT_CDSS (1 << 7) #define SDHC_SYS_CTRL 0x2c -#define SDHC_INT_STATUS 0x30 /* * The clock enable bits exist in different registers for ESDHC vs USDHC, but @@ -169,31 +171,32 @@ static struct ofw_compat_data compat_data[] = { {"fsl,imx6sl-usdhc", HWTYPE_USDHC}, {"fsl,imx53-esdhc", HWTYPE_ESDHC}, {"fsl,imx51-esdhc", HWTYPE_ESDHC}, + {"fsl,esdhc", HWTYPE_ESDHC}, {NULL, HWTYPE_NONE}, }; -static uint16_t imx_sdhc_get_clock(struct imx_sdhci_softc *sc); -static void imx_sdhc_set_clock(struct imx_sdhci_softc *sc, uint16_t val); -static void imx_sdhci_r1bfix_func(void *arg); +static uint16_t fsl_sdhc_get_clock(struct fsl_sdhci_softc *sc); +static void fsl_sdhc_set_clock(struct fsl_sdhci_softc *sc, uint16_t val); +static void fsl_sdhci_r1bfix_func(void *arg); static inline uint32_t -RD4(struct imx_sdhci_softc *sc, bus_size_t off) +RD4(struct fsl_sdhci_softc *sc, bus_size_t off) { return (bus_read_4(sc->mem_res, off)); } static inline void -WR4(struct imx_sdhci_softc *sc, bus_size_t off, uint32_t val) +WR4(struct fsl_sdhci_softc *sc, bus_size_t off, uint32_t val) { bus_write_4(sc->mem_res, off, val); } static uint8_t -imx_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) +fsl_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); uint32_t val32, wrk32; /* @@ -246,9 +249,9 @@ imx_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) } static uint16_t -imx_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) +fsl_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; if (sc->hwtype == HWTYPE_USDHC) { @@ -297,16 +300,16 @@ imx_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) * hardware type, complex enough to have their own function. */ if (off == SDHCI_CLOCK_CONTROL) { - return (imx_sdhc_get_clock(sc)); + return (fsl_sdhc_get_clock(sc)); } return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff); } static uint32_t -imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) +fsl_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); uint32_t val32, wrk32; val32 = RD4(sc, off); @@ -348,7 +351,7 @@ imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) } /* - * imx_sdhci_intr() can synthesize a DATA_END interrupt following a + * fsl_sdhci_intr() can synthesize a DATA_END interrupt following a * command with an R1B response, mix it into the hardware status. */ if (off == SDHCI_INT_STATUS) { @@ -359,18 +362,18 @@ imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) } static void -imx_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, +fsl_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); bus_read_multi_4(sc->mem_res, off, data, count); } static void -imx_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val) +fsl_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; /* @@ -397,6 +400,11 @@ imx_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t if (off == SDHCI_POWER_CONTROL) { return; } +#ifdef __powerpc__ + /* XXX Reset doesn't seem to work as expected. Do nothing for now. */ + if (off == SDHCI_SOFTWARE_RESET) + return; +#endif val32 = RD4(sc, off & ~3); val32 &= ~(0xff << (off & 3) * 8); @@ -406,9 +414,9 @@ imx_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t } static void -imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val) +fsl_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; /* @@ -416,7 +424,7 @@ imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_ * that can handle the ESDHC versus USDHC differences. */ if (off == SDHCI_CLOCK_CONTROL) { - imx_sdhc_set_clock(sc, val); + fsl_sdhc_set_clock(sc, val); return; } @@ -432,7 +440,7 @@ imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_ * there's a control bit for it (bit 3) in the vendor register. * When we're starting a command that needs a manual DAT0 line check at * interrupt time, we leave ourselves a note in r1bfix_type so that we - * can do the extra work in imx_sdhci_intr(). + * can do the extra work in fsl_sdhci_intr(). */ if (off == SDHCI_COMMAND_FLAGS) { if (val & SDHCI_CMD_DATA) { @@ -485,9 +493,9 @@ imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_ } static void -imx_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val) +fsl_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); /* Clear synthesized interrupts, then pass the value to the hardware. */ if (off == SDHCI_INT_STATUS) { @@ -498,16 +506,16 @@ imx_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_ } static void -imx_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, +fsl_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); bus_write_multi_4(sc->mem_res, off, data, count); } static uint16_t -imx_sdhc_get_clock(struct imx_sdhci_softc *sc) +fsl_sdhc_get_clock(struct fsl_sdhci_softc *sc) { uint16_t val; @@ -531,17 +539,20 @@ imx_sdhc_get_clock(struct imx_sdhci_softc *sc) val |= SDHCI_CLOCK_INT_STABLE; /* - * On ESDHC hardware the card bus clock enable is in the usual sdhci - * register but it's a different bit, so transcribe it (note the + * On i.MX ESDHC hardware the card bus clock enable is in the usual + * sdhci register but it's a different bit, so transcribe it (note the * difference between standard SDHCI_ and Freescale SDHC_ prefixes - * here). On USDHC hardware there is a force-on bit, but no force-off - * for the card bus clock (the hardware runs the clock when transfers - * are active no matter what), so we always say the clock is on. + * here). On USDHC and QorIQ ESDHC hardware there is a force-on bit, but + * no force-off for the card bus clock (the hardware runs the clock when + * transfers are active no matter what), so we always say the clock is + * on. * XXX Maybe we should say it's in whatever state the sdhci driver last * set it to. */ if (sc->hwtype == HWTYPE_ESDHC) { +#ifdef __arm__ if (RD4(sc, SDHC_SYS_CTRL) & SDHC_CLK_SDCLKEN) +#endif val |= SDHCI_CLOCK_CARD_EN; } else { val |= SDHCI_CLOCK_CARD_EN; @@ -551,7 +562,7 @@ imx_sdhc_get_clock(struct imx_sdhci_softc *sc) } static void -imx_sdhc_set_clock(struct imx_sdhci_softc *sc, uint16_t val) +fsl_sdhc_set_clock(struct fsl_sdhci_softc *sc, uint16_t val) { uint32_t divisor, freq, prescale, val32; @@ -565,15 +576,18 @@ imx_sdhc_set_clock(struct imx_sdhci_softc *sc, uint16_t val) sc->sdclockreg_freq_bits = val & SDHCI_DIVIDERS_MASK; if (sc->hwtype == HWTYPE_ESDHC) { /* - * The ESDHC hardware requires the driver to manually start and - * stop the sd bus clock. If the enable bit is not set, turn - * off the clock in hardware and we're done, otherwise decode - * the requested frequency. ESDHC hardware is sdhci 2.0; the - * sdhci driver will use the original 8-bit divisor field and - * the "base / 2^N" divisor scheme. + * The i.MX5 ESDHC hardware requires the driver to manually + * start and stop the sd bus clock. If the enable bit is not + * set, turn off the clock in hardware and we're done, otherwise + * decode the requested frequency. ESDHC hardware is sdhci 2.0; + * the sdhci driver will use the original 8-bit divisor field + * and the "base / 2^N" divisor scheme. */ if ((val & SDHCI_CLOCK_CARD_EN) == 0) { +#ifdef __arm__ + /* On QorIQ, this is a reserved bit. */ WR4(sc, SDHCI_CLOCK_CONTROL, val32 & ~SDHC_CLK_SDCLKEN); +#endif return; } @@ -625,11 +639,12 @@ imx_sdhc_set_clock(struct imx_sdhci_softc *sc, uint16_t val) val32 &= ~(SDHC_CLK_DIVISOR_MASK | SDHC_CLK_PRESCALE_MASK); val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT; val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT; + val32 |= SDHC_CLK_IPGEN; WR4(sc, SDHCI_CLOCK_CONTROL, val32); } static boolean_t -imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc) +fsl_sdhci_r1bfix_is_wait_done(struct fsl_sdhci_softc *sc) { uint32_t inhibit; @@ -646,7 +661,7 @@ imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc) if (inhibit && getsbinuptime() < sc->r1bfix_timeout_at) { callout_reset_sbt(&sc->r1bfix_callout, SBT_1MS, 0, - imx_sdhci_r1bfix_func, sc, 0); + fsl_sdhci_r1bfix_func, sc, 0); return (false); } @@ -670,22 +685,22 @@ imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc) } static void -imx_sdhci_r1bfix_func(void * arg) +fsl_sdhci_r1bfix_func(void * arg) { - struct imx_sdhci_softc *sc = arg; + struct fsl_sdhci_softc *sc = arg; boolean_t r1bwait_done; mtx_lock(&sc->slot.mtx); - r1bwait_done = imx_sdhci_r1bfix_is_wait_done(sc); + r1bwait_done = fsl_sdhci_r1bfix_is_wait_done(sc); mtx_unlock(&sc->slot.mtx); if (r1bwait_done) sdhci_generic_intr(&sc->slot); } static void -imx_sdhci_intr(void *arg) +fsl_sdhci_intr(void *arg) { - struct imx_sdhci_softc *sc = arg; + struct fsl_sdhci_softc *sc = arg; uint32_t intmask; mtx_lock(&sc->slot.mtx); @@ -710,10 +725,10 @@ imx_sdhci_intr(void *arg) */ switch (sc->r1bfix_type) { case R1BFIX_NODATA: - intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_RESPONSE; + intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_RESPONSE; break; case R1BFIX_AC12: - intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_DATA_END; + intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_DATA_END; break; default: intmask = 0; @@ -721,9 +736,9 @@ imx_sdhci_intr(void *arg) } if (intmask) { sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS; - if (!imx_sdhci_r1bfix_is_wait_done(sc)) { - WR4(sc, SDHC_INT_STATUS, intmask); - bus_barrier(sc->mem_res, SDHC_INT_STATUS, 4, + if (!fsl_sdhci_r1bfix_is_wait_done(sc)) { + WR4(sc, SDHCI_INT_STATUS, intmask); + bus_barrier(sc->mem_res, SDHCI_INT_STATUS, 4, BUS_SPACE_BARRIER_WRITE); } } @@ -733,31 +748,76 @@ imx_sdhci_intr(void *arg) } static int -imx_sdhci_get_ro(device_t bus, device_t child) +fsl_sdhci_get_ro(device_t bus, device_t child) { + struct fsl_sdhci_softc *sc = device_get_softc(bus); - return (false); + if (RD4(sc, SDHCI_PRESENT_STATE) & SDHC_PRES_WPSPL) + return (false); + return (true); } +#ifdef __powerpc__ +static uint32_t +fsl_sdhci_get_platform_clock(device_t dev) +{ + device_t parent; + phandle_t node; + uint32_t clock; + + node = ofw_bus_get_node(dev); + + /* Get sdhci node properties */ + if((OF_getprop(node, "clock-frequency", (void *)&clock, + sizeof(clock)) <= 0) || (clock == 0)) { + + /* + * Trying to get clock from parent device (soc) if correct + * clock cannot be acquired from sdhci node. + */ + parent = device_get_parent(dev); + node = ofw_bus_get_node(parent); + + /* Get soc properties */ + if ((OF_getprop(node, "bus-frequency", (void *)&clock, + sizeof(clock)) <= 0) || (clock == 0)) { + device_printf(dev,"Cannot acquire correct sdhci " + "frequency from DTS.\n"); + + return (0); + } + /* eSDHC clock is 1/2 platform clock. */ + clock /= 2; + } + + if (bootverbose) + device_printf(dev, "Acquired clock: %d from DTS\n", clock); + + return (clock); +} +#endif + + static int -imx_sdhci_detach(device_t dev) +fsl_sdhci_detach(device_t dev) { return (EBUSY); } static int -imx_sdhci_attach(device_t dev) +fsl_sdhci_attach(device_t dev) { - struct imx_sdhci_softc *sc = device_get_softc(dev); + struct fsl_sdhci_softc *sc = device_get_softc(dev); int rid, err; phandle_t node; + uint32_t protctl; sc->dev = dev; sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (sc->hwtype == HWTYPE_NONE) - panic("Impossible: not compatible in imx_sdhci_attach()"); + panic("Impossible: not compatible in fsl_sdhci_attach()"); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, @@ -778,7 +838,7 @@ imx_sdhci_attach(device_t dev) } if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, imx_sdhci_intr, sc, &sc->intr_cookie)) { + NULL, fsl_sdhci_intr, sc, &sc->intr_cookie)) { device_printf(dev, "cannot setup interrupt handler\n"); err = ENXIO; goto fail; @@ -807,9 +867,23 @@ imx_sdhci_attach(device_t dev) * * XXX need named constants for this stuff. */ - WR4(sc, SDHC_WTMK_LVL, 0x08800880); +#ifdef __powerpc__ + /* P1022 has the '*_BRST_LEN' fields as reserved, always reading 0x10 */ + if ((SVR_VER(mfspr(SPR_SVR)) & 0xfff6) == SVR_P1022 ) + WR4(sc, SDHC_WTMK_LVL, 0x10801080); + else +#endif + WR4(sc, SDHC_WTMK_LVL, 0x08800880); + /* + * We read in native byte order in the main driver, but the register + * defaults to little endian. + */ +#ifdef __powerpc__ + sc->baseclk_hz = fsl_sdhci_get_platform_clock(dev); +#else sc->baseclk_hz = imx_ccm_sdhci_hz(); +#endif sc->slot.max_clk = sc->baseclk_hz; /* @@ -830,6 +904,16 @@ imx_sdhci_attach(device_t dev) /* XXX put real gpio hookup here. */ sc->force_card_present = true; } +#ifdef __powerpc__ + /* Default to big-endian on powerpc */ + protctl = RD4(sc, SDHC_PROT_CTRL); + protctl &= ~SDHC_PROT_EMODE_MASK; + if (OF_hasprop(node, "little-endian")) + protctl |= SDHC_PROT_EMODE_LITTLE; + else + protctl |= SDHC_PROT_EMODE_BIG; + WR4(sc, SDHC_PROT_CTRL, protctl); +#endif callout_init(&sc->r1bfix_callout, 1); sdhci_init_slot(dev, &sc->slot, 0); @@ -853,7 +937,7 @@ imx_sdhci_attach(device_t dev) } static int -imx_sdhci_probe(device_t dev) +fsl_sdhci_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) @@ -872,11 +956,11 @@ imx_sdhci_probe(device_t dev) return (ENXIO); } -static device_method_t imx_sdhci_methods[] = { +static device_method_t fsl_sdhci_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, imx_sdhci_probe), - DEVMETHOD(device_attach, imx_sdhci_attach), - DEVMETHOD(device_detach, imx_sdhci_detach), + DEVMETHOD(device_probe, fsl_sdhci_probe), + DEVMETHOD(device_attach, fsl_sdhci_attach), + DEVMETHOD(device_detach, fsl_sdhci_detach), /* Bus interface */ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), @@ -886,32 +970,32 @@ static device_method_t imx_sdhci_methods[] = { /* MMC bridge interface */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), DEVMETHOD(mmcbr_request, sdhci_generic_request), - DEVMETHOD(mmcbr_get_ro, imx_sdhci_get_ro), + DEVMETHOD(mmcbr_get_ro, fsl_sdhci_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), /* SDHCI registers accessors */ - DEVMETHOD(sdhci_read_1, imx_sdhci_read_1), - DEVMETHOD(sdhci_read_2, imx_sdhci_read_2), - DEVMETHOD(sdhci_read_4, imx_sdhci_read_4), - DEVMETHOD(sdhci_read_multi_4, imx_sdhci_read_multi_4), - DEVMETHOD(sdhci_write_1, imx_sdhci_write_1), - DEVMETHOD(sdhci_write_2, imx_sdhci_write_2), - DEVMETHOD(sdhci_write_4, imx_sdhci_write_4), - DEVMETHOD(sdhci_write_multi_4, imx_sdhci_write_multi_4), + DEVMETHOD(sdhci_read_1, fsl_sdhci_read_1), + DEVMETHOD(sdhci_read_2, fsl_sdhci_read_2), + DEVMETHOD(sdhci_read_4, fsl_sdhci_read_4), + DEVMETHOD(sdhci_read_multi_4, fsl_sdhci_read_multi_4), + DEVMETHOD(sdhci_write_1, fsl_sdhci_write_1), + DEVMETHOD(sdhci_write_2, fsl_sdhci_write_2), + DEVMETHOD(sdhci_write_4, fsl_sdhci_write_4), + DEVMETHOD(sdhci_write_multi_4, fsl_sdhci_write_multi_4), { 0, 0 } }; -static devclass_t imx_sdhci_devclass; +static devclass_t fsl_sdhci_devclass; -static driver_t imx_sdhci_driver = { - "sdhci_imx", - imx_sdhci_methods, - sizeof(struct imx_sdhci_softc), +static driver_t fsl_sdhci_driver = { + "sdhci_fsl", + fsl_sdhci_methods, + sizeof(struct fsl_sdhci_softc), }; -DRIVER_MODULE(sdhci_imx, simplebus, imx_sdhci_driver, imx_sdhci_devclass, 0, 0); -MODULE_DEPEND(sdhci_imx, sdhci, 1, 1, 1); -DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_imx, mmc, 1, 1, 1); +DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass, 0, 0); +MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1); +DRIVER_MODULE(mmc, sdhci_fsl, mmc_driver, mmc_devclass, NULL, NULL); +MODULE_DEPEND(sdhci_fsl, mmc, 1, 1, 1); diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index e625d4f11f32..9ea85adba555 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -1309,7 +1309,7 @@ sdhci_acmd_irq(struct sdhci_slot *slot) void sdhci_generic_intr(struct sdhci_slot *slot) { - uint32_t intmask; + uint32_t intmask, present; SDHCI_LOCK(slot); /* Read slot interrupt status. */ @@ -1323,6 +1323,13 @@ sdhci_generic_intr(struct sdhci_slot *slot) /* Handle card presence interrupts. */ if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { + present = RD4(slot, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT; + slot->intmask &= + ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); + slot->intmask |= present ? SDHCI_INT_CARD_REMOVE : + SDHCI_INT_CARD_INSERT; + WR4(slot, SDHCI_INT_ENABLE, slot->intmask); + WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); WR4(slot, SDHCI_INT_STATUS, intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)); diff --git a/sys/dev/smbus/smbus.c b/sys/dev/smbus/smbus.c index d485094e036f..328c4520a798 100644 --- a/sys/dev/smbus/smbus.c +++ b/sys/dev/smbus/smbus.c @@ -50,7 +50,6 @@ struct smbus_ivar /* * Autoconfiguration and support routines for System Management bus */ -static void smbus_probe_device(device_t dev, u_char addr); static int smbus_probe(device_t dev) @@ -65,13 +64,9 @@ static int smbus_attach(device_t dev) { struct smbus_softc *sc = device_get_softc(dev); - unsigned char addr; mtx_init(&sc->lock, device_get_nameunit(dev), "smbus", MTX_DEF); bus_generic_probe(dev); - for (addr = SMBUS_ADDR_MIN; addr < SMBUS_ADDR_MAX; ++addr) { - smbus_probe_device(dev, addr); - } bus_enumerate_hinted_children(dev); bus_generic_attach(dev); @@ -98,30 +93,6 @@ smbus_generic_intr(device_t dev, u_char devaddr, char low, char high, int err) { } -static void -smbus_probe_device(device_t dev, u_char addr) -{ - device_t child; - int error; - u_char cmd; - u_char buf[2]; - struct smbus_ivar *devi; - - cmd = 0x01; - error = smbus_trans(dev, addr, cmd, - SMB_TRANS_NOCNT | SMB_TRANS_NOREPORT, - NULL, 0, buf, 1, NULL); - if (error == 0) { - if (bootverbose) - device_printf(dev, "Probed address 0x%02x\n", addr); - child = BUS_ADD_CHILD(dev, SMBUS_ORDER_PNP, NULL, -1); - if (child == NULL) - return; - devi = device_get_ivars(child); - devi->addr = addr; - } -} - static device_t smbus_add_child(device_t dev, u_int order, const char *name, int unit) { diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c index 757a96a8b831..a7c0600a34b7 100644 --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -330,10 +330,13 @@ ums_intr_callback(struct usb_xfer *xfer, usb_error_t error) dx, dy, dz, dt, dw, buttons); /* translate T-axis into button presses until further */ - if (dt > 0) + if (dt > 0) { + ums_put_queue(sc, 0, 0, 0, 0, buttons); buttons |= 1UL << 5; - else if (dt < 0) + } else if (dt < 0) { + ums_put_queue(sc, 0, 0, 0, 0, buttons); buttons |= 1UL << 6; + } sc->sc_status.button = buttons; sc->sc_status.dx += dx; diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 52896a844708..a53fb5acf25b 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -350,7 +350,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp, *retdirp = NULL; cnp->cn_nameptr = cnp->cn_pnbuf; - ndp->ni_strictrelative = 0; + ndp->ni_lcf = 0; /* * Extract and set starting directory. */ diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index d74b92e59776..3ccbd583fa2d 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -668,6 +668,7 @@ g_dev_strategy(struct bio *bp) sc = cp->private; KASSERT(cp->acr || cp->acw, ("Consumer with zero access count in g_dev_strategy")); + biotrack(bp, __func__); #ifdef INVARIANTS if ((bp->bio_offset % cp->provider->sectorsize) != 0 || (bp->bio_bcount % cp->provider->sectorsize) != 0) { diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 8c3ec6452cb3..dbaa6b524db3 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -421,6 +421,8 @@ g_disk_start(struct bio *bp) int error; off_t off; + biotrack(bp, __func__); + sc = bp->bio_to->private; if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) { g_io_deliver(bp, ENXIO); diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index dbb346842df7..e192f67d94d4 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -223,6 +223,9 @@ g_clone_bio(struct bio *bp) /* Inherit classification info from the parent */ bp2->bio_classifier1 = bp->bio_classifier1; bp2->bio_classifier2 = bp->bio_classifier2; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + bp2->bio_track_bp = bp->bio_track_bp; +#endif bp->bio_children++; } #ifdef KTR @@ -362,6 +365,8 @@ g_io_check(struct bio *bp) off_t excess; int error; + biotrack(bp, __func__); + cp = bp->bio_from; pp = bp->bio_to; @@ -503,6 +508,8 @@ g_run_classifiers(struct bio *bp) struct g_classifier_hook *hook; int classified = 0; + biotrack(bp, __func__); + TAILQ_FOREACH(hook, &g_classifier_tailq, link) classified |= hook->func(hook->arg, bp); @@ -518,6 +525,8 @@ g_io_request(struct bio *bp, struct g_consumer *cp) int direct, error, first; uint8_t cmd; + biotrack(bp, __func__); + KASSERT(cp != NULL, ("NULL cp in g_io_request")); KASSERT(bp != NULL, ("NULL bp in g_io_request")); pp = cp->provider; @@ -644,6 +653,8 @@ g_io_deliver(struct bio *bp, int error) struct mtx *mtxp; int direct, first; + biotrack(bp, __func__); + KASSERT(bp != NULL, ("NULL bp in g_io_deliver")); pp = bp->bio_to; KASSERT(pp != NULL, ("NULL bio_to in g_io_deliver")); @@ -835,6 +846,7 @@ g_io_schedule_down(struct thread *tp __unused) } CTR0(KTR_GEOM, "g_down has work to do"); g_bioq_unlock(&g_bio_run_down); + biotrack(bp, __func__); if (pace != 0) { /* * There has been at least one memory allocation diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index d0df840945c4..33416063eec6 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -1531,6 +1531,10 @@ DB_SHOW_COMMAND(bio, db_show_bio) db_printf(" caller2: %p\n", bp->bio_caller2); db_printf(" bio_from: %p\n", bp->bio_from); db_printf(" bio_to: %p\n", bp->bio_to); + +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + db_printf(" bio_track_bp: %p\n", bp->bio_track_bp); +#endif } } diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c index eda4b75b0891..c59cc6a569e2 100644 --- a/sys/geom/geom_vfs.c +++ b/sys/geom/geom_vfs.c @@ -192,6 +192,10 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp) } bip->bio_done = g_vfs_done; bip->bio_caller2 = bp; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + buf_track(bp, __func__); + bip->bio_track_bp = bp; +#endif g_io_request(bip, cp); } diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index a7513980e3ba..4f52398ca0b9 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -2154,6 +2154,8 @@ g_part_start(struct bio *bp) struct g_provider *pp; char buf[64]; + biotrack(bp, __func__); + pp = bp->bio_to; gp = pp->geom; table = gp->softc; diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 51e9cf2f738e..b19e4d73b0db 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -1952,6 +1952,7 @@ bufwrite(struct buf *bp) if (oldflags & B_ASYNC) BUF_KERNPROC(bp); bp->b_iooffset = dbtob(bp->b_blkno); + buf_track(bp, __func__); bstrategy(bp); if ((oldflags & B_ASYNC) == 0) { @@ -2078,6 +2079,8 @@ bdwrite(struct buf *bp) VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL); } + buf_track(bp, __func__); + /* * Set the *dirty* buffer range based upon the VM system dirty * pages. @@ -2386,6 +2389,8 @@ brelse(struct buf *bp) brelvp(bp); } + buf_track(bp, __func__); + /* buffers with no memory */ if (bp->b_bufsize == 0) { buf_free(bp); @@ -2470,6 +2475,7 @@ bqrelse(struct buf *bp) binsfree(bp, qindex); out: + buf_track(bp, __func__); /* unlock */ BUF_UNLOCK(bp); if (qindex == QUEUE_CLEAN) @@ -3716,6 +3722,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo, CTR4(KTR_BUF, "getblk(%p, %ld, %d) = %p", vp, (long)blkno, size, bp); BUF_ASSERT_HELD(bp); end: + buf_track(bp, __func__); KASSERT(bp->b_bufobj == bo, ("bp %p wrong b_bufobj %p should be %p", bp, bp->b_bufobj, bo)); return (bp); @@ -3892,6 +3899,7 @@ biodone(struct bio *bp) void (*done)(struct bio *); vm_offset_t start, end; + biotrack(bp, __func__); if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) { bp->bio_flags &= ~BIO_TRANSIENT_MAPPING; bp->bio_flags |= BIO_UNMAPPED; @@ -3948,6 +3956,15 @@ biofinish(struct bio *bp, struct devstat *stat, int error) biodone(bp); } +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) +void +biotrack_buf(struct bio *bp, const char *location) +{ + + buf_track(bp->bio_track_bp, location); +} +#endif + /* * bufwait: * @@ -3998,6 +4015,7 @@ bufdone(struct buf *bp) struct bufobj *dropobj; void (*biodone)(struct buf *); + buf_track(bp, __func__); CTR3(KTR_BUF, "bufdone(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); dropobj = NULL; @@ -4801,6 +4819,9 @@ DB_SHOW_COMMAND(buffer, db_show_buffer) { /* get args */ struct buf *bp = (struct buf *)addr; +#ifdef FULL_BUF_TRACKING + uint32_t i, j; +#endif if (!have_addr) { db_printf("usage: show buffer \n"); @@ -4837,6 +4858,16 @@ DB_SHOW_COMMAND(buffer, db_show_buffer) } db_printf("\n"); } +#if defined(FULL_BUF_TRACKING) + db_printf("b_io_tracking: b_io_tcnt = %u\n", bp->b_io_tcnt); + + i = bp->b_io_tcnt % BUF_TRACKING_SIZE; + for (j = 1; j <= BUF_TRACKING_SIZE; j++) + db_printf(" %2u: %s\n", j, + bp->b_io_tracking[BUF_TRACKING_ENTRY(i - j)]); +#elif defined(BUF_TRACKING) + db_printf("b_io_tracking: %s\n", bp->b_io_tracking); +#endif db_printf(" "); BUF_LOCKPRINTINFO(bp); } diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 018be4860005..532261e8625f 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -1008,6 +1008,7 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len, reassignbuf(tbp); /* put on clean list */ bufobj_wref(tbp->b_bufobj); BUF_KERNPROC(tbp); + buf_track(tbp, __func__); TAILQ_INSERT_TAIL(&bp->b_cluster.cluster_head, tbp, b_cluster.cluster_entry); } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 884900234ac9..56a3fe5bebcf 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -73,21 +73,28 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, entry, "struct vnode *", "char *", "unsigned long"); SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); -/* - * Allocation zone for namei - */ +/* Allocation zone for namei. */ uma_zone_t namei_zone; -/* - * Placeholder vnode for mp traversal - */ + +/* Placeholder vnode for mp traversal. */ static struct vnode *vp_crossmp; +struct nameicap_tracker { + struct vnode *dp; + TAILQ_ENTRY(nameicap_tracker) nm_link; +}; + +/* Zone for cap mode tracker elements used for dotdot capability checks. */ +static uma_zone_t nt_zone; + static void nameiinit(void *dummy __unused) { namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + nt_zone = uma_zcreate("rentr", sizeof(struct nameicap_tracker), + NULL, NULL, NULL, NULL, sizeof(void *), 0); getnewvnode("crossmp", NULL, &dead_vnodeops, &vp_crossmp); vn_lock(vp_crossmp, LK_EXCLUSIVE); VN_LOCK_ASHARE(vp_crossmp); @@ -97,11 +104,82 @@ SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL); static int lookup_shared = 1; SYSCTL_INT(_vfs, OID_AUTO, lookup_shared, CTLFLAG_RWTUN, &lookup_shared, 0, - "Enables/Disables shared locks for path name translation"); + "enables shared locks for path name translation"); + +/* + * Intent is that lookup_cap_dotdot becomes unconditionally enabled, + * but it defaults to the disabled state until verification efforts + * are complete. + */ +static int lookup_cap_dotdot = 0; +SYSCTL_INT(_vfs, OID_AUTO, lookup_cap_dotdot, CTLFLAG_RWTUN, + &lookup_cap_dotdot, 0, + "enables \"..\" components in path lookup in capability mode"); +static int lookup_cap_dotdot_nonlocal = 0; +SYSCTL_INT(_vfs, OID_AUTO, lookup_cap_dotdot_nonlocal, CTLFLAG_RWTUN, + &lookup_cap_dotdot_nonlocal, 0, + "enables \"..\" components in path lookup in capability mode " + "on non-local mount"); + +static void +nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp) +{ + struct nameicap_tracker *nt; + + if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR) + return; + nt = uma_zalloc(nt_zone, M_WAITOK); + vhold(dp); + nt->dp = dp; + TAILQ_INSERT_TAIL(&ndp->ni_cap_tracker, nt, nm_link); +} + +static void +nameicap_cleanup(struct nameidata *ndp) +{ + struct nameicap_tracker *nt, *nt1; + + KASSERT(TAILQ_EMPTY(&ndp->ni_cap_tracker) || + (ndp->ni_lcf & NI_LCF_CAP_DOTDOT) != 0, ("not strictrelative")); + TAILQ_FOREACH_SAFE(nt, &ndp->ni_cap_tracker, nm_link, nt1) { + TAILQ_REMOVE(&ndp->ni_cap_tracker, nt, nm_link); + vdrop(nt->dp); + uma_zfree(nt_zone, nt); + } +} + +/* + * For dotdot lookups in capability mode, only allow the component + * lookup to succeed if the resulting directory was already traversed + * during the operation. Also fail dotdot lookups for non-local + * filesystems, where external agents might assist local lookups to + * escape the compartment. + */ +static int +nameicap_check_dotdot(struct nameidata *ndp, struct vnode *dp) +{ + struct nameicap_tracker *nt; + struct mount *mp; + + if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp == NULL || + dp->v_type != VDIR) + return (0); + mp = dp->v_mount; + if (lookup_cap_dotdot_nonlocal == 0 && mp != NULL && + (mp->mnt_flag & MNT_LOCAL) == 0) + return (ENOTCAPABLE); + TAILQ_FOREACH_REVERSE(nt, &ndp->ni_cap_tracker, nameicap_tracker_head, + nm_link) { + if (dp == nt->dp) + return (0); + } + return (ENOTCAPABLE); +} static void namei_cleanup_cnp(struct componentname *cnp) { + uma_zfree(namei_zone, cnp->cn_pnbuf); #ifdef DIAGNOSTIC cnp->cn_pnbuf = NULL; @@ -115,7 +193,7 @@ namei_handle_root(struct nameidata *ndp, struct vnode **dpp) struct componentname *cnp; cnp = &ndp->ni_cnd; - if (ndp->ni_strictrelative != 0) { + if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0) { #ifdef KTRACE if (KTRPOINT(curthread, KTR_CAPFAIL)) ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); @@ -158,12 +236,16 @@ namei(struct nameidata *ndp) char *cp; /* pointer into pathname argument */ struct vnode *dp; /* the directory we are searching */ struct iovec aiov; /* uio for reading symbolic links */ + struct componentname *cnp; + struct thread *td; + struct proc *p; + cap_rights_t rights; struct uio auio; int error, linklen, startdir_used; - struct componentname *cnp = &ndp->ni_cnd; - struct thread *td = cnp->cn_thread; - struct proc *p = td->td_proc; + cnp = &ndp->ni_cnd; + td = cnp->cn_thread; + p = td->td_proc; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc")); KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0, @@ -175,6 +257,8 @@ namei(struct nameidata *ndp) if (!lookup_shared) cnp->cn_flags &= ~LOCKSHARED; fdp = p->p_fd; + TAILQ_INIT(&ndp->ni_cap_tracker); + ndp->ni_lcf = 0; /* We will set this ourselves if we need it. */ cnp->cn_flags &= ~TRAILINGSLASH; @@ -186,11 +270,11 @@ namei(struct nameidata *ndp) if ((cnp->cn_flags & HASBUF) == 0) cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); if (ndp->ni_segflg == UIO_SYSSPACE) - error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, - MAXPATHLEN, (size_t *)&ndp->ni_pathlen); + error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, + &ndp->ni_pathlen); else - error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, - MAXPATHLEN, (size_t *)&ndp->ni_pathlen); + error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, + &ndp->ni_pathlen); /* * Don't allow empty pathnames. @@ -200,13 +284,21 @@ namei(struct nameidata *ndp) #ifdef CAPABILITY_MODE /* - * In capability mode, lookups must be "strictly relative" (i.e. - * not an absolute path, and not containing '..' components) to - * a real file descriptor, not the pseudo-descriptor AT_FDCWD. + * In capability mode, lookups must be restricted to happen in + * the subtree with the root specified by the file descriptor: + * - The root must be real file descriptor, not the pseudo-descriptor + * AT_FDCWD. + * - The passed path must be relative and not absolute. + * - If lookup_cap_dotdot is disabled, path must not contain the + * '..' components. + * - If lookup_cap_dotdot is enabled, we verify that all '..' + * components lookups result in the directories which were + * previously walked by us, which prevents an escape from + * the relative root. */ if (error == 0 && IN_CAPABILITY_MODE(td) && (cnp->cn_flags & NOCAPCHECK) == 0) { - ndp->ni_strictrelative = 1; + ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; if (ndp->ni_dirfd == AT_FDCWD) { #ifdef KTRACE if (KTRPOINT(td, KTR_CAPFAIL)) @@ -258,8 +350,6 @@ namei(struct nameidata *ndp) dp = fdp->fd_cdir; VREF(dp); } else { - cap_rights_t rights; - rights = ndp->ni_rightsneeded; cap_rights_set(&rights, CAP_LOOKUP); @@ -282,7 +372,7 @@ namei(struct nameidata *ndp) &rights) || ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL || ndp->ni_filecaps.fc_nioctls != -1) { - ndp->ni_strictrelative = 1; + ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; } #endif } @@ -297,6 +387,9 @@ namei(struct nameidata *ndp) vrele(dp); goto out; } + if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && + lookup_cap_dotdot != 0) + ndp->ni_lcf |= NI_LCF_CAP_DOTDOT; SDT_PROBE3(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf, cnp->cn_flags); for (;;) { @@ -313,7 +406,7 @@ namei(struct nameidata *ndp) namei_cleanup_cnp(cnp); } else cnp->cn_flags |= HASBUF; - + nameicap_cleanup(ndp); SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp); return (0); } @@ -387,6 +480,7 @@ namei(struct nameidata *ndp) out: vrele(ndp->ni_rootdir); namei_cleanup_cnp(cnp); + nameicap_cleanup(ndp); SDT_PROBE2(vfs, namei, lookup, return, error, NULL); return (error); } @@ -583,6 +677,8 @@ lookup(struct nameidata *ndp) goto bad; } + nameicap_tracker_add(ndp, dp); + /* * Check for degenerate name (e.g. / or "") * which is a way of talking about a directory, @@ -618,9 +714,8 @@ lookup(struct nameidata *ndp) /* * Handle "..": five special cases. - * 0. If doing a capability lookup, return ENOTCAPABLE (this is a - * fairly conservative design choice, but it's the only one that we - * are satisfied guarantees the property we're looking for). + * 0. If doing a capability lookup and lookup_cap_dotdot is + * disabled, return ENOTCAPABLE. * 1. Return an error if this is the last component of * the name and the operation is DELETE or RENAME. * 2. If at root directory (e.g. after chroot) @@ -632,9 +727,15 @@ lookup(struct nameidata *ndp) * .. in the other filesystem. * 4. If the vnode is the top directory of * the jail or chroot, don't let them out. + * 5. If doing a capability lookup and lookup_cap_dotdot is + * enabled, return ENOTCAPABLE if the lookup would escape + * from the initial file descriptor directory. Checks are + * done by ensuring that namei() already traversed the + * result of dotdot lookup. */ if (cnp->cn_flags & ISDOTDOT) { - if (ndp->ni_strictrelative != 0) { + if ((ndp->ni_lcf & (NI_LCF_STRICTRELATIVE | NI_LCF_CAP_DOTDOT)) + == NI_LCF_STRICTRELATIVE) { #ifdef KTRACE if (KTRPOINT(curthread, KTR_CAPFAIL)) ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); @@ -676,6 +777,14 @@ lookup(struct nameidata *ndp) vn_lock(dp, compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY, ISDOTDOT)); + error = nameicap_check_dotdot(ndp, dp); + if (error != 0) { +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_CAPFAIL)) + ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); +#endif + goto bad; + } } } @@ -735,6 +844,7 @@ lookup(struct nameidata *ndp) vn_lock(dp, compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY, cnp->cn_flags)); + nameicap_tracker_add(ndp, dp); goto unionlookup; } @@ -855,6 +965,16 @@ lookup(struct nameidata *ndp) vrele(ndp->ni_dvp); goto dirloop; } + if (cnp->cn_flags & ISDOTDOT) { + error = nameicap_check_dotdot(ndp, ndp->ni_vp); + if (error != 0) { +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_CAPFAIL)) + ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); +#endif + goto bad2; + } + } if (*ndp->ni_next == '/') { cnp->cn_nameptr = ndp->ni_next; while (*cnp->cn_nameptr == '/') { @@ -1081,7 +1201,6 @@ NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, ndp->ni_dirp = namep; ndp->ni_dirfd = dirfd; ndp->ni_startdir = startdir; - ndp->ni_strictrelative = 0; if (rightsp != NULL) ndp->ni_rightsneeded = *rightsp; else diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 03dc29eb8398..922ad88839aa 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -446,16 +446,19 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, size_t *countp, enum uio_seg bufseg, int flags) { struct mount *mp, *nmp; - struct statfs *sfsp, *sp, sb; + struct statfs *sfsp, *sp, sb, *tofree; size_t count, maxcount; int error; +restart: maxcount = bufsize / sizeof(struct statfs); - if (bufsize == 0) + if (bufsize == 0) { sfsp = NULL; - else if (bufseg == UIO_USERSPACE) + tofree = NULL; + } else if (bufseg == UIO_USERSPACE) { sfsp = *buf; - else /* if (bufseg == UIO_SYSSPACE) */ { + tofree = NULL; + } else /* if (bufseg == UIO_SYSSPACE) */ { count = 0; mtx_lock(&mountlist_mtx); TAILQ_FOREACH(mp, &mountlist, mnt_list) { @@ -464,8 +467,8 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, mtx_unlock(&mountlist_mtx); if (maxcount > count) maxcount = count; - sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, - M_WAITOK); + tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs), + M_TEMP, M_WAITOK); } count = 0; mtx_lock(&mountlist_mtx); @@ -480,9 +483,24 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, continue; } #endif - if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK)) { - nmp = TAILQ_NEXT(mp, mnt_list); - continue; + if (flags == MNT_WAIT) { + if (vfs_busy(mp, MBF_MNTLSTLOCK) != 0) { + /* + * If vfs_busy() failed, and MBF_NOWAIT + * wasn't passed, then the mp is gone. + * Furthermore, because of MBF_MNTLSTLOCK, + * the mountlist_mtx was dropped. We have + * no other choice than to start over. + */ + mtx_unlock(&mountlist_mtx); + free(tofree, M_TEMP); + goto restart; + } + } else { + if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK) != 0) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } } if (sfsp && count < maxcount) { sp = &mp->mnt_stat; @@ -1012,7 +1030,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, * understand exactly what would happen, and we don't think * that it ever should. */ - if (nd.ni_strictrelative == 0 && + if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) == 0 && (error == ENODEV || error == ENXIO) && td->td_dupfd >= 0) { error = dupfdopen(td, fdp, td->td_dupfd, flags, error, @@ -1058,7 +1076,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct filecaps *fcaps; #ifdef CAPABILITIES - if (nd.ni_strictrelative == 1) + if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) != 0) fcaps = &nd.ni_filecaps; else #endif diff --git a/sys/modules/hyperv/netvsc/Makefile b/sys/modules/hyperv/netvsc/Makefile index b27ea406c9cc..1d572cb6fef1 100644 --- a/sys/modules/hyperv/netvsc/Makefile +++ b/sys/modules/hyperv/netvsc/Makefile @@ -4,7 +4,7 @@ ${.CURDIR}/../../../dev/hyperv/vmbus KMOD= hv_netvsc -SRCS= hn_nvs.c hn_rndis.c hv_netvsc_drv_freebsd.c +SRCS= hn_nvs.c hn_rndis.c if_hn.c SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h vmbus_if.h CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/netvsc diff --git a/sys/netinet/cc/cc_cdg.c b/sys/netinet/cc/cc_cdg.c index b9049fb7222b..a92864dea65e 100644 --- a/sys/netinet/cc/cc_cdg.c +++ b/sys/netinet/cc/cc_cdg.c @@ -474,7 +474,9 @@ cdg_cong_signal(struct cc_var *ccv, uint32_t signal_type) ENTER_RECOVERY(CCV(ccv, t_flags)); break; case CC_RTO: - CCV(ccv, snd_ssthresh) = max(2*mss, cwin/2); + CCV(ccv, snd_ssthresh) = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; CCV(ccv, snd_cwnd) = mss; break; default: diff --git a/sys/netinet/cc/cc_chd.c b/sys/netinet/cc/cc_chd.c index fd2f6b8ec1b6..0b8c982ffd12 100644 --- a/sys/netinet/cc/cc_chd.c +++ b/sys/netinet/cc/cc_chd.c @@ -330,13 +330,11 @@ chd_cong_signal(struct cc_var *ccv, uint32_t signal_type) struct ertt *e_t; struct chd *chd_data; int qdly; - uint32_t cwin; u_int mss; e_t = khelp_get_osd(CCV(ccv, osd), ertt_id); chd_data = ccv->cc_data; qdly = imax(e_t->rtt, chd_data->maxrtt_in_rtt) - e_t->minrtt; - cwin = CCV(ccv, snd_cwnd); mss = CCV(ccv, t_maxseg); switch(signal_type) { @@ -378,7 +376,9 @@ chd_cong_signal(struct cc_var *ccv, uint32_t signal_type) ENTER_FASTRECOVERY(CCV(ccv, t_flags)); break; case CC_RTO: - CCV(ccv, snd_ssthresh) = max(2*mss, cwin/2); + CCV(ccv, snd_ssthresh) = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; CCV(ccv, snd_cwnd) = mss; break; diff --git a/sys/netinet/cc/cc_dctcp.c b/sys/netinet/cc/cc_dctcp.c index e79fb19d96da..199cf05fcb63 100644 --- a/sys/netinet/cc/cc_dctcp.c +++ b/sys/netinet/cc/cc_dctcp.c @@ -230,19 +230,21 @@ static void dctcp_cong_signal(struct cc_var *ccv, uint32_t type) { struct dctcp *dctcp_data; - uint32_t cwin; + uint32_t cwin, ssthresh_on_loss; u_int mss; dctcp_data = ccv->cc_data; cwin = CCV(ccv, snd_cwnd); mss = CCV(ccv, t_maxseg); + ssthresh_on_loss = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; switch (type) { case CC_NDUPACK: if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { - CCV(ccv, snd_ssthresh) = mss * - max(cwin / 2 / mss, 2); + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; dctcp_data->num_cong_events++; } else { /* cwnd has already updated as congestion @@ -250,8 +252,7 @@ dctcp_cong_signal(struct cc_var *ccv, uint32_t type) * snd_cwnd_prev and recalculate snd_ssthresh */ cwin = CCV(ccv, snd_cwnd_prev); - CCV(ccv, snd_ssthresh) = - max(cwin / 2 / mss, 2) * mss; + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; } ENTER_RECOVERY(CCV(ccv, t_flags)); } @@ -265,8 +266,7 @@ dctcp_cong_signal(struct cc_var *ccv, uint32_t type) if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { if (V_dctcp_slowstart && dctcp_data->num_cong_events++ == 0) { - CCV(ccv, snd_ssthresh) = - mss * max(cwin / 2 / mss, 2); + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; dctcp_data->alpha = MAX_ALPHA_VALUE; dctcp_data->bytes_ecn = 0; dctcp_data->bytes_total = 0; @@ -285,7 +285,7 @@ dctcp_cong_signal(struct cc_var *ccv, uint32_t type) dctcp_update_alpha(ccv); dctcp_data->save_sndnxt += CCV(ccv, t_maxseg); dctcp_data->num_cong_events++; - CCV(ccv, snd_ssthresh) = max(2 * mss, cwin / 2); + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; CCV(ccv, snd_cwnd) = mss; } break; diff --git a/sys/netinet/cc/cc_htcp.c b/sys/netinet/cc/cc_htcp.c index 8842648435c0..4018eaf2542d 100644 --- a/sys/netinet/cc/cc_htcp.c +++ b/sys/netinet/cc/cc_htcp.c @@ -325,7 +325,9 @@ htcp_cong_signal(struct cc_var *ccv, uint32_t type) */ if (CCV(ccv, t_rxtshift) >= 2) htcp_data->t_last_cong = ticks; - CCV(ccv, snd_ssthresh) = max(2 * mss, cwin / 2); + CCV(ccv, snd_ssthresh) = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; CCV(ccv, snd_cwnd) = mss; break; } @@ -518,6 +520,10 @@ htcp_ssthresh_update(struct cc_var *ccv) CCV(ccv, snd_ssthresh) = ((u_long)CCV(ccv, snd_cwnd) * htcp_data->beta) >> HTCP_SHIFT; } + + /* Align ssthresh to MSS boundary */ + CCV(ccv, snd_ssthresh) = (CCV(ccv, snd_ssthresh) / CCV(ccv, t_maxseg)) + * CCV(ccv, t_maxseg); } diff --git a/sys/netinet/cc/cc_newreno.c b/sys/netinet/cc/cc_newreno.c index 3aa16019657d..392a2f21cd84 100644 --- a/sys/netinet/cc/cc_newreno.c +++ b/sys/netinet/cc/cc_newreno.c @@ -182,23 +182,26 @@ newreno_after_idle(struct cc_var *ccv) static void newreno_cong_signal(struct cc_var *ccv, uint32_t type) { - uint32_t cwin; + uint32_t cwin, ssthresh_on_loss; u_int mss; cwin = CCV(ccv, snd_cwnd); mss = CCV(ccv, t_maxseg); + ssthresh_on_loss = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; /* Catch algos which mistakenly leak private signal types. */ KASSERT((type & CC_SIGPRIVMASK) == 0, ("%s: congestion signal type 0x%08x is private\n", __func__, type)); - cwin = max(2*mss, cwin/2); + cwin = max(cwin / 2 / mss, 2) * mss; switch (type) { case CC_NDUPACK: if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { - CCV(ccv, snd_ssthresh) = cwin; + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; CCV(ccv, snd_cwnd) = cwin; } ENTER_RECOVERY(CCV(ccv, t_flags)); @@ -206,13 +209,13 @@ newreno_cong_signal(struct cc_var *ccv, uint32_t type) break; case CC_ECN: if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { - CCV(ccv, snd_ssthresh) = cwin; + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; CCV(ccv, snd_cwnd) = cwin; ENTER_CONGRECOVERY(CCV(ccv, t_flags)); } break; case CC_RTO: - CCV(ccv, snd_ssthresh) = cwin; + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; CCV(ccv, snd_cwnd) = mss; break; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 792818a9231d..63038584274b 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -444,7 +444,8 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type) * ssthresh = max (FlightSize / 2, 2*SMSS) eq (4) */ tp->snd_ssthresh = - max((tp->snd_max - tp->snd_una) / 2, 2 * maxseg); + max((tp->snd_max - tp->snd_una) / 2 / maxseg, 2) + * maxseg; tp->snd_cwnd = maxseg; } break; diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c index 3460036279ed..8d0b69ea6338 100644 --- a/sys/netpfil/ipfw/ip_fw_pfil.c +++ b/sys/netpfil/ipfw/ip_fw_pfil.c @@ -303,11 +303,9 @@ ipfw_check_packet(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, /* * ipfw processing for ethernet packets (in and out). - * Inteface is NULL from ether_demux, and ifp from - * ether_output_frame. */ int -ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, +ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, struct inpcb *inp) { struct ether_header *eh; @@ -348,7 +346,7 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */ args.m = m; /* the packet we are looking at */ - args.oif = dir == PFIL_OUT ? dst: NULL; /* destination, if any */ + args.oif = dir == PFIL_OUT ? ifp: NULL; /* destination, if any */ args.next_hop = NULL; /* we do not support forward yet */ args.next_hop6 = NULL; /* we do not support forward yet */ args.eh = &save_eh; /* MAC header for bridged/MAC packets */ @@ -383,14 +381,13 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, case IP_FW_DUMMYNET: ret = EACCES; - int dir; if (ip_dn_io_ptr == NULL) break; /* i.e. drop */ *m0 = NULL; - dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN); - ip_dn_io_ptr(&m, dir, &args); + dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT; + ip_dn_io_ptr(&m, dir | PROTO_LAYER2, &args); return 0; default: diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h index bfd205fb2002..35bd90095e34 100644 --- a/sys/powerpc/include/spr.h +++ b/sys/powerpc/include/spr.h @@ -698,8 +698,12 @@ #define SVR_MPC8572E 0x80e8 #define SVR_P1011 0x80e5 #define SVR_P1011E 0x80ed +#define SVR_P1013 0x80e7 +#define SVR_P1013E 0x80ef #define SVR_P1020 0x80e4 #define SVR_P1020E 0x80ec +#define SVR_P1022 0x80e6 +#define SVR_P1022E 0x80ee #define SVR_P2010 0x80e3 #define SVR_P2010E 0x80eb #define SVR_P2020 0x80e2 diff --git a/sys/powerpc/mpc85xx/fsl_sdhc.c b/sys/powerpc/mpc85xx/fsl_sdhc.c deleted file mode 100644 index 03e6bdd5089a..000000000000 --- a/sys/powerpc/mpc85xx/fsl_sdhc.c +++ /dev/null @@ -1,1303 +0,0 @@ -/*- - * Copyright (c) 2011-2012 Semihalf - * 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. - */ - -/* - * Driver for Freescale integrated eSDHC controller. - * Limitations: - * - No support for multi-block transfers. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "opt_platform.h" - -#include "mmcbr_if.h" - -#include "fsl_sdhc.h" - -#ifdef DEBUG -#define DPRINTF(fmt, arg...) printf("DEBUG %s(): " fmt, __FUNCTION__, ##arg) -#else -#define DPRINTF(fmt, arg...) -#endif - - -/***************************************************************************** - * Register the driver - *****************************************************************************/ -/* Forward declarations */ -static int fsl_sdhc_probe(device_t); -static int fsl_sdhc_attach(device_t); -static int fsl_sdhc_detach(device_t); - -static int fsl_sdhc_read_ivar(device_t, device_t, int, uintptr_t *); -static int fsl_sdhc_write_ivar(device_t, device_t, int, uintptr_t); - -static int fsl_sdhc_update_ios(device_t, device_t); -static int fsl_sdhc_request(device_t, device_t, struct mmc_request *); -static int fsl_sdhc_get_ro(device_t, device_t); -static int fsl_sdhc_acquire_host(device_t, device_t); -static int fsl_sdhc_release_host(device_t, device_t); - -static device_method_t fsl_sdhc_methods[] = { - /* device_if */ - DEVMETHOD(device_probe, fsl_sdhc_probe), - DEVMETHOD(device_attach, fsl_sdhc_attach), - DEVMETHOD(device_detach, fsl_sdhc_detach), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, fsl_sdhc_read_ivar), - DEVMETHOD(bus_write_ivar, fsl_sdhc_write_ivar), - - /* OFW bus interface */ - DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), - DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), - DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), - DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), - DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), - - /* mmcbr_if */ - DEVMETHOD(mmcbr_update_ios, fsl_sdhc_update_ios), - DEVMETHOD(mmcbr_request, fsl_sdhc_request), - DEVMETHOD(mmcbr_get_ro, fsl_sdhc_get_ro), - DEVMETHOD(mmcbr_acquire_host, fsl_sdhc_acquire_host), - DEVMETHOD(mmcbr_release_host, fsl_sdhc_release_host), - - {0, 0}, -}; - -/* kobj_class definition */ -static driver_t fsl_sdhc_driver = { - "sdhci_fsl", - fsl_sdhc_methods, - sizeof(struct fsl_sdhc_softc) -}; - -static devclass_t fsl_sdhc_devclass; - -DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhc_driver, fsl_sdhc_devclass, 0, 0); -DRIVER_MODULE(mmc, sdhci_fsl, mmc_driver, mmc_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_fsl, mmc, 1, 1, 1); - -/***************************************************************************** - * Private methods - *****************************************************************************/ -static inline int -read4(struct fsl_sdhc_softc *sc, unsigned int offset) -{ - - return bus_space_read_4(sc->bst, sc->bsh, offset); -} - -static inline void -write4(struct fsl_sdhc_softc *sc, unsigned int offset, int value) -{ - - bus_space_write_4(sc->bst, sc->bsh, offset, value); -} - -static inline void -set_bit(struct fsl_sdhc_softc *sc, uint32_t offset, uint32_t mask) -{ - uint32_t x = read4(sc, offset); - - write4(sc, offset, x | mask); -} - -static inline void -clear_bit(struct fsl_sdhc_softc *sc, uint32_t offset, uint32_t mask) -{ - uint32_t x = read4(sc, offset); - - write4(sc, offset, x & ~mask); -} - -static int -wait_for_bit_clear(struct fsl_sdhc_softc *sc, enum sdhc_reg_off reg, - uint32_t bit) -{ - uint32_t timeout = 10; - uint32_t stat; - - stat = read4(sc, reg); - while (stat & bit) { - if (timeout == 0) { - return (-1); - } - --timeout; - DELAY(1000); - stat = read4(sc, reg); - } - - return (0); -} - -static int -wait_for_free_line(struct fsl_sdhc_softc *sc, enum sdhc_line line) -{ - uint32_t timeout = 100; - uint32_t stat; - - stat = read4(sc, SDHC_PRSSTAT); - while (stat & line) { - if (timeout == 0) { - return (-1); - } - --timeout; - DELAY(1000); - stat = read4(sc, SDHC_PRSSTAT); - } - - return (0); -} - -static uint32_t -get_platform_clock(struct fsl_sdhc_softc *sc) -{ - device_t self, parent; - phandle_t node; - uint32_t clock; - - self = sc->self; - node = ofw_bus_get_node(self); - - /* Get sdhci node properties */ - if((OF_getprop(node, "clock-frequency", (void *)&clock, - sizeof(clock)) <= 0) || (clock == 0)) { - - /* - * Trying to get clock from parent device (soc) if correct - * clock cannot be acquired from sdhci node. - */ - parent = device_get_parent(self); - node = ofw_bus_get_node(parent); - - /* Get soc properties */ - if ((OF_getprop(node, "bus-frequency", (void *)&clock, - sizeof(clock)) <= 0) || (clock == 0)) { - device_printf(self,"Cannot acquire correct sdhci " - "frequency from DTS.\n"); - - return (0); - } - } - - DPRINTF("Acquired clock: %d from DTS\n", clock); - - return (clock); -} - -/** - * Set clock driving card. - * @param sc - * @param clock Desired clock frequency in Hz - */ -static void -set_clock(struct fsl_sdhc_softc *sc, uint32_t clock) -{ - uint32_t base_clock; - uint32_t divisor, prescaler = 1; - uint32_t round = 0; - - if (clock == sc->slot.clock) - return; - - if (clock == 0) { - clear_bit(sc, SDHC_SYSCTL, MASK_CLOCK_CONTROL | SYSCTL_PEREN | - SYSCTL_HCKEN | SYSCTL_IPGEN); - return; - } - - base_clock = sc->platform_clock; - round = base_clock & 0x2; - base_clock >>= 2; - base_clock += round; - round = 0; - - /* SD specification 1.1 doesn't allow frequences above 50 MHz */ - if (clock > FSL_SDHC_MAX_CLOCK) - clock = FSL_SDHC_MAX_CLOCK; - - /* - * divisor = ceil(base_clock / clock) - * TODO: Reconsider symmetric rounding here instead of ceiling. - */ - divisor = howmany(base_clock, clock); - - while (divisor > 16) { - round = divisor & 0x1; - divisor >>= 1; - - prescaler <<= 1; - } - divisor += round - 1; - - /* Turn off the clock. */ - clear_bit(sc, SDHC_SYSCTL, MASK_CLOCK_CONTROL); - - /* Write clock settings. */ - set_bit(sc, SDHC_SYSCTL, (prescaler << SHIFT_SDCLKFS) | - (divisor << SHIFT_DVS)); - - /* - * Turn on clocks. - * TODO: This actually disables clock automatic gating off feature of - * the controller which eventually should be enabled but as for now - * it prevents controller from generating card insertion/removal - * interrupts correctly. - */ - set_bit(sc, SDHC_SYSCTL, SYSCTL_PEREN | SYSCTL_HCKEN | SYSCTL_IPGEN); - - sc->slot.clock = clock; - - DPRINTF("given clock = %d, computed clock = %d\n", clock, - (base_clock / prescaler) / (divisor + 1)); -} - -static inline void -send_80_clock_ticks(struct fsl_sdhc_softc *sc) -{ - int err; - - err = wait_for_free_line(sc, SDHC_CMD_LINE | SDHC_DAT_LINE); - if (err != 0) { - device_printf(sc->self, "Can't acquire data/cmd lines\n"); - return; - } - - set_bit(sc, SDHC_SYSCTL, SYSCTL_INITA); - err = wait_for_bit_clear(sc, SDHC_SYSCTL, SYSCTL_INITA); - if (err != 0) { - device_printf(sc->self, "Can't send 80 clocks to the card.\n"); - } -} - -static void -set_bus_width(struct fsl_sdhc_softc *sc, enum mmc_bus_width width) -{ - - DPRINTF("setting bus width to %d\n", width); - switch (width) { - case bus_width_1: - set_bit(sc, SDHC_PROCTL, DTW_1); - break; - case bus_width_4: - set_bit(sc, SDHC_PROCTL, DTW_4); - break; - case bus_width_8: - set_bit(sc, SDHC_PROCTL, DTW_8); - break; - default: - device_printf(sc->self, "Unsupported bus width\n"); - } -} - -static void -reset_controller_all(struct fsl_sdhc_softc *sc) -{ - uint32_t count = 5; - - set_bit(sc, SDHC_SYSCTL, SYSCTL_RSTA); - while (read4(sc, SDHC_SYSCTL) & SYSCTL_RSTA) { - DELAY(FSL_SDHC_RESET_DELAY); - --count; - if (count == 0) { - device_printf(sc->self, - "Can't reset the controller\n"); - return; - } - } -} - -static void -reset_controller_dat_cmd(struct fsl_sdhc_softc *sc) -{ - int err; - - set_bit(sc, SDHC_SYSCTL, SYSCTL_RSTD | SYSCTL_RSTC); - err = wait_for_bit_clear(sc, SDHC_SYSCTL, SYSCTL_RSTD | SYSCTL_RSTC); - if (err != 0) { - device_printf(sc->self, "Can't reset data & command part!\n"); - return; - } -} - -static void -init_controller(struct fsl_sdhc_softc *sc) -{ - - /* Enable interrupts. */ -#ifdef FSL_SDHC_NO_DMA - write4(sc, SDHC_IRQSTATEN, MASK_IRQ_ALL & ~IRQ_DINT & ~IRQ_DMAE); - write4(sc, SDHC_IRQSIGEN, MASK_IRQ_ALL & ~IRQ_DINT & ~IRQ_DMAE); -#else - write4(sc, SDHC_IRQSTATEN, MASK_IRQ_ALL & ~IRQ_BRR & ~IRQ_BWR); - write4(sc, SDHC_IRQSIGEN, MASK_IRQ_ALL & ~IRQ_BRR & ~IRQ_BWR); - - /* Write DMA address */ - write4(sc, SDHC_DSADDR, sc->dma_phys); - - /* Enable snooping and fix for AHB2MAG bypass. */ - write4(sc, SDHC_DCR, DCR_SNOOP | DCR_AHB2MAG_BYPASS); -#endif - /* Set data timeout. */ - set_bit(sc, SDHC_SYSCTL, 0xe << SHIFT_DTOCV); - - /* Set water-mark levels (FIFO buffer size). */ - write4(sc, SDHC_WML, (FSL_SDHC_FIFO_BUF_WORDS << 16) | - FSL_SDHC_FIFO_BUF_WORDS); -} - -static void -init_mmc_host_struct(struct fsl_sdhc_softc *sc) -{ - struct mmc_host *host = &sc->mmc_host; - - /* Clear host structure. */ - bzero(host, sizeof(struct mmc_host)); - - /* Calculate minimum and maximum operating frequencies. */ - host->f_min = sc->platform_clock / FSL_SDHC_MAX_DIV; - host->f_max = FSL_SDHC_MAX_CLOCK; - - /* Set operation conditions (voltage). */ - host->host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; - - /* Set additional host controller capabilities. */ - host->caps = MMC_CAP_4_BIT_DATA; - - /* Set mode. */ - host->mode = mode_sd; -} - -static void -card_detect_task(void *arg, int pending) -{ - struct fsl_sdhc_softc *sc = (struct fsl_sdhc_softc *)arg; - int err; - int insert; - - insert = read4(sc, SDHC_PRSSTAT) & PRSSTAT_CINS; - - mtx_lock(&sc->mtx); - - if (insert) { - if (sc->child != NULL) { - mtx_unlock(&sc->mtx); - return; - } - - sc->child = device_add_child(sc->self, "mmc", -1); - if (sc->child == NULL) { - device_printf(sc->self, "Couldn't add MMC bus!\n"); - mtx_unlock(&sc->mtx); - return; - } - - /* Initialize MMC bus host structure. */ - init_mmc_host_struct(sc); - device_set_ivars(sc->child, &sc->mmc_host); - - } else { - if (sc->child == NULL) { - mtx_unlock(&sc->mtx); - return; - } - } - - mtx_unlock(&sc->mtx); - - if (insert) { - if ((err = device_probe_and_attach(sc->child)) != 0) { - device_printf(sc->self, "MMC bus failed on probe " - "and attach! error %d\n", err); - device_delete_child(sc->self, sc->child); - sc->child = NULL; - } - } else { - if (device_delete_child(sc->self, sc->child) != 0) - device_printf(sc->self, "Could not delete MMC bus!\n"); - sc->child = NULL; - } -} - -static void -card_detect_delay(void *arg) -{ - struct fsl_sdhc_softc *sc = arg; - - taskqueue_enqueue(taskqueue_swi_giant, &sc->card_detect_task); -} - -static void -finalize_request(struct fsl_sdhc_softc *sc) -{ - - DPRINTF("finishing request %p\n", sc->request); - - sc->request->done(sc->request); - sc->request = NULL; -} - -/** - * Read response from card. - * @todo Implement Auto-CMD responses being held in R3 for multi-block xfers. - * @param sc - */ -static void -get_response(struct fsl_sdhc_softc *sc) -{ - struct mmc_command *cmd = sc->request->cmd; - int i; - uint32_t val; - uint8_t ext = 0; - - if (cmd->flags & MMC_RSP_136) { - /* CRC is stripped, need to shift one byte left. */ - for (i = 0; i < 4; i++) { - val = read4(sc, SDHC_CMDRSP0 + i * 4); - cmd->resp[3 - i] = (val << 8) + ext; - ext = val >> 24; - } - } else { - cmd->resp[0] = read4(sc, SDHC_CMDRSP0); - } -} - -#ifdef FSL_SDHC_NO_DMA -/** - * Read all content of a fifo buffer. - * @warning Assumes data buffer is 32-bit aligned. - * @param sc - */ -static void -read_block_pio(struct fsl_sdhc_softc *sc) -{ - struct mmc_data *data = sc->request->cmd->data; - size_t left = min(FSL_SDHC_FIFO_BUF_SIZE, data->len); - uint8_t *buf = data->data; - uint32_t word; - - buf += sc->data_offset; - bus_space_read_multi_4(sc->bst, sc->bsh, SDHC_DATPORT, (uint32_t *)buf, - left >> 2); - - sc->data_offset += left; - - /* Handle 32-bit unaligned size case. */ - left &= 0x3; - if (left > 0) { - buf = (uint8_t *)data->data + (sc->data_offset & ~0x3); - word = read4(sc, SDHC_DATPORT); - while (left > 0) { - *(buf++) = word; - word >>= 8; - --left; - } - } -} - -/** - * Write a fifo buffer. - * @warning Assumes data buffer size is 32-bit aligned. - * @param sc - */ -static void -write_block_pio(struct fsl_sdhc_softc *sc) -{ - struct mmc_data *data = sc->request->cmd->data; - size_t left = min(FSL_SDHC_FIFO_BUF_SIZE, data->len); - uint8_t *buf = data->data; - uint32_t word = 0; - - DPRINTF("sc->data_offset %d\n", sc->data_offset); - - buf += sc->data_offset; - bus_space_write_multi_4(sc->bst, sc->bsh, SDHC_DATPORT, (uint32_t *)buf, - left >> 2); - - sc->data_offset += left; - - /* Handle 32-bit unaligned size case. */ - left &= 0x3; - if (left > 0) { - buf = (uint8_t *)data->data + (sc->data_offset & ~0x3); - while (left > 0) { - word += *(buf++); - word <<= 8; - --left; - } - write4(sc, SDHC_DATPORT, word); - } -} - -static void -pio_read_transfer(struct fsl_sdhc_softc *sc) -{ - - while (read4(sc, SDHC_PRSSTAT) & PRSSTAT_BREN) { - read_block_pio(sc); - - /* - * TODO: should we check here whether data_offset >= data->len? - */ - } -} - -static void -pio_write_transfer(struct fsl_sdhc_softc *sc) -{ - - while (read4(sc, SDHC_PRSSTAT) & PRSSTAT_BWEN) { - write_block_pio(sc); - - /* - * TODO: should we check here whether data_offset >= data->len? - */ - } -} -#endif /* FSL_SDHC_USE_DMA */ - -static inline void -handle_command_intr(struct fsl_sdhc_softc *sc, uint32_t irq_stat) -{ - struct mmc_command *cmd = sc->request->cmd; - - /* Handle errors. */ - if (irq_stat & IRQ_CTOE) { - cmd->error = MMC_ERR_TIMEOUT; - } else if (irq_stat & IRQ_CCE) { - cmd->error = MMC_ERR_BADCRC; - } else if (irq_stat & (IRQ_CEBE | IRQ_CIE)) { - cmd->error = MMC_ERR_FIFO; - } - - if (cmd->error) { - device_printf(sc->self, "Error interrupt occured\n"); - reset_controller_dat_cmd(sc); - return; - } - - if (sc->command_done) - return; - - if (irq_stat & IRQ_CC) { - sc->command_done = 1; - - if (cmd->flags & MMC_RSP_PRESENT) - get_response(sc); - } -} - -static inline void -handle_data_intr(struct fsl_sdhc_softc *sc, uint32_t irq_stat) -{ - struct mmc_command *cmd = sc->request->cmd; - - /* Handle errors. */ - if (irq_stat & IRQ_DTOE) { - cmd->error = MMC_ERR_TIMEOUT; - } else if (irq_stat & (IRQ_DCE | IRQ_DEBE)) { - cmd->error = MMC_ERR_BADCRC; - } else if (irq_stat & IRQ_ERROR_DATA_MASK) { - cmd->error = MMC_ERR_FAILED; - } - - if (cmd->error) { - device_printf(sc->self, "Error interrupt occured\n"); - sc->data_done = 1; - reset_controller_dat_cmd(sc); - return; - } - - if (sc->data_done) - return; - -#ifdef FSL_SDHC_NO_DMA - if (irq_stat & IRQ_BRR) { - pio_read_transfer(sc); - } - - if (irq_stat & IRQ_BWR) { - pio_write_transfer(sc); - } -#else - if (irq_stat & IRQ_DINT) { - struct mmc_data *data = sc->request->cmd->data; - - /* Synchronize DMA. */ - if (data->flags & MMC_DATA_READ) { - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTREAD); - memcpy(data->data, sc->dma_mem, data->len); - } else { - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTWRITE); - } - - /* - * TODO: For multiple block transfers, address of dma memory - * in DSADDR register should be set to the beginning of the - * segment here. Also offset to data pointer should be handled. - */ - } -#endif - - if (irq_stat & IRQ_TC) - sc->data_done = 1; -} - -static void -interrupt_handler(void *arg) -{ - struct fsl_sdhc_softc *sc = (struct fsl_sdhc_softc *)arg; - uint32_t irq_stat; - - mtx_lock(&sc->mtx); - - irq_stat = read4(sc, SDHC_IRQSTAT); - - /* Card interrupt. */ - if (irq_stat & IRQ_CINT) { - DPRINTF("Card interrupt recievied\n"); - - } - - /* Card insertion interrupt. */ - if (irq_stat & IRQ_CINS) { - clear_bit(sc, SDHC_IRQSIGEN, IRQ_CINS); - clear_bit(sc, SDHC_IRQSTATEN, IRQ_CINS); - set_bit(sc, SDHC_IRQSIGEN, IRQ_CRM); - set_bit(sc, SDHC_IRQSTATEN, IRQ_CRM); - - callout_reset(&sc->card_detect_callout, hz / 2, - card_detect_delay, sc); - } - - /* Card removal interrupt. */ - if (irq_stat & IRQ_CRM) { - clear_bit(sc, SDHC_IRQSIGEN, IRQ_CRM); - clear_bit(sc, SDHC_IRQSTATEN, IRQ_CRM); - set_bit(sc, SDHC_IRQSIGEN, IRQ_CINS); - set_bit(sc, SDHC_IRQSTATEN, IRQ_CINS); - - callout_stop(&sc->card_detect_callout); - taskqueue_enqueue(taskqueue_swi_giant, &sc->card_detect_task); - } - - /* Handle request interrupts. */ - if (sc->request) { - handle_command_intr(sc, irq_stat); - handle_data_intr(sc, irq_stat); - - /* - * Finalize request when transfer is done successfully - * or was interrupted due to error. - */ - if ((sc->data_done && sc->command_done) || - (sc->request->cmd->error)) - finalize_request(sc); - } - - /* Clear status register. */ - write4(sc, SDHC_IRQSTAT, irq_stat); - - mtx_unlock(&sc->mtx); -} - -#ifndef FSL_SDHC_NO_DMA -static void -dma_get_phys_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) -{ - - if (error != 0) - return; - - /* Get first segment's physical address. */ - *(bus_addr_t *)arg = segs->ds_addr; -} - -static int -init_dma(struct fsl_sdhc_softc *sc) -{ - device_t self = sc->self; - int err; - - err = bus_dma_tag_create(bus_get_dma_tag(self), - FSL_SDHC_DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, FSL_SDHC_DMA_BLOCK_SIZE, 1, - FSL_SDHC_DMA_BLOCK_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL, - &sc->dma_tag); - - if (err) { - device_printf(self, "Could not create DMA tag!\n"); - return (-1); - } - - err = bus_dmamem_alloc(sc->dma_tag, (void **)&(sc->dma_mem), - BUS_DMA_NOWAIT | BUS_DMA_NOCACHE, &sc->dma_map); - if (err) { - device_printf(self, "Could not allocate DMA memory!\n"); - goto fail1; - } - - err = bus_dmamap_load(sc->dma_tag, sc->dma_map, (void *)sc->dma_mem, - FSL_SDHC_DMA_BLOCK_SIZE, dma_get_phys_addr, &sc->dma_phys, 0); - if (err) { - device_printf(self, "Could not load DMA map!\n"); - goto fail2; - } - - return (0); - -fail2: - bus_dmamem_free(sc->dma_tag, sc->dma_mem, sc->dma_map); -fail1: - bus_dma_tag_destroy(sc->dma_tag); - - return (-1); -} -#endif /* FSL_SDHC_NO_DMA */ - -static uint32_t -set_xfertyp_register(const struct mmc_command *cmd) -{ - uint32_t xfertyp = 0; - - /* Set command index. */ - xfertyp |= cmd->opcode << CMDINX_SHIFT; - - /* Set command type. */ - if (cmd->opcode == MMC_STOP_TRANSMISSION) - xfertyp |= CMDTYP_ABORT; - - /* Set data preset select. */ - if (cmd->data) { - xfertyp |= XFERTYP_DPSEL; - - /* Set transfer direction. */ - if (cmd->data->flags & MMC_DATA_READ) - xfertyp |= XFERTYP_DTDSEL; - } - - /* Set command index check. */ - if (cmd->flags & MMC_RSP_OPCODE) - xfertyp |= XFERTYP_CICEN; - - /* Set command CRC check. */ - if (cmd->flags & MMC_RSP_CRC) - xfertyp |= XFERTYP_CCCEN; - - /* Set response type */ - if (!(cmd->flags & MMC_RSP_PRESENT)) - xfertyp |= RSPTYP_NONE; - else if (cmd->flags & MMC_RSP_136) - xfertyp |= RSPTYP_136; - else if (cmd->flags & MMC_RSP_BUSY) - xfertyp |= RSPTYP_48_BUSY; - else - xfertyp |= RSPTYP_48; - -#ifndef FSL_SDHC_NO_DMA - /* Enable DMA */ - xfertyp |= XFERTYP_DMAEN; -#endif - - return (xfertyp); -} - -static uint32_t -set_blkattr_register(const struct mmc_data *data) -{ - - if (data->len <= FSL_SDHC_MAX_BLOCK_SIZE) { - /* One block transfer. */ - return (BLKATTR_BLOCK_COUNT(1) | ((data->len) & - BLKATTR_BLKSZE)); - } - - /* TODO: Write code here for multi-block transfers. */ - return (0); -} - -/** - * Initiate data transfer. Interrupt handler will finalize it. - * @todo Implement multi-block transfers. - * @param sc - * @param cmd - */ -static int -start_data(struct fsl_sdhc_softc *sc, struct mmc_data *data) -{ - uint32_t reg; - - if ((uint32_t)data->data & 0x3) { - device_printf(sc->self, "32-bit unaligned data pointer in " - "request\n"); - return (-1); - } - - sc->data_done = 0; - -#ifdef FSL_SDHC_NO_DMA - sc->data_ptr = data->data; - sc->data_offset = 0; -#else - /* Write DMA address register. */ - write4(sc, SDHC_DSADDR, sc->dma_phys); - - /* Synchronize DMA. */ - if (data->flags & MMC_DATA_READ) { - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREREAD); - } else { - memcpy(sc->dma_mem, data->data, data->len); - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREWRITE); - } -#endif - /* Set block size and count. */ - reg = set_blkattr_register(data); - if (reg == 0) { - device_printf(sc->self, "Requested unsupported multi-block " - "transfer.\n"); - return (-1); - } - write4(sc, SDHC_BLKATTR, reg); - - return (0); -} - -static int -start_command(struct fsl_sdhc_softc *sc, struct mmc_command *cmd) -{ - struct mmc_request *req = sc->request; - uint32_t mask; - uint32_t xfertyp; - int err; - - DPRINTF("opcode %d, flags 0x%08x\n", cmd->opcode, cmd->flags); - DPRINTF("PRSSTAT = 0x%08x\n", read4(sc, SDHC_PRSSTAT)); - - sc->command_done = 0; - - cmd->error = MMC_ERR_NONE; - - /* TODO: should we check here for card presence and clock settings? */ - - /* Always wait for free CMD line. */ - mask = SDHC_CMD_LINE; - /* Wait for free DAT if we have data or busy signal. */ - if (cmd->data || (cmd->flags & MMC_RSP_BUSY)) - mask |= SDHC_DAT_LINE; - /* We shouldn't wait for DAT for stop commands. */ - if (cmd == req->stop) - mask &= ~SDHC_DAT_LINE; - err = wait_for_free_line(sc, mask); - if (err != 0) { - device_printf(sc->self, "Controller never released inhibit " - "bit(s).\n"); - reset_controller_dat_cmd(sc); - cmd->error = MMC_ERR_FAILED; - sc->request = NULL; - req->done(req); - return (-1); - } - - xfertyp = set_xfertyp_register(cmd); - - if (cmd->data != NULL) { - err = start_data(sc, cmd->data); - if (err != 0) { - device_printf(sc->self, - "Data transfer request failed\n"); - reset_controller_dat_cmd(sc); - cmd->error = MMC_ERR_FAILED; - sc->request = NULL; - req->done(req); - return (-1); - } - } - - write4(sc, SDHC_CMDARG, cmd->arg); - write4(sc, SDHC_XFERTYP, xfertyp); - - DPRINTF("XFERTYP = 0x%08x\n", xfertyp); - DPRINTF("CMDARG = 0x%08x\n", cmd->arg); - - return (0); -} - -#ifdef DEBUG -static void -dump_registers(struct fsl_sdhc_softc *sc) -{ - printf("PRSSTAT = 0x%08x\n", read4(sc, SDHC_PRSSTAT)); - printf("PROCTL = 0x%08x\n", read4(sc, SDHC_PROCTL)); - printf("HOSTCAPBLT = 0x%08x\n", read4(sc, SDHC_HOSTCAPBLT)); - printf("IRQSTAT = 0x%08x\n", read4(sc, SDHC_IRQSTAT)); - printf("IRQSTATEN = 0x%08x\n", read4(sc, SDHC_IRQSTATEN)); - printf("IRQSIGEN = 0x%08x\n", read4(sc, SDHC_IRQSIGEN)); - printf("WML = 0x%08x\n", read4(sc, SDHC_WML)); - printf("DSADDR = 0x%08x\n", read4(sc, SDHC_DSADDR)); - printf("XFERTYP = 0x%08x\n", read4(sc, SDHC_XFERTYP)); - printf("DCR = 0x%08x\n", read4(sc, SDHC_DCR)); -} -#endif - -/***************************************************************************** - * Public methods - *****************************************************************************/ -/* - * Device interface methods. - */ -static int -fsl_sdhc_probe(device_t self) -{ - static const char *desc = - "Freescale Enhanced Secure Digital Host Controller"; - - if (!ofw_bus_is_compatible(self, "fsl,p2020-esdhc") && - !ofw_bus_is_compatible(self, "fsl,esdhc")) - return (ENXIO); - - device_set_desc(self, desc); - - return (BUS_PROBE_VENDOR); -} - -static int -fsl_sdhc_attach(device_t self) -{ - struct fsl_sdhc_softc *sc; - - sc = device_get_softc(self); - - sc->self = self; - - mtx_init(&sc->mtx, device_get_nameunit(self), NULL, MTX_DEF); - - /* Setup memory resource */ - sc->mem_rid = 0; - sc->mem_resource = bus_alloc_resource_any(self, SYS_RES_MEMORY, - &sc->mem_rid, RF_ACTIVE); - if (sc->mem_resource == NULL) { - device_printf(self, "Could not allocate memory.\n"); - goto fail; - } - sc->bst = rman_get_bustag(sc->mem_resource); - sc->bsh = rman_get_bushandle(sc->mem_resource); - - /* Setup interrupt resource. */ - sc->irq_rid = 0; - sc->irq_resource = bus_alloc_resource_any(self, SYS_RES_IRQ, - &sc->irq_rid, RF_ACTIVE); - if (sc->irq_resource == NULL) { - device_printf(self, "Could not allocate interrupt.\n"); - goto fail; - } - if (bus_setup_intr(self, sc->irq_resource, INTR_TYPE_MISC | - INTR_MPSAFE, NULL, interrupt_handler, sc, &sc->ihl) != 0) { - device_printf(self, "Could not setup interrupt.\n"); - goto fail; - } - - /* Setup DMA. */ -#ifndef FSL_SDHC_NO_DMA - if (init_dma(sc) != 0) { - device_printf(self, "Could not setup DMA\n"); - } -#endif - sc->bus_busy = 0; - sc->platform_clock = get_platform_clock(sc); - if (sc->platform_clock == 0) { - device_printf(self, "Could not get platform clock.\n"); - goto fail; - } - sc->command_done = 1; - sc->data_done = 1; - - /* Init card detection task. */ - TASK_INIT(&sc->card_detect_task, 0, card_detect_task, sc); - callout_init(&sc->card_detect_callout, 1); - - reset_controller_all(sc); - init_controller(sc); - set_clock(sc, 400000); - send_80_clock_ticks(sc); - -#ifdef DEBUG - dump_registers(sc); -#endif - - return (0); - -fail: - fsl_sdhc_detach(self); - return (ENXIO); -} - -static int -fsl_sdhc_detach(device_t self) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - int err; - - if (sc->child) - device_delete_child(self, sc->child); - - taskqueue_drain(taskqueue_swi_giant, &sc->card_detect_task); - -#ifndef FSL_SDHC_NO_DMA - bus_dmamap_unload(sc->dma_tag, sc->dma_map); - bus_dmamem_free(sc->dma_tag, sc->dma_mem, sc->dma_map); - bus_dma_tag_destroy(sc->dma_tag); -#endif - - if (sc->ihl != NULL) { - err = bus_teardown_intr(self, sc->irq_resource, sc->ihl); - if (err) - return (err); - } - if (sc->irq_resource != NULL) { - err = bus_release_resource(self, SYS_RES_IRQ, sc->irq_rid, - sc->irq_resource); - if (err) - return (err); - - } - if (sc->mem_resource != NULL) { - err = bus_release_resource(self, SYS_RES_MEMORY, sc->mem_rid, - sc->mem_resource); - if (err) - return (err); - } - - mtx_destroy(&sc->mtx); - - return (0); -} - - -/* - * Bus interface methods. - */ -static int -fsl_sdhc_read_ivar(device_t self, device_t child, int index, - uintptr_t *result) -{ - struct mmc_host *host = device_get_ivars(child); - - switch (index) { - case MMCBR_IVAR_BUS_MODE: - *(int *)result = host->ios.bus_mode; - break; - case MMCBR_IVAR_BUS_WIDTH: - *(int *)result = host->ios.bus_width; - break; - case MMCBR_IVAR_CHIP_SELECT: - *(int *)result = host->ios.chip_select; - break; - case MMCBR_IVAR_CLOCK: - *(int *)result = host->ios.clock; - break; - case MMCBR_IVAR_F_MIN: - *(int *)result = host->f_min; - break; - case MMCBR_IVAR_F_MAX: - *(int *)result = host->f_max; - break; - case MMCBR_IVAR_HOST_OCR: - *(int *)result = host->host_ocr; - break; - case MMCBR_IVAR_MODE: - *(int *)result = host->mode; - break; - case MMCBR_IVAR_OCR: - *(int *)result = host->ocr; - break; - case MMCBR_IVAR_POWER_MODE: - *(int *)result = host->ios.power_mode; - break; - case MMCBR_IVAR_VDD: - *(int *)result = host->ios.vdd; - break; - default: - return (EINVAL); - } - - return (0); -} - -static int -fsl_sdhc_write_ivar(device_t self, device_t child, int index, - uintptr_t value) -{ - struct mmc_host *host = device_get_ivars(child); - - switch (index) { - case MMCBR_IVAR_BUS_MODE: - host->ios.bus_mode = value; - break; - case MMCBR_IVAR_BUS_WIDTH: - host->ios.bus_width = value; - break; - case MMCBR_IVAR_CHIP_SELECT: - host->ios.chip_select = value; - break; - case MMCBR_IVAR_CLOCK: - host->ios.clock = value; - break; - case MMCBR_IVAR_MODE: - host->mode = value; - break; - case MMCBR_IVAR_OCR: - host->ocr = value; - break; - case MMCBR_IVAR_POWER_MODE: - host->ios.power_mode = value; - break; - case MMCBR_IVAR_VDD: - host->ios.vdd = value; - break; - case MMCBR_IVAR_HOST_OCR: - case MMCBR_IVAR_F_MIN: - case MMCBR_IVAR_F_MAX: - default: - /* Instance variable not writable. */ - return (EINVAL); - } - - return (0); -} - - -/* - * MMC bridge methods. - */ -static int -fsl_sdhc_update_ios(device_t self, device_t reqdev) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - struct mmc_host *host = device_get_ivars(reqdev); - struct mmc_ios *ios = &host->ios; - - mtx_lock(&sc->mtx); - - /* Full reset on bus power down to clear from any state. */ - if (ios->power_mode == power_off) { - reset_controller_all(sc); - init_controller(sc); - } - - set_clock(sc, ios->clock); - set_bus_width(sc, ios->bus_width); - - mtx_unlock(&sc->mtx); - - return (0); -} - -static int -fsl_sdhc_request(device_t self, device_t reqdev, struct mmc_request *req) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - int err; - - mtx_lock(&sc->mtx); - - sc->request = req; - err = start_command(sc, req->cmd); - - mtx_unlock(&sc->mtx); - - return (err); -} - -static int -fsl_sdhc_get_ro(device_t self, device_t reqdev) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - - /* Wouldn't it be faster using branching (if {}) ?? */ - return (((read4(sc, SDHC_PRSSTAT) & PRSSTAT_WPSPL) >> 19) ^ 0x1); -} - -static int -fsl_sdhc_acquire_host(device_t self, device_t reqdev) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - int retval = 0; - - mtx_lock(&sc->mtx); - - while (sc->bus_busy) - retval = mtx_sleep(sc, &sc->mtx, PZERO, "sdhcah", 0); - ++(sc->bus_busy); - - mtx_unlock(&sc->mtx); - - return (retval); -} - -static int -fsl_sdhc_release_host(device_t self, device_t reqdev) -{ - struct fsl_sdhc_softc *sc = device_get_softc(self); - - mtx_lock(&sc->mtx); - --(sc->bus_busy); - mtx_unlock(&sc->mtx); - wakeup(sc); - - return (0); -} diff --git a/sys/powerpc/mpc85xx/fsl_sdhc.h b/sys/powerpc/mpc85xx/fsl_sdhc.h deleted file mode 100644 index 9bd2e3d3c4df..000000000000 --- a/sys/powerpc/mpc85xx/fsl_sdhc.h +++ /dev/null @@ -1,297 +0,0 @@ -/*- - * Copyright (c) 2011-2012 Semihalf - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef FSL_SDHC_H_ -#define FSL_SDHC_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "mmcbr_if.h" - - -/***************************************************************************** - * Private defines - *****************************************************************************/ -struct slot { - uint32_t clock; -}; - -struct fsl_sdhc_softc { - device_t self; - device_t child; - - bus_space_handle_t bsh; - bus_space_tag_t bst; - - struct resource *mem_resource; - int mem_rid; - struct resource *irq_resource; - int irq_rid; - void *ihl; - - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; - uint32_t* dma_mem; - bus_addr_t dma_phys; - - struct mtx mtx; - - struct task card_detect_task; - struct callout card_detect_callout; - - struct mmc_host mmc_host; - - struct slot slot; - uint32_t bus_busy; - uint32_t platform_clock; - - struct mmc_request *request; - int data_done; - int command_done; - int use_dma; - uint32_t* data_ptr; - uint32_t data_offset; -}; - -#define FSL_SDHC_RESET_DELAY 50 - -#define FSL_SDHC_BASE_CLOCK_DIV (2) -#define FSL_SDHC_MAX_DIV (FSL_SDHC_BASE_CLOCK_DIV * 256 * 16) -#define FSL_SDHC_MIN_DIV (FSL_SDHC_BASE_CLOCK_DIV * 2) -#define FSL_SDHC_MAX_CLOCK (50000000) - -#define FSL_SDHC_MAX_BLOCK_COUNT (65535) -#define FSL_SDHC_MAX_BLOCK_SIZE (4096) - -#define FSL_SDHC_FIFO_BUF_SIZE (64) /* Water-mark level. */ -#define FSL_SDHC_FIFO_BUF_WORDS (FSL_SDHC_FIFO_BUF_SIZE / 4) - -#define FSL_SDHC_DMA_SEGMENT_SIZE (1024) -#define FSL_SDHC_DMA_ALIGNMENT (4) -#define FSL_SDHC_DMA_BLOCK_SIZE FSL_SDHC_MAX_BLOCK_SIZE - - -/* - * Offsets of SD HC registers - */ -enum sdhc_reg_off { - SDHC_DSADDR = 0x000, - SDHC_BLKATTR = 0x004, - SDHC_CMDARG = 0x008, - SDHC_XFERTYP = 0x00c, - SDHC_CMDRSP0 = 0x010, - SDHC_CMDRSP1 = 0x014, - SDHC_CMDRSP2 = 0x018, - SDHC_CMDRSP3 = 0x01c, - SDHC_DATPORT = 0x020, - SDHC_PRSSTAT = 0x024, - SDHC_PROCTL = 0x028, - SDHC_SYSCTL = 0x02c, - SDHC_IRQSTAT = 0x030, - SDHC_IRQSTATEN = 0x034, - SDHC_IRQSIGEN = 0x038, - SDHC_AUTOC12ERR = 0x03c, - SDHC_HOSTCAPBLT = 0x040, - SDHC_WML = 0x044, - SDHC_FEVT = 0x050, - SDHC_HOSTVER = 0x0fc, - SDHC_DCR = 0x40c -}; - -enum sysctl_bit { - SYSCTL_INITA = 0x08000000, - SYSCTL_RSTD = 0x04000000, - SYSCTL_RSTC = 0x02000000, - SYSCTL_RSTA = 0x01000000, - SYSCTL_DTOCV = 0x000f0000, - SYSCTL_SDCLKFS = 0x0000ff00, - SYSCTL_DVS = 0x000000f0, - SYSCTL_PEREN = 0x00000004, - SYSCTL_HCKEN = 0x00000002, - SYSCTL_IPGEN = 0x00000001 -}; - -#define HEX_LEFT_SHIFT(x) (4 * x) -enum sysctl_shift { - SHIFT_DTOCV = HEX_LEFT_SHIFT(4), - SHIFT_SDCLKFS = HEX_LEFT_SHIFT(2), - SHIFT_DVS = HEX_LEFT_SHIFT(1) -}; - -enum proctl_bit { - PROCTL_WECRM = 0x04000000, - PROCTL_WECINS = 0x02000000, - PROCTL_WECINT = 0x01000000, - PROCTL_RWCTL = 0x00040000, - PROCTL_CREQ = 0x00020000, - PROCTL_SABGREQ = 0x00010000, - PROCTL_CDSS = 0x00000080, - PROCTL_CDTL = 0x00000040, - PROCTL_EMODE = 0x00000030, - PROCTL_D3CD = 0x00000008, - PROCTL_DTW = 0x00000006 -}; - -enum dtw { - DTW_1 = 0x00000000, - DTW_4 = 0x00000002, - DTW_8 = 0x00000004 -}; - -enum prsstat_bit { - PRSSTAT_DLSL = 0xff000000, - PRSSTAT_CLSL = 0x00800000, - PRSSTAT_WPSPL = 0x00080000, - PRSSTAT_CDPL = 0x00040000, - PRSSTAT_CINS = 0x00010000, - PRSSTAT_BREN = 0x00000800, - PRSSTAT_BWEN = 0x00000400, - PRSSTAT_RTA = 0x00000200, - PRSSTAT_WTA = 0x00000100, - PRSSTAT_SDOFF = 0x00000080, - PRSSTAT_PEROFF = 0x00000040, - PRSSTAT_HCKOFF = 0x00000020, - PRSSTAT_IPGOFF = 0x00000010, - PRSSTAT_DLA = 0x00000004, - PRSSTAT_CDIHB = 0x00000002, - PRSSTAT_CIHB = 0x00000001 - -}; - -enum irq_bits { - IRQ_DMAE = 0x10000000, - IRQ_AC12E = 0x01000000, - IRQ_DEBE = 0x00400000, - IRQ_DCE = 0x00200000, - IRQ_DTOE = 0x00100000, - IRQ_CIE = 0x00080000, - IRQ_CEBE = 0x00040000, - IRQ_CCE = 0x00020000, - IRQ_CTOE = 0x00010000, - IRQ_CINT = 0x00000100, - IRQ_CRM = 0x00000080, - IRQ_CINS = 0x00000040, - IRQ_BRR = 0x00000020, - IRQ_BWR = 0x00000010, - IRQ_DINT = 0x00000008, - IRQ_BGE = 0x00000004, - IRQ_TC = 0x00000002, - IRQ_CC = 0x00000001 -}; - -enum irq_masks { - IRQ_ERROR_DATA_MASK = IRQ_DMAE | IRQ_DEBE | IRQ_DCE | IRQ_DTOE, - IRQ_ERROR_CMD_MASK = IRQ_AC12E | IRQ_CIE | IRQ_CTOE | IRQ_CCE | - IRQ_CEBE -}; - -enum dcr_bits { - DCR_PRI = 0x0000c000, - DCR_SNOOP = 0x00000040, - DCR_AHB2MAG_BYPASS = 0x00000020, - DCR_RD_SAFE = 0x00000004, - DCR_RD_PFE = 0x00000002, - DCR_RD_PF_SIZE = 0x00000001 -}; - -#define DCR_PRI_SHIFT (14) - -enum xfertyp_bits { - XFERTYP_CMDINX = 0x3f000000, - XFERTYP_CMDTYP = 0x00c00000, - XFERTYP_DPSEL = 0x00200000, - XFERTYP_CICEN = 0x00100000, - XFERTYP_CCCEN = 0x00080000, - XFERTYP_RSPTYP = 0x00030000, - XFERTYP_MSBSEL = 0x00000020, - XFERTYP_DTDSEL = 0x00000010, - XFERTYP_AC12EN = 0x00000004, - XFERTYP_BCEN = 0x00000002, - XFERTYP_DMAEN = 0x00000001 -}; - -#define CMDINX_SHIFT (24) - -enum xfertyp_cmdtyp { - CMDTYP_NORMAL = 0x00000000, - CMDYTP_SUSPEND = 0x00400000, - CMDTYP_RESUME = 0x00800000, - CMDTYP_ABORT = 0x00c00000 -}; - -enum xfertyp_rsptyp { - RSPTYP_NONE = 0x00000000, - RSPTYP_136 = 0x00010000, - RSPTYP_48 = 0x00020000, - RSPTYP_48_BUSY = 0x00030000 -}; - -enum blkattr_bits { - BLKATTR_BLKSZE = 0x00001fff, - BLKATTR_BLKCNT = 0xffff0000 -}; -#define BLKATTR_BLOCK_COUNT(x) (x << 16) - -enum wml_bits { - WR_WML = 0x00ff0000, - RD_WML = 0x000000ff, -}; - -enum sdhc_bit_mask { - MASK_CLOCK_CONTROL = 0x0000ffff, - MASK_IRQ_ALL = IRQ_DMAE | IRQ_AC12E | IRQ_DEBE | IRQ_DCE | - IRQ_DTOE | IRQ_CIE | IRQ_CEBE | IRQ_CCE | - IRQ_CTOE | IRQ_CINT | IRQ_CRM | IRQ_CINS | - IRQ_BRR | IRQ_BWR | IRQ_DINT | IRQ_BGE | - IRQ_TC | IRQ_CC, -}; - -enum sdhc_line { - SDHC_DAT_LINE = 0x2, - SDHC_CMD_LINE = 0x1 -}; - -#endif /* FSL_SDHC_H_ */ diff --git a/sys/sys/bio.h b/sys/sys/bio.h index 8821fef59bb3..9c669537e7ed 100644 --- a/sys/sys/bio.h +++ b/sys/sys/bio.h @@ -121,6 +121,9 @@ struct bio { void *_bio_caller2; uint8_t _bio_cflags; #endif +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + struct buf *bio_track_bp; /* Parent buf for tracking */ +#endif /* XXX: these go away when bio chaining is introduced */ daddr_t bio_pblkno; /* physical block number */ @@ -142,6 +145,23 @@ void biodone(struct bio *bp); void biofinish(struct bio *bp, struct devstat *stat, int error); int biowait(struct bio *bp, const char *wchan); +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) +void biotrack_buf(struct bio *bp, const char *location); + +static __inline void +biotrack(struct bio *bp, const char *location) +{ + + if (bp->bio_track_bp != NULL) + biotrack_buf(bp, location); +} +#else +static __inline void +biotrack(struct bio *bp __unused, const char *location __unused) +{ +} +#endif + void bioq_disksort(struct bio_queue_head *ap, struct bio *bp); struct bio *bioq_first(struct bio_queue_head *head); struct bio *bioq_takefirst(struct bio_queue_head *head); diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 034671e794d1..f1d08d728bf8 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -140,6 +140,15 @@ struct buf { void *b_fsprivate1; void *b_fsprivate2; void *b_fsprivate3; + +#if defined(FULL_BUF_TRACKING) +#define BUF_TRACKING_SIZE 32 +#define BUF_TRACKING_ENTRY(x) ((x) & (BUF_TRACKING_SIZE - 1)) + const char *b_io_tracking[BUF_TRACKING_SIZE]; + uint32_t b_io_tcnt; +#elif defined(BUF_TRACKING) + const char *b_io_tracking; +#endif }; #define b_object b_bufobj->bo_object @@ -429,6 +438,17 @@ buf_countdeps(struct buf *bp, int i) return (0); } +static __inline void +buf_track(struct buf *bp, const char *location) +{ + +#if defined(FULL_BUF_TRACKING) + bp->b_io_tracking[BUF_TRACKING_ENTRY(bp->b_io_tcnt++)] = location; +#elif defined(BUF_TRACKING) + bp->b_io_tracking = location; +#endif +} + #endif /* _KERNEL */ /* diff --git a/sys/sys/namei.h b/sys/sys/namei.h index bb1631b5cc79..af79eb9eb9ef 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -55,6 +55,9 @@ struct componentname { long cn_namelen; /* length of looked up component */ }; +struct nameicap_tracker; +TAILQ_HEAD(nameicap_tracker_head, nameicap_tracker); + /* * Encapsulation of namei parameters. */ @@ -72,7 +75,7 @@ struct nameidata { struct vnode *ni_rootdir; /* logical root directory */ struct vnode *ni_topdir; /* logical top directory */ int ni_dirfd; /* starting directory for *at functions */ - int ni_strictrelative; /* relative lookup only; no '..' */ + int ni_lcf; /* local call flags */ /* * Results: returned from namei */ @@ -94,6 +97,7 @@ struct nameidata { * through the VOP interface. */ struct componentname ni_cnd; + struct nameicap_tracker_head ni_cap_tracker; }; #ifdef _KERNEL @@ -151,6 +155,12 @@ struct nameidata { #define NOCAPCHECK 0x20000000 /* do not perform capability checks */ #define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */ +/* + * Flags in ni_lcf, valid for the duration of the namei call. + */ +#define NI_LCF_STRICTRELATIVE 0x0001 /* relative lookup only */ +#define NI_LCF_CAP_DOTDOT 0x0002 /* ".." in strictrelative case */ + /* * Initialization of a nameidata structure. */ diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c index cabed2baea16..6f1b8e70bcf9 100644 --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -10,7 +10,7 @@ * 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. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -61,11 +61,7 @@ __FBSDID("$FreeBSD$"); * remaining space in the directory. */ int -ffs_blkatoff(vp, offset, res, bpp) - struct vnode *vp; - off_t offset; - char **res; - struct buf **bpp; +ffs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) { struct inode *ip; struct fs *fs; @@ -95,11 +91,7 @@ ffs_blkatoff(vp, offset, res, bpp) * to the incore copy. */ void -ffs_load_inode(bp, ip, fs, ino) - struct buf *bp; - struct inode *ip; - struct fs *fs; - ino_t ino; +ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino) { if (I_IS_UFS1(ip)) { @@ -131,11 +123,7 @@ ffs_load_inode(bp, ip, fs, ino) * of some frags. */ void -ffs_fragacct(fs, fragmap, fraglist, cnt) - struct fs *fs; - int fragmap; - int32_t fraglist[]; - int cnt; +ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt) { int inblk; int field, subfield; @@ -167,10 +155,7 @@ ffs_fragacct(fs, fragmap, fraglist, cnt) * check if a block is available */ int -ffs_isblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - ufs1_daddr_t h; +ffs_isblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h) { unsigned char mask; @@ -199,10 +184,7 @@ ffs_isblock(fs, cp, h) * check if a block is free */ int -ffs_isfreeblock(fs, cp, h) - struct fs *fs; - u_char *cp; - ufs1_daddr_t h; +ffs_isfreeblock(struct fs *fs, u_char *cp, ufs1_daddr_t h) { switch ((int)fs->fs_frag) { @@ -227,10 +209,7 @@ ffs_isfreeblock(fs, cp, h) * take a block out of the map */ void -ffs_clrblock(fs, cp, h) - struct fs *fs; - u_char *cp; - ufs1_daddr_t h; +ffs_clrblock(struct fs *fs, u_char *cp, ufs1_daddr_t h) { switch ((int)fs->fs_frag) { @@ -258,10 +237,7 @@ ffs_clrblock(fs, cp, h) * put a block into the map */ void -ffs_setblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - ufs1_daddr_t h; +ffs_setblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h) { switch ((int)fs->fs_frag) { @@ -292,11 +268,7 @@ ffs_setblock(fs, cp, h) * Cnt == 1 means free; cnt == -1 means allocating. */ void -ffs_clusteracct(fs, cgp, blkno, cnt) - struct fs *fs; - struct cg *cgp; - ufs1_daddr_t blkno; - int cnt; +ffs_clusteracct(struct fs *fs, struct cg *cgp, ufs1_daddr_t blkno, int cnt) { int32_t *sump; int32_t *lp; diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 67f8c754a9a0..47a1bd57ef24 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -420,8 +420,7 @@ RetryFault:; * they will stay around as well. * * Bump the paging-in-progress count to prevent size changes (e.g. - * truncation operations) during I/O. This must be done after - * obtaining the vnode lock in order to avoid possible deadlocks. + * truncation operations) during I/O. */ vm_object_reference_locked(fs.first_object); vm_object_pip_add(fs.first_object, 1); @@ -647,7 +646,13 @@ RetryFault:; if (locked != LK_EXCLUSIVE) locked = LK_SHARED; - /* Do not sleep for vnode lock while fs.m is busy */ + + /* + * We must not sleep acquiring the vnode lock + * while we have the page exclusive busied or + * the object's paging-in-progress count + * incremented. Otherwise, we could deadlock. + */ error = vget(vp, locked | LK_CANRECURSE | LK_NOWAIT, curthread); if (error != 0) { diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index fccd1c8b8c96..87557aef472b 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -376,6 +376,7 @@ initpbuf(struct buf *bp) bp->b_iodone = NULL; bp->b_error = 0; BUF_LOCK(bp, LK_EXCLUSIVE, NULL); + buf_track(bp, __func__); } /* @@ -473,6 +474,7 @@ relpbuf(struct buf *bp, int *pfreecnt) KASSERT(bp->b_vp == NULL, ("relpbuf with vp")); KASSERT(bp->b_bufobj == NULL, ("relpbuf with bufobj")); + buf_track(bp, __func__); BUF_UNLOCK(bp); mtx_lock(&pbuf_mtx); diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index b0d3a0eaf815..06518521ab1a 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -14,6 +14,11 @@ ATF_TESTS_C+= unix_passfd_test TEST_METADATA.unix_seqpacket_test+= timeout="15" ATF_TESTS_C+= waitpid_nohang +ATF_TESTS_SH+= coredump_phnum_test + +BINDIR= ${TESTSDIR} +PROGS+= coredump_phnum_helper + LIBADD.ptrace_test+= pthread LIBADD.unix_seqpacket_test+= pthread diff --git a/tests/sys/kern/coredump_phnum_helper.c b/tests/sys/kern/coredump_phnum_helper.c new file mode 100644 index 000000000000..da023e691a24 --- /dev/null +++ b/tests/sys/kern/coredump_phnum_helper.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, Conrad Meyer + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include + +#include +#include +#include + +/* + * This program is intended to create a bunch of segment mappings, then dump + * core. + */ +int +main(int argc __unused, char **argv __unused) +{ + void *v; + unsigned i; + + for (i = 0; i < UINT16_MAX + 1000; i++) { + /* + * Alternate protections; otherwise the kernel will just extend + * the adjacent same-protection previous mapping. + */ + v = mmap(NULL, PAGE_SIZE, + (((i % 2) == 0) ? PROT_READ : 0) | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (v == MAP_FAILED) + err(1, "mmap"); + } + + /* Dump core. */ + abort(); +} diff --git a/tests/sys/kern/coredump_phnum_test.sh b/tests/sys/kern/coredump_phnum_test.sh new file mode 100755 index 000000000000..4132396cd11f --- /dev/null +++ b/tests/sys/kern/coredump_phnum_test.sh @@ -0,0 +1,90 @@ +# +# Copyright (c) 2016 Dell EMC Isilon +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions, and the following disclaimer, +# without modification. +# 2. Redistributions in binary form must reproduce at minimum a disclaimer +# substantially similar to the "NO WARRANTY" disclaimer below +# ("Disclaimer") and any redistribution must be conditioned upon +# including a substantially similar Disclaimer requirement for further +# binary redistribution. +# +# NO WARRANTY +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGES. +# +# $FreeBSD$ + +atf_test_case coredump_phnum cleanup +coredump_phnum_head() +{ + atf_set "allow_sysctl_side_effects" "1" + atf_set "descr" "More than 65534 segments" + atf_set "require.progs" "readelf procstat" + atf_set "require.user" "root" +} +coredump_phnum_body() +{ + # Set up core dumping + cat > coredump_phnum_restore_state.sh <<-EOF + #!/bin/sh + ulimit -c '$(ulimit -c)' + sysctl kern.coredump=$(sysctl -n kern.coredump) + sysctl kern.corefile='$(sysctl -n kern.corefile)' +EOF + chmod +x coredump_phnum_restore_state.sh + + ulimit -c unlimited + sysctl kern.coredump=1 + sysctl kern.corefile="$(pwd)/coredump_phnum_helper.core" + + atf_check -s signal:sigabrt "$(atf_get_srcdir)/coredump_phnum_helper" + + # Check that core looks good + if [ ! -f coredump_phnum_helper.core ]; then + atf_fail "Helper program did not dump core" + fi + + # These magic numbers don't have any real significance. They are just + # the result of running the helper program and dumping core. The only + # important bit is that they're larger than 65535 (UINT16_MAX). + readelf -h coredump_phnum_helper.core | \ + atf_check -o "match:65535 \(66169\)" \ + grep "Number of program headers:" + readelf -l coredump_phnum_helper.core | \ + atf_check -o "match:There are 66169 program headers" \ + grep -1 "program headers" + readelf -S coredump_phnum_helper.core | \ + atf_check -o "match: 0000000000000001 .* 66169 " \ + grep -A1 "^ \[ 0\] " + + procstat -v coredump_phnum_helper.core | \ + atf_check -o "match:66545" wc -l +} +coredump_phnum_cleanup() +{ + rm -f coredump_phnum_helper.core + if [ -x coredump_phnum_restore_state.sh ]; then + ./coredump_phnum_restore_state.sh + fi + rm -f coredump_phnum_restore_state.sh +} + +atf_init_test_cases() +{ + atf_add_test_case coredump_phnum +} diff --git a/usr.bin/calendar/Makefile b/usr.bin/calendar/Makefile index 5e8ba8805893..38cf6db51848 100644 --- a/usr.bin/calendar/Makefile +++ b/usr.bin/calendar/Makefile @@ -15,20 +15,22 @@ FR_LINKS= fr_FR.ISO8859-15 TEXTMODE?= 444 beforeinstall: - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \ + ${INSTALL} ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \ ${.CURDIR}/calendars/calendar.* ${DESTDIR}${SHAREDIR}/calendar .for lang in ${INTER} - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \ + ${INSTALL} ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \ ${.CURDIR}/calendars/${lang}/calendar.* \ ${DESTDIR}${SHAREDIR}/calendar/${lang} .endfor .for link in ${DE_LINKS} rm -rf ${DESTDIR}${SHAREDIR}/calendar/${link} - ln -s de_DE.ISO8859-1 ${DESTDIR}${SHAREDIR}/calendar/${link} + ${INSTALL} ${TAG_ARGS} -l s de_DE.ISO8859-1 \ + ${DESTDIR}${SHAREDIR}/calendar/${link} .endfor .for link in ${FR_LINKS} rm -rf ${DESTDIR}${SHAREDIR}/calendar/${link} - ln -s fr_FR.ISO8859-1 ${DESTDIR}${SHAREDIR}/calendar/${link} + ${INSTALL} ${TAG_ARGS} -l s fr_FR.ISO8859-1 \ + ${DESTDIR}${SHAREDIR}/calendar/${link} .endfor .if ${MK_TESTS} != "no" diff --git a/usr.sbin/autofs/autounmountd.c b/usr.sbin/autofs/autounmountd.c index 3a13225aa80a..f65e78a81067 100644 --- a/usr.sbin/autofs/autounmountd.c +++ b/usr.sbin/autofs/autounmountd.c @@ -244,8 +244,11 @@ do_wait(int kq, double sleep_time) log_debugx("waiting for filesystem event"); nevents = kevent(kq, NULL, 0, &unused, 1, NULL); } - if (nevents < 0) + if (nevents < 0) { + if (errno == EINTR) + return; log_err(1, "kevent"); + } if (nevents == 0) { log_debugx("timeout reached"); diff --git a/usr.sbin/cpucontrol/Makefile b/usr.sbin/cpucontrol/Makefile index 2d51429ec4c7..df84f7082e87 100644 --- a/usr.sbin/cpucontrol/Makefile +++ b/usr.sbin/cpucontrol/Makefile @@ -2,7 +2,7 @@ PROG= cpucontrol MAN= cpucontrol.8 -SRCS= cpucontrol.c intel.c amd.c via.c +SRCS= cpucontrol.c intel.c amd.c amd10h.c via.c NO_WCAST_ALIGN= diff --git a/usr.sbin/cpucontrol/amd.h b/usr.sbin/cpucontrol/amd.h index cf109c27041d..64eb35271b45 100644 --- a/usr.sbin/cpucontrol/amd.h +++ b/usr.sbin/cpucontrol/amd.h @@ -33,6 +33,8 @@ */ ucode_probe_t amd_probe; ucode_update_t amd_update; +ucode_probe_t amd10h_probe; +ucode_update_t amd10h_update; typedef struct amd_fw_header { uint32_t date; /* Update creation date. */ @@ -46,4 +48,45 @@ typedef struct amd_fw_header { #define AMD_MAGIC 0xaaaaaa +/* + * AMD family 10h and later. + */ +typedef struct amd_10h_fw_header { + uint32_t data_code; + uint32_t patch_id; + uint16_t mc_patch_data_id; + uint8_t mc_patch_data_len; + uint8_t init_flag; + uint32_t mc_patch_data_checksum; + uint32_t nb_dev_id; + uint32_t sb_dev_id; + uint16_t processor_rev_id; + uint8_t nb_rev_id; + uint8_t sb_rev_id; + uint8_t bios_api_rev; + uint8_t reserved1[3]; + uint32_t match_reg[8]; +} amd_10h_fw_header_t; + +typedef struct equiv_cpu_entry { + uint32_t installed_cpu; + uint32_t fixed_errata_mask; + uint32_t fixed_errata_compare; + uint16_t equiv_cpu; + uint16_t res; +} equiv_cpu_entry_t; + +typedef struct section_header { + uint32_t type; + uint32_t size; +} section_header_t; + +typedef struct container_header { + uint32_t magic; +} container_header_t; + +#define AMD_10H_MAGIC 0x414d44 +#define AMD_10H_EQUIV_TABLE_TYPE 0 +#define AMD_10H_uCODE_TYPE 1 + #endif /* !AMD_H */ diff --git a/usr.sbin/cpucontrol/amd10h.c b/usr.sbin/cpucontrol/amd10h.c new file mode 100644 index 000000000000..40cef9c41408 --- /dev/null +++ b/usr.sbin/cpucontrol/amd10h.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2012 Andriy Gapon . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "cpucontrol.h" +#include "amd.h" + +int +amd10h_probe(int fd) +{ + char vendor[13]; + cpuctl_cpuid_args_t idargs; + uint32_t family; + uint32_t signature; + int error; + + idargs.level = 0; + error = ioctl(fd, CPUCTL_CPUID, &idargs); + if (error < 0) { + WARN(0, "ioctl()"); + return (1); + } + ((uint32_t *)vendor)[0] = idargs.data[1]; + ((uint32_t *)vendor)[1] = idargs.data[3]; + ((uint32_t *)vendor)[2] = idargs.data[2]; + vendor[12] = '\0'; + if (strncmp(vendor, AMD_VENDOR_ID, sizeof(AMD_VENDOR_ID)) != 0) + return (1); + + idargs.level = 1; + error = ioctl(fd, CPUCTL_CPUID, &idargs); + if (error < 0) { + WARN(0, "ioctl()"); + return (1); + } + signature = idargs.data[0]; + family = ((signature >> 8) & 0x0f) + ((signature >> 20) & 0xff); + if (family < 0x10) + return (1); + return (0); +} + +/* + * NB: the format of microcode update files is not documented by AMD. + * It has been reverse engineered from studying Coreboot, illumos and Linux + * source code. + */ +void +amd10h_update(const char *dev, const char *path) +{ + struct stat st; + cpuctl_cpuid_args_t idargs; + cpuctl_msr_args_t msrargs; + cpuctl_update_args_t args; + const amd_10h_fw_header_t *fw_header; + const amd_10h_fw_header_t *selected_fw; + const equiv_cpu_entry_t *equiv_cpu_table; + const section_header_t *section_header; + const container_header_t *container_header; + const uint8_t *fw_data; + uint8_t *fw_image; + size_t fw_size; + size_t selected_size; + uint32_t revision; + uint32_t new_rev; + uint32_t signature; + uint16_t equiv_id; + int fd, devfd; + unsigned int i; + int error; + + assert(path); + assert(dev); + + fd = -1; + fw_image = MAP_FAILED; + devfd = open(dev, O_RDWR); + if (devfd < 0) { + WARN(0, "could not open %s for writing", dev); + return; + } + idargs.level = 1; + error = ioctl(devfd, CPUCTL_CPUID, &idargs); + if (error < 0) { + WARN(0, "ioctl()"); + goto done; + } + signature = idargs.data[0]; + + msrargs.msr = 0x0000008b; + error = ioctl(devfd, CPUCTL_RDMSR, &msrargs); + if (error < 0) { + WARN(0, "ioctl(%s)", dev); + goto done; + } + revision = (uint32_t)msrargs.data; + + WARNX(1, "found cpu family %#x model %#x " + "stepping %#x extfamily %#x extmodel %#x.", + (signature >> 8) & 0x0f, (signature >> 4) & 0x0f, + (signature >> 0) & 0x0f, (signature >> 20) & 0xff, + (signature >> 16) & 0x0f); + WARNX(1, "microcode revision %#x", revision); + + /* + * Open the firmware file. + */ + fd = open(path, O_RDONLY, 0); + if (fd < 0) { + WARN(0, "open(%s)", path); + goto done; + } + error = fstat(fd, &st); + if (error != 0) { + WARN(0, "fstat(%s)", path); + goto done; + } + if (st.st_size < 0 || (size_t)st.st_size < + (sizeof(*container_header) + sizeof(*section_header))) { + WARNX(2, "file too short: %s", path); + goto done; + } + fw_size = st.st_size; + + /* + * mmap the whole image. + */ + fw_image = (uint8_t *)mmap(NULL, st.st_size, PROT_READ, + MAP_PRIVATE, fd, 0); + if (fw_image == MAP_FAILED) { + WARN(0, "mmap(%s)", path); + goto done; + } + + fw_data = fw_image; + container_header = (const container_header_t *)fw_data; + if (container_header->magic != AMD_10H_MAGIC) { + WARNX(2, "%s is not a valid amd firmware: bad magic", path); + goto done; + } + fw_data += sizeof(*container_header); + fw_size -= sizeof(*container_header); + + section_header = (const section_header_t *)fw_data; + if (section_header->type != AMD_10H_EQUIV_TABLE_TYPE) { + WARNX(2, "%s is not a valid amd firmware: " + "first section is not CPU equivalence table", path); + goto done; + } + if (section_header->size == 0) { + WARNX(2, "%s is not a valid amd firmware: " + "first section is empty", path); + goto done; + } + fw_data += sizeof(*section_header); + fw_size -= sizeof(*section_header); + + if (section_header->size > fw_size) { + WARNX(2, "%s is not a valid amd firmware: " + "file is truncated", path); + goto done; + } + if (section_header->size < sizeof(*equiv_cpu_table)) { + WARNX(2, "%s is not a valid amd firmware: " + "first section is too short", path); + goto done; + } + equiv_cpu_table = (const equiv_cpu_entry_t *)fw_data; + fw_data += section_header->size; + fw_size -= section_header->size; + + equiv_id = 0; + for (i = 0; equiv_cpu_table[i].installed_cpu != 0; i++) { + if (signature == equiv_cpu_table[i].installed_cpu) { + equiv_id = equiv_cpu_table[i].equiv_cpu; + WARNX(3, "equiv_id: %x", equiv_id); + break; + } + } + if (equiv_id == 0) { + WARNX(2, "CPU is not found in the equivalence table"); + goto done; + } + + selected_fw = NULL; + selected_size = 0; + while (fw_size >= sizeof(*section_header)) { + section_header = (const section_header_t *)fw_data; + fw_data += sizeof(*section_header); + fw_size -= sizeof(*section_header); + if (section_header->type != AMD_10H_uCODE_TYPE) { + WARNX(2, "%s is not a valid amd firmware: " + "section has incorret type", path); + goto done; + } + if (section_header->size > fw_size) { + WARNX(2, "%s is not a valid amd firmware: " + "file is truncated", path); + goto done; + } + if (section_header->size < sizeof(*fw_header)) { + WARNX(2, "%s is not a valid amd firmware: " + "section is too short", path); + goto done; + } + fw_header = (const amd_10h_fw_header_t *)fw_data; + fw_data += section_header->size; + fw_size -= section_header->size; + + if (fw_header->processor_rev_id != equiv_id) + continue; /* different cpu */ + if (fw_header->patch_id <= revision) + continue; /* not newer revision */ + if (fw_header->nb_dev_id != 0 || fw_header->sb_dev_id != 0) { + WARNX(2, "Chipset-specific microcode is not supported"); + } + + WARNX(3, "selecting revision: %x", fw_header->patch_id); + revision = fw_header->patch_id; + selected_fw = fw_header; + selected_size = section_header->size; + } + + if (fw_size != 0) { + WARNX(2, "%s is not a valid amd firmware: " + "file is truncated", path); + goto done; + } + + if (selected_fw != NULL) { + WARNX(1, "selected ucode size is %zu", selected_size); + fprintf(stderr, "%s: updating cpu %s to revision %#x... ", + path, dev, revision); + + args.data = __DECONST(void *, selected_fw); + args.size = selected_size; + error = ioctl(devfd, CPUCTL_UPDATE, &args); + if (error < 0) { + fprintf(stderr, "failed.\n"); + warn("ioctl()"); + goto done; + } + fprintf(stderr, "done.\n"); + } + + msrargs.msr = 0x0000008b; + error = ioctl(devfd, CPUCTL_RDMSR, &msrargs); + if (error < 0) { + WARN(0, "ioctl(%s)", dev); + goto done; + } + new_rev = (uint32_t)msrargs.data; + if (new_rev != revision) + WARNX(0, "revision after update %#x", new_rev); + +done: + if (fd >= 0) + close(fd); + if (devfd >= 0) + close(devfd); + if (fw_image != MAP_FAILED) + if (munmap(fw_image, st.st_size) != 0) + warn("munmap(%s)", path); + return; +} diff --git a/usr.sbin/cpucontrol/cpucontrol.c b/usr.sbin/cpucontrol/cpucontrol.c index 504ac50be7fb..48e12e7ae6b4 100644 --- a/usr.sbin/cpucontrol/cpucontrol.c +++ b/usr.sbin/cpucontrol/cpucontrol.c @@ -91,6 +91,7 @@ static struct ucode_handler { ucode_update_t *update; } handlers[] = { { intel_probe, intel_update }, + { amd10h_probe, amd10h_update }, { amd_probe, amd_update }, { via_probe, via_update }, }; diff --git a/usr.sbin/cron/cron/cron.8 b/usr.sbin/cron/cron/cron.8 index dc53101cf677..1bc04bd01944 100644 --- a/usr.sbin/cron/cron/cron.8 +++ b/usr.sbin/cron/cron/cron.8 @@ -17,7 +17,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Octobre 31, 2016 +.Dd October 31, 2016 .Dt CRON 8 .Os .Sh NAME diff --git a/usr.sbin/cron/cron/database.c b/usr.sbin/cron/cron/database.c index 2ac7113c1171..2b0c67b9c02d 100644 --- a/usr.sbin/cron/cron/database.c +++ b/usr.sbin/cron/cron/database.c @@ -44,7 +44,7 @@ load_database(old_db) { DIR *dir; struct stat statbuf; - struct stat syscron_stat; + struct stat syscron_stat, st; time_t maxmtime; DIR_T *dp; cron_db new_db; @@ -124,7 +124,8 @@ load_database(old_db) while (NULL != (dp = readdir(dir))) { if (dp->d_name[0] == '.') continue; - if (dp->d_type != DT_REG) + if (fstatat(dirfd(dir), dp->d_name, &st, 0) == 0 && + !S_ISREG(st.st_mode)) continue; snprintf(tabname, sizeof(tabname), "%s/%s", syscrontabs[i].name, dp->d_name); diff --git a/usr.sbin/rtadvd/if.c b/usr.sbin/rtadvd/if.c index dc6ac8e320db..6013e9ba08c1 100644 --- a/usr.sbin/rtadvd/if.c +++ b/usr.sbin/rtadvd/if.c @@ -470,11 +470,18 @@ update_ifinfo(struct ifilist_head_t *ifi_head, int ifindex) ifindex != ifm->ifm_index) continue; + /* ifname */ + if (if_indextoname(ifm->ifm_index, ifname) == NULL) { + syslog(LOG_WARNING, + "<%s> ifname not found (idx=%d)", + __func__, ifm->ifm_index); + continue; + } + /* lookup an entry with the same ifindex */ TAILQ_FOREACH(ifi, ifi_head, ifi_next) { if (ifm->ifm_index == ifi->ifi_ifindex) break; - if_indextoname(ifm->ifm_index, ifname); if (strncmp(ifname, ifi->ifi_ifname, sizeof(ifname)) == 0) break; @@ -493,15 +500,7 @@ update_ifinfo(struct ifilist_head_t *ifi_head, int ifindex) ifi->ifi_ifindex = ifm->ifm_index; /* ifname */ - if_indextoname(ifm->ifm_index, ifi->ifi_ifname); - if (ifi->ifi_ifname == NULL) { - syslog(LOG_WARNING, - "<%s> ifname not found (idx=%d)", - __func__, ifm->ifm_index); - if (ifi_new) - free(ifi); - continue; - } + strlcpy(ifi->ifi_ifname, ifname, IFNAMSIZ); if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, diff --git a/usr.sbin/syslogd/syslog.conf.5 b/usr.sbin/syslogd/syslog.conf.5 index 3378aa08cda3..94c1cd415369 100644 --- a/usr.sbin/syslogd/syslog.conf.5 +++ b/usr.sbin/syslogd/syslog.conf.5 @@ -28,7 +28,7 @@ .\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd September 12, 2012 +.Dd November 1, 2016 .Dt SYSLOG.CONF 5 .Os .Sh NAME @@ -62,6 +62,12 @@ field is separated from the .Em action field by one or more tab characters or spaces. .Pp +A special +.Em include +keyword can be used to include all files with names ending in '.conf' and not +beginning with a '.' contained in the directory following the keyword. +This keyword can only be used in the first level configuration file. +.Pp Note that if you use spaces as separators, your .Nm might be incompatible with other Unices or Unix-like systems. diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index 556278159364..4c415fa8c6a8 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -118,6 +119,8 @@ __FBSDID("$FreeBSD$"); const char *ConfFile = _PATH_LOGCONF; const char *PidFile = _PATH_LOGPID; const char ctty[] = _PATH_CONSOLE; +static const char include_str[] = "include"; +static const char include_ext[] = ".conf"; #define dprintf if (Debug) printf @@ -1601,6 +1604,157 @@ die(int signo) exit(1); } +static int +configfiles(const struct dirent *dp) +{ + const char *p; + size_t ext_len; + + if (dp->d_name[0] == '.') + return (0); + + ext_len = sizeof(include_ext) -1; + + if (dp->d_namlen <= ext_len) + return (0); + + p = &dp->d_name[dp->d_namlen - ext_len]; + if (strcmp(p, include_ext) != 0) + return (0); + + return (1); +} + +static void +readconfigfile(FILE *cf, struct filed **nextp, int allow_includes) +{ + FILE *cf2; + struct filed *f; + struct dirent **ent; + char cline[LINE_MAX]; + char host[MAXHOSTNAMELEN]; + char prog[LINE_MAX]; + char file[MAXPATHLEN]; + char *p, *tmp; + int i, nents; + size_t include_len; + + /* + * Foreach line in the conf table, open that file. + */ + f = NULL; + include_len = sizeof(include_str) -1; + (void)strlcpy(host, "*", sizeof(host)); + (void)strlcpy(prog, "*", sizeof(prog)); + while (fgets(cline, sizeof(cline), cf) != NULL) { + /* + * check for end-of-section, comments, strip off trailing + * spaces and newline character. #!prog is treated specially: + * following lines apply only to that program. + */ + for (p = cline; isspace(*p); ++p) + continue; + if (*p == 0) + continue; + if (allow_includes && + strncmp(p, include_str, include_len) == 0 && + isspace(p[include_len])) { + p += include_len; + while (isspace(*p)) + p++; + tmp = p; + while (*tmp != '\0' && !isspace(*tmp)) + tmp++; + *tmp = '\0'; + dprintf("Trying to include files in '%s'\n", p); + nents = scandir(p, &ent, configfiles, alphasort); + if (nents == -1) { + dprintf("Unable to open '%s': %s\n", p, + strerror(errno)); + continue; + } + for (i = 0; i < nents; i++) { + if (snprintf(file, sizeof(file), "%s/%s", p, + ent[i]->d_name) >= (int)sizeof(file)) { + dprintf("ignoring path too long: " + "'%s/%s'\n", p, ent[i]->d_name); + free(ent[i]); + continue; + } + free(ent[i]); + cf2 = fopen(file, "r"); + if (cf2 == NULL) + continue; + dprintf("reading %s\n", file); + readconfigfile(cf2, nextp, 0); + fclose(cf2); + } + free(ent); + continue; + } + if (*p == '#') { + p++; + if (*p != '!' && *p != '+' && *p != '-') + continue; + } + if (*p == '+' || *p == '-') { + host[0] = *p++; + while (isspace(*p)) + p++; + if ((!*p) || (*p == '*')) { + (void)strlcpy(host, "*", sizeof(host)); + continue; + } + if (*p == '@') + p = LocalHostName; + for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { + if (!isalnum(*p) && *p != '.' && *p != '-' + && *p != ',' && *p != ':' && *p != '%') + break; + host[i] = *p++; + } + host[i] = '\0'; + continue; + } + if (*p == '!') { + p++; + while (isspace(*p)) p++; + if ((!*p) || (*p == '*')) { + (void)strlcpy(prog, "*", sizeof(prog)); + continue; + } + for (i = 0; i < LINE_MAX - 1; i++) { + if (!isprint(p[i]) || isspace(p[i])) + break; + prog[i] = p[i]; + } + prog[i] = 0; + continue; + } + for (p = cline + 1; *p != '\0'; p++) { + if (*p != '#') + continue; + if (*(p - 1) == '\\') { + strcpy(p - 1, p); + p--; + continue; + } + *p = '\0'; + break; + } + for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) + cline[i] = '\0'; + f = (struct filed *)calloc(1, sizeof(*f)); + if (f == NULL) { + logerror("calloc"); + exit(1); + } + *nextp = f; + nextp = &f->f_next; + cfline(cline, f, prog, host); + } +} + /* * INIT -- Initialize syslogd from configuration table */ @@ -1611,9 +1765,6 @@ init(int signo) FILE *cf; struct filed *f, *next, **nextp; char *p; - char cline[LINE_MAX]; - char prog[LINE_MAX]; - char host[MAXHOSTNAMELEN]; char oldLocalHostName[MAXHOSTNAMELEN]; char hostMsg[2*MAXHOSTNAMELEN+40]; char bootfileMsg[LINE_MAX]; @@ -1684,7 +1835,6 @@ init(int signo) free((char *)f); } Files = NULL; - nextp = &Files; /* open the configuration file */ if ((cf = fopen(ConfFile, "r")) == NULL) { @@ -1705,83 +1855,7 @@ init(int signo) return; } - /* - * Foreach line in the conf table, open that file. - */ - f = NULL; - (void)strlcpy(host, "*", sizeof(host)); - (void)strlcpy(prog, "*", sizeof(prog)); - while (fgets(cline, sizeof(cline), cf) != NULL) { - /* - * check for end-of-section, comments, strip off trailing - * spaces and newline character. #!prog is treated specially: - * following lines apply only to that program. - */ - for (p = cline; isspace(*p); ++p) - continue; - if (*p == 0) - continue; - if (*p == '#') { - p++; - if (*p != '!' && *p != '+' && *p != '-') - continue; - } - if (*p == '+' || *p == '-') { - host[0] = *p++; - while (isspace(*p)) - p++; - if ((!*p) || (*p == '*')) { - (void)strlcpy(host, "*", sizeof(host)); - continue; - } - if (*p == '@') - p = LocalHostName; - for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { - if (!isalnum(*p) && *p != '.' && *p != '-' - && *p != ',' && *p != ':' && *p != '%') - break; - host[i] = *p++; - } - host[i] = '\0'; - continue; - } - if (*p == '!') { - p++; - while (isspace(*p)) p++; - if ((!*p) || (*p == '*')) { - (void)strlcpy(prog, "*", sizeof(prog)); - continue; - } - for (i = 0; i < LINE_MAX - 1; i++) { - if (!isprint(p[i]) || isspace(p[i])) - break; - prog[i] = p[i]; - } - prog[i] = 0; - continue; - } - for (p = cline + 1; *p != '\0'; p++) { - if (*p != '#') - continue; - if (*(p - 1) == '\\') { - strcpy(p - 1, p); - p--; - continue; - } - *p = '\0'; - break; - } - for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) - cline[i] = '\0'; - f = (struct filed *)calloc(1, sizeof(*f)); - if (f == NULL) { - logerror("calloc"); - exit(1); - } - *nextp = f; - nextp = &f->f_next; - cfline(cline, f, prog, host); - } + readconfigfile(cf, &Files, 1); /* close the configuration file */ (void)fclose(cf);