Merge ^/head r305220 through r305300.

This commit is contained in:
Dimitry Andric 2016-09-02 19:44:23 +00:00
commit 2aeb03806a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang390-import/; revision=305301
86 changed files with 1366 additions and 2280 deletions

View file

@ -1628,8 +1628,10 @@ _crunchide= usr.sbin/crunch/crunchide
# r285986 crunchen: use STRIPBIN rather than STRIP
# 1100113: Support MK_AUTO_OBJ
# 1200006: META_MODE fixes
.if ${BOOTSTRAPPING} < 1100078 || \
(${MK_AUTO_OBJ} == "yes" && ${BOOTSTRAPPING} < 1100114)
(${MK_AUTO_OBJ} == "yes" && ${BOOTSTRAPPING} < 1100114) || \
(${MK_META_MODE} == "yes" && ${BOOTSTRAPPING} < 1200006)
_crunchgen= usr.sbin/crunch/crunchgen
.endif

View file

@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
# 20160901: Remove digi(4)
OLD_FILES+=usr/share/man/man4/digi.4.gz
# 20160819: Remove ie(4)
OLD_FILES+=usr/share/man/man4/i386/ie.4.gz
# 20160819: Remove spic(4)

View file

@ -60,7 +60,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
${_libgssapi} \
${_librpcsec_gss} \
${_libiconv_modules} \
libifc \
libifconfig \
libipsec \
libjail \
libkiconv \

View file

@ -36,72 +36,72 @@ __FBSDID("$FreeBSD$");
#include <signal.h>
const char *const sys_signame[NSIG] = {
"Signal 0",
"HUP", /* SIGHUP */
"INT", /* SIGINT */
"QUIT", /* SIGQUIT */
"ILL", /* SIGILL */
"TRAP", /* SIGTRAP */
"ABRT", /* SIGABRT */
"EMT", /* SIGEMT */
"FPE", /* SIGFPE */
"KILL", /* SIGKILL */
"BUS", /* SIGBUS */
"SEGV", /* SIGSEGV */
"SYS", /* SIGSYS */
"PIPE", /* SIGPIPE */
"ALRM", /* SIGALRM */
"TERM", /* SIGTERM */
"URG", /* SIGURG */
"STOP", /* SIGSTOP */
"TSTP", /* SIGTSTP */
"CONT", /* SIGCONT */
"CHLD", /* SIGCHLD */
"TTIN", /* SIGTTIN */
"TTOU", /* SIGTTOU */
"IO", /* SIGIO */
"XCPU", /* SIGXCPU */
"XFSZ", /* SIGXFSZ */
"VTALRM", /* SIGVTALRM */
"PROF", /* SIGPROF */
"WINCH", /* SIGWINCH */
"INFO", /* SIGINFO */
"USR1", /* SIGUSR1 */
"USR2" /* SIGUSR2 */
[0] = "Signal 0",
[SIGHUP] = "HUP",
[SIGINT] = "INT",
[SIGQUIT] = "QUIT",
[SIGILL] = "ILL",
[SIGTRAP] = "TRAP",
[SIGABRT] = "ABRT",
[SIGEMT] = "EMT",
[SIGFPE] = "FPE",
[SIGKILL] = "KILL",
[SIGBUS] = "BUS",
[SIGSEGV] = "SEGV",
[SIGSYS] = "SYS",
[SIGPIPE] = "PIPE",
[SIGALRM] = "ALRM",
[SIGTERM] = "TERM",
[SIGURG] = "URG",
[SIGSTOP] = "STOP",
[SIGTSTP] = "TSTP",
[SIGCONT] = "CONT",
[SIGCHLD] = "CHLD",
[SIGTTIN] = "TTIN",
[SIGTTOU] = "TTOU",
[SIGIO] = "IO",
[SIGXCPU] = "XCPU",
[SIGXFSZ] = "XFSZ",
[SIGVTALRM] = "VTALRM",
[SIGPROF] = "PROF",
[SIGWINCH] = "WINCH",
[SIGINFO] = "INFO",
[SIGUSR1] = "USR1",
[SIGUSR2] = "USR2",
};
const char *const sys_siglist[NSIG] = {
"Signal 0",
"Hangup", /* SIGHUP */
"Interrupt", /* SIGINT */
"Quit", /* SIGQUIT */
"Illegal instruction", /* SIGILL */
"Trace/BPT trap", /* SIGTRAP */
"Abort trap", /* SIGABRT */
"EMT trap", /* SIGEMT */
"Floating point exception", /* SIGFPE */
"Killed", /* SIGKILL */
"Bus error", /* SIGBUS */
"Segmentation fault", /* SIGSEGV */
"Bad system call", /* SIGSYS */
"Broken pipe", /* SIGPIPE */
"Alarm clock", /* SIGALRM */
"Terminated", /* SIGTERM */
"Urgent I/O condition", /* SIGURG */
"Suspended (signal)", /* SIGSTOP */
"Suspended", /* SIGTSTP */
"Continued", /* SIGCONT */
"Child exited", /* SIGCHLD */
"Stopped (tty input)", /* SIGTTIN */
"Stopped (tty output)", /* SIGTTOU */
"I/O possible", /* SIGIO */
"Cputime limit exceeded", /* SIGXCPU */
"Filesize limit exceeded", /* SIGXFSZ */
"Virtual timer expired", /* SIGVTALRM */
"Profiling timer expired", /* SIGPROF */
"Window size changes", /* SIGWINCH */
"Information request", /* SIGINFO */
"User defined signal 1", /* SIGUSR1 */
"User defined signal 2" /* SIGUSR2 */
[0] = "Signal 0",
[SIGHUP] = "Hangup",
[SIGINT] = "Interrupt",
[SIGQUIT] = "Quit",
[SIGILL] = "Illegal instruction",
[SIGTRAP] = "Trace/BPT trap",
[SIGABRT] = "Abort trap",
[SIGEMT] = "EMT trap",
[SIGFPE] = "Floating point exception",
[SIGKILL] = "Killed",
[SIGBUS] = "Bus error",
[SIGSEGV] = "Segmentation fault",
[SIGSYS] = "Bad system call",
[SIGPIPE] = "Broken pipe",
[SIGALRM] = "Alarm clock",
[SIGTERM] = "Terminated",
[SIGURG] = "Urgent I/O condition",
[SIGSTOP] = "Suspended (signal)",
[SIGTSTP] = "Suspended",
[SIGCONT] = "Continued",
[SIGCHLD] = "Child exited",
[SIGTTIN] = "Stopped (tty input)",
[SIGTTOU] = "Stopped (tty output)",
[SIGIO] = "I/O possible",
[SIGXCPU] = "Cputime limit exceeded",
[SIGXFSZ] = "Filesize limit exceeded",
[SIGVTALRM] = "Virtual timer expired",
[SIGPROF] = "Profiling timer expired",
[SIGWINCH] = "Window size changes",
[SIGINFO] = "Information request",
[SIGUSR1] = "User defined signal 1",
[SIGUSR2] = "User defined signal 2",
};
const int sys_nsig = sizeof(sys_siglist) / sizeof(sys_siglist[0]);

View file

