Merge ^/head r303250 through r308226.

This commit is contained in:
Dimitry Andric 2016-11-02 19:18:24 +00:00
commit a2b802ce70
113 changed files with 2873 additions and 4144 deletions

View File

@ -543,8 +543,8 @@ HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT
CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCXXFLAGS} ${XCFLAGS}" \ CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCXXFLAGS} ${XCFLAGS}" \
CPP="${XCPP} ${XCFLAGS}" \ CPP="${XCPP} ${XCFLAGS}" \
AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \ AS="${XAS}" AR="${XAR}" LD="${XLD}" LLVM_LINK="${XLLVM_LINK}" \
OBJCOPY="${XOBJCOPY}" \ NM=${XNM} OBJCOPY="${XOBJCOPY}" \
RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \ RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \
SIZE="${XSIZE}" SIZE="${XSIZE}"

View File

@ -52,9 +52,10 @@
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include "hv_kvp.h" #include "hv_kvp.h"
#include "hv_utilreg.h"
typedef uint8_t __u8; typedef uint8_t __u8;
typedef uint16_t __u16; typedef uint16_t __u16;
typedef uint32_t __u32; 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, kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
(MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
/* /*
* Retrieve the IPV6 address of default gateway. * 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. * Execute the command to gather gateway IPV6 info.
*/ */
kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
(MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
/* /*
* we just invoke an external script to get the DNS info. * 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) { if ((length - *offset) < addr_length + 1) {
return (HV_KVP_E_FAIL); return (EINVAL);
} }
if (str == NULL) { if (str == NULL) {
strlcpy(buffer, "inet_ntop failed\n", length); strlcpy(buffer, "inet_ntop failed\n", length);
return (HV_KVP_E_FAIL); return (errno);
} }
if (*offset == 0) { if (*offset == 0) {
strlcpy(buffer, tmp, length); strlcpy(buffer, tmp, length);
@ -832,7 +831,7 @@ kvp_get_ip_info(int family, char *if_name, int op,
if (getifaddrs(&ifap)) { if (getifaddrs(&ifap)) {
strlcpy(buffer, "getifaddrs failed\n", buffer_length); strlcpy(buffer, "getifaddrs failed\n", buffer_length);
return (HV_KVP_E_FAIL); return (errno);
} }
curp = ifap; curp = ifap;
@ -924,7 +923,6 @@ kvp_get_ip_info(int family, char *if_name, int op,
/* /*
* Collect other ip configuration info. * Collect other ip configuration info.
*/ */
kvp_get_ipconfig_info(if_name, ip_buffer); 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); ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3);
if (ret < 0) { if (ret < 0) {
return (HV_KVP_E_FAIL); return (EIO);
} }
return (0); return (0);
@ -979,7 +977,7 @@ kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
if (file == NULL) { if (file == NULL) {
KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); 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); mac_addr = kvp_if_name_to_mac(if_name);
if (mac_addr == NULL) { if (mac_addr == NULL) {
error = HV_KVP_E_FAIL; error = EINVAL;
goto kvp_set_ip_info_error; goto kvp_set_ip_info_error;
} }
/* MAC Address */ /* 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; struct hv_kvp_ipaddr_value *ip_val;
char *if_name; char *if_name;
int error = 0;
assert(op_msg != NULL); assert(op_msg != NULL);
KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n");
ip_val = &op_msg->body.kvp_ip_val; 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_name = kvp_mac_to_if_name((char *)ip_val->adapter_id);
if (if_name == NULL) { if (if_name == NULL) {
/* No interface found with the mac address. */ /* 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; 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)); 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); free(if_name);
kvp_op_getipinfo_done: 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; struct hv_kvp_ipaddr_value *ip_val;
char *if_name; char *if_name;
int error = 0;
assert(op_msg != NULL); assert(op_msg != NULL);
KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n");
ip_val = &op_msg->body.kvp_ip_val; 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_name = (char *)ip_val->adapter_id;
if (if_name == NULL) { if (if_name == NULL) {
/* No adapter provided. */ /* No adapter provided. */
op_msg->hdr.error = HV_KVP_GUID_NOTFOUND; op_msg->hdr.error = HV_GUID_NOTFOUND;
goto kvp_op_setipinfo_done; 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: 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); assert(op_hdlr != NULL);
op_pool = op_msg->hdr.kvp_hdr.pool; 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) { switch(op_hdlr->kvp_op_key) {
case HV_KVP_OP_SET: case HV_KVP_OP_SET:
@ -1198,8 +1200,7 @@ kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data)
} }
if (error != 0) if (error != 0)
op_msg->hdr.error = HV_KVP_S_CONT; op_msg->hdr.error = HV_S_CONT;
return(error); 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 = op_msg->hdr.kvp_hdr.operation;
op_pool = op_msg->hdr.kvp_hdr.pool; 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 * 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, HV_KVP_EXCHANGE_MAX_KEY_SIZE,
op_msg->body.kvp_enum_data.data.msg_value.value, op_msg->body.kvp_enum_data.data.msg_value.value,
HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
op_msg->hdr.error = HV_KVP_S_CONT; op_msg->hdr.error = HV_S_CONT;
error = -1; error = -1;
} }
goto kvp_op_enumerate_done; 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", KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n",
op_msg->body.kvp_enum_data.index); op_msg->body.kvp_enum_data.index);
#endif #endif
op_msg->hdr.error = HV_KVP_S_CONT; op_msg->hdr.error = HV_S_CONT;
error = -1; error = -1;
break; break;
} }
kvp_op_enumerate_done: kvp_op_enumerate_done:
if (error != 0)
op_msg->hdr.error = HV_S_CONT;
return(error); return(error);
} }
@ -1496,10 +1499,13 @@ main(int argc, char *argv[])
*/ */
error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg,
(void *)&kvp_op_hdlrs[op]); (void *)&kvp_op_hdlrs[op]);
if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT) if (error != 0) {
KVP_LOG(LOG_WARNING, assert(hv_msg->hdr.error != HV_S_OK);
"Operation failed OP = %d, error = 0x%x\n", if (hv_msg->hdr.error != HV_S_CONT)
op, error); KVP_LOG(LOG_WARNING,
"Operation failed OP = %d, error = 0x%x\n",
op, error);
}
} }
/* /*

View File

@ -468,6 +468,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
if (kex == NULL) if (kex == NULL)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
ptr = sshpkt_ptr(ssh, &dlen); ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r; return r;

View File

@ -459,7 +459,7 @@ distrib-dirs: ${MTREES:N/*} distrib-cleanup .PHONY
.endif .endif
etc-examples-install: ${META_DEPS} 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 \ ${BIN1} ${BIN2} nsmb.conf opieaccess \
${DESTDIR}${SHAREDIR}/examples/etc ${DESTDIR}${SHAREDIR}/examples/etc

View File

@ -78,6 +78,8 @@
.. ..
ssl ssl
.. ..
syslog.d
..
zfs zfs
.. ..
.. ..

View File

@ -34,3 +34,5 @@ cron.* /var/log/cron
!ppp !ppp
*.* /var/log/ppp.log *.* /var/log/ppp.log
!* !*
include /etc/syslog.d
include /usr/local/etc/syslog.d

View File

@ -397,11 +397,11 @@ _libinstall: _lib-eh-install
_lib-eh-install: _lib-eh-install:
.if ${MK_INSTALLLIB} != "no" .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} ${_INSTALLFLAGS} libgcc_eh.a ${DESTDIR}${LIBDIR}
.endif .endif
.if ${MK_PROFILE} != "no" .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} ${_INSTALLFLAGS} libgcc_eh_p.a ${DESTDIR}${LIBDIR}
.endif .endif

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h> #include <fcntl.h>
#include "un-namespace.h" #include "un-namespace.h"
#include "endian.h"
#include "collate.h" #include "collate.h"
#include "setlocale.h" #include "setlocale.h"
#include "ldpart.h" #include "ldpart.h"
@ -160,7 +161,7 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table)
if ((info->directive_count < 1) || if ((info->directive_count < 1) ||
(info->directive_count >= COLL_WEIGHTS_MAX) || (info->directive_count >= COLL_WEIGHTS_MAX) ||
((chains = info->chain_count) < 0)) { ((chains = BSWAP(info->chain_count)) < 0)) {
(void) munmap(map, sbuf.st_size); (void) munmap(map, sbuf.st_size);
errno = EINVAL; errno = EINVAL;
return (_LDP_ERROR); 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)) + i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) +
(sizeof (collate_chain_t) * chains) + (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++) { 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))) { if (i != (sbuf.st_size - (TMP - map))) {
(void) munmap(map, sbuf.st_size); (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); TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1);
for (z = 0; z < info->directive_count; z++) { 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; 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 { } else {
table->subst_table[z] = NULL; 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); TMP += chains * sizeof (collate_chain_t);
} else } else
table->chain_pri_table = NULL; table->chain_pri_table = NULL;
if (info->large_count > 0) if (BSWAP(info->large_count) > 0)
table->large_pri_table = (void *)TMP; table->large_pri_table = (void *)TMP;
else else
table->large_pri_table = NULL; table->large_pri_table = NULL;
@ -209,7 +210,7 @@ static const int32_t *
substsearch(struct xlocale_collate *table, const wchar_t key, int pass) substsearch(struct xlocale_collate *table, const wchar_t key, int pass)
{ {
const collate_subst_t *p; const collate_subst_t *p;
int n = table->info->subst_count[pass]; int n = BSWAP(table->info->subst_count[pass]);
if (n == 0) if (n == 0)
return (NULL); return (NULL);
@ -221,7 +222,8 @@ substsearch(struct xlocale_collate *table, const wchar_t key, int pass)
return (NULL); return (NULL);
p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY); p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY);
assert(p->key == key); assert(BSWAP(p->key) == key);
return (p->pri); return (p->pri);
} }
@ -229,7 +231,7 @@ static collate_chain_t *
chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len)
{ {
int low = 0; int low = 0;
int high = table->info->chain_count - 1;; int high = BSWAP(table->info->chain_count) - 1;
int next, compar, l; int next, compar, l;
collate_chain_t *p; collate_chain_t *p;
collate_chain_t *tab = table->chain_pri_table; 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) { while (low <= high) {
next = (low + high) / 2; next = (low + high) / 2;
p = tab + next; p = tab + next;
compar = *key - *p->str; compar = *key - le16toh(*p->str);
if (compar == 0) { if (compar == 0) {
l = wcsnlen(p->str, COLLATE_STR_LEN); l = wcsnlen(p->str, COLLATE_STR_LEN);
compar = wcsncmp(key, p->str, l); compar = wcsncmp(key, p->str, l);
@ -261,7 +263,7 @@ static collate_large_t *
largesearch(struct xlocale_collate *table, const wchar_t key) largesearch(struct xlocale_collate *table, const wchar_t key)
{ {
int low = 0; int low = 0;
int high = table->info->large_count - 1; int high = BSWAP(table->info->large_count) - 1;
int next, compar; int next, compar;
collate_large_t *p; collate_large_t *p;
collate_large_t *tab = table->large_pri_table; collate_large_t *tab = table->large_pri_table;
@ -272,7 +274,7 @@ largesearch(struct xlocale_collate *table, const wchar_t key)
while (low <= high) { while (low <= high) {
next = (low + high) / 2; next = (low + high) / 2;
p = tab + next; p = tab + next;
compar = key - p->val; compar = key - BSWAP(p->val);
if (compar == 0) if (compar == 0)
return (p); return (p);
if (compar > 0) 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. * Character is a small (8-bit) character.
* We just look these up directly for speed. * 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)) { ((match = largesearch(table, *t)) != NULL)) {
/* /*
* Character was found in the extended table. * Character was found in the extended table.
*/ */
*pri = match->pri.pri[which]; *pri = BSWAP(match->pri.pri[which]);
} else { } 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. */ /* Mask off sign bit to prevent ordering confusion. */
*pri = (*t & COLLATE_MAX_PRIORITY); *pri = (*t & COLLATE_MAX_PRIORITY);
} else { } else {
*pri = table->info->undef_pri[which]; *pri = BSWAP(table->info->undef_pri[which]);
} }
/* No substitutions for undefined characters! */ /* No substitutions for undefined characters! */
return; return;
@ -374,9 +376,9 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len,
* code ensures this for us. * code ensures this for us.
*/ */
if ((sptr = substsearch(table, *pri, which)) != NULL) { if ((sptr = substsearch(table, *pri, which)) != NULL) {
if ((*pri = *sptr) > 0) { if ((*pri = BSWAP(*sptr)) > 0) {
sptr++; 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) xfrm(struct xlocale_collate *table, unsigned char *p, int pri, int pass)
{ {
/* we use unsigned to ensure zero fill on right shift */ /* 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; int nc = 0;
while (val) { while (val) {
@ -678,7 +680,7 @@ __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len)
e = -1; e = -1;
if (*str <= UCHAR_MAX) if (*str <= UCHAR_MAX)
e = table->char_pri_table[*str].pri[0]; 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; collate_large_t *match_large;
match_large = largesearch(table, *str); match_large = largesearch(table, *str);
if (match_large) if (match_large)
@ -688,7 +690,7 @@ __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len)
return (1); return (1);
return (e > 0 ? e : 0); return (e > 0 ? e : 0);
} }
if (table->info->chain_count > 0) { if (BSWAP(table->info->chain_count) > 0) {
wchar_t name[COLLATE_STR_LEN]; wchar_t name[COLLATE_STR_LEN];
collate_chain_t *match_chain; collate_chain_t *match_chain;
int clen; int clen;

52
lib/libc/locale/endian.h Normal file
View File

@ -0,0 +1,52 @@
/*-
* Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
* 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 <sys/endian.h>
/*
* 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

View File

@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h> #include <unistd.h>
#include "un-namespace.h" #include "un-namespace.h"
#include "endian.h"
#include "runefile.h" #include "runefile.h"
_RuneLocale * _RuneLocale *
@ -107,29 +108,29 @@ _Read_RuneMagi(const char *fname)
} }
runetype_ext_ranges = (_FileRuneEntry *)variable; 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) { if (variable > lastp) {
goto invalid; goto invalid;
} }
maplower_ext_ranges = (_FileRuneEntry *)variable; 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) { if (variable > lastp) {
goto invalid; goto invalid;
} }
mapupper_ext_ranges = (_FileRuneEntry *)variable; 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) { if (variable > lastp) {
goto invalid; goto invalid;
} }
frr = runetype_ext_ranges; 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; uint32_t *types;
if (frr[x].map == 0) { if (BSWAP(frr[x].map) == 0) {
int len = frr[x].max - frr[x].min + 1; int len = BSWAP(frr[x].max) - BSWAP(frr[x].min) + 1;
types = variable; types = variable;
variable = types + len; variable = types + len;
runetype_ext_len += 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; goto invalid;
} }
@ -147,10 +148,10 @@ _Read_RuneMagi(const char *fname)
* Convert from disk format to host format. * Convert from disk format to host format.
*/ */
data = malloc(sizeof(_RuneLocale) + data = malloc(sizeof(_RuneLocale) +
(frl->runetype_ext_nranges + frl->maplower_ext_nranges + (BSWAP(frl->runetype_ext_nranges) + BSWAP(frl->maplower_ext_nranges) +
frl->mapupper_ext_nranges) * sizeof(_RuneEntry) + BSWAP(frl->mapupper_ext_nranges)) * sizeof(_RuneEntry) +
runetype_ext_len * sizeof(*rr->__types) + runetype_ext_len * sizeof(*rr->__types) +
frl->variable_len); BSWAP(frl->variable_len));
if (data == NULL) { if (data == NULL) {
saverr = errno; saverr = errno;
munmap(fdata, sb.st_size); 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->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic));
memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding));
rl->__variable_len = frl->variable_len; rl->__variable_len = BSWAP(frl->variable_len);
rl->__runetype_ext.__nranges = frl->runetype_ext_nranges; rl->__runetype_ext.__nranges = BSWAP(frl->runetype_ext_nranges);
rl->__maplower_ext.__nranges = frl->maplower_ext_nranges; rl->__maplower_ext.__nranges = BSWAP(frl->maplower_ext_nranges);
rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges; rl->__mapupper_ext.__nranges = BSWAP(frl->mapupper_ext_nranges);
for (x = 0; x < _CACHED_RUNES; ++x) { for (x = 0; x < _CACHED_RUNES; ++x) {
rl->__runetype[x] = frl->runetype[x]; rl->__runetype[x] = BSWAP(frl->runetype[x]);
rl->__maplower[x] = frl->maplower[x]; rl->__maplower[x] = BSWAP(frl->maplower[x]);
rl->__mapupper[x] = frl->mapupper[x]; rl->__mapupper[x] = BSWAP(frl->mapupper[x]);
} }
rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
@ -187,15 +188,15 @@ _Read_RuneMagi(const char *fname)
rl->__variable = rl->__mapupper_ext.__ranges + rl->__variable = rl->__mapupper_ext.__ranges +
rl->__mapupper_ext.__nranges; 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; frr = runetype_ext_ranges;
rr = rl->__runetype_ext.__ranges; rr = rl->__runetype_ext.__ranges;
for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
uint32_t *types; uint32_t *types;
rr[x].__min = frr[x].min; rr[x].__min = BSWAP(frr[x].min);
rr[x].__max = frr[x].max; rr[x].__max = BSWAP(frr[x].max);
rr[x].__map = frr[x].map; rr[x].__map = BSWAP(frr[x].map);
if (rr[x].__map == 0) { if (rr[x].__map == 0) {
int len = rr[x].__max - rr[x].__min + 1; int len = rr[x].__max - rr[x].__min + 1;
types = variable; types = variable;
@ -211,17 +212,17 @@ _Read_RuneMagi(const char *fname)
frr = maplower_ext_ranges; frr = maplower_ext_ranges;
rr = rl->__maplower_ext.__ranges; rr = rl->__maplower_ext.__ranges;
for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
rr[x].__min = frr[x].min; rr[x].__min = BSWAP(frr[x].min);
rr[x].__max = frr[x].max; rr[x].__max = BSWAP(frr[x].max);
rr[x].__map = frr[x].map; rr[x].__map = BSWAP(frr[x].map);
} }
frr = mapupper_ext_ranges; frr = mapupper_ext_ranges;
rr = rl->__mapupper_ext.__ranges; rr = rl->__mapupper_ext.__ranges;
for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) {
rr[x].__min = frr[x].min; rr[x].__min = BSWAP(frr[x].min);
rr[x].__max = frr[x].max; rr[x].__max = BSWAP(frr[x].max);
rr[x].__map = frr[x].map; rr[x].__map = BSWAP(frr[x].map);
} }
memcpy(rl->__variable, variable, rl->__variable_len); memcpy(rl->__variable, variable, rl->__variable_len);

View File

@ -75,140 +75,140 @@ static const struct {
double hi; double hi;
double lo; double lo;
} tbl[INTERVALS] = { } tbl[INTERVALS] = {
0x1p+0, 0x0p+0, { 0x1p+0, 0x0p+0 },
/* /*
* XXX hi is rounded down, and the formatting is not quite normal. * 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 * But I rather like both. The 0x1.*p format is good for 4N+1
* mantissa bits. Rounding down makes the lo terms positive, * mantissa bits. Rounding down makes the lo terms positive,
* so that the columnar formatting can be simpler. * so that the columnar formatting can be simpler.
*/ */
0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54, { 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54 },
0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53, { 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53 },
0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53, { 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53 },
0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55, { 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55 },
0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53, { 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53 },
0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57, { 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57 },
0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54, { 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54 },
0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54, { 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54 },
0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54, { 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54 },
0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59, { 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59 },
0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53, { 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53 },
0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53, { 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53 },
0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53, { 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53 },
0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53, { 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53 },
0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55, { 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55 },
0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53, { 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53 },
0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53, { 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53 },
0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55, { 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55 },
0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53, { 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53 },
0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54, { 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54 },
0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53, { 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53 },
0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55, { 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55 },
0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55, { 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55 },
0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54, { 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54 },
0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55, { 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55 },
0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55, { 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55 },
0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53, { 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53 },
0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55, { 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55 },
0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53, { 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53 },
0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54, { 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54 },
0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56, { 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56 },
0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55, { 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55 },
0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55, { 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55 },
0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54, { 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54 },
0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53, { 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53 },
0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53, { 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53 },
0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53, { 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53 },
0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53, { 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53 },
0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53, { 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53 },
0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55, { 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55 },
0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53, { 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53 },
0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53, { 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53 },
0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53, { 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53 },
0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59, { 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59 },
0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54, { 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54 },
0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56, { 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56 },
0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54, { 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54 },
0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56, { 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56 },
0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54, { 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54 },
0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53, { 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53 },
0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53, { 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53 },
0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53, { 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53 },
0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53, { 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53 },
0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54, { 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54 },
0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55, { 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55 },
0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54, { 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54 },
0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60, { 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60 },
0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54, { 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54 },
0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53, { 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53 },
0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53, { 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53 },
0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53, { 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53 },
0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53, { 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53 },
0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57, { 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57 },
0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53, { 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53 },
0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53, { 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53 },
0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53, { 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53 },
0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53, { 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53 },
0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53, { 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53 },
0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53, { 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53 },
0x1.75feb564267c8p+0, 0x1.7edd354674916p-53, { 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53 },
0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54, { 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54 },
0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53, { 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53 },
0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54, { 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54 },
0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56, { 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56 },
0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53, { 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53 },
0x1.82589994cce12p+0, 0x1.159f115f56694p-53, { 0x1.82589994cce12p+0, 0x1.159f115f56694p-53 },
0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53, { 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53 },
0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53, { 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53 },
0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54, { 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54 },
0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54, { 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54 },
0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53, { 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53 },
0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55, { 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55 },
0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53, { 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53 },
0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53, { 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53 },
0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53, { 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53 },
0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53, { 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53 },
0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53, { 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53 },
0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56, { 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56 },
0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56, { 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56 },
0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53, { 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53 },
0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54, { 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54 },
0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53, { 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53 },
0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54, { 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54 },
0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54, { 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54 },
0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53, { 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53 },
0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54, { 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54 },
0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53, { 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53 },
0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53, { 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53 },
0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53, { 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53 },
0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53, { 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53 },
0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53, { 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53 },
0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55, { 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55 },
0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53, { 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53 },
0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55, { 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55 },
0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54, { 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54 },
0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54, { 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54 },
0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56, { 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56 },
0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56, { 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56 },
0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53, { 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53 },
0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53, { 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53 },
0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53, { 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53 },
0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55, { 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55 },
0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53, { 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53 },
0x1.da9e603db3285p+0, 0x1.c2300696db532p-54, { 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54 },
0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54, { 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54 },
0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53, { 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53 },
0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53, { 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53 },
0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55, { 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55 },
0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54, { 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54 },
0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53, { 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53 },
0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53, { 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53 },
0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54, { 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54 },
0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54, { 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54 },
0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54, { 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54 },
0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53, { 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53 },
0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55, { 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55 },
0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 { 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 }
}; };
/* /*

View File

@ -152,135 +152,135 @@ static const struct {
* mainly to minimize the size of the table. Using all 24 bits * mainly to minimize the size of the table. Using all 24 bits
* in a float for it automatically satisfies the above constraints. * in a float for it automatically satisfies the above constraints.
*/ */
0x800000.0p-23, 0, 0, { 0x800000.0p-23, 0, 0 },
0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6675.0p-84, { 0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6675.0p-84 },
0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83718.0p-84, { 0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83718.0p-84 },
0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173698.0p-83, { 0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173698.0p-83 },
0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e79.0p-82, { 0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e79.0p-82 },
0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82, { 0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82 },
0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a1076.0p-83, { 0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a1076.0p-83 },
0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb9589.0p-82, { 0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb9589.0p-82 },
0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c5.0p-91, { 0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c5.0p-91 },
0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560e.0p-81, { 0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560e.0p-81 },
0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d503.0p-82, { 0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d503.0p-82 },
0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83, { 0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83 },
0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da9a.0p-81, { 0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da9a.0p-81 },
0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83, { 0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83 },
0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251af0.0p-85, { 0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251af0.0p-85 },
0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d5.0p-84, { 0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d5.0p-84 },
0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e676.0p-81, { 0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e676.0p-81 },
0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f42.0p-82, { 0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f42.0p-82 },
0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6b00.0p-80, { 0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6b00.0p-80 },
0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83, { 0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83 },
0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82, { 0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82 },
0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80, { 0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80 },
0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c47.0p-82, { 0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c47.0p-82 },
0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e569.0p-81, { 0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e569.0p-81 },
0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba936770.0p-84, { 0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba936770.0p-84 },
0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d32.0p-80, { 0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d32.0p-80 },
0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b7.0p-81, { 0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b7.0p-81 },
0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06.0p-80, { 0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06.0p-80 },
0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82, { 0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82 },
0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d6866.0p-81, { 0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d6866.0p-81 },
0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae55.0p-80, { 0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae55.0p-80 },
0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc45954.0p-81, { 0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc45954.0p-81 },
0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d.0p-81, { 0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d.0p-81 },
0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df842.0p-85, { 0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df842.0p-85 },
0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe.0p-87, { 0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe.0p-87 },
0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa69.0p-81, { 0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa69.0p-81 },
0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb3283.0p-80, { 0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb3283.0p-80 },
0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e.0p-79, { 0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e.0p-79 },
0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f46.0p-79, { 0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f46.0p-79 },
0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a.0p-81, { 0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a.0p-81 },
0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de9.0p-79, { 0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de9.0p-79 },
0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5148.0p-81, { 0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5148.0p-81 },
0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba4.0p-79, { 0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba4.0p-79 },
0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b731.0p-80, { 0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b731.0p-80 },
0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81, { 0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81 },
0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79, { 0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79 },
0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c566.0p-79, { 0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c566.0p-79 },
0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb24.0p-81, { 0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb24.0p-81 },
0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698.0p-81, { 0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698.0p-81 },
0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123616.0p-82, { 0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123616.0p-82 },
0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b2.0p-80, { 0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b2.0p-80 },
0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a424234.0p-79, { 0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a424234.0p-79 },
0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83, { 0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83 },
0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770634.0p-79, { 0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770634.0p-79 },
0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b152.0p-82, { 0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b152.0p-82 },
0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f09.0p-80, { 0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f09.0p-80 },
0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad89.0p-79, { 0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad89.0p-79 },
0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf.0p-79, { 0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf.0p-79 },
0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab90486409.0p-80, { 0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab90486409.0p-80 },
0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333.0p-79, { 0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333.0p-79 },
0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80, { 0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80 },
0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c9.0p-80, { 0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c9.0p-80 },
0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79, { 0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79 },
0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a87.0p-81, { 0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a87.0p-81 },
0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3cb.0p-79, { 0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3cb.0p-79 },
0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d.0p-81, { 0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d.0p-81 },
0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81, { 0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81 },
0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79, { 0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79 },
0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b61.0p-80, { 0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b61.0p-80 },
0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a3.0p-80, { 0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a3.0p-80 },
0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82, { 0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82 },
0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80, { 0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80 },
0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f57.0p-80, { 0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f57.0p-80 },
0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80, { 0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80 },
0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d4.0p-80, { 0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d4.0p-80 },
0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd.0p-79, { 0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd.0p-79 },
0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f730190.0p-79, { 0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f730190.0p-79 },
0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cd.0p-80, { 0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cd.0p-80 },
0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d.0p-81, { 0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d.0p-81 },
0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af2.0p-79, { 0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af2.0p-79 },
0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84, { 0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84 },
0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade0.0p-79, { 0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade0.0p-79 },
0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1.0p-79, { 0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1.0p-79 },
0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c53.0p-79, { 0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c53.0p-79 },
0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f.0p-78, { 0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f.0p-78 },
0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e5.0p-81, { 0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e5.0p-81 },
0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b.0p-79, { 0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b.0p-79 },
0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb8287.0p-78, { 0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb8287.0p-78 },
0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9c.0p-78, { 0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9c.0p-78 },
0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f0.0p-79, { 0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f0.0p-79 },
0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd6.0p-80, { 0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd6.0p-80 },
0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de.0p-78, { 0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de.0p-78 },
0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78, { 0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78 },
0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79, { 0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79 },
0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79, { 0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79 },
0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f77.0p-78, { 0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f77.0p-78 },
0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80, { 0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80 },
0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d7.0p-79, { 0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d7.0p-79 },
0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3237.0p-79, { 0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3237.0p-79 },
0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d.0p-79, { 0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d.0p-79 },
0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c337.0p-79, { 0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c337.0p-79 },
0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf3.0p-78, { 0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf3.0p-78 },
0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79, { 0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79 },
0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507c.0p-78, { 0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507c.0p-78 },
0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e98.0p-79, { 0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e98.0p-79 },
0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78, { 0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78 },
0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f952.0p-78, { 0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f952.0p-78 },
0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe.0p-78, { 0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe.0p-78 },
0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576b.0p-78, { 0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576b.0p-78 },
0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a2.0p-79, { 0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a2.0p-79 },
0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79, { 0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79 },
0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f.0p-81, { 0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f.0p-81 },
0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79, { 0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79 },
0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d20.0p-78, { 0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d20.0p-78 },
0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c01.0p-79, { 0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c01.0p-79 },
0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541ad.0p-79, { 0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541ad.0p-79 },
0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4572.0p-78, { 0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4572.0p-78 },
0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c.0p-80, { 0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c.0p-80 },
0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d74936.0p-80, { 0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d74936.0p-80 },
0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce53266.0p-79, { 0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce53266.0p-79 },
0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d2.0p-79, { 0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d2.0p-79 },
0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b36.0p-80, { 0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b36.0p-80 },
0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3.0p-79, { 0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3.0p-79 },
0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80, { 0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80 },
0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80, { 0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80 },
0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a83.0p-81, { 0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a83.0p-81 },
0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b.0p-78, { 0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b.0p-78 },
0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a198.0p-78, { 0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a198.0p-78 },
0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c39.0p-81, { 0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c39.0p-81 },
}; };
#ifdef USE_UTAB #ifdef USE_UTAB
@ -288,135 +288,135 @@ static const struct {
float H; /* 1 + i/INTERVALS (exact) */ float H; /* 1 + i/INTERVALS (exact) */
float E; /* H(i) * G(i) - 1 (exact) */ float E; /* H(i) * G(i) - 1 (exact) */
} U[TSIZE] = { } U[TSIZE] = {
0x800000.0p-23, 0, { 0x800000.0p-23, 0 },
0x810000.0p-23, -0x800000.0p-37, { 0x810000.0p-23, -0x800000.0p-37 },
0x820000.0p-23, -0x800000.0p-35, { 0x820000.0p-23, -0x800000.0p-35 },
0x830000.0p-23, -0x900000.0p-34, { 0x830000.0p-23, -0x900000.0p-34 },
0x840000.0p-23, -0x800000.0p-33, { 0x840000.0p-23, -0x800000.0p-33 },
0x850000.0p-23, -0xc80000.0p-33, { 0x850000.0p-23, -0xc80000.0p-33 },
0x860000.0p-23, -0xa00000.0p-36, { 0x860000.0p-23, -0xa00000.0p-36 },
0x870000.0p-23, 0x940000.0p-33, { 0x870000.0p-23, 0x940000.0p-33 },
0x880000.0p-23, 0x800000.0p-35, { 0x880000.0p-23, 0x800000.0p-35 },
0x890000.0p-23, -0xc80000.0p-34, { 0x890000.0p-23, -0xc80000.0p-34 },
0x8a0000.0p-23, 0xe00000.0p-36, { 0x8a0000.0p-23, 0xe00000.0p-36 },
0x8b0000.0p-23, 0x900000.0p-33, { 0x8b0000.0p-23, 0x900000.0p-33 },
0x8c0000.0p-23, -0x800000.0p-35, { 0x8c0000.0p-23, -0x800000.0p-35 },
0x8d0000.0p-23, -0xe00000.0p-33, { 0x8d0000.0p-23, -0xe00000.0p-33 },
0x8e0000.0p-23, 0x880000.0p-33, { 0x8e0000.0p-23, 0x880000.0p-33 },
0x8f0000.0p-23, -0xa80000.0p-34, { 0x8f0000.0p-23, -0xa80000.0p-34 },
0x900000.0p-23, -0x800000.0p-35, { 0x900000.0p-23, -0x800000.0p-35 },
0x910000.0p-23, 0x800000.0p-37, { 0x910000.0p-23, 0x800000.0p-37 },
0x920000.0p-23, 0x900000.0p-35, { 0x920000.0p-23, 0x900000.0p-35 },
0x930000.0p-23, 0xd00000.0p-35, { 0x930000.0p-23, 0xd00000.0p-35 },
0x940000.0p-23, 0xe00000.0p-35, { 0x940000.0p-23, 0xe00000.0p-35 },
0x950000.0p-23, 0xc00000.0p-35, { 0x950000.0p-23, 0xc00000.0p-35 },
0x960000.0p-23, 0xe00000.0p-36, { 0x960000.0p-23, 0xe00000.0p-36 },
0x970000.0p-23, -0x800000.0p-38, { 0x970000.0p-23, -0x800000.0p-38 },
0x980000.0p-23, -0xc00000.0p-35, { 0x980000.0p-23, -0xc00000.0p-35 },
0x990000.0p-23, -0xd00000.0p-34, { 0x990000.0p-23, -0xd00000.0p-34 },
0x9a0000.0p-23, 0x880000.0p-33, { 0x9a0000.0p-23, 0x880000.0p-33 },
0x9b0000.0p-23, 0xe80000.0p-35, { 0x9b0000.0p-23, 0xe80000.0p-35 },
0x9c0000.0p-23, -0x800000.0p-35, { 0x9c0000.0p-23, -0x800000.0p-35 },
0x9d0000.0p-23, 0xb40000.0p-33, { 0x9d0000.0p-23, 0xb40000.0p-33 },
0x9e0000.0p-23, 0x880000.0p-34, { 0x9e0000.0p-23, 0x880000.0p-34 },
0x9f0000.0p-23, -0xe00000.0p-35, { 0x9f0000.0p-23, -0xe00000.0p-35 },
0xa00000.0p-23, 0x800000.0p-33, { 0xa00000.0p-23, 0x800000.0p-33 },
0xa10000.0p-23, -0x900000.0p-36, { 0xa10000.0p-23, -0x900000.0p-36 },
0xa20000.0p-23, -0xb00000.0p-33, { 0xa20000.0p-23, -0xb00000.0p-33 },
0xa30000.0p-23, -0xa00000.0p-36, { 0xa30000.0p-23, -0xa00000.0p-36 },
0xa40000.0p-23, 0x800000.0p-33, { 0xa40000.0p-23, 0x800000.0p-33 },
0xa50000.0p-23, -0xf80000.0p-35, { 0xa50000.0p-23, -0xf80000.0p-35 },
0xa60000.0p-23, 0x880000.0p-34, { 0xa60000.0p-23, 0x880000.0p-34 },
0xa70000.0p-23, -0x900000.0p-33, { 0xa70000.0p-23, -0x900000.0p-33 },
0xa80000.0p-23, -0x800000.0p-35, { 0xa80000.0p-23, -0x800000.0p-35 },
0xa90000.0p-23, 0x900000.0p-34, { 0xa90000.0p-23, 0x900000.0p-34 },
0xaa0000.0p-23, 0xa80000.0p-33, { 0xaa0000.0p-23, 0xa80000.0p-33 },
0xab0000.0p-23, -0xac0000.0p-34, { 0xab0000.0p-23, -0xac0000.0p-34 },
0xac0000.0p-23, -0x800000.0p-37, { 0xac0000.0p-23, -0x800000.0p-37 },
0xad0000.0p-23, 0xf80000.0p-35, { 0xad0000.0p-23, 0xf80000.0p-35 },
0xae0000.0p-23, 0xf80000.0p-34, { 0xae0000.0p-23, 0xf80000.0p-34 },
0xaf0000.0p-23, -0xac0000.0p-33, { 0xaf0000.0p-23, -0xac0000.0p-33 },
0xb00000.0p-23, -0x800000.0p-33, { 0xb00000.0p-23, -0x800000.0p-33 },
0xb10000.0p-23, -0xb80000.0p-34, { 0xb10000.0p-23, -0xb80000.0p-34 },
0xb20000.0p-23, -0x800000.0p-34, { 0xb20000.0p-23, -0x800000.0p-34 },
0xb30000.0p-23, -0xb00000.0p-35, { 0xb30000.0p-23, -0xb00000.0p-35 },
0xb40000.0p-23, -0x800000.0p-35, { 0xb40000.0p-23, -0x800000.0p-35 },
0xb50000.0p-23, -0xe00000.0p-36, { 0xb50000.0p-23, -0xe00000.0p-36 },
0xb60000.0p-23, -0x800000.0p-35, { 0xb60000.0p-23, -0x800000.0p-35 },
0xb70000.0p-23, -0xb00000.0p-35, { 0xb70000.0p-23, -0xb00000.0p-35 },
0xb80000.0p-23, -0x800000.0p-34, { 0xb80000.0p-23, -0x800000.0p-34 },
0xb90000.0p-23, -0xb80000.0p-34, { 0xb90000.0p-23, -0xb80000.0p-34 },
0xba0000.0p-23, -0x800000.0p-33, { 0xba0000.0p-23, -0x800000.0p-33 },
0xbb0000.0p-23, -0xac0000.0p-33, { 0xbb0000.0p-23, -0xac0000.0p-33 },
0xbc0000.0p-23, 0x980000.0p-33, { 0xbc0000.0p-23, 0x980000.0p-33 },
0xbd0000.0p-23, 0xbc0000.0p-34, { 0xbd0000.0p-23, 0xbc0000.0p-34 },
0xbe0000.0p-23, 0xe00000.0p-36, { 0xbe0000.0p-23, 0xe00000.0p-36 },
0xbf0000.0p-23, -0xb80000.0p-35, { 0xbf0000.0p-23, -0xb80000.0p-35 },
0xc00000.0p-23, -0x800000.0p-33, { 0xc00000.0p-23, -0x800000.0p-33 },
0xc10000.0p-23, 0xa80000.0p-33, { 0xc10000.0p-23, 0xa80000.0p-33 },
0xc20000.0p-23, 0x900000.0p-34, { 0xc20000.0p-23, 0x900000.0p-34 },
0xc30000.0p-23, -0x800000.0p-35, { 0xc30000.0p-23, -0x800000.0p-35 },
0xc40000.0p-23, -0x900000.0p-33, { 0xc40000.0p-23, -0x900000.0p-33 },
0xc50000.0p-23, 0x820000.0p-33, { 0xc50000.0p-23, 0x820000.0p-33 },
0xc60000.0p-23, 0x800000.0p-38, { 0xc60000.0p-23, 0x800000.0p-38 },
0xc70000.0p-23, -0x820000.0p-33, { 0xc70000.0p-23, -0x820000.0p-33 },
0xc80000.0p-23, 0x800000.0p-33, { 0xc80000.0p-23, 0x800000.0p-33 },
0xc90000.0p-23, -0xa00000.0p-36, { 0xc90000.0p-23, -0xa00000.0p-36 },
0xca0000.0p-23, -0xb00000.0p-33, { 0xca0000.0p-23, -0xb00000.0p-33 },
0xcb0000.0p-23, 0x840000.0p-34, { 0xcb0000.0p-23, 0x840000.0p-34 },
0xcc0000.0p-23, -0xd00000.0p-34, { 0xcc0000.0p-23, -0xd00000.0p-34 },
0xcd0000.0p-23, 0x800000.0p-33, { 0xcd0000.0p-23, 0x800000.0p-33 },
0xce0000.0p-23, -0xe00000.0p-35, { 0xce0000.0p-23, -0xe00000.0p-35 },
0xcf0000.0p-23, 0xa60000.0p-33, { 0xcf0000.0p-23, 0xa60000.0p-33 },
0xd00000.0p-23, -0x800000.0p-35, { 0xd00000.0p-23, -0x800000.0p-35 },
0xd10000.0p-23, 0xb40000.0p-33, { 0xd10000.0p-23, 0xb40000.0p-33 },
0xd20000.0p-23, -0x800000.0p-35, { 0xd20000.0p-23, -0x800000.0p-35 },
0xd30000.0p-23, 0xaa0000.0p-33, { 0xd30000.0p-23, 0xaa0000.0p-33 },
0xd40000.0p-23, -0xe00000.0p-35, { 0xd40000.0p-23, -0xe00000.0p-35 },
0xd50000.0p-23, 0x880000.0p-33, { 0xd50000.0p-23, 0x880000.0p-33 },
0xd60000.0p-23, -0xd00000.0p-34, { 0xd60000.0p-23, -0xd00000.0p-34 },
0xd70000.0p-23, 0x9c0000.0p-34, { 0xd70000.0p-23, 0x9c0000.0p-34 },
0xd80000.0p-23, -0xb00000.0p-33, { 0xd80000.0p-23, -0xb00000.0p-33 },
0xd90000.0p-23, -0x800000.0p-38, { 0xd90000.0p-23, -0x800000.0p-38 },
0xda0000.0p-23, 0xa40000.0p-33, { 0xda0000.0p-23, 0xa40000.0p-33 },
0xdb0000.0p-23, -0xdc0000.0p-34, { 0xdb0000.0p-23, -0xdc0000.0p-34 },
0xdc0000.0p-23, 0xc00000.0p-35, { 0xdc0000.0p-23, 0xc00000.0p-35 },
0xdd0000.0p-23, 0xca0000.0p-33, { 0xdd0000.0p-23, 0xca0000.0p-33 },
0xde0000.0p-23, -0xb80000.0p-34, { 0xde0000.0p-23, -0xb80000.0p-34 },
0xdf0000.0p-23, 0xd00000.0p-35, { 0xdf0000.0p-23, 0xd00000.0p-35 },
0xe00000.0p-23, 0xc00000.0p-33, { 0xe00000.0p-23, 0xc00000.0p-33 },
0xe10000.0p-23, -0xf40000.0p-34, { 0xe10000.0p-23, -0xf40000.0p-34 },
0xe20000.0p-23, 0x800000.0p-37, { 0xe20000.0p-23, 0x800000.0p-37 },
0xe30000.0p-23, 0x860000.0p-33, { 0xe30000.0p-23, 0x860000.0p-33 },
0xe40000.0p-23, -0xc80000.0p-33, { 0xe40000.0p-23, -0xc80000.0p-33 },
0xe50000.0p-23, -0xa80000.0p-34, { 0xe50000.0p-23, -0xa80000.0p-34 },
0xe60000.0p-23, 0xe00000.0p-36, { 0xe60000.0p-23, 0xe00000.0p-36 },
0xe70000.0p-23, 0x880000.0p-33, { 0xe70000.0p-23, 0x880000.0p-33 },
0xe80000.0p-23, -0xe00000.0p-33, { 0xe80000.0p-23, -0xe00000.0p-33 },
0xe90000.0p-23, -0xfc0000.0p-34, { 0xe90000.0p-23, -0xfc0000.0p-34 },
0xea0000.0p-23, -0x800000.0p-35, { 0xea0000.0p-23, -0x800000.0p-35 },
0xeb0000.0p-23, 0xe80000.0p-35, { 0xeb0000.0p-23, 0xe80000.0p-35 },
0xec0000.0p-23, 0x900000.0p-33, { 0xec0000.0p-23, 0x900000.0p-33 },
0xed0000.0p-23, 0xe20000.0p-33, { 0xed0000.0p-23, 0xe20000.0p-33 },
0xee0000.0p-23, -0xac0000.0p-33, { 0xee0000.0p-23, -0xac0000.0p-33 },
0xef0000.0p-23, -0xc80000.0p-34, { 0xef0000.0p-23, -0xc80000.0p-34 },
0xf00000.0p-23, -0x800000.0p-35, { 0xf00000.0p-23, -0x800000.0p-35 },
0xf10000.0p-23, 0x800000.0p-35, { 0xf10000.0p-23, 0x800000.0p-35 },
0xf20000.0p-23, 0xb80000.0p-34, { 0xf20000.0p-23, 0xb80000.0p-34 },
0xf30000.0p-23, 0x940000.0p-33, { 0xf30000.0p-23, 0x940000.0p-33 },
0xf40000.0p-23, 0xc80000.0p-33, { 0xf40000.0p-23, 0xc80000.0p-33 },
0xf50000.0p-23, -0xf20000.0p-33, { 0xf50000.0p-23, -0xf20000.0p-33 },
0xf60000.0p-23, -0xc80000.0p-33, { 0xf60000.0p-23, -0xc80000.0p-33 },
0xf70000.0p-23, -0xa20000.0p-33, { 0xf70000.0p-23, -0xa20000.0p-33 },
0xf80000.0p-23, -0x800000.0p-33, { 0xf80000.0p-23, -0x800000.0p-33 },
0xf90000.0p-23, -0xc40000.0p-34, { 0xf90000.0p-23, -0xc40000.0p-34 },
0xfa0000.0p-23, -0x900000.0p-34, { 0xfa0000.0p-23, -0x900000.0p-34 },
0xfb0000.0p-23, -0xc80000.0p-35, { 0xfb0000.0p-23, -0xc80000.0p-35 },
0xfc0000.0p-23, -0x800000.0p-35, { 0xfc0000.0p-23, -0x800000.0p-35 },
0xfd0000.0p-23, -0x900000.0p-36, { 0xfd0000.0p-23, -0x900000.0p-36 },
0xfe0000.0p-23, -0x800000.0p-37, { 0xfe0000.0p-23, -0x800000.0p-37 },
0xff0000.0p-23, -0x800000.0p-39, { 0xff0000.0p-23, -0x800000.0p-39 },
0x800000.0p-22, 0, { 0x800000.0p-22, 0 },
}; };
#endif /* USE_UTAB */ #endif /* USE_UTAB */

