mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
Merging ^/head r278298 through r278350.
This commit is contained in:
commit
b40d827331
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang360-import/; revision=278351
@ -41,6 +41,7 @@ LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
|
||||
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
|
||||
LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
|
||||
LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
|
||||
LINE("libdevctl", "Device Control Library (libdevctl, \\-ldevctl)")
|
||||
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
|
||||
LINE("libdevstat", "Device Statistics Library (libdevstat, \\-ldevstat)")
|
||||
LINE("libdisk", "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")
|
||||
|
@ -28,7 +28,7 @@ extra_commands="config console status"
|
||||
|
||||
need_dad_wait=
|
||||
|
||||
# extact_var jail name param num defval
|
||||
# extract_var jail name param num defval
|
||||
# Extract value from ${jail_$jail_$name} or ${jail_$name} and
|
||||
# set it to $param. If not defined, $defval is used.
|
||||
# When $num is [0-9]*, ${jail_$jail_$name$num} are looked up and
|
||||
|
@ -165,13 +165,14 @@ static_inet()
|
||||
|
||||
static_inet6()
|
||||
{
|
||||
local _action _if _skip fibmod fibs
|
||||
local _action _if _skip fibmod fibs allfibs
|
||||
_action=$1
|
||||
_if=$2
|
||||
|
||||
# get the number of FIBs supported.
|
||||
fibs=$((`${SYSCTL_N} net.fibs` - 1))
|
||||
if [ "$fibs" -gt 0 ]; then
|
||||
allfibs=`${SYSCTL_N} net.add_addr_allfibs`
|
||||
if [ "$fibs" -gt 0 ] && [ "$allfibs" -ne 0 ]; then
|
||||
fibmod="-fib 0-$fibs"
|
||||
else
|
||||
fibmod=
|
||||
|
@ -41,6 +41,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
|
||||
${_libcom_err} \
|
||||
libcompat \
|
||||
libcrypt \
|
||||
libdevctl \
|
||||
libdevinfo \
|
||||
libdevstat \
|
||||
libdpv \
|
||||
|
@ -9,6 +9,10 @@ CFLAGS+= -I${.CURDIR}/../common \
|
||||
-I${.CURDIR}/../../libc/include \
|
||||
-mlongcall
|
||||
|
||||
# XXX: See the log for r232932 as to why the above -mlongcall is needed. Since
|
||||
# clang doesn't support -mlongcall, and testing shows a clang linked with a
|
||||
# clang-built csu segfaults, this must currently be compiled with gcc. Once
|
||||
# clang supports -mlongcall, or we get a fixed ld, this can be revisited.
|
||||
CC:= gcc
|
||||
COMPILER_TYPE:= gcc
|
||||
|
||||
|
@ -85,10 +85,13 @@ getdiskbyname(const char *name)
|
||||
cq++, cp++;
|
||||
*cq = '\0';
|
||||
|
||||
if (cgetstr(buf, "ty", &cq) > 0 && strcmp(cq, "removable") == 0)
|
||||
dp->d_flags |= D_REMOVABLE;
|
||||
else if (cq && strcmp(cq, "simulated") == 0)
|
||||
dp->d_flags |= D_RAMDISK;
|
||||
if (cgetstr(buf, "ty", &cq) > 0) {
|
||||
if (strcmp(cq, "removable") == 0)
|
||||
dp->d_flags |= D_REMOVABLE;
|
||||
else if (cq && strcmp(cq, "simulated") == 0)
|
||||
dp->d_flags |= D_RAMDISK;
|
||||
free(cq);
|
||||
}
|
||||
if (cgetcap(buf, "sf", ':') != NULL)
|
||||
dp->d_flags |= D_BADSECT;
|
||||
|
||||
@ -100,9 +103,10 @@ getdiskbyname(const char *name)
|
||||
getnumdflt(dp->d_nsectors, "ns", 0);
|
||||
getnumdflt(dp->d_ncylinders, "nc", 0);
|
||||
|
||||
if (cgetstr(buf, "dt", &cq) > 0)
|
||||
if (cgetstr(buf, "dt", &cq) > 0) {
|
||||
dp->d_type = gettype(cq, dktypenames);
|
||||
else
|
||||
free(cq);
|
||||
} else
|
||||
getnumdflt(dp->d_type, "dt", 0);
|
||||
getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
|
||||
getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
|
||||
@ -140,8 +144,11 @@ getdiskbyname(const char *name)
|
||||
pp->p_frag = 8;
|
||||
}
|
||||
getnumdflt(pp->p_fstype, ptype, 0);
|
||||
if (pp->p_fstype == 0 && cgetstr(buf, ptype, &cq) > 0)
|
||||
pp->p_fstype = gettype(cq, fstypenames);
|
||||
if (pp->p_fstype == 0)
|
||||
if (cgetstr(buf, ptype, &cq) >= 0) {
|
||||
pp->p_fstype = gettype(cq, fstypenames);
|
||||
free(cq);
|
||||
}
|
||||
max = p;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
|
||||
__RCSID("$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#endif
|
||||
__FBSDID("$FreeBSD$");
|
||||
@ -25,9 +25,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
/*
|
||||
* delete node with given key
|
||||
* find a node with given key
|
||||
*
|
||||
* vkey: key to be deleted
|
||||
* vkey: key to be found
|
||||
* vrootp: address of the root of the tree
|
||||
* compar: function to carry out node comparisons
|
||||
*/
|
||||
@ -65,7 +65,8 @@ tdelete(const void * __restrict vkey, void ** __restrict vrootp,
|
||||
q->rlink = (*rootp)->rlink;
|
||||
}
|
||||
}
|
||||
free(*rootp); /* D4: Free node */
|
||||
if (p != *rootp)
|
||||
free(*rootp); /* D4: Free node */
|
||||
*rootp = q; /* link parent to new node */
|
||||
return p;
|
||||
}
|
||||
|
8
lib/libdevctl/Makefile
Normal file
8
lib/libdevctl/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
LIB= devctl
|
||||
SRCS= devctl.c
|
||||
INCS= devctl.h
|
||||
MAN= devctl.3
|
||||
|
||||
.include <bsd.lib.mk>
|
295
lib/libdevctl/devctl.3
Normal file
295
lib/libdevctl/devctl.3
Normal file
@ -0,0 +1,295 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 26, 2014
|
||||
.Dt DEVCTL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm devctl ,
|
||||
.Nm devctl_attach ,
|
||||
.Nm devctl_detach ,
|
||||
.Nm devctl_disable ,
|
||||
.Nm devctl_enable ,
|
||||
.Nm devctl_resume ,
|
||||
.Nm devctl_suspend
|
||||
.Nd device control library
|
||||
.Sh LIBRARY
|
||||
.Lb libdevctl
|
||||
.Sh SYNOPSIS
|
||||
.In devctl.h
|
||||
.Ft int
|
||||
.Fn devctl_attach "const char *device"
|
||||
.Ft int
|
||||
.Fn devctl_detach "const char *device" "bool force"
|
||||
.Ft int
|
||||
.Fn devctl_disable "const char *device" "bool force_detach"
|
||||
.Ft int
|
||||
.Fn devctl_enable "const char *device"
|
||||
.Ft int
|
||||
.Fn devctl_resume "const char *device"
|
||||
.Ft int
|
||||
.Fn devctl_suspend "const char *device"
|
||||
.Ft int
|
||||
.Fn devctl_set_driver "const char *device" "const char *driver" "bool force"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
library adjusts the state of devices in the kernel's internal device
|
||||
hierarchy.
|
||||
Each control operation accepts a
|
||||
.Fa device
|
||||
argument that identifies the device to adjust.
|
||||
The
|
||||
.Fa device
|
||||
may be specified as either the name of an existing device or as a
|
||||
bus-specific address.
|
||||
The following bus-specific address formats are currently supported:
|
||||
.Bl -tag -offset indent
|
||||
.It Sy pci Ns Fa domain Ns : Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function
|
||||
A PCI device with the specified
|
||||
.Fa domain ,
|
||||
.Fa bus ,
|
||||
.Fa slot ,
|
||||
and
|
||||
.Fa function .
|
||||
.It Sy pci Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function
|
||||
A PCI device in domain zero with the specified
|
||||
.Fa bus ,
|
||||
.Fa slot ,
|
||||
and
|
||||
.Fa function .
|
||||
.It Fa handle
|
||||
A device with an ACPI handle of
|
||||
.Fa handle .
|
||||
The handle must be specified as an absolute path and must begin with a
|
||||
.Dq \e .
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_attach
|
||||
function probes a device and attaches a suitable device driver if one is
|
||||
found.
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_detach
|
||||
function detaches a device from its current device driver.
|
||||
The device is left detached until either a new driver for its parent
|
||||
bus is loaded or the device is explicitly probed via
|
||||
.Fn devctl_attach .
|
||||
If
|
||||
.Fa force
|
||||
is true,
|
||||
the current device driver will be detached even if the device is busy.
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_disable
|
||||
function disables a device.
|
||||
If the device is currently attached to a device driver,
|
||||
the device driver will be detached from the device,
|
||||
but the device will retain its current name.
|
||||
If
|
||||
.Fa force_detach
|
||||
is true,
|
||||
the current device driver will be detached even if the device is busy.
|
||||
The device will remain disabled and detached until it is explicitly enabled
|
||||
via
|
||||
.Fn devctl_enable .
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_enable
|
||||
function re-enables a disabled device.
|
||||
The device will probe and attach if a suitable device driver is found.
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_suspend
|
||||
function suspends a device.
|
||||
This may include placing the device in a reduced power state,
|
||||
but any device driver currently attached to the device will remain attached.
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_resume
|
||||
function resumes a suspended device to a fully working state.
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_set_driver
|
||||
function attaches a device driver named
|
||||
.Fa driver
|
||||
to a device.
|
||||
If the device is already attached and
|
||||
.Fa force
|
||||
is false,
|
||||
the request will fail.
|
||||
If the device is already attached and
|
||||
.Fa force
|
||||
is true,
|
||||
the device will be detached from its current device driver before it is
|
||||
attached to the new device driver.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std devctl_attach devctl_detach devctl_disable devctl_enable \
|
||||
devctl_suspend devctl_resume devctl_set_driver
|
||||
.Sh ERRORS
|
||||
In addition to specific errors noted below,
|
||||
all of the
|
||||
.Nm
|
||||
functions may fail for any of the errors described in
|
||||
.Xr open 2
|
||||
as well as:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The device name is too long.
|
||||
.It Bq Er ENOENT
|
||||
No existing device matches the specified name or location.
|
||||
.It Bq Er EPERM
|
||||
The current process is not permitted to adjust the state of
|
||||
.Fa device .
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_attach
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The device is already attached.
|
||||
.It Bq Er ENOMEM
|
||||
An internal memory allocation request failed.
|
||||
.It Bq Er ENXIO
|
||||
The device is disabled.
|
||||
.It Bq Er ENXIO
|
||||
No suitable driver for the device could be found,
|
||||
or the driver failed to attach.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_detach
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The current device driver for
|
||||
.Fa device
|
||||
is busy and cannot detach at this time.
|
||||
Note that some drivers may return this even if
|
||||
.Fa force
|
||||
is true.
|
||||
.It Bq Er ENXIO
|
||||
The device is not attached to a driver.
|
||||
.It Bq Er ENXIO
|
||||
The current device driver for
|
||||
.Fa device
|
||||
does not support detaching.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_enable
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The device is already enabled.
|
||||
.It Bq Er ENOMEM
|
||||
An internal memory allocation request failed.
|
||||
.It Bq Er ENXIO
|
||||
No suitable driver for the device could be found,
|
||||
or the driver failed to attach.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_disable
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The current device driver for
|
||||
.Fa device
|
||||
is busy and cannot detach at this time.
|
||||
Note that some drivers may return this even if
|
||||
.Fa force_detach
|
||||
is true.
|
||||
.It Bq Er ENXIO
|
||||
The device is already disabled.
|
||||
.It Bq Er ENXIO
|
||||
The current device driver for
|
||||
.Fa device
|
||||
does not support detaching.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_suspend
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The device is already suspended.
|
||||
.It Bq Er EINVAL
|
||||
The device to be suspended is the root bus device.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_resume
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The device is not suspended.
|
||||
.It Bq Er EINVAL
|
||||
The device to be resumed is the root bus device.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn devctl_set_driver
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBUSY
|
||||
The device is currently attached to a device driver and
|
||||
.Fa force
|
||||
is false.
|
||||
.It Bq Er EBUSY
|
||||
The current device driver for
|
||||
.Fa device
|
||||
is busy and cannot detach at this time.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa driver
|
||||
argument points outside the process' allocated address space.
|
||||
.It Bq Er ENOENT
|
||||
No device driver with the requested name exists.
|
||||
.It Bq Er ENOMEM
|
||||
An internal memory allocation request failed.
|
||||
.It Bq Er ENXIO
|
||||
The device is disabled.
|
||||
.It Bq Er ENXIO
|
||||
The new device driver failed to attach.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr devinfo 3 ,
|
||||
.Xr devstat 3 ,
|
||||
.Xr devctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
library first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh BUGS
|
||||
If a device is suspended individually via
|
||||
.Fn devctl_suspend
|
||||
and the entire machine is subsequently suspended,
|
||||
the device will be resumed when the machine resumes.
|
124
lib/libdevctl/devctl.c
Normal file
124
lib/libdevctl/devctl.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/bus.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "devctl.h"
|
||||
|
||||
static int
|
||||
devctl_request(u_long cmd, struct devreq *req)
|
||||
{
|
||||
static int devctl2_fd = -1;
|
||||
|
||||
if (devctl2_fd == -1) {
|
||||
devctl2_fd = open("/dev/devctl2", O_RDONLY);
|
||||
if (devctl2_fd == -1)
|
||||
return (-1);
|
||||
}
|
||||
return (ioctl(devctl2_fd, cmd, req));
|
||||
}
|
||||
|
||||
static int
|
||||
devctl_simple_request(u_long cmd, const char *name, int flags)
|
||||
{
|
||||
struct devreq req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >=
|
||||
sizeof(req.dr_name)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
req.dr_flags = flags;
|
||||
return (devctl_request(cmd, &req));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_attach(const char *device)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_ATTACH, device, 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_detach(const char *device, bool force)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_DETACH, device, force ?
|
||||
DEVF_FORCE_DETACH : 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_enable(const char *device)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_ENABLE, device, 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_disable(const char *device, bool force_detach)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_DISABLE, device, force_detach ?
|
||||
DEVF_FORCE_DETACH : 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_suspend(const char *device)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_SUSPEND, device, 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_resume(const char *device)
|
||||
{
|
||||
|
||||
return (devctl_simple_request(DEV_RESUME, device, 0));
|
||||
}
|
||||
|
||||
int
|
||||
devctl_set_driver(const char *device, const char *driver, bool force)
|
||||
{
|
||||
struct devreq req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
|
||||
sizeof(req.dr_name)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
req.dr_data = __DECONST(char *, driver);
|
||||
if (force)
|
||||
req.dr_flags |= DEVF_SET_DRIVER_DETACH;
|
||||
return (devctl_request(DEV_SET_DRIVER, &req));
|
||||
}
|
42
lib/libdevctl/devctl.h
Normal file
42
lib/libdevctl/devctl.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __DEVCTL_H__
|
||||
#define __DEVCTL_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
int devctl_attach(const char *device);
|
||||
int devctl_detach(const char *device, bool force);
|
||||
int devctl_enable(const char *device);
|
||||
int devctl_disable(const char *device, bool force_detach);
|
||||
int devctl_suspend(const char *device);
|
||||
int devctl_resume(const char *device);
|
||||
int devctl_set_driver(const char *device, const char *driver, bool force);
|
||||
|
||||
#endif /* !__DEVCTL_H__ */
|
@ -50,7 +50,7 @@ struct devinfo_dev {
|
||||
char *dd_location; /* Where bus thinks dev at */
|
||||
uint32_t dd_devflags; /* API flags */
|
||||
uint16_t dd_flags; /* internal dev flags */
|
||||
devinfo_state_t dd_state; /* attacement state of dev */
|
||||
devinfo_state_t dd_state; /* attachment state of dev */
|
||||
};
|
||||
|
||||
struct devinfo_rman {
|
||||
|
@ -62,12 +62,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netgraph/ng_atmllc.h>
|
||||
#include <netgraph/ng_bpf.h>
|
||||
#include <netgraph/ng_bridge.h>
|
||||
#include <netgraph/ng_car.h>
|
||||
#include <netgraph/ng_cisco.h>
|
||||
#include <netgraph/ng_deflate.h>
|
||||
#include <netgraph/ng_device.h>
|
||||
#include <netgraph/ng_echo.h>
|
||||
#include <netgraph/ng_eiface.h>
|
||||
#include <netgraph/ng_etf.h>
|
||||
#include <netgraph/ng_ether.h>
|
||||
#include <netgraph/ng_ether_echo.h>
|
||||
#include <netgraph/ng_frame_relay.h>
|
||||
#include <netgraph/ng_gif.h>
|
||||
#include <netgraph/ng_gif_demux.h>
|
||||
@ -81,15 +84,20 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netgraph/ng_lmi.h>
|
||||
#include <netgraph/ng_mppc.h>
|
||||
#include <netgraph/ng_nat.h>
|
||||
#include <netgraph/netflow/ng_netflow.h>
|
||||
#include <netgraph/ng_one2many.h>
|
||||
#include <netgraph/ng_patch.h>
|
||||
#include <netgraph/ng_pipe.h>
|
||||
#include <netgraph/ng_ppp.h>
|
||||
#include <netgraph/ng_pppoe.h>
|
||||
#include <netgraph/ng_pptpgre.h>
|
||||
#include <netgraph/ng_pred1.h>
|
||||
#include <netgraph/ng_rfc1490.h>
|
||||
#include <netgraph/ng_socket.h>
|
||||
#include <netgraph/ng_source.h>
|
||||
#include <netgraph/ng_split.h>
|
||||
#include <netgraph/ng_sppp.h>
|
||||
#include <netgraph/ng_tag.h>
|
||||
#include <netgraph/ng_tcpmss.h>
|
||||
#include <netgraph/ng_tee.h>
|
||||
#include <netgraph/ng_tty.h>
|
||||
@ -129,12 +137,15 @@ static const struct ng_cookie cookies[] = {
|
||||
COOKIE(ATMLLC),
|
||||
COOKIE(BPF),
|
||||
COOKIE(BRIDGE),
|
||||
COOKIE(CAR),
|
||||
COOKIE(CISCO),
|
||||
COOKIE(DEFLATE),
|
||||
COOKIE(DEVICE),
|
||||
COOKIE(ECHO),
|
||||
COOKIE(EIFACE),
|
||||
COOKIE(ETF),
|
||||
COOKIE(ETHER),
|
||||
COOKIE(ETHER_ECHO),
|
||||
COOKIE(FRAMERELAY),
|
||||
COOKIE(GIF),
|
||||
COOKIE(GIF_DEMUX),
|
||||
@ -149,15 +160,20 @@ static const struct ng_cookie cookies[] = {
|
||||
COOKIE(LMI),
|
||||
COOKIE(MPPC),
|
||||
COOKIE(NAT),
|
||||
COOKIE(NETFLOW),
|
||||
COOKIE(ONE2MANY),
|
||||
COOKIE(PATCH),
|
||||
COOKIE(PIPE),
|
||||
COOKIE(PPP),
|
||||
COOKIE(PPPOE),
|
||||
COOKIE(PPTPGRE),
|
||||
COOKIE(PRED1),
|
||||
COOKIE(RFC1490),
|
||||
COOKIE(SOCKET),
|
||||
COOKIE(SOURCE),
|
||||
COOKIE(SPLIT),
|
||||
COOKIE(SPPP),
|
||||
COOKIE(TAG),
|
||||
COOKIE(TCPMSS),
|
||||
COOKIE(TEE),
|
||||
COOKIE(TTY),
|
||||
@ -181,9 +197,8 @@ NgSetDebug(int level)
|
||||
{
|
||||
int old = _gNgDebugLevel;
|
||||
|
||||
if (level < 0)
|
||||
level = old;
|
||||
_gNgDebugLevel = level;
|
||||
if (level >= 0)
|
||||
_gNgDebugLevel = level;
|
||||
return (old);
|
||||
}
|
||||
|
||||
@ -225,10 +240,10 @@ _NgDebugMsg(const struct ng_mesg *msg, const char *path)
|
||||
/* Display header stuff */
|
||||
NGLOGX("NG_MESG :");
|
||||
NGLOGX(" vers %d", msg->header.version);
|
||||
NGLOGX(" arglen %d", msg->header.arglen);
|
||||
NGLOGX(" flags %ld", msg->header.flags);
|
||||
NGLOGX(" token %lu", (u_long)msg->header.token);
|
||||
NGLOGX(" cookie %s (%d)",
|
||||
NGLOGX(" arglen %u", msg->header.arglen);
|
||||
NGLOGX(" flags %x", msg->header.flags);
|
||||
NGLOGX(" token %u", msg->header.token);
|
||||
NGLOGX(" cookie %s (%u)",
|
||||
NgCookie(msg->header.typecookie), msg->header.typecookie);
|
||||
|
||||
/* At lower debugging levels, skip ASCII translation */
|
||||
|
@ -86,16 +86,13 @@ _pthread_barrier_init(pthread_barrier_t *barrier,
|
||||
if (barrier == NULL || count <= 0)
|
||||
return (EINVAL);
|
||||
|
||||
bar = malloc(sizeof(struct pthread_barrier));
|
||||
bar = calloc(1, sizeof(struct pthread_barrier));
|
||||
if (bar == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
_thr_umutex_init(&bar->b_lock);
|
||||
_thr_ucond_init(&bar->b_cv);
|
||||
bar->b_cycle = 0;
|
||||
bar->b_waiters = 0;
|
||||
bar->b_count = count;
|
||||
bar->b_refcount = 0;
|
||||
*barrier = bar;
|
||||
|
||||
return (0);
|
||||
|
@ -27,38 +27,28 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
double
|
||||
scalbln (double x, long n)
|
||||
{
|
||||
int in;
|
||||
#define NMAX 65536
|
||||
#define NMIN -65536
|
||||
|
||||
in = (int)n;
|
||||
if (in != n)
|
||||
in = (n > 0) ? INT_MAX: INT_MIN;
|
||||
return (scalbn(x, in));
|
||||
double
|
||||
scalbln(double x, long n)
|
||||
{
|
||||
|
||||
return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
|
||||
}
|
||||
|
||||
float
|
||||
scalblnf (float x, long n)
|
||||
scalblnf(float x, long n)
|
||||
{
|
||||
int in;
|
||||
|
||||
in = (int)n;
|
||||
if (in != n)
|
||||
in = (n > 0) ? INT_MAX: INT_MIN;
|
||||
return (scalbnf(x, in));
|
||||
return (scalbnf(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
|
||||
}
|
||||
|
||||
long double
|
||||
scalblnl (long double x, long n)
|
||||
scalblnl(long double x, long n)
|
||||
{
|
||||
int in;
|
||||
|
||||
in = (int)n;
|
||||
if (in != n)
|
||||
in = (n > 0) ? INT_MAX: INT_MIN;
|
||||
return (scalbnl(x, in));
|
||||
return (scalbnl(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 30, 2012
|
||||
.Dd February 6, 2015
|
||||
.Dt WITNESS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -32,7 +32,9 @@
|
||||
.Nd lock validation facility
|
||||
.Sh SYNOPSIS
|
||||
.Cd options WITNESS
|
||||
.Cd options WITNESS_COUNT
|
||||
.Cd options WITNESS_KDB
|
||||
.Cd options WITNESS_NO_VNODE
|
||||
.Cd options WITNESS_SKIPSPIN
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
@ -56,6 +58,28 @@ does not recurse on a non-recursive lock,
|
||||
or attempt an upgrade on a shared lock held by another thread.
|
||||
If any of these checks fail, then the kernel will panic.
|
||||
.Pp
|
||||
The
|
||||
.Dv WITNESS_COUNT
|
||||
kernel option controls the maximum number of
|
||||
.Xr witness 4
|
||||
entries that are tracked in the kernel.
|
||||
The maximum number of entries can be queried via the
|
||||
.Va debug.witness.count
|
||||
sysctl.
|
||||
It can also be set from the
|
||||
.Xr loader 8
|
||||
via the
|
||||
.Va debug.witness.count
|
||||
environment variable.
|
||||
.Pp
|
||||
The
|
||||
.Dv WITNESS_NO_VNODE
|
||||
kernel option tells
|
||||
.Xr witness 4
|
||||
to ignore locking issues between
|
||||
.Xr vnode 9
|
||||
objects.
|
||||
.Pp
|
||||
The flag that controls whether or not the kernel debugger is entered when a
|
||||
lock order violation is detected can be set in a variety of ways.
|
||||
By default, the flag is off, but if the
|
||||
|
@ -39,6 +39,7 @@ LIBCRYPT?= ${DESTDIR}${LIBDIR}/libcrypt.a
|
||||
LIBCRYPTO?= ${DESTDIR}${LIBDIR}/libcrypto.a
|
||||
LIBCTF?= ${DESTDIR}${LIBDIR}/libctf.a
|
||||
LIBCURSES?= ${DESTDIR}${LIBDIR}/libcurses.a
|
||||
LIBDEVCTL?= ${DESTDIR}${LIBDIR}/libdevctl.a
|
||||
LIBDEVINFO?= ${DESTDIR}${LIBDIR}/libdevinfo.a
|
||||
LIBDEVSTAT?= ${DESTDIR}${LIBDIR}/libdevstat.a
|
||||
LIBDIALOG?= ${DESTDIR}${LIBDIR}/libdialog.a
|
||||
|
@ -72,6 +72,7 @@ _LIBRARIES= \
|
||||
ctf \
|
||||
cuse \
|
||||
cxxrt \
|
||||
devctl \
|
||||
devinfo \
|
||||
devstat \
|
||||
dialog \
|
||||
|
@ -1064,15 +1064,28 @@ void
|
||||
ipi_startup(int apic_id, int vector)
|
||||
{
|
||||
|
||||
/*
|
||||
* This attempts to follow the algorithm described in the
|
||||
* Intel Multiprocessor Specification v1.4 in section B.4.
|
||||
* For each IPI, we allow the local APIC ~20us to deliver the
|
||||
* IPI. If that times out, we panic.
|
||||
*/
|
||||
|
||||
/*
|
||||
* first we do an INIT IPI: this INIT IPI might be run, resetting
|
||||
* and running the target CPU. OR this INIT IPI might be latched (P5
|
||||
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
|
||||
* ignored.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
lapic_ipi_wait(20);
|
||||
|
||||
/* Explicitly deassert the INIT IPI. */
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT,
|
||||
apic_id);
|
||||
|
||||
DELAY(10000); /* wait ~10mS */
|
||||
|
||||
/*
|
||||
@ -1084,9 +1097,11 @@ ipi_startup(int apic_id, int vector)
|
||||
* will run.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
vector, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
if (!lapic_ipi_wait(20))
|
||||
panic("Failed to deliver first STARTUP IPI to APIC %d",
|
||||
apic_id);
|
||||
DELAY(200); /* wait ~200uS */
|
||||
|
||||
/*
|
||||
@ -1096,9 +1111,12 @@ ipi_startup(int apic_id, int vector)
|
||||
* recognized after hardware RESET or INIT IPI.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
vector, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
if (!lapic_ipi_wait(20))
|
||||
panic("Failed to deliver second STARTUP IPI to APIC %d",
|
||||
apic_id);
|
||||
|
||||
DELAY(200); /* wait ~200uS */
|
||||
}
|
||||
|
||||
|
@ -29,21 +29,21 @@ dev/mbox/mbox_if.m standard
|
||||
dev/ofw/ofw_cpu.c standard
|
||||
|
||||
# VideoCore driver
|
||||
contrib/vchiq/interface/compat/vchi_bsd.c standard \
|
||||
contrib/vchiq/interface/compat/vchi_bsd.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_arm.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_arm.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_connected.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_connected.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_core.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_core.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_shim.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_shim.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_util.c standard \
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_util.c optional vchiq \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
|
@ -129,9 +129,12 @@ device smsc
|
||||
device spibus
|
||||
device bcm2835_spi
|
||||
|
||||
device vchiq
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT # Configure using FDT/DTB data
|
||||
# Note: DTB is normally loaded and modified by RPi boot loader, then
|
||||
# handed to kernel via U-Boot and ubldr.
|
||||
#options FDT_DTB_STATIC
|
||||
makeoptions FDT_DTS_FILE=rpi.dts
|
||||
#makeoptions FDT_DTS_FILE=rpi.dts
|
||||
makeoptions MODULES_EXTRA=dtb/rpi
|
||||
|
@ -2,20 +2,19 @@ FAT template boot filesystem created by generate-fat.sh
|
||||
DO NOT EDIT
|
||||
$FreeBSD$
|
||||
begin 644 fat.tmpl.bz2
|
||||
M0EIH.3%!62936=AO?&0`&J9____[ZZKJJ_^N_ZO^Z_^[OO_\`5`(0!0&#$D"
|
||||
M0$)$2&(<P`(\K5,M9"5%&DQ---,FAH,0```T````R-!HQ`&30`-&"#)ID$JF
|
||||
M1)[U4_5-&@`T```#0&AH````````````(,F`$P`!,`1IA&````"9-,308`1@
|
||||
M````!))!BDVI/U0`]0R>H:`81HT#)D!H-#U`T#31IH-&(``R8$9_I)6[MY/,
|
||||
M(H=/()+4&!(3V0"20C3J5$L5@2`219,"T6JI,@0"2*2\=LAD6=>N6<O!'F<.
|
||||
MQ2`;9$.P]202R&N9I3BX[E0;C7/9BF'`((K?M1ZK0B2Q;BLJ9!(`21P&1:;B
|
||||
MDD)S!-L5BL5BL/173`@@M!!!!!X@BQ0@@@@@@CJ"A!!!"!`TWD!B!`@0($"J
|
||||
M9(E`B,1(D2)$B;V]S&-,&#!@P8,'1\*$+59`:41,';;/)32*G*Q52N![20F8
|
||||
M9CCYSB#!2=[EG.),$:P,>(8QSW'U+N42P^'5X@7X``23=EA``#Z,O)^-VTX@
|
||||
M`+E!=,&6PV11C:*D8K#^<%FTG-%!@PR72@\ZU0B<D6I$FT/1\<A#/`;ET5$)
|
||||
MKT-MBW97\J.P/H0ADE"(EBN6";@5#$2#!(\F/E8M+!8-A-S"+$U5[\J>F1Y]
|
||||
MF-FPGL2L>4QCU&O/>89^#H$6^<;&WKC9W52KUX."CM6+GD;(=1!MUD,,?Y[]
|
||||
MTLAG0];,:B^]M%BH0J1":_C-*2I9R3AS#,&0>$RCY'T/R?HR!?'5$MILQ:!"
|
||||
M+;10A*!&^<(_/8>D8<CDN9]HO)OH13W(Q())?'R2WTV9*G_4T<=Y!'1+'9,(
|
||||
J1-/V<ME.&9Q3LKI2S$(`$D,``'_=FF*).\[A.)#4HU1=R13A0D-AO?&0
|
||||
M0EIH.3%!629362AK*D(`&I+____[ZZKJZ_^N_ZO^Z_Z_OJ[L`4`!7I0$#&$"
|
||||
M0$!$3&(<P`(;J*C:0E0E#30&AH`T````9#0```9````#)ZF0:,-3U/409,`)
|
||||
M@`"8`C3",````$R:8F@P`C`````"24U,D>I-DTU,)ZAZ0VA-!M0T'J`>H#"9
|
||||
M'I#0-H&HQI&0&3&FH>H>*`JHHU3V]1%/4/2``T#0`!H``#0`````#1H,@``6
|
||||
M'1&G'&@?$6[T#A)?X8$A160"20BO#")0J4TB1*4GXF$B4I,&>43+=_?K=#3*
|
||||
M6]<E0HE`UBF?(J%8BRF#?8OQ2'D)`)(EL2;F4.'R>R"ZNKJZI,9*68E8*E2Q
|
||||
M4J5*E3'(1830A"$(12A-"<(0A#]VD)H0A"$,>I0FA"$(0I\>P^=F5:M6K5JU
|
||||
M:DI3:64UN;[7%5B]Y-^\]@_K@B:N\/,5F%&H<\G#IXQXAEFC&D?![6%0'6MR
|
||||
MX1@@%FC"FD`M7,/SXFNG:2`'-0<-C$8^+$N.7M1B,^6)9,DV9,0A\OL<:C"L
|
||||
ML1V&,<\9YRB>XV#BG")'6NKRK^("UF2XO?_L!#29">MGDF$R3).!PX&%E,4C
|
||||
M''=(FL1.`_3?CN@-IB2PI3!FF\<8X.X@D,>CA90I)#M$XRPNDFJELL<3=1?8
|
||||
M2B7\5Z64,!7Z;EEBW-MXN-4IJ@W$462]-*\YCR,-B,5[W?=3&L/U>SX,WV#\
|
||||
M\B`:I"'0Z)5"$1B.E)(K[5I4RS`%R$>Y\D0NR*,;<9CZ:^V3P(I?D<D#!UC)
|
||||
D^M-HEE3SAN-8O0FQ$(`$(DF`?ZQ]'U2F_XNY(IPH2!0UE2$`
|
||||
`
|
||||
end
|
||||
|
@ -20,7 +20,7 @@ OUTPUT_FILE=fat.tmpl
|
||||
|
||||
dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$FAT_SIZE
|
||||
DEVICE=`mdconfig -a -f $OUTPUT_FILE`
|
||||
newfs_msdos -F 12 $DEVICE
|
||||
newfs_msdos -F 12 -L EFI $DEVICE
|
||||
mkdir stub
|
||||
mount -t msdosfs /dev/$DEVICE stub
|
||||
|
||||
|
@ -89,7 +89,7 @@ variable logoY
|
||||
0 25 at-xy
|
||||
;
|
||||
|
||||
: fbsdbw-logo ( x y -- ) \ "FreeBSD" logo in B/W (12 rows x 21 columns)
|
||||
: fbsdbw-logo ( x y -- ) \ "FreeBSD" logo in B/W (13 rows x 21 columns)
|
||||
|
||||
\ We used to use the beastie himself as our default... until the
|
||||
\ eventual complaint derided his reign of the advanced boot-menu.
|
||||
@ -106,16 +106,17 @@ variable logoY
|
||||
5 + swap 6 + swap
|
||||
|
||||
2dup at-xy ." ______" 1+
|
||||
2dup at-xy ." | ____|" 1+
|
||||
2dup at-xy ." | |__ _ __ ___ ___ " 1+
|
||||
2dup at-xy ." | __|| '__/ _ \/ _ \" 1+
|
||||
2dup at-xy ." | | | | | __/ __/" 1+
|
||||
2dup at-xy ." | ____| __ ___ ___ " 1+
|
||||
2dup at-xy ." | |__ | '__/ _ \/ _ \" 1+
|
||||
2dup at-xy ." | __|| | | __/ __/" 1+
|
||||
2dup at-xy ." | | | | | | |" 1+
|
||||
2dup at-xy ." |_| |_| \___|\___|" 1+
|
||||
2dup at-xy ." ____ _____ _____" 1+
|
||||
2dup at-xy ." | _ \ / ____| __ \" 1+
|
||||
2dup at-xy ." | |_) | (___ | | | |" 1+
|
||||
2dup at-xy ." | _ < \___ \| | | |" 1+
|
||||
2dup at-xy ." | |_) |____) | |__| |" 1+
|
||||
2dup at-xy ." | | | |" 1+
|
||||
at-xy ." |____/|_____/|_____/"
|
||||
|
||||
\ Put the cursor back at the bottom
|
||||
|
@ -33,13 +33,14 @@ variable brandY
|
||||
2 brandX !
|
||||
1 brandY !
|
||||
|
||||
: fbsd-logo ( x y -- ) \ "FreeBSD" [wide] logo in B/W (6 rows x 42 columns)
|
||||
: fbsd-logo ( x y -- ) \ "FreeBSD" [wide] logo in B/W (7 rows x 42 columns)
|
||||
|
||||
2dup at-xy ." ______ ____ _____ _____ " 1+
|
||||
2dup at-xy ." | ____| | _ \ / ____| __ \ " 1+
|
||||
2dup at-xy ." | |___ _ __ ___ ___ | |_) | (___ | | | |" 1+
|
||||
2dup at-xy ." | ___| '__/ _ \/ _ \| _ < \___ \| | | |" 1+
|
||||
2dup at-xy ." | | | | | __/ __/| |_) |____) | |__| |" 1+
|
||||
2dup at-xy ." | | | | | | || | | |" 1+
|
||||
at-xy ." |_| |_| \___|\___||____/|_____/|_____/ "
|
||||
|
||||
\ Put the cursor back at the bottom
|
||||
|
@ -1222,7 +1222,7 @@ cfiscsi_session_unregister_initiator(struct cfiscsi_session *cs)
|
||||
}
|
||||
|
||||
static struct cfiscsi_session *
|
||||
cfiscsi_session_new(struct cfiscsi_softc *softc)
|
||||
cfiscsi_session_new(struct cfiscsi_softc *softc, const char *offload)
|
||||
{
|
||||
struct cfiscsi_session *cs;
|
||||
int error;
|
||||
@ -1242,7 +1242,11 @@ cfiscsi_session_new(struct cfiscsi_softc *softc)
|
||||
cv_init(&cs->cs_login_cv, "cfiscsi_login");
|
||||
#endif
|
||||
|
||||
cs->cs_conn = icl_new_conn(NULL, "cfiscsi", &cs->cs_lock);
|
||||
cs->cs_conn = icl_new_conn(offload, "cfiscsi", &cs->cs_lock);
|
||||
if (cs->cs_conn == NULL) {
|
||||
free(cs, M_CFISCSI);
|
||||
return (NULL);
|
||||
}
|
||||
cs->cs_conn->ic_receive = cfiscsi_receive_callback;
|
||||
cs->cs_conn->ic_error = cfiscsi_error_callback;
|
||||
cs->cs_conn->ic_prv0 = cs;
|
||||
@ -1325,7 +1329,7 @@ cfiscsi_accept(struct socket *so, struct sockaddr *sa, int portal_id)
|
||||
{
|
||||
struct cfiscsi_session *cs;
|
||||
|
||||
cs = cfiscsi_session_new(&cfiscsi_softc);
|
||||
cs = cfiscsi_session_new(&cfiscsi_softc, NULL);
|
||||
if (cs == NULL) {
|
||||
CFISCSI_WARN("failed to create session");
|
||||
return;
|
||||
@ -1469,7 +1473,7 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
|
||||
mtx_unlock(&cfiscsi_softc.lock);
|
||||
} else {
|
||||
#endif
|
||||
cs = cfiscsi_session_new(softc);
|
||||
cs = cfiscsi_session_new(softc, cihp->offload);
|
||||
if (cs == NULL) {
|
||||
ci->status = CTL_ISCSI_ERROR;
|
||||
snprintf(ci->error_str, sizeof(ci->error_str),
|
||||
@ -1620,6 +1624,7 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
|
||||
"<max_data_segment_length>%zd</max_data_segment_length>"
|
||||
"<immediate_data>%d</immediate_data>"
|
||||
"<iser>%d</iser>"
|
||||
"<offload>%s</offload>"
|
||||
"</connection>\n",
|
||||
cs->cs_id,
|
||||
cs->cs_initiator_name, cs->cs_initiator_addr, cs->cs_initiator_alias,
|
||||
@ -1629,7 +1634,8 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
|
||||
cs->cs_conn->ic_data_crc32c ? "CRC32C" : "None",
|
||||
cs->cs_max_data_segment_length,
|
||||
cs->cs_immediate_data,
|
||||
cs->cs_conn->ic_iser);
|
||||
cs->cs_conn->ic_iser,
|
||||
cs->cs_conn->ic_offload);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
@ -1749,6 +1755,26 @@ cfiscsi_ioctl_logout(struct ctl_iscsi *ci)
|
||||
ci->status = CTL_ISCSI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
cfiscsi_ioctl_limits(struct ctl_iscsi *ci)
|
||||
{
|
||||
struct ctl_iscsi_limits_params *cilp;
|
||||
int error;
|
||||
|
||||
cilp = (struct ctl_iscsi_limits_params *)&(ci->data);
|
||||
|
||||
error = icl_limits(cilp->offload, &cilp->data_segment_limit);
|
||||
if (error != 0) {
|
||||
ci->status = CTL_ISCSI_ERROR;
|
||||
snprintf(ci->error_str, sizeof(ci->error_str),
|
||||
"%s: icl_limits failed with error %d",
|
||||
__func__, error);
|
||||
return;
|
||||
}
|
||||
|
||||
ci->status = CTL_ISCSI_OK;
|
||||
}
|
||||
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
static void
|
||||
cfiscsi_ioctl_listen(struct ctl_iscsi *ci)
|
||||
@ -2176,6 +2202,9 @@ cfiscsi_ioctl(struct cdev *dev,
|
||||
case CTL_ISCSI_LOGOUT:
|
||||
cfiscsi_ioctl_logout(ci);
|
||||
break;
|
||||
case CTL_ISCSI_LIMITS:
|
||||
cfiscsi_ioctl_limits(ci);
|
||||
break;
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
case CTL_ISCSI_LISTEN:
|
||||
cfiscsi_ioctl_listen(ci);
|
||||
|
@ -657,6 +657,7 @@ typedef enum {
|
||||
CTL_ISCSI_LIST,
|
||||
CTL_ISCSI_LOGOUT,
|
||||
CTL_ISCSI_TERMINATE,
|
||||
CTL_ISCSI_LIMITS,
|
||||
#if defined(ICL_KERNEL_PROXY) || 1
|
||||
/*
|
||||
* We actually need those in all cases, but leave the ICL_KERNEL_PROXY,
|
||||
@ -677,6 +678,7 @@ typedef enum {
|
||||
#define CTL_ISCSI_NAME_LEN 224 /* 223 bytes, by RFC 3720, + '\0' */
|
||||
#define CTL_ISCSI_ADDR_LEN 47 /* INET6_ADDRSTRLEN + '\0' */
|
||||
#define CTL_ISCSI_ALIAS_LEN 128 /* Arbitrary. */
|
||||
#define CTL_ISCSI_OFFLOAD_LEN 8 /* Arbitrary. */
|
||||
|
||||
struct ctl_iscsi_handoff_params {
|
||||
char initiator_name[CTL_ISCSI_NAME_LEN];
|
||||
@ -698,11 +700,12 @@ struct ctl_iscsi_handoff_params {
|
||||
uint32_t max_burst_length;
|
||||
uint32_t first_burst_length;
|
||||
uint32_t immediate_data;
|
||||
char offload[CTL_ISCSI_OFFLOAD_LEN];
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
int connection_id;
|
||||
int spare[3];
|
||||
int spare[1];
|
||||
#else
|
||||
int spare[4];
|
||||
int spare[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -733,6 +736,14 @@ struct ctl_iscsi_terminate_params {
|
||||
int spare[4];
|
||||
};
|
||||
|
||||
struct ctl_iscsi_limits_params {
|
||||
char offload[CTL_ISCSI_OFFLOAD_LEN];
|
||||
/* passed to kernel */
|
||||
size_t data_segment_limit;
|
||||
/* passed to userland */
|
||||
int spare[4];
|
||||
};
|
||||
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
struct ctl_iscsi_listen_params {
|
||||
int iser;
|
||||
@ -780,6 +791,7 @@ union ctl_iscsi_data {
|
||||
struct ctl_iscsi_list_params list;
|
||||
struct ctl_iscsi_logout_params logout;
|
||||
struct ctl_iscsi_terminate_params terminate;
|
||||
struct ctl_iscsi_limits_params limits;
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
struct ctl_iscsi_listen_params listen;
|
||||
struct ctl_iscsi_accept_params accept;
|
||||
|
@ -3193,7 +3193,7 @@ libkern/jenkins_hash.c standard
|
||||
libkern/murmur3_32.c standard
|
||||
libkern/mcount.c optional profiling-routine
|
||||
libkern/memcchr.c standard
|
||||
libkern/memchr.c optional fdt | gdb
|
||||
libkern/memchr.c standard
|
||||
libkern/memcmp.c standard
|
||||
libkern/memmem.c optional gdb
|
||||
libkern/qsort.c standard
|
||||
|
@ -174,7 +174,7 @@ SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS}
|
||||
SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o}
|
||||
SYSTEM_OBJS+= hack.So
|
||||
SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} --no-warn-mismatch \
|
||||
-warn-common -export-dynamic -dynamic-linker /red/herring \
|
||||
--warn-common --export-dynamic --dynamic-linker /red/herring \
|
||||
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
|
||||
SYSTEM_LD_TAIL= @${OBJCOPY} --strip-symbol gcc2_compiled. ${.TARGET} ; \
|
||||
${SIZE} ${.TARGET} ; chmod 755 ${.TARGET}
|
||||
|
@ -317,12 +317,12 @@ typedef struct {
|
||||
|
||||
/* Support for multiple INIs */
|
||||
struct ar9300_ini_array {
|
||||
u_int32_t *ia_array;
|
||||
const u_int32_t *ia_array;
|
||||
u_int32_t ia_rows;
|
||||
u_int32_t ia_columns;
|
||||
};
|
||||
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
|
||||
(iniarray)->ia_array = (u_int32_t *)(array); \
|
||||
(iniarray)->ia_array = (const u_int32_t *)(array); \
|
||||
(iniarray)->ia_rows = (rows); \
|
||||
(iniarray)->ia_columns = (columns); \
|
||||
} while (0)
|
||||
|
@ -101,6 +101,7 @@ int acpi_quirks;
|
||||
/* Supported sleep states. */
|
||||
static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT];
|
||||
|
||||
static void acpi_lookup(void *arg, const char *name, device_t *dev);
|
||||
static int acpi_modevent(struct module *mod, int event, void *junk);
|
||||
static int acpi_probe(device_t dev);
|
||||
static int acpi_attach(device_t dev);
|
||||
@ -671,8 +672,10 @@ acpi_attach(device_t dev)
|
||||
/* Register ACPI again to pass the correct argument of pm_func. */
|
||||
power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
|
||||
|
||||
if (!acpi_disabled("bus"))
|
||||
if (!acpi_disabled("bus")) {
|
||||
EVENTHANDLER_REGISTER(dev_lookup, acpi_lookup, NULL, 1000);
|
||||
acpi_probe_children(dev);
|
||||
}
|
||||
|
||||
/* Update all GPEs and enable runtime GPEs. */
|
||||
status = AcpiUpdateAllGpes();
|
||||
@ -3401,6 +3404,31 @@ acpi_disabled(char *subsys)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_lookup(void *arg, const char *name, device_t *dev)
|
||||
{
|
||||
ACPI_HANDLE handle;
|
||||
|
||||
if (*dev != NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Allow any handle name that is specified as an absolute path and
|
||||
* starts with '\'. We could restrict this to \_SB and friends,
|
||||
* but see acpi_probe_children() for notes on why we scan the entire
|
||||
* namespace for devices.
|
||||
*
|
||||
* XXX: The pathname argument to AcpiGetHandle() should be fixed to
|
||||
* be const.
|
||||
*/
|
||||
if (name[0] != '\\')
|
||||
return;
|
||||
if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, __DECONST(char *, name),
|
||||
&handle)))
|
||||
return;
|
||||
*dev = acpi_get_device(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Control interface.
|
||||
*
|
||||
|
44
sys/dev/cxgbe/if_cxl.c
Normal file
44
sys/dev/cxgbe/if_cxl.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Chelsio Communications, Inc.
|
||||
* All rights reserved.
|
||||
* Written by: Navdeep Parhar <np@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
static int
|
||||
mod_event(module_t mod, int cmd, void *arg)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
static moduledata_t if_cxl_mod = {"if_cxl", mod_event};
|
||||
DECLARE_MODULE(if_cxl, if_cxl_mod, SI_SUB_EXEC, SI_ORDER_ANY);
|
||||
MODULE_VERSION(if_cxl, 1);
|
||||
MODULE_DEPEND(if_cxl, cxl, 1, 1, 1);
|
@ -8215,7 +8215,12 @@ toe_capability(struct port_info *pi, int enable)
|
||||
return (ENODEV);
|
||||
|
||||
if (enable) {
|
||||
if (!(sc->flags & FULL_INIT_DONE)) {
|
||||
/*
|
||||
* We need the port's queues around so that we're able to send
|
||||
* and receive CPLs to/from the TOE even if the ifnet for this
|
||||
* port has never been UP'd administratively.
|
||||
*/
|
||||
if (!(pi->flags & PORT_INIT_DONE)) {
|
||||
rc = cxgbe_init_synchronized(pi);
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
@ -49,6 +49,23 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ipmi/ipmivars.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Driver request structures are allocated on the stack via alloca() to
|
||||
* avoid calling malloc(), especially for the watchdog handler.
|
||||
* To avoid too much stack growth, a previously allocated structure can
|
||||
* be reused via IPMI_INIT_DRIVER_REQUEST(), but the caller should ensure
|
||||
* that there is adequate reply/request space in the original allocation.
|
||||
*/
|
||||
#define IPMI_INIT_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \
|
||||
bzero((req), sizeof(struct ipmi_request)); \
|
||||
ipmi_init_request((req), NULL, 0, (addr), (cmd), (reqlen), (replylen))
|
||||
|
||||
#define IPMI_ALLOC_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \
|
||||
(req) = __builtin_alloca(sizeof(struct ipmi_request) + \
|
||||
(reqlen) + (replylen)); \
|
||||
IPMI_INIT_DRIVER_REQUEST((req), (addr), (cmd), (reqlen), \
|
||||
(replylen))
|
||||
|
||||
#ifdef IPMB
|
||||
static int ipmi_ipmb_checksum(u_char, int);
|
||||
static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
|
||||
@ -181,8 +198,8 @@ ipmi_dtor(void *arg)
|
||||
*/
|
||||
dev->ipmi_closing = 1;
|
||||
while (dev->ipmi_requests > 0) {
|
||||
msleep(&dev->ipmi_requests, &sc->ipmi_lock, PWAIT,
|
||||
"ipmidrain", 0);
|
||||
msleep(&dev->ipmi_requests, &sc->ipmi_requests_lock,
|
||||
PWAIT, "ipmidrain", 0);
|
||||
ipmi_purge_completed_requests(dev);
|
||||
}
|
||||
}
|
||||
@ -215,7 +232,7 @@ ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
|
||||
u_char slave_addr = 0x52;
|
||||
int error;
|
||||
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_SEND_MSG, data_len + 8, 0);
|
||||
req->ir_request[0] = channel;
|
||||
req->ir_request[1] = slave_addr;
|
||||
@ -231,7 +248,6 @@ ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
|
||||
|
||||
ipmi_submit_driver_request(sc, req);
|
||||
error = req->ir_error;
|
||||
ipmi_free_request(req);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -243,7 +259,7 @@ ipmi_handle_attn(struct ipmi_softc *sc)
|
||||
int error;
|
||||
|
||||
device_printf(sc->ipmi_dev, "BMC has a message\n");
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_MSG_FLAGS, 0, 1);
|
||||
|
||||
ipmi_submit_driver_request(sc, req);
|
||||
@ -257,9 +273,7 @@ ipmi_handle_attn(struct ipmi_softc *sc)
|
||||
"watchdog about to go off");
|
||||
}
|
||||
if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) {
|
||||
ipmi_free_request(req);
|
||||
|
||||
req = ipmi_alloc_driver_request(
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req,
|
||||
IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0,
|
||||
16);
|
||||
|
||||
@ -268,7 +282,6 @@ ipmi_handle_attn(struct ipmi_softc *sc)
|
||||
}
|
||||
}
|
||||
error = req->ir_error;
|
||||
ipmi_free_request(req);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -478,15 +491,11 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data,
|
||||
* Request management.
|
||||
*/
|
||||
|
||||
/* Allocate a new request with request and reply buffers. */
|
||||
struct ipmi_request *
|
||||
ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
|
||||
uint8_t command, size_t requestlen, size_t replylen)
|
||||
static __inline void
|
||||
ipmi_init_request(struct ipmi_request *req, struct ipmi_device *dev, long msgid,
|
||||
uint8_t addr, uint8_t command, size_t requestlen, size_t replylen)
|
||||
{
|
||||
struct ipmi_request *req;
|
||||
|
||||
req = malloc(sizeof(struct ipmi_request) + requestlen + replylen,
|
||||
M_IPMI, M_WAITOK | M_ZERO);
|
||||
req->ir_owner = dev;
|
||||
req->ir_msgid = msgid;
|
||||
req->ir_addr = addr;
|
||||
@ -499,6 +508,18 @@ ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
|
||||
req->ir_reply = (char *)&req[1] + requestlen;
|
||||
req->ir_replybuflen = replylen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a new request with request and reply buffers. */
|
||||
struct ipmi_request *
|
||||
ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
|
||||
uint8_t command, size_t requestlen, size_t replylen)
|
||||
{
|
||||
struct ipmi_request *req;
|
||||
|
||||
req = malloc(sizeof(struct ipmi_request) + requestlen + replylen,
|
||||
M_IPMI, M_WAITOK | M_ZERO);
|
||||
ipmi_init_request(req, dev, msgid, addr, command, requestlen, replylen);
|
||||
return (req);
|
||||
}
|
||||
|
||||
@ -533,21 +554,13 @@ ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
}
|
||||
}
|
||||
|
||||
/* Enqueue an internal driver request and wait until it is completed. */
|
||||
/* Perform an internal driver request. */
|
||||
int
|
||||
ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req,
|
||||
int timo)
|
||||
{
|
||||
int error;
|
||||
|
||||
IPMI_LOCK(sc);
|
||||
error = sc->ipmi_enqueue_request(sc, req);
|
||||
if (error == 0)
|
||||
error = msleep(req, &sc->ipmi_lock, 0, "ipmireq", timo);
|
||||
if (error == 0)
|
||||
error = req->ir_error;
|
||||
IPMI_UNLOCK(sc);
|
||||
return (error);
|
||||
return (sc->ipmi_driver_request(sc, req, timo));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -564,7 +577,7 @@ ipmi_dequeue_request(struct ipmi_softc *sc)
|
||||
IPMI_LOCK_ASSERT(sc);
|
||||
|
||||
while (!sc->ipmi_detaching && TAILQ_EMPTY(&sc->ipmi_pending_requests))
|
||||
cv_wait(&sc->ipmi_request_added, &sc->ipmi_lock);
|
||||
cv_wait(&sc->ipmi_request_added, &sc->ipmi_requests_lock);
|
||||
if (sc->ipmi_detaching)
|
||||
return (NULL);
|
||||
|
||||
@ -598,7 +611,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
|
||||
if (sec > 0xffff / 10)
|
||||
return (EINVAL);
|
||||
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_SET_WDOG, 6, 0);
|
||||
|
||||
if (sec) {
|
||||
@ -622,9 +635,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
|
||||
if (error)
|
||||
device_printf(sc->ipmi_dev, "Failed to set watchdog\n");
|
||||
else if (sec) {
|
||||
ipmi_free_request(req);
|
||||
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_RESET_WDOG, 0, 0);
|
||||
|
||||
error = ipmi_submit_driver_request(sc, req, 0);
|
||||
@ -633,7 +644,6 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
|
||||
"Failed to reset watchdog\n");
|
||||
}
|
||||
|
||||
ipmi_free_request(req);
|
||||
return (error);
|
||||
/*
|
||||
dump_watchdog(sc);
|
||||
@ -680,7 +690,8 @@ ipmi_startup(void *arg)
|
||||
dev = sc->ipmi_dev;
|
||||
|
||||
/* Initialize interface-independent state. */
|
||||
mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF);
|
||||
mtx_init(&sc->ipmi_requests_lock, "ipmi requests", NULL, MTX_DEF);
|
||||
mtx_init(&sc->ipmi_io_lock, "ipmi io", NULL, MTX_DEF);
|
||||
cv_init(&sc->ipmi_request_added, "ipmireq");
|
||||
TAILQ_INIT(&sc->ipmi_pending_requests);
|
||||
|
||||
@ -693,28 +704,24 @@ ipmi_startup(void *arg)
|
||||
}
|
||||
|
||||
/* Send a GET_DEVICE_ID request. */
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_DEVICE_ID, 0, 15);
|
||||
|
||||
error = ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
|
||||
if (error == EWOULDBLOCK) {
|
||||
device_printf(dev, "Timed out waiting for GET_DEVICE_ID\n");
|
||||
ipmi_free_request(req);
|
||||
return;
|
||||
} else if (error) {
|
||||
device_printf(dev, "Failed GET_DEVICE_ID: %d\n", error);
|
||||
ipmi_free_request(req);
|
||||
return;
|
||||
} else if (req->ir_compcode != 0) {
|
||||
device_printf(dev,
|
||||
"Bad completion code for GET_DEVICE_ID: %d\n",
|
||||
req->ir_compcode);
|
||||
ipmi_free_request(req);
|
||||
return;
|
||||
} else if (req->ir_replylen < 5) {
|
||||
device_printf(dev, "Short reply for GET_DEVICE_ID: %d\n",
|
||||
req->ir_replylen);
|
||||
ipmi_free_request(req);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -724,9 +731,7 @@ ipmi_startup(void *arg)
|
||||
req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f,
|
||||
req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4);
|
||||
|
||||
ipmi_free_request(req);
|
||||
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_CLEAR_FLAGS, 1, 0);
|
||||
|
||||
ipmi_submit_driver_request(sc, req, 0);
|
||||
@ -738,25 +743,21 @@ ipmi_startup(void *arg)
|
||||
if (req->ir_compcode == 0xc1) {
|
||||
device_printf(dev, "Clear flags illegal\n");
|
||||
}
|
||||
ipmi_free_request(req);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_CHANNEL_INFO, 1, 0);
|
||||
req->ir_request[0] = i;
|
||||
|
||||
ipmi_submit_driver_request(sc, req, 0);
|
||||
|
||||
if (req->ir_compcode != 0) {
|
||||
ipmi_free_request(req);
|
||||
if (req->ir_compcode != 0)
|
||||
break;
|
||||
}
|
||||
ipmi_free_request(req);
|
||||
}
|
||||
device_printf(dev, "Number of channels %d\n", i);
|
||||
|
||||
/* probe for watchdog */
|
||||
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_WDOG, 0, 0);
|
||||
|
||||
ipmi_submit_driver_request(sc, req, 0);
|
||||
@ -767,7 +768,6 @@ ipmi_startup(void *arg)
|
||||
sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list,
|
||||
ipmi_wd_event, sc, 0);
|
||||
}
|
||||
ipmi_free_request(req);
|
||||
|
||||
sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
|
||||
UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
|
||||
@ -834,14 +834,16 @@ ipmi_detach(device_t dev)
|
||||
sc->ipmi_detaching = 1;
|
||||
if (sc->ipmi_kthread) {
|
||||
cv_broadcast(&sc->ipmi_request_added);
|
||||
msleep(sc->ipmi_kthread, &sc->ipmi_lock, 0, "ipmi_wait", 0);
|
||||
msleep(sc->ipmi_kthread, &sc->ipmi_requests_lock, 0,
|
||||
"ipmi_wait", 0);
|
||||
}
|
||||
IPMI_UNLOCK(sc);
|
||||
if (sc->ipmi_irq)
|
||||
bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq);
|
||||
|
||||
ipmi_release_resources(dev);
|
||||
mtx_destroy(&sc->ipmi_lock);
|
||||
mtx_destroy(&sc->ipmi_io_lock);
|
||||
mtx_destroy(&sc->ipmi_requests_lock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -321,6 +321,8 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
u_char *cp, data;
|
||||
int i, state;
|
||||
|
||||
IPMI_IO_LOCK(sc);
|
||||
|
||||
/* Send the request. */
|
||||
if (!kcs_start_write(sc)) {
|
||||
device_printf(sc->ipmi_dev, "KCS: Failed to start write\n");
|
||||
@ -444,6 +446,7 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
}
|
||||
i++;
|
||||
}
|
||||
IPMI_IO_UNLOCK(sc);
|
||||
req->ir_replylen = i;
|
||||
#ifdef KCS_DEBUG
|
||||
device_printf(sc->ipmi_dev, "KCS: READ finished (%d bytes)\n", i);
|
||||
@ -457,6 +460,7 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
return (1);
|
||||
fail:
|
||||
kcs_error(sc);
|
||||
IPMI_IO_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -492,6 +496,21 @@ kcs_startup(struct ipmi_softc *sc)
|
||||
device_get_nameunit(sc->ipmi_dev)));
|
||||
}
|
||||
|
||||
static int
|
||||
kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
ok = 0;
|
||||
for (i = 0; i < 3 && !ok; i++)
|
||||
ok = kcs_polled_request(sc, req);
|
||||
if (ok)
|
||||
req->ir_error = 0;
|
||||
else
|
||||
req->ir_error = EIO;
|
||||
return (req->ir_error);
|
||||
}
|
||||
|
||||
int
|
||||
ipmi_kcs_attach(struct ipmi_softc *sc)
|
||||
{
|
||||
@ -500,6 +519,7 @@ ipmi_kcs_attach(struct ipmi_softc *sc)
|
||||
/* Setup function pointers. */
|
||||
sc->ipmi_startup = kcs_startup;
|
||||
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
|
||||
sc->ipmi_driver_request = kcs_driver_request;
|
||||
|
||||
/* See if we can talk to the controller. */
|
||||
status = INB(sc, KCS_CTL_STS);
|
||||
|
@ -364,8 +364,11 @@ smic_loop(void *arg)
|
||||
while ((req = ipmi_dequeue_request(sc)) != NULL) {
|
||||
IPMI_UNLOCK(sc);
|
||||
ok = 0;
|
||||
for (i = 0; i < 3 && !ok; i++)
|
||||
for (i = 0; i < 3 && !ok; i++) {
|
||||
IPMI_IO_LOCK(sc);
|
||||
ok = smic_polled_request(sc, req);
|
||||
IPMI_IO_UNLOCK(sc);
|
||||
}
|
||||
if (ok)
|
||||
req->ir_error = 0;
|
||||
else
|
||||
@ -385,6 +388,24 @@ smic_startup(struct ipmi_softc *sc)
|
||||
"%s: smic", device_get_nameunit(sc->ipmi_dev)));
|
||||
}
|
||||
|
||||
static int
|
||||
smic_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
ok = 0;
|
||||
for (i = 0; i < 3 && !ok; i++) {
|
||||
IPMI_IO_LOCK(sc);
|
||||
ok = smic_polled_request(sc, req);
|
||||
IPMI_IO_UNLOCK(sc);
|
||||
}
|
||||
if (ok)
|
||||
req->ir_error = 0;
|
||||
else
|
||||
req->ir_error = EIO;
|
||||
return (req->ir_error);
|
||||
}
|
||||
|
||||
int
|
||||
ipmi_smic_attach(struct ipmi_softc *sc)
|
||||
{
|
||||
@ -393,6 +414,7 @@ ipmi_smic_attach(struct ipmi_softc *sc)
|
||||
/* Setup function pointers. */
|
||||
sc->ipmi_startup = smic_startup;
|
||||
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
|
||||
sc->ipmi_driver_request = smic_driver_request;
|
||||
|
||||
/* See if we can talk to the controller. */
|
||||
flags = INB(sc, SMIC_FLAGS);
|
||||
|
@ -359,6 +359,22 @@ ssif_startup(struct ipmi_softc *sc)
|
||||
"%s: ssif", device_get_nameunit(sc->ipmi_dev)));
|
||||
}
|
||||
|
||||
static int
|
||||
ssif_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
{
|
||||
int error;
|
||||
|
||||
IPMI_LOCK(sc);
|
||||
error = ipmi_polled_enqueue_request(sc, req);
|
||||
if (error == 0)
|
||||
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq",
|
||||
timo);
|
||||
if (error == 0)
|
||||
error = req->ir_error;
|
||||
IPMI_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ipmi_ssif_attach(struct ipmi_softc *sc, device_t smbus, int smbus_address)
|
||||
{
|
||||
@ -370,6 +386,7 @@ ipmi_ssif_attach(struct ipmi_softc *sc, device_t smbus, int smbus_address)
|
||||
/* Setup function pointers. */
|
||||
sc->ipmi_startup = ssif_startup;
|
||||
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
|
||||
sc->ipmi_driver_request = ssif_driver_request;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ struct ipmi_softc {
|
||||
} _iface;
|
||||
int ipmi_io_rid;
|
||||
int ipmi_io_type;
|
||||
struct mtx ipmi_io_lock;
|
||||
struct resource *ipmi_io_res[MAX_RES];
|
||||
int ipmi_io_spacing;
|
||||
int ipmi_irq_rid;
|
||||
@ -107,12 +108,13 @@ struct ipmi_softc {
|
||||
eventhandler_tag ipmi_watchdog_tag;
|
||||
int ipmi_watchdog_active;
|
||||
struct intr_config_hook ipmi_ich;
|
||||
struct mtx ipmi_lock;
|
||||
struct mtx ipmi_requests_lock;
|
||||
struct cv ipmi_request_added;
|
||||
struct proc *ipmi_kthread;
|
||||
driver_intr_t *ipmi_intr;
|
||||
int (*ipmi_startup)(struct ipmi_softc *);
|
||||
int (*ipmi_enqueue_request)(struct ipmi_softc *, struct ipmi_request *);
|
||||
int (*ipmi_driver_request)(struct ipmi_softc *, struct ipmi_request *, int);
|
||||
};
|
||||
|
||||
#define ipmi_ssif_smbus_address _iface.ssif.smbus_address
|
||||
@ -183,12 +185,13 @@ struct ipmi_ipmb {
|
||||
#define IPMI_ADDR(netfn, lun) ((netfn) << 2 | (lun))
|
||||
#define IPMI_REPLY_ADDR(addr) ((addr) + 0x4)
|
||||
|
||||
#define IPMI_LOCK(sc) mtx_lock(&(sc)->ipmi_lock)
|
||||
#define IPMI_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_lock)
|
||||
#define IPMI_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_lock, MA_OWNED)
|
||||
#define IPMI_LOCK(sc) mtx_lock(&(sc)->ipmi_requests_lock)
|
||||
#define IPMI_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_requests_lock)
|
||||
#define IPMI_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_requests_lock, MA_OWNED)
|
||||
|
||||
#define ipmi_alloc_driver_request(addr, cmd, reqlen, replylen) \
|
||||
ipmi_alloc_request(NULL, 0, (addr), (cmd), (reqlen), (replylen))
|
||||
#define IPMI_IO_LOCK(sc) mtx_lock(&(sc)->ipmi_io_lock)
|
||||
#define IPMI_IO_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_io_lock)
|
||||
#define IPMI_IO_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_io_lock, MA_OWNED)
|
||||
|
||||
#if __FreeBSD_version < 601105
|
||||
#define bus_read_1(r, o) \
|
||||
|
@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/conf.h>
|
||||
@ -4824,8 +4825,8 @@ pci_child_location_str_method(device_t dev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
|
||||
snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child),
|
||||
pci_get_function(child));
|
||||
snprintf(buf, buflen, "pci%d:%d:%d:%d", pci_get_domain(child),
|
||||
pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -4855,10 +4856,60 @@ pci_assign_interrupt_method(device_t dev, device_t child)
|
||||
cfg->intpin));
|
||||
}
|
||||
|
||||
static void
|
||||
pci_lookup(void *arg, const char *name, device_t *dev)
|
||||
{
|
||||
long val;
|
||||
char *end;
|
||||
int domain, bus, slot, func;
|
||||
|
||||
if (*dev != NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Accept pciconf-style selectors of either pciD:B:S:F or
|
||||
* pciB:S:F. In the latter case, the domain is assumed to
|
||||
* be zero.
|
||||
*/
|
||||
if (strncmp(name, "pci", 3) != 0)
|
||||
return;
|
||||
val = strtol(name + 3, &end, 10);
|
||||
if (val < 0 || val > INT_MAX || *end != ':')
|
||||
return;
|
||||
domain = val;
|
||||
val = strtol(end + 1, &end, 10);
|
||||
if (val < 0 || val > INT_MAX || *end != ':')
|
||||
return;
|
||||
bus = val;
|
||||
val = strtol(end + 1, &end, 10);
|
||||
if (val < 0 || val > INT_MAX)
|
||||
return;
|
||||
slot = val;
|
||||
if (*end == ':') {
|
||||
val = strtol(end + 1, &end, 10);
|
||||
if (val < 0 || val > INT_MAX || *end != '\0')
|
||||
return;
|
||||
func = val;
|
||||
} else if (*end == '\0') {
|
||||
func = slot;
|
||||
slot = bus;
|
||||
bus = domain;
|
||||
domain = 0;
|
||||
} else
|
||||
return;
|
||||
|
||||
if (domain > PCI_DOMAINMAX || bus > PCI_BUSMAX || slot > PCI_SLOTMAX ||
|
||||
func > PCIE_ARI_FUNCMAX || (slot != 0 && func > PCI_FUNCMAX))
|
||||
return;
|
||||
|
||||
*dev = pci_find_dbsf(domain, bus, slot, func);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_modevent(module_t mod, int what, void *arg)
|
||||
{
|
||||
static struct cdev *pci_cdev;
|
||||
static eventhandler_tag tag;
|
||||
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
@ -4867,9 +4918,13 @@ pci_modevent(module_t mod, int what, void *arg)
|
||||
pci_cdev = make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644,
|
||||
"pci");
|
||||
pci_load_vendor_data();
|
||||
tag = EVENTHANDLER_REGISTER(dev_lookup, pci_lookup, NULL,
|
||||
1000);
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
if (tag != NULL)
|
||||
EVENTHANDLER_DEREGISTER(dev_lookup, tag);
|
||||
destroy_dev(pci_cdev);
|
||||
break;
|
||||
}
|
||||
|
@ -1137,15 +1137,28 @@ void
|
||||
ipi_startup(int apic_id, int vector)
|
||||
{
|
||||
|
||||
/*
|
||||
* This attempts to follow the algorithm described in the
|
||||
* Intel Multiprocessor Specification v1.4 in section B.4.
|
||||
* For each IPI, we allow the local APIC ~20us to deliver the
|
||||
* IPI. If that times out, we panic.
|
||||
*/
|
||||
|
||||
/*
|
||||
* first we do an INIT IPI: this INIT IPI might be run, resetting
|
||||
* and running the target CPU. OR this INIT IPI might be latched (P5
|
||||
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
|
||||
* ignored.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
lapic_ipi_wait(20);
|
||||
|
||||
/* Explicitly deassert the INIT IPI. */
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT,
|
||||
apic_id);
|
||||
|
||||
DELAY(10000); /* wait ~10mS */
|
||||
|
||||
/*
|
||||
@ -1157,9 +1170,11 @@ ipi_startup(int apic_id, int vector)
|
||||
* will run.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
vector, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
if (!lapic_ipi_wait(20))
|
||||
panic("Failed to deliver first STARTUP IPI to APIC %d",
|
||||
apic_id);
|
||||
DELAY(200); /* wait ~200uS */
|
||||
|
||||
/*
|
||||
@ -1169,9 +1184,12 @@ ipi_startup(int apic_id, int vector)
|
||||
* recognized after hardware RESET or INIT IPI.
|
||||
*/
|
||||
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
|
||||
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
|
||||
vector, apic_id);
|
||||
lapic_ipi_wait(-1);
|
||||
if (!lapic_ipi_wait(20))
|
||||
panic("Failed to deliver second STARTUP IPI to APIC %d",
|
||||
apic_id);
|
||||
|
||||
DELAY(200); /* wait ~200uS */
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/queue.h>
|
||||
@ -128,15 +129,6 @@ struct device {
|
||||
device_state_t state; /**< current device state */
|
||||
uint32_t devflags; /**< api level flags for device_get_flags() */
|
||||
u_int flags; /**< internal device flags */
|
||||
#define DF_ENABLED 0x01 /* device should be probed/attached */
|
||||
#define DF_FIXEDCLASS 0x02 /* devclass specified at create time */
|
||||
#define DF_WILDCARD 0x04 /* unit was originally wildcard */
|
||||
#define DF_DESCMALLOCED 0x08 /* description was malloced */
|
||||
#define DF_QUIET 0x10 /* don't print verbose attach message */
|
||||
#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */
|
||||
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
|
||||
#define DF_REBID 0x80 /* Can rebid after attach */
|
||||
#define DF_SUSPENDED 0x100 /* Device is suspended. */
|
||||
u_int order; /**< order from device_add_child_ordered() */
|
||||
void *ivars; /**< instance variables */
|
||||
void *softc; /**< current driver's variables */
|
||||
@ -148,6 +140,8 @@ struct device {
|
||||
static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
|
||||
static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
|
||||
|
||||
static void devctl2_init(void);
|
||||
|
||||
#ifdef BUS_DEBUG
|
||||
|
||||
static int bus_debug = 1;
|
||||
@ -432,6 +426,7 @@ devinit(void)
|
||||
cv_init(&devsoftc.cv, "dev cv");
|
||||
TAILQ_INIT(&devsoftc.devq);
|
||||
knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
|
||||
devctl2_init();
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2647,6 +2642,15 @@ device_is_attached(device_t dev)
|
||||
return (dev->state >= DS_ATTACHED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return non-zero if the device is currently suspended.
|
||||
*/
|
||||
int
|
||||
device_is_suspended(device_t dev)
|
||||
{
|
||||
return ((dev->flags & DF_SUSPENDED) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the devclass of a device
|
||||
* @see devclass_add_device().
|
||||
@ -5031,3 +5035,253 @@ bus_free_resource(device_t dev, int type, struct resource *r)
|
||||
return (0);
|
||||
return (bus_release_resource(dev, type, rman_get_rid(r), r));
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/devctl2 implementation. The existing /dev/devctl device has
|
||||
* implicit semantics on open, so it could not be reused for this.
|
||||
* Another option would be to call this /dev/bus?
|
||||
*/
|
||||
static int
|
||||
find_device(struct devreq *req, device_t *devp)
|
||||
{
|
||||
device_t dev;
|
||||
|
||||
/*
|
||||
* First, ensure that the name is nul terminated.
|
||||
*/
|
||||
if (memchr(req->dr_name, '\0', sizeof(req->dr_name)) == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Second, try to find an attached device whose name matches
|
||||
* 'name'.
|
||||
*/
|
||||
TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
|
||||
if (dev->nameunit != NULL &&
|
||||
strcmp(dev->nameunit, req->dr_name) == 0) {
|
||||
*devp = dev;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, give device enumerators a chance. */
|
||||
dev = NULL;
|
||||
EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev);
|
||||
if (dev == NULL)
|
||||
return (ENOENT);
|
||||
*devp = dev;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bool
|
||||
driver_exists(struct device *bus, const char *driver)
|
||||
{
|
||||
devclass_t dc;
|
||||
|
||||
for (dc = bus->devclass; dc != NULL; dc = dc->parent) {
|
||||
if (devclass_find_driver_internal(dc, driver) != NULL)
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
static int
|
||||
devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct devreq *req;
|
||||
device_t dev;
|
||||
int error, old;
|
||||
|
||||
/* Locate the device to control. */
|
||||
mtx_lock(&Giant);
|
||||
req = (struct devreq *)data;
|
||||
switch (cmd) {
|
||||
case DEV_ATTACH:
|
||||
case DEV_DETACH:
|
||||
case DEV_ENABLE:
|
||||
case DEV_DISABLE:
|
||||
case DEV_SUSPEND:
|
||||
case DEV_RESUME:
|
||||
case DEV_SET_DRIVER:
|
||||
error = priv_check(td, PRIV_DRIVER);
|
||||
if (error == 0)
|
||||
error = find_device(req, &dev);
|
||||
break;
|
||||
default:
|
||||
error = ENOTTY;
|
||||
break;
|
||||
}
|
||||
if (error) {
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Perform the requested operation. */
|
||||
switch (cmd) {
|
||||
case DEV_ATTACH:
|
||||
if (device_is_attached(dev) && (dev->flags & DF_REBID) == 0)
|
||||
error = EBUSY;
|
||||
else if (!device_is_enabled(dev))
|
||||
error = ENXIO;
|
||||
else
|
||||
error = device_probe_and_attach(dev);
|
||||
break;
|
||||
case DEV_DETACH:
|
||||
if (!device_is_attached(dev)) {
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
|
||||
error = device_quiesce(dev);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
error = device_detach(dev);
|
||||
break;
|
||||
case DEV_ENABLE:
|
||||
if (device_is_enabled(dev)) {
|
||||
error = EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device has been probed but not attached (e.g.
|
||||
* when it has been disabled by a loader hint), just
|
||||
* attach the device rather than doing a full probe.
|
||||
*/
|
||||
device_enable(dev);
|
||||
if (device_is_alive(dev)) {
|
||||
/*
|
||||
* If the device was disabled via a hint, clear
|
||||
* the hint.
|
||||
*/
|
||||
if (resource_disabled(dev->driver->name, dev->unit))
|
||||
resource_unset_value(dev->driver->name,
|
||||
dev->unit, "disabled");
|
||||
error = device_attach(dev);
|
||||
} else
|
||||
error = device_probe_and_attach(dev);
|
||||
break;
|
||||
case DEV_DISABLE:
|
||||
if (!device_is_enabled(dev)) {
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
|
||||
error = device_quiesce(dev);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force DF_FIXEDCLASS on around detach to preserve
|
||||
* the existing name.
|
||||
*/
|
||||
old = dev->flags;
|
||||
dev->flags |= DF_FIXEDCLASS;
|
||||
error = device_detach(dev);
|
||||
if (!(old & DF_FIXEDCLASS))
|
||||
dev->flags &= ~DF_FIXEDCLASS;
|
||||
if (error == 0)
|
||||
device_disable(dev);
|
||||
break;
|
||||
case DEV_SUSPEND:
|
||||
if (device_is_suspended(dev)) {
|
||||
error = EBUSY;
|
||||
break;
|
||||
}
|
||||
if (device_get_parent(dev) == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
error = BUS_SUSPEND_CHILD(device_get_parent(dev), dev);
|
||||
break;
|
||||
case DEV_RESUME:
|
||||
if (!device_is_suspended(dev)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (device_get_parent(dev) == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
error = BUS_RESUME_CHILD(device_get_parent(dev), dev);
|
||||
break;
|
||||
case DEV_SET_DRIVER: {
|
||||
devclass_t dc;
|
||||
char driver[128];
|
||||
|
||||
error = copyinstr(req->dr_data, driver, sizeof(driver), NULL);
|
||||
if (error)
|
||||
break;
|
||||
if (driver[0] == '\0') {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (dev->devclass != NULL &&
|
||||
strcmp(driver, dev->devclass->name) == 0)
|
||||
/* XXX: Could possibly force DF_FIXEDCLASS on? */
|
||||
break;
|
||||
|
||||
/*
|
||||
* Scan drivers for this device's bus looking for at
|
||||
* least one matching driver.
|
||||
*/
|
||||
if (dev->parent == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!driver_exists(dev->parent, driver)) {
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
dc = devclass_create(driver);
|
||||
if (dc == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Detach device if necessary. */
|
||||
if (device_is_attached(dev)) {
|
||||
if (req->dr_flags & DEVF_SET_DRIVER_DETACH)
|
||||
error = device_detach(dev);
|
||||
else
|
||||
error = EBUSY;
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear any previously-fixed device class and unit. */
|
||||
if (dev->flags & DF_FIXEDCLASS)
|
||||
devclass_delete_device(dev->devclass, dev);
|
||||
dev->flags |= DF_WILDCARD;
|
||||
dev->unit = -1;
|
||||
|
||||
/* Force the new device class. */
|
||||
error = devclass_add_device(dc, dev);
|
||||
if (error)
|
||||
break;
|
||||
dev->flags |= DF_FIXEDCLASS;
|
||||
error = device_probe_and_attach(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct cdevsw devctl2_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_ioctl = devctl2_ioctl,
|
||||
.d_name = "devctl2",
|
||||
};
|
||||
|
||||
static void
|
||||
devctl2_init(void)
|
||||
{
|
||||
|
||||
make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
|
||||
UID_ROOT, GID_WHEEL, 0600, "devctl2");
|
||||
}
|
||||
|
@ -461,3 +461,31 @@ resource_disabled(const char *name, int unit)
|
||||
return (0);
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear a value associated with a device by removing it from
|
||||
* the kernel environment. This only removes a hint for an
|
||||
* exact unit.
|
||||
*/
|
||||
int
|
||||
resource_unset_value(const char *name, int unit, const char *resname)
|
||||
{
|
||||
char varname[128];
|
||||
const char *retname, *retvalue;
|
||||
int error, line;
|
||||
size_t len;
|
||||
|
||||
line = 0;
|
||||
error = resource_find(&line, NULL, name, &unit, resname, NULL,
|
||||
&retname, NULL, NULL, NULL, NULL, &retvalue);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
retname -= strlen("hint.");
|
||||
len = retvalue - retname - 1;
|
||||
if (len > sizeof(varname) - 1)
|
||||
return (ENAMETOOLONG);
|
||||
memcpy(varname, retname, len);
|
||||
varname[len] = '\0';
|
||||
return (kern_unsetenv(varname));
|
||||
}
|
||||
|
@ -735,6 +735,8 @@ _zfs= zfs
|
||||
|
||||
.endif
|
||||
|
||||
SUBDIR+=${MODULES_EXTRA}
|
||||
|
||||
.for reject in ${WITHOUT_MODULES}
|
||||
SUBDIR:= ${SUBDIR:N${reject}}
|
||||
.endfor
|
||||
|
@ -6,6 +6,7 @@ SYSDIR?=${.CURDIR}/../..
|
||||
.include "${SYSDIR}/conf/kern.opts.mk"
|
||||
|
||||
SUBDIR= if_cxgbe
|
||||
SUBDIR+= if_cxl
|
||||
SUBDIR+= t4_firmware
|
||||
SUBDIR+= t5_firmware
|
||||
SUBDIR+= ${_tom}
|
||||
|
11
sys/modules/cxgbe/if_cxl/Makefile
Normal file
11
sys/modules/cxgbe/if_cxl/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
CXGBE= ${.CURDIR}/../../../dev/cxgbe
|
||||
.PATH: ${CXGBE}
|
||||
|
||||
KMOD= if_cxl
|
||||
SRCS= if_cxl.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
5
sys/modules/dtb/rpi/Makefile
Normal file
5
sys/modules/dtb/rpi/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
# $FreeBSD$
|
||||
# DTS files for the Raspberry Pi-B
|
||||
DTS=rpi.dts
|
||||
|
||||
.include <bsd.dtb.mk>
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <machine/_limits.h>
|
||||
#include <sys/_bus_dma.h>
|
||||
#include <sys/ioccom.h>
|
||||
|
||||
/**
|
||||
* @defgroup NEWBUS newbus - a generic framework for managing devices
|
||||
@ -70,14 +71,61 @@ struct u_device {
|
||||
char dv_pnpinfo[128]; /**< @brief Plug and play info */
|
||||
char dv_location[128]; /**< @brief Where is the device? */
|
||||
uint32_t dv_devflags; /**< @brief API Flags for device */
|
||||
uint16_t dv_flags; /**< @brief flags for dev date */
|
||||
uint16_t dv_flags; /**< @brief flags for dev state */
|
||||
device_state_t dv_state; /**< @brief State of attachment */
|
||||
/* XXX more driver info? */
|
||||
};
|
||||
|
||||
/* Flags exported via dv_flags. */
|
||||
#define DF_ENABLED 0x01 /* device should be probed/attached */
|
||||
#define DF_FIXEDCLASS 0x02 /* devclass specified at create time */
|
||||
#define DF_WILDCARD 0x04 /* unit was originally wildcard */
|
||||
#define DF_DESCMALLOCED 0x08 /* description was malloced */
|
||||
#define DF_QUIET 0x10 /* don't print verbose attach message */
|
||||
#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */
|
||||
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
|
||||
#define DF_REBID 0x80 /* Can rebid after attach */
|
||||
#define DF_SUSPENDED 0x100 /* Device is suspended. */
|
||||
|
||||
/**
|
||||
* @brief Device request structure used for ioctl's.
|
||||
*
|
||||
* Used for ioctl's on /dev/devctl2. All device ioctl's
|
||||
* must have parameter definitions which begin with dr_name.
|
||||
*/
|
||||
struct devreq_buffer {
|
||||
void *buffer;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct devreq {
|
||||
char dr_name[128];
|
||||
int dr_flags; /* request-specific flags */
|
||||
union {
|
||||
struct devreq_buffer dru_buffer;
|
||||
void *dru_data;
|
||||
} dr_dru;
|
||||
#define dr_buffer dr_dru.dru_buffer /* variable-sized buffer */
|
||||
#define dr_data dr_dru.dru_data /* fixed-size buffer */
|
||||
};
|
||||
|
||||
#define DEV_ATTACH _IOW('D', 1, struct devreq)
|
||||
#define DEV_DETACH _IOW('D', 2, struct devreq)
|
||||
#define DEV_ENABLE _IOW('D', 3, struct devreq)
|
||||
#define DEV_DISABLE _IOW('D', 4, struct devreq)
|
||||
#define DEV_SUSPEND _IOW('D', 5, struct devreq)
|
||||
#define DEV_RESUME _IOW('D', 6, struct devreq)
|
||||
#define DEV_SET_DRIVER _IOW('D', 7, struct devreq)
|
||||
|
||||
/* Flags for DEV_DETACH and DEV_DISABLE. */
|
||||
#define DEVF_FORCE_DETACH 0x0000001
|
||||
|
||||
/* Flags for DEV_SET_DRIVER. */
|
||||
#define DEVF_SET_DRIVER_DETACH 0x0000001 /* Detach existing driver. */
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/kobj.h>
|
||||
|
||||
/**
|
||||
@ -93,6 +141,14 @@ void devctl_notify(const char *__system, const char *__subsystem,
|
||||
void devctl_queue_data_f(char *__data, int __flags);
|
||||
void devctl_queue_data(char *__data);
|
||||
|
||||
/**
|
||||
* Device name parsers. Hook to allow device enumerators to map
|
||||
* scheme-specific names to a device.
|
||||
*/
|
||||
typedef void (*dev_lookup_fn)(void *arg, const char *name,
|
||||
device_t *result);
|
||||
EVENTHANDLER_DECLARE(dev_lookup, dev_lookup_fn);
|
||||
|
||||
/**
|
||||
* @brief A device driver (included mainly for compatibility with
|
||||
* FreeBSD 4.x).
|
||||
@ -454,6 +510,7 @@ struct sysctl_oid *device_get_sysctl_tree(device_t dev);
|
||||
int device_is_alive(device_t dev); /* did probe succeed? */
|
||||
int device_is_attached(device_t dev); /* did attach succeed? */
|
||||
int device_is_enabled(device_t dev);
|
||||
int device_is_suspended(device_t dev);
|
||||
int device_is_quiet(device_t dev);
|
||||
int device_print_prettyname(device_t dev);
|
||||
int device_printf(device_t dev, const char *, ...) __printflike(2, 3);
|
||||
@ -517,6 +574,8 @@ int resource_set_long(const char *name, int unit, const char *resname,
|
||||
long value);
|
||||
int resource_set_string(const char *name, int unit, const char *resname,
|
||||
const char *value);
|
||||
int resource_unset_value(const char *name, int unit, const char *resname);
|
||||
|
||||
/*
|
||||
* Functions for maintaining and checking consistency of
|
||||
* bus information exported to userspace.
|
||||
|
@ -1452,22 +1452,22 @@ SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_THIRD, apic_setup_io, NULL);
|
||||
static int
|
||||
native_lapic_ipi_wait(int delay)
|
||||
{
|
||||
int x, incr;
|
||||
int x;
|
||||
|
||||
/*
|
||||
* Wait delay loops for IPI to be sent. This is highly bogus
|
||||
* since this is sensitive to CPU clock speed. If delay is
|
||||
* Wait delay microseconds for IPI to be sent. If delay is
|
||||
* -1, we wait forever.
|
||||
*/
|
||||
if (delay == -1) {
|
||||
incr = 0;
|
||||
delay = 1;
|
||||
} else
|
||||
incr = 1;
|
||||
for (x = 0; x < delay; x += incr) {
|
||||
while ((lapic->icr_lo & APIC_DELSTAT_MASK) != APIC_DELSTAT_IDLE)
|
||||
ia32_pause();
|
||||
return (1);
|
||||
}
|
||||
|
||||
for (x = 0; x < delay; x += 5) {
|
||||
if ((lapic->icr_lo & APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
|
||||
return (1);
|
||||
ia32_pause();
|
||||
DELAY(5);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -1501,9 +1501,9 @@ native_lapic_ipi_raw(register_t icrlo, u_int dest)
|
||||
intr_restore(saveintr);
|
||||
}
|
||||
|
||||
#define BEFORE_SPIN 1000000
|
||||
#define BEFORE_SPIN 50000
|
||||
#ifdef DETECT_DEADLOCK
|
||||
#define AFTER_SPIN 1000
|
||||
#define AFTER_SPIN 50
|
||||
#endif
|
||||
|
||||
static void
|
||||
@ -1514,7 +1514,7 @@ native_lapic_ipi_vectored(u_int vector, int dest)
|
||||
KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
|
||||
("%s: invalid vector %d", __func__, vector));
|
||||
|
||||
icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
|
||||
icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE | APIC_LEVEL_ASSERT;
|
||||
|
||||
/*
|
||||
* IPI_STOP_HARD is just a "fake" vector used to send a NMI.
|
||||
@ -1522,9 +1522,9 @@ native_lapic_ipi_vectored(u_int vector, int dest)
|
||||
* the vector.
|
||||
*/
|
||||
if (vector == IPI_STOP_HARD)
|
||||
icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
|
||||
icrlo |= APIC_DELMODE_NMI;
|
||||
else
|
||||
icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
|
||||
icrlo |= vector | APIC_DELMODE_FIXED;
|
||||
destfield = 0;
|
||||
switch (dest) {
|
||||
case APIC_IPI_DEST_SELF:
|
||||
|
@ -41,6 +41,7 @@
|
||||
.Op Fl e Ar extras-manifest
|
||||
.Op Fl f Ar filelist
|
||||
.Op Fl k Ar keydir Op Fl K Ar user
|
||||
.Op Fl l Ar label
|
||||
.Op Fl p Ar master.passwd Op Fl g Ar group
|
||||
.Op Fl s Ar size
|
||||
.Ar image-file
|
||||
@ -94,6 +95,8 @@ If no
|
||||
.Fl K
|
||||
argument is supplied then the files will be installed in the root user's
|
||||
directory.
|
||||
.It Fl l Ar label
|
||||
Set the file system volume label.
|
||||
.It Fl p Ar master.passwd Op Fl g Ar group
|
||||
Install an alternate
|
||||
.Ar master.passwd
|
||||
|
@ -75,7 +75,7 @@ KEYDIR=
|
||||
KEYUSERS=
|
||||
PASSWD=
|
||||
|
||||
while getopts "B:de:f:g:K:k:p:s:" opt; do
|
||||
while getopts "B:de:f:g:K:k:l:p:s:" opt; do
|
||||
case "$opt" in
|
||||
B) BFLAG="-B ${OPTARG}" ;;
|
||||
d) DEBUG=1 ;;
|
||||
@ -84,6 +84,7 @@ while getopts "B:de:f:g:K:k:p:s:" opt; do
|
||||
g) GROUP="${OPTARG}" ;;
|
||||
K) KEYUSERS="${KEYUSERS} ${OPTARG}" ;;
|
||||
k) KEYDIR="${OPTARG}" ;;
|
||||
l) LABEL="${OPTARG}" ;;
|
||||
p) PASSWD="${OPTARG}" ;;
|
||||
s) SIZE="${OPTARG}" ;;
|
||||
*) usage ;;
|
||||
@ -165,13 +166,15 @@ if [ -n "${FILELIST}" ]; then
|
||||
awk '
|
||||
!/ type=/ { file = $1 }
|
||||
/ type=/ { if ($1 == file) {print} }' >> ${manifest}
|
||||
else
|
||||
elif [ -n "${EXTRAS}" ]; then
|
||||
# Start with all the files in BSDROOT/METALOG except those in
|
||||
# one of the EXTRAS manifests.
|
||||
grep -h type=file ${EXTRAS} | cut -d' ' -f1 | \
|
||||
sort -u ${BSDROOT}/METALOG - | awk '
|
||||
!/ type=/ { file = $1 }
|
||||
/ type=/ { if ($1 != file) {print} }' >> ${manifest}
|
||||
else
|
||||
sort -u ${BSDROOT}/METALOG >> ${manifest}
|
||||
fi
|
||||
|
||||
# For each extras file, add contents keys relative to the directory the
|
||||
@ -228,9 +231,12 @@ if [ -n "${KEYDIR}" ]; then
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "${LABEL}" ]; then
|
||||
LABELFLAG="-o label=${LABEL}"
|
||||
fi
|
||||
if [ -n "${SIZE}" ]; then
|
||||
SIZEFLAG="-s ${SIZE}"
|
||||
fi
|
||||
|
||||
cd ${BSDROOT}; makefs ${DUPFLAG} -N ${DBDIR} ${SIZEFLAG} ${BFLAG} \
|
||||
-t ffs -f 256 ${IMGFILE} ${manifest}
|
||||
-t ffs ${LABELFLAG} -f 256 ${IMGFILE} ${manifest}
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 8, 2005
|
||||
.Dd February 6, 2015
|
||||
.Dt KTRDUMP 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -34,9 +34,9 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl cfqrtH
|
||||
.Op Fl e Ar execfile
|
||||
.Op Fl i Ar ktrfile
|
||||
.Op Fl m Ar corefile
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
.Op Fl o Ar outfile
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
@ -44,7 +44,7 @@ The
|
||||
utility is used to dump the contents of the kernel ktr trace buffer.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width ".Fl e Ar execfile"
|
||||
.Bl -tag -width ".Fl i Ar ktrfile"
|
||||
.It Fl c
|
||||
Print the CPU number that each entry was logged from.
|
||||
.It Fl f
|
||||
@ -61,11 +61,11 @@ Print the thread ID for each entry.
|
||||
File containing saved ktr trace events; for more information see the
|
||||
.Xr ktr 4
|
||||
manual page.
|
||||
.It Fl e Ar execfile
|
||||
.It Fl N Ar system
|
||||
The kernel image to resolve symbols from.
|
||||
The default is the value returned via
|
||||
.Xr getbootfile 3 .
|
||||
.It Fl m Ar corefile
|
||||
.It Fl M Ar core
|
||||
The core file or memory image to read from.
|
||||
The default is
|
||||
.Pa /dev/mem .
|
||||
|
@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define SBUFLEN 128
|
||||
#define USAGE \
|
||||
"usage: ktrdump [-cfqrtH] [-e execfile] [-i ktrfile] [-m corefile] [-o outfile]\n"
|
||||
"usage: ktrdump [-cfqrtH] [-i ktrfile] [-M core] [-N system] [-o outfile]\n"
|
||||
|
||||
static void usage(void);
|
||||
|
||||
@ -59,9 +59,9 @@ static struct nlist nl[] = {
|
||||
};
|
||||
|
||||
static int cflag;
|
||||
static int eflag;
|
||||
static int fflag;
|
||||
static int mflag;
|
||||
static int Mflag;
|
||||
static int Nflag;
|
||||
static int qflag;
|
||||
static int rflag;
|
||||
static int tflag;
|
||||
@ -103,16 +103,17 @@ main(int ac, char **av)
|
||||
* Parse commandline arguments.
|
||||
*/
|
||||
out = stdout;
|
||||
while ((c = getopt(ac, av, "cfqrtHe:i:m:o:")) != -1)
|
||||
while ((c = getopt(ac, av, "cfqrtHe:i:m:M:N:o:")) != -1)
|
||||
switch (c) {
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'N':
|
||||
case 'e':
|
||||
if (strlcpy(execfile, optarg, sizeof(execfile))
|
||||
>= sizeof(execfile))
|
||||
errx(1, "%s: File name too long", optarg);
|
||||
eflag = 1;
|
||||
Nflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
@ -122,11 +123,12 @@ main(int ac, char **av)
|
||||
if ((in = open(optarg, O_RDONLY)) == -1)
|
||||
err(1, "%s", optarg);
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (strlcpy(corefile, optarg, sizeof(corefile))
|
||||
>= sizeof(corefile))
|
||||
errx(1, "%s: File name too long", optarg);
|
||||
mflag = 1;
|
||||
Mflag = 1;
|
||||
break;
|
||||
case 'o':
|
||||
if ((out = fopen(optarg, "w")) == NULL)
|
||||
@ -157,8 +159,8 @@ main(int ac, char **av)
|
||||
* Open our execfile and corefile, resolve needed symbols and read in
|
||||
* the trace buffer.
|
||||
*/
|
||||
if ((kd = kvm_openfiles(eflag ? execfile : NULL,
|
||||
mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
|
||||
if ((kd = kvm_openfiles(Nflag ? execfile : NULL,
|
||||
Mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
|
||||
errx(1, "%s", errbuf);
|
||||
if (kvm_nlist(kd, nl) != 0 ||
|
||||
kvm_read(kd, nl[0].n_value, &version, sizeof(version)) == -1)
|
||||
|
@ -19,6 +19,7 @@ SUBDIR= adduser \
|
||||
ctld \
|
||||
daemon \
|
||||
dconschat \
|
||||
devctl \
|
||||
devinfo \
|
||||
digictl \
|
||||
diskinfo \
|
||||
|
@ -3439,6 +3439,7 @@ struct cctl_islist_conn {
|
||||
char *header_digest;
|
||||
char *data_digest;
|
||||
char *max_data_segment_length;;
|
||||
char *offload;;
|
||||
int immediate_data;
|
||||
int iser;
|
||||
STAILQ_ENTRY(cctl_islist_conn) links;
|
||||
@ -3552,6 +3553,9 @@ cctl_islist_end_element(void *user_data, const char *name)
|
||||
} else if (strcmp(name, "max_data_segment_length") == 0) {
|
||||
cur_conn->max_data_segment_length = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "offload") == 0) {
|
||||
cur_conn->offload = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "immediate_data") == 0) {
|
||||
cur_conn->immediate_data = atoi(str);
|
||||
} else if (strcmp(name, "iser") == 0) {
|
||||
@ -3559,8 +3563,12 @@ cctl_islist_end_element(void *user_data, const char *name)
|
||||
} else if (strcmp(name, "connection") == 0) {
|
||||
islist->cur_conn = NULL;
|
||||
} else if (strcmp(name, "ctlislist") == 0) {
|
||||
} else
|
||||
errx(1, "unknown element %s", name);
|
||||
/* Nothing. */
|
||||
} else {
|
||||
/*
|
||||
* Unknown element; ignore it for forward compatiblity.
|
||||
*/
|
||||
}
|
||||
|
||||
free(str);
|
||||
}
|
||||
@ -3668,6 +3676,7 @@ cctl_islist(int fd, int argc, char **argv, char *combinedopt)
|
||||
printf("DataSegmentLen: %s\n", conn->max_data_segment_length);
|
||||
printf("ImmediateData: %s\n", conn->immediate_data ? "Yes" : "No");
|
||||
printf("iSER (RDMA): %s\n", conn->iser ? "Yes" : "No");
|
||||
printf("Offload driver: %s\n", conn->offload);
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
|
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 1, 2015
|
||||
.Dd February 6, 2015
|
||||
.Dt CTL.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -66,7 +66,7 @@ file is:
|
||||
|
||||
.No target Ar name {
|
||||
.Dl auth-group Ar name
|
||||
.Dl portal-group Ar name
|
||||
.Dl portal-group Ar name Op Ar agname
|
||||
.Dl lun Ar number Ar name
|
||||
.Dl lun Ar number No {
|
||||
.Dl path Ar path
|
||||
@ -310,12 +310,17 @@ This clause is mutually exclusive with
|
||||
.Sy auth-group ;
|
||||
one cannot use
|
||||
both in a single target.
|
||||
.It Ic portal-group Ar name
|
||||
.It Ic offload Ar driver
|
||||
Define iSCSI hardware offload driver to use for this target.
|
||||
.It Ic portal-group Ar name Op Ar agname
|
||||
Assign a previously defined portal group to the target.
|
||||
The default portal group is
|
||||
.Qq Ar default ,
|
||||
which makes the target available
|
||||
on TCP port 3260 on all configured IPv4 and IPv6 addresses.
|
||||
Optional second argument specifies auth group name for connections
|
||||
to this specific portal group.
|
||||
If second argument is not specified, target auth group is used.
|
||||
.It Ic redirect Aq Ar address
|
||||
IPv4 or IPv6 address to redirect initiators to.
|
||||
When configured, all initiators attempting to connect to this target
|
||||
|
@ -91,6 +91,7 @@ conf_new(void)
|
||||
TAILQ_INIT(&conf->conf_luns);
|
||||
TAILQ_INIT(&conf->conf_targets);
|
||||
TAILQ_INIT(&conf->conf_auth_groups);
|
||||
TAILQ_INIT(&conf->conf_ports);
|
||||
TAILQ_INIT(&conf->conf_portal_groups);
|
||||
TAILQ_INIT(&conf->conf_isns);
|
||||
|
||||
@ -124,6 +125,7 @@ conf_delete(struct conf *conf)
|
||||
portal_group_delete(pg);
|
||||
TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
|
||||
isns_delete(is);
|
||||
assert(TAILQ_EMPTY(&conf->conf_ports));
|
||||
free(conf->conf_pidfile_path);
|
||||
free(conf);
|
||||
}
|
||||
@ -609,6 +611,7 @@ portal_group_new(struct conf *conf, const char *name)
|
||||
log_err(1, "calloc");
|
||||
pg->pg_name = checked_strdup(name);
|
||||
TAILQ_INIT(&pg->pg_portals);
|
||||
TAILQ_INIT(&pg->pg_ports);
|
||||
pg->pg_conf = conf;
|
||||
pg->pg_tag = 0; /* Assigned later in conf_apply(). */
|
||||
TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
|
||||
@ -620,7 +623,10 @@ void
|
||||
portal_group_delete(struct portal_group *pg)
|
||||
{
|
||||
struct portal *portal, *tmp;
|
||||
struct port *port, *tport;
|
||||
|
||||
TAILQ_FOREACH_SAFE(port, &pg->pg_ports, p_pgs, tport)
|
||||
port_delete(port);
|
||||
TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next);
|
||||
|
||||
TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
|
||||
@ -784,6 +790,7 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
|
||||
struct target *target;
|
||||
struct portal *portal;
|
||||
struct portal_group *pg;
|
||||
struct port *port;
|
||||
struct isns_req *req;
|
||||
int res = 0;
|
||||
uint32_t error;
|
||||
@ -807,11 +814,14 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
|
||||
isns_req_add_32(req, 33, 1); /* 1 -- Target*/
|
||||
if (target->t_alias != NULL)
|
||||
isns_req_add_str(req, 34, target->t_alias);
|
||||
pg = target->t_portal_group;
|
||||
isns_req_add_32(req, 51, pg->pg_tag);
|
||||
TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
|
||||
isns_req_add_addr(req, 49, portal->p_ai);
|
||||
isns_req_add_port(req, 50, portal->p_ai);
|
||||
TAILQ_FOREACH(port, &target->t_ports, p_ts) {
|
||||
if ((pg = port->p_portal_group) == NULL)
|
||||
continue;
|
||||
isns_req_add_32(req, 51, pg->pg_tag);
|
||||
TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
|
||||
isns_req_add_addr(req, 49, portal->p_ai);
|
||||
isns_req_add_port(req, 50, portal->p_ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
res = isns_req_send(s, req);
|
||||
@ -1123,6 +1133,68 @@ valid_iscsi_name(const char *name)
|
||||
return (true);
|
||||
}
|
||||
|
||||
struct port *
|
||||
port_new(struct conf *conf, struct target *target, struct portal_group *pg)
|
||||
{
|
||||
struct port *port;
|
||||
|
||||
port = calloc(1, sizeof(*port));
|
||||
if (port == NULL)
|
||||
log_err(1, "calloc");
|
||||
asprintf(&port->p_name, "%s-%s", pg->pg_name, target->t_name);
|
||||
if (port_find(conf, port->p_name) != NULL) {
|
||||
log_warnx("duplicate port \"%s\"", port->p_name);
|
||||
free(port);
|
||||
return (NULL);
|
||||
}
|
||||
port->p_conf = conf;
|
||||
TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
|
||||
TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts);
|
||||
port->p_target = target;
|
||||
TAILQ_INSERT_TAIL(&pg->pg_ports, port, p_pgs);
|
||||
port->p_portal_group = pg;
|
||||
return (port);
|
||||
}
|
||||
|
||||
struct port *
|
||||
port_find(const struct conf *conf, const char *name)
|
||||
{
|
||||
struct port *port;
|
||||
|
||||
TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
|
||||
if (strcasecmp(port->p_name, name) == 0)
|
||||
return (port);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct port *
|
||||
port_find_in_pg(const struct portal_group *pg, const char *target)
|
||||
{
|
||||
struct port *port;
|
||||
|
||||
TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
|
||||
if (strcasecmp(port->p_target->t_name, target) == 0)
|
||||
return (port);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
port_delete(struct port *port)
|
||||
{
|
||||
|
||||
if (port->p_portal_group)
|
||||
TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs);
|
||||
if (port->p_target)
|
||||
TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts);
|
||||
TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next);
|
||||
free(port->p_name);
|
||||
free(port);
|
||||
}
|
||||
|
||||
struct target *
|
||||
target_new(struct conf *conf, const char *name)
|
||||
{
|
||||
@ -1151,6 +1223,7 @@ target_new(struct conf *conf, const char *name)
|
||||
targ->t_name[i] = tolower(targ->t_name[i]);
|
||||
|
||||
targ->t_conf = conf;
|
||||
TAILQ_INIT(&targ->t_ports);
|
||||
TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
|
||||
|
||||
return (targ);
|
||||
@ -1159,7 +1232,10 @@ target_new(struct conf *conf, const char *name)
|
||||
void
|
||||
target_delete(struct target *targ)
|
||||
{
|
||||
struct port *port, *tport;
|
||||
|
||||
TAILQ_FOREACH_SAFE(port, &targ->t_ports, p_ts, tport)
|
||||
port_delete(port);
|
||||
TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
|
||||
|
||||
free(targ->t_name);
|
||||
@ -1196,11 +1272,20 @@ target_set_redirection(struct target *target, const char *addr)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
target_set_ctl_port(struct target *target, uint32_t value)
|
||||
int
|
||||
target_set_offload(struct target *target, const char *offload)
|
||||
{
|
||||
|
||||
target->t_ctl_port = value;
|
||||
if (target->t_offload != NULL) {
|
||||
log_warnx("cannot set offload to \"%s\" for "
|
||||
"target \"%s\"; already defined",
|
||||
offload, target->t_name);
|
||||
return (1);
|
||||
}
|
||||
|
||||
target->t_offload = checked_strdup(offload);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct lun *
|
||||
@ -1445,6 +1530,8 @@ conf_print(struct conf *conf)
|
||||
fprintf(stderr, "target %s {\n", targ->t_name);
|
||||
if (targ->t_alias != NULL)
|
||||
fprintf(stderr, "\t alias %s\n", targ->t_alias);
|
||||
if (targ->t_offload != NULL)
|
||||
fprintf(stderr, "\t offload %s\n", targ->t_offload);
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
}
|
||||
@ -1508,6 +1595,7 @@ conf_verify(struct conf *conf)
|
||||
{
|
||||
struct auth_group *ag;
|
||||
struct portal_group *pg;
|
||||
struct port *port;
|
||||
struct target *targ;
|
||||
struct lun *lun;
|
||||
bool found;
|
||||
@ -1527,10 +1615,10 @@ conf_verify(struct conf *conf)
|
||||
"default");
|
||||
assert(targ->t_auth_group != NULL);
|
||||
}
|
||||
if (targ->t_portal_group == NULL) {
|
||||
targ->t_portal_group = portal_group_find(conf,
|
||||
"default");
|
||||
assert(targ->t_portal_group != NULL);
|
||||
if (TAILQ_EMPTY(&targ->t_ports)) {
|
||||
pg = portal_group_find(conf, "default");
|
||||
assert(pg != NULL);
|
||||
port_new(conf, targ, pg);
|
||||
}
|
||||
found = false;
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
@ -1558,20 +1646,14 @@ conf_verify(struct conf *conf)
|
||||
if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN)
|
||||
pg->pg_discovery_filter = PG_FILTER_NONE;
|
||||
|
||||
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
|
||||
if (targ->t_portal_group == pg)
|
||||
break;
|
||||
}
|
||||
if (pg->pg_redirection != NULL) {
|
||||
if (targ != NULL) {
|
||||
if (!TAILQ_EMPTY(&pg->pg_ports)) {
|
||||
if (pg->pg_redirection != NULL) {
|
||||
log_debugx("portal-group \"%s\" assigned "
|
||||
"to target \"%s\", but configured "
|
||||
"to target, but configured "
|
||||
"for redirection",
|
||||
pg->pg_name, targ->t_name);
|
||||
pg->pg_name);
|
||||
}
|
||||
pg->pg_unassigned = false;
|
||||
} else if (targ != NULL) {
|
||||
pg->pg_unassigned = false;
|
||||
} else {
|
||||
if (strcmp(pg->pg_name, "default") != 0)
|
||||
log_warnx("portal-group \"%s\" not assigned "
|
||||
@ -1592,6 +1674,12 @@ conf_verify(struct conf *conf)
|
||||
break;
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
|
||||
if (port->p_auth_group == ag) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
|
||||
if (pg->pg_discovery_auth_group == ag) {
|
||||
found = true;
|
||||
@ -1613,10 +1701,10 @@ conf_verify(struct conf *conf)
|
||||
static int
|
||||
conf_apply(struct conf *oldconf, struct conf *newconf)
|
||||
{
|
||||
struct target *oldtarg, *newtarg, *tmptarg;
|
||||
struct lun *oldlun, *newlun, *tmplun;
|
||||
struct portal_group *oldpg, *newpg;
|
||||
struct portal *oldp, *newp;
|
||||
struct port *oldport, *newport, *tmpport;
|
||||
struct isns *oldns, *newns;
|
||||
pid_t otherpid;
|
||||
int changed, cumulated_error = 0, error, sockbuf;
|
||||
@ -1684,17 +1772,17 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
|
||||
* really happen, so leave it as it is for now.
|
||||
*/
|
||||
/*
|
||||
* First, remove any targets present in the old configuration
|
||||
* First, remove any ports present in the old configuration
|
||||
* and missing in the new one.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
|
||||
newtarg = target_find(newconf, oldtarg->t_name);
|
||||
if (newtarg != NULL)
|
||||
TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) {
|
||||
newport = port_find(newconf, oldport->p_name);
|
||||
if (newport != NULL)
|
||||
continue;
|
||||
error = kernel_port_remove(oldtarg);
|
||||
error = kernel_port_remove(oldport);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove target %s",
|
||||
oldtarg->t_name);
|
||||
log_warnx("failed to remove port %s",
|
||||
oldport->p_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
@ -1809,21 +1897,21 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now add new targets or modify existing ones.
|
||||
* Now add new ports or modify existing ones.
|
||||
*/
|
||||
TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
|
||||
oldtarg = target_find(oldconf, newtarg->t_name);
|
||||
TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) {
|
||||
oldport = port_find(oldconf, newport->p_name);
|
||||
|
||||
if (oldtarg == NULL)
|
||||
error = kernel_port_add(newtarg);
|
||||
else {
|
||||
target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
|
||||
error = kernel_port_update(newtarg);
|
||||
if (oldport == NULL) {
|
||||
error = kernel_port_add(newport);
|
||||
} else {
|
||||
newport->p_ctl_port = oldport->p_ctl_port;
|
||||
error = kernel_port_update(newport);
|
||||
}
|
||||
if (error != 0) {
|
||||
log_warnx("failed to %s target %s",
|
||||
(oldtarg == NULL) ? "add" : "update",
|
||||
newtarg->t_name);
|
||||
log_warnx("failed to %s port %s",
|
||||
(oldport == NULL) ? "add" : "update",
|
||||
newport->p_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
|
@ -119,11 +119,25 @@ struct portal_group {
|
||||
int pg_discovery_filter;
|
||||
bool pg_unassigned;
|
||||
TAILQ_HEAD(, portal) pg_portals;
|
||||
TAILQ_HEAD(, port) pg_ports;
|
||||
char *pg_redirection;
|
||||
|
||||
uint16_t pg_tag;
|
||||
};
|
||||
|
||||
struct port {
|
||||
TAILQ_ENTRY(port) p_next;
|
||||
TAILQ_ENTRY(port) p_pgs;
|
||||
TAILQ_ENTRY(port) p_ts;
|
||||
struct conf *p_conf;
|
||||
char *p_name;
|
||||
struct auth_group *p_auth_group;
|
||||
struct portal_group *p_portal_group;
|
||||
struct target *p_target;
|
||||
|
||||
uint32_t p_ctl_port;
|
||||
};
|
||||
|
||||
struct lun_option {
|
||||
TAILQ_ENTRY(lun_option) lo_next;
|
||||
struct lun *lo_lun;
|
||||
@ -152,12 +166,11 @@ struct target {
|
||||
struct conf *t_conf;
|
||||
struct lun *t_luns[MAX_LUNS];
|
||||
struct auth_group *t_auth_group;
|
||||
struct portal_group *t_portal_group;
|
||||
TAILQ_HEAD(, port) t_ports;
|
||||
char *t_name;
|
||||
char *t_alias;
|
||||
char *t_offload;
|
||||
char *t_redirection;
|
||||
|
||||
uint32_t t_ctl_port;
|
||||
};
|
||||
|
||||
struct isns {
|
||||
@ -172,6 +185,7 @@ struct conf {
|
||||
TAILQ_HEAD(, lun) conf_luns;
|
||||
TAILQ_HEAD(, target) conf_targets;
|
||||
TAILQ_HEAD(, auth_group) conf_auth_groups;
|
||||
TAILQ_HEAD(, port) conf_ports;
|
||||
TAILQ_HEAD(, portal_group) conf_portal_groups;
|
||||
TAILQ_HEAD(, isns) conf_isns;
|
||||
int conf_isns_period;
|
||||
@ -199,6 +213,7 @@ struct conf {
|
||||
|
||||
struct connection {
|
||||
struct portal *conn_portal;
|
||||
struct port *conn_port;
|
||||
struct target *conn_target;
|
||||
int conn_socket;
|
||||
int conn_session_type;
|
||||
@ -209,6 +224,7 @@ struct connection {
|
||||
struct sockaddr_storage conn_initiator_sa;
|
||||
uint32_t conn_cmdsn;
|
||||
uint32_t conn_statsn;
|
||||
size_t conn_data_segment_limit;
|
||||
size_t conn_max_data_segment_length;
|
||||
size_t conn_max_burst_length;
|
||||
int conn_immediate_data;
|
||||
@ -317,14 +333,21 @@ void isns_register(struct isns *isns, struct isns *oldisns);
|
||||
void isns_check(struct isns *isns);
|
||||
void isns_deregister(struct isns *isns);
|
||||
|
||||
struct port *port_new(struct conf *conf, struct target *target,
|
||||
struct portal_group *pg);
|
||||
struct port *port_find(const struct conf *conf, const char *name);
|
||||
struct port *port_find_in_pg(const struct portal_group *pg,
|
||||
const char *target);
|
||||
void port_delete(struct port *port);
|
||||
|
||||
struct target *target_new(struct conf *conf, const char *name);
|
||||
void target_delete(struct target *target);
|
||||
struct target *target_find(struct conf *conf,
|
||||
const char *name);
|
||||
int target_set_redirection(struct target *target,
|
||||
const char *addr);
|
||||
void target_set_ctl_port(struct target *target,
|
||||
uint32_t value);
|
||||
int target_set_offload(struct target *target,
|
||||
const char *offload);
|
||||
|
||||
struct lun *lun_new(struct conf *conf, const char *name);
|
||||
void lun_delete(struct lun *lun);
|
||||
@ -351,9 +374,11 @@ int kernel_lun_add(struct lun *lun);
|
||||
int kernel_lun_resize(struct lun *lun);
|
||||
int kernel_lun_remove(struct lun *lun);
|
||||
void kernel_handoff(struct connection *conn);
|
||||
int kernel_port_add(struct target *targ);
|
||||
int kernel_port_update(struct target *targ);
|
||||
int kernel_port_remove(struct target *targ);
|
||||
void kernel_limits(const char *offload,
|
||||
size_t *max_data_segment_length);
|
||||
int kernel_port_add(struct port *port);
|
||||
int kernel_port_update(struct port *port);
|
||||
int kernel_port_remove(struct port *port);
|
||||
void kernel_capsicate(void);
|
||||
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
|
@ -162,6 +162,7 @@ logout_new_response(struct pdu *request)
|
||||
static void
|
||||
discovery_add_target(struct keys *response_keys, const struct target *targ)
|
||||
{
|
||||
struct port *port;
|
||||
struct portal *portal;
|
||||
char *buf;
|
||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||
@ -169,7 +170,10 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
|
||||
int ret;
|
||||
|
||||
keys_add(response_keys, "TargetName", targ->t_name);
|
||||
TAILQ_FOREACH(portal, &targ->t_portal_group->pg_portals, p_next) {
|
||||
TAILQ_FOREACH(port, &targ->t_ports, p_ts) {
|
||||
if (port->p_portal_group == NULL)
|
||||
continue;
|
||||
TAILQ_FOREACH(portal, &port->p_portal_group->pg_portals, p_next) {
|
||||
ai = portal->p_ai;
|
||||
ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
|
||||
@ -183,13 +187,13 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
|
||||
if (strcmp(hbuf, "0.0.0.0") == 0)
|
||||
continue;
|
||||
ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf,
|
||||
targ->t_portal_group->pg_tag);
|
||||
port->p_portal_group->pg_tag);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (strcmp(hbuf, "::") == 0)
|
||||
continue;
|
||||
ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf,
|
||||
targ->t_portal_group->pg_tag);
|
||||
port->p_portal_group->pg_tag);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
@ -198,19 +202,24 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
|
||||
log_err(1, "asprintf");
|
||||
keys_add(response_keys, "TargetAddress", buf);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
discovery_target_filtered_out(const struct connection *conn,
|
||||
const struct target *targ)
|
||||
const struct port *port)
|
||||
{
|
||||
const struct auth_group *ag;
|
||||
const struct portal_group *pg;
|
||||
const struct target *targ;
|
||||
const struct auth *auth;
|
||||
int error;
|
||||
|
||||
ag = targ->t_auth_group;
|
||||
targ = port->p_target;
|
||||
ag = port->p_auth_group;
|
||||
if (ag == NULL)
|
||||
ag = targ->t_auth_group;
|
||||
pg = conn->conn_portal->p_portal_group;
|
||||
|
||||
assert(pg->pg_discovery_auth_group != PG_FILTER_UNKNOWN);
|
||||
@ -265,8 +274,8 @@ discovery(struct connection *conn)
|
||||
{
|
||||
struct pdu *request, *response;
|
||||
struct keys *request_keys, *response_keys;
|
||||
const struct port *port;
|
||||
const struct portal_group *pg;
|
||||
const struct target *targ;
|
||||
const char *send_targets;
|
||||
|
||||
pg = conn->conn_portal->p_portal_group;
|
||||
@ -284,29 +293,23 @@ discovery(struct connection *conn)
|
||||
response_keys = keys_new();
|
||||
|
||||
if (strcmp(send_targets, "All") == 0) {
|
||||
TAILQ_FOREACH(targ, &pg->pg_conf->conf_targets, t_next) {
|
||||
if (targ->t_portal_group != pg) {
|
||||
log_debugx("not returning target \"%s\"; "
|
||||
"belongs to a different portal group",
|
||||
targ->t_name);
|
||||
continue;
|
||||
}
|
||||
if (discovery_target_filtered_out(conn, targ)) {
|
||||
TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
|
||||
if (discovery_target_filtered_out(conn, port)) {
|
||||
/* Ignore this target. */
|
||||
continue;
|
||||
}
|
||||
discovery_add_target(response_keys, targ);
|
||||
discovery_add_target(response_keys, port->p_target);
|
||||
}
|
||||
} else {
|
||||
targ = target_find(pg->pg_conf, send_targets);
|
||||
if (targ == NULL) {
|
||||
port = port_find_in_pg(pg, send_targets);
|
||||
if (port == NULL) {
|
||||
log_debugx("initiator requested information on unknown "
|
||||
"target \"%s\"; returning nothing", send_targets);
|
||||
} else {
|
||||
if (discovery_target_filtered_out(conn, targ)) {
|
||||
if (discovery_target_filtered_out(conn, port)) {
|
||||
/* Ignore this target. */
|
||||
} else {
|
||||
discovery_add_target(response_keys, targ);
|
||||
discovery_add_target(response_keys, port->p_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,9 +121,10 @@ struct cctl_lun {
|
||||
|
||||
struct cctl_port {
|
||||
uint32_t port_id;
|
||||
int cfiscsi_status;
|
||||
int cfiscsi_state;
|
||||
char *cfiscsi_target;
|
||||
uint16_t cfiscsi_portal_group_tag;
|
||||
char *ctld_portal_group_name;
|
||||
STAILQ_HEAD(,cctl_lun_nv) attr_list;
|
||||
STAILQ_ENTRY(cctl_port) links;
|
||||
};
|
||||
@ -332,10 +333,13 @@ cctl_end_pelement(void *user_data, const char *name)
|
||||
if (strcmp(name, "cfiscsi_target") == 0) {
|
||||
cur_port->cfiscsi_target = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "cfiscsi_status") == 0) {
|
||||
cur_port->cfiscsi_status = strtoul(str, NULL, 0);
|
||||
} else if (strcmp(name, "cfiscsi_state") == 0) {
|
||||
cur_port->cfiscsi_state = strtoul(str, NULL, 0);
|
||||
} else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) {
|
||||
cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0);
|
||||
} else if (strcmp(name, "ctld_portal_group_name") == 0) {
|
||||
cur_port->ctld_portal_group_name = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "targ_port") == 0) {
|
||||
devlist->cur_port = NULL;
|
||||
} else if (strcmp(name, "ctlportlist") == 0) {
|
||||
@ -373,6 +377,8 @@ conf_new_from_kernel(void)
|
||||
{
|
||||
struct conf *conf = NULL;
|
||||
struct target *targ;
|
||||
struct portal_group *pg;
|
||||
struct port *cp;
|
||||
struct lun *cl;
|
||||
struct lun_option *lo;
|
||||
struct ctl_lun_list list;
|
||||
@ -496,9 +502,9 @@ conf_new_from_kernel(void)
|
||||
"ignoring", (uintmax_t)port->port_id);
|
||||
continue;
|
||||
}
|
||||
if (port->cfiscsi_status != 1) {
|
||||
if (port->cfiscsi_state != 1) {
|
||||
log_debugx("CTL port %ju is not active (%d); ignoring",
|
||||
(uintmax_t)port->port_id, port->cfiscsi_status);
|
||||
(uintmax_t)port->port_id, port->cfiscsi_state);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -514,6 +520,28 @@ conf_new_from_kernel(void)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (port->ctld_portal_group_name == NULL)
|
||||
continue;
|
||||
pg = portal_group_find(conf, port->ctld_portal_group_name);
|
||||
if (pg == NULL) {
|
||||
#if 0
|
||||
log_debugx("found new kernel portal group %s for CTL port %ld",
|
||||
port->ctld_portal_group_name, port->port_id);
|
||||
#endif
|
||||
pg = portal_group_new(conf, port->ctld_portal_group_name);
|
||||
if (pg == NULL) {
|
||||
log_warnx("portal_group_new failed");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pg->pg_tag = port->cfiscsi_portal_group_tag;
|
||||
cp = port_new(conf, targ, pg);
|
||||
if (cp == NULL) {
|
||||
log_warnx("port_new failed");
|
||||
continue;
|
||||
}
|
||||
cp->p_ctl_port = port->port_id;
|
||||
}
|
||||
|
||||
STAILQ_FOREACH(lun, &devlist.lun_list, links) {
|
||||
@ -771,6 +799,10 @@ kernel_handoff(struct connection *conn)
|
||||
sizeof(req.data.handoff.initiator_isid));
|
||||
strlcpy(req.data.handoff.target_name,
|
||||
conn->conn_target->t_name, sizeof(req.data.handoff.target_name));
|
||||
if (conn->conn_target->t_offload != NULL) {
|
||||
strlcpy(req.data.handoff.offload,
|
||||
conn->conn_target->t_offload, sizeof(req.data.handoff.offload));
|
||||
}
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
if (proxy_mode)
|
||||
req.data.handoff.connection_id = conn->conn_socket;
|
||||
@ -803,33 +835,68 @@ kernel_handoff(struct connection *conn)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
kernel_limits(const char *offload, size_t *max_data_segment_length)
|
||||
{
|
||||
struct ctl_iscsi req;
|
||||
|
||||
bzero(&req, sizeof(req));
|
||||
|
||||
req.type = CTL_ISCSI_LIMITS;
|
||||
if (offload != NULL) {
|
||||
strlcpy(req.data.limits.offload, offload,
|
||||
sizeof(req.data.limits.offload));
|
||||
}
|
||||
|
||||
if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
|
||||
log_err(1, "error issuing CTL_ISCSI ioctl; "
|
||||
"dropping connection");
|
||||
}
|
||||
|
||||
if (req.status != CTL_ISCSI_OK) {
|
||||
log_errx(1, "error returned from CTL iSCSI limits request: "
|
||||
"%s; dropping connection", req.error_str);
|
||||
}
|
||||
|
||||
*max_data_segment_length = req.data.limits.data_segment_limit;
|
||||
if (offload != NULL) {
|
||||
log_debugx("MaxRecvDataSegment kernel limit for offload "
|
||||
"\"%s\" is %zd", offload, *max_data_segment_length);
|
||||
} else {
|
||||
log_debugx("MaxRecvDataSegment kernel limit is %zd",
|
||||
*max_data_segment_length);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
kernel_port_add(struct target *targ)
|
||||
kernel_port_add(struct port *port)
|
||||
{
|
||||
struct ctl_port_entry entry;
|
||||
struct ctl_req req;
|
||||
struct ctl_lun_map lm;
|
||||
struct target *targ = port->p_target;
|
||||
struct portal_group *pg = port->p_portal_group;
|
||||
char tagstr[16];
|
||||
int error, i;
|
||||
int error, i, n;
|
||||
|
||||
/* Create iSCSI port. */
|
||||
bzero(&req, sizeof(req));
|
||||
strlcpy(req.driver, "iscsi", sizeof(req.driver));
|
||||
req.reqtype = CTL_REQ_CREATE;
|
||||
req.num_args = 4;
|
||||
req.args = malloc(req.num_args * sizeof(*req.args));
|
||||
req.args[0].namelen = sizeof("port_id");
|
||||
req.args[0].name = __DECONST(char *, "port_id");
|
||||
req.args[0].vallen = sizeof(targ->t_ctl_port);
|
||||
req.args[0].value = &targ->t_ctl_port;
|
||||
req.args[0].flags = CTL_BEARG_WR;
|
||||
str_arg(&req.args[1], "cfiscsi_target", targ->t_name);
|
||||
snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
|
||||
str_arg(&req.args[2], "cfiscsi_portal_group_tag", tagstr);
|
||||
n = 0;
|
||||
req.args[n].namelen = sizeof("port_id");
|
||||
req.args[n].name = __DECONST(char *, "port_id");
|
||||
req.args[n].vallen = sizeof(port->p_ctl_port);
|
||||
req.args[n].value = &port->p_ctl_port;
|
||||
req.args[n++].flags = CTL_BEARG_WR;
|
||||
str_arg(&req.args[n++], "cfiscsi_target", targ->t_name);
|
||||
snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
|
||||
str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr);
|
||||
if (targ->t_alias)
|
||||
str_arg(&req.args[3], "cfiscsi_target_alias", targ->t_alias);
|
||||
else
|
||||
req.num_args--;
|
||||
str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias);
|
||||
str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name);
|
||||
req.num_args = n;
|
||||
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
|
||||
free(req.args);
|
||||
if (error != 0) {
|
||||
@ -848,7 +915,7 @@ kernel_port_add(struct target *targ)
|
||||
}
|
||||
|
||||
/* Explicitly enable mapping to block any access except allowed. */
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.port = port->p_ctl_port;
|
||||
lm.plun = UINT32_MAX;
|
||||
lm.lun = 0;
|
||||
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
|
||||
@ -859,7 +926,7 @@ kernel_port_add(struct target *targ)
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
if (targ->t_luns[i] == NULL)
|
||||
continue;
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.port = port->p_ctl_port;
|
||||
lm.plun = i;
|
||||
lm.lun = targ->t_luns[i]->l_ctl_lun;
|
||||
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
|
||||
@ -869,7 +936,7 @@ kernel_port_add(struct target *targ)
|
||||
|
||||
/* Enable port */
|
||||
bzero(&entry, sizeof(entry));
|
||||
entry.targ_port = targ->t_ctl_port;
|
||||
entry.targ_port = port->p_ctl_port;
|
||||
error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry);
|
||||
if (error != 0) {
|
||||
log_warn("CTL_ENABLE_PORT ioctl failed");
|
||||
@ -880,14 +947,15 @@ kernel_port_add(struct target *targ)
|
||||
}
|
||||
|
||||
int
|
||||
kernel_port_update(struct target *targ)
|
||||
kernel_port_update(struct port *port)
|
||||
{
|
||||
struct ctl_lun_map lm;
|
||||
struct target *targ = port->p_target;
|
||||
int error, i;
|
||||
|
||||
/* Map configured LUNs and unmap others */
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.port = port->p_ctl_port;
|
||||
lm.plun = i;
|
||||
if (targ->t_luns[i] == NULL)
|
||||
lm.lun = UINT32_MAX;
|
||||
@ -901,10 +969,12 @@ kernel_port_update(struct target *targ)
|
||||
}
|
||||
|
||||
int
|
||||
kernel_port_remove(struct target *targ)
|
||||
kernel_port_remove(struct port *port)
|
||||
{
|
||||
struct ctl_req req;
|
||||
char tagstr[16];
|
||||
struct target *targ = port->p_target;
|
||||
struct portal_group *pg = port->p_portal_group;
|
||||
int error;
|
||||
|
||||
bzero(&req, sizeof(req));
|
||||
@ -913,7 +983,7 @@ kernel_port_remove(struct target *targ)
|
||||
req.num_args = 2;
|
||||
req.args = malloc(req.num_args * sizeof(*req.args));
|
||||
str_arg(&req.args[0], "cfiscsi_target", targ->t_name);
|
||||
snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
|
||||
snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
|
||||
str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
|
||||
|
||||
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
|
||||
|
@ -453,7 +453,8 @@ static void
|
||||
login_negotiate_key(struct pdu *request, const char *name,
|
||||
const char *value, bool skipped_security, struct keys *response_keys)
|
||||
{
|
||||
int which, tmp;
|
||||
int which;
|
||||
size_t tmp;
|
||||
struct connection *conn;
|
||||
|
||||
conn = request->pdu_connection;
|
||||
@ -552,13 +553,13 @@ login_negotiate_key(struct pdu *request, const char *name,
|
||||
log_errx(1, "received invalid "
|
||||
"MaxRecvDataSegmentLength");
|
||||
}
|
||||
if (tmp > MAX_DATA_SEGMENT_LENGTH) {
|
||||
if (tmp > conn->conn_data_segment_limit) {
|
||||
log_debugx("capping MaxRecvDataSegmentLength "
|
||||
"from %d to %d", tmp, MAX_DATA_SEGMENT_LENGTH);
|
||||
tmp = MAX_DATA_SEGMENT_LENGTH;
|
||||
"from %zd to %zd", tmp, conn->conn_data_segment_limit);
|
||||
tmp = conn->conn_data_segment_limit;
|
||||
}
|
||||
conn->conn_max_data_segment_length = tmp;
|
||||
keys_add_int(response_keys, name, MAX_DATA_SEGMENT_LENGTH);
|
||||
keys_add_int(response_keys, name, tmp);
|
||||
} else if (strcmp(name, "MaxBurstLength") == 0) {
|
||||
tmp = strtoul(value, NULL, 10);
|
||||
if (tmp <= 0) {
|
||||
@ -566,7 +567,7 @@ login_negotiate_key(struct pdu *request, const char *name,
|
||||
log_errx(1, "received invalid MaxBurstLength");
|
||||
}
|
||||
if (tmp > MAX_BURST_LENGTH) {
|
||||
log_debugx("capping MaxBurstLength from %d to %d",
|
||||
log_debugx("capping MaxBurstLength from %zd to %d",
|
||||
tmp, MAX_BURST_LENGTH);
|
||||
tmp = MAX_BURST_LENGTH;
|
||||
}
|
||||
@ -579,10 +580,10 @@ login_negotiate_key(struct pdu *request, const char *name,
|
||||
log_errx(1, "received invalid "
|
||||
"FirstBurstLength");
|
||||
}
|
||||
if (tmp > MAX_DATA_SEGMENT_LENGTH) {
|
||||
log_debugx("capping FirstBurstLength from %d to %d",
|
||||
tmp, MAX_DATA_SEGMENT_LENGTH);
|
||||
tmp = MAX_DATA_SEGMENT_LENGTH;
|
||||
if (tmp > conn->conn_data_segment_limit) {
|
||||
log_debugx("capping FirstBurstLength from %zd to %zd",
|
||||
tmp, conn->conn_data_segment_limit);
|
||||
tmp = conn->conn_data_segment_limit;
|
||||
}
|
||||
/*
|
||||
* We don't pass the value to the kernel; it only enforces
|
||||
@ -680,6 +681,18 @@ login_negotiate(struct connection *conn, struct pdu *request)
|
||||
int i;
|
||||
bool redirected, skipped_security;
|
||||
|
||||
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
|
||||
/*
|
||||
* Query the kernel for MaxDataSegmentLength it can handle.
|
||||
* In case of offload, it depends on hardware capabilities.
|
||||
*/
|
||||
assert(conn->conn_target != NULL);
|
||||
kernel_limits(conn->conn_target->t_offload,
|
||||
&conn->conn_data_segment_limit);
|
||||
} else {
|
||||
conn->conn_data_segment_limit = MAX_DATA_SEGMENT_LENGTH;
|
||||
}
|
||||
|
||||
if (request == NULL) {
|
||||
log_debugx("beginning operational parameter negotiation; "
|
||||
"waiting for Login PDU");
|
||||
@ -827,19 +840,22 @@ login(struct connection *conn)
|
||||
log_errx(1, "received Login PDU without TargetName");
|
||||
}
|
||||
|
||||
conn->conn_target = target_find(pg->pg_conf, target_name);
|
||||
if (conn->conn_target == NULL) {
|
||||
conn->conn_port = port_find_in_pg(pg, target_name);
|
||||
if (conn->conn_port == NULL) {
|
||||
login_send_error(request, 0x02, 0x03);
|
||||
log_errx(1, "requested target \"%s\" not found",
|
||||
target_name);
|
||||
}
|
||||
conn->conn_target = conn->conn_port->p_target;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we know what kind of authentication we need.
|
||||
*/
|
||||
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
|
||||
ag = conn->conn_target->t_auth_group;
|
||||
ag = conn->conn_port->p_auth_group;
|
||||
if (ag == NULL)
|
||||
ag = conn->conn_target->t_auth_group;
|
||||
if (ag->ag_name != NULL) {
|
||||
log_debugx("initiator requests to connect "
|
||||
"to target \"%s\"; auth-group \"%s\"",
|
||||
|
@ -60,7 +60,7 @@ extern void yyrestart(FILE *);
|
||||
%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
|
||||
%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
|
||||
%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
|
||||
%token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
|
||||
%token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
|
||||
%token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
|
||||
%token TARGET TIMEOUT
|
||||
|
||||
@ -463,6 +463,8 @@ target_entry:
|
||||
|
|
||||
target_initiator_portal
|
||||
|
|
||||
target_offload
|
||||
|
|
||||
target_portal_group
|
||||
|
|
||||
target_redirect
|
||||
@ -652,21 +654,69 @@ target_initiator_portal: INITIATOR_PORTAL STR
|
||||
}
|
||||
;
|
||||
|
||||
target_portal_group: PORTAL_GROUP STR
|
||||
target_offload: OFFLOAD STR
|
||||
{
|
||||
if (target->t_portal_group != NULL) {
|
||||
log_warnx("portal-group for target \"%s\" "
|
||||
"specified more than once", target->t_name);
|
||||
int error;
|
||||
|
||||
error = target_set_offload(target, $2);
|
||||
free($2);
|
||||
if (error != 0)
|
||||
return (1);
|
||||
}
|
||||
;
|
||||
|
||||
target_portal_group: PORTAL_GROUP STR STR
|
||||
{
|
||||
struct portal_group *tpg;
|
||||
struct auth_group *tag;
|
||||
struct port *tp;
|
||||
|
||||
tpg = portal_group_find(conf, $2);
|
||||
if (tpg == NULL) {
|
||||
log_warnx("unknown portal-group \"%s\" for target "
|
||||
"\"%s\"", $2, target->t_name);
|
||||
free($2);
|
||||
free($3);
|
||||
return (1);
|
||||
}
|
||||
tag = auth_group_find(conf, $3);
|
||||
if (tag == NULL) {
|
||||
log_warnx("unknown auth-group \"%s\" for target "
|
||||
"\"%s\"", $3, target->t_name);
|
||||
free($2);
|
||||
free($3);
|
||||
return (1);
|
||||
}
|
||||
tp = port_new(conf, target, tpg);
|
||||
if (tp == NULL) {
|
||||
log_warnx("can't link portal-group \"%s\" to target "
|
||||
"\"%s\"", $2, target->t_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
target->t_portal_group = portal_group_find(conf, $2);
|
||||
if (target->t_portal_group == NULL) {
|
||||
tp->p_auth_group = tag;
|
||||
free($2);
|
||||
free($3);
|
||||
}
|
||||
| PORTAL_GROUP STR
|
||||
{
|
||||
struct portal_group *tpg;
|
||||
struct port *tp;
|
||||
|
||||
tpg = portal_group_find(conf, $2);
|
||||
if (tpg == NULL) {
|
||||
log_warnx("unknown portal-group \"%s\" for target "
|
||||
"\"%s\"", $2, target->t_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
tp = port_new(conf, target, tpg);
|
||||
if (tp == NULL) {
|
||||
log_warnx("can't link portal-group \"%s\" to target "
|
||||
"\"%s\"", $2, target->t_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
@ -65,6 +65,7 @@ listen { return LISTEN; }
|
||||
listen-iser { return LISTEN_ISER; }
|
||||
lun { return LUN; }
|
||||
maxproc { return MAXPROC; }
|
||||
offload { return OFFLOAD; }
|
||||
option { return OPTION; }
|
||||
path { return PATH; }
|
||||
pidfile { return PIDFILE; }
|
||||
|
9
usr.sbin/devctl/Makefile
Normal file
9
usr.sbin/devctl/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= devctl
|
||||
MAN= devctl.8
|
||||
MAN=
|
||||
|
||||
LIBADD= devctl
|
||||
|
||||
.include <bsd.prog.mk>
|
137
usr.sbin/devctl/devctl.8
Normal file
137
usr.sbin/devctl/devctl.8
Normal file
@ -0,0 +1,137 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 5, 2015
|
||||
.Dt DEVCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm devctl
|
||||
.Nd device control utility
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Cm attach
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm detach
|
||||
.Op Fl f
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm disable
|
||||
.Op Fl f
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm enable
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm suspend
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm resume
|
||||
.Ar device
|
||||
.Nm
|
||||
.Cm set driver
|
||||
.Op Fl f
|
||||
.Ar device driver
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility adjusts the state of individual devices in the kernel's
|
||||
internal device hierarchy.
|
||||
Each invocation of
|
||||
.Nm
|
||||
consists of a single command followed by command-specific arguments.
|
||||
Each command operates on a single device specified via the
|
||||
.Ar device
|
||||
argument.
|
||||
The
|
||||
.Ar device
|
||||
may be specified either as the name of an existing device or as a
|
||||
bus-specific address.
|
||||
More details on supported address formats can be found in
|
||||
.Xr devctl 3 .
|
||||
.Pp
|
||||
The following commands are supported:
|
||||
.Bl -tag -width indent
|
||||
.It Cm attach Ar device
|
||||
Force the kernel to re-probe the device.
|
||||
If a suitable driver is found,
|
||||
it is attached to the device.
|
||||
.It Xo Cm detach
|
||||
.Op Fl f
|
||||
.Ar device
|
||||
.Xc
|
||||
Detach the device from its current device driver.
|
||||
If the
|
||||
.Fl f
|
||||
flag is specified,
|
||||
the device driver will be detached even if the device is busy.
|
||||
.It Xo Cm disable
|
||||
.Op Fl f
|
||||
.Ar device
|
||||
.Xc
|
||||
Disable a device.
|
||||
If the device is currently attached to a device driver,
|
||||
the device driver will be detached from the device,
|
||||
but the device will retain its current name.
|
||||
If the
|
||||
.Fl f
|
||||
flag is specified,
|
||||
the device driver will be detached even if the device is busy.
|
||||
.It Cm enable Ar device
|
||||
Enable a device.
|
||||
The device will probe and attach if a suitable device driver is found.
|
||||
Note that this can re-enable a device disabled at boot time via a
|
||||
loader tunable.
|
||||
.It Cm suspend Ar device
|
||||
Suspend a device.
|
||||
This may include placing the device in a reduced power state.
|
||||
.It Cm resume device
|
||||
Resume a suspended device to a fully working state.
|
||||
.It Xo Cm set driver
|
||||
.Op Fl f
|
||||
.Ar device driver
|
||||
.Xc
|
||||
Force the device to use a device driver named
|
||||
.Ar driver .
|
||||
If the device is already attached to a device driver and the
|
||||
.Fl f
|
||||
flag is specified,
|
||||
the device will be detached from its current device driver before it is
|
||||
attached to the new device driver.
|
||||
If the device is already attached to a device driver and the
|
||||
.Fl f
|
||||
flag is not specified,
|
||||
the device will not be changed.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr devctl 3 ,
|
||||
.Xr devinfo 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 11.0 .
|
282
usr.sbin/devctl/devctl.c
Normal file
282
usr.sbin/devctl/devctl.c
Normal file
@ -0,0 +1,282 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/linker_set.h>
|
||||
#include <devctl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct devctl_command {
|
||||
const char *name;
|
||||
int (*handler)(int ac, char **av);
|
||||
};
|
||||
|
||||
#define DEVCTL_DATASET(name) devctl_ ## name ## _table
|
||||
|
||||
#define DEVCTL_COMMAND(set, name, function) \
|
||||
static struct devctl_command function ## _devctl_command = \
|
||||
{ #name, function }; \
|
||||
DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
|
||||
|
||||
#define DEVCTL_TABLE(set, name) \
|
||||
SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
|
||||
\
|
||||
static int \
|
||||
devctl_ ## name ## _table_handler(int ac, char **av) \
|
||||
{ \
|
||||
return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
|
||||
SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
|
||||
} \
|
||||
DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
|
||||
|
||||
static int devctl_table_handler(struct devctl_command **start,
|
||||
struct devctl_command **end, int ac, char **av);
|
||||
|
||||
SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
|
||||
|
||||
DEVCTL_TABLE(top, set);
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
|
||||
"usage: devctl attach device",
|
||||
" devctl detach [-f] device",
|
||||
" devctl disable [-f] device",
|
||||
" devctl enable device",
|
||||
" devctl suspend device",
|
||||
" devctl resume device",
|
||||
" devctl set driver [-f] device driver");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
devctl_table_handler(struct devctl_command **start,
|
||||
struct devctl_command **end, int ac, char **av)
|
||||
{
|
||||
struct devctl_command **cmd;
|
||||
|
||||
if (ac < 2) {
|
||||
warnx("The %s command requires a sub-command.", av[0]);
|
||||
return (EINVAL);
|
||||
}
|
||||
for (cmd = start; cmd < end; cmd++) {
|
||||
if (strcmp((*cmd)->name, av[1]) == 0)
|
||||
return ((*cmd)->handler(ac - 1, av + 1));
|
||||
}
|
||||
|
||||
warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
static int
|
||||
help(int ac __unused, char **av __unused)
|
||||
{
|
||||
|
||||
usage();
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, help, help);
|
||||
|
||||
static int
|
||||
attach(int ac, char **av)
|
||||
{
|
||||
|
||||
if (ac != 2)
|
||||
usage();
|
||||
if (devctl_attach(av[1]) < 0)
|
||||
err(1, "Failed to attach %s", av[1]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, attach, attach);
|
||||
|
||||
static void
|
||||
detach_usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: devctl detach [-f] device\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
detach(int ac, char **av)
|
||||
{
|
||||
bool force;
|
||||
int ch;
|
||||
|
||||
force = false;
|
||||
while ((ch = getopt(ac, av, "f")) != -1)
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
force = true;
|
||||
break;
|
||||
default:
|
||||
detach_usage();
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if (ac != 1)
|
||||
detach_usage();
|
||||
if (devctl_detach(av[0], force) < 0)
|
||||
err(1, "Failed to detach %s", av[0]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, detach, detach);
|
||||
|
||||
static void
|
||||
disable_usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: devctl disable [-f] device\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
disable(int ac, char **av)
|
||||
{
|
||||
bool force;
|
||||
int ch;
|
||||
|
||||
force = false;
|
||||
while ((ch = getopt(ac, av, "f")) != -1)
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
force = true;
|
||||
break;
|
||||
default:
|
||||
disable_usage();
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if (ac != 1)
|
||||
disable_usage();
|
||||
if (devctl_disable(av[0], force) < 0)
|
||||
err(1, "Failed to disable %s", av[0]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, disable, disable);
|
||||
|
||||
static int
|
||||
enable(int ac, char **av)
|
||||
{
|
||||
|
||||
if (ac != 2)
|
||||
usage();
|
||||
if (devctl_enable(av[1]) < 0)
|
||||
err(1, "Failed to enable %s", av[1]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, enable, enable);
|
||||
|
||||
static int
|
||||
suspend(int ac, char **av)
|
||||
{
|
||||
|
||||
if (ac != 2)
|
||||
usage();
|
||||
if (devctl_suspend(av[1]) < 0)
|
||||
err(1, "Failed to suspend %s", av[1]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, suspend, suspend);
|
||||
|
||||
static int
|
||||
resume(int ac, char **av)
|
||||
{
|
||||
|
||||
if (ac != 2)
|
||||
usage();
|
||||
if (devctl_resume(av[1]) < 0)
|
||||
err(1, "Failed to resume %s", av[1]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(top, resume, resume);
|
||||
|
||||
static void
|
||||
set_driver_usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
set_driver(int ac, char **av)
|
||||
{
|
||||
bool force;
|
||||
int ch;
|
||||
|
||||
force = false;
|
||||
while ((ch = getopt(ac, av, "f")) != -1)
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
force = true;
|
||||
break;
|
||||
default:
|
||||
set_driver_usage();
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if (ac != 2)
|
||||
set_driver_usage();
|
||||
if (devctl_set_driver(av[0], av[1], force) < 0)
|
||||
err(1, "Failed to set %s driver to %s", av[0], av[1]);
|
||||
return (0);
|
||||
}
|
||||
DEVCTL_COMMAND(set, driver, set_driver);
|
||||
|
||||
int
|
||||
main(int ac, char *av[])
|
||||
{
|
||||
struct devctl_command **cmd;
|
||||
|
||||
if (ac == 1)
|
||||
usage();
|
||||
ac--;
|
||||
av++;
|
||||
|
||||
SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
|
||||
if (strcmp((*cmd)->name, av[0]) == 0) {
|
||||
if ((*cmd)->handler(ac, av) != 0)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
warnx("Unknown command %s.", av[0]);
|
||||
return (1);
|
||||
}
|
@ -146,6 +146,10 @@ print_device(struct devinfo_dev *dev, void *arg)
|
||||
printf(" pnpinfo %s", dev->dd_pnpinfo);
|
||||
if (vflag && *dev->dd_location)
|
||||
printf(" at %s", dev->dd_location);
|
||||
if (!(dev->dd_flags & DF_ENABLED))
|
||||
printf(" (disabled)");
|
||||
else if (dev->dd_flags & DF_SUSPENDED)
|
||||
printf(" (suspended)");
|
||||
printf("\n");
|
||||
if (rflag) {
|
||||
ia.indent = indent + 4;
|
||||
|
@ -2828,18 +2828,27 @@ Kernel updates have been installed. Please reboot and run
|
||||
grep -E '^[^|]+\|d\|' > INDEX-NEW
|
||||
install_from_index INDEX-NEW || return 1
|
||||
|
||||
# Install new runtime linker
|
||||
grep -vE '^/boot/' $1/INDEX-NEW |
|
||||
grep -vE '^[^|]+\|d\|' |
|
||||
grep -E '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' > INDEX-NEW
|
||||
install_from_index INDEX-NEW || return 1
|
||||
|
||||
# Install new shared libraries next
|
||||
grep -vE '^/boot/' $1/INDEX-NEW |
|
||||
grep -vE '^[^|]+\|d\|' |
|
||||
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
|
||||
grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
|
||||
install_from_index INDEX-NEW || return 1
|
||||
|
||||
# Deal with everything else
|
||||
grep -vE '^/boot/' $1/INDEX-OLD |
|
||||
grep -vE '^[^|]+\|d\|' |
|
||||
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
|
||||
grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD
|
||||
grep -vE '^/boot/' $1/INDEX-NEW |
|
||||
grep -vE '^[^|]+\|d\|' |
|
||||
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
|
||||
grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
|
||||
install_from_index INDEX-NEW || return 1
|
||||
install_delete INDEX-OLD INDEX-NEW || return 1
|
||||
|
@ -112,6 +112,12 @@ next_command(struct cfjail *j)
|
||||
if (!bool_param(j->intparams[IP_MOUNT_FDESCFS]))
|
||||
continue;
|
||||
j->comstring = &dummystring;
|
||||
break;
|
||||
case IP_MOUNT_PROCFS:
|
||||
if (!bool_param(j->intparams[IP_MOUNT_PROCFS]))
|
||||
continue;
|
||||
j->comstring = &dummystring;
|
||||
break;
|
||||
case IP__OP:
|
||||
case IP_STOP_TIMEOUT:
|
||||
j->comstring = &dummystring;
|
||||
@ -528,6 +534,32 @@ run_command(struct cfjail *j)
|
||||
}
|
||||
break;
|
||||
|
||||
case IP_MOUNT_PROCFS:
|
||||
argv = alloca(7 * sizeof(char *));
|
||||
path = string_param(j->intparams[KP_PATH]);
|
||||
if (path == NULL) {
|
||||
jail_warnx(j, "mount.procfs: no path");
|
||||
return -1;
|
||||
}
|
||||
devpath = alloca(strlen(path) + 6);
|
||||
sprintf(devpath, "%s/proc", path);
|
||||
if (check_path(j, "mount.procfs", devpath, 0,
|
||||
down ? "procfs" : NULL) < 0)
|
||||
return -1;
|
||||
if (down) {
|
||||
argv[0] = "/sbin/umount";
|
||||
argv[1] = devpath;
|
||||
argv[2] = NULL;
|
||||
} else {
|
||||
argv[0] = _PATH_MOUNT;
|
||||
argv[1] = "-t";
|
||||
argv[2] = "procfs";
|
||||
argv[3] = ".";
|
||||
argv[4] = devpath;
|
||||
argv[5] = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case IP_COMMAND:
|
||||
if (j->name != NULL)
|
||||
goto default_command;
|
||||
|
@ -84,6 +84,7 @@ static const struct ipspec intparams[] = {
|
||||
[IP_MOUNT] = {"mount", PF_INTERNAL | PF_REV},
|
||||
[IP_MOUNT_DEVFS] = {"mount.devfs", PF_INTERNAL | PF_BOOL},
|
||||
[IP_MOUNT_FDESCFS] = {"mount.fdescfs", PF_INTERNAL | PF_BOOL},
|
||||
[IP_MOUNT_PROCFS] = {"mount.procfs", PF_INTERNAL | PF_BOOL},
|
||||
[IP_MOUNT_FSTAB] = {"mount.fstab", PF_INTERNAL},
|
||||
[IP_STOP_TIMEOUT] = {"stop.timeout", PF_INTERNAL | PF_INT},
|
||||
[IP_VNET_INTERFACE] = {"vnet.interface", PF_INTERNAL},
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 28, 2015
|
||||
.Dd February 6, 2015
|
||||
.Dt JAIL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -753,6 +753,12 @@ Mount a
|
||||
filesystem on the chrooted
|
||||
.Pa /dev/fd
|
||||
directory.
|
||||
.It Va mount.procfs
|
||||
Mount a
|
||||
.Xr procfs 5
|
||||
filesystem on the chrooted
|
||||
.Pa /proc
|
||||
directory.
|
||||
.It Va allow.dying
|
||||
Allow making changes to a
|
||||
.Va dying
|
||||
@ -1207,6 +1213,7 @@ environment of the first jail.
|
||||
.Xr jls 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr named 8 ,
|
||||
.Xr procfs 5 ,
|
||||
.Xr reboot 8 ,
|
||||
.Xr rpcbind 8 ,
|
||||
.Xr sendmail 8 ,
|
||||
|
@ -93,6 +93,7 @@ static const enum intparam startcommands[] = {
|
||||
IP__MOUNT_FROM_FSTAB,
|
||||
IP_MOUNT_DEVFS,
|
||||
IP_MOUNT_FDESCFS,
|
||||
IP_MOUNT_PROCFS,
|
||||
IP_EXEC_PRESTART,
|
||||
IP__OP,
|
||||
IP_VNET_INTERFACE,
|
||||
@ -109,6 +110,7 @@ static const enum intparam stopcommands[] = {
|
||||
IP_STOP_TIMEOUT,
|
||||
IP__OP,
|
||||
IP_EXEC_POSTSTOP,
|
||||
IP_MOUNT_PROCFS,
|
||||
IP_MOUNT_FDESCFS,
|
||||
IP_MOUNT_DEVFS,
|
||||
IP__MOUNT_FROM_FSTAB,
|
||||
|
@ -96,6 +96,7 @@ enum intparam {
|
||||
IP_MOUNT, /* Mount points in fstab(5) form */
|
||||
IP_MOUNT_DEVFS, /* Mount /dev under prison root */
|
||||
IP_MOUNT_FDESCFS, /* Mount /dev/fd under prison root */
|
||||
IP_MOUNT_PROCFS, /* Mount /proc under prison root */
|
||||
IP_MOUNT_FSTAB, /* A standard fstab(5) file */
|
||||
IP_STOP_TIMEOUT, /* Time to wait after sending SIGTERM */
|
||||
IP_VNET_INTERFACE, /* Assign interface(s) to vnet jail */
|
||||
|
Loading…
Reference in New Issue
Block a user