@ -47,11 +47,16 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
{
wint_t wc;
size_t len;
int savserr;
FIX_LOCALE(locale);
FLOCKFILE(fp);
ORIENT(fp, 1);
savserr = fp->_flags & __SERR;
fp->_flags &= ~__SERR;
len = 0;
while ((wc = __fgetwc(fp, locale)) != WEOF) {
#define GROW 512
@ -64,7 +69,12 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
if (wc == L'\n')
break;
}
if (len == 0 || (wc == WEOF && !__sfeof(fp)))
/* fgetwc(3) may set both __SEOF and __SERR at once. */
if (__sferror(fp))
goto error;
fp->_flags |= savserr;
if (len == 0)
goto error;
FUNLOCKFILE(fp);

View file

@ -1,18 +1,18 @@
# $FreeBSD$
PACKAGE= lib${LIB}
LIB= ifc
LIB= ifconfig
# Don't build shared library, for now.
NO_PIC=
SHLIBDIR?= /lib
SHLIB_MAJOR= 1
SRCS= libifc.c libifc_internal.c
SRCS= libifconfig.c libifconfig_internal.c
INCSDIR= ${INCLUDEDIR}
INCS= libifc.h
INCS= libifconfig.h
#MAN= libifco.3
#MAN= libifconfig.3
CFLAGS+= -I${.CURDIR}
WARNS?=6

View file

@ -71,16 +71,16 @@
#include <string.h>
#include <unistd.h>
#include "libifc.h"
#include "libifc_internal.h"
#include "libifconfig.h"
#include "libifconfig_internal.h"
libifc_handle_t *
libifc_open(void)
ifconfig_handle_t *
ifconfig_open(void)
{
struct libifc_handle *h;
struct ifconfig_handle *h;
h = calloc(1, sizeof(struct libifc_handle));
h = calloc(1, sizeof(struct ifconfig_handle));
for (int i = 0; i <= AF_MAX; i++) {
h->sockets[i] = -1;
@ -91,7 +91,7 @@ libifc_open(void)
void
libifc_close(libifc_handle_t *h)
ifconfig_close(ifconfig_handle_t *h)
{
for (int i = 0; i <= AF_MAX; i++) {
if (h->sockets[i] != -1) {
@ -102,29 +102,29 @@ libifc_close(libifc_handle_t *h)
}
libifc_errtype
libifc_err_errtype(libifc_handle_t *h)
ifconfig_errtype
ifconfig_err_errtype(ifconfig_handle_t *h)
{
return (h->error.errtype);
}
int
libifc_err_errno(libifc_handle_t *h)
ifconfig_err_errno(ifconfig_handle_t *h)
{
return (h->error.errcode);
}
unsigned long
libifc_err_ioctlreq(libifc_handle_t *h)
ifconfig_err_ioctlreq(ifconfig_handle_t *h)
{
return (h->error.ioctl_request);
}
int
libifc_get_description(libifc_handle_t *h, const char *name, char **description)
ifconfig_get_description(ifconfig_handle_t *h, const char *name, char **description)
{
struct ifreq ifr;
char *descr = NULL;
@ -141,7 +141,7 @@ libifc_get_description(libifc_handle_t *h, const char *name, char **description)
ifr.ifr_buffer.buffer = descr;
ifr.ifr_buffer.length = descrlen;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFDESCR,
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDESCR,
&ifr) != 0) {
return (-1);
}
@ -166,7 +166,7 @@ libifc_get_description(libifc_handle_t *h, const char *name, char **description)
int
libifc_set_description(libifc_handle_t *h, const char *name,
ifconfig_set_description(ifconfig_handle_t *h, const char *name,
const char *newdescription)
{
struct ifreq ifr;
@ -180,7 +180,7 @@ libifc_set_description(libifc_handle_t *h, const char *name,
* TODO: Decide whether this should be an error condition instead.
*/
if (desclen == 0) {
return (libifc_unset_description(h, name));
return (ifconfig_unset_description(h, name));
}
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
@ -193,7 +193,7 @@ libifc_set_description(libifc_handle_t *h, const char *name,
return (-1);
}
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) != 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) != 0) {
free(ifr.ifr_buffer.buffer);
return (-1);
}
@ -202,7 +202,7 @@ libifc_set_description(libifc_handle_t *h, const char *name,
}
int libifc_unset_description(libifc_handle_t *h, const char *name)
int ifconfig_unset_description(ifconfig_handle_t *h, const char *name)
{
struct ifreq ifr;
@ -211,14 +211,14 @@ int libifc_unset_description(libifc_handle_t *h, const char *name)
ifr.ifr_buffer.length = 0;
ifr.ifr_buffer.buffer = NULL;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) < 0) {
return (-1);
}
return (0);
}
int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname)
int ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname)
{
struct ifreq ifr;
char *tmpname;
@ -234,7 +234,7 @@ int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname)
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_data = tmpname;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME, &ifr) != 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME, &ifr) != 0) {
free(tmpname);
return (-1);
}
@ -243,27 +243,27 @@ int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname)
}
int libifc_set_mtu(libifc_handle_t *h, const char *name, const int mtu)
int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU, &ifr) < 0) {
return (-1);
}
return (0);
}
int libifc_get_mtu(libifc_handle_t *h, const char *name, int *mtu)
int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU, &ifr) == -1) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU, &ifr) == -1) {
return (-1);
}
*mtu = ifr.ifr_mtu;
@ -271,27 +271,27 @@ int libifc_get_mtu(libifc_handle_t *h, const char *name, int *mtu)
}
int libifc_set_metric(libifc_handle_t *h, const char *name, const int mtu)
int ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int mtu)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC, &ifr) < 0) {
return (-1);
}
return (0);
}
int libifc_get_metric(libifc_handle_t *h, const char *name, int *metric)
int ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC, &ifr) == -1) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC, &ifr) == -1) {
return (-1);
}
*metric = ifr.ifr_metric;
@ -299,16 +299,16 @@ int libifc_get_metric(libifc_handle_t *h, const char *name, int *metric)
}
int libifc_set_capability(libifc_handle_t *h, const char *name,
int ifconfig_set_capability(ifconfig_handle_t *h, const char *name,
const int capability)
{
struct ifreq ifr;
struct libifc_capabilities ifcap;
struct ifconfig_capabilities ifcap;
int flags;
int value;
memset(&ifr, 0, sizeof(struct ifreq));
if (libifc_get_capability(h, name, &ifcap) != 0) {
if (ifconfig_get_capability(h, name, &ifcap) != 0) {
return (-1);
}
@ -329,22 +329,22 @@ int libifc_set_capability(libifc_handle_t *h, const char *name,
* set for this request.
*/
ifr.ifr_reqcap = flags;
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP, &ifr) < 0) {
return (-1);
}
return (0);
}
int libifc_get_capability(libifc_handle_t *h, const char *name,
struct libifc_capabilities *capability)
int ifconfig_get_capability(ifconfig_handle_t *h, const char *name,
struct ifconfig_capabilities *capability)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP, &ifr) < 0) {
return (-1);
}
capability->curcap = ifr.ifr_curcap;
@ -353,21 +353,21 @@ int libifc_get_capability(libifc_handle_t *h, const char *name,
}
int libifc_destroy_interface(libifc_handle_t *h, const char *name)
int ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY, &ifr) < 0) {
return (-1);
}
return (0);
}
int libifc_create_interface(libifc_handle_t *h, const char *name, char **ifname)
int ifconfig_create_interface(ifconfig_handle_t *h, const char *name, char **ifname)
{
struct ifreq ifr;
@ -389,7 +389,7 @@ int libifc_create_interface(libifc_handle_t *h, const char *name, char **ifname)
/* No special handling for this interface type. */
if (libifc_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
return (-1);
}
*ifname = strdup(ifr.ifr_name);

View file

@ -34,16 +34,16 @@
typedef enum {
OTHER, IOCTL, SOCKET
} libifc_errtype;
} ifconfig_errtype;
/*
* Opaque definition so calling application can just pass a
* pointer to it for library use.
*/
struct libifc_handle;
typedef struct libifc_handle libifc_handle_t;
struct ifconfig_handle;
typedef struct ifconfig_handle ifconfig_handle_t;
struct libifc_capabilities {
struct ifconfig_capabilities {
/** Current capabilities (ifconfig prints this as 'options')*/
int curcap;
/** Requested capabilities (ifconfig prints this as 'capabilities')*/
@ -55,57 +55,57 @@ struct libifc_capabilities {
* Example usage:
*{@code
* // Create state object
* libifc_handle_t *lifh = libifc_open();
* ifconfig_handle_t *lifh = ifconfig_open();
*
* // Do stuff with it
*
* // Dispose of the state object
* libifc_close(lifh);
* ifconfig_close(lifh);
* lifh = NULL;
*}
*/
libifc_handle_t *libifc_open(void);
ifconfig_handle_t *ifconfig_open(void);
/** Frees resources held in the provided state object.
* @param h The state object to close.
* @see #libifc_open(void)
* @see #ifconfig_open(void)
*/
void libifc_close(libifc_handle_t *h);
void ifconfig_close(ifconfig_handle_t *h);
/** Identifies what kind of error occured. */
libifc_errtype libifc_err_errtype(libifc_handle_t *h);
ifconfig_errtype ifconfig_err_errtype(ifconfig_handle_t *h);
/** Retrieves the errno associated with the error, if any. */
int libifc_err_errno(libifc_handle_t *h);
int ifconfig_err_errno(ifconfig_handle_t *h);
/** If error type was IOCTL, this identifies which request failed. */
unsigned long libifc_err_ioctlreq(libifc_handle_t *h);
unsigned long ifconfig_err_ioctlreq(ifconfig_handle_t *h);
int libifc_get_description(libifc_handle_t *h, const char *name,
int ifconfig_get_description(ifconfig_handle_t *h, const char *name,
char **description);
int libifc_set_description(libifc_handle_t *h, const char *name,
int ifconfig_set_description(ifconfig_handle_t *h, const char *name,
const char *newdescription);
int libifc_unset_description(libifc_handle_t *h, const char *name);
int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname);
int libifc_set_mtu(libifc_handle_t *h, const char *name, const int mtu);
int libifc_get_mtu(libifc_handle_t *h, const char *name, int *mtu);
int ifconfig_unset_description(ifconfig_handle_t *h, const char *name);
int ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname);
int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu);
int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu);
int libifc_set_metric(libifc_handle_t *h, const char *name, const int metric);
int libifc_get_metric(libifc_handle_t *h, const char *name, int *metric);
int ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int metric);
int ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric);
int libifc_set_capability(libifc_handle_t *h, const char *name,
int ifconfig_set_capability(ifconfig_handle_t *h, const char *name,
const int capability);
int libifc_get_capability(libifc_handle_t *h, const char *name,
struct libifc_capabilities *capability);
int ifconfig_get_capability(ifconfig_handle_t *h, const char *name,
struct ifconfig_capabilities *capability);
/** Destroy a virtual interface
* @param name Interface to destroy
*/
int libifc_destroy_interface(libifc_handle_t *h, const char *name);
int ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name);
/** Creates a (virtual) interface
* @param name Name of interface to create. Example: bridge or bridge42
* @param name ifname Is set to actual name of created interface
*/
int libifc_create_interface(libifc_handle_t *h, const char *name,
int ifconfig_create_interface(ifconfig_handle_t *h, const char *name,
char **ifname);

View file

@ -40,11 +40,11 @@
#include <unistd.h>
#include "libifc.h" // Needed for libifc_errstate
#include "libifc_internal.h"
#include "libifconfig.h" // Needed for ifconfig_errstate
#include "libifconfig_internal.h"
int
libifc_ioctlwrap_ret(libifc_handle_t *h, unsigned long request, int rcode)
ifconfig_ioctlwrap_ret(ifconfig_handle_t *h, unsigned long request, int rcode)
{
if (rcode != 0) {
h->error.errtype = IOCTL;
@ -56,17 +56,17 @@ libifc_ioctlwrap_ret(libifc_handle_t *h, unsigned long request, int rcode)
int
libifc_ioctlwrap(libifc_handle_t *h, const int addressfamily,
ifconfig_ioctlwrap(ifconfig_handle_t *h, const int addressfamily,
unsigned long request, struct ifreq *ifr)
{
int s;
if (libifc_socket(h, addressfamily, &s) != 0) {
if (ifconfig_socket(h, addressfamily, &s) != 0) {
return (-1);
}
int rcode = ioctl(s, request, ifr);
return (libifc_ioctlwrap_ret(h, request, rcode));
return (ifconfig_ioctlwrap_ret(h, request, rcode));
}
@ -74,7 +74,7 @@ libifc_ioctlwrap(libifc_handle_t *h, const int addressfamily,
* Function to get socket for the specified address family.
* If the socket doesn't already exist, attempt to create it.
*/
int libifc_socket(libifc_handle_t *h, const int addressfamily, int *s)
int ifconfig_socket(ifconfig_handle_t *h, const int addressfamily, int *s)
{
if (addressfamily > AF_MAX) {
h->error.errtype = SOCKET;

View file

@ -32,14 +32,14 @@
#pragma once
#include "libifc.h"
#include "libifconfig.h"
struct errstate {
/**
* Type of error.
*/
libifc_errtype errtype;
ifconfig_errtype errtype;
/**
* The error occured in this ioctl() request.
@ -53,7 +53,7 @@ struct errstate {
int errcode;
};
struct libifc_handle {
struct ifconfig_handle {
struct errstate error;
int sockets[AF_MAX + 1];
};
@ -69,7 +69,7 @@ struct libifc_handle {
* {@code
* static void myfunc() \{
* int s;
* if (libifc_socket(AF_LOCAL, &s) != 0) \{
* if (ifconfig_socket(AF_LOCAL, &s) != 0) \{
* // Handle error state here
* \}
* // user code here
@ -77,11 +77,11 @@ struct libifc_handle {
* }
* }
*/
int libifc_socket(libifc_handle_t *h, const int addressfamily, int *s);
int ifconfig_socket(ifconfig_handle_t *h, const int addressfamily, int *s);
/** Function used by other wrapper functions to populate _errstate when appropriate.*/
int libifc_ioctlwrap_ret(libifc_handle_t *h, unsigned long request, int rcode);
int ifconfig_ioctlwrap_ret(ifconfig_handle_t *h, unsigned long request, int rcode);
/** Function to wrap ioctl() and automatically populate libifc_errstate when appropriate.*/
int libifc_ioctlwrap(libifc_handle_t *h, const int addressfamily,
/** Function to wrap ioctl() and automatically populate ifconfig_errstate when appropriate.*/
int ifconfig_ioctlwrap(ifconfig_handle_t *h, const int addressfamily,
unsigned long request, struct ifreq *ifr);

View file

@ -176,6 +176,12 @@ libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
return (LIBUSB20_ERROR_BUSY);
if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) {
MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE;
/*
* The kernel can setup 8 times more frames when
* pre-scaling ISOCHRONOUS transfers. Make sure the
* length and pointer buffers are big enough:
*/
MaxFrameCount *= 8;
pre_scale = 1;
} else {
pre_scale = 0;
@ -200,8 +206,13 @@ libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
}
memset(xfer->ppBuffer, 0, size);
error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
MaxFrameCount, ep_no, stream_id, pre_scale);
if (pre_scale) {
error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
MaxFrameCount / 8, ep_no, stream_id, 1);
} else {
error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
MaxFrameCount, ep_no, stream_id, 0);
}
if (error) {
free(xfer->ppBuffer);

View file

@ -427,7 +427,6 @@ test_large(void)
test_odd_tol(ctanh, z,
CMPLXL(1.0, 8.95257245135025991216632140458264468e-309L),
DBL_ULP());
#if !defined(__i386__)
z = CMPLXL(30, 0x1p1023L);
test_odd_tol(ctanh, z,
CMPLXL(1.0, -1.62994325413993477997492170229268382e-26L),
@ -437,7 +436,6 @@ test_large(void)
CMPLXL(0.878606311888306869546254022621986509L,
-0.225462792499754505792678258169527424L),
DBL_ULP());
#endif
z = CMPLXL(710.6, 0.78539816339744830961566084581987572L);
test_odd_tol(csinh, z,
@ -475,8 +473,12 @@ main(int argc, char *argv[])
test_small();
printf("ok 5 - ctrig small\n");
#if defined(__i386__)
printf("ok 6 # SKIP ctrig large # fails on i386 because of bug 205446\n");
#else
test_large();
printf("ok 6 - ctrig large\n");
#endif
return (0);
}

View file

@ -1098,9 +1098,6 @@
<para>[&arch.i386;] STB 4 port card using shared IRQ</para>
<para>[&arch.i386;] DigiBoard intelligent serial cards (digi
driver)</para>
<para>[&arch.amd64;, &arch.i386;] PCI-Based multi-port serial
boards (&man.puc.4; driver)</para>

View file

@ -52,6 +52,7 @@ DIRDEPS = \
usr.bin/lex/lib \
usr.bin/yacc.host \
usr.sbin/crunch/crunchgen.host \
usr.sbin/crunch/crunchide.host \
.include <dirdeps.mk>

View file

@ -1,9 +0,0 @@
# $FreeBSD$
default:
$(CC) -Wall -fPIC -lifc -g -o example_setdescription setdescription.c
$(CC) -Wall -fPIC -lifc -g -o example_setmtu setmtu.c
$(CC) -Wall -fPIC -lifc -g -o example_ifdestroy ifdestroy.c
$(CC) -Wall -fPIC -lifc -g -o example_ifcreate ifcreate.c
clean:
rm -f example_*

View file

@ -0,0 +1,8 @@
# $FreeBSD$
default:
$(CC) -Wall -fPIC -lifconfig -g -o example_setdescription setdescription.c
$(CC) -Wall -fPIC -lifconfig -g -o example_setmtu setmtu.c
$(CC) -Wall -fPIC -lifconfig -g -o example_ifdestroy ifdestroy.c
$(CC) -Wall -fPIC -lifconfig -g -o example_ifcreate ifcreate.c
clean:
rm -f example_*

View file

@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libifc.h>
#include <libifconfig.h>
int main(int argc, char *argv[])
@ -55,21 +55,21 @@ int main(int argc, char *argv[])
printf("Requested interface name: %s\n", ifname);
libifc_handle_t *lifh = libifc_open();
if (libifc_create_interface(lifh, ifname, &ifactualname) == 0) {
ifconfig_handle_t *lifh = ifconfig_open();
if (ifconfig_create_interface(lifh, ifname, &ifactualname) == 0) {
printf("Successfully created interface '%s'\n", ifactualname);
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
free(ifactualname);
return (0);
} else {
switch (libifc_err_errtype(lifh)) {
switch (ifconfig_err_errtype(lifh)) {
case SOCKET:
warnx("couldn't create socket. This shouldn't happen.\n");
break;
case IOCTL:
if (libifc_err_ioctlreq(lifh) == SIOCIFCREATE2) {
if (ifconfig_err_ioctlreq(lifh) == SIOCIFCREATE2) {
warnx(
"Failed to create interface (SIOCIFCREATE2)\n");
}
@ -79,12 +79,12 @@ int main(int argc, char *argv[])
"This is a thorough example accommodating for temporary"
" 'not implemented yet' errors. That's likely what happened"
" now. If not, your guess is as good as mine. ;)"
" Error code: %d\n", libifc_err_errno(
" Error code: %d\n", ifconfig_err_errno(
lifh));
break;
}
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
free(ifactualname);

View file

@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libifc.h>
#include <libifconfig.h>
int main(int argc, char *argv[])
@ -55,20 +55,20 @@ int main(int argc, char *argv[])
printf("Interface name: %s\n", ifname);
libifc_handle_t *lifh = libifc_open();
if (libifc_destroy_interface(lifh, ifname) == 0) {
ifconfig_handle_t *lifh = ifconfig_open();
if (ifconfig_destroy_interface(lifh, ifname) == 0) {
printf("Successfully destroyed interface '%s'.", ifname);
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
return (0);
} else {
switch (libifc_err_errtype(lifh)) {
switch (ifconfig_err_errtype(lifh)) {
case SOCKET:
warnx("couldn't create socket. This shouldn't happen.\n");
break;
case IOCTL:
if (libifc_err_ioctlreq(lifh) == SIOCIFDESTROY) {
if (ifconfig_err_ioctlreq(lifh) == SIOCIFDESTROY) {
warnx(
"Failed to destroy interface (SIOCIFDESTROY)\n");
}
@ -79,7 +79,7 @@ int main(int argc, char *argv[])
break;
}
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
return (-1);

View file

@ -35,7 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libifc.h>
#include <libifconfig.h>
int main(int argc, char *argv[])
@ -54,27 +54,27 @@ int main(int argc, char *argv[])
printf("Interface name: %s\n", ifname);
libifc_handle_t *lifh = libifc_open();
if (libifc_get_description(lifh, ifname, &curdescr) == 0) {
ifconfig_handle_t *lifh = ifconfig_open();
if (ifconfig_get_description(lifh, ifname, &curdescr) == 0) {
printf("Old description: %s\n", curdescr);
}
printf("New description: %s\n\n", ifdescr);
if (libifc_set_description(lifh, ifname, ifdescr) == 0) {
if (ifconfig_set_description(lifh, ifname, ifdescr) == 0) {
printf("New description successfully set.\n");
} else {
switch (libifc_err_errtype(lifh)) {
switch (ifconfig_err_errtype(lifh)) {
case SOCKET:
err(libifc_err_errno(lifh), "Socket error");
err(ifconfig_err_errno(lifh), "Socket error");
break;
case IOCTL:
err(libifc_err_errno(
err(ifconfig_err_errno(
lifh), "IOCTL(%lu) error",
libifc_err_ioctlreq(lifh));
ifconfig_err_ioctlreq(lifh));
break;
case OTHER:
err(libifc_err_errno(lifh), "Other error");
err(ifconfig_err_errno(lifh), "Other error");
break;
}
}
@ -86,6 +86,6 @@ int main(int argc, char *argv[])
ifdescr = NULL;
curdescr = NULL;
libifc_close(lifh);
ifconfig_close(lifh);
return (0);
}

View file

@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libifc.h>
#include <libifconfig.h>
int main(int argc, char *argv[])
@ -58,26 +58,26 @@ int main(int argc, char *argv[])
printf("Interface name: %s\n", ifname);
printf("New MTU: %d", mtu);
libifc_handle_t *lifh = libifc_open();
if (libifc_set_mtu(lifh, ifname, mtu) == 0) {
ifconfig_handle_t *lifh = ifconfig_open();
if (ifconfig_set_mtu(lifh, ifname, mtu) == 0) {
printf("Successfully changed MTU of %s to %d\n", ifname, mtu);
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
return (0);
} else {
switch (libifc_err_errtype(lifh)) {
switch (ifconfig_err_errtype(lifh)) {
case SOCKET:
warnx("couldn't create socket. This shouldn't happen.\n");
break;
case IOCTL:
if (libifc_err_ioctlreq(lifh) == SIOCSIFMTU) {
if (ifconfig_err_ioctlreq(lifh) == SIOCSIFMTU) {
warnx("Failed to set MTU (SIOCSIFMTU)\n");
} else {
warnx(
"Failed to set MTU due to error in unexpected ioctl() call %lu. Error code: %i.\n",
libifc_err_ioctlreq(lifh),
libifc_err_errno(lifh));
ifconfig_err_ioctlreq(lifh),
ifconfig_err_errno(lifh));
}
break;
default:
@ -86,7 +86,7 @@ int main(int argc, char *argv[])
break;
}
libifc_close(lifh);
ifconfig_close(lifh);
lifh = NULL;
free(ifname);
return (-1);

View file

@ -122,7 +122,6 @@ MAN= aac.4 \
ddb.4 \
de.4 \
devctl.4 \
digi.4 \
disc.4 \
divert.4 \
${_dpms.4} \

View file

@ -1,377 +0,0 @@
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Systems Programming Group of the University of Utah Computer
.\" Science Department.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)dca.4 5.2 (Berkeley) 3/27/91
.\" from: com.4,v 1.1 1993/08/06 11:19:07 cgd Exp
.\" from: sio.4,v 1.15 1994/12/06 20:14:30 bde Exp
.\" $FreeBSD$
.\"
.Dd December 7, 2003
.Dt DIGI 4
.Os
.Sh NAME
.Nm digi
.Nd DigiBoard intelligent serial cards driver
.Sh SYNOPSIS
.Cd "device digi"
.Pp
This man page was originally written for the dgb driver, and should
likely be gone over with a fine tooth comb to reflect differences
with the digi driver.
.Pp
When not defined the number is computed:
.Bd -ragged -offset 4n
default
.Dv NDGBPORTS
= number_of_described_DigiBoard_cards * 16
.Ed
.Pp
If it is less than the actual number of ports
the system will be able to use only the
first
.Dv NDGBPORTS
ports.
If it is greater then all ports will be usable
but some memory will be wasted.
.Pp
Meaning of
.Cm flags :
.Bl -tag -width indent -compact
.It 0x0001
use alternate pinout (exchange DCD and DSR lines)
.It 0x0002
do not use 8K window mode of PC/Xe
.El
.Pp
Device numbering:
.Bd -literal -compact
0b\fICC\fPmmmmmmmm\fIOLIPPPPP\fP
\fBCC\fPard number
\fRmmmmmmmm\fPajor number
call\fBO\fPut
\fBL\fPock
\fBI\fPnitial
\fBPPPPP\fPort number
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for DigiBoard PC/Xe and PC/Xi series intelligent
serial multiport cards with asynchronous interfaces based on the
.Tn EIA
.Tn RS-232C
.Pf ( Tn CCITT
.Tn V.24 )
standard.
.Pp
Input and output for each line may set to one of following baud rates;
50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, 4800, 9600,
19200, 38400, 57600, or for newer versions of cards 115200.
.Pp
The driver does not use any interrupts, it is
.Dq polling-based .
This means that
it uses clock interrupts instead of interrupts generated by DigiBoard cards and
checks the state of cards 25 times per second.
This is practical because the
DigiBoard cards have large input and output buffers (more than 1Kbyte per
port) and hardware that allows efficiently finding the port that needs
attention.
The only problem seen with this policy is slower
SLIP and PPP response.
.Pp
Each line in the kernel configuration file describes one card, not one port
as in the
.Xr sio 4
driver.
.Pp
The
.Cm flags
keyword may be used on each
.Dq Li "device dgb"
line in the kernel configuration file
to change the pinout of the interface or to use new PC/Xe cards
which can work with an 8K memory window in compatibility mode
(with a 64K memory window).
Note
that using 8K memory window does not mean shorter input/output buffers, it means
only that all buffers will be mapped to the same memory address and switched as
needed.
.Pp
The
.Cm port
value must be the same
as the
port
set on the card by jumpers.
For PC/Xi cards the same rule is applicable to the
.Cm iomem
value.
It must be the same as the memory address set on the card
by jumpers.
.\"Some documentation gives the address as a ``paragraph'' or ``segment'';
.\"you can get the value of address by adding the digit "0" at end of
.\"paragraph value, e.g., 0xfc000 -> 0xfc0000.
For PC/Xe cards there is no need to use jumpers for this purpose.
In fact there are no jumpers to do it.
Just
write the address you want as the
.Cm iomem
value in kernel config file and the card will be programmed
to use this address.
.Pp
The same range of memory addresses may be used
for all the DigiBoards installed
(but not for any other card or real memory).
DigiBoards
with a large amount of memory (256K or 512K and perhaps
even 128K) must be mapped
to memory addresses outside of the first megabyte.
If the computer
has more than 15 megabytes of memory then there is no free address space
outside of the first megabyte where such DigiBoards can be mapped.
In this case you
may need to reduce the amount of memory in the computer.
But many machines provide a better solution.
They have the ability to
.Dq "turn off"
the memory in the 16th megabyte (addresses 0xF00000 - 0xFFFFFF)
using the
BIOS setup.
Then the DigiBoard's address space can be set to this
.Dq hole .
.\" XXX the following should be true for all serial drivers and
.\" should not be repeated in the man pages for all serial drivers.
.\" It was copied from sio.4. The only changes were s/sio/dgb/g.
.Pp
Serial ports controlled by the
.Nm
driver can be used for both
.Dq callin
and
.Dq callout .
For each port there is a callin device and a callout device.
The minor number of the callout device is 128 higher
than that of the corresponding callin port.
The callin device is general purpose.
Processes opening it normally wait for carrier
and for the callout device to become inactive.
The callout device is used to steal the port from
processes waiting for carrier on the callin device.
Processes opening it do not wait for carrier
and put any processes waiting for carrier on the callin device into
a deeper sleep so that they do not conflict with the callout session.
The callout device is abused for handling programs that are supposed
to work on general ports and need to open the port without waiting
but are too stupid to do so.
.Pp
The
.Nm
driver also supports an initial-state and a lock-state control
device for each of the callin and the callout
.Dq data
devices.
The minor number of the initial-state device is 32 higher
than that of the corresponding data device.
The minor number of the lock-state device is 64 higher
than that of the corresponding data device.
The termios settings of a data device are copied
from those of the corresponding initial-state device
on first opens and are not inherited from previous opens.
Use
.Xr stty 1
in the normal way on the initial-state devices to program
initial termios states suitable for your setup.
.Pp
The lock termios state acts as flags to disable changing
the termios state.
E.g., to lock a flag variable such as
.Dv CRTSCTS ,
use
.Dq Li "stty crtscts"
on the lock-state device.
Speeds and special characters
may be locked by setting the corresponding value in the lock-state
device to any nonzero value.
.Pp
Correct programs talking to correctly wired external devices
.\" XXX change next line in other man pages too, and rewrite this paragraph.
work with almost arbitrary initial states and no locking,
but other setups may benefit from changing some of the default
initial state and locking the state.
In particular, the initial states for non (POSIX) standard flags
should be set to suit the devices attached and may need to be
locked to prevent buggy programs from changing them.
E.g.,
.Dv CRTSCTS
should be locked on for devices that support
RTS/CTS handshaking at all times and off for devices that do not
support it at all.
.Dv CLOCAL
should be locked on for devices
that do not support carrier.
.Dv HUPCL
may be locked off if you do not
want to hang up for some reason.
In general, very bad things happen
if something is locked to the wrong state, and things should not
be locked for devices that support more than one setting.
The
.Dv CLOCAL
flag on callin ports should be locked off for logins
to avoid certain security holes, but this needs to be done by
getty if the callin port is used for anything else.
.Sh FILES
.Bl -tag -width /dev/ttyiD?? -compact
.It Pa /dev/ttyD??
for callin ports
.It Pa /dev/ttyiD??
.It Pa /dev/ttylD??
corresponding callin initial-state and lock-state devices
.Pp
.It Pa /dev/cuaD??
for callout ports
.It Pa /dev/cuaiD??
.It Pa /dev/cualD??
corresponding callout initial-state and lock-state devices
.El
.Pp
.Bl -tag -width /etc/rc.serial -compact
.It Pa /etc/rc.serial
examples of setting the initial-state and lock-state devices
.El
.Pp
The first question mark in these device names is short for the
card number
(a decimal number between 0 and 65535 inclusive).
The second question mark is short for the port number
(a letter in the range [0-9a-v]).
.Sh DIAGNOSTICS
You may enable extended diagnostics by defining DEBUG at the
start of the source file
.Pa dgb.c .
.Bl -diag
.It dgb\fIX\fP: warning: address \fIN\fP truncated to \fIM\fP
The memory address for the PC/Xe's 8K window is misaligned (it should be
on an 8K boundary) or outside of the first megabyte.
.It dgb\fIX\fP: 1st reset failed
Problems with accessing I/O port of the card, probably
the wrong
.Cm port
value is specified in the kernel config file.
.It dgb\fIX\fP: 2nd reset failed
Problems with hardware.
.It dgb\fIX\fP: \fIN\fP[st,nd,rd,th] memory test failed
Problems with accessing the memory of the card, probably
the wrong
.Cm iomem
value is specified in the kernel config file.
.It dgb\fIX\fP: BIOS start failed
Problems with starting the on-board BIOS.
Probably the memory addresses of the
DigiBoard overlap with some other device or with RAM.
.It dgb\fIX\fP: BIOS download failed
Problems with the on-board BIOS.
Probably the memory addresses of the
DigiBoard overlap with some other device or with RAM.
.It dgb\fIX\fP: FEP code download failed
Problems with downloading of the Front-End Processor's micro-OS.
Probably the memory addresses of the
DigiBoard overlap with some other device or with RAM.
.It dgb\fIX\fP: FEP/OS start failed
Problems with starting of the Front-End Processor's micro-OS.
Probably the memory addresses of the
DigiBoard overlap with some other device or with RAM.
.It dgb\fIX\fP: too many ports
This DigiBoard reports that it has more than 32 ports.
Perhaps a hardware problem or
the memory addresses of the
DigiBoard overlap with some other device or with RAM.
.It dgb\fIX\fP: only \fIN\fP ports are usable
The
.Dv NDGBPORTS
parameter is too small and there is only enough space allocated
for
.Ar N
ports on this card.
.It dgb\fIX\fP: port \fIY\fP is broken
The on-board diagnostic has reported that the specified port has hardware
problems.
.It dgb\fIX\fP: polling of disabled board stopped
Internal problems in the polling logic of driver.
.It dgb\fIX\fP: event queue's head or tail is wrong!
Internal problems in the driver or hardware.
.It dgb\fIX\fP: port \fIY\fP: got event on nonexisting port
Some status changed on a port that is physically present but is
unusable due to misconfiguration.
.It dgb\fIX\fP: port \fIY\fP: event \fIN\fP mstat \fIM\fP lstat \fIK\fP
The driver got a strange event from card.
Probably this means that you have a
newer card with an extended list of events or some other hardware problem.
.It dgb\fIX\fP: port \fIY\fP: overrun
Input buffer has filled up.
Problems in polling logic of driver.
.It dgb\fIX\fP: port \fIY\fP: FEP command on disabled port
Internal problems in driver.
.It dgb\fIX\fP: port \fIY\fP: timeout on FEP command
Problems in hardware.
.El
.Sh SEE ALSO
.Xr stty 1 ,
.Xr termios 4 ,
.Xr tty 4 ,
.Xr comcontrol 8
.\" XXX add next line to many other drivers.
.Sh HISTORY
The
.Nm
driver is derived from the
.Xr sio 4
driver and the DigiBoard driver from
.Tn Linux
and is
.Ud
.Sh BUGS
The implementation of sending
.Dv BREAK
is broken.
.Dv BREAK
of fixed length of 1/4 s
is sent anyway.
.Pp
There was a bug in implementation of
.Xr select 2 .
It is fixed now but not widely tested yet.
.Pp
There is no ditty command.
Most of its functions (alternate pinout,
speed up to 115200 baud, etc.) are implemented in the driver itself.
Some
other functions are missing.

View file

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 3, 2016
.Dd September 1, 2016
.Dt PCI 9
.Os
.Sh NAME
@ -910,11 +910,6 @@ with one in the new distribution.
The
.Fn pci_remap_msix
function will fail if this condition is not met.
.Sh IMPLEMENTATION NOTES
The
.Vt pci_addr_t
type varies according to the size of the PCI bus address
space on the target architecture.
.Sh SEE ALSO
.Xr pci 4 ,
.Xr pciconf 8 ,

View file

@ -112,6 +112,7 @@ CRUNCHENV+= MK_TESTS=no \
_RECURSING_CRUNCH=1
.ORDER: ${OUTPUTS} objs
${OUTPUTS:[1]}: .META
${OUTPUTS:[2..-1]}: .NOMETA
${OUTPUTS}: ${CONF}
MAKE=${MAKE} ${CRUNCHENV:NMK_AUTO_OBJ=*} MAKEOBJDIRPREFIX=${CRUNCHOBJS} \
MK_AUTO_OBJ=${MK_AUTO_OBJ} \
@ -122,11 +123,13 @@ ${OUTPUTS}: ${CONF}
# These 2 targets cannot use .MAKE since they depend on the generated
# ${OUTMK} above.
${PROG}: ${OUTPUTS} objs .META
${PROG}: ${OUTPUTS} objs .NOMETA .PHONY
${CRUNCHENV} \
CC="${CC} ${CFLAGS} ${LDFLAGS}" \
CXX="${CXX} ${CXXFLAGS} ${LDFLAGS}" \
${MAKE} .MAKE.MODE=normal -f ${OUTMK} exe
${MAKE} .MAKE.MODE="${.MAKE.MODE} curdirOk=yes" \
.MAKE.META.IGNORE_PATHS="${.MAKE.META.IGNORE_PATHS}" \
-f ${OUTMK} exe
objs: ${OUTMK} .META
${CRUNCHENV} MAKEOBJDIRPREFIX=${CRUNCHOBJS} \
@ -166,3 +169,5 @@ clean:
fi
META_XTRAS+= ${find ${CRUNCHOBJS}${SRCTOP} -name '*.meta' 2>/dev/null || true:L:sh}
META_XTRAS+= ${echo ${CRUNCHOBJS}/*.lo.meta 2>/dev/null || true:L:sh}
META_XTRAS+= ${PROG}.meta

View file

@ -82,7 +82,7 @@ LIBIBMAD?= ${DESTDIR}${LIBDIR}/libibmad.a
LIBIBSDP?= ${DESTDIR}${LIBDIR}/libibsdp.a
LIBIBUMAD?= ${DESTDIR}${LIBDIR}/libibumad.a
LIBIBVERBS?= ${DESTDIR}${LIBDIR}/libibverbs.a
LIBIFC?= ${DESTDIR}${LIBDIR}/libifc.a
LIBIFCONFIG?= ${DESTDIR}${LIBDIR}/libifconfig.a
LIBIPSEC?= ${DESTDIR}${LIBDIR}/libipsec.a
LIBJAIL?= ${DESTDIR}${LIBDIR}/libjail.a
LIBKADM5CLNT?= ${DESTDIR}${LIBDIR}/libkadm5clnt.a

View file

@ -105,7 +105,7 @@ _LIBRARIES= \
heimntlm \
heimsqlite \
hx509 \
ifc \
ifconfig \
ipsec \
jail \
kadm5clnt \

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
!!#1TB
!!#2TB
!!#3TB
!!#4TB
!!#5TB
!!#6TB
!!#7TB
!!#8TB
!!#9TB
#1#0TB
#1#1TB
#1#2TB
#
# Long month names (as in a date)
一月
@ -63,7 +63,7 @@
下午
#
# date_fmt
%Y年%b月%e日 %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
一月

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
#
# Long month names (as in a date)
一月
@ -63,7 +63,7 @@
下午
#
# date_fmt
%Y年%b月%e日 %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
一月

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
#
# Long month names (as in a date)
一月
@ -63,7 +63,7 @@
下午
#
# date_fmt
%Y年%b月%e日 %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
一月

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
 1月
 2月
 3月
 4月
 5月
 6月
 7月
 8月
 9月
10月
11月
12月
#
# Long month names (as in a date)
一月
@ -63,7 +63,7 @@
下午
#
# date_fmt
%Y年%b月%e日 %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
一月

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
 1月
 2月
 3月
 4月
 5月
 6月
 7月
 8月
 9月
10月
11月
12月
#
# Long month names (as in a date)
1¤ë
@ -63,7 +63,7 @@
¤U¤È
#
# date_fmt
%Y¦~%b¤ë%e¤é %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
1¤ë

View file

@ -4,18 +4,18 @@
# -----------------------------------------------------------------------------
#
# Short month names
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
#
# Long month names (as in a date)
1月
@ -63,7 +63,7 @@
下午
#
# date_fmt
%Y年%b月%e日 %A %X %Z
%Y年%_m月%e日 %A %X %Z
#
# Long month names (without case ending)
1月

View file

@ -61,8 +61,13 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_AXP81X_REG, "AXP81x regulator", "AXP81x power regulator");
#define AXP_ICTYPE 0x03
#define AXP_POWERCTL1 0x10
#define AXP_POWERCTL1_DCDC2 (1 << 1)
#define AXP_POWERCTL2 0x12
#define AXP_POWERCTL2_DC1SW (1 << 7)
#define AXP_VOLTCTL_DCDC2 0x21
#define AXP_VOLTCTL_STATUS (1 << 7)
#define AXP_VOLTCTL_MASK 0x7f
#define AXP_POWERBAT 0x32
#define AXP_POWERBAT_SHUTDOWN (1 << 7)
#define AXP_IRQEN1 0x40
@ -109,10 +114,18 @@ struct axp81x_regdef {
char *supply_name;
uint8_t enable_reg;
uint8_t enable_mask;
uint8_t voltage_reg;
int voltage_min;
int voltage_max;
int voltage_step1;
int voltage_nstep1;
int voltage_step2;
int voltage_nstep2;
};
enum axp81x_reg_id {
AXP81X_REG_ID_DC1SW
AXP81X_REG_ID_DC1SW,
AXP81X_REG_ID_DCDC2,
};
static struct axp81x_regdef axp81x_regdefs[] = {
@ -122,6 +135,19 @@ static struct axp81x_regdef axp81x_regdefs[] = {
.enable_reg = AXP_POWERCTL2,
.enable_mask = AXP_POWERCTL2_DC1SW,
},
{
.id = AXP81X_REG_ID_DCDC2,
.name = "dcdc2",
.enable_reg = AXP_POWERCTL1,
.enable_mask = AXP_POWERCTL1_DCDC2,
.voltage_reg = AXP_VOLTCTL_DCDC2,
.voltage_min = 500,
.voltage_max = 1300,
.voltage_step1 = 10,
.voltage_nstep1 = 70,
.voltage_step2 = 20,
.voltage_nstep2 = 5,
},
};
struct axp81x_softc;
@ -218,17 +244,82 @@ axp81x_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
return (0);
}
static void
axp81x_regnode_reg_to_voltage(struct axp81x_reg_sc *sc, uint8_t val, int *uv)
{
if (val < sc->def->voltage_nstep1)
*uv = sc->def->voltage_min + val * sc->def->voltage_step1;
else
*uv = sc->def->voltage_min +
(sc->def->voltage_nstep1 * sc->def->voltage_step1) +
((val - sc->def->voltage_nstep1) * sc->def->voltage_step2);
*uv *= 1000;
}
static int
axp81x_regnode_voltage_to_reg(struct axp81x_reg_sc *sc, int min_uvolt,
int max_uvolt, uint8_t *val)
{
uint8_t nval;
int nstep, uvolt;
nval = 0;
uvolt = sc->def->voltage_min * 1000;
for (nstep = 0; nstep < sc->def->voltage_nstep1 && uvolt < min_uvolt;
nstep++) {
++nval;
uvolt += (sc->def->voltage_step1 * 1000);
}
for (nstep = 0; nstep < sc->def->voltage_nstep2 && uvolt < min_uvolt;
nstep++) {
++nval;
uvolt += (sc->def->voltage_step2 * 1000);
}
if (uvolt > max_uvolt)
return (EINVAL);
*val = nval;
return (0);
}
static int
axp81x_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
int max_uvolt, int *udelay)
{
return (ENXIO);
struct axp81x_reg_sc *sc;
uint8_t val;
sc = regnode_get_softc(regnode);
if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
return (ENXIO);
if (axp81x_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
return (ERANGE);
axp81x_write(sc->base_dev, sc->def->voltage_reg, val);
*udelay = 0;
return (0);
}
static int
axp81x_regnode_get_voltage(struct regnode *regnode, int *uvolt)
{
return (ENXIO);
struct axp81x_reg_sc *sc;
uint8_t val;
sc = regnode_get_softc(regnode);
if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
return (ENXIO);
axp81x_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
axp81x_regnode_reg_to_voltage(sc, val & AXP_VOLTCTL_MASK, uvolt);
return (0);
}
static regnode_method_t axp81x_regnode_methods[] = {
@ -519,6 +610,10 @@ axp81x_reg_attach(device_t dev, phandle_t node,
memset(&initdef, 0, sizeof(initdef));
regulator_parse_ofw_stdparam(dev, node, &initdef);
if (initdef.std_param.min_uvolt == 0)
initdef.std_param.min_uvolt = def->voltage_min * 1000;
if (initdef.std_param.max_uvolt == 0)
initdef.std_param.max_uvolt = def->voltage_max * 1000;
initdef.id = def->id;
initdef.ofw_node = node;
regnode = regnode_create(dev, &axp81x_regnode_class, &initdef);

View file

@ -110,14 +110,14 @@ __FBSDID("$FreeBSD$");
#define A13_PLL2_PRE_DIV (0x1f << 0)
#define A13_PLL2_PRE_DIV_SHIFT 0
#define A23_PLL1_FACTOR_P (0x3 << 16)
#define A23_PLL1_FACTOR_P_SHIFT 16
#define A23_PLL1_FACTOR_N (0x1f << 8)
#define A23_PLL1_FACTOR_N_SHIFT 8
#define A23_PLL1_FACTOR_K (0x3 << 4)
#define A23_PLL1_FACTOR_K_SHIFT 4
#define A23_PLL1_FACTOR_M (0x3 << 0)
#define A23_PLL1_FACTOR_M_SHIFT 0
#define A23_PLL1_FACTOR_P (0x3 << 16)
#define A23_PLL1_FACTOR_P_SHIFT 16
#define A31_PLL1_LOCK (1 << 28)
#define A31_PLL1_CPU_SIGMA_DELTA_EN (1 << 24)
@ -171,6 +171,24 @@ __FBSDID("$FreeBSD$");
#define CLKID_A31_PLL6 0
#define CLKID_A31_PLL6_X2 1
struct aw_pll_factor {
unsigned int n;
unsigned int k;
unsigned int m;
unsigned int p;
uint64_t freq;
};
#define PLLFACTOR(_n, _k, _m, _p, _freq) \
{ .n = (_n), .k = (_k), .m = (_m), .p = (_p), .freq = (_freq) }
static struct aw_pll_factor aw_a23_pll1_factors[] = {
PLLFACTOR(16, 0, 0, 0, 408000000),
PLLFACTOR(26, 0, 0, 0, 648000000),
PLLFACTOR(16, 1, 0, 0, 816000000),
PLLFACTOR(20, 1, 0, 0, 1008000000),
PLLFACTOR(24, 1, 0, 0, 1200000000),
};
enum aw_pll_type {
AWPLL_A10_PLL1 = 1,
AWPLL_A10_PLL2,
@ -556,6 +574,39 @@ a13_pll2_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout,
return (0);
}
static int
a23_pll1_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout,
int flags)
{
struct aw_pll_factor *f;
uint32_t val;
int n;
f = NULL;
for (n = 0; n < nitems(aw_a23_pll1_factors); n++) {
if (aw_a23_pll1_factors[n].freq == *fout) {
f = &aw_a23_pll1_factors[n];
break;
}
}
if (f == NULL)
return (EINVAL);
DEVICE_LOCK(sc);
PLL_READ(sc, &val);
val &= ~(A23_PLL1_FACTOR_N|A23_PLL1_FACTOR_K|A23_PLL1_FACTOR_M|
A23_PLL1_FACTOR_P);
val |= (f->n << A23_PLL1_FACTOR_N_SHIFT);
val |= (f->k << A23_PLL1_FACTOR_K_SHIFT);
val |= (f->m << A23_PLL1_FACTOR_M_SHIFT);
val |= (f->p << A23_PLL1_FACTOR_P_SHIFT);
PLL_WRITE(sc, val);
DEVICE_UNLOCK(sc);
return (0);
}
static int
a23_pll1_recalc(struct aw_pll_sc *sc, uint64_t *freq)
{
@ -719,7 +770,7 @@ static struct aw_pll_funcs aw_pll_func[] = {
PLL(AWPLL_A10_PLL5, a10_pll5_recalc, NULL, NULL),
PLL(AWPLL_A10_PLL6, a10_pll6_recalc, a10_pll6_set_freq, a10_pll6_init),
PLL(AWPLL_A13_PLL2, a13_pll2_recalc, a13_pll2_set_freq, NULL),
PLL(AWPLL_A23_PLL1, a23_pll1_recalc, NULL, NULL),
PLL(AWPLL_A23_PLL1, a23_pll1_recalc, a23_pll1_set_freq, NULL),
PLL(AWPLL_A31_PLL1, a31_pll1_recalc, NULL, NULL),
PLL(AWPLL_A31_PLL6, a31_pll6_recalc, NULL, a31_pll6_init),
PLL(AWPLL_A80_PLL4, a80_pll4_recalc, NULL, NULL),

View file

@ -416,8 +416,17 @@ cpu_flush_dcache(void *ptr, size_t len)
int
cpu_est_clockrate(int cpu_id, uint64_t *rate)
{
struct pcpu *pc;
panic("ARM64TODO: cpu_est_clockrate");
pc = pcpu_find(cpu_id);
if (pc == NULL || rate == NULL)
return (EINVAL);
if (pc->pc_clock == 0)
return (EOPNOTSUPP);
*rate = pc->pc_clock;
return (0);
}
void

View file

@ -38,7 +38,8 @@
#define PCPU_MD_FIELDS \
u_int pc_acpi_id; /* ACPI CPU id */ \
u_int pc_midr; /* stored MIDR value */ \
char __pad[121]
uint64_t pc_clock; \
char __pad[113]
#ifdef _KERNEL

View file

@ -791,11 +791,17 @@ dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
/*
* Determine the number of levels necessary for the meta-dnode
* to contain DN_MAX_OBJECT dnodes.
* to contain DN_MAX_OBJECT dnodes. Note that in order to
* ensure that we do not overflow 64 bits, there has to be
* a nlevels that gives us a number of blocks > DN_MAX_OBJECT
* but < 2^64. Therefore,
* (mdn->dn_indblkshift - SPA_BLKPTRSHIFT) (10) must be
* less than (64 - log2(DN_MAX_OBJECT)) (16).
*/
while ((uint64_t)mdn->dn_nblkptr << (mdn->dn_datablkshift +
while ((uint64_t)mdn->dn_nblkptr <<
(mdn->dn_datablkshift - DNODE_SHIFT +
(levels - 1) * (mdn->dn_indblkshift - SPA_BLKPTRSHIFT)) <
DN_MAX_OBJECT * sizeof (dnode_phys_t))
DN_MAX_OBJECT)
levels++;
mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] =

View file

@ -151,6 +151,8 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* IOCTL */
};
static sysevent_t *spa_event_create(spa_t *spa, vdev_t *vd, const char *name);
static void spa_event_post(sysevent_t *ev);
static void spa_sync_version(void *arg, dmu_tx_t *tx);
static void spa_sync_props(void *arg, dmu_tx_t *tx);
static boolean_t spa_has_active_shared_spare(spa_t *spa);
@ -5738,6 +5740,7 @@ int
spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
{
vdev_t *vd;
sysevent_t *ev = NULL;
metaslab_group_t *mg;
nvlist_t **spares, **l2cache, *nv;
uint64_t txg = 0;
@ -5761,6 +5764,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
* in this pool.
*/
if (vd == NULL || unspare) {
if (vd == NULL)
vd = spa_lookup_by_guid(spa, guid, B_TRUE);
ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX);
spa_vdev_remove_aux(spa->spa_spares.sav_config,
ZPOOL_CONFIG_SPARES, spares, nspares, nv);
spa_load_spares(spa);
@ -5768,7 +5774,6 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
} else {
error = SET_ERROR(EBUSY);
}
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX);
} else if (spa->spa_l2cache.sav_vdevs != NULL &&
nvlist_lookup_nvlist_array(spa->spa_l2cache.sav_config,
ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0 &&
@ -5776,11 +5781,12 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
/*
* Cache devices can always be removed.
*/
vd = spa_lookup_by_guid(spa, guid, B_TRUE);
ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX);
spa_vdev_remove_aux(spa->spa_l2cache.sav_config,
ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv);
spa_load_l2cache(spa);
spa->spa_l2cache.sav_sync = B_TRUE;
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX);
} else if (vd != NULL && vd->vdev_islog) {
ASSERT(!locked);
ASSERT(vd == vd->vdev_top);
@ -5817,9 +5823,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
/*
* Clean up the vdev namespace.
*/
ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_DEV);
spa_vdev_remove_from_namespace(spa, vd);
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_DEV);
} else if (vd != NULL) {
/*
* Normal vdevs cannot be removed (yet).
@ -5835,6 +5841,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
if (!locked)
error = spa_vdev_exit(spa, NULL, txg, error);
if (ev)
spa_event_post(ev);
return (error);
}
@ -7229,24 +7238,17 @@ spa_has_active_shared_spare(spa_t *spa)
return (B_FALSE);
}
/*
* Post a sysevent corresponding to the given event. The 'name' must be one of
* the event definitions in sys/sysevent/eventdefs.h. The payload will be
* filled in from the spa and (optionally) the vdev. This doesn't do anything
* in the userland libzpool, as we don't want consumers to misinterpret ztest
* or zdb as real changes.
*/
void
spa_event_notify(spa_t *spa, vdev_t *vd, const char *name)
static sysevent_t *
spa_event_create(spa_t *spa, vdev_t *vd, const char *name)
{
sysevent_t *ev = NULL;
#ifdef _KERNEL
sysevent_t *ev;
sysevent_attr_list_t *attr = NULL;
sysevent_value_t value;
sysevent_id_t eid;
ev = sysevent_alloc(EC_ZFS, (char *)name, SUNW_KERN_PUB "zfs",
SE_SLEEP);
ASSERT(ev != NULL);
value.value_type = SE_DATA_TYPE_STRING;
value.value.sv_string = spa_name(spa);
@ -7278,11 +7280,34 @@ spa_event_notify(spa_t *spa, vdev_t *vd, const char *name)
goto done;
attr = NULL;
(void) log_sysevent(ev, SE_SLEEP, &eid);
done:
if (attr)
sysevent_free_attr(attr);
#endif
return (ev);
}
static void
spa_event_post(sysevent_t *ev)
{
#ifdef _KERNEL
sysevent_id_t eid;
(void) log_sysevent(ev, SE_SLEEP, &eid);
sysevent_free(ev);
#endif
}
/*
* Post a sysevent corresponding to the given event. The 'name' must be one of
* the event definitions in sys/sysevent/eventdefs.h. The payload will be
* filled in from the spa and (optionally) the vdev. This doesn't do anything
* in the userland libzpool, as we don't want consumers to misinterpret ztest
* or zdb as real changes.
*/
void
spa_event_notify(spa_t *spa, vdev_t *vd, const char *name)
{
spa_event_post(spa_event_create(spa, vd, name));
}

View file

@ -411,12 +411,20 @@ zfs_deadman_init()
* it is possible to run the pool completely out of space, causing it to
* be permanently read-only.
*
* Note that on very small pools, the slop space will be larger than
* 3.2%, in an effort to have it be at least spa_min_slop (128MB),
* but we never allow it to be more than half the pool size.
*
* See also the comments in zfs_space_check_t.
*/
int spa_slop_shift = 5;
SYSCTL_INT(_vfs_zfs, OID_AUTO, spa_slop_shift, CTLFLAG_RWTUN,
&spa_slop_shift, 0,
"Shift value of reserved space (1/(2^spa_slop_shift)).");
uint64_t spa_min_slop = 128 * 1024 * 1024;
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, spa_min_slop, CTLFLAG_RWTUN,
&spa_min_slop, 0,
"Minimal value of reserved space");
/*
* ==========================================================================
@ -1723,14 +1731,16 @@ spa_get_asize(spa_t *spa, uint64_t lsize)
/*
* Return the amount of slop space in bytes. It is 1/32 of the pool (3.2%),
* or at least 32MB.
* or at least 128MB, unless that would cause it to be more than half the
* pool size.
*
* See the comment above spa_slop_shift for details.
*/
uint64_t
spa_get_slop_space(spa_t *spa) {
spa_get_slop_space(spa_t *spa)
{
uint64_t space = spa_get_dspace(spa);
return (MAX(space >> spa_slop_shift, SPA_MINDEVSIZE >> 1));
return (MAX(space >> spa_slop_shift, MIN(space >> 1, spa_min_slop)));
}
uint64_t

View file

@ -58,7 +58,7 @@ extern "C" {
*/
#define DNODE_SHIFT 9 /* 512 bytes */
#define DN_MIN_INDBLKSHIFT 12 /* 4k */
#define DN_MAX_INDBLKSHIFT 14 /* 16k */
#define DN_MAX_INDBLKSHIFT 17 /* 128k */
#define DNODE_BLOCK_SHIFT 14 /* 16k */
#define DNODE_CORE_SIZE 64 /* 64 bytes for dnode sans blkptrs */
#define DN_MAX_OBJECT_SHIFT 48 /* 256 trillion (zfs_fid_t limit) */
@ -88,6 +88,11 @@ extern "C" {
#define DNODES_PER_BLOCK_SHIFT (DNODE_BLOCK_SHIFT - DNODE_SHIFT)
#define DNODES_PER_BLOCK (1ULL << DNODES_PER_BLOCK_SHIFT)
/*
* This is inaccurate if the indblkshift of the particular object is not the
* max. But it's only used by userland to calculate the zvol reservation.
*/
#define DNODES_PER_LEVEL_SHIFT (DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT)
#define DNODES_PER_LEVEL (1ULL << DNODES_PER_LEVEL_SHIFT)

View file

@ -500,6 +500,14 @@ zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
dsl_dataset_t *ds;
dsl_pool_t *dp;
/*
* First do a quick check for root in the global zone, which
* is allowed to do all write_perms. This ensures that zfs_ioc_*
* will get to handle nonexistent datasets.
*/
if (INGLOBALZONE(curthread) && secpolicy_zfs(cr) == 0)
return (0);
error = dsl_pool_hold(name, FTAG, &dp);
if (error != 0)
return (error);

View file

@ -610,6 +610,8 @@ typedef struct zpool_rewind_policy {
/*
* This is needed in userland to report the minimum necessary device size.
*
* Note that the zfs test suite uses 64MB vdevs.
*/
#define SPA_MINDEVSIZE (64ULL << 20)

View file

@ -1349,16 +1349,6 @@ dev/dcons/dcons.c optional dcons
dev/dcons/dcons_crom.c optional dcons_crom
dev/dcons/dcons_os.c optional dcons
dev/de/if_de.c optional de pci
dev/digi/CX.c optional digi_CX
dev/digi/CX_PCI.c optional digi_CX_PCI
dev/digi/EPCX.c optional digi_EPCX
dev/digi/EPCX_PCI.c optional digi_EPCX_PCI
dev/digi/Xe.c optional digi_Xe
dev/digi/Xem.c optional digi_Xem
dev/digi/Xr.c optional digi_Xr
dev/digi/digi.c optional digi
dev/digi/digi_isa.c optional digi isa
dev/digi/digi_pci.c optional digi pci
dev/dpt/dpt_eisa.c optional dpt eisa
dev/dpt/dpt_pci.c optional dpt pci
dev/dpt/dpt_scsi.c optional dpt

View file

@ -90,7 +90,6 @@ __FBSDID("$FreeBSD$");
#include "common/t4_regs.h" /* for PCIE_MEM_ACCESS */
#include "tom/t4_tom.h"
#include "cxgbei.h"
#include "cxgbei_ulp2_ddp.h"
static int worker_thread_count;
static struct cxgbei_worker_thread_softc *cwt_softc;
@ -101,374 +100,48 @@ struct icl_pdu *icl_cxgbei_new_pdu(int);
void icl_cxgbei_new_pdu_set_conn(struct icl_pdu *, struct icl_conn *);
void icl_cxgbei_conn_pdu_free(struct icl_conn *, struct icl_pdu *);
/*
* Direct Data Placement -
* Directly place the iSCSI Data-In or Data-Out PDU's payload into pre-posted
* final destination host-memory buffers based on the Initiator Task Tag (ITT)
* in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
* The host memory address is programmed into h/w in the format of pagepod
* entries.
* The location of the pagepod entry is encoded into ddp tag which is used as
* the base for ITT/TTT.
*/
/*
* functions to program the pagepod in h/w
*/
static void inline
ppod_set(struct pagepod *ppod,
struct cxgbei_ulp2_pagepod_hdr *hdr,
struct cxgbei_ulp2_gather_list *gl,
unsigned int pidx)
static void
free_ci_counters(struct cxgbei_data *ci)
{
int i;
memcpy(ppod, hdr, sizeof(*hdr));
#define FREE_CI_COUNTER(x) do { \
if (ci->x != NULL) { \
counter_u64_free(ci->x); \
ci->x = NULL; \
} \
} while (0)
for (i = 0; i < (PPOD_PAGES + 1); i++, pidx++) {
ppod->addr[i] = pidx < gl->nelem ?
cpu_to_be64(gl->dma_sg[pidx].phys_addr) : 0ULL;
}
}
static void inline
ppod_clear(struct pagepod *ppod)
{
memset(ppod, 0, sizeof(*ppod));
}
static inline void
ulp_mem_io_set_hdr(struct adapter *sc, int tid, struct ulp_mem_io *req,
unsigned int wr_len, unsigned int dlen,
unsigned int pm_addr)
{
struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
INIT_ULPTX_WR(req, wr_len, 0, 0);
req->cmd = cpu_to_be32(V_ULPTX_CMD(ULP_TX_MEM_WRITE) |
V_ULP_MEMIO_ORDER(is_t4(sc)) |
V_T5_ULP_MEMIO_IMM(is_t5(sc)));
req->dlen = htonl(V_ULP_MEMIO_DATA_LEN(dlen >> 5));
req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16)
| V_FW_WR_FLOWID(tid));
req->lock_addr = htonl(V_ULP_MEMIO_ADDR(pm_addr >> 5));
idata->cmd_more = htonl(V_ULPTX_CMD(ULP_TX_SC_IMM));
idata->len = htonl(dlen);
}
#define ULPMEM_IDATA_MAX_NPPODS 1 /* 256/PPOD_SIZE */
#define PCIE_MEMWIN_MAX_NPPODS 16 /* 1024/PPOD_SIZE */
static int
ppod_write_idata(struct cxgbei_data *ci,
struct cxgbei_ulp2_pagepod_hdr *hdr,
unsigned int idx, unsigned int npods,
struct cxgbei_ulp2_gather_list *gl,
unsigned int gl_pidx, struct toepcb *toep)
{
u_int dlen = PPOD_SIZE * npods;
u_int pm_addr = idx * PPOD_SIZE + ci->llimit;
u_int wr_len = roundup(sizeof(struct ulp_mem_io) +
sizeof(struct ulptx_idata) + dlen, 16);
struct ulp_mem_io *req;
struct ulptx_idata *idata;
struct pagepod *ppod;
u_int i;
struct wrqe *wr;
struct adapter *sc = toep->vi->pi->adapter;
wr = alloc_wrqe(wr_len, toep->ctrlq);
if (wr == NULL) {
CXGBE_UNIMPLEMENTED("ppod_write_idata: alloc_wrqe failure");
return (ENOMEM);
}
req = wrtod(wr);
memset(req, 0, wr_len);
ulp_mem_io_set_hdr(sc, toep->tid, req, wr_len, dlen, pm_addr);
idata = (struct ulptx_idata *)(req + 1);
ppod = (struct pagepod *)(idata + 1);
for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES) {
if (!hdr) /* clear the pagepod */
ppod_clear(ppod);
else /* set the pagepod */
ppod_set(ppod, hdr, gl, gl_pidx);
}
t4_wrq_tx(sc, wr);
return 0;
}
int
t4_ddp_set_map(struct cxgbei_data *ci, void *iccp,
struct cxgbei_ulp2_pagepod_hdr *hdr, u_int idx, u_int npods,
struct cxgbei_ulp2_gather_list *gl, int reply)
{
struct icl_cxgbei_conn *icc = (struct icl_cxgbei_conn *)iccp;
struct toepcb *toep = icc->toep;
int err;
unsigned int pidx = 0, w_npods = 0, cnt;
/*
* on T4, if we use a mix of IMMD and DSGL with ULP_MEM_WRITE,
* the order would not be guaranteed, so we will stick with IMMD
*/
gl->tid = toep->tid;
gl->port_id = toep->vi->pi->port_id;
gl->egress_dev = (void *)toep->vi->ifp;
/* send via immediate data */
for (; w_npods < npods; idx += cnt, w_npods += cnt,
pidx += PPOD_PAGES) {
cnt = npods - w_npods;
if (cnt > ULPMEM_IDATA_MAX_NPPODS)
cnt = ULPMEM_IDATA_MAX_NPPODS;
err = ppod_write_idata(ci, hdr, idx, cnt, gl, pidx, toep);
if (err) {
printf("%s: ppod_write_idata failed\n", __func__);
break;
}
}
return err;
}
void
t4_ddp_clear_map(struct cxgbei_data *ci, struct cxgbei_ulp2_gather_list *gl,
u_int tag, u_int idx, u_int npods, struct icl_cxgbei_conn *icc)
{
struct toepcb *toep = icc->toep;
int err = -1;
u_int pidx = 0;
u_int w_npods = 0;
u_int cnt;
for (; w_npods < npods; idx += cnt, w_npods += cnt,
pidx += PPOD_PAGES) {
cnt = npods - w_npods;
if (cnt > ULPMEM_IDATA_MAX_NPPODS)
cnt = ULPMEM_IDATA_MAX_NPPODS;
err = ppod_write_idata(ci, NULL, idx, cnt, gl, 0, toep);
if (err)
break;
}
FREE_CI_COUNTER(ddp_setup_ok);
FREE_CI_COUNTER(ddp_setup_error);
FREE_CI_COUNTER(ddp_bytes);
FREE_CI_COUNTER(ddp_pdus);
FREE_CI_COUNTER(fl_bytes);
FREE_CI_COUNTER(fl_pdus);
#undef FREE_CI_COUNTER
}
static int
cxgbei_map_sg(struct cxgbei_sgl *sgl, struct ccb_scsiio *csio)
alloc_ci_counters(struct cxgbei_data *ci)
{
unsigned int data_len = csio->dxfer_len;
unsigned int sgoffset = (uint64_t)csio->data_ptr & PAGE_MASK;
unsigned int nsge;
unsigned char *sgaddr = csio->data_ptr;
unsigned int len = 0;
nsge = (csio->dxfer_len + sgoffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
sgl->sg_addr = sgaddr;
sgl->sg_offset = sgoffset;
if (data_len < (PAGE_SIZE - sgoffset))
len = data_len;
else
len = PAGE_SIZE - sgoffset;
#define ALLOC_CI_COUNTER(x) do { \
ci->x = counter_u64_alloc(M_WAITOK); \
if (ci->x == NULL) \
goto fail; \
} while (0)
sgl->sg_length = len;
data_len -= len;
sgaddr += len;
sgl = sgl+1;
while (data_len > 0) {
sgl->sg_addr = sgaddr;
len = (data_len < PAGE_SIZE)? data_len: PAGE_SIZE;
sgl->sg_length = len;
sgaddr += len;
data_len -= len;
sgl = sgl + 1;
}
return nsge;
}
static int
cxgbei_map_sg_tgt(struct cxgbei_sgl *sgl, union ctl_io *io)
{
unsigned int data_len, sgoffset, nsge;
unsigned char *sgaddr;
unsigned int len = 0, index = 0, ctl_sg_count, i;
struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
if (io->scsiio.kern_sg_entries > 0) {
ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
ctl_sg_count = io->scsiio.kern_sg_entries;
} else {
ctl_sglist = &ctl_sg_entry;
ctl_sglist->addr = io->scsiio.kern_data_ptr;
ctl_sglist->len = io->scsiio.kern_data_len;
ctl_sg_count = 1;
}
sgaddr = sgl->sg_addr = ctl_sglist[index].addr;
sgoffset = sgl->sg_offset = (uint64_t)sgl->sg_addr & PAGE_MASK;
data_len = ctl_sglist[index].len;
if (data_len < (PAGE_SIZE - sgoffset))
len = data_len;
else
len = PAGE_SIZE - sgoffset;
sgl->sg_length = len;
data_len -= len;
sgaddr += len;
sgl = sgl+1;
len = 0;
for (i = 0; i< ctl_sg_count; i++)
len += ctl_sglist[i].len;
nsge = (len + sgoffset + PAGE_SIZE -1) >> PAGE_SHIFT;
while (data_len > 0) {
sgl->sg_addr = sgaddr;
len = (data_len < PAGE_SIZE)? data_len: PAGE_SIZE;
sgl->sg_length = len;
sgaddr += len;
data_len -= len;
sgl = sgl + 1;
if (data_len == 0) {
if (index == ctl_sg_count - 1)
break;
index++;
sgaddr = ctl_sglist[index].addr;
data_len = ctl_sglist[index].len;
}
}
return nsge;
}
static int
t4_sk_ddp_tag_reserve(struct cxgbei_data *ci, struct icl_cxgbei_conn *icc,
u_int xferlen, struct cxgbei_sgl *sgl, u_int sgcnt, u_int *ddp_tag)
{
struct cxgbei_ulp2_gather_list *gl;
int err = -EINVAL;
struct toepcb *toep = icc->toep;
gl = cxgbei_ulp2_ddp_make_gl_from_iscsi_sgvec(xferlen, sgl, sgcnt, ci, 0);
if (gl) {
err = cxgbei_ulp2_ddp_tag_reserve(ci, icc, toep->tid,
&ci->tag_format, ddp_tag, gl, 0, 0);
if (err) {
cxgbei_ulp2_ddp_release_gl(ci, gl);
}
}
return err;
}
static unsigned int
cxgbei_task_reserve_itt(struct icl_conn *ic, void **prv,
struct ccb_scsiio *scmd, unsigned int *itt)
{
struct icl_cxgbei_conn *icc = ic_to_icc(ic);
int xferlen = scmd->dxfer_len;
struct cxgbei_task_data *tdata = NULL;
struct cxgbei_sgl *sge = NULL;
struct toepcb *toep = icc->toep;
struct adapter *sc = td_adapter(toep->td);
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
int err = -1;
MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
tdata = (struct cxgbei_task_data *)*prv;
if (xferlen == 0 || tdata == NULL)
goto out;
if (xferlen < DDP_THRESHOLD)
goto out;
if ((scmd->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
tdata->nsge = cxgbei_map_sg(tdata->sgl, scmd);
if (tdata->nsge == 0) {
CTR1(KTR_CXGBE, "%s: map_sg failed", __func__);
return 0;
}
sge = tdata->sgl;
tdata->sc_ddp_tag = *itt;
CTR3(KTR_CXGBE, "%s: *itt:0x%x sc_ddp_tag:0x%x",
__func__, *itt, tdata->sc_ddp_tag);
if (cxgbei_ulp2_sw_tag_usable(&ci->tag_format,
tdata->sc_ddp_tag)) {
err = t4_sk_ddp_tag_reserve(ci, icc, scmd->dxfer_len,
sge, tdata->nsge, &tdata->sc_ddp_tag);
} else {
CTR3(KTR_CXGBE,
"%s: itt:0x%x sc_ddp_tag:0x%x not usable",
__func__, *itt, tdata->sc_ddp_tag);
}
}
out:
if (err < 0)
tdata->sc_ddp_tag =
cxgbei_ulp2_set_non_ddp_tag(&ci->tag_format, *itt);
return tdata->sc_ddp_tag;
}
static unsigned int
cxgbei_task_reserve_ttt(struct icl_conn *ic, void **prv, union ctl_io *io,
unsigned int *ttt)
{
struct icl_cxgbei_conn *icc = ic_to_icc(ic);
struct toepcb *toep = icc->toep;
struct adapter *sc = td_adapter(toep->td);
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
struct cxgbei_task_data *tdata = NULL;
int xferlen, err = -1;
struct cxgbei_sgl *sge = NULL;
MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
xferlen = (io->scsiio.kern_data_len - io->scsiio.ext_data_filled);
tdata = (struct cxgbei_task_data *)*prv;
if ((xferlen == 0) || (tdata == NULL))
goto out;
if (xferlen < DDP_THRESHOLD)
goto out;
tdata->nsge = cxgbei_map_sg_tgt(tdata->sgl, io);
if (tdata->nsge == 0) {
CTR1(KTR_CXGBE, "%s: map_sg failed", __func__);
return 0;
}
sge = tdata->sgl;
tdata->sc_ddp_tag = *ttt;
if (cxgbei_ulp2_sw_tag_usable(&ci->tag_format, tdata->sc_ddp_tag)) {
err = t4_sk_ddp_tag_reserve(ci, icc, xferlen, sge,
tdata->nsge, &tdata->sc_ddp_tag);
} else {
CTR2(KTR_CXGBE, "%s: sc_ddp_tag:0x%x not usable",
__func__, tdata->sc_ddp_tag);
}
out:
if (err < 0)
tdata->sc_ddp_tag =
cxgbei_ulp2_set_non_ddp_tag(&ci->tag_format, *ttt);
return tdata->sc_ddp_tag;
}
static int
t4_sk_ddp_tag_release(struct icl_cxgbei_conn *icc, unsigned int ddp_tag)
{
struct toepcb *toep = icc->toep;
struct adapter *sc = td_adapter(toep->td);
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
cxgbei_ulp2_ddp_tag_release(ci, ddp_tag, icc);
ALLOC_CI_COUNTER(ddp_setup_ok);
ALLOC_CI_COUNTER(ddp_setup_error);
ALLOC_CI_COUNTER(ddp_bytes);
ALLOC_CI_COUNTER(ddp_pdus);
ALLOC_CI_COUNTER(fl_bytes);
ALLOC_CI_COUNTER(fl_pdus);
#undef ALLOC_CI_COUNTER
return (0);
fail:
free_ci_counters(ci);
return (ENOMEM);
}
static void
@ -504,58 +177,81 @@ read_pdu_limits(struct adapter *sc, uint32_t *max_tx_pdu_len,
static int
cxgbei_init(struct adapter *sc, struct cxgbei_data *ci)
{
int nppods, bits, rc;
static const u_int pgsz_order[] = {0, 1, 2, 3};
struct sysctl_oid *oid;
struct sysctl_oid_list *children;
struct ppod_region *pr;
uint32_t r;
int rc;
MPASS(sc->vres.iscsi.size > 0);
MPASS(ci != NULL);
rc = alloc_ci_counters(ci);
if (rc != 0)
return (rc);
ci->llimit = sc->vres.iscsi.start;
ci->ulimit = sc->vres.iscsi.start + sc->vres.iscsi.size - 1;
read_pdu_limits(sc, &ci->max_tx_pdu_len, &ci->max_rx_pdu_len);
nppods = sc->vres.iscsi.size >> IPPOD_SIZE_SHIFT;
if (nppods <= 1024)
return (ENXIO);
bits = fls(nppods);
if (bits > IPPOD_IDX_MAX_SIZE)
bits = IPPOD_IDX_MAX_SIZE;
nppods = (1 << (bits - 1)) - 1;
rc = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR,
BUS_SPACE_MAXADDR, NULL, NULL, UINT32_MAX , 8, BUS_SPACE_MAXSIZE,
BUS_DMA_ALLOCNOW, NULL, NULL, &ci->ulp_ddp_tag);
pr = &ci->pr;
r = t4_read_reg(sc, A_ULP_RX_ISCSI_PSZ);
rc = t4_init_ppod_region(pr, &sc->vres.iscsi, r, "iSCSI page pods");
if (rc != 0) {
device_printf(sc->dev, "%s: failed to create DMA tag: %u.\n",
device_printf(sc->dev,
"%s: failed to initialize the iSCSI page pod region: %u.\n",
__func__, rc);
free_ci_counters(ci);
return (rc);
}
ci->colors = malloc(nppods * sizeof(char), M_CXGBE, M_NOWAIT | M_ZERO);
ci->gl_map = malloc(nppods * sizeof(struct cxgbei_ulp2_gather_list *),
M_CXGBE, M_NOWAIT | M_ZERO);
if (ci->colors == NULL || ci->gl_map == NULL) {
bus_dma_tag_destroy(ci->ulp_ddp_tag);
free(ci->colors, M_CXGBE);
free(ci->gl_map, M_CXGBE);
return (ENOMEM);
r = t4_read_reg(sc, A_ULP_RX_ISCSI_TAGMASK);
r &= V_ISCSITAGMASK(M_ISCSITAGMASK);
if (r != pr->pr_tag_mask) {
/*
* Recent firmwares are supposed to set up the the iSCSI tagmask
* but we'll do it ourselves it the computed value doesn't match
* what's in the register.
*/
device_printf(sc->dev,
"tagmask 0x%08x does not match computed mask 0x%08x.\n", r,
pr->pr_tag_mask);
t4_set_reg_field(sc, A_ULP_RX_ISCSI_TAGMASK,
V_ISCSITAGMASK(M_ISCSITAGMASK), pr->pr_tag_mask);
}
mtx_init(&ci->map_lock, "ddp lock", NULL, MTX_DEF | MTX_DUPOK);
ci->nppods = nppods;
ci->idx_last = nppods;
ci->idx_bits = bits;
ci->idx_mask = (1 << bits) - 1;
ci->rsvd_tag_mask = (1 << (bits + IPPOD_IDX_SHIFT)) - 1;
sysctl_ctx_init(&ci->ctx);
oid = device_get_sysctl_tree(sc->dev); /* dev.t5nex.X */
children = SYSCTL_CHILDREN(oid);
ci->tag_format.sw_bits = bits;
ci->tag_format.rsvd_bits = bits;
ci->tag_format.rsvd_shift = IPPOD_IDX_SHIFT;
ci->tag_format.rsvd_mask = ci->idx_mask;
oid = SYSCTL_ADD_NODE(&ci->ctx, children, OID_AUTO, "iscsi", CTLFLAG_RD,
NULL, "iSCSI ULP statistics");
children = SYSCTL_CHILDREN(oid);
t4_iscsi_init(sc, ci->idx_mask << IPPOD_IDX_SHIFT, pgsz_order);
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_setup_ok",
CTLFLAG_RD, &ci->ddp_setup_ok,
"# of times DDP buffer was setup successfully.");
return (rc);
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_setup_error",
CTLFLAG_RD, &ci->ddp_setup_error,
"# of times DDP buffer setup failed.");
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_bytes",
CTLFLAG_RD, &ci->ddp_bytes, "# of bytes placed directly");
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_pdus",
CTLFLAG_RD, &ci->ddp_pdus, "# of PDUs with data placed directly.");
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "fl_bytes",
CTLFLAG_RD, &ci->fl_bytes, "# of data bytes delivered in freelist");
SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "fl_pdus",
CTLFLAG_RD, &ci->fl_pdus,
"# of PDUs with data delivered in freelist");
ci->ddp_threshold = 2048;
SYSCTL_ADD_UINT(&ci->ctx, children, OID_AUTO, "ddp_threshold",
CTLFLAG_RW, &ci->ddp_threshold, 0, "Rx zero copy threshold");
return (0);
}
static int
@ -567,15 +263,18 @@ do_rx_iscsi_hdr(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
struct toepcb *toep = lookup_tid(sc, tid);
struct icl_pdu *ip;
struct icl_cxgbei_pdu *icp;
uint16_t len_ddp = be16toh(cpl->pdu_len_ddp);
uint16_t len = be16toh(cpl->len);
M_ASSERTPKTHDR(m);
MPASS(m->m_pkthdr.len == len + sizeof(*cpl));
ip = icl_cxgbei_new_pdu(M_NOWAIT);
if (ip == NULL)
CXGBE_UNIMPLEMENTED("PDU allocation failure");
m_copydata(m, sizeof(*cpl), ISCSI_BHS_SIZE, (caddr_t)ip->ip_bhs);
ip->ip_data_len = G_ISCSI_PDU_LEN(len_ddp) - len;
icp = ip_to_icp(ip);
bcopy(mtod(m, caddr_t) + sizeof(*cpl), icp->ip.ip_bhs, sizeof(struct
iscsi_bhs));
icp->icp_seq = ntohl(cpl->seq);
icp->icp_flags = ICPF_RX_HDR;
@ -584,8 +283,8 @@ do_rx_iscsi_hdr(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
toep->ulpcb2 = icp;
#if 0
CTR4(KTR_CXGBE, "%s: tid %u, cpl->len hlen %u, m->m_len hlen %u",
__func__, tid, ntohs(cpl->len), m->m_len);
CTR5(KTR_CXGBE, "%s: tid %u, cpl->len %u, pdu_len_ddp 0x%04x, icp %p",
__func__, tid, len, len_ddp, icp);
#endif
m_freem(m);
@ -596,28 +295,32 @@ static int
do_rx_iscsi_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
{
struct adapter *sc = iq->adapter;
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
struct cpl_iscsi_data *cpl = mtod(m, struct cpl_iscsi_data *);
u_int tid = GET_TID(cpl);
struct toepcb *toep = lookup_tid(sc, tid);
struct icl_cxgbei_pdu *icp = toep->ulpcb2;
M_ASSERTPKTHDR(m);
MPASS(m->m_pkthdr.len == be16toh(cpl->len) + sizeof(*cpl));
/* Must already have received the header (but not the data). */
MPASS(icp != NULL);
MPASS(icp->icp_flags == ICPF_RX_HDR);
MPASS(icp->ip.ip_data_mbuf == NULL);
MPASS(icp->ip.ip_data_len == 0);
m_adj(m, sizeof(*cpl));
MPASS(icp->ip.ip_data_len == m->m_pkthdr.len);
icp->icp_flags |= ICPF_RX_FLBUF;
icp->ip.ip_data_mbuf = m;
icp->ip.ip_data_len = m->m_pkthdr.len;
counter_u64_add(ci->fl_pdus, 1);
counter_u64_add(ci->fl_bytes, m->m_pkthdr.len);
#if 0
CTR4(KTR_CXGBE, "%s: tid %u, cpl->len dlen %u, m->m_len dlen %u",
__func__, tid, ntohs(cpl->len), m->m_len);
CTR3(KTR_CXGBE, "%s: tid %u, cpl->len %u", __func__, tid,
be16toh(cpl->len));
#endif
return (0);
@ -627,6 +330,7 @@ static int
do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
{
struct adapter *sc = iq->adapter;
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
const struct cpl_rx_data_ddp *cpl = (const void *)(rss + 1);
u_int tid = GET_TID(cpl);
struct toepcb *toep = lookup_tid(sc, tid);
@ -645,20 +349,32 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
/* Must already be assembling a PDU. */
MPASS(icp != NULL);
MPASS(icp->icp_flags & ICPF_RX_HDR); /* Data is optional. */
ip = &icp->ip;
MPASS((icp->icp_flags & ICPF_RX_STATUS) == 0);
pdu_len = be16toh(cpl->len); /* includes everything. */
val = be32toh(cpl->ddpvld);
#if 0
CTR4(KTR_CXGBE,
"%s: tid %u, cpl->len %u, ddpvld 0x%08x, icp_flags 0x%08x",
__func__, tid, pdu_len, val, icp->icp_flags);
#endif
icp->icp_flags |= ICPF_RX_STATUS;
val = ntohl(cpl->ddpvld);
ip = &icp->ip;
if (val & F_DDP_PADDING_ERR)
icp->icp_flags |= ICPF_PAD_ERR;
if (val & F_DDP_HDRCRC_ERR)
icp->icp_flags |= ICPF_HCRC_ERR;
if (val & F_DDP_DATACRC_ERR)
icp->icp_flags |= ICPF_DCRC_ERR;
if (ip->ip_data_mbuf == NULL) {
/* XXXNP: what should ip->ip_data_len be, and why? */
if (val & F_DDP_PDU && ip->ip_data_mbuf == NULL) {
MPASS((icp->icp_flags & ICPF_RX_FLBUF) == 0);
MPASS(ip->ip_data_len > 0);
icp->icp_flags |= ICPF_RX_DDP;
counter_u64_add(ci->ddp_pdus, 1);
counter_u64_add(ci->ddp_bytes, ip->ip_data_len);
}
pdu_len = ntohs(cpl->len); /* includes everything. */
INP_WLOCK(inp);
if (__predict_false(inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT))) {
@ -744,11 +460,6 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
m_freem(m);
}
#if 0
CTR4(KTR_CXGBE, "%s: tid %u, pdu_len %u, pdu_flags 0x%x",
__func__, tid, pdu_len, icp->icp_flags);
#endif
STAILQ_INSERT_TAIL(&icc->rcvd_pdus, ip, ip_next);
if ((icc->rx_flags & RXF_ACTIVE) == 0) {
struct cxgbei_worker_thread_softc *cwt = &cwt_softc[icc->cwt];
@ -772,47 +483,6 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
return (0);
}
/* initiator */
void
cxgbei_conn_task_reserve_itt(void *conn, void **prv,
void *scmd, unsigned int *itt)
{
unsigned int tag;
tag = cxgbei_task_reserve_itt(conn, prv, scmd, itt);
if (tag)
*itt = htonl(tag);
return;
}
/* target */
void
cxgbei_conn_transfer_reserve_ttt(void *conn, void **prv,
void *scmd, unsigned int *ttt)
{
unsigned int tag;
tag = cxgbei_task_reserve_ttt(conn, prv, scmd, ttt);
if (tag)
*ttt = htonl(tag);
return;
}
void
cxgbei_cleanup_task(void *conn, void *ofld_priv)
{
struct icl_conn *ic = (struct icl_conn *)conn;
struct icl_cxgbei_conn *icc = ic_to_icc(ic);
struct cxgbei_task_data *tdata = ofld_priv;
struct adapter *sc = icc->sc;
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
MPASS(tdata != NULL);
if (cxgbei_ulp2_is_ddp_tag(&ci->tag_format, tdata->sc_ddp_tag))
t4_sk_ddp_tag_release(icc, tdata->sc_ddp_tag);
memset(tdata, 0, sizeof(*tdata));
}
static int
cxgbei_activate(struct adapter *sc)
{
@ -834,7 +504,7 @@ cxgbei_activate(struct adapter *sc)
}
/* per-adapter softc for iSCSI */
ci = malloc(sizeof(*ci), M_CXGBE, M_ZERO | M_NOWAIT);
ci = malloc(sizeof(*ci), M_CXGBE, M_ZERO | M_WAITOK);
if (ci == NULL)
return (ENOMEM);
@ -852,12 +522,15 @@ cxgbei_activate(struct adapter *sc)
static int
cxgbei_deactivate(struct adapter *sc)
{
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
ASSERT_SYNCHRONIZED_OP(sc);
if (sc->iscsi_ulp_softc != NULL) {
cxgbei_ddp_cleanup(sc->iscsi_ulp_softc);
free(sc->iscsi_ulp_softc, M_CXGBE);
if (ci != NULL) {
sysctl_ctx_free(&ci->ctx);
t4_free_ppod_region(&ci->pr);
free_ci_counters(ci);
free(ci, M_CXGBE);
sc->iscsi_ulp_softc = NULL;
}

View file

@ -105,69 +105,25 @@ ip_to_icp(struct icl_pdu *ip)
return (__containerof(ip, struct icl_cxgbei_pdu, ip));
}
struct cxgbei_sgl {
int sg_flag;
void *sg_addr;
void *sg_dma_addr;
size_t sg_offset;
size_t sg_length;
};
#define cxgbei_scsi_for_each_sg(_sgl, _sgel, _n, _i) \
for (_i = 0, _sgel = (cxgbei_sgl*) (_sgl); _i < _n; _i++, \
_sgel++)
#define sg_dma_addr(_sgel) _sgel->sg_dma_addr
#define sg_virt(_sgel) _sgel->sg_addr
#define sg_len(_sgel) _sgel->sg_length
#define sg_off(_sgel) _sgel->sg_offset
#define sg_next(_sgel) _sgel + 1
/* private data for each scsi task */
struct cxgbei_task_data {
struct cxgbei_sgl sgl[256];
u_int nsge;
u_int sc_ddp_tag;
};
struct cxgbei_ulp2_tag_format {
u_char sw_bits;
u_char rsvd_bits;
u_char rsvd_shift;
u_char filler[1];
uint32_t rsvd_mask;
};
struct cxgbei_data {
u_int llimit;
u_int ulimit;
u_int nppods;
u_int idx_last;
u_char idx_bits;
uint32_t idx_mask;
uint32_t rsvd_tag_mask;
u_int max_tx_pdu_len;
u_int max_rx_pdu_len;
struct mtx map_lock;
bus_dma_tag_t ulp_ddp_tag;
unsigned char *colors;
struct cxgbei_ulp2_gather_list **gl_map;
u_int ddp_threshold;
struct ppod_region pr;
struct cxgbei_ulp2_tag_format tag_format;
struct sysctl_ctx_list ctx; /* from uld_activate to deactivate */
counter_u64_t ddp_setup_ok;
counter_u64_t ddp_setup_error;
counter_u64_t ddp_bytes;
counter_u64_t ddp_pdus;
counter_u64_t fl_bytes;
counter_u64_t fl_pdus;
};
void cxgbei_conn_task_reserve_itt(void *, void **, void *, unsigned int *);
void cxgbei_conn_transfer_reserve_ttt(void *, void **, void *, unsigned int *);
void cxgbei_cleanup_task(void *, void *);
/* cxgbei.c */
u_int cxgbei_select_worker_thread(struct icl_cxgbei_conn *);
struct cxgbei_ulp2_pagepod_hdr;
int t4_ddp_set_map(struct cxgbei_data *, void *,
struct cxgbei_ulp2_pagepod_hdr *, u_int, u_int,
struct cxgbei_ulp2_gather_list *, int);
void t4_ddp_clear_map(struct cxgbei_data *, struct cxgbei_ulp2_gather_list *,
u_int, u_int, u_int, struct icl_cxgbei_conn *);
/* icl_cxgbei.c */
int icl_cxgbei_mod_load(void);
int icl_cxgbei_mod_unload(void);

View file

@ -1,417 +0,0 @@
/*-
* Copyright (c) 2012 Chelsio Communications, Inc.
* All rights reserved.
*
* Chelsio T5xx iSCSI driver
* cxgbei_ulp2_ddp.c: Chelsio iSCSI DDP Manager.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/toecore.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_fsm.h>
#include <dev/iscsi/icl.h>
#include <dev/iscsi/iscsi_proto.h>
#include "common/common.h"
#include "common/t4_msg.h"
#include "common/t4_regs.h" /* for PCIE_MEM_ACCESS */
#include "tom/t4_tom.h"
#include "cxgbei.h"
#include "cxgbei_ulp2_ddp.h"
/*
* Map a single buffer address.
*/
static void
ulp2_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
bus_addr_t *ba = arg;
if (error)
return;
KASSERT(nseg == 1, ("%s: %d segments returned!", __func__, nseg));
*ba = segs->ds_addr;
}
/*
* iSCSI Direct Data Placement
*
* T4/5 ulp2 h/w can directly place the iSCSI Data-In or Data-Out PDU's
* payload into pre-posted final destination host-memory buffers based on the
* Initiator Task Tag (ITT) in Data-In or Target Task Tag (TTT) in Data-Out
* PDUs.
*
* The host memory address is programmed into h/w in the format of pagepod
* entries.
* The location of the pagepod entry is encoded into ddp tag which is used or
* is the base for ITT/TTT.
*/
static inline int
ddp_find_unused_entries(struct cxgbei_data *ci, u_int start, u_int max,
u_int count, u_int *idx, struct cxgbei_ulp2_gather_list *gl)
{
unsigned int i, j, k;
/* not enough entries */
if (max - start < count)
return (EBUSY);
max -= count;
mtx_lock(&ci->map_lock);
for (i = start; i < max;) {
for (j = 0, k = i; j < count; j++, k++) {
if (ci->gl_map[k])
break;
}
if (j == count) {
for (j = 0, k = i; j < count; j++, k++)
ci->gl_map[k] = gl;
mtx_unlock(&ci->map_lock);
*idx = i;
return (0);
}
i += j + 1;
}
mtx_unlock(&ci->map_lock);
return (EBUSY);
}
static inline void
ddp_unmark_entries(struct cxgbei_data *ci, u_int start, u_int count)
{
mtx_lock(&ci->map_lock);
memset(&ci->gl_map[start], 0,
count * sizeof(struct cxgbei_ulp2_gather_list *));
mtx_unlock(&ci->map_lock);
}
static inline void
ddp_gl_unmap(struct cxgbei_data *ci, struct cxgbei_ulp2_gather_list *gl)
{
int i;
if (!gl->pages[0])
return;
for (i = 0; i < gl->nelem; i++) {
bus_dmamap_unload(ci->ulp_ddp_tag, gl->dma_sg[i].bus_map);
bus_dmamap_destroy(ci->ulp_ddp_tag, gl->dma_sg[i].bus_map);
}
}
static inline int
ddp_gl_map(struct cxgbei_data *ci, struct cxgbei_ulp2_gather_list *gl)
{
int i, rc;
bus_addr_t pa;
MPASS(ci != NULL);
mtx_lock(&ci->map_lock);
for (i = 0; i < gl->nelem; i++) {
rc = bus_dmamap_create(ci->ulp_ddp_tag, 0,
&gl->dma_sg[i].bus_map);
if (rc != 0)
goto unmap;
rc = bus_dmamap_load(ci->ulp_ddp_tag, gl->dma_sg[i].bus_map,
gl->pages[i], PAGE_SIZE, ulp2_dma_map_addr,
&pa, BUS_DMA_NOWAIT);
if (rc != 0)
goto unmap;
gl->dma_sg[i].phys_addr = pa;
}
mtx_unlock(&ci->map_lock);
return (0);
unmap:
if (i) {
u_int nelem = gl->nelem;
gl->nelem = i;
ddp_gl_unmap(ci, gl);
gl->nelem = nelem;
}
return (ENOMEM);
}
/**
* cxgbei_ulp2_ddp_make_gl_from_iscsi_sgvec - build ddp page buffer list
* @xferlen: total buffer length
* @sgl: page buffer scatter-gather list (struct cxgbei_sgl)
* @sgcnt: # of page buffers
* @gfp: allocation mode
*
* construct a ddp page buffer list from the scsi scattergather list.
* coalesce buffers as much as possible, and obtain dma addresses for
* each page.
*
* Return the cxgbei_ulp2_gather_list constructed from the page buffers if the
* memory can be used for ddp. Return NULL otherwise.
*/
struct cxgbei_ulp2_gather_list *
cxgbei_ulp2_ddp_make_gl_from_iscsi_sgvec(u_int xferlen, struct cxgbei_sgl *sgl,
u_int sgcnt, struct cxgbei_data *ci, int gfp)
{
struct cxgbei_ulp2_gather_list *gl;
struct cxgbei_sgl *sg = sgl;
void *sgpage = (void *)((u64)sg->sg_addr & (~PAGE_MASK));
unsigned int sglen = sg->sg_length;
unsigned int sgoffset = (u64)sg->sg_addr & PAGE_MASK;
unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
PAGE_SHIFT;
int i = 1, j = 0;
if (xferlen <= DDP_THRESHOLD) {
CTR2(KTR_CXGBE, "xfer %u < threshold %u, no ddp.",
xferlen, DDP_THRESHOLD);
return NULL;
}
gl = malloc(sizeof(struct cxgbei_ulp2_gather_list) +
npages * (sizeof(struct dma_segments) + sizeof(void *)),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (gl == NULL)
return (NULL);
gl->pages = (void **)&gl->dma_sg[npages];
gl->length = xferlen;
gl->offset = sgoffset;
gl->pages[0] = sgpage;
CTR6(KTR_CXGBE,
"%s: xferlen:0x%x len:0x%x off:0x%x sg_addr:%p npages:%d",
__func__, xferlen, gl->length, gl->offset, sg->sg_addr, npages);
for (i = 1, sg = sg_next(sg); i < sgcnt; i++, sg = sg_next(sg)) {
void *page = sg->sg_addr;
if (sgpage == page && sg->sg_offset == sgoffset + sglen)
sglen += sg->sg_length;
else {
/* make sure the sgl is fit for ddp:
* each has the same page size, and
* all of the middle pages are used completely
*/
if ((j && sgoffset) ||
((i != sgcnt - 1) &&
((sglen + sgoffset) & ~CXGBEI_PAGE_MASK))){
goto error_out;
}
j++;
if (j == gl->nelem || sg->sg_offset) {
goto error_out;
}
gl->pages[j] = page;
sglen = sg->sg_length;
sgoffset = sg->sg_offset;
sgpage = page;
}
}
gl->nelem = ++j;
if (ddp_gl_map(ci, gl) < 0)
goto error_out;
return gl;
error_out:
free(gl, M_DEVBUF);
return NULL;
}
/**
* cxgbei_ulp2_ddp_release_gl - release a page buffer list
* @gl: a ddp page buffer list
* @pdev: pci_dev used for pci_unmap
* free a ddp page buffer list resulted from cxgbei_ulp2_ddp_make_gl().
*/
void
cxgbei_ulp2_ddp_release_gl(struct cxgbei_data *ci,
struct cxgbei_ulp2_gather_list *gl)
{
ddp_gl_unmap(ci, gl);
free(gl, M_DEVBUF);
}
/**
* cxgbei_ulp2_ddp_tag_reserve - set up ddp for a data transfer
* @ci: adapter's ddp info
* @tid: connection id
* @tformat: tag format
* @tagp: contains s/w tag initially, will be updated with ddp/hw tag
* @gl: the page momory list
* @gfp: allocation mode
*
* ddp setup for a given page buffer list and construct the ddp tag.
* return 0 if success, < 0 otherwise.
*/
int
cxgbei_ulp2_ddp_tag_reserve(struct cxgbei_data *ci, void *icc, u_int tid,
struct cxgbei_ulp2_tag_format *tformat, u32 *tagp,
struct cxgbei_ulp2_gather_list *gl, int gfp, int reply)
{
struct cxgbei_ulp2_pagepod_hdr hdr;
u_int npods, idx;
int rc;
u32 sw_tag = *tagp;
u32 tag;
MPASS(ci != NULL);
if (!gl || !gl->nelem || gl->length < DDP_THRESHOLD)
return (EINVAL);
npods = (gl->nelem + IPPOD_PAGES_MAX - 1) >> IPPOD_PAGES_SHIFT;
if (ci->idx_last == ci->nppods)
rc = ddp_find_unused_entries(ci, 0, ci->nppods, npods, &idx,
gl);
else {
rc = ddp_find_unused_entries(ci, ci->idx_last + 1,
ci->nppods, npods, &idx, gl);
if (rc && ci->idx_last >= npods) {
rc = ddp_find_unused_entries(ci, 0,
min(ci->idx_last + npods, ci->nppods),
npods, &idx, gl);
}
}
if (rc) {
CTR3(KTR_CXGBE, "xferlen %u, gl %u, npods %u NO DDP.",
gl->length, gl->nelem, npods);
return (rc);
}
tag = cxgbei_ulp2_ddp_tag_base(idx, ci->colors, tformat, sw_tag);
CTR4(KTR_CXGBE, "%s: sw_tag:0x%x idx:0x%x tag:0x%x",
__func__, sw_tag, idx, tag);
hdr.rsvd = 0;
hdr.vld_tid = htonl(F_IPPOD_VALID | V_IPPOD_TID(tid));
hdr.pgsz_tag_clr = htonl(tag & ci->rsvd_tag_mask);
hdr.maxoffset = htonl(gl->length);
hdr.pgoffset = htonl(gl->offset);
rc = t4_ddp_set_map(ci, icc, &hdr, idx, npods, gl, reply);
if (rc < 0)
goto unmark_entries;
ci->idx_last = idx;
*tagp = tag;
return (0);
unmark_entries:
ddp_unmark_entries(ci, idx, npods);
return (rc);
}
/**
* cxgbei_ulp2_ddp_tag_release - release a ddp tag
* @ci: adapter's ddp info
* @tag: ddp tag
* ddp cleanup for a given ddp tag and release all the resources held
*/
void
cxgbei_ulp2_ddp_tag_release(struct cxgbei_data *ci, uint32_t tag,
struct icl_cxgbei_conn *icc)
{
uint32_t idx;
MPASS(ci != NULL);
MPASS(icc != NULL);
idx = (tag >> IPPOD_IDX_SHIFT) & ci->idx_mask;
CTR3(KTR_CXGBE, "tag:0x%x idx:0x%x nppods:0x%x",
tag, idx, ci->nppods);
if (idx < ci->nppods) {
struct cxgbei_ulp2_gather_list *gl = ci->gl_map[idx];
unsigned int npods;
if (!gl || !gl->nelem) {
CTR4(KTR_CXGBE,
"release 0x%x, idx 0x%x, gl 0x%p, %u.",
tag, idx, gl, gl ? gl->nelem : 0);
return;
}
npods = (gl->nelem + IPPOD_PAGES_MAX - 1) >> IPPOD_PAGES_SHIFT;
CTR3(KTR_CXGBE, "ddp tag 0x%x, release idx 0x%x, npods %u.",
tag, idx, npods);
t4_ddp_clear_map(ci, gl, tag, idx, npods, icc);
ddp_unmark_entries(ci, idx, npods);
cxgbei_ulp2_ddp_release_gl(ci, gl);
} else
CTR3(KTR_CXGBE, "ddp tag 0x%x, idx 0x%x > max 0x%x.",
tag, idx, ci->nppods);
}
/**
* cxgbei_ddp_cleanup - release the adapter's ddp resources
*/
void
cxgbei_ddp_cleanup(struct cxgbei_data *ci)
{
int i = 0;
while (i < ci->nppods) {
struct cxgbei_ulp2_gather_list *gl = ci->gl_map[i];
if (gl) {
int npods = (gl->nelem + IPPOD_PAGES_MAX - 1)
>> IPPOD_PAGES_SHIFT;
free(gl, M_DEVBUF);
i += npods;
} else
i++;
}
free(ci->colors, M_CXGBE);
free(ci->gl_map, M_CXGBE);
}
#endif

View file

@ -1,217 +0,0 @@
/*-
* Copyright (c) 2012 Chelsio Communications, Inc.
* All rights reserved.
*
* Chelsio T5xx iSCSI driver
* cxgbei_ulp2_ddp.c: Chelsio iSCSI DDP Manager.
*
* 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 __CXGBEI_ULP2_DDP_H__
#define __CXGBEI_ULP2_DDP_H__
#define CXGBEI_PAGE_MASK (~(PAGE_SIZE-1))
#define DDP_THRESHOLD 2048
/*
* cxgbei ddp tag are 32 bits, it consists of reserved bits used by h/w and
* non-reserved bits that can be used by the iscsi s/w.
* The reserved bits are identified by the rsvd_bits and rsvd_shift fields
* in struct cxgbei_ulp2_tag_format.
*
* The upper most reserved bit can be used to check if a tag is ddp tag or not:
* if the bit is 0, the tag is a valid ddp tag
*/
/*
* cxgbei_ulp2_is_ddp_tag - check if a given tag is a hw/ddp tag
* @tformat: tag format information
* @tag: tag to be checked
*
* return true if the tag is a ddp tag, false otherwise.
*/
static inline int
cxgbei_ulp2_is_ddp_tag(struct cxgbei_ulp2_tag_format *tformat, uint32_t tag)
{
return (!(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1))));
}
/*
* cxgbei_ulp2_sw_tag_usable - check if s/w tag has enough bits left for hw bits
* @tformat: tag format information
* @sw_tag: s/w tag to be checked
*
* return true if the tag can be used for hw ddp tag, false otherwise.
*/
static inline int
cxgbei_ulp2_sw_tag_usable(struct cxgbei_ulp2_tag_format *tformat,
uint32_t sw_tag)
{
return (1); /* XXXNP: huh? */
sw_tag >>= (32 - tformat->rsvd_bits + tformat->rsvd_shift);
return !sw_tag;
}
/*
* cxgbei_ulp2_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
* @tformat: tag format information
* @sw_tag: s/w tag to be checked
*
* insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
*/
static inline uint32_t
cxgbei_ulp2_set_non_ddp_tag(struct cxgbei_ulp2_tag_format *tformat,
uint32_t sw_tag)
{
uint32_t rsvd_bits = tformat->rsvd_bits + tformat->rsvd_shift;
if (sw_tag) {
u32 v1 = sw_tag & ((1 << (rsvd_bits - 1)) - 1);
u32 v2 = (sw_tag >> (rsvd_bits - 1)) << rsvd_bits;
return v2 | (1 << (rsvd_bits - 1)) | v1;
}
return sw_tag | (1 << (rsvd_bits - 1)) ;
}
struct dma_segments {
bus_dmamap_t bus_map;
bus_addr_t phys_addr;
};
/*
* struct cxgbei_ulp2_gather_list - cxgbei direct data placement memory
*
* @tag: ddp tag
* @length: total data buffer length
* @offset: initial offset to the 1st page
* @nelem: # of pages
* @pages: page pointers
* @phys_addr: physical address
*/
struct cxgbei_ulp2_gather_list {
uint32_t tag;
uint32_t tid;
uint32_t port_id;
void *egress_dev;
unsigned int length;
unsigned int offset;
unsigned int nelem;
bus_size_t mapsize;
bus_dmamap_t bus_map;
bus_dma_segment_t *segments;
void **pages;
struct dma_segments dma_sg[0];
};
#define IPPOD_SIZE sizeof(struct cxgbei_ulp2_pagepod) /* 64 */
#define IPPOD_SIZE_SHIFT 6
#define IPPOD_COLOR_SHIFT 0
#define IPPOD_COLOR_SIZE 6
#define IPPOD_COLOR_MASK ((1 << IPPOD_COLOR_SIZE) - 1)
#define IPPOD_IDX_SHIFT IPPOD_COLOR_SIZE
#define IPPOD_IDX_MAX_SIZE 24
#define S_IPPOD_TID 0
#define M_IPPOD_TID 0xFFFFFF
#define V_IPPOD_TID(x) ((x) << S_IPPOD_TID)
#define S_IPPOD_VALID 24
#define V_IPPOD_VALID(x) ((x) << S_IPPOD_VALID)
#define F_IPPOD_VALID V_IPPOD_VALID(1U)
#define S_IPPOD_COLOR 0
#define M_IPPOD_COLOR 0x3F
#define V_IPPOD_COLOR(x) ((x) << S_IPPOD_COLOR)
#define S_IPPOD_TAG 6
#define M_IPPOD_TAG 0xFFFFFF
#define V_IPPOD_TAG(x) ((x) << S_IPPOD_TAG)
#define S_IPPOD_PGSZ 30
#define M_IPPOD_PGSZ 0x3
#define V_IPPOD_PGSZ(x) ((x) << S_IPPOD_PGSZ)
static inline uint32_t
cxgbei_ulp2_ddp_tag_base(u_int idx, u_char *colors,
struct cxgbei_ulp2_tag_format *tformat, uint32_t sw_tag)
{
if (__predict_false(++colors[idx] == 1 << IPPOD_IDX_SHIFT))
colors[idx] = 0;
sw_tag <<= tformat->rsvd_bits + tformat->rsvd_shift;
return (sw_tag | idx << IPPOD_IDX_SHIFT | colors[idx]);
}
#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */
/*
* align pdu size to multiple of 512 for better performance
*/
#define cxgbei_align_pdu_size(n) do { n = (n) & (~511); } while (0)
#define ULP2_MAX_PKT_SIZE 16224
#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
#define IPPOD_PAGES_MAX 4
#define IPPOD_PAGES_SHIFT 2 /* 4 pages per pod */
/*
* struct pagepod_hdr, pagepod - pagepod format
*/
struct cxgbei_ulp2_pagepod_hdr {
uint32_t vld_tid;
uint32_t pgsz_tag_clr;
uint32_t maxoffset;
uint32_t pgoffset;
uint64_t rsvd;
};
struct cxgbei_ulp2_pagepod {
struct cxgbei_ulp2_pagepod_hdr hdr;
uint64_t addr[IPPOD_PAGES_MAX + 1];
};
int cxgbei_ulp2_ddp_tag_reserve(struct cxgbei_data *, void *, unsigned int,
struct cxgbei_ulp2_tag_format *, uint32_t *,
struct cxgbei_ulp2_gather_list *, int , int );
void cxgbei_ulp2_ddp_tag_release(struct cxgbei_data *, uint32_t,
struct icl_cxgbei_conn *);
struct cxgbei_ulp2_gather_list *cxgbei_ulp2_ddp_make_gl_from_iscsi_sgvec(u_int,
struct cxgbei_sgl *, u_int, struct cxgbei_data *, int);
void cxgbei_ulp2_ddp_release_gl(struct cxgbei_data *,
struct cxgbei_ulp2_gather_list *);
int cxgbei_ulp2_ddp_find_page_index(u_long);
int cxgbei_ulp2_adapter_ddp_info(struct cxgbei_data *,
struct cxgbei_ulp2_tag_format *);
void cxgbei_ddp_cleanup(struct cxgbei_data *);
#endif

View file

@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <machine/bus.h>
#include <vm/uma.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp.h>
@ -70,6 +72,28 @@ __FBSDID("$FreeBSD$");
#include <dev/iscsi/iscsi_proto.h>
#include <icl_conn_if.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_da.h>
#include <cam/ctl/ctl_io.h>
#include <cam/ctl/ctl.h>
#include <cam/ctl/ctl_backend.h>
#include <cam/ctl/ctl_error.h>
#include <cam/ctl/ctl_frontend.h>
#include <cam/ctl/ctl_debug.h>
#include <cam/ctl/ctl_ha.h>
#include <cam/ctl/ctl_ioctl.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_xpt.h>
#include <cam/cam_debug.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_periph.h>
#include <cam/cam_compat.h>
#include <cam/scsi/scsi_message.h>
#include "common/common.h"
#include "common/t4_tcb.h"
#include "tom/t4_tom.h"
@ -90,8 +114,7 @@ static int recvspace = 1048576;
SYSCTL_INT(_kern_icl_cxgbei, OID_AUTO, recvspace, CTLFLAG_RWTUN,
&recvspace, 0, "Default receive socket buffer size");
static uma_zone_t icl_transfer_zone;
static uma_zone_t prsv_zone;
static volatile u_int icl_cxgbei_ncons;
#define ICL_CONN_LOCK(X) mtx_lock(X->ic_lock)
@ -242,12 +265,6 @@ icl_cxgbei_conn_pdu_data_segment_length(struct icl_conn *ic,
return (icl_pdu_data_segment_length(request));
}
static uint32_t
icl_conn_build_tasktag(struct icl_conn *ic, uint32_t tag)
{
return tag;
}
static struct mbuf *
finalize_pdu(struct icl_cxgbei_conn *icc, struct icl_cxgbei_pdu *icp)
{
@ -776,55 +793,221 @@ icl_cxgbei_conn_close(struct icl_conn *ic)
int
icl_cxgbei_conn_task_setup(struct icl_conn *ic, struct icl_pdu *ip,
struct ccb_scsiio *csio, uint32_t *task_tagp, void **prvp)
struct ccb_scsiio *csio, uint32_t *ittp, void **arg)
{
void *prv;
struct icl_cxgbei_conn *icc = ic_to_icc(ic);
struct toepcb *toep = icc->toep;
struct adapter *sc = icc->sc;
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
struct ppod_region *pr = &ci->pr;
struct ppod_reservation *prsv;
uint32_t itt;
int rc = 0;
*task_tagp = icl_conn_build_tasktag(ic, *task_tagp);
/* This is for the offload driver's state. Must not be set already. */
MPASS(arg != NULL);
MPASS(*arg == NULL);
prv = uma_zalloc(icl_transfer_zone, M_NOWAIT | M_ZERO);
if (prv == NULL)
return (ENOMEM);
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_IN ||
csio->dxfer_len < ci->ddp_threshold) {
no_ddp:
/*
* No DDP for this I/O. Allocate an ITT (based on the one
* passed in) that cannot be a valid hardware DDP tag in the
* iSCSI region.
*/
itt = *ittp & M_PPOD_TAG;
itt = V_PPOD_TAG(itt) | pr->pr_invalid_bit;
*ittp = htobe32(itt);
MPASS(*arg == NULL); /* State is maintained for DDP only. */
if (rc != 0)
counter_u64_add(ci->ddp_setup_error, 1);
return (0);
}
*prvp = prv;
/*
* Reserve resources for DDP, update the itt that should be used in the
* PDU, and save DDP specific state for this I/O in *arg.
*/
cxgbei_conn_task_reserve_itt(ic, prvp, csio, task_tagp);
prsv = uma_zalloc(prsv_zone, M_NOWAIT);
if (prsv == NULL) {
rc = ENOMEM;
goto no_ddp;
}
/* XXX add support for all CAM_DATA_ types */
MPASS((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR);
rc = t4_alloc_page_pods_for_buf(pr, (vm_offset_t)csio->data_ptr,
csio->dxfer_len, prsv);
if (rc != 0) {
uma_zfree(prsv_zone, prsv);
goto no_ddp;
}
rc = t4_write_page_pods_for_buf(sc, toep->ofld_txq, toep->tid, prsv,
(vm_offset_t)csio->data_ptr, csio->dxfer_len);
if (rc != 0) {
t4_free_page_pods(prsv);
uma_zfree(prsv_zone, prsv);
goto no_ddp;
}
*ittp = htobe32(prsv->prsv_tag);
*arg = prsv;
counter_u64_add(ci->ddp_setup_ok, 1);
return (0);
}
void
icl_cxgbei_conn_task_done(struct icl_conn *ic, void *prv)
icl_cxgbei_conn_task_done(struct icl_conn *ic, void *arg)
{
cxgbei_cleanup_task(ic, prv);
uma_zfree(icl_transfer_zone, prv);
if (arg != NULL) {
struct ppod_reservation *prsv = arg;
t4_free_page_pods(prsv);
uma_zfree(prsv_zone, prsv);
}
}
/* XXXNP: PDU should be passed in as parameter, like on the initiator. */
#define io_to_request_pdu(io) ((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr)
#define io_to_ppod_reservation(io) ((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND2].ptr)
int
icl_cxgbei_conn_transfer_setup(struct icl_conn *ic, union ctl_io *io,
uint32_t *transfer_tag, void **prvp)
uint32_t *tttp, void **arg)
{
void *prv;
struct icl_cxgbei_conn *icc = ic_to_icc(ic);
struct toepcb *toep = icc->toep;
struct ctl_scsiio *ctsio = &io->scsiio;
struct adapter *sc = icc->sc;
struct cxgbei_data *ci = sc->iscsi_ulp_softc;
struct ppod_region *pr = &ci->pr;
struct ppod_reservation *prsv;
uint32_t ttt;
int xferlen, rc = 0, alias;
*transfer_tag = icl_conn_build_tasktag(ic, *transfer_tag);
/* This is for the offload driver's state. Must not be set already. */
MPASS(arg != NULL);
MPASS(*arg == NULL);
prv = uma_zalloc(icl_transfer_zone, M_NOWAIT | M_ZERO);
if (prv == NULL)
return (ENOMEM);
if (ctsio->ext_data_filled == 0) {
int first_burst;
struct icl_pdu *ip = io_to_request_pdu(io);
vm_offset_t buf;
#ifdef INVARIANTS
struct icl_cxgbei_pdu *icp = ip_to_icp(ip);
*prvp = prv;
MPASS(icp->icp_signature == CXGBEI_PDU_SIGNATURE);
MPASS(ic == ip->ip_conn);
MPASS(ip->ip_bhs_mbuf != NULL);
#endif
first_burst = icl_pdu_data_segment_length(ip);
cxgbei_conn_transfer_reserve_ttt(ic, prvp, io, transfer_tag);
/*
* Note that ICL calls conn_transfer_setup even if the first
* burst had everything and there's nothing left to transfer.
*/
MPASS(ctsio->kern_data_len >= first_burst);
xferlen = ctsio->kern_data_len;
if (xferlen - first_burst < ci->ddp_threshold) {
no_ddp:
/*
* No DDP for this transfer. Allocate a TTT (based on
* the one passed in) that cannot be a valid hardware
* DDP tag in the iSCSI region.
*/
ttt = *tttp & M_PPOD_TAG;
ttt = V_PPOD_TAG(ttt) | pr->pr_invalid_bit;
*tttp = htobe32(ttt);
MPASS(io_to_ppod_reservation(io) == NULL);
if (rc != 0)
counter_u64_add(ci->ddp_setup_error, 1);
return (0);
}
if (ctsio->kern_sg_entries == 0)
buf = (vm_offset_t)ctsio->kern_data_ptr;
else if (ctsio->kern_sg_entries == 1) {
struct ctl_sg_entry *sgl = (void *)ctsio->kern_data_ptr;
MPASS(sgl->len == xferlen);
buf = (vm_offset_t)sgl->addr;
} else {
rc = EAGAIN; /* XXX implement */
goto no_ddp;
}
/*
* Reserve resources for DDP, update the ttt that should be used
* in the PDU, and save DDP specific state for this I/O.
*/
MPASS(io_to_ppod_reservation(io) == NULL);
prsv = uma_zalloc(prsv_zone, M_NOWAIT);
if (prsv == NULL) {
rc = ENOMEM;
goto no_ddp;
}
rc = t4_alloc_page_pods_for_buf(pr, buf, xferlen, prsv);
if (rc != 0) {
uma_zfree(prsv_zone, prsv);
goto no_ddp;
}
rc = t4_write_page_pods_for_buf(sc, toep->ofld_txq, toep->tid,
prsv, buf, xferlen);
if (rc != 0) {
t4_free_page_pods(prsv);
uma_zfree(prsv_zone, prsv);
goto no_ddp;
}
*tttp = htobe32(prsv->prsv_tag);
io_to_ppod_reservation(io) = prsv;
*arg = ctsio;
counter_u64_add(ci->ddp_setup_ok, 1);
return (0);
}
/*
* In the middle of an I/O. A non-NULL page pod reservation indicates
* that a DDP buffer is being used for the I/O.
*/
prsv = io_to_ppod_reservation(ctsio);
if (prsv == NULL)
goto no_ddp;
alias = (prsv->prsv_tag & pr->pr_alias_mask) >> pr->pr_alias_shift;
alias++;
prsv->prsv_tag &= ~pr->pr_alias_mask;
prsv->prsv_tag |= alias << pr->pr_alias_shift & pr->pr_alias_mask;
*tttp = htobe32(prsv->prsv_tag);
*arg = ctsio;
return (0);
}
void
icl_cxgbei_conn_transfer_done(struct icl_conn *ic, void *prv)
icl_cxgbei_conn_transfer_done(struct icl_conn *ic, void *arg)
{
cxgbei_cleanup_task(ic, prv);
uma_zfree(icl_transfer_zone, prv);
struct ctl_scsiio *ctsio = arg;
if (ctsio != NULL && ctsio->kern_data_len == ctsio->ext_data_filled) {
struct ppod_reservation *prsv;
prsv = io_to_ppod_reservation(ctsio);
MPASS(prsv != NULL);
t4_free_page_pods(prsv);
uma_zfree(prsv_zone, prsv);
}
}
static void
@ -882,9 +1065,12 @@ icl_cxgbei_mod_load(void)
{
int rc;
icl_transfer_zone = uma_zcreate("icl_transfer",
16 * 1024, NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, 0);
/*
* Space to track pagepod reservations.
*/
prsv_zone = uma_zcreate("Pagepod reservations",
sizeof(struct ppod_reservation), NULL, NULL, NULL, NULL,
CACHE_LINE_SIZE, 0);
refcount_init(&icl_cxgbei_ncons, 0);
@ -903,7 +1089,7 @@ icl_cxgbei_mod_unload(void)
icl_unregister("cxgbei", false);
uma_zdestroy(icl_transfer_zone);
uma_zdestroy(prsv_zone);
return (0);
}

View file

@ -155,7 +155,6 @@ int t4_register_uld(struct uld_info *);
int t4_unregister_uld(struct uld_info *);
int t4_activate_uld(struct adapter *, int);
int t4_deactivate_uld(struct adapter *, int);
void t4_iscsi_init(struct adapter *, u_int, const u_int *);
int uld_active(struct adapter *, int);
#endif
#endif

View file

@ -8929,16 +8929,6 @@ t4_db_dropped(struct adapter *sc)
}
#ifdef TCP_OFFLOAD
void
t4_iscsi_init(struct adapter *sc, u_int tag_mask, const u_int *pgsz_order)
{
t4_write_reg(sc, A_ULP_RX_ISCSI_TAGMASK, tag_mask);
t4_write_reg(sc, A_ULP_RX_ISCSI_PSZ, V_HPZ0(pgsz_order[0]) |
V_HPZ1(pgsz_order[1]) | V_HPZ2(pgsz_order[2]) |
V_HPZ3(pgsz_order[3]));
}
static int
toe_capability(struct vi_info *vi, int enable)
{

View file

@ -575,11 +575,20 @@ t4_tweak_chip_settings(struct adapter *sc)
V_TIMERVALUE5(us_to_core_ticks(sc, intr_timer[5]));
t4_write_reg(sc, A_SGE_TIMER_VALUE_4_AND_5, v);
/* 4K, 16K, 64K, 256K DDP "page sizes" */
/* 4K, 16K, 64K, 256K DDP "page sizes" for TDDP */
v = V_HPZ0(0) | V_HPZ1(2) | V_HPZ2(4) | V_HPZ3(6);
t4_write_reg(sc, A_ULP_RX_TDDP_PSZ, v);
m = v = F_TDDPTAGTCB;
/*
* 4K, 8K, 16K, 64K DDP "page sizes" for iSCSI DDP. These have been
* chosen with MAXPHYS = 128K in mind. The largest DDP buffer that we
* may have to deal with is MAXPHYS + 1 page.
*/
v = V_HPZ0(0) | V_HPZ1(1) | V_HPZ2(2) | V_HPZ3(4);
t4_write_reg(sc, A_ULP_RX_ISCSI_PSZ, v);
/* We use multiple DDP page sizes both in plain-TOE and ISCSI modes. */
m = v = F_TDDPTAGTCB | F_ISCSITAGTCB;
t4_set_reg_field(sc, A_ULP_RX_CTL, m, v);
m = V_INDICATESIZE(M_INDICATESIZE) | F_REARMDDPOFFSET |

View file

@ -1289,7 +1289,7 @@ netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen,
struct ifnet *ifp = rxr->hn_ifp;
struct mbuf *m_new;
int size, do_lro = 0, do_csum = 1;
int hash_type = M_HASHTYPE_OPAQUE_HASH;
int hash_type;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return (0);
@ -1335,28 +1335,29 @@ netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen,
do_csum = 0;
/* receive side checksum offload */
if (info->csum_info != NULL) {
if (info->csum_info != HN_NDIS_RXCSUM_INFO_INVALID) {
/* IP csum offload */
if (info->csum_info->receive.ip_csum_succeeded && do_csum) {
if ((info->csum_info & NDIS_RXCSUM_INFO_IPCS_OK) && do_csum) {
m_new->m_pkthdr.csum_flags |=
(CSUM_IP_CHECKED | CSUM_IP_VALID);
rxr->hn_csum_ip++;
}
/* TCP/UDP csum offload */
if ((info->csum_info->receive.tcp_csum_succeeded ||
info->csum_info->receive.udp_csum_succeeded) && do_csum) {
if ((info->csum_info & (NDIS_RXCSUM_INFO_UDPCS_OK |
NDIS_RXCSUM_INFO_TCPCS_OK)) && do_csum) {
m_new->m_pkthdr.csum_flags |=
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
m_new->m_pkthdr.csum_data = 0xffff;
if (info->csum_info->receive.tcp_csum_succeeded)
if (info->csum_info & NDIS_RXCSUM_INFO_TCPCS_OK)
rxr->hn_csum_tcp++;
else
rxr->hn_csum_udp++;
}
if (info->csum_info->receive.ip_csum_succeeded &&
info->csum_info->receive.tcp_csum_succeeded)
if ((info->csum_info &
(NDIS_RXCSUM_INFO_TCPCS_OK | NDIS_RXCSUM_INFO_IPCS_OK)) ==
(NDIS_RXCSUM_INFO_TCPCS_OK | NDIS_RXCSUM_INFO_IPCS_OK))
do_lro = 1;
} else {
const struct ether_header *eh;
@ -1420,13 +1421,13 @@ netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen,
m_new->m_flags |= M_VLANTAG;
}
if (info->hash_info != NULL && info->hash_value != NULL) {
if (info->hash_info != HN_NDIS_HASH_INFO_INVALID) {
rxr->hn_rss_pkts++;
m_new->m_pkthdr.flowid = info->hash_value->hash_value;
if ((info->hash_info->hash_info & NDIS_HASH_FUNCTION_MASK) ==
m_new->m_pkthdr.flowid = info->hash_value;
hash_type = M_HASHTYPE_OPAQUE_HASH;
if ((info->hash_info & NDIS_HASH_FUNCTION_MASK) ==
NDIS_HASH_FUNCTION_TOEPLITZ) {
uint32_t type =
(info->hash_info->hash_info & NDIS_HASH_TYPE_MASK);
uint32_t type = (info->hash_info & NDIS_HASH_TYPE_MASK);
switch (type) {
case NDIS_HASH_IPV4:
@ -1455,12 +1456,8 @@ netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen,
}
}
} else {
if (info->hash_value != NULL) {
m_new->m_pkthdr.flowid = info->hash_value->hash_value;
} else {
m_new->m_pkthdr.flowid = rxr->hn_rx_idx;
hash_type = M_HASHTYPE_OPAQUE;
}
m_new->m_pkthdr.flowid = rxr->hn_rx_idx;
hash_type = M_HASHTYPE_OPAQUE;
}
M_HASHTYPE_SET(m_new, hash_type);

View file

@ -157,9 +157,8 @@ hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
uint32_t mask = 0, len;
info->vlan_info = HN_NDIS_VLAN_INFO_INVALID;
info->csum_info = NULL;
info->hash_info = NULL;
info->hash_value = NULL;
info->csum_info = HN_NDIS_RXCSUM_INFO_INVALID;
info->hash_info = HN_NDIS_HASH_INFO_INVALID;
if (rpkt->per_pkt_info_offset == 0)
return (0);
@ -192,34 +191,31 @@ hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
data = pi->rm_data;
switch (pi->rm_type) {
case ieee_8021q_info:
case NDIS_PKTINFO_TYPE_VLAN:
if (__predict_false(dlen < NDIS_VLAN_INFO_SIZE))
return (EINVAL);
info->vlan_info = *((const uint32_t *)data);
mask |= HV_RF_RECVINFO_VLAN;
break;
case tcpip_chksum_info:
if (__predict_false(dlen <
sizeof(rndis_tcp_ip_csum_info)))
case NDIS_PKTINFO_TYPE_CSUM:
if (__predict_false(dlen < NDIS_RXCSUM_INFO_SIZE))
return (EINVAL);
info->csum_info = data;
info->csum_info = *((const uint32_t *)data);
mask |= HV_RF_RECVINFO_CSUM;
break;
case nbl_hash_value:
if (__predict_false(dlen <
sizeof(struct rndis_hash_value)))
case HN_NDIS_PKTINFO_TYPE_HASHVAL:
if (__predict_false(dlen < HN_NDIS_HASH_VALUE_SIZE))
return (EINVAL);
info->hash_value = data;
info->hash_value = *((const uint32_t *)data);
mask |= HV_RF_RECVINFO_HASHVAL;
break;
case nbl_hash_info:
if (__predict_false(dlen <
sizeof(struct rndis_hash_info)))
case HN_NDIS_PKTINFO_TYPE_HASHINF:
if (__predict_false(dlen < HN_NDIS_HASH_INFO_SIZE))
return (EINVAL);
info->hash_info = data;
info->hash_info = *((const uint32_t *)data);
mask |= HV_RF_RECVINFO_HASHINF;
break;
@ -235,6 +231,13 @@ hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
pi = (const struct rndis_pktinfo *)
((const uint8_t *)pi + pi->rm_size);
}
/*
* Final fixup.
* - If there is no hash value, invalidate the hash info.
*/
if ((mask & HV_RF_RECVINFO_HASHVAL) == 0)
info->hash_info = HN_NDIS_HASH_INFO_INVALID;
return (0);
}

View file

@ -208,4 +208,17 @@ struct hn_nvs_rndis_ack {
} __packed;
CTASSERT(sizeof(struct hn_nvs_rndis_ack) >= HN_NVS_REQSIZE_MIN);
/*
* RNDIS extension
*/
/* Per-packet hash info */
#define HN_NDIS_HASH_INFO_SIZE sizeof(uint32_t)
#define HN_NDIS_PKTINFO_TYPE_HASHINF NDIS_PKTINFO_TYPE_ORIG_NBLIST
/* NDIS_HASH_ */
/* Per-packet hash value */
#define HN_NDIS_HASH_VALUE_SIZE sizeof(uint32_t)
#define HN_NDIS_PKTINFO_TYPE_HASHVAL NDIS_PKTINFO_TYPE_PKT_CANCELID
#endif /* !_IF_HNREG_H_ */

View file

@ -56,12 +56,14 @@ struct ndis_8021q_info_;
struct rndis_tcp_ip_csum_info_;
#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff
#define HN_NDIS_RXCSUM_INFO_INVALID 0
#define HN_NDIS_HASH_INFO_INVALID 0
struct hn_recvinfo {
uint32_t vlan_info;
const struct rndis_tcp_ip_csum_info_ *csum_info;
const struct rndis_hash_info *hash_info;
const struct rndis_hash_value *hash_value;
uint32_t csum_info;
uint32_t hash_info;
uint32_t hash_value;
};
#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \

View file

@ -219,4 +219,16 @@ struct ndis_rssprm_toeplitz {
#define NDIS_VLAN_INFO_CFI(inf) (((inf) & NDIS_VLAN_INFO_CFI_MASK) >> 3)
#define NDIS_VLAN_INFO_PRI(inf) ((inf) & NDIS_VLAN_INFO_PRI_MASK)
/* Reception checksum */
#define NDIS_RXCSUM_INFO_SIZE sizeof(uint32_t)
#define NDIS_RXCSUM_INFO_TCPCS_FAILED 0x0001
#define NDIS_RXCSUM_INFO_UDPCS_FAILED 0x0002
#define NDIS_RXCSUM_INFO_IPCS_FAILED 0x0004
#define NDIS_RXCSUM_INFO_TCPCS_OK 0x0008
#define NDIS_RXCSUM_INFO_UDPCS_OK 0x0010
#define NDIS_RXCSUM_INFO_IPCS_OK 0x0020
#define NDIS_RXCSUM_INFO_LOOPBACK 0x0040
#define NDIS_RXCSUM_INFO_TCPCS_INVAL 0x0080
#define NDIS_RXCSUM_INFO_IPCS_INVAL 0x0100
#endif /* !_NET_NDIS_H_ */

View file

@ -69,7 +69,7 @@ vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc)
if (error)
return;
if (dlen < sizeof(struct vmbus_icmsg_hdr)) {
if (dlen < sizeof(*hdr)) {
device_printf(sc->ic_dev, "invalid data len %d\n", dlen);
return;
}

View file

@ -22,28 +22,23 @@
* 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$
*/
/*
* A common driver for all hyper-V util services.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/reboot.h>
#include <sys/timetc.h>
#include <sys/syscallsubr.h>
#include <sys/systm.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
#include <dev/hyperv/utilities/hv_utilreg.h>
#include "hv_util.h"
#include <dev/hyperv/utilities/hv_util.h>
#include <dev/hyperv/utilities/vmbus_icreg.h>
#include "vmbus_if.h"
static const struct vmbus_ic_desc vmbus_shutdown_descs[] = {
@ -56,73 +51,78 @@ static const struct vmbus_ic_desc vmbus_shutdown_descs[] = {
VMBUS_IC_DESC_END
};
/**
* Shutdown
*/
static void
hv_shutdown_cb(struct vmbus_channel *channel, void *context)
vmbus_shutdown_cb(struct vmbus_channel *chan, void *xsc)
{
uint8_t* buf;
uint8_t execute_shutdown = 0;
hv_vmbus_icmsg_hdr* icmsghdrp;
uint32_t recv_len;
uint64_t request_id;
int ret;
hv_vmbus_shutdown_msg_data* shutdown_msg;
hv_util_sc *softc;
struct hv_util_sc *sc = xsc;
struct vmbus_icmsg_hdr *hdr;
struct vmbus_icmsg_shutdown *msg;
int dlen, error, do_shutdown = 0;
uint64_t xactid;
void *data;
softc = (hv_util_sc*)context;
buf = softc->receive_buffer;
/*
* Receive request.
*/
data = sc->receive_buffer;
dlen = sc->ic_buflen;
error = vmbus_chan_recv(chan, data, &dlen, &xactid);
KASSERT(error != ENOBUFS, ("icbuf is not large enough"));
if (error)
return;
recv_len = softc->ic_buflen;
ret = vmbus_chan_recv(channel, buf, &recv_len, &request_id);
KASSERT(ret != ENOBUFS, ("hvshutdown recvbuf is not large enough"));
/* XXX check recv_len to make sure that it contains enough data */
if (dlen < sizeof(*hdr)) {
device_printf(sc->ic_dev, "invalid data len %d\n", dlen);
return;
}
hdr = data;
if ((ret == 0) && recv_len > 0) {
icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
&buf[sizeof(struct hv_vmbus_pipe_hdr)];
if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
int error;
error = vmbus_ic_negomsg(softc, buf, &recv_len);
/*
* Update request, which will be echoed back as response.
*/
switch (hdr->ic_type) {
case VMBUS_ICMSG_TYPE_NEGOTIATE:
error = vmbus_ic_negomsg(sc, data, &dlen);
if (error)
return;
} else {
shutdown_msg =
(struct hv_vmbus_shutdown_msg_data *)
&buf[sizeof(struct hv_vmbus_pipe_hdr) +
sizeof(struct hv_vmbus_icmsg_hdr)];
break;
switch (shutdown_msg->flags) {
case 0:
case 1:
icmsghdrp->status = HV_S_OK;
execute_shutdown = 1;
if(bootverbose)
printf("Shutdown request received -"
" graceful shutdown initiated\n");
break;
default:
icmsghdrp->status = HV_E_FAIL;
execute_shutdown = 0;
printf("Shutdown request received -"
" Invalid request\n");
break;
}
}
case VMBUS_ICMSG_TYPE_SHUTDOWN:
if (dlen < VMBUS_ICMSG_SHUTDOWN_SIZE_MIN) {
device_printf(sc->ic_dev, "invalid shutdown len %d\n",
dlen);
return;
}
msg = data;
icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION |
HV_ICMSGHDRFLAG_RESPONSE;
/* XXX ic_flags definition? */
if (msg->ic_haltflags == 0 || msg->ic_haltflags == 1) {
device_printf(sc->ic_dev, "shutdown requested\n");
hdr->ic_status = VMBUS_ICMSG_STATUS_OK;
do_shutdown = 1;
} else {
device_printf(sc->ic_dev, "unknown shutdown flags "
"0x%08x\n", msg->ic_haltflags);
hdr->ic_status = VMBUS_ICMSG_STATUS_FAIL;
}
break;
vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0,
buf, recv_len, request_id);
default:
device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type);
break;
}
if (execute_shutdown)
shutdown_nice(RB_POWEROFF);
/*
* Send response by echoing the updated request back.
*/
hdr->ic_flags = VMBUS_ICMSG_FLAG_XACT | VMBUS_ICMSG_FLAG_RESP;
error = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
data, dlen, xactid);
if (error)
device_printf(sc->ic_dev, "resp send failed: %d\n", error);
if (do_shutdown)
shutdown_nice(RB_POWEROFF);
}
static int
@ -135,7 +135,8 @@ hv_shutdown_probe(device_t dev)
static int
hv_shutdown_attach(device_t dev)
{
return hv_util_attach(dev, hv_shutdown_cb);
return (hv_util_attach(dev, vmbus_shutdown_cb));
}
static device_method_t shutdown_methods[] = {

View file

@ -22,37 +22,25 @@
* 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$
*/
/*
* A common driver for all hyper-V util services.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/reboot.h>
#include <sys/timetc.h>
#include <sys/syscallsubr.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
#include <dev/hyperv/utilities/hv_utilreg.h>
#include "hv_util.h"
#include "vmbus_if.h"
#include <dev/hyperv/utilities/hv_util.h>
#include <dev/hyperv/utilities/vmbus_icreg.h>
#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */
#define HV_ICTIMESYNCFLAG_PROBE 0
#define HV_ICTIMESYNCFLAG_SYNC 1
#define HV_ICTIMESYNCFLAG_SAMPLE 2
#define HV_NANO_SEC_PER_SEC 1000000000
#define HV_NANO_SEC_PER_MILLI_SEC 1000000
#include "vmbus_if.h"
static const struct vmbus_ic_desc vmbus_timesync_descs[] = {
{
@ -64,135 +52,144 @@ static const struct vmbus_ic_desc vmbus_timesync_descs[] = {
VMBUS_IC_DESC_END
};
struct hv_ictimesync_data {
uint64_t parenttime;
uint64_t childtime;
uint64_t roundtriptime;
uint8_t flags;
} __packed;
/*
* Globals
*/
SYSCTL_NODE(_hw, OID_AUTO, hvtimesync, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
"Hyper-V timesync interface");
/* Ignore the sync request when set to 1. */
static int ignore_sync_req = 0;
SYSCTL_INT(_hw_hvtimesync, OID_AUTO, ignore_sync_req, CTLFLAG_RWTUN,
&ignore_sync_req, 0,
"Ignore the sync request when set to 1.");
static int vmbus_ts_ignore_sync = 0;
SYSCTL_INT(_hw_hvtimesync, OID_AUTO, ignore_sync, CTLFLAG_RWTUN,
&vmbus_ts_ignore_sync, 0, "Ignore the sync request.");
/*
* Trigger sample sync when drift exceeds threshold (ms).
* Ignore the sample request when set to 0.
*/
static int sample_drift = 100;
SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_drift, CTLFLAG_RWTUN,
&sample_drift, 0,
"Threshold that makes sample request trigger the sync.");
static int vmbus_ts_sample_thresh = 100;
SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_thresh, CTLFLAG_RWTUN,
&vmbus_ts_sample_thresh, 0,
"Threshold that makes sample request trigger the sync (unit: ms).");
/**
* @brief Synchronize time with host after reboot, restore, etc.
*
* ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
* After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
* message after the timesync channel is opened. Since the hv_utils module is
* loaded after hv_vmbus, the first message is usually missed. The other
* thing is, systime is automatically set to emulated hardware clock which may
* not be UTC time or in the same time zone. So, to override these effects, we
* use the first 50 time samples for initial system time setting.
*/
static inline
void hv_adj_guesttime(hv_util_sc *sc, uint64_t hosttime, uint8_t flags)
static int vmbus_ts_sample_verbose = 0;
SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_verbose, CTLFLAG_RWTUN,
&vmbus_ts_sample_verbose, 0, "Increase sample request verbosity.");
static void
vmbus_timesync(struct hv_util_sc *sc, uint64_t hvtime, uint8_t tsflags)
{
struct timespec guest_ts, host_ts;
uint64_t host_tns, guest_tns;
int64_t diff;
int error;
struct timespec vm_ts;
uint64_t hv_ns, vm_ns;
host_tns = (hosttime - HV_WLTIMEDELTA) * 100;
host_ts.tv_sec = (time_t)(host_tns/HV_NANO_SEC_PER_SEC);
host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC);
hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE) * VMBUS_ICMSG_TS_FACTOR;
nanotime(&vm_ts);
vm_ns = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec;
nanotime(&guest_ts);
guest_tns = guest_ts.tv_sec * HV_NANO_SEC_PER_SEC + guest_ts.tv_nsec;
if ((tsflags & VMBUS_ICMSG_TS_FLAG_SYNC) && !vmbus_ts_ignore_sync) {
struct timespec hv_ts;
if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0 && ignore_sync_req == 0) {
if (bootverbose) {
device_printf(sc->ic_dev, "handle sync request "
"{host: %ju, guest: %ju}\n",
(uintmax_t)host_tns, (uintmax_t)guest_tns);
device_printf(sc->ic_dev, "apply sync request, "
"hv: %ju, vm: %ju\n",
(uintmax_t)hv_ns, (uintmax_t)vm_ns);
}
error = kern_clock_settime(curthread, CLOCK_REALTIME,
&host_ts);
hv_ts.tv_sec = hv_ns / NANOSEC;
hv_ts.tv_nsec = hv_ns % NANOSEC;
kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts);
/* Done! */
return;
}
if ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0 && sample_drift != 0) {
if (bootverbose) {
device_printf(sc->ic_dev, "handle sample request "
"{host: %ju, guest: %ju}\n",
(uintmax_t)host_tns, (uintmax_t)guest_tns);
if ((tsflags & VMBUS_ICMSG_TS_FLAG_SAMPLE) &&
vmbus_ts_sample_thresh > 0) {
int64_t diff;
if (vmbus_ts_sample_verbose) {
device_printf(sc->ic_dev, "sample request, "
"hv: %ju, vm: %ju\n",
(uintmax_t)hv_ns, (uintmax_t)vm_ns);
}
diff = (int64_t)(host_tns - guest_tns) / HV_NANO_SEC_PER_MILLI_SEC;
if (diff > sample_drift || diff < -sample_drift) {
error = kern_clock_settime(curthread, CLOCK_REALTIME,
&host_ts);
if (bootverbose)
device_printf(sc->ic_dev, "trigger sample sync");
if (hv_ns > vm_ns)
diff = hv_ns - vm_ns;
else
diff = vm_ns - hv_ns;
/* nanosec -> millisec */
diff /= 1000000;
if (diff > vmbus_ts_sample_thresh) {
struct timespec hv_ts;
if (bootverbose) {
device_printf(sc->ic_dev,
"apply sample request, hv: %ju, vm: %ju\n",
(uintmax_t)hv_ns, (uintmax_t)vm_ns);
}
hv_ts.tv_sec = hv_ns / NANOSEC;
hv_ts.tv_nsec = hv_ns % NANOSEC;
kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts);
}
/* Done */
return;
}
}
/**
* Time Sync Channel message handler
*/
static void
hv_timesync_cb(struct vmbus_channel *channel, void *context)
vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc)
{
hv_vmbus_icmsg_hdr* icmsghdrp;
uint32_t recvlen;
uint64_t requestId;
int ret;
uint8_t* time_buf;
struct hv_ictimesync_data* timedatap;
hv_util_sc *softc;
struct hv_util_sc *sc = xsc;
struct vmbus_icmsg_hdr *hdr;
const struct vmbus_icmsg_timesync *msg;
int dlen, error;
uint64_t xactid;
void *data;
softc = (hv_util_sc*)context;
time_buf = softc->receive_buffer;
/*
* Receive request.
*/
data = sc->receive_buffer;
dlen = sc->ic_buflen;
error = vmbus_chan_recv(chan, data, &dlen, &xactid);
KASSERT(error != ENOBUFS, ("icbuf is not large enough"));
if (error)
return;
recvlen = softc->ic_buflen;
ret = vmbus_chan_recv(channel, time_buf, &recvlen, &requestId);
KASSERT(ret != ENOBUFS, ("hvtimesync recvbuf is not large enough"));
/* XXX check recvlen to make sure that it contains enough data */
if (dlen < sizeof(*hdr)) {
device_printf(sc->ic_dev, "invalid data len %d\n", dlen);
return;
}
hdr = data;
if ((ret == 0) && recvlen > 0) {
icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &time_buf[
sizeof(struct hv_vmbus_pipe_hdr)];
if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
int error;
error = vmbus_ic_negomsg(softc, time_buf, &recvlen);
/*
* Update request, which will be echoed back as response.
*/
switch (hdr->ic_type) {
case VMBUS_ICMSG_TYPE_NEGOTIATE:
error = vmbus_ic_negomsg(sc, data, &dlen);
if (error)
return;
} else {
timedatap = (struct hv_ictimesync_data *) &time_buf[
sizeof(struct hv_vmbus_pipe_hdr) +
sizeof(struct hv_vmbus_icmsg_hdr)];
hv_adj_guesttime(softc, timedatap->parenttime, timedatap->flags);
}
break;
icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION
| HV_ICMSGHDRFLAG_RESPONSE;
case VMBUS_ICMSG_TYPE_TIMESYNC:
if (dlen < sizeof(*msg)) {
device_printf(sc->ic_dev, "invalid timesync len %d\n",
dlen);
return;
}
msg = data;
vmbus_timesync(sc, msg->ic_hvtime, msg->ic_tsflags);
break;
vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0,
time_buf, recvlen, requestId);
default:
device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type);
break;
}
/*
* Send response by echoing the updated request back.
*/
hdr->ic_flags = VMBUS_ICMSG_FLAG_XACT | VMBUS_ICMSG_FLAG_RESP;
error = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
data, dlen, xactid);
if (error)
device_printf(sc->ic_dev, "resp send failed: %d\n", error);
}
static int
@ -205,20 +202,15 @@ hv_timesync_probe(device_t dev)
static int
hv_timesync_attach(device_t dev)
{
return hv_util_attach(dev, hv_timesync_cb);
}
static int
hv_timesync_detach(device_t dev)
{
return hv_util_detach(dev);
return (hv_util_attach(dev, vmbus_timesync_cb));
}
static device_method_t timesync_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, hv_timesync_probe),
DEVMETHOD(device_attach, hv_timesync_attach),
DEVMETHOD(device_detach, hv_timesync_detach),
DEVMETHOD(device_detach, hv_util_detach),
{ 0, 0 }
};

View file

@ -91,4 +91,35 @@ struct vmbus_icmsg_heartbeat {
#define VMBUS_ICMSG_HEARTBEAT_SIZE_MIN \
__offsetof(struct vmbus_icmsg_heartbeat, ic_rsvd[0])
/* VMBUS_ICMSG_TYPE_SHUTDOWN */
struct vmbus_icmsg_shutdown {
struct vmbus_icmsg_hdr ic_hdr;
uint32_t ic_code;
uint32_t ic_timeo;
uint32_t ic_haltflags;
uint8_t ic_msg[2048];
} __packed;
#define VMBUS_ICMSG_SHUTDOWN_SIZE_MIN \
__offsetof(struct vmbus_icmsg_shutdown, ic_msg[0])
/* VMBUS_ICMSG_TYPE_TIMESYNC */
struct vmbus_icmsg_timesync {
struct vmbus_icmsg_hdr ic_hdr;
uint64_t ic_hvtime;
uint64_t ic_vmtime;
uint64_t ic_rtt;
uint8_t ic_tsflags; /* VMBUS_ICMSG_TS_FLAG_ */
} __packed;
#define VMBUS_ICMSG_TS_FLAG_SYNC 0x01
#define VMBUS_ICMSG_TS_FLAG_SAMPLE 0x02
/* XXX consolidate w/ hyperv */
#define VMBUS_ICMSG_TS_BASE 116444736000000000ULL
#define VMBUS_ICMSG_TS_FACTOR 100ULL
#ifndef NANOSEC
#define NANOSEC 1000000000ULL
#endif
#endif /* !_VMBUS_ICREG_H_ */

View file

@ -750,13 +750,13 @@ ioat_process_events(struct ioat_softc *ioat)
* Fatal programming error on this DMA channel. Flush any outstanding
* work with error status and restart the engine.
*/
ioat_log_message(0, "Channel halted due to fatal programming error\n");
mtx_lock(&ioat->submit_lock);
mtx_lock(&ioat->cleanup_lock);
ioat->quiescing = TRUE;
chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET);
ioat_halted_debug(ioat, chanerr);
if (1 <= g_ioat_debug_level)
ioat_halted_debug(ioat, chanerr);
ioat->stats.last_halt_chanerr = chanerr;
while (ioat_get_active(ioat) > 0) {

View file

@ -1678,13 +1678,39 @@ sccnkbdunlock(sc_softc_t *sc, struct sc_cnstate *sp)
static void
sccnscrlock(sc_softc_t *sc, struct sc_cnstate *sp)
{
SC_VIDEO_LOCK(sc);
int retries;
/**
* Locking method:
* - if kdb_active and video_mtx is not owned by anyone, then lock
* by kdb remaining active
* - if !kdb_active, try to acquire video_mtx without blocking or
* recursing; if we get it then it works normally.
* Note that video_mtx is especially unusable if we already own it,
* since then it is protecting something and syscons is not reentrant
* enough to ignore the protection even in the kdb_active case.
*/
if (kdb_active) {
sp->kdb_locked = sc->video_mtx.mtx_lock == MTX_UNOWNED || panicstr;
sp->mtx_locked = FALSE;
} else {
sp->kdb_locked = FALSE;
for (retries = 0; retries < 1000; retries++) {
sp->mtx_locked = mtx_trylock_spin_flags(&sc->video_mtx,
MTX_QUIET) != 0 || panicstr;
if (sp->mtx_locked)
break;
DELAY(1);
}
}
}
static void
sccnscrunlock(sc_softc_t *sc, struct sc_cnstate *sp)
{
SC_VIDEO_UNLOCK(sc);
if (sp->mtx_locked)
mtx_unlock_spin(&sc->video_mtx);
sp->mtx_locked = sp->kdb_locked = FALSE;
}
static void
@ -1721,6 +1747,8 @@ over_keyboard: ;
/* The screen is opened iff locking it succeeds. */
sccnscrlock(sc, sp);
if (!sp->kdb_locked && !sp->mtx_locked)
return;
sp->scr_opened = TRUE;
/* The screen switch is optional. */
@ -1797,6 +1825,10 @@ sc_cnungrab(struct consdev *cp)
atomic_add_int(&sc->grab_level, -1);
}
static char sc_cnputc_log[0x1000];
static u_int sc_cnputc_loghead;
static u_int sc_cnputc_logtail;
static void
sc_cnputc(struct consdev *cd, int c)
{
@ -1808,12 +1840,28 @@ sc_cnputc(struct consdev *cd, int c)
struct tty *tp;
#endif
#endif /* !SC_NO_HISTORY */
u_int head;
int s;
/* assert(sc_console != NULL) */
sccnopen(scp->sc, &st, 0);
/*
* Log the output.
*
* In the unlocked case, the logging is intentionally only
* perfectly atomic for the indexes.
*/
head = atomic_fetchadd_int(&sc_cnputc_loghead, 1);
sc_cnputc_log[head % sizeof(sc_cnputc_log)] = c;
/*
* If we couldn't open, return to defer output.
*/
if (!st.scr_opened)
return;
#ifndef SC_NO_HISTORY
if (scp == scp->sc->cur_scp && scp->status & SLKED) {
scp->status &= ~SLKED;
@ -1841,8 +1889,14 @@ sc_cnputc(struct consdev *cd, int c)
}
#endif /* !SC_NO_HISTORY */
buf[0] = c;
sc_puts(scp, buf, 1, 1);
/* Play any output still in the log (our char may already be done). */
while (sc_cnputc_logtail != atomic_load_acq_int(&sc_cnputc_loghead)) {
buf[0] = sc_cnputc_log[sc_cnputc_logtail++ % sizeof(sc_cnputc_log)];
if (atomic_load_acq_int(&sc_cnputc_loghead) - sc_cnputc_logtail >=
sizeof(sc_cnputc_log))
continue;
sc_puts(scp, buf, 1, 1);
}
s = spltty(); /* block sckbdevent and scrn_timer */
sccnupdate(scp);
@ -1883,9 +1937,11 @@ sc_cngetc_locked(struct sc_cnstate *sp)
* Stop the screen saver and update the screen if necessary.
* What if we have been running in the screen saver code... XXX
*/
sc_touch_scrn_saver();
if (sp->scr_opened)
sc_touch_scrn_saver();
scp = sc_console->sc->cur_scp; /* XXX */
sccnupdate(scp);
if (sp->scr_opened)
sccnupdate(scp);
if (fkeycp < fkey.len)
return fkey.str[fkeycp++];

View file

@ -191,6 +191,8 @@ struct tty;
struct sc_cnstate {
u_char kbd_locked;
u_char kdb_locked;
u_char mtx_locked;
u_char kbd_opened;
u_char scr_opened;
};

View file

@ -189,46 +189,46 @@ SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl,
* The array below categorizes the signals and their default actions
* according to the following properties:
*/
#define SA_KILL 0x01 /* terminates process by default */
#define SA_CORE 0x02 /* ditto and coredumps */
#define SA_STOP 0x04 /* suspend process */
#define SA_TTYSTOP 0x08 /* ditto, from tty */
#define SA_IGNORE 0x10 /* ignore by default */
#define SA_CONT 0x20 /* continue if suspended */
#define SA_CANTMASK 0x40 /* non-maskable, catchable */
#define SIGPROP_KILL 0x01 /* terminates process by default */
#define SIGPROP_CORE 0x02 /* ditto and coredumps */
#define SIGPROP_STOP 0x04 /* suspend process */
#define SIGPROP_TTYSTOP 0x08 /* ditto, from tty */
#define SIGPROP_IGNORE 0x10 /* ignore by default */
#define SIGPROP_CONT 0x20 /* continue if suspended */
#define SIGPROP_CANTMASK 0x40 /* non-maskable, catchable */
static int sigproptbl[NSIG] = {
SA_KILL, /* SIGHUP */
SA_KILL, /* SIGINT */
SA_KILL|SA_CORE, /* SIGQUIT */
SA_KILL|SA_CORE, /* SIGILL */
SA_KILL|SA_CORE, /* SIGTRAP */
SA_KILL|SA_CORE, /* SIGABRT */
SA_KILL|SA_CORE, /* SIGEMT */
SA_KILL|SA_CORE, /* SIGFPE */
SA_KILL, /* SIGKILL */
SA_KILL|SA_CORE, /* SIGBUS */
SA_KILL|SA_CORE, /* SIGSEGV */
SA_KILL|SA_CORE, /* SIGSYS */
SA_KILL, /* SIGPIPE */
SA_KILL, /* SIGALRM */
SA_KILL, /* SIGTERM */
SA_IGNORE, /* SIGURG */
SA_STOP, /* SIGSTOP */
SA_STOP|SA_TTYSTOP, /* SIGTSTP */
SA_IGNORE|SA_CONT, /* SIGCONT */
SA_IGNORE, /* SIGCHLD */
SA_STOP|SA_TTYSTOP, /* SIGTTIN */
SA_STOP|SA_TTYSTOP, /* SIGTTOU */
SA_IGNORE, /* SIGIO */
SA_KILL, /* SIGXCPU */
SA_KILL, /* SIGXFSZ */
SA_KILL, /* SIGVTALRM */
SA_KILL, /* SIGPROF */
SA_IGNORE, /* SIGWINCH */
SA_IGNORE, /* SIGINFO */
SA_KILL, /* SIGUSR1 */
SA_KILL, /* SIGUSR2 */
SIGPROP_KILL, /* SIGHUP */
SIGPROP_KILL, /* SIGINT */
SIGPROP_KILL | SIGPROP_CORE, /* SIGQUIT */
SIGPROP_KILL | SIGPROP_CORE, /* SIGILL */
SIGPROP_KILL | SIGPROP_CORE, /* SIGTRAP */
SIGPROP_KILL | SIGPROP_CORE, /* SIGABRT */
SIGPROP_KILL | SIGPROP_CORE, /* SIGEMT */
SIGPROP_KILL | SIGPROP_CORE, /* SIGFPE */
SIGPROP_KILL, /* SIGKILL */
SIGPROP_KILL | SIGPROP_CORE, /* SIGBUS */
SIGPROP_KILL | SIGPROP_CORE, /* SIGSEGV */
SIGPROP_KILL | SIGPROP_CORE, /* SIGSYS */
SIGPROP_KILL, /* SIGPIPE */
SIGPROP_KILL, /* SIGALRM */
SIGPROP_KILL, /* SIGTERM */
SIGPROP_IGNORE, /* SIGURG */
SIGPROP_STOP, /* SIGSTOP */
SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTSTP */
SIGPROP_IGNORE | SIGPROP_CONT, /* SIGCONT */
SIGPROP_IGNORE, /* SIGCHLD */
SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTTIN */
SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTTOU */
SIGPROP_IGNORE, /* SIGIO */
SIGPROP_KILL, /* SIGXCPU */
SIGPROP_KILL, /* SIGXFSZ */
SIGPROP_KILL, /* SIGVTALRM */
SIGPROP_KILL, /* SIGPROF */
SIGPROP_IGNORE, /* SIGWINCH */
SIGPROP_IGNORE, /* SIGINFO */
SIGPROP_KILL, /* SIGUSR1 */
SIGPROP_KILL, /* SIGUSR2 */
};
static void reschedule_signals(struct proc *p, sigset_t block, int flags);
@ -755,7 +755,7 @@ kern_sigaction(struct thread *td, int sig, const struct sigaction *act,
* have to restart the process.
*/
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
(sigprop(sig) & SA_IGNORE &&
(sigprop(sig) & SIGPROP_IGNORE &&
ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) {
/* never to be seen again */
sigqueue_delete_proc(p, sig);
@ -923,7 +923,7 @@ siginit(p)
ps = p->p_sigacts;
mtx_lock(&ps->ps_mtx);
for (i = 1; i <= NSIG; i++) {
if (sigprop(i) & SA_IGNORE && i != SIGCONT) {
if (sigprop(i) & SIGPROP_IGNORE && i != SIGCONT) {
SIGADDSET(ps->ps_sigignore, i);
}
}
@ -940,7 +940,7 @@ sigdflt(struct sigacts *ps, int sig)
mtx_assert(&ps->ps_mtx, MA_OWNED);
SIGDELSET(ps->ps_sigcatch, sig);
if ((sigprop(sig) & SA_IGNORE) != 0 && sig != SIGCONT)
if ((sigprop(sig) & SIGPROP_IGNORE) != 0 && sig != SIGCONT)
SIGADDSET(ps->ps_sigignore, sig);
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
SIGDELSET(ps->ps_siginfo, sig);
@ -969,7 +969,7 @@ execsigs(struct proc *p)
while (SIGNOTEMPTY(ps->ps_sigcatch)) {
sig = sig_ffs(&ps->ps_sigcatch);
sigdflt(ps, sig);
if ((sigprop(sig) & SA_IGNORE) != 0)
if ((sigprop(sig) & SIGPROP_IGNORE) != 0)
sigqueue_delete_proc(p, sig);
}
@ -2154,16 +2154,16 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
intrval = ERESTART;
mtx_unlock(&ps->ps_mtx);
if (prop & SA_CONT)
if (prop & SIGPROP_CONT)
sigqueue_delete_stopmask_proc(p);
else if (prop & SA_STOP) {
else if (prop & SIGPROP_STOP) {
/*
* If sending a tty stop signal to a member of an orphaned
* process group, discard the signal here if the action
* is default; don't stop the process below if sleeping,
* and don't clear any pending SIGCONT.
*/
if ((prop & SA_TTYSTOP) &&
if ((prop & SIGPROP_TTYSTOP) &&
(p->p_pgrp->pg_jobc == 0) &&
(action == SIG_DFL)) {
if (ksi && (ksi->ksi_flags & KSI_INS))
@ -2188,7 +2188,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
* except that stopped processes must be continued by SIGCONT.
*/
if (action == SIG_HOLD &&
!((prop & SA_CONT) && (p->p_flag & P_STOPPED_SIG)))
!((prop & SIGPROP_CONT) && (p->p_flag & P_STOPPED_SIG)))
return (ret);
/*
* SIGKILL: Remove procfs STOPEVENTs and ptrace events.
@ -2228,7 +2228,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
goto runfast;
}
if (prop & SA_CONT) {
if (prop & SIGPROP_CONT) {
/*
* If traced process is already stopped,
* then no further action is necessary.
@ -2278,7 +2278,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
goto out;
}
if (prop & SA_STOP) {
if (prop & SIGPROP_STOP) {
/*
* If traced process is already stopped,
* then no further action is necessary.
@ -2325,7 +2325,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
MPASS(action == SIG_DFL);
if (prop & SA_STOP) {
if (prop & SIGPROP_STOP) {
if (p->p_flag & (P_PPWAIT|P_WEXIT))
goto out;
p->p_flag |= P_STOPPED_SIG;
@ -2394,7 +2394,7 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
* priority of the idle thread, since we still allow to signal
* kernel processes.
*/
if (action == SIG_DFL && (prop & SA_KILL) != 0 &&
if (action == SIG_DFL && (prop & SIGPROP_KILL) != 0 &&
td->td_priority > PUSER && !TD_IS_IDLETHREAD(td))
sched_prio(td, PUSER);
if (TD_ON_SLEEPQ(td)) {
@ -2411,7 +2411,7 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
* asleep, we are finished; the process should not
* be awakened.
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
if ((prop & SIGPROP_CONT) && action == SIG_DFL) {
thread_unlock(td);
PROC_SUNLOCK(p);
sigqueue_delete(&p->p_sigqueue, sig);
@ -2427,7 +2427,7 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
* Don't awaken a sleeping thread for SIGSTOP if the
* STOP signal is deferred.
*/
if ((prop & SA_STOP) != 0 && (td->td_flags & (TDF_SBDRY |
if ((prop & SIGPROP_STOP) != 0 && (td->td_flags & (TDF_SBDRY |
TDF_SERESTART | TDF_SEINTR)) == TDF_SBDRY)
goto out;
@ -2858,10 +2858,10 @@ issignal(struct thread *td)
* if process is member of an orphaned
* process group, ignore tty stop signals.
*/
if (prop & SA_STOP) {
if (prop & SIGPROP_STOP) {
if (p->p_flag & (P_TRACED|P_WEXIT) ||
(p->p_pgrp->pg_jobc == 0 &&
prop & SA_TTYSTOP))
prop & SIGPROP_TTYSTOP))
break; /* == ignore */
if (TD_SBDRY_INTR(td)) {
KASSERT((td->td_flags & TDF_SBDRY) != 0,
@ -2881,7 +2881,7 @@ issignal(struct thread *td)
PROC_SUNLOCK(p);
mtx_lock(&ps->ps_mtx);
goto next;
} else if (prop & SA_IGNORE) {
} else if (prop & SIGPROP_IGNORE) {
/*
* Except for SIGCONT, shouldn't get here.
* Default action is to ignore; drop it.
@ -2897,7 +2897,7 @@ issignal(struct thread *td)
* to take action on an ignored signal other
* than SIGCONT, unless process is traced.
*/
if ((prop & SA_CONT) == 0 &&
if ((prop & SIGPROP_CONT) == 0 &&
(p->p_flag & P_TRACED) == 0)
printf("issignal\n");
break; /* == ignore */
@ -3059,7 +3059,8 @@ sigexit(td, sig)
* XXX If another thread attempts to single-thread before us
* (e.g. via fork()), we won't get a dump at all.
*/
if ((sigprop(sig) & SA_CORE) && thread_single(p, SINGLE_NO_EXIT) == 0) {
if ((sigprop(sig) & SIGPROP_CORE) &&
thread_single(p, SINGLE_NO_EXIT) == 0) {
p->p_sig = sig;
/*
* Log signals which would cause core dumps

View file

@ -6,7 +6,6 @@ CXGBE = ${.CURDIR}/../../../dev/cxgbe
KMOD= cxgbei
SRCS= cxgbei.c
SRCS+= cxgbei_ulp2_ddp.c
SRCS+= icl_cxgbei.c
SRCS+= bus_if.h
SRCS+= device_if.h

View file

@ -1,12 +0,0 @@
# $FreeBSD$
SUBDIR= digi
SUBDIR+=digi_CX
SUBDIR+=digi_CX_PCI
SUBDIR+=digi_EPCX
SUBDIR+=digi_EPCX_PCI
SUBDIR+=digi_Xe
SUBDIR+=digi_Xem
SUBDIR+=digi_Xr
.include <bsd.subdir.mk>

View file

@ -1,3 +0,0 @@
# $FreeBSD$
.include "../Makefile.inc"

View file

@ -1,16 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi
SRCS= digi.c digi_pci.c digi_isa.c
SRCS+= digi.h digi_pci.h digireg.h digi_mod.h
SRCS+= bus_if.h pci_if.h device_if.h
SRCS+= opt_compat.h
.if !defined(KERNBUILDDIR)
opt_compat.h:
echo "#define COMPAT_43 1" > ${.TARGET}
echo "#define COMPAT_FREEBSD6 1" >> ${.TARGET}
.endif
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_CX
SRCS= CX.c CX.bios.h CX.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_CX_PCI
SRCS= CX_PCI.c CX_PCI.bios.h CX_PCI.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_EPCX
SRCS= EPCX.c EPCX.bios.h EPCX.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_EPCX_PCI
SRCS= EPCX_PCI.c EPCX_PCI.bios.h EPCX_PCI.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_Xe
SRCS= Xe.c Xe.bios.h Xe.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_Xem
SRCS= Xem.c Xem.bios.h Xem.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -1,7 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/digi
KMOD= digi_Xr
SRCS= Xr.c Xr.bios.h Xr.fepos.h digi_mod.h
.include <bsd.kmod.mk>

View file

@ -92,6 +92,14 @@
#define RNDIS_DF_CONNECTIONLESS 0x00000001
#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
/*
* Common RNDIS message header.
*/
struct rndis_msghdr {
uint32_t rm_type;
uint32_t rm_len;
};
/*
* RNDIS data message
*/
@ -147,6 +155,12 @@ struct rndis_pktinfo {
/*
* RNDIS control messages
*/
/*
* Common header for RNDIS completion messages.
*
* NOTE: It does not apply to REMOTE_NDIS_RESET_CMPLT.
*/
struct rndis_comp_hdr {
uint32_t rm_type;
uint32_t rm_len;
@ -316,7 +330,7 @@ struct rndis_keepalive_comp {
#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000
/* RNDIS offsets */
#define RNDIS_HEADER_OFFSET 8 /* bytes */
#define RNDIS_HEADER_OFFSET ((uint32_t)sizeof(struct rndis_msghdr))
#define RNDIS_DATA_OFFSET \
((uint32_t)(sizeof(struct rndis_packet_msg) - RNDIS_HEADER_OFFSET))

View file

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1200005 /* Master, propagated to newvers */
#define __FreeBSD_version 1200006 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

View file

@ -78,6 +78,8 @@ BSTCENV= \
BSTCARGS= \
${BSARGS:NDESTDIR=*:NOBJTOP=*:NOBJROOT=*:NMK_CROSS_COMPILER=*:NMK_CLANG=*:NMK_GCC=*} \
BUILD_DIRDEPS=yes \
LLVM_TBLGEN=${TOOLSDIR}/usr/bin/llvm-tblgen \
CLANG_TBLGEN=${TOOLSDIR}/usr/bin/clang-tblgen \
-DWITH_STAGING \
-DWITH_TOOLSDIR

View file

@ -18,6 +18,9 @@ DIRDEPS = \
usr.bin/xlint/xlint \
usr.bin/yacc \
usr.sbin/config \
usr.sbin/crunch/crunchgen \
usr.sbin/crunch/crunchide \
.if ${MK_KERBEROS} != "no"
DIRDEPS+= \

View file

@ -47,6 +47,9 @@ DIRDEPS = \
secure/lib/libcrypto \
secure/lib/libssl \
usr.bin/lex/lib \
usr.bin/yacc.host \
usr.sbin/crunch/crunchgen.host \
usr.sbin/crunch/crunchide.host \
.include <dirdeps.mk>

View file

@ -243,7 +243,10 @@ sub callback_dtformat {
if ($nl eq 'ja_JP') {
$s =~ s/(> )(%H)/$1%A $2/;
} elsif ($nl eq 'ko_KR' || $nl eq 'zh_TW') {
} elsif ($nl eq 'ko_KR' || $nl eq 'zh_CN' || $nl eq 'zh_TW') {
if ($nl ne 'ko_KR') {
$s =~ s/%m/%_m/;
}
$s =~ s/(> )(%p)/$1%A $2/;
}
$s =~ s/\.,/\./;

View file

@ -85,6 +85,10 @@ default
Do not attempt to resolve network addresses (normally
.Nm
interprets addresses and attempts to display them as names).
When
.Fl n
is specified more than once, hostnames stored in utmp are attempted to
resolve to display them as network addresses.
.El
.Pp
If one or more

View file

@ -180,7 +180,7 @@ main(int argc, char *argv[])
nlistf = optarg;
break;
case 'n':
nflag = 1;
nflag += 1;
break;
case 'f': case 'l': case 's': case 'u': case 'w':
warnx("[-flsuw] no longer supported");
@ -378,12 +378,12 @@ main(int argc, char *argv[])
lsin->sin_family = AF_INET;
isaddr = 1;
}
if (!nflag) {
if (nflag == 0) {
/* Attempt to change an IP address into a name */
if (isaddr && realhostname_sa(fn, sizeof(fn), sa,
sa->sa_len) == HOSTNAME_FOUND)
p = fn;
} else if (!isaddr) {
} else if (!isaddr && nflag > 1) {
/*
* If a host has only one A/AAAA RR, change a
* name into an IP address

View file

@ -73,7 +73,6 @@
#define MAX_COMMAND 1000 /* max length of internally generated cmd */
#define MAX_ENVSTR 1000 /* max length of envvar=value\0 strings */
#define MAX_TEMPSTR 100 /* obvious */
#define MAX_UNAME 20 /* max length of username, should be overkill */
#define ROOT_UID 0 /* don't change this, it really must be root */
#define ROOT_USER "root" /* ditto */
#define SYS_NAME "*system*" /* magic owner name for system crontab */

View file

@ -28,6 +28,7 @@ static const char rcsid[] =
#define MAIN_PROGRAM
#include <sys/param.h>
#include "cron.h"
#include <errno.h>
#include <fcntl.h>
@ -57,7 +58,7 @@ static char *Options[] = { "???", "list", "delete", "edit", "replace" };
static PID_T Pid;
static char User[MAX_UNAME], RealUser[MAX_UNAME];
static char User[MAXLOGNAME], RealUser[MAXLOGNAME];
static char Filename[MAX_FNAME];
static FILE *NewCrontab;
static int CheckErrorCount;

View file

@ -1064,6 +1064,7 @@ prog_makefile_rules(FILE *outmk, prog_t *p)
}
fprintf(outmk, "\n");
}
fprintf(outmk, "$(%s_OBJPATHS): .NOMETA\n", p->ident);
if (p->srcdir && p->objs) {
fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);