View File

@ -37,16 +37,20 @@
#include <blacklist.h> #include <blacklist.h>
static struct blacklist *blstate; static struct blacklist *blstate;
extern int use_blacklist;
void void
blacklist_init(void) blacklist_init(void)
{ {
blstate = blacklist_open();
if (use_blacklist)
blstate = blacklist_open();
} }
void void
blacklist_notify(int action, int fd, char *msg) blacklist_notify(int action, int fd, char *msg)
{ {
if (blstate == NULL) if (blstate == NULL)
return; return;
(void)blacklist_r(blstate, action, fd, msg); (void)blacklist_r(blstate, action, fd, msg);

View File

@ -28,5 +28,26 @@
/* $FreeBSD$ */ /* $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_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 */

View File

@ -36,7 +36,7 @@
.Nd Internet File Transfer Protocol server .Nd Internet File Transfer Protocol server
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl 468ADdEhMmOoRrSUvW .Op Fl 468ABDdEhMmOoRrSUvW
.Op Fl l Op Fl l .Op Fl l Op Fl l
.Op Fl a Ar address .Op Fl a Ar address
.Op Fl P Ar port .Op Fl P Ar port
@ -95,6 +95,14 @@ When
.Fl D .Fl D
is specified, accept connections only on the specified is specified, accept connections only on the specified
.Ar address . .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 .It Fl D
With this option set, With this option set,
.Nm .Nm

View File

@ -144,6 +144,7 @@ int noretr = 0; /* RETR command is disabled. */
int noguestretr = 0; /* RETR command is disabled for anon users. */ int noguestretr = 0; /* RETR command is disabled for anon users. */
int noguestmkd = 0; /* MKD 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 noguestmod = 1; /* anon users may not modify existing files. */
int use_blacklist = 0;
off_t file_size; off_t file_size;
off_t byte_count; off_t byte_count;
@ -305,7 +306,7 @@ main(int argc, char *argv[], char **envp)
openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
while ((ch = getopt(argc, argv, while ((ch = getopt(argc, argv,
"468a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { "468a:ABdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
switch (ch) { switch (ch) {
case '4': case '4':
family = (family == AF_INET6) ? AF_UNSPEC : AF_INET; family = (family == AF_INET6) ? AF_UNSPEC : AF_INET;
@ -327,6 +328,14 @@ main(int argc, char *argv[], char **envp)
anon_only = 1; anon_only = 1;
break; break;
case 'B':
#ifdef USE_BLACKLIST
use_blacklist = 1;
#else
syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support");
#endif
break;
case 'd': case 'd':
ftpdebug++; ftpdebug++;
break; break;
@ -644,9 +653,7 @@ main(int argc, char *argv[], char **envp)
reply(220, "%s FTP server (%s) ready.", hostname, version); reply(220, "%s FTP server (%s) ready.", hostname, version);
else else
reply(220, "FTP server ready."); reply(220, "FTP server ready.");
#ifdef USE_BLACKLIST BLACKLIST_INIT();
blacklist_init();
#endif
for (;;) for (;;)
(void) yyparse(); (void) yyparse();
/* NOTREACHED */ /* NOTREACHED */
@ -1422,9 +1429,7 @@ pass(char *passwd)
*/ */
if (rval) { if (rval) {
reply(530, "Login incorrect."); reply(530, "Login incorrect.");
#ifdef USE_BLACKLIST BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Login incorrect");
blacklist_notify(1, STDIN_FILENO, "Login incorrect");
#endif
if (logging) { if (logging) {
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"FTP LOGIN FAILED FROM %s", "FTP LOGIN FAILED FROM %s",
@ -1441,12 +1446,9 @@ pass(char *passwd)
exit(0); exit(0);
} }
return; 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 */ login_attempts = 0; /* this time successful */
if (setegid(pw->pw_gid) < 0) { if (setegid(pw->pw_gid) < 0) {

View File

@ -10,6 +10,8 @@
# $FreeBSD$ # $FreeBSD$
# #
set -e
PATH=/bin:/usr/bin:/sbin:/usr/sbin PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH export PATH
@ -31,10 +33,6 @@ fi
echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab
echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local
makefs -B little -o label=FreeBSD_Install ${2}.part ${1} 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/fstab
rm ${1}/etc/rc.conf.local rm ${1}/etc/rc.conf.local

View File

@ -2716,11 +2716,6 @@ printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
static void static void
printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) 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); printf("%s", tag);
if (verbose) { if (verbose) {
@ -2754,7 +2749,6 @@ do { \
printf(" FORM:0x%x CAPS:0x%x>", mconf->conf_form, printf(" FORM:0x%x CAPS:0x%x>", mconf->conf_form,
mconf->conf_cap); mconf->conf_cap);
} }
#undef MATCHOUI
} }
static void static void

View File

@ -250,7 +250,7 @@ copies:
symlinks: symlinks:
.for i in ${LDIRS} .for i in ${LDIRS}
rm -rf ${DESTDIR}${BINDIR}/$i rm -rf ${DESTDIR}${BINDIR}/$i
ln -s ${.CURDIR}/$i ${DESTDIR}${BINDIR}/$i ${INSTALL} ${TAG_ARGS} -l s ${.CURDIR}/$i ${DESTDIR}${BINDIR}/$i
.endfor .endfor
etc-examples: etc-examples:

View File

@ -78,7 +78,7 @@ CTFFLAGS+= -g
# prefer .s to a .c, add .po, remove stuff not used in the BSD libraries # prefer .s to a .c, add .po, remove stuff not used in the BSD libraries
# .pico used for PIC object files # .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 !defined(PICFLAG)
.if ${MACHINE_CPUARCH} == "sparc64" .if ${MACHINE_CPUARCH} == "sparc64"
@ -199,6 +199,18 @@ lib${LIB_PRIVATE}${LIB}_p.a: ${POBJS}
${RANLIB} ${RANLIBFLAGS} ${.TARGET} ${RANLIB} ${RANLIBFLAGS} ${.TARGET}
.endif .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) || \ .if defined(SHLIB_NAME) || \
defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB) defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
SOBJS+= ${OBJS:.o=.pico} SOBJS+= ${OBJS:.o=.pico}

View File

@ -4,7 +4,7 @@
.include <bsd.init.mk> .include <bsd.init.mk>
.include <bsd.compiler.mk> .include <bsd.compiler.mk>
.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. # XXX The use of COPTS in modern makefiles is discouraged.
.if defined(COPTS) .if defined(COPTS)
@ -147,6 +147,19 @@ ${PROGNAME}.debug: ${PROG_FULL}
${OBJCOPY} --only-keep-debug ${PROG_FULL} ${.TARGET} ${OBJCOPY} --only-keep-debug ${PROG_FULL} ${.TARGET}
.endif .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) && \ .if ${MK_MAN} != "no" && !defined(MAN) && \
!defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \ !defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \
!defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \ !defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \
@ -166,14 +179,14 @@ all: all-man
.endif .endif
.if defined(PROG) .if defined(PROG)
CLEANFILES+= ${PROG} CLEANFILES+= ${PROG} ${PROG}.bc ${PROG}.ll
.if ${MK_DEBUG_FILES} != "no" .if ${MK_DEBUG_FILES} != "no"
CLEANFILES+= ${PROG_FULL} ${PROGNAME}.debug CLEANFILES+= ${PROG_FULL} ${PROG_FULL}.bc ${PROGNAME}.debug ${PROG_FULL}.ll
.endif .endif
.endif .endif
.if defined(OBJS) .if defined(OBJS)
CLEANFILES+= ${OBJS} CLEANFILES+= ${OBJS} ${BCOBJS} ${LLOBJS}
.endif .endif
.include <bsd.libnames.mk> .include <bsd.libnames.mk>

View File

@ -231,6 +231,8 @@ LINTLIBFLAGS ?= -cghapbxu -C ${LIB}
MAKE ?= make MAKE ?= make
.if !defined(%POSIX) .if !defined(%POSIX)
LLVM_LINK ?= llvm-link
LORDER ?= lorder LORDER ?= lorder
NM ?= nm NM ?= nm

View File

@ -83,7 +83,9 @@ options RCTL # Resource limits
options KDB # Enable kernel debugger support. options KDB # Enable kernel debugger support.
options KDB_TRACE # Print a stack trace for a panic. options KDB_TRACE # Print a stack trace for a panic.
# For full debugger support use (turn off in stable branch): # For full debugger support use (turn off in stable branch):
options BUF_TRACKING # Track buffer history
options DDB # Support DDB. options DDB # Support DDB.
options FULL_BUF_TRACKING # Track more buffer history
options GDB # Support remote GDB. options GDB # Support remote GDB.
options DEADLKRES # Enable the deadlock resolver options DEADLKRES # Enable the deadlock resolver
options INVARIANTS # Enable calls of extra sanity checking options INVARIANTS # Enable calls of extra sanity checking

View File

@ -34,5 +34,7 @@ nooptions INVARIANTS
nooptions INVARIANT_SUPPORT nooptions INVARIANT_SUPPORT
nooptions WITNESS nooptions WITNESS
nooptions WITNESS_SKIPSPIN nooptions WITNESS_SKIPSPIN
nooptions BUF_TRACKING
nooptions DEADLKRES nooptions DEADLKRES
nooptions FULL_BUF_TRACKING

View File

@ -500,7 +500,8 @@ pmap_set_tex(void)
/* Add shareable bits for normal memory in SMP case. */ /* Add shareable bits for normal memory in SMP case. */
#ifdef SMP #ifdef SMP
prrr |= PRRR_NS1; if (ARM_USE_MP_EXTENSIONS)
prrr |= PRRR_NS1;
#endif #endif
cp15_prrr_set(prrr); cp15_prrr_set(prrr);
cp15_nmrr_set(nmrr); cp15_nmrr_set(nmrr);

View File

@ -21,6 +21,7 @@
ident GENERIC ident GENERIC
cpu CPU_CORTEXA_MP cpu CPU_CORTEXA_MP
cpu CPU_CORTEXA8
machine arm armv6 machine arm armv6
makeoptions CONF_CFLAGS="-march=armv7a" makeoptions CONF_CFLAGS="-march=armv7a"
@ -37,6 +38,8 @@ files "../broadcom/bcm2835/files.bcm2836"
files "../broadcom/bcm2835/files.bcm283x" files "../broadcom/bcm2835/files.bcm283x"
files "../nvidia/tegra124/files.tegra124" files "../nvidia/tegra124/files.tegra124"
files "../qemu/files.qemu" files "../qemu/files.qemu"
files "../ti/files.ti"
files "../ti/am335x/files.am335x"
options SOC_ALLWINNER_A20 options SOC_ALLWINNER_A20
options SOC_ALLWINNER_A31 options SOC_ALLWINNER_A31
@ -44,6 +47,7 @@ options SOC_ALLWINNER_A31S
options SOC_ALLWINNER_A83T options SOC_ALLWINNER_A83T
options SOC_ALLWINNER_H3 options SOC_ALLWINNER_H3
options SOC_BCM2836 options SOC_BCM2836
options SOC_TI_AM335X
options SCHED_ULE # ULE scheduler options SCHED_ULE # ULE scheduler
options SMP # Enable multiple cores options SMP # Enable multiple cores
@ -66,6 +70,9 @@ device cpufreq
options INTRNG options INTRNG
device gic device gic
# PMU support (for CCNT).
device pmu
# ARM Generic Timer # ARM Generic Timer
device generic_timer device generic_timer
@ -113,9 +120,14 @@ device axp81x # AXP813/818 Power Management Unit
device bcm2835_bsc device bcm2835_bsc
device icee device icee
device sy8106a # SY8106A Buck Regulator 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 # GPIO
device gpio device gpio
device gpiobacklight
device gpioled device gpioled
device gpioregulator device gpioregulator
@ -128,6 +140,16 @@ device aw_cir
# SPI # SPI
device spibus device spibus
device bcm2835_spi 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 scbus # SCSI bus (required for ATA/SCSI)
device da # Direct Access (disks) device da # Direct Access (disks)
@ -141,11 +163,16 @@ device usb
device ohci device ohci
device ehci device ehci
device dwcotg # DWC OTG controller device dwcotg # DWC OTG controller
device musb
device umass # Disks/Mass storage - Requires scbus and da device umass # Disks/Mass storage - Requires scbus and da
device uhid # "Human Interface Devices" device uhid # "Human Interface Devices"
device ukbd # Allow keyboard like HIDs to control console 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 # Ethernet
device loop device loop
device ether device ether
@ -176,6 +203,12 @@ device vchiq
# Pinmux # Pinmux
device fdt_pinctrl device fdt_pinctrl
# TI Programmable Realtime Unit support
device ti_pruss
# Mailbox support
device ti_mbox
# Extensible Firmware Interface # Extensible Firmware Interface
options EFI options EFI

View File

@ -32,7 +32,7 @@ arm/freescale/imx/imx51_ccm.c standard
dev/ata/chipsets/ata-fsl.c optional imxata dev/ata/chipsets/ata-fsl.c optional imxata
# SDHCI/MMC # SDHCI/MMC
arm/freescale/imx/imx_sdhci.c optional sdhci dev/sdhci/fsl_sdhci.c optional sdhci
# USB OH3 controller (1 OTG, 3 EHCI) # USB OH3 controller (1 OTG, 3 EHCI)
arm/freescale/imx/imx_nop_usbphy.c optional ehci arm/freescale/imx/imx_nop_usbphy.c optional ehci

View File

@ -32,7 +32,7 @@ arm/freescale/imx/imx6_ipu.c optional vt
# #
# Optional devices. # 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 arm/freescale/imx/imx_wdog.c optional imxwdt

View File

@ -45,6 +45,21 @@
#define CPU_ASID_KERNEL 0 #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 !!! */ 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 dcache_wb_pou_checked(vm_offset_t, vm_size_t);
vm_offset_t icache_inv_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 */ /* TLB */
_WF0(_CP15_TLBIALL, CP15_TLBIALL) /* Invalidate entire unified 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 */ _WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS) /* Invalidate entire unified TLB IS */
#endif #endif
_WF1(_CP15_TLBIASID, CP15_TLBIASID(%0)) /* Invalidate unified TLB by ASID */ _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 */ _WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0)) /* Invalidate unified TLB by ASID IS */
#endif #endif
_WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0)) /* Invalidate unified TLB by MVA, all ASID */ _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 */ _WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0)) /* Invalidate unified TLB by MVA, all ASID IS */
#endif #endif
_WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0)) /* Invalidate unified TLB by MVA */ _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 */ /* Cache and Branch predictor */
_WF0(_CP15_BPIALL, CP15_BPIALL) /* Branch predictor invalidate all */ _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 */ _WF0(_CP15_BPIALLIS, CP15_BPIALLIS) /* Branch predictor invalidate all IS */
#endif #endif
_WF1(_CP15_BPIMVA, CP15_BPIMVA(%0)) /* Branch predictor invalidate by MVA */ _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_DCIMVAC, CP15_DCIMVAC(%0)) /* Data cache invalidate by MVA PoC */
_WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */ _WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */
_WF0(_CP15_ICIALLU, CP15_ICIALLU) /* Instruction cache invalidate all PoU */ _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 */ _WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS) /* Instruction cache invalidate all PoU IS */
#endif #endif
_WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0)) /* Instruction cache invalidate */ _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. */ /* Broadcasting operations. */
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
#if defined(CPU_CORTEXA8)
#define ARM_HAVE_MP_EXTENSIONS (cpuinfo.mp_ext != 0)
#else
#define ARM_HAVE_MP_EXTENSIONS 1
#endif
static __inline void static __inline void
tlb_flush_all(void) tlb_flush_all(void)
{ {
dsb(); dsb();
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_TLBIALLIS(); _CP15_TLBIALLIS();
else else
_CP15_TLBIALL(); _CP15_TLBIALL();
@ -370,7 +379,7 @@ tlb_flush_all_ng(void)
{ {
dsb(); dsb();
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_TLBIASIDIS(CPU_ASID_KERNEL); _CP15_TLBIASIDIS(CPU_ASID_KERNEL);
else else
_CP15_TLBIASID(CPU_ASID_KERNEL); _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)); KASSERT((va & PAGE_MASK) == 0, ("%s: va %#x not aligned", __func__, va));
dsb(); dsb();
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_TLBIMVAAIS(va); _CP15_TLBIMVAAIS(va);
else else
_CP15_TLBIMVA(va | CPU_ASID_KERNEL); _CP15_TLBIMVA(va | CPU_ASID_KERNEL);
@ -401,7 +410,7 @@ tlb_flush_range(vm_offset_t va, vm_size_t size)
size)); size));
dsb(); dsb();
if (ARM_HAVE_MP_EXTENSIONS) { if (ARM_USE_MP_EXTENSIONS) {
for (; va < eva; va += PAGE_SIZE) for (; va < eva; va += PAGE_SIZE)
_CP15_TLBIMVAAIS(va); _CP15_TLBIMVAAIS(va);
} else { } else {
@ -410,14 +419,14 @@ tlb_flush_range(vm_offset_t va, vm_size_t size)
} }
dsb(); dsb();
} }
#else /* SMP */ #else /* __ARM_ARCH < 7 */
#define tlb_flush_all() tlb_flush_all_local() #define tlb_flush_all() tlb_flush_all_local()
#define tlb_flush_all_ng() tlb_flush_all_ng_local() #define tlb_flush_all_ng() tlb_flush_all_ng_local()
#define tlb_flush(va) tlb_flush_local(va) #define tlb_flush(va) tlb_flush_local(va)
#define tlb_flush_range(va, size) tlb_flush_range_local(va, size) #define tlb_flush_range(va, size) tlb_flush_range_local(va, size)
#endif /* SMP */ #endif /* __ARM_ARCH < 7 */
/* /*
* Cache maintenance operations. * Cache maintenance operations.
@ -431,8 +440,8 @@ icache_sync(vm_offset_t va, vm_size_t size)
dsb(); dsb();
va &= ~cpuinfo.dcache_line_mask; va &= ~cpuinfo.dcache_line_mask;
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
if (ARM_HAVE_MP_EXTENSIONS) { if (ARM_USE_MP_EXTENSIONS) {
for ( ; va < eva; va += cpuinfo.dcache_line_size) for ( ; va < eva; va += cpuinfo.dcache_line_size)
_CP15_DCCMVAU(va); _CP15_DCCMVAU(va);
} else } else
@ -442,8 +451,8 @@ icache_sync(vm_offset_t va, vm_size_t size)
_CP15_DCCMVAC(va); _CP15_DCCMVAC(va);
} }
dsb(); dsb();
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_ICIALLUIS(); _CP15_ICIALLUIS();
else else
#endif #endif
@ -456,8 +465,8 @@ icache_sync(vm_offset_t va, vm_size_t size)
static __inline void static __inline void
icache_inv_all(void) icache_inv_all(void)
{ {
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_ICIALLUIS(); _CP15_ICIALLUIS();
else else
#endif #endif
@ -470,8 +479,8 @@ icache_inv_all(void)
static __inline void static __inline void
bpb_inv_all(void) bpb_inv_all(void)
{ {
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
if (ARM_HAVE_MP_EXTENSIONS) if (ARM_USE_MP_EXTENSIONS)
_CP15_BPIALLIS(); _CP15_BPIALLIS();
else else
#endif #endif
@ -488,8 +497,8 @@ dcache_wb_pou(vm_offset_t va, vm_size_t size)
dsb(); dsb();
va &= ~cpuinfo.dcache_line_mask; va &= ~cpuinfo.dcache_line_mask;
#if __ARM_ARCH >= 7 && defined SMP #if __ARM_ARCH >= 7
if (ARM_HAVE_MP_EXTENSIONS) { if (ARM_USE_MP_EXTENSIONS) {
for ( ; va < eva; va += cpuinfo.dcache_line_size) for ( ; va < eva; va += cpuinfo.dcache_line_size)
_CP15_DCCMVAU(va); _CP15_DCCMVAU(va);
} else } else

View File

@ -140,7 +140,7 @@
/* /*
* CP15 C7 registers * CP15 C7 registers
*/ */
#if __ARM_ARCH >= 7 && defined(SMP) #if __ARM_ARCH >= 7
/* From ARMv7: */ /* From ARMv7: */
#define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */ #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 */ #define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */
@ -205,7 +205,7 @@
/* /*
* CP15 C8 registers * CP15 C8 registers
*/ */
#if __ARM_ARCH >= 7 && defined(SMP) #if __ARM_ARCH >= 7
/* From ARMv7: */ /* From ARMv7: */
#define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */ #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 */ #define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */

View File

@ -357,10 +357,12 @@ efinet_dev_print(int verbose)
for (unit = 0, h = efi_find_handle(&efinet_dev, 0); for (unit = 0, h = efi_find_handle(&efinet_dev, 0);
h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) { h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) {
printf(" %s%d:", efinet_dev.dv_name, unit); printf(" %s%d:", efinet_dev.dv_name, unit);
text = efi_devpath_name(efi_lookup_devpath(h)); if (verbose) {
if (text != NULL) { text = efi_devpath_name(efi_lookup_devpath(h));
printf(" %S", text); if (text != NULL) {
efi_free_devpath_name(text); printf(" %S", text);
efi_free_devpath_name(text);
}
} }
if (pager_output("\n")) if (pager_output("\n"))
break; break;

View File

@ -744,6 +744,9 @@ struct ccb_scsiio {
#define CAM_TAG_ACTION_NONE 0x00 #define CAM_TAG_ACTION_NONE 0x00
u_int tag_id; /* tag id from initator (target mode) */ u_int tag_id; /* tag id from initator (target mode) */
u_int init_id; /* initiator id of who selected */ 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 * 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->sense_len = sense_len;
csio->cdb_len = cdb_len; csio->cdb_len = cdb_len;
csio->tag_action = tag_action; csio->tag_action = tag_action;
#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
csio->bio = NULL;
#endif
} }
static __inline void static __inline void

View File

@ -1427,6 +1427,11 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
union ccb *orig_ccb = ccb; union ccb *orig_ccb = ccb;
int error, recoveryccb; 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); periph = xpt_path_periph(ccb->ccb_h.path);
recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone); recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone);
if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) { if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) {

View File

@ -31,6 +31,7 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/bio.h>
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/types.h> #include <sys/types.h>
@ -4471,6 +4472,12 @@ xpt_done(union ccb *done_ccb)
struct cam_doneq *queue; struct cam_doneq *queue;
int run, hash; 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, CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("xpt_done: func= %#x %s status %#x\n", ("xpt_done: func= %#x %s status %#x\n",
done_ccb->ccb_h.func_code, done_ccb->ccb_h.func_code,
@ -5189,6 +5196,16 @@ xpt_done_process(struct ccb_hdr *ccb_h)
struct cam_devq *devq; struct cam_devq *devq;
struct mtx *mtx = NULL; 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) { if (ccb_h->flags & CAM_HIGH_POWER) {
struct highpowerlist *hphead; struct highpowerlist *hphead;
struct cam_ed *device; struct cam_ed *device;

View File

@ -2949,6 +2949,8 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
void *data_ptr; void *data_ptr;
int rw_op; int rw_op;
biotrack(bp, __func__);
if (bp->bio_cmd == BIO_WRITE) { if (bp->bio_cmd == BIO_WRITE) {
softc->flags |= DA_FLAG_DIRTY; softc->flags |= DA_FLAG_DIRTY;
rw_op = SCSI_RW_WRITE; rw_op = SCSI_RW_WRITE;
@ -2976,6 +2978,9 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
/*dxfer_len*/ bp->bio_bcount, /*dxfer_len*/ bp->bio_bcount,
/*sense_len*/SSD_FULL_SIZE, /*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000); da_default_timeout * 1000);
#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
start_ccb->csio.bio = bp;
#endif
break; break;
} }
case BIO_FLUSH: 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")); CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
csio = &done_ccb->csio; 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; state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
switch (state) { switch (state) {
case DA_CCB_BUFFER_IO: 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); LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
if (LIST_EMPTY(&softc->pending_ccbs)) if (LIST_EMPTY(&softc->pending_ccbs))
softc->flags |= DA_FLAG_WAS_OTAG; 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; struct cam_periph *periph;
int error, error_code, sense_key, asc, ascq; 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); periph = xpt_path_periph(ccb->ccb_h.path);
softc = (struct da_softc *)periph->softc; softc = (struct da_softc *)periph->softc;

View File

@ -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_destroy(itx_t *itx);
extern void zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx); 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 void zil_commit(zilog_t *zilog, uint64_t oid);
extern int zil_vdev_offline(const char *osname, void *txarg); extern int zil_vdev_offline(const char *osname, void *txarg);

View File

@ -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 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) - \ #define LWB_EMPTY(lwb) ((BP_GET_LSIZE(&lwb->lwb_blk) - \
sizeof (zil_chain_t)) == (lwb->lwb_sz - lwb->lwb_nused)) 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. * 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) zil_async_to_sync(zilog_t *zilog, uint64_t foid)
{ {
uint64_t otxg, txg; uint64_t otxg, txg;

View File

@ -169,6 +169,7 @@ typedef struct zvol_state {
uint32_t zv_open_count[OTYPCNT]; /* open counts */ uint32_t zv_open_count[OTYPCNT]; /* open counts */
#endif #endif
uint32_t zv_total_opens; /* total open count */ uint32_t zv_total_opens; /* total open count */
uint32_t zv_sync_cnt; /* synchronous open count */
zilog_t *zv_zilog; /* ZIL handle */ zilog_t *zv_zilog; /* ZIL handle */
list_t zv_extents; /* List of extents for dump */ list_t zv_extents; /* List of extents for dump */
znode_t zv_znode; /* for range locking */ 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); BP_ZERO(&lr->lr_blkptr);
itx->itx_private = zv; 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); zil_itx_assign(zilog, itx, tx);
@ -1674,7 +1677,7 @@ zvol_strategy(struct bio *bp)
if (error != 0) { if (error != 0) {
dmu_tx_abort(tx); dmu_tx_abort(tx);
} else { } else {
zvol_log_truncate(zv, tx, off, resid, B_TRUE); zvol_log_truncate(zv, tx, off, resid, sync);
dmu_tx_commit(tx); dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ,
off, resid); 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_offset = off;
lr->lr_length = len; lr->lr_length = len;
itx->itx_sync = sync; itx->itx_sync = (sync || zv->zv_sync_cnt != 0);
zil_itx_assign(zilog, itx, tx); zil_itx_assign(zilog, itx, tx);
} }
@ -3075,6 +3078,11 @@ zvol_d_open(struct cdev *dev, int flags, int fmt, struct thread *td)
#endif #endif
zv->zv_total_opens++; 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); mutex_exit(&zfsdev_state_lock);
return (err); return (err);
out: 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. * You may get multiple opens, but only one close.
*/ */
zv->zv_total_opens--; zv->zv_total_opens--;
if (flags & (FSYNC | FDSYNC))
zv->zv_sync_cnt--;
if (zv->zv_total_opens == 0) if (zv->zv_total_opens == 0)
zvol_last_close(zv); 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; zvol_state_t *zv;
rl_t *rl; rl_t *rl;
off_t offset, length, chunk; off_t offset, length;
int i, error; int i, error;
u_int u; boolean_t sync;
zv = dev->si_drv2; 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); dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
error = dmu_tx_assign(tx, TXG_WAIT); error = dmu_tx_assign(tx, TXG_WAIT);
if (error != 0) { if (error != 0) {
sync = FALSE;
dmu_tx_abort(tx); dmu_tx_abort(tx);
} else { } 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); dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ,
offset, length); offset, length);
} }
zfs_range_unlock(rl); zfs_range_unlock(rl);
if (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) if (sync)
zil_commit(zv->zv_zilog, ZVOL_OBJ); zil_commit(zv->zv_zilog, ZVOL_OBJ);
break; break;
case DIOCGSTRIPESIZE: case DIOCGSTRIPESIZE:

View File

@ -293,7 +293,7 @@ dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc
dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_nvs.c optional hyperv
dev/hyperv/netvsc/hn_rndis.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/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv

View File

@ -250,7 +250,7 @@ dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc
dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_nvs.c optional hyperv
dev/hyperv/netvsc/hn_rndis.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/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv

View File

@ -63,6 +63,7 @@ dev/ofw/ofw_subr.c optional aim powerpc
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx
dev/scc/scc_bfe_macio.c optional scc powermac 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/sec/sec.c optional sec mpc85xx
dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac
dev/sound/macio/davbus.c optional snd_davbus 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_bus_fdt.c optional ds1553 fdt
powerpc/mpc85xx/ds1553_core.c optional ds1553 powerpc/mpc85xx/ds1553_core.c optional ds1553
powerpc/mpc85xx/fsl_diu.c optional mpc85xx diu 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/i2c.c optional iicbus fdt
powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/isa.c optional mpc85xx isa
powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/lbc.c optional mpc85xx

View File

@ -50,12 +50,14 @@ TWA_FLASH_FIRMWARE opt_twa.h
# Debugging options. # Debugging options.
ALT_BREAK_TO_DEBUGGER opt_kdb.h ALT_BREAK_TO_DEBUGGER opt_kdb.h
BREAK_TO_DEBUGGER opt_kdb.h BREAK_TO_DEBUGGER opt_kdb.h
BUF_TRACKING opt_global.h
DDB DDB
DDB_BUFR_SIZE opt_ddb.h DDB_BUFR_SIZE opt_ddb.h
DDB_CAPTURE_DEFAULTBUFSIZE opt_ddb.h DDB_CAPTURE_DEFAULTBUFSIZE opt_ddb.h
DDB_CAPTURE_MAXBUFSIZE opt_ddb.h DDB_CAPTURE_MAXBUFSIZE opt_ddb.h
DDB_CTF opt_ddb.h DDB_CTF opt_ddb.h
DDB_NUMSYM opt_ddb.h DDB_NUMSYM opt_ddb.h
FULL_BUF_TRACKING opt_global.h
GDB GDB
KDB opt_global.h KDB opt_global.h
KDB_TRACE opt_kdb.h KDB_TRACE opt_kdb.h

View File

@ -1062,27 +1062,15 @@ doopen(struct psm_softc *sc, int command_byte)
*/ */
if (sc->hw.model == MOUSE_MODEL_GENERIC) { if (sc->hw.model == MOUSE_MODEL_GENERIC) {
if (tap_enabled > 0) { 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, VLOG(2, (LOG_DEBUG,
"psm%d: enable tap and drag gestures\n", "psm%d: enable tap and drag gestures\n",
sc->unit)); sc->unit));
mouse_ext_command(sc->kbdc, 0x00); synaptics_set_mode(sc, synaptics_preferred_mode(sc));
set_mouse_sampling_rate(sc->kbdc, 20);
} else if (tap_enabled == 0) { } 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, VLOG(2, (LOG_DEBUG,
"psm%d: disable tap and drag gestures\n", "psm%d: disable tap and drag gestures\n",
sc->unit)); sc->unit));
mouse_ext_command(sc->kbdc, 0x04); synaptics_set_mode(sc, synaptics_preferred_mode(sc));
set_mouse_sampling_rate(sc->kbdc, 20);
} }
} }
@ -5364,6 +5352,24 @@ static int
synaptics_preferred_mode(struct psm_softc *sc) { synaptics_preferred_mode(struct psm_softc *sc) {
int mode_byte; 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; mode_byte = 0xc4;
/* request wmode where available */ /* 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 * Enable advanced gestures mode if supported and we are not entering
* passthrough mode. * passthrough or relative mode.
*/ */
if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) && 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); mouse_ext_command(sc->kbdc, 3);
set_mouse_sampling_rate(sc->kbdc, 0xc8); set_mouse_sampling_rate(sc->kbdc, 0xc8);
} }
@ -5698,6 +5704,9 @@ enable_synaptics(struct psm_softc *sc, enum probearg arg)
if (!synaptics_support) if (!synaptics_support)
return (FALSE); 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)); synaptics_set_mode(sc, synaptics_preferred_mode(sc));
if (trackpoint_support && synhw.capPassthrough) { if (trackpoint_support && synhw.capPassthrough) {

View File

@ -70,8 +70,6 @@
#include <sys/systm.h> #include <sys/systm.h>
#include "opt_global.h"
#define BHND_ERROR_LEVEL 0x00 #define BHND_ERROR_LEVEL 0x00
#define BHND_ERROR_MSG "ERROR" #define BHND_ERROR_MSG "ERROR"
#define BHND_WARN_LEVEL 0x10 #define BHND_WARN_LEVEL 0x10

View File

@ -57,7 +57,7 @@ static d_ioctl_t cpuctl_ioctl;
#define CPUCTL_VERSION 1 #define CPUCTL_VERSION 1
#ifdef DEBUG #ifdef CPUCTL_DEBUG
# define DPRINTF(format,...) printf(format, __VA_ARGS__); # define DPRINTF(format,...) printf(format, __VA_ARGS__);
#else #else
# define DPRINTF(...) # define DPRINTF(...)
@ -377,13 +377,24 @@ update_intel(int cpu, cpuctl_update_args_t *args, struct thread *td)
return (ret); 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 static int
update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td)
{ {
void *ptr = NULL; void *ptr;
uint32_t tmp[4];
int is_bound = 0;
int oldcpu;
int ret; int ret;
if (args->size == 0 || args->data == NULL) { 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__); DPRINTF("[cpuctl,%d]: firmware image too large", __LINE__);
return (EINVAL); 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); ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK);
if (ptr == NULL) {
DPRINTF("[cpuctl,%d]: cannot allocate %zd bytes of memory",
__LINE__, args->size);
return (ENOMEM);
}
if (copyin(args->data, ptr, args->size) != 0) { if (copyin(args->data, ptr, args->size) != 0) {
DPRINTF("[cpuctl,%d]: copyin %p->%p of %zd bytes failed", DPRINTF("[cpuctl,%d]: copyin %p->%p of %zd bytes failed",
__LINE__, args->data, ptr, args->size); __LINE__, args->data, ptr, args->size);
ret = EFAULT; ret = EFAULT;
goto fail; goto fail;
} }
oldcpu = td->td_oncpu; smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, ptr);
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);
ret = 0; ret = 0;
fail: fail:
if (ptr != NULL) free(ptr, M_CPUCTL);
contigfree(ptr, args->size, M_CPUCTL);
return (ret); return (ret);
} }

View File

@ -365,7 +365,6 @@ MODULE_DEPEND(em, netmap, 1, 1, 1);
#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
#define M_TSO_LEN 66
#define MAX_INTS_PER_SEC 8000 #define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) #define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256))

View File

@ -44,15 +44,4 @@ struct hyperv_guid {
int hyperv_guid2str(const struct hyperv_guid *, char *, size_t); 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_ */ #endif /* _HYPERV_H_ */

View File

@ -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_set(struct vmbus_channel *chan, int cpu);
void vmbus_chan_cpu_rr(struct vmbus_channel *chan); 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); void vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on);
struct vmbus_channel ** struct vmbus_channel **

View File

@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$");
/* hv_kvp defines */ /* hv_kvp defines */
#define BUFFERSIZE sizeof(struct hv_kvp_msg) #define BUFFERSIZE sizeof(struct hv_kvp_msg)
#define KVP_SUCCESS 0
#define KVP_ERROR 1
#define kvp_hdr hdr.kvp_hdr #define kvp_hdr hdr.kvp_hdr
#define KVP_FWVER_MAJOR 3 #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_IP_INFO:
case HV_KVP_OP_SET: case HV_KVP_OP_SET:
case HV_KVP_OP_DELETE: case HV_KVP_OP_DELETE:
return (KVP_SUCCESS); return (0);
case HV_KVP_OP_ENUMERATE: case HV_KVP_OP_ENUMERATE:
host_exchg_data = &hmsg->body.kvp_enum_data.data; 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; host_exchg_data->value_type = HV_REG_SZ;
if ((hkey_len < 0) || (hvalue_len < 0)) if ((hkey_len < 0) || (hvalue_len < 0))
return (HV_KVP_E_FAIL); return (EINVAL);
return (KVP_SUCCESS); return (0);
case HV_KVP_OP_GET: case HV_KVP_OP_GET:
host_exchg_data = &hmsg->body.kvp_get.data; 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; host_exchg_data->value_type = HV_REG_SZ;
if ((hkey_len < 0) || (hvalue_len < 0)) if ((hkey_len < 0) || (hvalue_len < 0))
return (HV_KVP_E_FAIL); return (EINVAL);
return (KVP_SUCCESS); return (0);
default: 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. * Send the response back to the host.
*/ */
static void 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; struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp;
hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *) hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *)
&sc->rcv_buf[sizeof(struct hv_vmbus_pipe_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->status = error;
hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION |
HV_ICMSGHDRFLAG_RESPONSE; HV_ICMSGHDRFLAG_RESPONSE;
@ -612,8 +607,10 @@ hv_kvp_process_request(void *context, int pending)
error = vmbus_ic_negomsg(&sc->util_sc, error = vmbus_ic_negomsg(&sc->util_sc,
kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER); kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER);
/* XXX handle vmbus_ic_negomsg failure. */ /* 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 * It is ok to not acquire the mutex before setting
* req_in_progress here because negotiation is the * 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)) { if (hv_kvp_req_in_progress(sc)) {
hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__); 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; 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; struct hv_kvp_msg *hv_kvp_dev_buf;
hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1; 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) if (!sc->register_done)
return (KVP_ERROR); return (EPERM);
sema_wait(&sc->dev_sema); sema_wait(&sc->dev_sema);
@ -789,7 +786,7 @@ hv_kvp_dev_daemon_write(struct cdev *dev, struct uio *uio, int ioflag __unused)
} }
else { else {
hv_kvp_log_info("%s, KVP Registration Failed\n", __func__); hv_kvp_log_info("%s, KVP Registration Failed\n", __func__);
return (KVP_ERROR); return (EINVAL);
} }
} else { } 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 *hmsg = sc->host_kvp_msg;
struct hv_kvp_msg *umsg = &sc->daemon_kvp_msg; struct hv_kvp_msg *umsg = &sc->daemon_kvp_msg;
hv_kvp_convert_usermsg_to_hostmsg(umsg, hmsg); error = hv_kvp_convert_usermsg_to_hostmsg(umsg, hmsg);
hv_kvp_respond_host(sc, KVP_SUCCESS); hv_kvp_respond_host(sc, umsg->hdr.error);
wakeup(sc); wakeup(sc);
sc->req_in_progress = false; 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; sc->daemon_busy = false;
@ -865,7 +867,7 @@ hv_kvp_attach(device_t dev)
child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_kvp_log", 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); TASK_INIT(&sc->task, 0, hv_kvp_process_request, sc);

View File

@ -144,19 +144,6 @@ enum hv_kvp_exchg_pool {
HV_KVP_POOL_COUNT /* Number of pools, must be last. */ 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_NONE 0x00
#define ADDR_FAMILY_IPV4 0x01 #define ADDR_FAMILY_IPV4 0x01
#define ADDR_FAMILY_IPV6 0x02 #define ADDR_FAMILY_IPV6 0x02

View File

@ -29,10 +29,17 @@
#ifndef _HV_UTILREG_H_ #ifndef _HV_UTILREG_H_
#define _HV_UTILREG_H_ #define _HV_UTILREG_H_
#define HV_S_OK 0x00000000 /*
#define HV_E_FAIL 0x80004005 * Some Hyper-V status codes.
#define HV_ERROR_NOT_SUPPORTED 0x80070032 */
#define HV_ERROR_MACHINE_LOCKED 0x800704F7 #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 * Common defines for Hyper-V ICs

View File

@ -926,28 +926,28 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
int int
vmbus_chan_recv_pkt(struct vmbus_channel *chan, 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, pkt_hlen;
int error, pktlen;
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) if (error)
return (error); return (error);
if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { if (__predict_false(pkt->cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) {
vmbus_chan_printf(chan, "invalid hlen %u\n", pkt.cph_hlen); vmbus_chan_printf(chan, "invalid hlen %u\n", pkt->cph_hlen);
/* XXX this channel is dead actually. */ /* XXX this channel is dead actually. */
return (EIO); 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", 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. */ /* XXX this channel is dead actually. */
return (EIO); return (EIO);
} }
pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen); pktlen = VMBUS_CHANPKT_GETLEN(pkt->cph_tlen);
if (*pktlen0 < pktlen) { if (*pktlen0 < pktlen) {
/* Return the size of this packet. */ /* Return the size of this packet. */
*pktlen0 = pktlen; *pktlen0 = pktlen;
@ -955,8 +955,12 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan,
} }
*pktlen0 = pktlen; *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")); KASSERT(!error, ("vmbus_rxbr_read failed"));
return (0); 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 ** struct vmbus_channel **
vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt) vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt)
{ {

View File

@ -37,7 +37,7 @@
__FBSDID("$FreeBSD$"); __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_reg.h for datasheet reference and notes.
* See ig4_var.h for locking semantics. * See ig4_var.h for locking semantics.
@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h> #include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h> #include <dev/pci/pcireg.h>
#include <dev/smbus/smbconf.h>
#include <dev/iicbus/iicbus.h> #include <dev/iicbus/iicbus.h>
#include <dev/iicbus/iiconf.h> #include <dev/iicbus/iiconf.h>
@ -236,18 +235,13 @@ data_read(ig4iic_softc_t *sc)
* the target address for when the controller later issues a START. * the target address for when the controller later issues a START.
*/ */
static void 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 tar;
uint32_t ctl; uint32_t ctl;
int use_10bit; int use_10bit;
use_10bit = sc->use_10bit; use_10bit = 0;
if (trans_op & SMB_TRANS_7BIT)
use_10bit = 0;
if (trans_op & SMB_TRANS_10BIT)
use_10bit = 1;
if (sc->slave_valid && sc->last_slave == slave && if (sc->slave_valid && sc->last_slave == slave &&
sc->use_10bit == use_10bit) { sc->use_10bit == use_10bit) {
return; return;
@ -290,209 +284,13 @@ set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op)
sc->last_slave = slave; 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 * IICBUS API FUNCTIONS
*/ */
static int static int
ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave) ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave)
{ {
/* XXX 10-bit address support? */ set_slave_addr(sc, slave >> 1);
set_slave_addr(sc, slave >> 1, 0);
return (0); return (0);
} }
@ -706,7 +504,7 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
/* TODO handle speed configuration? */ /* TODO handle speed configuration? */
if (oldaddr != NULL) if (oldaddr != NULL)
*oldaddr = sc->last_slave << 1; *oldaddr = sc->last_slave << 1;
set_slave_addr(sc, addr >> 1, 0); set_slave_addr(sc, addr >> 1);
if (addr == IIC_UNKNOWN) if (addr == IIC_UNKNOWN)
sc->slave_valid = false; 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() * Called from ig4iic_pci_attach/detach()
*/ */
int int
@ -836,7 +632,6 @@ ig4iic_start(void *xdev)
config_intrhook_disestablish(&sc->enum_hook); config_intrhook_disestablish(&sc->enum_hook);
/* Attach us to the smbus */
error = bus_generic_attach(sc->dev); error = bus_generic_attach(sc->dev);
if (error) { if (error) {
device_printf(sc->dev, device_printf(sc->dev,
@ -844,8 +639,6 @@ ig4iic_start(void *xdev)
} }
} }
int int
ig4iic_detach(ig4iic_softc_t *sc) ig4iic_detach(ig4iic_softc_t *sc)
{ {
@ -874,276 +667,6 @@ ig4iic_detach(ig4iic_softc_t *sc)
return (0); 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. * Interrupt Operation, see ig4_var.h for locking semantics.
*/ */

View File

@ -37,7 +37,7 @@
__FBSDID("$FreeBSD$"); __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_reg.h for datasheet reference and notes.
*/ */
@ -59,11 +59,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h> #include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h> #include <dev/pci/pcireg.h>
#include <dev/smbus/smbconf.h>
#include <dev/iicbus/iiconf.h> #include <dev/iicbus/iiconf.h>
#include "smbus_if.h"
#include <dev/ichiic/ig4_reg.h> #include <dev/ichiic/ig4_reg.h>
#include <dev/ichiic/ig4_var.h> #include <dev/ichiic/ig4_var.h>
@ -167,20 +164,6 @@ static device_method_t ig4iic_pci_methods[] = {
DEVMETHOD(device_attach, ig4iic_pci_attach), DEVMETHOD(device_attach, ig4iic_pci_attach),
DEVMETHOD(device_detach, ig4iic_pci_detach), 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_transfer, ig4iic_transfer),
DEVMETHOD(iicbus_reset, ig4iic_reset), DEVMETHOD(iicbus_reset, ig4iic_reset),
DEVMETHOD(iicbus_callback, iicbus_null_callback), 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, DRIVER_MODULE_ORDERED(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0,
SI_ORDER_ANY); SI_ORDER_ANY);
MODULE_DEPEND(ig4iic, pci, 1, 1, 1); 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_DEPEND(ig4iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
MODULE_VERSION(ig4iic, 1); MODULE_VERSION(ig4iic, 1);

View File

@ -47,14 +47,14 @@
* I am also using the linux driver code as a reference to help resolve any * 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. * issues that come. These will be specifically documented in the code.
* *
* Please see protocol notes in section 5.21. This controller is an I2C * This controller is an I2C master only and cannot act as a slave. The IO
* master only and cannot act as a slave. The IO voltage should be set by * voltage should be set by the BIOS. Standard (100Kb/s) and Fast (400Kb/s)
* the BIOS. Standard (100Kb/s) and Fast (400Kb/s) and fast mode plus * and fast mode plus (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT
* (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT supported. * supported.
*/ */
#ifndef _BUS_SMBUS_INTELGEN4_IG4_REG_H_ #ifndef _ICHIIC_IG4_REG_H_
#define _BUS_SMBUS_INTELGEN4_IG4_REG_H_ #define _ICHIIC_IG4_REG_H_
/* /*
* 22.2 MMIO registers can be accessed through BAR0 in PCI mode or through * 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_DECODE(v) ((v) & 0x3F)
#define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F) #define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F)
#endif #endif /* _ICHIIC_IG4_REG_H_ */

View File

@ -35,13 +35,12 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#ifndef _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ #ifndef _ICHIIC_IG4_VAR_H_
#define _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ #define _ICHIIC_IG4_VAR_H_
#include "bus_if.h" #include "bus_if.h"
#include "device_if.h" #include "device_if.h"
#include "pci_if.h" #include "pci_if.h"
#include "smbus_if.h"
#include "iicbus_if.h" #include "iicbus_if.h"
#define IG4_RBUFSIZE 128 #define IG4_RBUFSIZE 128
@ -75,12 +74,12 @@ struct ig4iic_softc {
/* /*
* Locking semantics: * 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 * with the controller acquire an exclusive lock on call_lock
* to prevent interleaving of calls to the interface and a lock on * to prevent interleaving of calls to the interface and a lock on
* io_lock right afterwards, to synchronize controller I/O activity. * 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 * 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 * wait_status and set_controller. It is safe to drop io_lock in those
* places, because the interrupt handler only accesses those registers: * 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 * Locking outside of those places is required to make the content
* of rpos/rnext predictable (e.g. whenever data_read is called and in * of rpos/rnext predictable (e.g. whenever data_read is called and in
* smb_transaction). * ig4iic_transfer).
*/ */
struct sx call_lock; struct sx call_lock;
struct mtx io_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_attach(ig4iic_softc_t *sc);
int ig4iic_detach(ig4iic_softc_t *sc); int ig4iic_detach(ig4iic_softc_t *sc);
/* SMBus methods */ /* iicbus 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;
extern iicbus_transfer_t ig4iic_transfer; extern iicbus_transfer_t ig4iic_transfer;
extern iicbus_reset_t ig4iic_reset; extern iicbus_reset_t ig4iic_reset;
#endif #endif /* _ICHIIC_IG4_VAR_H_ */

View File

@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$");
#define BUS_SPACE_MAXADDR_40BIT 0xFFFFFFFFFFULL #define BUS_SPACE_MAXADDR_40BIT 0xFFFFFFFFFFULL
#endif #endif
#define IOAT_REFLK (&ioat->submit_lock) #define IOAT_REFLK (&ioat->submit_lock)
#define IOAT_SHRINK_PERIOD (10 * hz)
static int ioat_probe(device_t device); static int ioat_probe(device_t device);
static int ioat_attach(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_active(struct ioat_softc *ioat);
static inline uint32_t ioat_get_ring_space(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, static void ioat_free_ring(struct ioat_softc *, uint32_t size,
struct ioat_descriptor **); 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);
static int ioat_reserve_space(struct ioat_softc *, uint32_t, int mflags); 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); 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_halted_debug(struct ioat_softc *, uint32_t);
static void ioat_poll_timer_callback(void *arg); 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 dump_descriptor(void *hw_desc);
static void ioat_submit_single(struct ioat_softc *ioat); static void ioat_submit_single(struct ioat_softc *ioat);
static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg, 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, 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."); 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 * OS <-> Driver interface structures
*/ */
@ -336,7 +330,6 @@ ioat_detach(device_t device)
ioat_teardown_intr(ioat); ioat_teardown_intr(ioat);
callout_drain(&ioat->poll_timer); callout_drain(&ioat->poll_timer);
callout_drain(&ioat->shrink_timer);
pci_disable_busmaster(device); 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->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); return (0);
} }
@ -388,8 +386,8 @@ ioat_start_channel(struct ioat_softc *ioat)
/* Submit 'NULL' operation manually to avoid quiescing flag */ /* Submit 'NULL' operation manually to avoid quiescing flag */
desc = ioat_get_ring_entry(ioat, ioat->head); desc = ioat_get_ring_entry(ioat, ioat->head);
hw_desc = &ioat_get_descriptor(ioat, ioat->head)->dma;
dmadesc = &desc->bus_dmadesc; dmadesc = &desc->bus_dmadesc;
hw_desc = desc->u.dma;
dmadesc->callback_fn = NULL; dmadesc->callback_fn = NULL;
dmadesc->callback_arg = NULL; dmadesc->callback_arg = NULL;
@ -426,9 +424,10 @@ static int
ioat3_attach(device_t device) ioat3_attach(device_t device)
{ {
struct ioat_softc *ioat; struct ioat_softc *ioat;
struct ioat_descriptor **ring; struct ioat_descriptor *ring;
struct ioat_descriptor *next;
struct ioat_dma_hw_descriptor *dma_hw_desc; struct ioat_dma_hw_descriptor *dma_hw_desc;
void *hw_desc;
size_t ringsz;
int i, num_descriptors; int i, num_descriptors;
int error; int error;
uint8_t xfercap; 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->submit_lock, "ioat_submit", NULL, MTX_DEF);
mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF); mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF);
callout_init(&ioat->poll_timer, 1); callout_init(&ioat->poll_timer, 1);
callout_init(&ioat->shrink_timer, 1);
TASK_INIT(&ioat->reset_task, 0, ioat_reset_hw_task, ioat); TASK_INIT(&ioat->reset_task, 0, ioat_reset_hw_task, ioat);
/* Establish lock order for Witness */ /* Establish lock order for Witness */
@ -462,7 +460,6 @@ ioat3_attach(device_t device)
mtx_unlock(&ioat->cleanup_lock); mtx_unlock(&ioat->cleanup_lock);
mtx_unlock(&ioat->submit_lock); mtx_unlock(&ioat->submit_lock);
ioat->is_resize_pending = FALSE;
ioat->is_submitter_processing = FALSE; ioat->is_submitter_processing = FALSE;
ioat->is_completion_pending = FALSE; ioat->is_completion_pending = FALSE;
ioat->is_reset_pending = FALSE; ioat->is_reset_pending = FALSE;
@ -484,37 +481,42 @@ ioat3_attach(device_t device)
if (error != 0) if (error != 0)
return (error); return (error);
ioat->ring_size_order = IOAT_MIN_ORDER; ioat->ring_size_order = g_ioat_ring_order;
num_descriptors = 1 << ioat->ring_size_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, error = bus_dma_tag_create(bus_get_dma_tag(ioat->device),
BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2 * 1024 * 1024, 0x0, BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR,
sizeof(struct ioat_dma_hw_descriptor), 1, NULL, NULL, ringsz, 1, ringsz, 0, NULL, NULL, &ioat->hw_desc_tag);
sizeof(struct ioat_dma_hw_descriptor), 0, NULL, NULL, if (error != 0)
&ioat->hw_desc_tag); 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, ioat->ring = malloc(num_descriptors * sizeof(*ring), M_IOAT,
M_ZERO | M_WAITOK); M_ZERO | M_WAITOK);
ring = ioat->ring; ring = ioat->ring;
for (i = 0; i < num_descriptors; i++) { for (i = 0; i < num_descriptors; i++) {
ring[i] = ioat_alloc_ring_entry(ioat, M_WAITOK); memset(&ring[i].bus_dmadesc, 0, sizeof(ring[i].bus_dmadesc));
if (ring[i] == NULL) ring[i].id = i;
return (ENOMEM);
ring[i]->id = i;
} }
for (i = 0; i < num_descriptors - 1; i++) { for (i = 0; i < num_descriptors; i++) {
next = ring[i + 1]; dma_hw_desc = &ioat->hw_desc_ring[i].dma;
dma_hw_desc = ring[i]->u.dma; dma_hw_desc->next = RING_PHYS_ADDR(ioat, i + 1);
dma_hw_desc->next = next->hw_desc_bus_addr;
} }
ring[i]->u.dma->next = ring[0]->hw_desc_bus_addr;
ioat->head = ioat->hw_head = 0; ioat->head = ioat->hw_head = 0;
ioat->tail = 0; ioat->tail = 0;
ioat->last_seen = 0; ioat->last_seen = 0;
@ -680,6 +682,12 @@ ioat_process_events(struct ioat_softc *ioat)
comp_update = *ioat->comp_update; comp_update = *ioat->comp_update;
status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK; 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 (status == ioat->last_seen) {
/* /*
* If we landed in process_events and nothing has been * 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", CTR4(KTR_IOAT, "%s channel=%u hw_status=0x%lx last_seen=0x%lx",
__func__, ioat->chan_idx, comp_update, ioat->last_seen); __func__, ioat->chan_idx, comp_update, ioat->last_seen);
desc = ioat_get_ring_entry(ioat, ioat->tail - 1); while (RING_PHYS_ADDR(ioat, ioat->tail - 1) != status) {
while (desc->hw_desc_bus_addr != status) {
desc = ioat_get_ring_entry(ioat, ioat->tail); desc = ioat_get_ring_entry(ioat, ioat->tail);
dmadesc = &desc->bus_dmadesc; dmadesc = &desc->bus_dmadesc;
CTR5(KTR_IOAT, "channel=%u completing desc idx %u (%p) ok cb %p(%p)", 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)); ioat->chan_idx, ioat->head, ioat->tail, ioat_get_active(ioat));
if (completed != 0) { 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; ioat->stats.descriptors_processed += completed;
} }
@ -725,8 +732,6 @@ ioat_process_events(struct ioat_softc *ioat)
pending = (ioat_get_active(ioat) != 0); pending = (ioat_get_active(ioat) != 0);
if (!pending && ioat->is_completion_pending) { if (!pending && ioat->is_completion_pending) {
ioat->is_completion_pending = FALSE; ioat->is_completion_pending = FALSE;
callout_reset(&ioat->shrink_timer, IOAT_SHRINK_PERIOD,
ioat_shrink_timer_callback, ioat);
callout_stop(&ioat->poll_timer); callout_stop(&ioat->poll_timer);
} }
mtx_unlock(&ioat->submit_lock); mtx_unlock(&ioat->submit_lock);
@ -781,8 +786,6 @@ ioat_process_events(struct ioat_softc *ioat)
if (ioat->is_completion_pending) { if (ioat->is_completion_pending) {
ioat->is_completion_pending = FALSE; ioat->is_completion_pending = FALSE;
callout_reset(&ioat->shrink_timer, IOAT_SHRINK_PERIOD,
ioat_shrink_timer_callback, ioat);
callout_stop(&ioat->poll_timer); callout_stop(&ioat->poll_timer);
} }
@ -964,7 +967,6 @@ ioat_release(bus_dmaengine_t dmaengine)
ioat->is_completion_pending = TRUE; ioat->is_completion_pending = TRUE;
callout_reset(&ioat->poll_timer, 1, ioat_poll_timer_callback, callout_reset(&ioat->poll_timer, 1, ioat_poll_timer_callback,
ioat); ioat);
callout_stop(&ioat->shrink_timer);
} }
mtx_unlock(&ioat->submit_lock); mtx_unlock(&ioat->submit_lock);
} }
@ -998,7 +1000,7 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op,
return (NULL); return (NULL);
desc = ioat_get_ring_entry(ioat, ioat->head); 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_raw = 0;
hw_desc->u.control_generic.op = op; 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) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.dma; hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma;
hw_desc->u.control.null = 1; hw_desc->u.control.null = 1;
ioat_submit_single(ioat); ioat_submit_single(ioat);
return (&desc->bus_dmadesc); return (&desc->bus_dmadesc);
@ -1062,7 +1064,7 @@ ioat_copy(bus_dmaengine_t dmaengine, bus_addr_t dst,
if (desc == NULL) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.dma; hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma;
if (g_ioat_debug_level >= 3) if (g_ioat_debug_level >= 3)
dump_descriptor(hw_desc); dump_descriptor(hw_desc);
@ -1100,7 +1102,7 @@ ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_addr_t dst1,
if (desc == NULL) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.dma; hw_desc = &ioat_get_descriptor(ioat, desc->id)->dma;
if (src2 != src1 + PAGE_SIZE) { if (src2 != src1 + PAGE_SIZE) {
hw_desc->u.control.src_page_break = 1; hw_desc->u.control.src_page_break = 1;
hw_desc->next_src_addr = src2; 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) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.crc32; hw_desc = &ioat_get_descriptor(ioat, desc->id)->crc32;
if ((flags & DMA_CRC_INLINE) == 0) if ((flags & DMA_CRC_INLINE) == 0)
hw_desc->crc_address = crcptr; 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) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.crc32; hw_desc = &ioat_get_descriptor(ioat, desc->id)->crc32;
if ((flags & DMA_CRC_INLINE) == 0) if ((flags & DMA_CRC_INLINE) == 0)
hw_desc->crc_address = crcptr; 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) if (desc == NULL)
return (NULL); return (NULL);
hw_desc = desc->u.fill; hw_desc = &ioat_get_descriptor(ioat, desc->id)->fill;
if (g_ioat_debug_level >= 3) if (g_ioat_debug_level >= 3)
dump_descriptor(hw_desc); 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); 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 * Reserves space in this IOAT descriptor ring by ensuring enough slots remain
* for 'num_descs'. * for 'num_descs'.
@ -1402,8 +1350,6 @@ ioat_free_ring_entry(struct ioat_softc *ioat, struct ioat_descriptor *desc)
static int static int
ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags)
{ {
struct ioat_descriptor **new_ring;
uint32_t order;
boolean_t dug; boolean_t dug;
int error; int error;
@ -1411,7 +1357,7 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags)
error = 0; error = 0;
dug = FALSE; 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; error = EINVAL;
goto out; 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__, CTR3(KTR_IOAT, "%s channel=%u starved (%u)", __func__,
ioat->chan_idx, num_descs); ioat->chan_idx, num_descs);
if (!dug && !ioat->is_submitter_processing && if (!dug && !ioat->is_submitter_processing) {
(1 << ioat->ring_size_order) > num_descs) {
ioat->is_submitter_processing = TRUE; ioat->is_submitter_processing = TRUE;
mtx_unlock(&ioat->submit_lock); mtx_unlock(&ioat->submit_lock);
@ -1446,46 +1391,15 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags)
continue; continue;
} }
order = ioat->ring_size_order; if ((mflags & M_WAITOK) == 0) {
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;
}
error = EAGAIN; error = EAGAIN;
break; break;
} }
CTR2(KTR_IOAT, "%s channel=%u blocking on completions",
ioat->is_resize_pending = TRUE; __func__, ioat->chan_idx);
for (;;) { msleep(&ioat->tail, &ioat->submit_lock, 0,
mtx_unlock(&ioat->submit_lock); "ioat_full", 0);
continue;
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;
} }
out: out:
@ -1495,49 +1409,11 @@ ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags)
return (error); 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 static void
ioat_free_ring(struct ioat_softc *ioat, uint32_t size, 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); free(ring, M_IOAT);
} }
@ -1545,188 +1421,20 @@ static struct ioat_descriptor *
ioat_get_ring_entry(struct ioat_softc *ioat, uint32_t index) 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 static union ioat_hw_descriptor *
ring_grow(struct ioat_softc *ioat, uint32_t oldorder, ioat_get_descriptor(struct ioat_softc *ioat, uint32_t index)
struct ioat_descriptor **newring)
{ {
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); return (&ioat->hw_desc_ring[index % (1 << ioat->ring_size_order)]);
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);
} }
static void static void
ioat_halted_debug(struct ioat_softc *ioat, uint32_t chanerr) 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_log_message(0, "Channel halted (%b)\n", (int)chanerr,
IOAT_CHANERR_STR); IOAT_CHANERR_STR);
@ -1735,11 +1443,11 @@ ioat_halted_debug(struct ioat_softc *ioat, uint32_t chanerr)
mtx_assert(&ioat->cleanup_lock, MA_OWNED); mtx_assert(&ioat->cleanup_lock, MA_OWNED);
desc = ioat_get_ring_entry(ioat, ioat->tail + 0); desc = ioat_get_descriptor(ioat, ioat->tail + 0);
dump_descriptor(desc->u.raw); dump_descriptor(desc);
desc = ioat_get_ring_entry(ioat, ioat->tail + 1); desc = ioat_get_descriptor(ioat, ioat->tail + 1);
dump_descriptor(desc->u.raw); dump_descriptor(desc);
} }
static void static void
@ -1753,55 +1461,6 @@ ioat_poll_timer_callback(void *arg)
ioat_process_events(ioat); 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 * Support Functions
*/ */
@ -1946,7 +1605,7 @@ ioat_reset_hw(struct ioat_softc *ioat)
ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN); ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN);
ioat_write_chancmp(ioat, ioat->comp_update_bus_addr); 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; error = 0;
CTR2(KTR_IOAT, "%s channel=%u configured channel", __func__, CTR2(KTR_IOAT, "%s channel=%u configured channel", __func__,
ioat->chan_idx); ioat->chan_idx);
@ -2128,8 +1787,6 @@ ioat_setup_sysctl(device_t device)
SYSCTL_ADD_UQUAD(ctx, state, OID_AUTO, "last_completion", CTLFLAG_RD, SYSCTL_ADD_UQUAD(ctx, state, OID_AUTO, "last_completion", CTLFLAG_RD,
ioat->comp_update, "HW addr of last completion"); 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", SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_submitter_processing",
CTLFLAG_RD, &ioat->is_submitter_processing, 0, CTLFLAG_RD, &ioat->is_submitter_processing, 0,
"submitter processing"); "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_lock: %p\n", sc->poll_timer.c_lock);
db_printf(" c_flags: 0x%x\n", (unsigned)sc->poll_timer.c_flags); 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(" quiescing: %d\n", (int)sc->quiescing);
db_printf(" destroying: %d\n", (int)sc->destroying); 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", db_printf(" is_submitter_processing: %d\n",
(int)sc->is_submitter_processing); (int)sc->is_submitter_processing);
db_printf(" is_completion_pending: %d\n", (int)sc->is_completion_pending); 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(" ring_size_order: %u\n", sc->ring_size_order);
db_printf(" last_seen: 0x%lx\n", sc->last_seen); db_printf(" last_seen: 0x%lx\n", sc->last_seen);
db_printf(" ring: %p\n", sc->ring); 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 % db_printf(" ring[%u] (tail):\n", sc->tail %
(1 << sc->ring_size_order)); (1 << sc->ring_size_order));
db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->tail)->id); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->tail)->id);
db_printf(" addr: 0x%lx\n", 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", 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) % db_printf(" ring[%u] (head - 1):\n", (sc->head - 1) %
(1 << sc->ring_size_order)); (1 << sc->ring_size_order));
db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head - 1)->id); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head - 1)->id);
db_printf(" addr: 0x%lx\n", 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", 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) % db_printf(" ring[%u] (head):\n", (sc->head) %
(1 << sc->ring_size_order)); (1 << sc->ring_size_order));
db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head)->id); db_printf(" id: %u\n", ioat_get_ring_entry(sc, sc->head)->id);
db_printf(" addr: 0x%lx\n", 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", 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++) for (idx = 0; idx < (1 << sc->ring_size_order); idx++)
if ((*sc->comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK) 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(" ring[%u] == hardware tail\n", idx);
db_printf(" cleanup_lock: "); db_printf(" cleanup_lock: ");

View File

@ -413,19 +413,7 @@ struct bus_dmadesc {
struct ioat_descriptor { struct ioat_descriptor {
struct bus_dmadesc bus_dmadesc; 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; uint32_t id;
bus_addr_t hw_desc_bus_addr;
}; };
/* Unused by this driver at this time. */ /* Unused by this driver at this time. */
@ -487,7 +475,6 @@ struct ioat_softc {
boolean_t quiescing; boolean_t quiescing;
boolean_t destroying; boolean_t destroying;
boolean_t is_submitter_processing; boolean_t is_submitter_processing;
boolean_t is_resize_pending;
boolean_t is_completion_pending; /* submit_lock */ boolean_t is_completion_pending; /* submit_lock */
boolean_t is_reset_pending; boolean_t is_reset_pending;
boolean_t is_channel_running; boolean_t is_channel_running;
@ -501,7 +488,22 @@ struct ioat_softc {
uint32_t ring_size_order; uint32_t ring_size_order;
bus_addr_t last_seen; 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; struct mtx cleanup_lock;
volatile uint32_t refcnt; volatile uint32_t refcnt;

View File

@ -5071,18 +5071,6 @@ iwm_nic_error(struct iwm_softc *sc)
} }
#endif #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); #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) { while (sc->rxq.cur != hw) {
struct iwm_rx_ring *ring = &sc->rxq; 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_rx_packet *pkt;
struct iwm_cmd_response *cresp; struct iwm_cmd_response *cresp;
int qid, idx, code; int qid, idx, code;
bus_dmamap_sync(sc->rxq.data_dmat, data->map, bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTREAD); BUS_DMASYNC_POSTREAD);
pkt = mtod(data->m, struct iwm_rx_packet *); 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); code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
IWM_DPRINTF(sc, IWM_DEBUG_INTR, IWM_DPRINTF(sc, IWM_DEBUG_INTR,
"rx packet qid=%d idx=%d type=%x %d %d\n", "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. * 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 */ /* XXX look at mac_id to determine interface ID */
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
SYNC_RESP_STRUCT(resp, pkt); resp = (void *)pkt->data;
missed = le32toh(resp->consec_missed_beacons); missed = le32toh(resp->consec_missed_beacons);
IWM_DPRINTF(sc, IWM_DEBUG_BEACON | IWM_DEBUG_STATE, 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; struct iwm_mvm_alive_resp_v3 *resp3;
if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) { 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 sc->sc_uc.uc_error_event_table
= le32toh(resp1->error_event_table_ptr); = le32toh(resp1->error_event_table_ptr);
sc->sc_uc.uc_log_event_table 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)) { 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 sc->sc_uc.uc_error_event_table
= le32toh(resp2->error_event_table_ptr); = le32toh(resp2->error_event_table_ptr);
sc->sc_uc.uc_log_event_table 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)) { 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 sc->sc_uc.uc_error_event_table
= le32toh(resp3->error_event_table_ptr); = le32toh(resp3->error_event_table_ptr);
sc->sc_uc.uc_log_event_table 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: { case IWM_CALIB_RES_NOTIF_PHY_DB: {
struct iwm_calib_res_notif_phy_db *phy_db_notif; 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); iwm_phy_db_set_section(sc, phy_db_notif);
@ -5248,7 +5236,7 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_STATISTICS_NOTIFICATION: { case IWM_STATISTICS_NOTIFICATION: {
struct iwm_notif_statistics *stats; struct iwm_notif_statistics *stats;
SYNC_RESP_STRUCT(stats, pkt); stats = (void *)pkt->data;
memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats)); memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
sc->sc_noise = iwm_get_noise(sc, &stats->rx.general); sc->sc_noise = iwm_get_noise(sc, &stats->rx.general);
break; } break; }
@ -5256,8 +5244,6 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_NVM_ACCESS_CMD: case IWM_NVM_ACCESS_CMD:
case IWM_MCC_UPDATE_CMD: case IWM_MCC_UPDATE_CMD:
if (sc->sc_wantresp == ((qid << 16) | idx)) { if (sc->sc_wantresp == ((qid << 16) | idx)) {
bus_dmamap_sync(sc->rxq.data_dmat, data->map,
BUS_DMASYNC_POSTREAD);
memcpy(sc->sc_cmd_resp, memcpy(sc->sc_cmd_resp,
pkt, sizeof(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: { case IWM_MCC_CHUB_UPDATE_CMD: {
struct iwm_mcc_chub_notif *notif; 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[0] = (notif->mcc & 0xff00) >> 8;
sc->sc_fw_mcc[1] = notif->mcc & 0xff; 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_LQ_CMD:
case IWM_BT_CONFIG: case IWM_BT_CONFIG:
case IWM_REPLY_THERMAL_MNG_BACKOFF: case IWM_REPLY_THERMAL_MNG_BACKOFF:
SYNC_RESP_STRUCT(cresp, pkt); cresp = (void *)pkt->data;
if (sc->sc_wantresp == ((qid << 16) | idx)) { if (sc->sc_wantresp == ((qid << 16) | idx)) {
memcpy(sc->sc_cmd_resp, memcpy(sc->sc_cmd_resp,
pkt, sizeof(*pkt)+sizeof(*cresp)); pkt, sizeof(*pkt)+sizeof(*cresp));
@ -5316,20 +5302,20 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_SCAN_OFFLOAD_COMPLETE: { case IWM_SCAN_OFFLOAD_COMPLETE: {
struct iwm_periodic_scan_complete *notif; struct iwm_periodic_scan_complete *notif;
SYNC_RESP_STRUCT(notif, pkt); notif = (void *)pkt->data;
break; break;
} }
case IWM_SCAN_ITERATION_COMPLETE: { case IWM_SCAN_ITERATION_COMPLETE: {
struct iwm_lmac_scan_complete_notif *notif; 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); ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
break; break;
} }
case IWM_SCAN_COMPLETE_UMAC: { case IWM_SCAN_COMPLETE_UMAC: {
struct iwm_umac_scan_complete *notif; struct iwm_umac_scan_complete *notif;
SYNC_RESP_STRUCT(notif, pkt); notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"UMAC scan complete, status=0x%x\n", "UMAC scan complete, status=0x%x\n",
@ -5342,7 +5328,7 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_SCAN_ITERATION_COMPLETE_UMAC: { case IWM_SCAN_ITERATION_COMPLETE_UMAC: {
struct iwm_umac_scan_iter_complete_notif *notif; 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 " IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan iteration "
"complete, status=0x%x, %d channels scanned\n", "complete, status=0x%x, %d channels scanned\n",
@ -5353,7 +5339,7 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_REPLY_ERROR: { case IWM_REPLY_ERROR: {
struct iwm_error_resp *resp; struct iwm_error_resp *resp;
SYNC_RESP_STRUCT(resp, pkt); resp = (void *)pkt->data;
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"firmware error 0x%x, cmd 0x%x\n", "firmware error 0x%x, cmd 0x%x\n",
@ -5364,7 +5350,7 @@ iwm_notif_intr(struct iwm_softc *sc)
case IWM_TIME_EVENT_NOTIFICATION: { case IWM_TIME_EVENT_NOTIFICATION: {
struct iwm_time_event_notif *notif; struct iwm_time_event_notif *notif;
SYNC_RESP_STRUCT(notif, pkt); notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_INTR, IWM_DPRINTF(sc, IWM_DEBUG_INTR,
"TE notif status = 0x%x action = 0x%x\n", "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: { case IWM_SCD_QUEUE_CFG: {
struct iwm_scd_txq_cfg_rsp *rsp; struct iwm_scd_txq_cfg_rsp *rsp;
SYNC_RESP_STRUCT(rsp, pkt); rsp = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_CMD, IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"queue cfg token=0x%x sta_id=%d " "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_SHPREAMBLE /* short preamble supported */
// IEEE80211_C_BGSCAN /* capable of bg scanning */ // 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++) { for (i = 0; i < nitems(sc->sc_phyctxt); i++) {
sc->sc_phyctxt[i].id = i; sc->sc_phyctxt[i].id = i;
sc->sc_phyctxt[i].color = 0; sc->sc_phyctxt[i].color = 0;

View File

@ -1376,6 +1376,7 @@ mpr_get_tunables(struct mpr_softc *sc)
sc->max_io_pages = MPR_MAXIO_PAGES; sc->max_io_pages = MPR_MAXIO_PAGES;
sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
sc->use_phynum = 1;
/* /*
* Grab the global variables. * 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.max_io_pages", &sc->max_io_pages);
TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); 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.spinup_wait_time", &sc->spinup_wait_time);
TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum);
/* Grab the unit-instance variables */ /* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", 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", snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time",
device_get_unit(sc->mpr_dev)); device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); 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 static void
@ -1510,6 +1516,10 @@ mpr_setup_sysctl(struct mpr_softc *sc)
OID_AUTO, "spinup_wait_time", CTLFLAG_RD, OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
&sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
"spinup after SATA ID error"); "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 int

View File

@ -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) { if (id == MPR_MAP_BAD_ID) {
printf("failure at %s:%d/%s()! Could not get ID for device " if ((sc->use_phynum == 0)
"with handle 0x%04x\n", __FILE__, __LINE__, __func__, || ((id = config_page.PhyNum) > sassc->maxtargets)) {
handle); mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! "
error = ENXIO; "Could not get ID for device with handle 0x%04x\n",
goto out; __FILE__, __LINE__, __func__, handle);
error = ENXIO;
goto out;
}
} }
if (mprsas_check_id(sassc, id) != 0) { if (mprsas_check_id(sassc, id) != 0) {
@ -772,9 +783,16 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
goto out; 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", mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address); sas_address);
targ = &sassc->targets[id];
targ->devinfo = device_info; targ->devinfo = device_info;
targ->devname = le32toh(config_page.DeviceName.High); targ->devname = le32toh(config_page.DeviceName.High);
targ->devname = (targ->devname << 32) | targ->devname = (targ->devname << 32) |

View File

@ -271,6 +271,7 @@ struct mpr_softc {
uint16_t chain_seg_size; uint16_t chain_seg_size;
u_int enable_ssu; u_int enable_ssu;
int spinup_wait_time; int spinup_wait_time;
int use_phynum;
uint64_t chain_alloc_fail; uint64_t chain_alloc_fail;
struct sysctl_ctx_list sysctl_ctx; struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree; struct sysctl_oid *sysctl_tree;

View File

@ -1353,6 +1353,7 @@ mps_get_tunables(struct mps_softc *sc)
sc->max_io_pages = MPS_MAXIO_PAGES; sc->max_io_pages = MPS_MAXIO_PAGES;
sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD; sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
sc->use_phynum = 1;
/* /*
* Grab the global variables. * 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.max_io_pages", &sc->max_io_pages);
TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu); 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.spinup_wait_time", &sc->spinup_wait_time);
TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum);
/* Grab the unit-instance variables */ /* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level", 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", snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time",
device_get_unit(sc->mps_dev)); device_get_unit(sc->mps_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); 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 static void
@ -1495,6 +1501,10 @@ mps_setup_sysctl(struct mps_softc *sc)
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
mps_mapping_encl_dump, "A", "Enclosure Table Dump"); 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 int

View File

@ -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, callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0,
mpssas_scsiio_timeout, cm, 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); TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link);
ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); 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) { if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) {
TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
if (cm->cm_reply != NULL) if (cm->cm_reply != NULL)

View File

@ -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) { if (id == MPS_MAP_BAD_ID) {
printf("failure at %s:%d/%s()! Could not get ID for device " if ((sc->use_phynum == 0)
"with handle 0x%04x\n", __FILE__, __LINE__, __func__, || ((id = config_page.PhyNum) > sassc->maxtargets)) {
handle); mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! "
error = ENXIO; "Could not get ID for device with handle 0x%04x\n",
goto out; __FILE__, __LINE__, __func__, handle);
error = ENXIO;
goto out;
}
} }
if (mpssas_check_id(sassc, id) != 0) { if (mpssas_check_id(sassc, id) != 0) {
@ -684,9 +695,16 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
goto out; 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", mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address); sas_address);
targ = &sassc->targets[id];
targ->devinfo = device_info; targ->devinfo = device_info;
targ->devname = le32toh(config_page.DeviceName.High); targ->devname = le32toh(config_page.DeviceName.High);
targ->devname = (targ->devname << 32) | targ->devname = (targ->devname << 32) |

View File

@ -285,6 +285,7 @@ struct mps_softc {
int chain_free_lowwater; int chain_free_lowwater;
u_int enable_ssu; u_int enable_ssu;
int spinup_wait_time; int spinup_wait_time;
int use_phynum;
uint64_t chain_alloc_fail; uint64_t chain_alloc_fail;
struct sysctl_ctx_list sysctl_ctx; struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree; struct sysctl_oid *sysctl_tree;

View File

@ -28,7 +28,7 @@
__FBSDID("$FreeBSD$"); __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). * This supports both eSDHC (earlier SoCs) and uSDHC (more recent SoCs).
*/ */
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/callout.h> #include <sys/callout.h>
#include <sys/endian.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/libkern.h> #include <sys/libkern.h>
#include <sys/lock.h> #include <sys/lock.h>
@ -52,9 +53,11 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h> #include <machine/bus.h>
#include <machine/resource.h> #include <machine/resource.h>
#ifdef __arm__
#include <machine/intr.h> #include <machine/intr.h>
#include <arm/freescale/imx/imx_ccmvar.h> #include <arm/freescale/imx/imx_ccmvar.h>
#endif
#include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/ofw_bus_subr.h>
@ -66,7 +69,7 @@ __FBSDID("$FreeBSD$");
#include <dev/sdhci/sdhci.h> #include <dev/sdhci/sdhci.h>
#include "sdhci_if.h" #include "sdhci_if.h"
struct imx_sdhci_softc { struct fsl_sdhci_softc {
device_t dev; device_t dev;
struct resource * mem_res; struct resource * mem_res;
struct resource * irq_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 R1BFIX_AC12 2 /* Wait for busy after auto command 12. */
#define HWTYPE_NONE 0 /* Hardware not recognized/supported. */ #define HWTYPE_NONE 0 /* Hardware not recognized/supported. */
#define HWTYPE_ESDHC 1 /* imx5x and earlier. */ #define HWTYPE_ESDHC 1 /* fsl5x and earlier. */
#define HWTYPE_USDHC 2 /* imx6. */ #define HWTYPE_USDHC 2 /* fsl6. */
/* /*
* Freescale-specific registers, or in some cases the layout of bits within the * 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_PROT_CDSS (1 << 7)
#define SDHC_SYS_CTRL 0x2c #define SDHC_SYS_CTRL 0x2c
#define SDHC_INT_STATUS 0x30
/* /*
* The clock enable bits exist in different registers for ESDHC vs USDHC, but * 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,imx6sl-usdhc", HWTYPE_USDHC},
{"fsl,imx53-esdhc", HWTYPE_ESDHC}, {"fsl,imx53-esdhc", HWTYPE_ESDHC},
{"fsl,imx51-esdhc", HWTYPE_ESDHC}, {"fsl,imx51-esdhc", HWTYPE_ESDHC},
{"fsl,esdhc", HWTYPE_ESDHC},
{NULL, HWTYPE_NONE}, {NULL, HWTYPE_NONE},
}; };
static uint16_t imx_sdhc_get_clock(struct imx_sdhci_softc *sc); static uint16_t fsl_sdhc_get_clock(struct fsl_sdhci_softc *sc);
static void imx_sdhc_set_clock(struct imx_sdhci_softc *sc, uint16_t val); static void fsl_sdhc_set_clock(struct fsl_sdhci_softc *sc, uint16_t val);
static void imx_sdhci_r1bfix_func(void *arg); static void fsl_sdhci_r1bfix_func(void *arg);
static inline uint32_t 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)); return (bus_read_4(sc->mem_res, off));
} }
static inline void 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); bus_write_4(sc->mem_res, off, val);
} }
static uint8_t 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; 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 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; uint32_t val32;
if (sc->hwtype == HWTYPE_USDHC) { 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. * hardware type, complex enough to have their own function.
*/ */
if (off == SDHCI_CLOCK_CONTROL) { 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); return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff);
} }
static uint32_t 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; uint32_t val32, wrk32;
val32 = RD4(sc, off); 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. * command with an R1B response, mix it into the hardware status.
*/ */
if (off == SDHCI_INT_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 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) 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); bus_read_multi_4(sc->mem_res, off, data, count);
} }
static void 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; 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) { if (off == SDHCI_POWER_CONTROL) {
return; 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 = RD4(sc, off & ~3);
val32 &= ~(0xff << (off & 3) * 8); 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 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; 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. * that can handle the ESDHC versus USDHC differences.
*/ */
if (off == SDHCI_CLOCK_CONTROL) { if (off == SDHCI_CLOCK_CONTROL) {
imx_sdhc_set_clock(sc, val); fsl_sdhc_set_clock(sc, val);
return; 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. * 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 * 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 * 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 (off == SDHCI_COMMAND_FLAGS) {
if (val & SDHCI_CMD_DATA) { 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 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. */ /* Clear synthesized interrupts, then pass the value to the hardware. */
if (off == SDHCI_INT_STATUS) { 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 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) 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); bus_write_multi_4(sc->mem_res, off, data, count);
} }
static uint16_t static uint16_t
imx_sdhc_get_clock(struct imx_sdhci_softc *sc) fsl_sdhc_get_clock(struct fsl_sdhci_softc *sc)
{ {
uint16_t val; uint16_t val;
@ -531,17 +539,20 @@ imx_sdhc_get_clock(struct imx_sdhci_softc *sc)
val |= SDHCI_CLOCK_INT_STABLE; val |= SDHCI_CLOCK_INT_STABLE;
/* /*
* On ESDHC hardware the card bus clock enable is in the usual sdhci * On i.MX ESDHC hardware the card bus clock enable is in the usual
* register but it's a different bit, so transcribe it (note the * sdhci register but it's a different bit, so transcribe it (note the
* difference between standard SDHCI_ and Freescale SDHC_ prefixes * difference between standard SDHCI_ and Freescale SDHC_ prefixes
* here). On USDHC hardware there is a force-on bit, but no force-off * here). On USDHC and QorIQ ESDHC hardware there is a force-on bit, but
* for the card bus clock (the hardware runs the clock when transfers * no force-off for the card bus clock (the hardware runs the clock when
* are active no matter what), so we always say the clock is on. * 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 * XXX Maybe we should say it's in whatever state the sdhci driver last
* set it to. * set it to.
*/ */
if (sc->hwtype == HWTYPE_ESDHC) { if (sc->hwtype == HWTYPE_ESDHC) {
#ifdef __arm__
if (RD4(sc, SDHC_SYS_CTRL) & SDHC_CLK_SDCLKEN) if (RD4(sc, SDHC_SYS_CTRL) & SDHC_CLK_SDCLKEN)
#endif
val |= SDHCI_CLOCK_CARD_EN; val |= SDHCI_CLOCK_CARD_EN;
} else { } else {
val |= SDHCI_CLOCK_CARD_EN; val |= SDHCI_CLOCK_CARD_EN;
@ -551,7 +562,7 @@ imx_sdhc_get_clock(struct imx_sdhci_softc *sc)
} }
static void 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; 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; sc->sdclockreg_freq_bits = val & SDHCI_DIVIDERS_MASK;
if (sc->hwtype == HWTYPE_ESDHC) { if (sc->hwtype == HWTYPE_ESDHC) {
/* /*
* The ESDHC hardware requires the driver to manually start and * The i.MX5 ESDHC hardware requires the driver to manually
* stop the sd bus clock. If the enable bit is not set, turn * start and stop the sd bus clock. If the enable bit is not
* off the clock in hardware and we're done, otherwise decode * set, turn off the clock in hardware and we're done, otherwise
* the requested frequency. ESDHC hardware is sdhci 2.0; the * decode the requested frequency. ESDHC hardware is sdhci 2.0;
* sdhci driver will use the original 8-bit divisor field and * the sdhci driver will use the original 8-bit divisor field
* the "base / 2^N" divisor scheme. * and the "base / 2^N" divisor scheme.
*/ */
if ((val & SDHCI_CLOCK_CARD_EN) == 0) { 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); WR4(sc, SDHCI_CLOCK_CONTROL, val32 & ~SDHC_CLK_SDCLKEN);
#endif
return; 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 &= ~(SDHC_CLK_DIVISOR_MASK | SDHC_CLK_PRESCALE_MASK);
val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT; val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT;
val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT; val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT;
val32 |= SDHC_CLK_IPGEN;
WR4(sc, SDHCI_CLOCK_CONTROL, val32); WR4(sc, SDHCI_CLOCK_CONTROL, val32);
} }
static boolean_t 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; 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) { if (inhibit && getsbinuptime() < sc->r1bfix_timeout_at) {
callout_reset_sbt(&sc->r1bfix_callout, SBT_1MS, 0, callout_reset_sbt(&sc->r1bfix_callout, SBT_1MS, 0,
imx_sdhci_r1bfix_func, sc, 0); fsl_sdhci_r1bfix_func, sc, 0);
return (false); return (false);
} }
@ -670,22 +685,22 @@ imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc)
} }
static void 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; boolean_t r1bwait_done;
mtx_lock(&sc->slot.mtx); 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); mtx_unlock(&sc->slot.mtx);
if (r1bwait_done) if (r1bwait_done)
sdhci_generic_intr(&sc->slot); sdhci_generic_intr(&sc->slot);
} }
static void 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; uint32_t intmask;
mtx_lock(&sc->slot.mtx); mtx_lock(&sc->slot.mtx);
@ -710,10 +725,10 @@ imx_sdhci_intr(void *arg)
*/ */
switch (sc->r1bfix_type) { switch (sc->r1bfix_type) {
case R1BFIX_NODATA: case R1BFIX_NODATA:
intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_RESPONSE; intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_RESPONSE;
break; break;
case R1BFIX_AC12: case R1BFIX_AC12:
intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_DATA_END; intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_DATA_END;
break; break;
default: default:
intmask = 0; intmask = 0;
@ -721,9 +736,9 @@ imx_sdhci_intr(void *arg)
} }
if (intmask) { if (intmask) {
sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS; sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS;
if (!imx_sdhci_r1bfix_is_wait_done(sc)) { if (!fsl_sdhci_r1bfix_is_wait_done(sc)) {
WR4(sc, SDHC_INT_STATUS, intmask); WR4(sc, SDHCI_INT_STATUS, intmask);
bus_barrier(sc->mem_res, SDHC_INT_STATUS, 4, bus_barrier(sc->mem_res, SDHCI_INT_STATUS, 4,
BUS_SPACE_BARRIER_WRITE); BUS_SPACE_BARRIER_WRITE);
} }
} }
@ -733,31 +748,76 @@ imx_sdhci_intr(void *arg)
} }
static int 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 static int
imx_sdhci_detach(device_t dev) fsl_sdhci_detach(device_t dev)
{ {
return (EBUSY); return (EBUSY);
} }
static int 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; int rid, err;
phandle_t node; phandle_t node;
uint32_t protctl;
sc->dev = dev; sc->dev = dev;
sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
if (sc->hwtype == HWTYPE_NONE) if (sc->hwtype == HWTYPE_NONE)
panic("Impossible: not compatible in imx_sdhci_attach()"); panic("Impossible: not compatible in fsl_sdhci_attach()");
rid = 0; rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 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, 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"); device_printf(dev, "cannot setup interrupt handler\n");
err = ENXIO; err = ENXIO;
goto fail; goto fail;
@ -807,9 +867,23 @@ imx_sdhci_attach(device_t dev)
* *
* XXX need named constants for this stuff. * 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(); sc->baseclk_hz = imx_ccm_sdhci_hz();
#endif
sc->slot.max_clk = sc->baseclk_hz; sc->slot.max_clk = sc->baseclk_hz;
/* /*
@ -830,6 +904,16 @@ imx_sdhci_attach(device_t dev)
/* XXX put real gpio hookup here. */ /* XXX put real gpio hookup here. */
sc->force_card_present = true; 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); callout_init(&sc->r1bfix_callout, 1);
sdhci_init_slot(dev, &sc->slot, 0); sdhci_init_slot(dev, &sc->slot, 0);
@ -853,7 +937,7 @@ imx_sdhci_attach(device_t dev)
} }
static int static int
imx_sdhci_probe(device_t dev) fsl_sdhci_probe(device_t dev)
{ {
if (!ofw_bus_status_okay(dev)) if (!ofw_bus_status_okay(dev))
@ -872,11 +956,11 @@ imx_sdhci_probe(device_t dev)
return (ENXIO); return (ENXIO);
} }
static device_method_t imx_sdhci_methods[] = { static device_method_t fsl_sdhci_methods[] = {
/* Device interface */ /* Device interface */
DEVMETHOD(device_probe, imx_sdhci_probe), DEVMETHOD(device_probe, fsl_sdhci_probe),
DEVMETHOD(device_attach, imx_sdhci_attach), DEVMETHOD(device_attach, fsl_sdhci_attach),
DEVMETHOD(device_detach, imx_sdhci_detach), DEVMETHOD(device_detach, fsl_sdhci_detach),
/* Bus interface */ /* Bus interface */
DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
@ -886,32 +970,32 @@ static device_method_t imx_sdhci_methods[] = {
/* MMC bridge interface */ /* MMC bridge interface */
DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
DEVMETHOD(mmcbr_request, sdhci_generic_request), 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_acquire_host, sdhci_generic_acquire_host),
DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
/* SDHCI registers accessors */ /* SDHCI registers accessors */
DEVMETHOD(sdhci_read_1, imx_sdhci_read_1), DEVMETHOD(sdhci_read_1, fsl_sdhci_read_1),
DEVMETHOD(sdhci_read_2, imx_sdhci_read_2), DEVMETHOD(sdhci_read_2, fsl_sdhci_read_2),
DEVMETHOD(sdhci_read_4, imx_sdhci_read_4), DEVMETHOD(sdhci_read_4, fsl_sdhci_read_4),
DEVMETHOD(sdhci_read_multi_4, imx_sdhci_read_multi_4), DEVMETHOD(sdhci_read_multi_4, fsl_sdhci_read_multi_4),
DEVMETHOD(sdhci_write_1, imx_sdhci_write_1), DEVMETHOD(sdhci_write_1, fsl_sdhci_write_1),
DEVMETHOD(sdhci_write_2, imx_sdhci_write_2), DEVMETHOD(sdhci_write_2, fsl_sdhci_write_2),
DEVMETHOD(sdhci_write_4, imx_sdhci_write_4), DEVMETHOD(sdhci_write_4, fsl_sdhci_write_4),
DEVMETHOD(sdhci_write_multi_4, imx_sdhci_write_multi_4), DEVMETHOD(sdhci_write_multi_4, fsl_sdhci_write_multi_4),
{ 0, 0 } { 0, 0 }
}; };
static devclass_t imx_sdhci_devclass; static devclass_t fsl_sdhci_devclass;
static driver_t imx_sdhci_driver = { static driver_t fsl_sdhci_driver = {
"sdhci_imx", "sdhci_fsl",
imx_sdhci_methods, fsl_sdhci_methods,
sizeof(struct imx_sdhci_softc), sizeof(struct fsl_sdhci_softc),
}; };
DRIVER_MODULE(sdhci_imx, simplebus, imx_sdhci_driver, imx_sdhci_devclass, 0, 0); DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass, 0, 0);
MODULE_DEPEND(sdhci_imx, sdhci, 1, 1, 1); MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL); DRIVER_MODULE(mmc, sdhci_fsl, mmc_driver, mmc_devclass, NULL, NULL);
MODULE_DEPEND(sdhci_imx, mmc, 1, 1, 1); MODULE_DEPEND(sdhci_fsl, mmc, 1, 1, 1);

View File

@ -1309,7 +1309,7 @@ sdhci_acmd_irq(struct sdhci_slot *slot)
void void
sdhci_generic_intr(struct sdhci_slot *slot) sdhci_generic_intr(struct sdhci_slot *slot)
{ {
uint32_t intmask; uint32_t intmask, present;
SDHCI_LOCK(slot); SDHCI_LOCK(slot);
/* Read slot interrupt status. */ /* Read slot interrupt status. */
@ -1323,6 +1323,13 @@ sdhci_generic_intr(struct sdhci_slot *slot)
/* Handle card presence interrupts. */ /* Handle card presence interrupts. */
if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 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 & WR4(slot, SDHCI_INT_STATUS, intmask &
(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)); (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE));

View File

@ -50,7 +50,6 @@ struct smbus_ivar
/* /*
* Autoconfiguration and support routines for System Management bus * Autoconfiguration and support routines for System Management bus
*/ */
static void smbus_probe_device(device_t dev, u_char addr);
static int static int
smbus_probe(device_t dev) smbus_probe(device_t dev)
@ -65,13 +64,9 @@ static int
smbus_attach(device_t dev) smbus_attach(device_t dev)
{ {
struct smbus_softc *sc = device_get_softc(dev); struct smbus_softc *sc = device_get_softc(dev);
unsigned char addr;
mtx_init(&sc->lock, device_get_nameunit(dev), "smbus", MTX_DEF); mtx_init(&sc->lock, device_get_nameunit(dev), "smbus", MTX_DEF);
bus_generic_probe(dev); 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_enumerate_hinted_children(dev);
bus_generic_attach(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 static device_t
smbus_add_child(device_t dev, u_int order, const char *name, int unit) smbus_add_child(device_t dev, u_int order, const char *name, int unit)
{ {

View File

@ -330,10 +330,13 @@ ums_intr_callback(struct usb_xfer *xfer, usb_error_t error)
dx, dy, dz, dt, dw, buttons); dx, dy, dz, dt, dw, buttons);
/* translate T-axis into button presses until further */ /* 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; buttons |= 1UL << 5;
else if (dt < 0) } else if (dt < 0) {
ums_put_queue(sc, 0, 0, 0, 0, buttons);
buttons |= 1UL << 6; buttons |= 1UL << 6;
}
sc->sc_status.button = buttons; sc->sc_status.button = buttons;
sc->sc_status.dx += dx; sc->sc_status.dx += dx;

View File

@ -350,7 +350,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
*retdirp = NULL; *retdirp = NULL;
cnp->cn_nameptr = cnp->cn_pnbuf; cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_strictrelative = 0; ndp->ni_lcf = 0;
/* /*
* Extract and set starting directory. * Extract and set starting directory.
*/ */

View File

@ -668,6 +668,7 @@ g_dev_strategy(struct bio *bp)
sc = cp->private; sc = cp->private;
KASSERT(cp->acr || cp->acw, KASSERT(cp->acr || cp->acw,
("Consumer with zero access count in g_dev_strategy")); ("Consumer with zero access count in g_dev_strategy"));
biotrack(bp, __func__);
#ifdef INVARIANTS #ifdef INVARIANTS
if ((bp->bio_offset % cp->provider->sectorsize) != 0 || if ((bp->bio_offset % cp->provider->sectorsize) != 0 ||
(bp->bio_bcount % cp->provider->sectorsize) != 0) { (bp->bio_bcount % cp->provider->sectorsize) != 0) {

View File

@ -421,6 +421,8 @@ g_disk_start(struct bio *bp)
int error; int error;
off_t off; off_t off;
biotrack(bp, __func__);
sc = bp->bio_to->private; sc = bp->bio_to->private;
if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) { if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
g_io_deliver(bp, ENXIO); g_io_deliver(bp, ENXIO);

View File

@ -223,6 +223,9 @@ g_clone_bio(struct bio *bp)
/* Inherit classification info from the parent */ /* Inherit classification info from the parent */
bp2->bio_classifier1 = bp->bio_classifier1; bp2->bio_classifier1 = bp->bio_classifier1;
bp2->bio_classifier2 = bp->bio_classifier2; 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++; bp->bio_children++;
} }
#ifdef KTR #ifdef KTR
@ -362,6 +365,8 @@ g_io_check(struct bio *bp)
off_t excess; off_t excess;
int error; int error;
biotrack(bp, __func__);
cp = bp->bio_from; cp = bp->bio_from;
pp = bp->bio_to; pp = bp->bio_to;
@ -503,6 +508,8 @@ g_run_classifiers(struct bio *bp)
struct g_classifier_hook *hook; struct g_classifier_hook *hook;
int classified = 0; int classified = 0;
biotrack(bp, __func__);
TAILQ_FOREACH(hook, &g_classifier_tailq, link) TAILQ_FOREACH(hook, &g_classifier_tailq, link)
classified |= hook->func(hook->arg, bp); classified |= hook->func(hook->arg, bp);
@ -518,6 +525,8 @@ g_io_request(struct bio *bp, struct g_consumer *cp)
int direct, error, first; int direct, error, first;
uint8_t cmd; uint8_t cmd;
biotrack(bp, __func__);
KASSERT(cp != NULL, ("NULL cp in g_io_request")); KASSERT(cp != NULL, ("NULL cp in g_io_request"));
KASSERT(bp != NULL, ("NULL bp in g_io_request")); KASSERT(bp != NULL, ("NULL bp in g_io_request"));
pp = cp->provider; pp = cp->provider;
@ -644,6 +653,8 @@ g_io_deliver(struct bio *bp, int error)
struct mtx *mtxp; struct mtx *mtxp;
int direct, first; int direct, first;
biotrack(bp, __func__);
KASSERT(bp != NULL, ("NULL bp in g_io_deliver")); KASSERT(bp != NULL, ("NULL bp in g_io_deliver"));
pp = bp->bio_to; pp = bp->bio_to;
KASSERT(pp != NULL, ("NULL bio_to in g_io_deliver")); 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"); CTR0(KTR_GEOM, "g_down has work to do");
g_bioq_unlock(&g_bio_run_down); g_bioq_unlock(&g_bio_run_down);
biotrack(bp, __func__);
if (pace != 0) { if (pace != 0) {
/* /*
* There has been at least one memory allocation * There has been at least one memory allocation

View File

@ -1531,6 +1531,10 @@ DB_SHOW_COMMAND(bio, db_show_bio)
db_printf(" caller2: %p\n", bp->bio_caller2); db_printf(" caller2: %p\n", bp->bio_caller2);
db_printf(" bio_from: %p\n", bp->bio_from); db_printf(" bio_from: %p\n", bp->bio_from);
db_printf(" bio_to: %p\n", bp->bio_to); 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
} }
} }

View File

@ -192,6 +192,10 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
} }
bip->bio_done = g_vfs_done; bip->bio_done = g_vfs_done;
bip->bio_caller2 = bp; 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); g_io_request(bip, cp);
} }

View File

@ -2154,6 +2154,8 @@ g_part_start(struct bio *bp)
struct g_provider *pp; struct g_provider *pp;
char buf[64]; char buf[64];
biotrack(bp, __func__);
pp = bp->bio_to; pp = bp->bio_to;
gp = pp->geom; gp = pp->geom;
table = gp->softc; table = gp->softc;

View File

@ -1952,6 +1952,7 @@ bufwrite(struct buf *bp)
if (oldflags & B_ASYNC) if (oldflags & B_ASYNC)
BUF_KERNPROC(bp); BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno); bp->b_iooffset = dbtob(bp->b_blkno);
buf_track(bp, __func__);
bstrategy(bp); bstrategy(bp);
if ((oldflags & B_ASYNC) == 0) { 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); 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 * Set the *dirty* buffer range based upon the VM system dirty
* pages. * pages.
@ -2386,6 +2389,8 @@ brelse(struct buf *bp)
brelvp(bp); brelvp(bp);
} }
buf_track(bp, __func__);
/* buffers with no memory */ /* buffers with no memory */
if (bp->b_bufsize == 0) { if (bp->b_bufsize == 0) {
buf_free(bp); buf_free(bp);
@ -2470,6 +2475,7 @@ bqrelse(struct buf *bp)
binsfree(bp, qindex); binsfree(bp, qindex);
out: out:
buf_track(bp, __func__);
/* unlock */ /* unlock */
BUF_UNLOCK(bp); BUF_UNLOCK(bp);
if (qindex == QUEUE_CLEAN) 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); CTR4(KTR_BUF, "getblk(%p, %ld, %d) = %p", vp, (long)blkno, size, bp);
BUF_ASSERT_HELD(bp); BUF_ASSERT_HELD(bp);
end: end:
buf_track(bp, __func__);
KASSERT(bp->b_bufobj == bo, KASSERT(bp->b_bufobj == bo,
("bp %p wrong b_bufobj %p should be %p", bp, bp->b_bufobj, bo)); ("bp %p wrong b_bufobj %p should be %p", bp, bp->b_bufobj, bo));
return (bp); return (bp);
@ -3892,6 +3899,7 @@ biodone(struct bio *bp)
void (*done)(struct bio *); void (*done)(struct bio *);
vm_offset_t start, end; vm_offset_t start, end;
biotrack(bp, __func__);
if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) { if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) {
bp->bio_flags &= ~BIO_TRANSIENT_MAPPING; bp->bio_flags &= ~BIO_TRANSIENT_MAPPING;
bp->bio_flags |= BIO_UNMAPPED; bp->bio_flags |= BIO_UNMAPPED;
@ -3948,6 +3956,15 @@ biofinish(struct bio *bp, struct devstat *stat, int error)
biodone(bp); 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: * bufwait:
* *
@ -3998,6 +4015,7 @@ bufdone(struct buf *bp)
struct bufobj *dropobj; struct bufobj *dropobj;
void (*biodone)(struct buf *); void (*biodone)(struct buf *);
buf_track(bp, __func__);
CTR3(KTR_BUF, "bufdone(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); CTR3(KTR_BUF, "bufdone(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
dropobj = NULL; dropobj = NULL;
@ -4801,6 +4819,9 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
{ {
/* get args */ /* get args */
struct buf *bp = (struct buf *)addr; struct buf *bp = (struct buf *)addr;
#ifdef FULL_BUF_TRACKING
uint32_t i, j;
#endif
if (!have_addr) { if (!have_addr) {
db_printf("usage: show buffer <addr>\n"); db_printf("usage: show buffer <addr>\n");
@ -4837,6 +4858,16 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
} }
db_printf("\n"); 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(" "); db_printf(" ");
BUF_LOCKPRINTINFO(bp); BUF_LOCKPRINTINFO(bp);
} }

View File

@ -1008,6 +1008,7 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len,
reassignbuf(tbp); /* put on clean list */ reassignbuf(tbp); /* put on clean list */
bufobj_wref(tbp->b_bufobj); bufobj_wref(tbp->b_bufobj);
BUF_KERNPROC(tbp); BUF_KERNPROC(tbp);
buf_track(tbp, __func__);
TAILQ_INSERT_TAIL(&bp->b_cluster.cluster_head, TAILQ_INSERT_TAIL(&bp->b_cluster.cluster_head,
tbp, b_cluster.cluster_entry); tbp, b_cluster.cluster_entry);
} }

View File

@ -73,21 +73,28 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, entry, "struct vnode *", "char *",
"unsigned long"); "unsigned long");
SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
/* /* Allocation zone for namei. */
* Allocation zone for namei
*/
uma_zone_t namei_zone; uma_zone_t namei_zone;
/*
* Placeholder vnode for mp traversal /* Placeholder vnode for mp traversal. */
*/
static struct vnode *vp_crossmp; 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 static void
nameiinit(void *dummy __unused) nameiinit(void *dummy __unused)
{ {
namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL, namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, 0); 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); getnewvnode("crossmp", NULL, &dead_vnodeops, &vp_crossmp);
vn_lock(vp_crossmp, LK_EXCLUSIVE); vn_lock(vp_crossmp, LK_EXCLUSIVE);
VN_LOCK_ASHARE(vp_crossmp); VN_LOCK_ASHARE(vp_crossmp);
@ -97,11 +104,82 @@ SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL);
static int lookup_shared = 1; static int lookup_shared = 1;
SYSCTL_INT(_vfs, OID_AUTO, lookup_shared, CTLFLAG_RWTUN, &lookup_shared, 0, 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 static void
namei_cleanup_cnp(struct componentname *cnp) namei_cleanup_cnp(struct componentname *cnp)
{ {
uma_zfree(namei_zone, cnp->cn_pnbuf); uma_zfree(namei_zone, cnp->cn_pnbuf);
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
cnp->cn_pnbuf = NULL; cnp->cn_pnbuf = NULL;
@ -115,7 +193,7 @@ namei_handle_root(struct nameidata *ndp, struct vnode **dpp)
struct componentname *cnp; struct componentname *cnp;
cnp = &ndp->ni_cnd; cnp = &ndp->ni_cnd;
if (ndp->ni_strictrelative != 0) { if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0) {
#ifdef KTRACE #ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL)) if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
@ -158,12 +236,16 @@ namei(struct nameidata *ndp)
char *cp; /* pointer into pathname argument */ char *cp; /* pointer into pathname argument */
struct vnode *dp; /* the directory we are searching */ struct vnode *dp; /* the directory we are searching */
struct iovec aiov; /* uio for reading symbolic links */ struct iovec aiov; /* uio for reading symbolic links */
struct componentname *cnp;
struct thread *td;
struct proc *p;
cap_rights_t rights;
struct uio auio; struct uio auio;
int error, linklen, startdir_used; 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; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred;
KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc")); KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc"));
KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0, KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0,
@ -175,6 +257,8 @@ namei(struct nameidata *ndp)
if (!lookup_shared) if (!lookup_shared)
cnp->cn_flags &= ~LOCKSHARED; cnp->cn_flags &= ~LOCKSHARED;
fdp = p->p_fd; fdp = p->p_fd;
TAILQ_INIT(&ndp->ni_cap_tracker);
ndp->ni_lcf = 0;
/* We will set this ourselves if we need it. */ /* We will set this ourselves if we need it. */
cnp->cn_flags &= ~TRAILINGSLASH; cnp->cn_flags &= ~TRAILINGSLASH;
@ -186,11 +270,11 @@ namei(struct nameidata *ndp)
if ((cnp->cn_flags & HASBUF) == 0) if ((cnp->cn_flags & HASBUF) == 0)
cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
if (ndp->ni_segflg == UIO_SYSSPACE) if (ndp->ni_segflg == UIO_SYSSPACE)
error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN,
MAXPATHLEN, (size_t *)&ndp->ni_pathlen); &ndp->ni_pathlen);
else else
error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN,
MAXPATHLEN, (size_t *)&ndp->ni_pathlen); &ndp->ni_pathlen);
/* /*
* Don't allow empty pathnames. * Don't allow empty pathnames.
@ -200,13 +284,21 @@ namei(struct nameidata *ndp)
#ifdef CAPABILITY_MODE #ifdef CAPABILITY_MODE
/* /*
* In capability mode, lookups must be "strictly relative" (i.e. * In capability mode, lookups must be restricted to happen in
* not an absolute path, and not containing '..' components) to * the subtree with the root specified by the file descriptor:
* a real file descriptor, not the pseudo-descriptor AT_FDCWD. * - 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) && if (error == 0 && IN_CAPABILITY_MODE(td) &&
(cnp->cn_flags & NOCAPCHECK) == 0) { (cnp->cn_flags & NOCAPCHECK) == 0) {
ndp->ni_strictrelative = 1; ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
if (ndp->ni_dirfd == AT_FDCWD) { if (ndp->ni_dirfd == AT_FDCWD) {
#ifdef KTRACE #ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL)) if (KTRPOINT(td, KTR_CAPFAIL))
@ -258,8 +350,6 @@ namei(struct nameidata *ndp)
dp = fdp->fd_cdir; dp = fdp->fd_cdir;
VREF(dp); VREF(dp);
} else { } else {
cap_rights_t rights;
rights = ndp->ni_rightsneeded; rights = ndp->ni_rightsneeded;
cap_rights_set(&rights, CAP_LOOKUP); cap_rights_set(&rights, CAP_LOOKUP);
@ -282,7 +372,7 @@ namei(struct nameidata *ndp)
&rights) || &rights) ||
ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL || ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
ndp->ni_filecaps.fc_nioctls != -1) { ndp->ni_filecaps.fc_nioctls != -1) {
ndp->ni_strictrelative = 1; ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
} }
#endif #endif
} }
@ -297,6 +387,9 @@ namei(struct nameidata *ndp)
vrele(dp); vrele(dp);
goto out; 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, SDT_PROBE3(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf,
cnp->cn_flags); cnp->cn_flags);
for (;;) { for (;;) {
@ -313,7 +406,7 @@ namei(struct nameidata *ndp)
namei_cleanup_cnp(cnp); namei_cleanup_cnp(cnp);
} else } else
cnp->cn_flags |= HASBUF; cnp->cn_flags |= HASBUF;
nameicap_cleanup(ndp);
SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp); SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp);
return (0); return (0);
} }
@ -387,6 +480,7 @@ namei(struct nameidata *ndp)
out: out:
vrele(ndp->ni_rootdir); vrele(ndp->ni_rootdir);
namei_cleanup_cnp(cnp); namei_cleanup_cnp(cnp);
nameicap_cleanup(ndp);
SDT_PROBE2(vfs, namei, lookup, return, error, NULL); SDT_PROBE2(vfs, namei, lookup, return, error, NULL);
return (error); return (error);
} }
@ -583,6 +677,8 @@ lookup(struct nameidata *ndp)
goto bad; goto bad;
} }
nameicap_tracker_add(ndp, dp);
/* /*
* Check for degenerate name (e.g. / or "") * Check for degenerate name (e.g. / or "")
* which is a way of talking about a directory, * which is a way of talking about a directory,
@ -618,9 +714,8 @@ lookup(struct nameidata *ndp)
/* /*
* Handle "..": five special cases. * Handle "..": five special cases.
* 0. If doing a capability lookup, return ENOTCAPABLE (this is a * 0. If doing a capability lookup and lookup_cap_dotdot is
* fairly conservative design choice, but it's the only one that we * disabled, return ENOTCAPABLE.
* are satisfied guarantees the property we're looking for).
* 1. Return an error if this is the last component of * 1. Return an error if this is the last component of
* the name and the operation is DELETE or RENAME. * the name and the operation is DELETE or RENAME.
* 2. If at root directory (e.g. after chroot) * 2. If at root directory (e.g. after chroot)
@ -632,9 +727,15 @@ lookup(struct nameidata *ndp)
* .. in the other filesystem. * .. in the other filesystem.
* 4. If the vnode is the top directory of * 4. If the vnode is the top directory of
* the jail or chroot, don't let them out. * 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 (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 #ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL)) if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
@ -676,6 +777,14 @@ lookup(struct nameidata *ndp)
vn_lock(dp, vn_lock(dp,
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
LK_RETRY, ISDOTDOT)); 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, vn_lock(dp,
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
LK_RETRY, cnp->cn_flags)); LK_RETRY, cnp->cn_flags));
nameicap_tracker_add(ndp, dp);
goto unionlookup; goto unionlookup;
} }
@ -855,6 +965,16 @@ lookup(struct nameidata *ndp)
vrele(ndp->ni_dvp); vrele(ndp->ni_dvp);
goto dirloop; 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 == '/') { if (*ndp->ni_next == '/') {
cnp->cn_nameptr = ndp->ni_next; cnp->cn_nameptr = ndp->ni_next;
while (*cnp->cn_nameptr == '/') { 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_dirp = namep;
ndp->ni_dirfd = dirfd; ndp->ni_dirfd = dirfd;
ndp->ni_startdir = startdir; ndp->ni_startdir = startdir;
ndp->ni_strictrelative = 0;
if (rightsp != NULL) if (rightsp != NULL)
ndp->ni_rightsneeded = *rightsp; ndp->ni_rightsneeded = *rightsp;
else else

View File

@ -446,16 +446,19 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
size_t *countp, enum uio_seg bufseg, int flags) size_t *countp, enum uio_seg bufseg, int flags)
{ {
struct mount *mp, *nmp; struct mount *mp, *nmp;
struct statfs *sfsp, *sp, sb; struct statfs *sfsp, *sp, sb, *tofree;
size_t count, maxcount; size_t count, maxcount;
int error; int error;
restart:
maxcount = bufsize / sizeof(struct statfs); maxcount = bufsize / sizeof(struct statfs);
if (bufsize == 0) if (bufsize == 0) {
sfsp = NULL; sfsp = NULL;
else if (bufseg == UIO_USERSPACE) tofree = NULL;
} else if (bufseg == UIO_USERSPACE) {
sfsp = *buf; sfsp = *buf;
else /* if (bufseg == UIO_SYSSPACE) */ { tofree = NULL;
} else /* if (bufseg == UIO_SYSSPACE) */ {
count = 0; count = 0;
mtx_lock(&mountlist_mtx); mtx_lock(&mountlist_mtx);
TAILQ_FOREACH(mp, &mountlist, mnt_list) { 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); mtx_unlock(&mountlist_mtx);
if (maxcount > count) if (maxcount > count)
maxcount = count; maxcount = count;
sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs),
M_WAITOK); M_TEMP, M_WAITOK);
} }
count = 0; count = 0;
mtx_lock(&mountlist_mtx); mtx_lock(&mountlist_mtx);
@ -480,9 +483,24 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
continue; continue;
} }
#endif #endif
if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK)) { if (flags == MNT_WAIT) {
nmp = TAILQ_NEXT(mp, mnt_list); if (vfs_busy(mp, MBF_MNTLSTLOCK) != 0) {
continue; /*
* 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) { if (sfsp && count < maxcount) {
sp = &mp->mnt_stat; 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 * understand exactly what would happen, and we don't think
* that it ever should. * that it ever should.
*/ */
if (nd.ni_strictrelative == 0 && if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) == 0 &&
(error == ENODEV || error == ENXIO) && (error == ENODEV || error == ENXIO) &&
td->td_dupfd >= 0) { td->td_dupfd >= 0) {
error = dupfdopen(td, fdp, td->td_dupfd, flags, error, 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; struct filecaps *fcaps;
#ifdef CAPABILITIES #ifdef CAPABILITIES
if (nd.ni_strictrelative == 1) if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) != 0)
fcaps = &nd.ni_filecaps; fcaps = &nd.ni_filecaps;
else else
#endif #endif

View File

@ -4,7 +4,7 @@
${.CURDIR}/../../../dev/hyperv/vmbus ${.CURDIR}/../../../dev/hyperv/vmbus
KMOD= hv_netvsc 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 SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h vmbus_if.h
CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/netvsc CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/netvsc

View File

@ -474,7 +474,9 @@ cdg_cong_signal(struct cc_var *ccv, uint32_t signal_type)
ENTER_RECOVERY(CCV(ccv, t_flags)); ENTER_RECOVERY(CCV(ccv, t_flags));
break; break;
case CC_RTO: 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; CCV(ccv, snd_cwnd) = mss;
break; break;
default: default:

View File

@ -330,13 +330,11 @@ chd_cong_signal(struct cc_var *ccv, uint32_t signal_type)
struct ertt *e_t; struct ertt *e_t;
struct chd *chd_data; struct chd *chd_data;
int qdly; int qdly;
uint32_t cwin;
u_int mss; u_int mss;
e_t = khelp_get_osd(CCV(ccv, osd), ertt_id); e_t = khelp_get_osd(CCV(ccv, osd), ertt_id);
chd_data = ccv->cc_data; chd_data = ccv->cc_data;
qdly = imax(e_t->rtt, chd_data->maxrtt_in_rtt) - e_t->minrtt; qdly = imax(e_t->rtt, chd_data->maxrtt_in_rtt) - e_t->minrtt;
cwin = CCV(ccv, snd_cwnd);
mss = CCV(ccv, t_maxseg); mss = CCV(ccv, t_maxseg);
switch(signal_type) { switch(signal_type) {
@ -378,7 +376,9 @@ chd_cong_signal(struct cc_var *ccv, uint32_t signal_type)
ENTER_FASTRECOVERY(CCV(ccv, t_flags)); ENTER_FASTRECOVERY(CCV(ccv, t_flags));
break; break;
case CC_RTO: 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; CCV(ccv, snd_cwnd) = mss;
break; break;

View File

@ -230,19 +230,21 @@ static void
dctcp_cong_signal(struct cc_var *ccv, uint32_t type) dctcp_cong_signal(struct cc_var *ccv, uint32_t type)
{ {
struct dctcp *dctcp_data; struct dctcp *dctcp_data;
uint32_t cwin; uint32_t cwin, ssthresh_on_loss;
u_int mss; u_int mss;
dctcp_data = ccv->cc_data; dctcp_data = ccv->cc_data;
cwin = CCV(ccv, snd_cwnd); cwin = CCV(ccv, snd_cwnd);
mss = CCV(ccv, t_maxseg); mss = CCV(ccv, t_maxseg);
ssthresh_on_loss =
max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2)
* mss;
switch (type) { switch (type) {
case CC_NDUPACK: case CC_NDUPACK:
if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
CCV(ccv, snd_ssthresh) = mss * CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
max(cwin / 2 / mss, 2);
dctcp_data->num_cong_events++; dctcp_data->num_cong_events++;
} else { } else {
/* cwnd has already updated as congestion /* 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 * snd_cwnd_prev and recalculate snd_ssthresh
*/ */
cwin = CCV(ccv, snd_cwnd_prev); cwin = CCV(ccv, snd_cwnd_prev);
CCV(ccv, snd_ssthresh) = CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
max(cwin / 2 / mss, 2) * mss;
} }
ENTER_RECOVERY(CCV(ccv, t_flags)); 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 (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
if (V_dctcp_slowstart && if (V_dctcp_slowstart &&
dctcp_data->num_cong_events++ == 0) { dctcp_data->num_cong_events++ == 0) {
CCV(ccv, snd_ssthresh) = CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
mss * max(cwin / 2 / mss, 2);
dctcp_data->alpha = MAX_ALPHA_VALUE; dctcp_data->alpha = MAX_ALPHA_VALUE;
dctcp_data->bytes_ecn = 0; dctcp_data->bytes_ecn = 0;
dctcp_data->bytes_total = 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_update_alpha(ccv);
dctcp_data->save_sndnxt += CCV(ccv, t_maxseg); dctcp_data->save_sndnxt += CCV(ccv, t_maxseg);
dctcp_data->num_cong_events++; 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; CCV(ccv, snd_cwnd) = mss;
} }
break; break;

View File

@ -325,7 +325,9 @@ htcp_cong_signal(struct cc_var *ccv, uint32_t type)
*/ */
if (CCV(ccv, t_rxtshift) >= 2) if (CCV(ccv, t_rxtshift) >= 2)
htcp_data->t_last_cong = ticks; 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; CCV(ccv, snd_cwnd) = mss;
break; break;
} }
@ -518,6 +520,10 @@ htcp_ssthresh_update(struct cc_var *ccv)
CCV(ccv, snd_ssthresh) = ((u_long)CCV(ccv, snd_cwnd) * CCV(ccv, snd_ssthresh) = ((u_long)CCV(ccv, snd_cwnd) *
htcp_data->beta) >> HTCP_SHIFT; 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);
} }

View File

@ -182,23 +182,26 @@ newreno_after_idle(struct cc_var *ccv)
static void static void
newreno_cong_signal(struct cc_var *ccv, uint32_t type) newreno_cong_signal(struct cc_var *ccv, uint32_t type)
{ {
uint32_t cwin; uint32_t cwin, ssthresh_on_loss;
u_int mss; u_int mss;
cwin = CCV(ccv, snd_cwnd); cwin = CCV(ccv, snd_cwnd);
mss = CCV(ccv, t_maxseg); 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. */ /* Catch algos which mistakenly leak private signal types. */
KASSERT((type & CC_SIGPRIVMASK) == 0, KASSERT((type & CC_SIGPRIVMASK) == 0,
("%s: congestion signal type 0x%08x is private\n", __func__, type)); ("%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) { switch (type) {
case CC_NDUPACK: case CC_NDUPACK:
if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
if (!IN_CONGRECOVERY(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; CCV(ccv, snd_cwnd) = cwin;
} }
ENTER_RECOVERY(CCV(ccv, t_flags)); ENTER_RECOVERY(CCV(ccv, t_flags));
@ -206,13 +209,13 @@ newreno_cong_signal(struct cc_var *ccv, uint32_t type)
break; break;
case CC_ECN: case CC_ECN:
if (!IN_CONGRECOVERY(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; CCV(ccv, snd_cwnd) = cwin;
ENTER_CONGRECOVERY(CCV(ccv, t_flags)); ENTER_CONGRECOVERY(CCV(ccv, t_flags));
} }
break; break;
case CC_RTO: case CC_RTO:
CCV(ccv, snd_ssthresh) = cwin; CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
CCV(ccv, snd_cwnd) = mss; CCV(ccv, snd_cwnd) = mss;
break; break;
} }

View File

@ -444,7 +444,8 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
* ssthresh = max (FlightSize / 2, 2*SMSS) eq (4) * ssthresh = max (FlightSize / 2, 2*SMSS) eq (4)
*/ */
tp->snd_ssthresh = 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; tp->snd_cwnd = maxseg;
} }
break; break;

View File

@ -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). * ipfw processing for ethernet packets (in and out).
* Inteface is NULL from ether_demux, and ifp from
* ether_output_frame.
*/ */
int 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 inpcb *inp)
{ {
struct ether_header *eh; 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 */ m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */
args.m = m; /* the packet we are looking at */ 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_hop = NULL; /* we do not support forward yet */
args.next_hop6 = 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 */ 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: case IP_FW_DUMMYNET:
ret = EACCES; ret = EACCES;
int dir;
if (ip_dn_io_ptr == NULL) if (ip_dn_io_ptr == NULL)
break; /* i.e. drop */ break; /* i.e. drop */
*m0 = NULL; *m0 = NULL;
dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN); dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT;
ip_dn_io_ptr(&m, dir, &args); ip_dn_io_ptr(&m, dir | PROTO_LAYER2, &args);
return 0; return 0;
default: default:

View File

@ -698,8 +698,12 @@
#define SVR_MPC8572E 0x80e8 #define SVR_MPC8572E 0x80e8
#define SVR_P1011 0x80e5 #define SVR_P1011 0x80e5
#define SVR_P1011E 0x80ed #define SVR_P1011E 0x80ed
#define SVR_P1013 0x80e7
#define SVR_P1013E 0x80ef
#define SVR_P1020 0x80e4 #define SVR_P1020 0x80e4
#define SVR_P1020E 0x80ec #define SVR_P1020E 0x80ec
#define SVR_P1022 0x80e6
#define SVR_P1022E 0x80ee
#define SVR_P2010 0x80e3 #define SVR_P2010 0x80e3
#define SVR_P2010E 0x80eb #define SVR_P2010E 0x80eb
#define SVR_P2020 0x80e2 #define SVR_P2020 0x80e2

File diff suppressed because it is too large Load Diff

View File

@ -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 <sys/cdefs.h>
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcreg.h>
#include <dev/mmc/mmcvar.h>
#include <dev/mmc/mmcbrvar.h>
#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_ */

View File

@ -121,6 +121,9 @@ struct bio {
void *_bio_caller2; void *_bio_caller2;
uint8_t _bio_cflags; uint8_t _bio_cflags;
#endif #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 */ /* XXX: these go away when bio chaining is introduced */
daddr_t bio_pblkno; /* physical block number */ 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); void biofinish(struct bio *bp, struct devstat *stat, int error);
int biowait(struct bio *bp, const char *wchan); 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); void bioq_disksort(struct bio_queue_head *ap, struct bio *bp);
struct bio *bioq_first(struct bio_queue_head *head); struct bio *bioq_first(struct bio_queue_head *head);
struct bio *bioq_takefirst(struct bio_queue_head *head); struct bio *bioq_takefirst(struct bio_queue_head *head);

View File

@ -140,6 +140,15 @@ struct buf {
void *b_fsprivate1; void *b_fsprivate1;
void *b_fsprivate2; void *b_fsprivate2;
void *b_fsprivate3; 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 #define b_object b_bufobj->bo_object
@ -429,6 +438,17 @@ buf_countdeps(struct buf *bp, int i)
return (0); 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 */ #endif /* _KERNEL */
/* /*

View File

@ -55,6 +55,9 @@ struct componentname {
long cn_namelen; /* length of looked up component */ long cn_namelen; /* length of looked up component */
}; };
struct nameicap_tracker;
TAILQ_HEAD(nameicap_tracker_head, nameicap_tracker);
/* /*
* Encapsulation of namei parameters. * Encapsulation of namei parameters.
*/ */
@ -72,7 +75,7 @@ struct nameidata {
struct vnode *ni_rootdir; /* logical root directory */ struct vnode *ni_rootdir; /* logical root directory */
struct vnode *ni_topdir; /* logical top directory */ struct vnode *ni_topdir; /* logical top directory */
int ni_dirfd; /* starting directory for *at functions */ 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 * Results: returned from namei
*/ */
@ -94,6 +97,7 @@ struct nameidata {
* through the VOP interface. * through the VOP interface.
*/ */
struct componentname ni_cnd; struct componentname ni_cnd;
struct nameicap_tracker_head ni_cap_tracker;
}; };
#ifdef _KERNEL #ifdef _KERNEL
@ -151,6 +155,12 @@ struct nameidata {
#define NOCAPCHECK 0x20000000 /* do not perform capability checks */ #define NOCAPCHECK 0x20000000 /* do not perform capability checks */
#define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */ #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. * Initialization of a nameidata structure.
*/ */

View File

@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -61,11 +61,7 @@ __FBSDID("$FreeBSD$");
* remaining space in the directory. * remaining space in the directory.
*/ */
int int
ffs_blkatoff(vp, offset, res, bpp) ffs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
struct vnode *vp;
off_t offset;
char **res;
struct buf **bpp;
{ {
struct inode *ip; struct inode *ip;
struct fs *fs; struct fs *fs;
@ -95,11 +91,7 @@ ffs_blkatoff(vp, offset, res, bpp)
* to the incore copy. * to the incore copy.
*/ */
void void
ffs_load_inode(bp, ip, fs, ino) ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
struct buf *bp;
struct inode *ip;
struct fs *fs;
ino_t ino;
{ {
if (I_IS_UFS1(ip)) { if (I_IS_UFS1(ip)) {
@ -131,11 +123,7 @@ ffs_load_inode(bp, ip, fs, ino)
* of some frags. * of some frags.
*/ */
void void
ffs_fragacct(fs, fragmap, fraglist, cnt) ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt)
struct fs *fs;
int fragmap;
int32_t fraglist[];
int cnt;
{ {
int inblk; int inblk;
int field, subfield; int field, subfield;
@ -167,10 +155,7 @@ ffs_fragacct(fs, fragmap, fraglist, cnt)
* check if a block is available * check if a block is available
*/ */
int int
ffs_isblock(fs, cp, h) ffs_isblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h)
struct fs *fs;
unsigned char *cp;
ufs1_daddr_t h;
{ {
unsigned char mask; unsigned char mask;
@ -199,10 +184,7 @@ ffs_isblock(fs, cp, h)
* check if a block is free * check if a block is free
*/ */
int int
ffs_isfreeblock(fs, cp, h) ffs_isfreeblock(struct fs *fs, u_char *cp, ufs1_daddr_t h)
struct fs *fs;
u_char *cp;
ufs1_daddr_t h;
{ {
switch ((int)fs->fs_frag) { switch ((int)fs->fs_frag) {
@ -227,10 +209,7 @@ ffs_isfreeblock(fs, cp, h)
* take a block out of the map * take a block out of the map
*/ */
void void
ffs_clrblock(fs, cp, h) ffs_clrblock(struct fs *fs, u_char *cp, ufs1_daddr_t h)
struct fs *fs;
u_char *cp;
ufs1_daddr_t h;
{ {
switch ((int)fs->fs_frag) { switch ((int)fs->fs_frag) {
@ -258,10 +237,7 @@ ffs_clrblock(fs, cp, h)
* put a block into the map * put a block into the map
*/ */
void void
ffs_setblock(fs, cp, h) ffs_setblock(struct fs *fs, unsigned char *cp, ufs1_daddr_t h)
struct fs *fs;
unsigned char *cp;
ufs1_daddr_t h;
{ {
switch ((int)fs->fs_frag) { switch ((int)fs->fs_frag) {
@ -292,11 +268,7 @@ ffs_setblock(fs, cp, h)
* Cnt == 1 means free; cnt == -1 means allocating. * Cnt == 1 means free; cnt == -1 means allocating.
*/ */
void void
ffs_clusteracct(fs, cgp, blkno, cnt) ffs_clusteracct(struct fs *fs, struct cg *cgp, ufs1_daddr_t blkno, int cnt)
struct fs *fs;
struct cg *cgp;
ufs1_daddr_t blkno;
int cnt;
{ {
int32_t *sump; int32_t *sump;
int32_t *lp; int32_t *lp;

View File

@ -420,8 +420,7 @@ RetryFault:;
* they will stay around as well. * they will stay around as well.
* *
* Bump the paging-in-progress count to prevent size changes (e.g. * Bump the paging-in-progress count to prevent size changes (e.g.
* truncation operations) during I/O. This must be done after * truncation operations) during I/O.
* obtaining the vnode lock in order to avoid possible deadlocks.
*/ */
vm_object_reference_locked(fs.first_object); vm_object_reference_locked(fs.first_object);
vm_object_pip_add(fs.first_object, 1); vm_object_pip_add(fs.first_object, 1);
@ -647,7 +646,13 @@ RetryFault:;
if (locked != LK_EXCLUSIVE) if (locked != LK_EXCLUSIVE)
locked = LK_SHARED; 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 | error = vget(vp, locked | LK_CANRECURSE |
LK_NOWAIT, curthread); LK_NOWAIT, curthread);
if (error != 0) { if (error != 0) {

View File

@ -376,6 +376,7 @@ initpbuf(struct buf *bp)
bp->b_iodone = NULL; bp->b_iodone = NULL;
bp->b_error = 0; bp->b_error = 0;
BUF_LOCK(bp, LK_EXCLUSIVE, NULL); 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_vp == NULL, ("relpbuf with vp"));
KASSERT(bp->b_bufobj == NULL, ("relpbuf with bufobj")); KASSERT(bp->b_bufobj == NULL, ("relpbuf with bufobj"));
buf_track(bp, __func__);
BUF_UNLOCK(bp); BUF_UNLOCK(bp);
mtx_lock(&pbuf_mtx); mtx_lock(&pbuf_mtx);

View File

@ -14,6 +14,11 @@ ATF_TESTS_C+= unix_passfd_test
TEST_METADATA.unix_seqpacket_test+= timeout="15" TEST_METADATA.unix_seqpacket_test+= timeout="15"
ATF_TESTS_C+= waitpid_nohang ATF_TESTS_C+= waitpid_nohang
ATF_TESTS_SH+= coredump_phnum_test
BINDIR= ${TESTSDIR}
PROGS+= coredump_phnum_helper
LIBADD.ptrace_test+= pthread LIBADD.ptrace_test+= pthread
LIBADD.unix_seqpacket_test+= pthread LIBADD.unix_seqpacket_test+= pthread

Some files were not shown because too many files have changed in this diff Show More