Merge ^/head r326936 through r327149.
This commit is contained in:
commit
54b4b13c4a
@ -343,7 +343,7 @@ Write each command
|
||||
variable subjected to parameter expansion and arithmetic expansion)
|
||||
to standard error before it is executed.
|
||||
Useful for debugging.
|
||||
.It nolog
|
||||
.It Li nolog
|
||||
Another do-nothing option for
|
||||
.Tn POSIX
|
||||
compliance.
|
||||
@ -2739,7 +2739,7 @@ were a known job that exited with exit status 127.
|
||||
If no operands are given, wait for all jobs to complete
|
||||
and return an exit status of zero.
|
||||
.El
|
||||
.Ss Commandline Editing
|
||||
.Ss Command Line Editing
|
||||
When
|
||||
.Nm
|
||||
is being used interactively from a terminal, the current command
|
||||
|
@ -63,7 +63,7 @@ ldconfig_start()
|
||||
esac
|
||||
|
||||
case `sysctl -n hw.machine_arch` in
|
||||
armv6)
|
||||
armv[67])
|
||||
for i in ${ldconfig_localsoft_dirs}; do
|
||||
if [ -d "${i}" ]; then
|
||||
_files=`find ${i} -type f`
|
||||
|
@ -274,6 +274,7 @@ int cgetstr(char *, const char *, char **);
|
||||
int cgetustr(char *, const char *, char **);
|
||||
|
||||
int daemon(int, int);
|
||||
int daemonfd(int, int);
|
||||
char *devname(__dev_t, __mode_t);
|
||||
char *devname_r(__dev_t, __mode_t, char *, int);
|
||||
char *fdevname(int);
|
||||
|
@ -394,6 +394,7 @@ FBSD_1.4 {
|
||||
FBSD_1.5 {
|
||||
alphasort;
|
||||
basename;
|
||||
daemonfd;
|
||||
devname;
|
||||
devname_r;
|
||||
dirname;
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)daemon.3 8.1 (Berkeley) 6/9/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 9, 1993
|
||||
.Dd December 23, 2017
|
||||
.Dt DAEMON 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -40,6 +40,8 @@
|
||||
.In stdlib.h
|
||||
.Ft int
|
||||
.Fn daemon "int nochdir" "int noclose"
|
||||
.Ft int
|
||||
.Fn daemonfd "int chdirfd" "int nullfd"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn daemon
|
||||
@ -59,15 +61,39 @@ is non-zero,
|
||||
.Fn daemon
|
||||
will redirect standard input, standard output, and standard error to
|
||||
.Pa /dev/null .
|
||||
.Pp
|
||||
The
|
||||
.Fn daemonfd
|
||||
function is equivalent to the
|
||||
.Fn daemon
|
||||
function except that arguments are the descriptors for the current working
|
||||
directory and to the descriptor to
|
||||
.Pa /dev/null .
|
||||
.Pp
|
||||
If
|
||||
.Fa chdirfd
|
||||
is equal to
|
||||
.Pq -1
|
||||
the current working directory is not changed.
|
||||
.Pp
|
||||
If
|
||||
.Fa nullfd
|
||||
is equals to
|
||||
.Pq -1
|
||||
the redirection of standard input, standard output, and standard error is not
|
||||
closed.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std daemon
|
||||
.Rv -std daemon daemonfd
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn daemon
|
||||
and
|
||||
.Fn daemonfd
|
||||
function may fail and set
|
||||
.Va errno
|
||||
for any of the errors specified for the library functions
|
||||
.Xr fork 2
|
||||
.Xr open 2,
|
||||
and
|
||||
.Xr setsid 2 .
|
||||
.Sh SEE ALSO
|
||||
@ -79,6 +105,10 @@ The
|
||||
.Fn daemon
|
||||
function first appeared in
|
||||
.Bx 4.4 .
|
||||
The
|
||||
.Fn daemonfd
|
||||
function first appeared in
|
||||
.Fx 12.0 .
|
||||
.Sh CAVEATS
|
||||
Unless the
|
||||
.Fa noclose
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1990, 1993 The Regents of the University of California.
|
||||
* Copyright (c) 2017 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -46,10 +47,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include "libc_private.h"
|
||||
|
||||
int
|
||||
daemon(int nochdir, int noclose)
|
||||
daemonfd(int chdirfd, int nullfd)
|
||||
{
|
||||
struct sigaction osa, sa;
|
||||
int fd;
|
||||
pid_t newgrp;
|
||||
int oerrno;
|
||||
int osa_ok;
|
||||
@ -83,15 +83,39 @@ daemon(int nochdir, int noclose)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!nochdir)
|
||||
(void)chdir("/");
|
||||
if (chdirfd != -1)
|
||||
(void)fchdir(chdirfd);
|
||||
|
||||
if (!noclose && (fd = _open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
(void)_dup2(fd, STDIN_FILENO);
|
||||
(void)_dup2(fd, STDOUT_FILENO);
|
||||
(void)_dup2(fd, STDERR_FILENO);
|
||||
if (fd > 2)
|
||||
(void)_close(fd);
|
||||
if (nullfd != -1) {
|
||||
(void)_dup2(nullfd, STDIN_FILENO);
|
||||
(void)_dup2(nullfd, STDOUT_FILENO);
|
||||
(void)_dup2(nullfd, STDERR_FILENO);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
daemon(int nochdir, int noclose)
|
||||
{
|
||||
int chdirfd, nullfd, ret;
|
||||
|
||||
if (!noclose)
|
||||
nullfd = _open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
else
|
||||
nullfd = -1;
|
||||
|
||||
if (!nochdir)
|
||||
chdirfd = _open("/", O_EXEC);
|
||||
else
|
||||
chdirfd = -1;
|
||||
|
||||
ret = daemonfd(chdirfd, nullfd);
|
||||
|
||||
if (chdirfd != -1)
|
||||
_close(chdirfd);
|
||||
|
||||
if (nullfd > 2)
|
||||
_close(nullfd);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
@ -1277,7 +1277,8 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
||||
* does not accept. So we need to separate the case for
|
||||
* AF_INET.
|
||||
*/
|
||||
if (inet_aton(hostname, (struct in_addr *)pton) != 1)
|
||||
if (inet_aton(hostname, (struct in_addr *)pton) != 1 ||
|
||||
hostname[strspn(hostname, "0123456789.xabcdefXABCDEF")] != '\0')
|
||||
return 0;
|
||||
p = pton;
|
||||
break;
|
||||
|
@ -72,7 +72,7 @@ Fail if the file does not exist.
|
||||
.It Dq Li w
|
||||
Open for writing.
|
||||
The stream is positioned at the beginning of the file.
|
||||
Create the file if it does not exist.
|
||||
Truncate the file to zero length if it exists or create the file if it does not exist.
|
||||
.It Dq Li a
|
||||
Open for writing.
|
||||
The stream is positioned at the end of the file.
|
||||
|
@ -204,7 +204,7 @@ devinfo_init_devices(int generation)
|
||||
* Stop after a fairly insane number to avoid death in the case
|
||||
* of kernel corruption.
|
||||
*/
|
||||
for (dev_idx = 0; dev_idx < 1000; dev_idx++) {
|
||||
for (dev_idx = 0; dev_idx < 10000; dev_idx++) {
|
||||
|
||||
/*
|
||||
* Get the device information.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Codel/FQ_Codel and PIE/FQ_PIE Code:
|
||||
* Copyright (C) 2016 Centre for Advanced Internet Architectures,
|
||||
* Swinburne University of Technology, Melbourne, Australia.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
@ -2256,12 +2256,13 @@ do_range_cmd(int cmd, ipfw_range_tlv *rt)
|
||||
void
|
||||
ipfw_sets_handler(char *av[])
|
||||
{
|
||||
uint32_t masks[2];
|
||||
int i;
|
||||
uint8_t cmd, rulenum;
|
||||
ipfw_range_tlv rt;
|
||||
char *msg;
|
||||
size_t size;
|
||||
uint32_t masks[2];
|
||||
int i;
|
||||
uint16_t rulenum;
|
||||
uint8_t cmd;
|
||||
|
||||
av++;
|
||||
memset(&rt, 0, sizeof(rt));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003,2010 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)reboot.8 8.1 (Berkeley) 6/9/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 23, 2017
|
||||
.Dd December 20, 2017
|
||||
.Dt REBOOT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -142,6 +142,12 @@ After changing vfs.root.mountfrom with
|
||||
.Xr kenv 1 ,
|
||||
.Nm Fl r
|
||||
can be used to change the root filesystem while preserving kernel state.
|
||||
This requires the
|
||||
.Xr tmpfs 5
|
||||
kernel module to be loaded because
|
||||
.Xr init 8
|
||||
needs a place to store itself after the old root is unmounted, but
|
||||
before the new root is in place.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
|
@ -382,6 +382,7 @@ MAN= aac.4 \
|
||||
${_ntb_hw_intel.4} \
|
||||
${_ntb_hw_plx.4} \
|
||||
${_ntb_transport.4} \
|
||||
${_nda.4} \
|
||||
${_if_ntb.4} \
|
||||
null.4 \
|
||||
numa.4 \
|
||||
@ -808,6 +809,7 @@ _if_wpi.4= if_wpi.4
|
||||
_ipmi.4= ipmi.4
|
||||
_io.4= io.4
|
||||
_linux.4= linux.4
|
||||
_nda.4= nda.4
|
||||
_ndis.4= ndis.4
|
||||
_nfe.4= nfe.4
|
||||
_nfsmb.4= nfsmb.4
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 19, 2015
|
||||
.Dd December 20, 2017
|
||||
.Dt ADA 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -157,6 +157,7 @@ ATA device nodes
|
||||
.Xr cam 4 ,
|
||||
.Xr da 4 ,
|
||||
.Xr mvs 4 ,
|
||||
.Xr nda 4 ,
|
||||
.Xr siis 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 11, 2015
|
||||
.Dd December 20, 2017
|
||||
.Dt DA 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -214,6 +214,7 @@ None.
|
||||
.Xr ada 4 ,
|
||||
.Xr cam 4 ,
|
||||
.Xr geom 4 ,
|
||||
.Xr nda 4 ,
|
||||
.Xr gpart 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -319,6 +319,6 @@ The
|
||||
driver was originally written by
|
||||
.An Intel Corporation Aq Mt freebsd@intel.com .
|
||||
It was merged with igb driver and converted to the iflib framework by
|
||||
.An Matthew Macy Aq Mt mmacy@nextbsd.org
|
||||
.An Matthew Macy Aq Mt mmacy@mattmacy.io
|
||||
and
|
||||
.An Sean Bruno Aq Mt sbruno@FreeBSD.org .
|
||||
|
@ -7,7 +7,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 5, 2017
|
||||
.Dd December 7, 2017
|
||||
.Dt MD 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -79,7 +79,8 @@ To create a kernel with a ramdisk or MD file system, your kernel config
|
||||
needs the following options:
|
||||
.Bd -literal -offset indent
|
||||
options MD_ROOT # MD is a potential root device
|
||||
options MD_ROOT_SIZE=8192 # 8MB ram disk
|
||||
options MD_ROOT_READONLY # disallow mounting root writeable
|
||||
options MD_ROOT_SIZE=8192 # 8MB ram disk
|
||||
makeoptions MFS_IMAGE=/h/foo/ARM-MD
|
||||
options ROOTDEVNAME=\\"ufs:md0\\"
|
||||
.Ed
|
||||
|
87
share/man/man4/nda.4
Normal file
87
share/man/man4/nda.4
Normal file
@ -0,0 +1,87 @@
|
||||
.\" Copyright (c) 2017 Netflix, Inc
|
||||
.\" 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 20, 2017
|
||||
.Dt NDA 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm nda
|
||||
.Nd NVMe Direct Access device driver
|
||||
.Sh SYNOPSIS
|
||||
.Cd device nvme
|
||||
.Cd device scbus
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for direct access devices, implementing the
|
||||
.Tn NVMe
|
||||
command protocol, that are attached to the system through a host adapter
|
||||
supported by the CAM subsystem.
|
||||
.Sh SYSCTL VARIABLES
|
||||
The following variables are available as both
|
||||
.Xr sysctl 8
|
||||
variables and
|
||||
.Xr loader 8
|
||||
tunables:
|
||||
.Bl -tag -width 12
|
||||
.It Va kern.cam.nda.sort_io_queue
|
||||
.Pp
|
||||
This variable determines whether the software queued entries are
|
||||
sorted in LBA order or not.
|
||||
Sorting is almost always a waste of time.
|
||||
The default is to not sort.
|
||||
.El
|
||||
.Pp
|
||||
The following report per-device settings, and are read-only unless
|
||||
otherwise indicated. Replace
|
||||
.Va N
|
||||
with the device unit number.
|
||||
.Bl -tag -width 12
|
||||
.It Va kern.cam.nda.N.rotating
|
||||
.Pp
|
||||
This variable reports whether the storage volume is spinning or
|
||||
flash.
|
||||
It's value is hard coded to 0 indicating flash.
|
||||
.It Va kern.cam.nda.N.unmapped_io
|
||||
This variable reports whether the
|
||||
.Nm
|
||||
driver accepts unmapped I/O for this unit.
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /dev/nda*" -compact
|
||||
.It Pa /dev/nda*
|
||||
NVMe storage device nodes
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr nvme 4 ,
|
||||
.Xr nvd 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 12.0 .
|
||||
.Sh AUTHORS
|
||||
.An Warner Losh Aq Mt imp@FreeBSD.org
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 8, 2016
|
||||
.Dd December 20, 2017
|
||||
.Dt PCI 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -492,6 +492,59 @@ The value of the tunable is the raw IRQ value to use for the INTx interrupt
|
||||
pin identified by the tunable name.
|
||||
Mapping of IRQ values to platform interrupt sources is machine dependent.
|
||||
.El
|
||||
.Sh DEVICE WIRING
|
||||
You can wire the device unit at a given location with device.hints.
|
||||
Entries of the form
|
||||
.Va hints.<name>.<unit>.at="pci<B>:<S>:<F>"
|
||||
or
|
||||
.Va hints.<name>.<unit>.at="pci<D>:<B>:<S>:<F>"
|
||||
will force the driver
|
||||
.Va name
|
||||
to probe and attach at unit
|
||||
.Va unit
|
||||
for any PCI device found to match the specification, where:
|
||||
.Bl -tag -width -indent
|
||||
.It <D>
|
||||
The domain
|
||||
.Pq or segment
|
||||
of the PCI device in decimal.
|
||||
Defaults to 0 if unspecified
|
||||
.It <B>
|
||||
The bus address of the PCI device in decimal.
|
||||
.It <S>
|
||||
The slot of the PCI device in decimal.
|
||||
.It <F>
|
||||
The function of the PCI device in decimal.
|
||||
.El
|
||||
.Pp
|
||||
The code to do the matching requires an exact string match.
|
||||
Do not specify the angle brackets
|
||||
.Pq < >
|
||||
in the hints file.
|
||||
Wiring multiple devices to the same
|
||||
.Va name
|
||||
and
|
||||
.Va unit
|
||||
produces undefined results.
|
||||
.Ss Examples
|
||||
Given the following lines in
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.nvme.3.at="pci6:0:0"
|
||||
.Cd hint.igb.8.at="pci14:0:0"
|
||||
If there is a device that supports
|
||||
.Xr igb 4
|
||||
at PCI bus 14 slot 0 function 0,
|
||||
then it will be assigned igb8 for probe and attach.
|
||||
Likewise, if there is an
|
||||
.Xr nvme 4
|
||||
card at PCI bus 6 slot 0 function 0,
|
||||
then it will be assigned nvme3 for probe and attach.
|
||||
If another type of card is in either of these locations, the name and
|
||||
unit of that card will be the default names and will be unaffected by
|
||||
these hints.
|
||||
If other igb or nvme cards are located elsewhere, they will be
|
||||
assigned their unit numbers sequentially, skipping the unit numbers
|
||||
that have 'at' hints.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/pci -compact
|
||||
.It Pa /dev/pci
|
||||
|
@ -24,12 +24,12 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.Dd January 15, 2017
|
||||
.Dd December 20, 2017
|
||||
.Dt CAM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm CAM
|
||||
.Nd Common Access Method SCSI/ATA subsystem
|
||||
.Nd Common Access Method Storage subsystem
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device scbus"
|
||||
.Cd "device ada"
|
||||
@ -54,13 +54,17 @@ The
|
||||
.Nm
|
||||
subsystem provides a uniform and modular system for the implementation
|
||||
of drivers to control various
|
||||
.Tn SCSI
|
||||
.Tn SCSI ,
|
||||
.Tn ATA ,
|
||||
.Tn NMVe ,
|
||||
and
|
||||
.Tn ATA
|
||||
.Tn MMC / SD
|
||||
devices, and to utilize different
|
||||
.Tn SCSI
|
||||
.Tn SCSI ,
|
||||
.Tn ATA ,
|
||||
.Tn NVMe ,
|
||||
and
|
||||
.Tn ATA
|
||||
.Tn MMC / SD
|
||||
host adapters through host adapter drivers.
|
||||
When the system probes buses, it attaches any devices it finds to the
|
||||
appropriate drivers.
|
||||
@ -213,6 +217,31 @@ and use the first respective counted instances.
|
||||
These examples can be combined together to allow a peripheral device to be
|
||||
wired to any particular controller, bus, target, and/or unit instance.
|
||||
.Pp
|
||||
This also works with
|
||||
.Xr nvme 4
|
||||
drives as well.
|
||||
.Bd -literal -offset indent
|
||||
hint.nvme.4.at="pci7:0:0"
|
||||
hint.scbus.10.at="nvme4"
|
||||
hint.nda.10.at="scbus10"
|
||||
hint.nda.10.target="1"
|
||||
hint.nda.10.unit="12"
|
||||
hint.nda.11.at="scbus10"
|
||||
hint.nda.11.target="1"
|
||||
hint.nda.11.unit="2"
|
||||
.Ed
|
||||
.Pp
|
||||
This assigns the NVMe card living at PCI bus 7 to scbus 10 (in PCIe,
|
||||
slot and function are rarely used and usually 0).
|
||||
The target for
|
||||
.Xr nda 4
|
||||
devices is always 1.
|
||||
The unit is the namespace identifier from the drive.
|
||||
The namespace id 1 is exported as
|
||||
.Tn nda10
|
||||
and namespace id 2 is exported as
|
||||
.Tn nda11 .
|
||||
.Pp
|
||||
When you have a mixture of wired down and counted devices then the
|
||||
counting begins with the first non-wired down unit for a particular
|
||||
type.
|
||||
@ -225,9 +254,11 @@ The system allows common device drivers to work through many different
|
||||
types of adapters.
|
||||
The adapters take requests from the upper layers and do
|
||||
all IO between the
|
||||
.Tn SCSI
|
||||
.Tn SCSI ,
|
||||
.Tn ATA ,
|
||||
.Tn NVMe ,
|
||||
or
|
||||
.Tn ATA
|
||||
.Tn MMC / SD
|
||||
bus and the system.
|
||||
The maximum size of a transfer is governed by the
|
||||
adapter.
|
||||
@ -322,6 +353,8 @@ for details.
|
||||
.Xr cd 4 ,
|
||||
.Xr ch 4 ,
|
||||
.Xr da 4 ,
|
||||
.Xr nda 4 ,
|
||||
.Xr nvme 4 ,
|
||||
.Xr pass 4 ,
|
||||
.Xr pt 4 ,
|
||||
.Xr sa 4 ,
|
||||
@ -351,3 +384,8 @@ The
|
||||
.Tn ATA
|
||||
support was added by
|
||||
.An Alexander Motin Aq Mt mav@FreeBSD.org .
|
||||
The
|
||||
.Nm
|
||||
.Tn NVMe
|
||||
support was added by
|
||||
.An Warner Losh Aq Mt imp@FreeBSD.org .
|
||||
|
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 23, 2017
|
||||
.Dd December 22, 2017
|
||||
.Dt ATOMIC 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -36,7 +36,8 @@
|
||||
.Nm atomic_readandclear ,
|
||||
.Nm atomic_set ,
|
||||
.Nm atomic_subtract ,
|
||||
.Nm atomic_store
|
||||
.Nm atomic_store ,
|
||||
.Nm atomic_thread_fence
|
||||
.Nd atomic operations
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
@ -60,7 +61,7 @@
|
||||
.Ft <type>
|
||||
.Fn atomic_fetchadd_<type> "volatile <type> *p" "<type> v"
|
||||
.Ft <type>
|
||||
.Fn atomic_load_acq_<type> "volatile <type> *p"
|
||||
.Fn atomic_load_[acq_]<type> "volatile <type> *p"
|
||||
.Ft <type>
|
||||
.Fn atomic_readandclear_<type> "volatile <type> *p"
|
||||
.Ft void
|
||||
@ -68,19 +69,33 @@
|
||||
.Ft void
|
||||
.Fn atomic_subtract_[acq_|rel_]<type> "volatile <type> *p" "<type> v"
|
||||
.Ft void
|
||||
.Fn atomic_store_rel_<type> "volatile <type> *p" "<type> v"
|
||||
.Fn atomic_store_[rel_]<type> "volatile <type> *p" "<type> v"
|
||||
.Ft <type>
|
||||
.Fn atomic_swap_<type> "volatile <type> *p" "<type> v"
|
||||
.Ft int
|
||||
.Fn atomic_testandclear_<type> "volatile <type> *p" "u_int v"
|
||||
.Ft int
|
||||
.Fn atomic_testandset_<type> "volatile <type> *p" "u_int v"
|
||||
.Ft void
|
||||
.Fn atomic_thread_fence_[acq|acq_rel|rel|seq_cst] "void"
|
||||
.Sh DESCRIPTION
|
||||
All of these operations are performed atomically across multiple
|
||||
threads and in the presence of interrupts, meaning that they are
|
||||
performed in an indivisible manner from the perspective of concurrently
|
||||
Atomic operations are commonly used to implement reference counts and as
|
||||
building blocks for synchronization primitives, such as mutexes.
|
||||
.Pp
|
||||
All of these operations are performed
|
||||
.Em atomically
|
||||
across multiple threads and in the presence of interrupts, meaning that they
|
||||
are performed in an indivisible manner from the perspective of concurrently
|
||||
running threads and interrupt handlers.
|
||||
.Pp
|
||||
On all architectures supported by
|
||||
.Fx ,
|
||||
ordinary loads and stores of integers in cache-coherent memory are
|
||||
inherently atomic if the integer is naturally aligned and its size does not
|
||||
exceed the processor's word size.
|
||||
However, such loads and stores may be elided from the program by
|
||||
the compiler, whereas atomic operations are always performed.
|
||||
.Pp
|
||||
When atomic operations are performed on cache-coherent memory, all
|
||||
operations on the same location are totally ordered.
|
||||
.Pp
|
||||
@ -93,29 +108,16 @@ interrupt handler will observe a
|
||||
.Em torn write ,
|
||||
or partial modification of the location.
|
||||
.Pp
|
||||
On all architectures supported by
|
||||
.Fx ,
|
||||
ordinary loads and stores of naturally aligned integer types
|
||||
are atomic, as executed by the processor.
|
||||
.Pp
|
||||
Atomic operations can be used to implement reference counts or as
|
||||
building blocks for synchronization primitives such as mutexes.
|
||||
.Pp
|
||||
The semantics of
|
||||
.Fx Ns 's
|
||||
atomic operations are almost identical to those of the similarly named
|
||||
C11 operations.
|
||||
The one important difference is that the C11 standard does not
|
||||
require ordinary loads and stores to ever be atomic.
|
||||
This is is why the
|
||||
.Fn atomic_load_explicit memory_order_relaxed
|
||||
operation exists in the C11 standard, but is not provided by
|
||||
.In machine/atomic.h .
|
||||
Except as noted below, the semantics of these operations are almost
|
||||
identical to the semantics of similarly named C11 atomic operations.
|
||||
.Ss Types
|
||||
Each atomic operation operates on a specific
|
||||
Most atomic operations act upon a specific
|
||||
.Fa type .
|
||||
The type to use is indicated in the function name.
|
||||
The available types that can be used are:
|
||||
That type is indicated in the function name.
|
||||
In contrast to C11 atomic operations,
|
||||
.Fx Ns 's
|
||||
atomic operations are performed on ordinary integer types.
|
||||
The available types are:
|
||||
.Pp
|
||||
.Bl -tag -offset indent -width short -compact
|
||||
.It Li int
|
||||
@ -147,8 +149,7 @@ unsigned 8-bit integer
|
||||
unsigned 16-bit integer
|
||||
.El
|
||||
.Pp
|
||||
These must not be used in MI code because the instructions to implement them
|
||||
efficiently might not be available.
|
||||
These types must not be used in machine-independent code.
|
||||
.Ss Acquire and Release Operations
|
||||
By default, a thread's accesses to different memory locations might not be
|
||||
performed in
|
||||
@ -167,52 +168,67 @@ Moreover, in some cases, such as the implementation of synchronization between
|
||||
threads, arbitrary reordering might result in the incorrect execution of the
|
||||
program.
|
||||
To constrain the reordering that both the compiler and processor might perform
|
||||
on a thread's accesses, the thread should use atomic operations with
|
||||
on a thread's accesses, a programmer can use atomic operations with
|
||||
.Em acquire
|
||||
and
|
||||
.Em release
|
||||
semantics.
|
||||
.Pp
|
||||
Most of the atomic operations on memory have three variants.
|
||||
The first variant performs the operation without imposing any ordering
|
||||
constraints on memory accesses to other locations.
|
||||
Atomic operations on memory have up to three variants.
|
||||
The first, or
|
||||
.Em relaxed
|
||||
variant, performs the operation without imposing any ordering constraints on
|
||||
accesses to other memory locations.
|
||||
This variant is the default.
|
||||
The second variant has acquire semantics, and the third variant has release
|
||||
semantics.
|
||||
In effect, operations with acquire and release semantics establish one-way
|
||||
barriers to reordering.
|
||||
.Pp
|
||||
When an atomic operation has acquire semantics, the effects of the operation
|
||||
must have completed before any subsequent load or store (by program order) is
|
||||
When an atomic operation has acquire semantics, the operation must have
|
||||
completed before any subsequent load or store (by program order) is
|
||||
performed.
|
||||
Conversely, acquire semantics do not require that prior loads or stores have
|
||||
completed before the atomic operation is performed.
|
||||
An atomic operation can only have acquire semantics if it performs a load
|
||||
from memory.
|
||||
To denote acquire semantics, the suffix
|
||||
.Dq Li _acq
|
||||
is inserted into the function name immediately prior to the
|
||||
.Dq Li _ Ns Aq Fa type
|
||||
suffix.
|
||||
For example, to subtract two integers ensuring that subsequent loads and
|
||||
stores happen after the subtraction is performed, use
|
||||
For example, to subtract two integers ensuring that the subtraction is
|
||||
completed before any subsequent loads and stores are performed, use
|
||||
.Fn atomic_subtract_acq_int .
|
||||
.Pp
|
||||
When an atomic operation has release semantics, the effects of all prior
|
||||
loads or stores (by program order) must have completed before the operation
|
||||
is performed.
|
||||
Conversely, release semantics do not require that the effects of the
|
||||
atomic operation must have completed before any subsequent load or store is
|
||||
performed.
|
||||
When an atomic operation has release semantics, all prior loads or stores
|
||||
(by program order) must have completed before the operation is performed.
|
||||
Conversely, release semantics do not require that the atomic operation must
|
||||
have completed before any subsequent load or store is performed.
|
||||
An atomic operation can only have release semantics if it performs a store
|
||||
to memory.
|
||||
To denote release semantics, the suffix
|
||||
.Dq Li _rel
|
||||
is inserted into the function name immediately prior to the
|
||||
.Dq Li _ Ns Aq Fa type
|
||||
suffix.
|
||||
For example, to add two long integers ensuring that all prior loads and
|
||||
stores happen before the addition, use
|
||||
stores are completed before the addition is performed, use
|
||||
.Fn atomic_add_rel_long .
|
||||
.Pp
|
||||
The one-way barriers provided by acquire and release operations allow the
|
||||
implementations of common synchronization primitives to express their
|
||||
ordering requirements without also imposing unnecessary ordering.
|
||||
When a release operation by one thread
|
||||
.Em synchronizes with
|
||||
an acquire operation by another thread, usually meaning that the acquire
|
||||
operation reads the value written by the release operation, then the effects
|
||||
of all prior stores by the releasing thread must become visible to
|
||||
subsequent loads by the acquiring thread.
|
||||
Moreover, the effects of all stores (by other threads) that were visible to
|
||||
the releasing thread must also become visible to the acquiring thread.
|
||||
These rules only apply to the synchronizing threads.
|
||||
Other threads might observe these stores in a different order.
|
||||
.Pp
|
||||
In effect, atomic operations with acquire and release semantics establish
|
||||
one-way barriers to reordering that enable the implementations of
|
||||
synchronization primitives to express their ordering requirements without
|
||||
also imposing unnecessary ordering.
|
||||
For example, for a critical section guarded by a mutex, an acquire operation
|
||||
when the mutex is locked and a release operation when the mutex is unlocked
|
||||
will prevent any loads or stores from moving outside of the critical
|
||||
@ -220,6 +236,61 @@ section.
|
||||
However, they will not prevent the compiler or processor from moving loads
|
||||
or stores into the critical section, which does not violate the semantics of
|
||||
a mutex.
|
||||
.Ss Thread Fence Operations
|
||||
Alternatively, a programmer can use atomic thread fence operations to
|
||||
constrain the reordering of accesses.
|
||||
In contrast to other atomic operations, fences do not, themselves, access
|
||||
memory.
|
||||
.Pp
|
||||
When a fence has acquire semantics, all prior loads (by program order) must
|
||||
have completed before any subsequent load or store is performed.
|
||||
Thus, an acquire fence is a two-way barrier for load operations.
|
||||
To denote acquire semantics, the suffix
|
||||
.Dq Li _acq
|
||||
is appended to the function name, for example,
|
||||
.Fn atomic_thread_fence_acq .
|
||||
.Pp
|
||||
When a fence has release semantics, all prior loads or stores (by program
|
||||
order) must have completed before any subsequent store operation is
|
||||
performed.
|
||||
Thus, a release fence is a two-way barrier for store operations.
|
||||
To denote release semantics, the suffix
|
||||
.Dq Li _rel
|
||||
is appended to the function name, for example,
|
||||
.Fn atomic_thread_fence_rel .
|
||||
.Pp
|
||||
Although
|
||||
.Fn atomic_thread_fence_acq_rel
|
||||
implements both acquire and release semantics, it is not a full barrier.
|
||||
For example, a store prior to the fence (in program order) may be completed
|
||||
after a load subsequent to the fence.
|
||||
In contrast,
|
||||
.Fn atomic_thread_fence_seq_cst
|
||||
implements a full barrier.
|
||||
Neither loads nor stores may cross this barrier in either direction.
|
||||
.Pp
|
||||
In C11, a release fence by one thread synchronizes with an acquire fence by
|
||||
another thread when an atomic load that is prior to the acquire fence (by
|
||||
program order) reads the value written by an atomic store that is subsequent
|
||||
to the release fence.
|
||||
In constrast, in FreeBSD, because of the atomicity of ordinary, naturally
|
||||
aligned loads and stores, fences can also be synchronized by ordinary loads
|
||||
and stores.
|
||||
This simplifies the implementation and use of some synchronization
|
||||
primitives in
|
||||
.Fx .
|
||||
.Pp
|
||||
Since neither a compiler nor a processor can foresee which (atomic) load
|
||||
will read the value written by an (atomic) store, the ordering constraints
|
||||
imposed by fences must be more restrictive than acquire loads and release
|
||||
stores.
|
||||
Essentially, this is why fences are two-way barriers.
|
||||
.Pp
|
||||
Although fences impose more restrictive ordering than acquire loads and
|
||||
release stores, by separating access from ordering, they can sometimes
|
||||
facilitate more efficient implementations of synchronization primitives.
|
||||
For example, they can be used to avoid executing a memory barrier until a
|
||||
memory access shows that some condition is satisfied.
|
||||
.Ss Multiple Processors
|
||||
In multiprocessor systems, the atomicity of the atomic operations on memory
|
||||
depends on support for cache coherence in the underlying architecture.
|
||||
@ -326,12 +397,6 @@ and do not have any variants with memory barriers at this time.
|
||||
.Bd -literal -compact
|
||||
return (*p);
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_load
|
||||
functions are only provided with acquire memory barriers.
|
||||
.Bl -hang
|
||||
.It Fn atomic_readandclear p
|
||||
.Bd -literal -compact
|
||||
tmp = *p;
|
||||
@ -363,12 +428,6 @@ and do not have any variants with memory barriers at this time.
|
||||
.Bd -literal -compact
|
||||
*p = v;
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_store
|
||||
functions are only provided with release memory barriers.
|
||||
.Bl -hang
|
||||
.It Fn atomic_swap p v
|
||||
.Bd -literal -compact
|
||||
tmp = *p;
|
||||
@ -490,43 +549,54 @@ The
|
||||
.Fn atomic_set ,
|
||||
and
|
||||
.Fn atomic_subtract
|
||||
operations were first introduced in
|
||||
operations were introduced in
|
||||
.Fx 3.0 .
|
||||
This first set only supported the types
|
||||
Initially, these operations were defined on the types
|
||||
.Dq Li char ,
|
||||
.Dq Li short ,
|
||||
.Dq Li int ,
|
||||
and
|
||||
.Dq Li long .
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_cmpset ,
|
||||
.Fn atomic_load ,
|
||||
.Fn atomic_load_acq ,
|
||||
.Fn atomic_readandclear ,
|
||||
and
|
||||
.Fn atomic_store
|
||||
.Fn atomic_store_rel
|
||||
operations were added in
|
||||
.Fx 5.0 .
|
||||
The types
|
||||
Simultaneously, the acquire and release variants were introduced, and
|
||||
support was added for operation on the types
|
||||
.Dq Li 8 ,
|
||||
.Dq Li 16 ,
|
||||
.Dq Li 32 ,
|
||||
.Dq Li 64 ,
|
||||
and
|
||||
.Dq Li ptr
|
||||
and all of the acquire and release variants
|
||||
were added in
|
||||
.Fx 5.0
|
||||
as well.
|
||||
.Dq Li ptr .
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_fetchadd
|
||||
operations were added in
|
||||
operation was added in
|
||||
.Fx 6.0 .
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_swap
|
||||
and
|
||||
.Fn atomic_testandset
|
||||
operations were added in
|
||||
.Fx 10.0 .
|
||||
.Pp
|
||||
The
|
||||
.Fn atomic_testandclear
|
||||
operation was added in
|
||||
and
|
||||
.Fn atomic_thread_fence
|
||||
operations were added in
|
||||
.Fx 11.0 .
|
||||
.Pp
|
||||
The relaxed variants of
|
||||
.Fn atomic_load
|
||||
and
|
||||
.Fn atomic_store
|
||||
were added in
|
||||
.Fx 12.0 .
|
||||
|
@ -794,4 +794,3 @@ Copyright (c) 1997-2012 Wolfram Schneider <wosch@FreeBSD.ORG>
|
||||
URL: http://svnweb.freebsd.org/base/head/share/misc/bsd-family-tree
|
||||
|
||||
$FreeBSD$
|
||||
$NetBSD: bsd-family-tree,v 1.62 2017/12/14 10:34:06 maya Exp $
|
||||
|
@ -45,7 +45,7 @@ extern char command_errbuf[COMMAND_ERRBUFSZ];
|
||||
#define CMD_FATAL 4
|
||||
|
||||
/* interp.c */
|
||||
void interact(const char *rc);
|
||||
void interact(void);
|
||||
int include(const char *filename);
|
||||
|
||||
/* interp_backslash.c */
|
||||
@ -55,7 +55,7 @@ char *backslash(const char *str);
|
||||
int parse(int *argc, char ***argv, const char *str);
|
||||
|
||||
/* interp_forth.c */
|
||||
void bf_init(const char *rc);
|
||||
void bf_init(void);
|
||||
int bf_run(char *line);
|
||||
|
||||
/* boot.c */
|
||||
|
@ -39,11 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef BOOT_FORTH
|
||||
#include "ficl.h"
|
||||
#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
|
||||
|
||||
extern FICL_VM *bf_vm;
|
||||
#else
|
||||
#define RETURN(x) return(x)
|
||||
#endif
|
||||
|
||||
#define MAXARGS 20 /* maximum number of arguments allowed */
|
||||
@ -51,12 +47,10 @@ extern FICL_VM *bf_vm;
|
||||
static void prompt(void);
|
||||
|
||||
#ifndef BOOT_FORTH
|
||||
static int perform(int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
* Perform the command
|
||||
*/
|
||||
int
|
||||
static int
|
||||
perform(int argc, char *argv[])
|
||||
{
|
||||
int result;
|
||||
@ -82,7 +76,7 @@ perform(int argc, char *argv[])
|
||||
} else {
|
||||
command_errmsg = "unknown command";
|
||||
}
|
||||
RETURN(result);
|
||||
return(result);
|
||||
}
|
||||
#endif /* ! BOOT_FORTH */
|
||||
|
||||
@ -90,7 +84,7 @@ perform(int argc, char *argv[])
|
||||
* Interactive mode
|
||||
*/
|
||||
void
|
||||
interact(const char *rc)
|
||||
interact(void)
|
||||
{
|
||||
static char input[256]; /* big enough? */
|
||||
#ifndef BOOT_FORTH
|
||||
@ -99,14 +93,11 @@ interact(const char *rc)
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_FORTH
|
||||
bf_init((rc) ? "" : NULL);
|
||||
bf_init();
|
||||
#endif
|
||||
|
||||
if (rc == NULL) {
|
||||
/* Read our default configuration. */
|
||||
include("/boot/loader.rc");
|
||||
} else if (*rc != '\0')
|
||||
include(rc);
|
||||
/* Read our default configuration. */
|
||||
include("/boot/loader.rc");
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
@ -250,7 +250,7 @@ bf_command(FICL_VM *vm)
|
||||
* Initialise the Forth interpreter, create all our commands as words.
|
||||
*/
|
||||
void
|
||||
bf_init(const char *rc)
|
||||
bf_init(void)
|
||||
{
|
||||
struct bootblk_command **cmdp;
|
||||
char create_buf[41]; /* 31 characters-long builtins */
|
||||
@ -280,14 +280,9 @@ bf_init(const char *rc)
|
||||
ficlSetEnv(bf_sys, "loader_version", bootprog_rev);
|
||||
|
||||
/* try to load and run init file if present */
|
||||
if (rc == NULL)
|
||||
rc = "/boot/boot.4th";
|
||||
if (*rc != '\0') {
|
||||
fd = open(rc, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
(void)ficlExecFD(bf_vm, fd);
|
||||
close(fd);
|
||||
}
|
||||
if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) {
|
||||
(void)ficlExecFD(bf_vm, fd);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,10 +430,10 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
|
||||
conout = ST->ConOut;
|
||||
conout->Reset(conout, TRUE);
|
||||
max_dim = best_mode = 0;
|
||||
for (i = 0; ; i++) {
|
||||
for (i = 0; i < conout->Mode->MaxMode; i++) {
|
||||
status = conout->QueryMode(conout, i, &cols, &rows);
|
||||
if (EFI_ERROR(status))
|
||||
break;
|
||||
continue;
|
||||
if (cols * rows > max_dim) {
|
||||
max_dim = cols * rows;
|
||||
best_mode = i;
|
||||
|
@ -501,7 +501,7 @@ main(int argc, CHAR16 *argv[])
|
||||
#endif
|
||||
}
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
return (EFI_SUCCESS); /* keep compiler happy */
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ BTXCRT= ${BTXDIR}/lib/crt0.o
|
||||
BTXSRC= ${BOOTSRC}/i386/btx
|
||||
BTXLIB= ${BTXSRC}/lib
|
||||
|
||||
CFLAGS+= -I${BTXLIB}
|
||||
|
||||
# compact binary with no padding between text, data, bss
|
||||
LDSCRIPT= ${BOOTSRC}/i386/boot.ldscript
|
||||
# LDFLAGS_BIN=-e start -Ttext ${ORG} -Wl,-T,${LDSCRIPT},-S,--oformat,binary
|
||||
|
@ -31,7 +31,6 @@ CFLAGS+=-fomit-frame-pointer \
|
||||
-DSIOFMT=${B2SIOFMT} \
|
||||
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
|
||||
-I${LDRSRC} \
|
||||
-I${BTXLIB} \
|
||||
-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
|
||||
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
|
||||
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
|
||||
|
@ -33,7 +33,6 @@ CFLAGS+=-DBOOTPROG=\"gptboot\" \
|
||||
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
|
||||
-I${LDRSRC} \
|
||||
-I${BOOTSRC}/i386/common \
|
||||
-I${BTXLIB} \
|
||||
-I${BOOTSRC}/i386/boot2 \
|
||||
-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
|
||||
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
|
||||
|
@ -12,7 +12,6 @@ SRCS+= dcons.c fwcrom.c
|
||||
CFLAGS+= -D_BOOT
|
||||
|
||||
CFLAGS+= -I${LDRSRC}
|
||||
CFLAGS+= -I${BTXLIB}
|
||||
CFLAGS+= -I${BOOTSRC}/i386/libi386
|
||||
|
||||
CFLAGS+= -Wformat -Wall
|
||||
|
@ -47,7 +47,6 @@ CFLAGS+= -Dalloca=__builtin_alloca
|
||||
|
||||
CFLAGS+= -I${BOOTSRC}/ficl -I${BOOTSRC}/ficl/i386 \
|
||||
-I${LDRSRC} -I${BOOTSRC}/i386/common \
|
||||
-I${BTXLIB} \
|
||||
-I${SYSDIR}/contrib/dev/acpica/include
|
||||
|
||||
# Handle FreeBSD specific %b and %D printf format specifiers
|
||||
|
@ -49,8 +49,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "bootstrap.h"
|
||||
#include "multiboot.h"
|
||||
#include "../i386/libi386/libi386.h"
|
||||
#include "../i386/btx/lib/btxv86.h"
|
||||
#include "libi386.h"
|
||||
#include <btxv86.h>
|
||||
|
||||
#define MULTIBOOT_SUPPORTED_FLAGS \
|
||||
(MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO)
|
||||
|
@ -56,9 +56,6 @@ LDFLAGS+= -static -Ttext 0x0
|
||||
LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
|
||||
CFLAGS+= -I${BOOTSRC}/i386
|
||||
|
||||
# BTX components
|
||||
CFLAGS+= -I${BTXLIB}
|
||||
|
||||
# Debug me!
|
||||
#CFLAGS+= -g
|
||||
#LDFLAGS+= -g
|
||||
|
@ -232,7 +232,7 @@ main(void)
|
||||
|
||||
bios_getsmap();
|
||||
|
||||
interact(NULL);
|
||||
interact();
|
||||
|
||||
/* if we ever get here, it is an error */
|
||||
return (1);
|
||||
|
@ -31,7 +31,6 @@ CFLAGS+=-DBOOTPROG=\"zfsboot\" \
|
||||
-I${ZFSSRC} \
|
||||
-I${SYSDIR}/crypto/skein \
|
||||
-I${SYSDIR}/cddl/boot/zfs \
|
||||
-I${BTXLIB} \
|
||||
-I${BOOTSRC}/i386/boot2 \
|
||||
-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
|
||||
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
|
||||
|
@ -149,7 +149,7 @@ main(int argc, char *argv[], char *envv[], struct bootinfo *bootinfop)
|
||||
printf("bootpath=\"%s\"\n", bootpath);
|
||||
#endif
|
||||
|
||||
interact(NULL);
|
||||
interact();
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ main(int (*openfirm)(void *))
|
||||
archsw.arch_readin = ofw_readin;
|
||||
archsw.arch_autoload = ofw_autoload;
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
OF_exit();
|
||||
|
||||
|
@ -122,7 +122,7 @@ main(int argc, const char **argv)
|
||||
setenv("loaddev", bootdev, 1);
|
||||
setenv("LINES", "24", 1);
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ main(void)
|
||||
setenv("LINES", "24", 1);
|
||||
setenv("hw.platform", "ps3", 1);
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -902,7 +902,7 @@ main(int (*openfirm)(void *))
|
||||
printf("bootpath=\"%s\"\n", bootpath);
|
||||
|
||||
/* Give control to the machine independent loader code. */
|
||||
interact(NULL);
|
||||
interact();
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -500,7 +500,7 @@ main(int argc, char **argv)
|
||||
archsw.arch_readin = uboot_readin;
|
||||
archsw.arch_autoload = uboot_autoload;
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks)
|
||||
if (setjmp(jb))
|
||||
return;
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
interact(); /* doesn't return */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
@ -57,6 +57,8 @@
|
||||
#define wmb() __asm __volatile("sfence;" : : : "memory")
|
||||
#define rmb() __asm __volatile("lfence;" : : : "memory")
|
||||
|
||||
#include <sys/atomic_common.h>
|
||||
|
||||
/*
|
||||
* Various simple operations on memory, each of which is atomic in the
|
||||
* presence of interrupts and multiple processors.
|
||||
|
@ -3174,8 +3174,28 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
|
||||
pir_desc = vlapic_vtx->pir_desc;
|
||||
|
||||
pending = atomic_load_acq_long(&pir_desc->pending);
|
||||
if (!pending)
|
||||
return (0); /* common case */
|
||||
if (!pending) {
|
||||
/*
|
||||
* While a virtual interrupt may have already been
|
||||
* processed the actual delivery maybe pending the
|
||||
* interruptibility of the guest. Recognize a pending
|
||||
* interrupt by reevaluating virtual interrupts
|
||||
* following Section 29.2.1 in the Intel SDM Volume 3.
|
||||
*/
|
||||
uint64_t val;
|
||||
uint8_t rvi, ppr;
|
||||
|
||||
vmx_getreg(vlapic_vtx->vmx, vlapic->vcpuid,
|
||||
VMCS_IDENT(VMCS_GUEST_INTR_STATUS), &val);
|
||||
rvi = val & APIC_TPR_INT;
|
||||
lapic = vlapic->apic_page;
|
||||
ppr = lapic->ppr & APIC_TPR_INT;
|
||||
if (rvi > ppr) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is an interrupt pending then it will be recognized only
|
||||
@ -3185,7 +3205,7 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
|
||||
* interrupt will be recognized.
|
||||
*/
|
||||
lapic = vlapic->apic_page;
|
||||
ppr = lapic->ppr & 0xf0;
|
||||
ppr = lapic->ppr & APIC_TPR_INT;
|
||||
if (ppr == 0)
|
||||
return (1);
|
||||
|
||||
@ -3195,7 +3215,7 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
|
||||
for (i = 3; i >= 0; i--) {
|
||||
pirval = pir_desc->pir[i];
|
||||
if (pirval != 0) {
|
||||
vpr = (i * 64 + flsl(pirval) - 1) & 0xf0;
|
||||
vpr = (i * 64 + flsl(pirval) - 1) & APIC_TPR_INT;
|
||||
return (vpr > ppr);
|
||||
}
|
||||
}
|
||||
|
@ -1128,6 +1128,19 @@ initarm(struct arm_boot_params *abp)
|
||||
pmap_set_tex();
|
||||
pmap_bootstrap_prepare(lastaddr);
|
||||
|
||||
/*
|
||||
* If EARLY_PRINTF support is enabled, we need to re-establish the
|
||||
* mapping after pmap_bootstrap_prepare() switches to new page tables.
|
||||
* Note that we can only do the remapping if the VA is outside the
|
||||
* kernel, now that we have real virtual (not VA=PA) mappings in effect.
|
||||
* Early printf does not work between the time pmap_set_tex() does
|
||||
* cp15_prrr_set() and this code remaps the VA.
|
||||
*/
|
||||
#if defined(EARLY_PRINTF) && defined(SOCDEV_PA) && defined(SOCDEV_VA) && SOCDEV_VA < KERNBASE
|
||||
pmap_preboot_map_attr(SOCDEV_PA, SOCDEV_VA, 1024 * 1024,
|
||||
VM_PROT_READ | VM_PROT_WRITE, VM_MEMATTR_DEVICE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now that proper page tables are installed, call cpu_setup() to enable
|
||||
* instruction and data caches and other chip-specific features.
|
||||
@ -1191,6 +1204,14 @@ initarm(struct arm_boot_params *abp)
|
||||
platform_gpio_init();
|
||||
cninit();
|
||||
|
||||
/*
|
||||
* If we made a mapping for EARLY_PRINTF after pmap_bootstrap_prepare(),
|
||||
* undo it now that the normal console printf works.
|
||||
*/
|
||||
#if defined(EARLY_PRINTF) && defined(SOCDEV_PA) && defined(SOCDEV_VA) && SOCDEV_VA < KERNBASE
|
||||
pmap_kremove(SOCDEV_VA);
|
||||
#endif
|
||||
|
||||
debugf("initarm: console initialized\n");
|
||||
debugf(" arg1 kmdp = 0x%08x\n", (uint32_t)kmdp);
|
||||
debugf(" boothowto = 0x%08x\n", boothowto);
|
||||
|
@ -1310,10 +1310,16 @@ pmap_kenter(vm_offset_t va, vm_paddr_t pa)
|
||||
PMAP_INLINE void
|
||||
pmap_kremove(vm_offset_t va)
|
||||
{
|
||||
pt1_entry_t *pte1p;
|
||||
pt2_entry_t *pte2p;
|
||||
|
||||
pte2p = pt2map_entry(va);
|
||||
pte2_clear(pte2p);
|
||||
pte1p = kern_pte1(va);
|
||||
if (pte1_is_section(pte1_load(pte1p))) {
|
||||
pte1_clear(pte1p);
|
||||
} else {
|
||||
pte2p = pt2map_entry(va);
|
||||
pte2_clear(pte2p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -41,6 +41,8 @@
|
||||
#ifndef _MACHINE_ATOMIC_H_
|
||||
#define _MACHINE_ATOMIC_H_
|
||||
|
||||
#include <sys/atomic_common.h>
|
||||
|
||||
#include <machine/armreg.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
@ -53,32 +55,6 @@
|
||||
#include <machine/atomic-v4.h>
|
||||
#endif /* Arch >= v6 */
|
||||
|
||||
static __inline int
|
||||
atomic_load_32(volatile uint32_t *v)
|
||||
{
|
||||
|
||||
return (*v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_store_32(volatile uint32_t *dst, uint32_t src)
|
||||
{
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_load_long(volatile u_long *v)
|
||||
{
|
||||
|
||||
return (*v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_store_long(volatile u_long *dst, u_long src)
|
||||
{
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
#define atomic_clear_ptr atomic_clear_32
|
||||
#define atomic_clear_acq_ptr atomic_clear_acq_32
|
||||
#define atomic_clear_rel_ptr atomic_clear_rel_32
|
||||
@ -92,7 +68,6 @@ atomic_store_long(volatile u_long *dst, u_long src)
|
||||
#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32
|
||||
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32
|
||||
#define atomic_load_acq_ptr atomic_load_acq_32
|
||||
#define atomic_store_ptr atomic_store_32
|
||||
#define atomic_store_rel_ptr atomic_store_rel_32
|
||||
#define atomic_swap_ptr atomic_swap_32
|
||||
#define atomic_readandclear_ptr atomic_readandclear_32
|
||||
|
@ -29,6 +29,8 @@
|
||||
#ifndef _MACHINE_ATOMIC_H_
|
||||
#define _MACHINE_ATOMIC_H_
|
||||
|
||||
#include <sys/atomic_common.h>
|
||||
|
||||
#define isb() __asm __volatile("isb" : : : "memory")
|
||||
|
||||
/*
|
||||
|
@ -633,6 +633,11 @@ struct ccb_pathinq_settings_sas {
|
||||
|
||||
struct ccb_pathinq_settings_nvme {
|
||||
uint32_t nsid; /* Namespace ID for this path */
|
||||
uint32_t domain;
|
||||
uint8_t bus;
|
||||
uint8_t slot;
|
||||
uint8_t function;
|
||||
uint8_t extra;
|
||||
};
|
||||
|
||||
#define PATHINQ_SETTINGS_SIZE 128
|
||||
|
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/buf.h>
|
||||
@ -1158,7 +1159,7 @@ cam_periph_runccb(union ccb *ccb,
|
||||
struct bintime *starttime;
|
||||
struct bintime ltime;
|
||||
int error;
|
||||
bool sched_stopped;
|
||||
bool must_poll;
|
||||
struct mtx *periph_mtx;
|
||||
struct cam_periph *periph;
|
||||
uint32_t timeout = 1;
|
||||
@ -1182,7 +1183,13 @@ cam_periph_runccb(union ccb *ccb,
|
||||
devstat_start_transaction(ds, starttime);
|
||||
}
|
||||
|
||||
sched_stopped = SCHEDULER_STOPPED();
|
||||
/*
|
||||
* We must poll the I/O while we're dumping. The scheduler is normally
|
||||
* stopped for dumping, except when we call doadump from ddb. While the
|
||||
* scheduler is running in this case, we still need to poll the I/O to
|
||||
* avoid sleeping waiting for the ccb to complete.
|
||||
*/
|
||||
must_poll = dumping;
|
||||
ccb->ccb_h.cbfcnp = cam_periph_done;
|
||||
periph = xpt_path_periph(ccb->ccb_h.path);
|
||||
periph_mtx = cam_periph_mtx(periph);
|
||||
@ -1193,7 +1200,7 @@ cam_periph_runccb(union ccb *ccb,
|
||||
* cam_periph_error can reschedule the ccb by calling xpt_action and returning
|
||||
* ERESTART, so we have to effect the polling in the do loop below.
|
||||
*/
|
||||
if (sched_stopped) {
|
||||
if (must_poll) {
|
||||
mtx_unlock(periph_mtx);
|
||||
timeout = xpt_poll_setup(ccb);
|
||||
}
|
||||
@ -1204,11 +1211,11 @@ cam_periph_runccb(union ccb *ccb,
|
||||
} else {
|
||||
xpt_action(ccb);
|
||||
do {
|
||||
if (!sched_stopped)
|
||||
cam_periph_ccbwait(ccb);
|
||||
else {
|
||||
if (must_poll) {
|
||||
xpt_pollwait(ccb, timeout);
|
||||
timeout = ccb->ccb_h.timeout * 10;
|
||||
} else {
|
||||
cam_periph_ccbwait(ccb);
|
||||
}
|
||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
|
||||
error = 0;
|
||||
@ -1220,7 +1227,7 @@ cam_periph_runccb(union ccb *ccb,
|
||||
} while (error == ERESTART);
|
||||
}
|
||||
|
||||
if (sched_stopped)
|
||||
if (must_poll)
|
||||
mtx_lock(periph_mtx);
|
||||
|
||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
||||
|
@ -201,6 +201,7 @@ typedef struct znode {
|
||||
boolean_t z_is_sa; /* are we native sa? */
|
||||
} znode_t;
|
||||
|
||||
#define ZFS_LINK_MAX UINT64_MAX
|
||||
|
||||
/*
|
||||
* Range locking rules
|
||||
|
@ -527,12 +527,10 @@ zfs_link_create(znode_t *dzp, const char *name, znode_t *zp, dmu_tx_t *tx,
|
||||
|
||||
ASSERT_VOP_ELOCKED(ZTOV(dzp), __func__);
|
||||
ASSERT_VOP_ELOCKED(ZTOV(zp), __func__);
|
||||
#if 0
|
||||
#ifdef __FreeBSD__
|
||||
if (zp_is_dir) {
|
||||
error = 0;
|
||||
if (dzp->z_links >= LINK_MAX)
|
||||
error = SET_ERROR(EMLINK);
|
||||
return (error);
|
||||
if (dzp->z_links >= ZFS_LINK_MAX)
|
||||
return (SET_ERROR(EMLINK));
|
||||
}
|
||||
#endif
|
||||
if (!(flag & ZRENAMING)) {
|
||||
@ -540,8 +538,8 @@ zfs_link_create(znode_t *dzp, const char *name, znode_t *zp, dmu_tx_t *tx,
|
||||
ASSERT(!(flag & (ZNEW | ZEXISTS)));
|
||||
return (SET_ERROR(ENOENT));
|
||||
}
|
||||
#if 0
|
||||
if (zp->z_links >= LINK_MAX) {
|
||||
#ifdef __FreeBSD__
|
||||
if (zp->z_links >= ZFS_LINK_MAX - zp_is_dir) {
|
||||
return (SET_ERROR(EMLINK));
|
||||
}
|
||||
#endif
|
||||
|
@ -2643,7 +2643,6 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
|
||||
int error = 0;
|
||||
uint32_t blksize;
|
||||
u_longlong_t nblocks;
|
||||
uint64_t links;
|
||||
uint64_t mtime[2], ctime[2], crtime[2], rdev;
|
||||
xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */
|
||||
xoptattr_t *xoap = NULL;
|
||||
@ -2695,11 +2694,10 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
|
||||
vn_fsid(vp, vap);
|
||||
#endif
|
||||
vap->va_nodeid = zp->z_id;
|
||||
if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp))
|
||||
links = zp->z_links + 1;
|
||||
else
|
||||
links = zp->z_links;
|
||||
vap->va_nlink = MIN(links, LINK_MAX); /* nlink_t limit! */
|
||||
vap->va_nlink = zp->z_links;
|
||||
if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp) &&
|
||||
zp->z_links < ZFS_LINK_MAX)
|
||||
vap->va_nlink++;
|
||||
vap->va_size = zp->z_size;
|
||||
#ifdef illumos
|
||||
vap->va_rdev = vp->v_rdev;
|
||||
@ -4404,7 +4402,7 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
|
||||
|
||||
switch (cmd) {
|
||||
case _PC_LINK_MAX:
|
||||
*valp = INT_MAX;
|
||||
*valp = MIN(LONG_MAX, ZFS_LINK_MAX);
|
||||
return (0);
|
||||
|
||||
case _PC_FILESIZEBITS:
|
||||
@ -5405,30 +5403,25 @@ zfs_freebsd_pathconf(ap)
|
||||
int error;
|
||||
|
||||
error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred, NULL);
|
||||
if (error == 0)
|
||||
if (error == 0) {
|
||||
*ap->a_retval = val;
|
||||
else if (error == EOPNOTSUPP)
|
||||
error = vop_stdpathconf(ap);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_freebsd_fifo_pathconf(ap)
|
||||
struct vop_pathconf_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_name;
|
||||
register_t *a_retval;
|
||||
} */ *ap;
|
||||
{
|
||||
return (error);
|
||||
}
|
||||
if (error != EOPNOTSUPP)
|
||||
return (error);
|
||||
|
||||
switch (ap->a_name) {
|
||||
case _PC_ACL_EXTENDED:
|
||||
case _PC_ACL_NFS4:
|
||||
case _PC_ACL_PATH_MAX:
|
||||
case _PC_MAC_PRESENT:
|
||||
return (zfs_freebsd_pathconf(ap));
|
||||
case _PC_NAME_MAX:
|
||||
*ap->a_retval = NAME_MAX;
|
||||
return (0);
|
||||
case _PC_PIPE_BUF:
|
||||
if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) {
|
||||
*ap->a_retval = PIPE_BUF;
|
||||
return (0);
|
||||
}
|
||||
return (EINVAL);
|
||||
default:
|
||||
return (fifo_specops.vop_pathconf(ap));
|
||||
return (vop_stdpathconf(ap));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6043,7 +6036,7 @@ struct vop_vector zfs_fifoops = {
|
||||
.vop_reclaim = zfs_freebsd_reclaim,
|
||||
.vop_setattr = zfs_freebsd_setattr,
|
||||
.vop_write = VOP_PANIC,
|
||||
.vop_pathconf = zfs_freebsd_fifo_pathconf,
|
||||
.vop_pathconf = zfs_freebsd_pathconf,
|
||||
.vop_fid = zfs_freebsd_fid,
|
||||
.vop_getacl = zfs_freebsd_getacl,
|
||||
.vop_setacl = zfs_freebsd_setacl,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||
* Copyright (c) 2016 Matt Macy (mmacy@nextbsd.org)
|
||||
* Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io)
|
||||
* Copyright (c) 2017 Mellanox Technologies, Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Matt Macy (mmacy@nextbsd.org)
|
||||
* Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1101,6 +1101,9 @@ options MD_ROOT_SIZE=10
|
||||
# images of type mfs_root or md_root.
|
||||
options MD_ROOT
|
||||
|
||||
# Write-protect the md root device so that it may not be mounted writeable.
|
||||
options MD_ROOT_READONLY
|
||||
|
||||
# Disk quotas are supported when this option is enabled.
|
||||
options QUOTA #enable disk quotas
|
||||
|
||||
|
@ -1723,6 +1723,9 @@ dev/extres/regulator/regnode_if.m optional ext_resources regulator fdt
|
||||
dev/extres/regulator/regulator.c optional ext_resources regulator fdt
|
||||
dev/extres/regulator/regulator_bus.c optional ext_resources regulator fdt
|
||||
dev/extres/regulator/regulator_fixed.c optional ext_resources regulator fdt
|
||||
dev/extres/syscon/syscon.c optional ext_resources syscon
|
||||
dev/extres/syscon/syscon_generic.c optional ext_resources syscon fdt
|
||||
dev/extres/syscon/syscon_if.m optional ext_resources syscon
|
||||
dev/fb/fbd.c optional fbd | vt
|
||||
dev/fb/fb_if.m standard
|
||||
dev/fb/splash.c optional sc splash
|
||||
@ -2223,11 +2226,9 @@ dev/ixgbe/if_ixv.c optional ixv inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP"
|
||||
dev/ixgbe/if_bypass.c optional ix inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
|
||||
dev/ixgbe/ixgbe_netmap.c optional ix inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
|
||||
dev/ixgbe/if_fdir.c optional ix inet | ixv inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
|
||||
dev/ixgbe/if_sriov.c optional ix inet | ixv inet \
|
||||
dev/ixgbe/if_sriov.c optional ix inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
|
||||
dev/ixgbe/ix_txrx.c optional ix inet | ixv inet \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
|
||||
@ -3109,8 +3110,6 @@ dev/stg/tmc18c30_subr.c optional stg
|
||||
dev/stge/if_stge.c optional stge
|
||||
dev/sym/sym_hipd.c optional sym \
|
||||
dependency "$S/dev/sym/sym_{conf,defs}.h"
|
||||
dev/syscon/syscon.c optional fdt syscon
|
||||
dev/syscon/syscon_if.m optional fdt syscon
|
||||
dev/syscons/blank/blank_saver.c optional blank_saver
|
||||
dev/syscons/daemon/daemon_saver.c optional daemon_saver
|
||||
dev/syscons/dragon/dragon_saver.c optional dragon_saver
|
||||
|
@ -11,7 +11,7 @@ SECTIONS
|
||||
/* Read-only sections, merged into text segment: */
|
||||
|
||||
. = kernbase;
|
||||
PROVIDE (begin = . - SIZEOF_HEADERS);
|
||||
PROVIDE (begin = .);
|
||||
|
||||
.text :
|
||||
{
|
||||
|
@ -165,6 +165,7 @@ MAC_STUB opt_dontuse.h
|
||||
MAC_TEST opt_dontuse.h
|
||||
MD_ROOT opt_md.h
|
||||
MD_ROOT_FSTYPE opt_md.h
|
||||
MD_ROOT_READONLY opt_md.h
|
||||
MD_ROOT_SIZE opt_md.h
|
||||
MFI_DEBUG opt_mfi.h
|
||||
MFI_DECODE_LOG opt_mfi.h
|
||||
|
@ -1014,10 +1014,7 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
|
||||
* name to see if one's resources are a subset of this device.
|
||||
*/
|
||||
line = 0;
|
||||
for (;;) {
|
||||
if (resource_find_dev(&line, name, &unit, "at", NULL) != 0)
|
||||
break;
|
||||
|
||||
while (resource_find_dev(&line, name, &unit, "at", NULL) == 0) {
|
||||
/* Must have an "at" for acpi or isa. */
|
||||
resource_string_value(name, unit, "at", &s);
|
||||
if (!(strcmp(s, "acpi0") == 0 || strcmp(s, "acpi") == 0 ||
|
||||
|
@ -140,6 +140,8 @@ struct acpi_cpu_device {
|
||||
#define CST_FFH_MWAIT_HW_COORD 0x0001
|
||||
#define CST_FFH_MWAIT_BM_AVOID 0x0002
|
||||
|
||||
#define CPUDEV_DEVICE_ID "ACPI0007"
|
||||
|
||||
/* Allow users to ignore processor orders in MADT. */
|
||||
static int cpu_unordered;
|
||||
SYSCTL_INT(_debug_acpi, OID_AUTO, cpu_unordered, CTLFLAG_RDTUN,
|
||||
@ -236,14 +238,21 @@ MODULE_DEPEND(cpu, acpi, 1, 1, 1);
|
||||
static int
|
||||
acpi_cpu_probe(device_t dev)
|
||||
{
|
||||
static char *cpudev_ids[] = { CPUDEV_DEVICE_ID, NULL };
|
||||
int acpi_id, cpu_id;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_HANDLE handle;
|
||||
ACPI_OBJECT *obj;
|
||||
ACPI_STATUS status;
|
||||
ACPI_OBJECT_TYPE type;
|
||||
|
||||
if (acpi_disabled("cpu") || acpi_get_type(dev) != ACPI_TYPE_PROCESSOR ||
|
||||
acpi_cpu_disabled)
|
||||
if (acpi_disabled("cpu") || acpi_cpu_disabled)
|
||||
return (ENXIO);
|
||||
type = acpi_get_type(dev);
|
||||
if (type != ACPI_TYPE_PROCESSOR && type != ACPI_TYPE_DEVICE)
|
||||
return (ENXIO);
|
||||
if (type == ACPI_TYPE_DEVICE &&
|
||||
ACPI_ID_PROBE(device_get_parent(dev), dev, cpudev_ids) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
handle = acpi_get_handle(dev);
|
||||
@ -251,29 +260,39 @@ acpi_cpu_probe(device_t dev)
|
||||
cpu_softc = malloc(sizeof(struct acpi_cpu_softc *) *
|
||||
(mp_maxid + 1), M_TEMP /* XXX */, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Get our Processor object. */
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
status = AcpiEvaluateObject(handle, NULL, NULL, &buf);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "probe failed to get Processor obj - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
}
|
||||
obj = (ACPI_OBJECT *)buf.Pointer;
|
||||
if (obj->Type != ACPI_TYPE_PROCESSOR) {
|
||||
device_printf(dev, "Processor object has bad type %d\n", obj->Type);
|
||||
AcpiOsFree(obj);
|
||||
return (ENXIO);
|
||||
}
|
||||
if (type == ACPI_TYPE_PROCESSOR) {
|
||||
/* Get our Processor object. */
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
status = AcpiEvaluateObject(handle, NULL, NULL, &buf);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "probe failed to get Processor obj - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
}
|
||||
obj = (ACPI_OBJECT *)buf.Pointer;
|
||||
if (obj->Type != ACPI_TYPE_PROCESSOR) {
|
||||
device_printf(dev, "Processor object has bad type %d\n",
|
||||
obj->Type);
|
||||
AcpiOsFree(obj);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the processor associated with our unit. We could use the
|
||||
* ProcId as a key, however, some boxes do not have the same values
|
||||
* in their Processor object as the ProcId values in the MADT.
|
||||
*/
|
||||
acpi_id = obj->Processor.ProcId;
|
||||
AcpiOsFree(obj);
|
||||
/*
|
||||
* Find the processor associated with our unit. We could use the
|
||||
* ProcId as a key, however, some boxes do not have the same values
|
||||
* in their Processor object as the ProcId values in the MADT.
|
||||
*/
|
||||
acpi_id = obj->Processor.ProcId;
|
||||
AcpiOsFree(obj);
|
||||
} else {
|
||||
status = acpi_GetInteger(handle, "_UID", &acpi_id);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "Device object has bad value - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
if (acpi_pcpu_get_id(dev, &acpi_id, &cpu_id) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
@ -325,19 +344,32 @@ acpi_cpu_attach(device_t dev)
|
||||
cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
|
||||
cpu_cst_cnt = AcpiGbl_FADT.CstControl;
|
||||
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "attach failed to get Processor obj - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_PROCESSOR) {
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "attach failed to get Processor obj - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
}
|
||||
obj = (ACPI_OBJECT *)buf.Pointer;
|
||||
sc->cpu_p_blk = obj->Processor.PblkAddress;
|
||||
sc->cpu_p_blk_len = obj->Processor.PblkLength;
|
||||
sc->cpu_acpi_id = obj->Processor.ProcId;
|
||||
AcpiOsFree(obj);
|
||||
} else {
|
||||
KASSERT(acpi_get_type(dev) == ACPI_TYPE_DEVICE,
|
||||
("Unexpected ACPI object"));
|
||||
status = acpi_GetInteger(sc->cpu_handle, "_UID", &sc->cpu_acpi_id);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(dev, "Device object has bad value - %s\n",
|
||||
AcpiFormatException(status));
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->cpu_p_blk = 0;
|
||||
sc->cpu_p_blk_len = 0;
|
||||
}
|
||||
obj = (ACPI_OBJECT *)buf.Pointer;
|
||||
sc->cpu_p_blk = obj->Processor.PblkAddress;
|
||||
sc->cpu_p_blk_len = obj->Processor.PblkLength;
|
||||
sc->cpu_acpi_id = obj->Processor.ProcId;
|
||||
AcpiOsFree(obj);
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n",
|
||||
device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));
|
||||
|
||||
|
@ -362,3 +362,4 @@ static devclass_t aha_devclass;
|
||||
|
||||
DRIVER_MODULE(aha, isa, aha_isa_driver, aha_devclass, 0, 0);
|
||||
MODULE_DEPEND(aha, isa, 1, 1, 1);
|
||||
ISA_PNP_INFO(aha_ids);
|
||||
|
@ -68,6 +68,7 @@ static const struct {
|
||||
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
|
||||
/* Not sure SB8x0/SB9x0 needs this quirk. Be conservative though */
|
||||
{0x43951002, 0x00, "AMD SB8x0/SB9x0", AHCI_Q_ATI_PMP_BUG},
|
||||
{0x43b71022, 0x00, "AMD 300 Series", 0},
|
||||
{0x78001022, 0x00, "AMD Hudson-2", 0},
|
||||
{0x78011022, 0x00, "AMD Hudson-2", 0},
|
||||
{0x78021022, 0x00, "AMD Hudson-2", 0},
|
||||
|
@ -242,3 +242,4 @@ extern devclass_t aic_devclass;
|
||||
|
||||
MODULE_DEPEND(aic, cam, 1,1,1);
|
||||
DRIVER_MODULE(aic, isa, aic_isa_driver, aic_devclass, 0, 0);
|
||||
ISA_PNP_INFO(aic_ids);
|
||||
|
@ -150,3 +150,4 @@ static devclass_t an_isa_devclass;
|
||||
DRIVER_MODULE(an, isa, an_isa_driver, an_isa_devclass, 0, 0);
|
||||
MODULE_DEPEND(an, isa, 1, 1, 1);
|
||||
MODULE_DEPEND(an, wlan, 1, 1, 1);
|
||||
ISA_PNP_INFO(an_ids);
|
||||
|
@ -322,3 +322,4 @@ atkbdc_isa_release_resource(device_t dev, device_t child, int type, int rid,
|
||||
|
||||
DRIVER_MODULE(atkbdc, isa, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||
ISA_PNP_INFO(atkbdc_ids);
|
||||
|
@ -561,6 +561,7 @@ struct bnxt_softc {
|
||||
#define BNXT_FLAG_VF 0x0001
|
||||
#define BNXT_FLAG_NPAR 0x0002
|
||||
#define BNXT_FLAG_WOL_CAP 0x0004
|
||||
#define BNXT_FLAG_SHORT_CMD 0x0008
|
||||
uint32_t flags;
|
||||
uint32_t total_msix;
|
||||
|
||||
@ -572,6 +573,7 @@ struct bnxt_softc {
|
||||
uint16_t hwrm_cmd_seq;
|
||||
uint32_t hwrm_cmd_timeo; /* milliseconds */
|
||||
struct iflib_dma_info hwrm_cmd_resp;
|
||||
struct iflib_dma_info hwrm_short_cmd_req_addr;
|
||||
/* Interrupt info for HWRM */
|
||||
struct if_irq irq;
|
||||
struct mtx hwrm_lock;
|
||||
|
@ -122,12 +122,37 @@ _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
|
||||
uint16_t cp_ring_id;
|
||||
uint8_t *valid;
|
||||
uint16_t err;
|
||||
uint16_t max_req_len = HWRM_MAX_REQ_LEN;
|
||||
struct hwrm_short_input short_input = {0};
|
||||
|
||||
/* TODO: DMASYNC in here. */
|
||||
req->seq_id = htole16(softc->hwrm_cmd_seq++);
|
||||
memset(resp, 0, PAGE_SIZE);
|
||||
cp_ring_id = le16toh(req->cmpl_ring);
|
||||
|
||||
if (softc->flags & BNXT_FLAG_SHORT_CMD) {
|
||||
void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
|
||||
|
||||
memcpy(short_cmd_req, req, msg_len);
|
||||
memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len-
|
||||
msg_len);
|
||||
|
||||
short_input.req_type = req->req_type;
|
||||
short_input.signature =
|
||||
htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
|
||||
short_input.size = htole16(msg_len);
|
||||
short_input.req_addr =
|
||||
htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
|
||||
|
||||
data = (uint32_t *)&short_input;
|
||||
msg_len = sizeof(short_input);
|
||||
|
||||
/* Sync memory write before updating doorbell */
|
||||
wmb();
|
||||
|
||||
max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
|
||||
}
|
||||
|
||||
/* Write request msg to hwrm channel */
|
||||
for (i = 0; i < msg_len; i += 4) {
|
||||
bus_space_write_4(softc->hwrm_bar.tag,
|
||||
@ -137,7 +162,7 @@ _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
|
||||
}
|
||||
|
||||
/* Clear to the end of the request buffer */
|
||||
for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
|
||||
for (i = msg_len; i < max_req_len; i += 4)
|
||||
bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
|
||||
i, 0);
|
||||
|
||||
@ -248,6 +273,7 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc)
|
||||
int rc;
|
||||
const char nastr[] = "<not installed>";
|
||||
const char naver[] = "<N/A>";
|
||||
uint32_t dev_caps_cfg;
|
||||
|
||||
softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
|
||||
softc->hwrm_cmd_timeo = 1000;
|
||||
@ -323,6 +349,11 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc)
|
||||
if (resp->def_req_timeout)
|
||||
softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
|
||||
|
||||
dev_caps_cfg = le32toh(resp->dev_caps_cfg);
|
||||
if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
|
||||
(dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
|
||||
softc->flags |= BNXT_FLAG_SHORT_CMD;
|
||||
|
||||
fail:
|
||||
BNXT_HWRM_UNLOCK(softc);
|
||||
return rc;
|
||||
@ -945,9 +976,9 @@ bnxt_cfg_async_cr(struct bnxt_softc *softc)
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
|
||||
|
||||
req.fid = 0xffff;
|
||||
req.fid = htole16(0xffff);
|
||||
req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
|
||||
req.async_event_cr = softc->def_cp_ring.ring.phys_id;
|
||||
req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
|
||||
|
||||
rc = hwrm_send_message(softc, &req, sizeof(req));
|
||||
}
|
||||
@ -957,7 +988,7 @@ bnxt_cfg_async_cr(struct bnxt_softc *softc)
|
||||
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
|
||||
|
||||
req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
|
||||
req.async_event_cr = softc->def_cp_ring.ring.phys_id;
|
||||
req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
|
||||
|
||||
rc = hwrm_send_message(softc, &req, sizeof(req));
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define BNXT_PAUSE_RX (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
|
||||
#define BNXT_AUTO_PAUSE_AUTONEG_PAUSE \
|
||||
(HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE)
|
||||
#define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input)
|
||||
|
||||
/* HWRM Function Prototypes */
|
||||
int bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc);
|
||||
|
@ -74,14 +74,16 @@ bnxt_init_sysctl_ctx(struct bnxt_softc *softc)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
sysctl_ctx_init(&softc->nvm_info->nvm_ctx);
|
||||
ctx = device_get_sysctl_ctx(softc->dev);
|
||||
softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx,
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
|
||||
"nvram", CTLFLAG_RD, 0, "nvram information");
|
||||
if (!softc->nvm_info->nvm_oid) {
|
||||
sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
|
||||
return ENOMEM;
|
||||
if (BNXT_PF(softc)) {
|
||||
sysctl_ctx_init(&softc->nvm_info->nvm_ctx);
|
||||
ctx = device_get_sysctl_ctx(softc->dev);
|
||||
softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx,
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
|
||||
"nvram", CTLFLAG_RD, 0, "nvram information");
|
||||
if (!softc->nvm_info->nvm_oid) {
|
||||
sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
|
||||
return ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
sysctl_ctx_init(&softc->hw_lro_ctx);
|
||||
@ -127,7 +129,7 @@ bnxt_free_sysctl_ctx(struct bnxt_softc *softc)
|
||||
else
|
||||
softc->ver_info->ver_oid = NULL;
|
||||
}
|
||||
if (softc->nvm_info->nvm_oid != NULL) {
|
||||
if (BNXT_PF(softc) && softc->nvm_info->nvm_oid != NULL) {
|
||||
orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
|
||||
if (orc)
|
||||
rc = orc;
|
||||
|
@ -643,6 +643,23 @@ bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_free_hwrm_short_cmd_req(struct bnxt_softc *softc)
|
||||
{
|
||||
if (softc->hwrm_short_cmd_req_addr.idi_vaddr)
|
||||
iflib_dma_free(&softc->hwrm_short_cmd_req_addr);
|
||||
softc->hwrm_short_cmd_req_addr.idi_vaddr = NULL;
|
||||
}
|
||||
|
||||
static int bnxt_alloc_hwrm_short_cmd_req(struct bnxt_softc *softc)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = iflib_dma_alloc(softc->ctx, softc->hwrm_max_req_len,
|
||||
&softc->hwrm_short_cmd_req_addr, BUS_DMA_NOWAIT);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Device setup and teardown */
|
||||
static int
|
||||
bnxt_attach_pre(if_ctx_t ctx)
|
||||
@ -714,19 +731,28 @@ bnxt_attach_pre(if_ctx_t ctx)
|
||||
goto ver_fail;
|
||||
}
|
||||
|
||||
/* Get NVRAM info */
|
||||
softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info),
|
||||
M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (softc->nvm_info == NULL) {
|
||||
rc = ENOMEM;
|
||||
device_printf(softc->dev,
|
||||
"Unable to allocate space for NVRAM info\n");
|
||||
goto nvm_alloc_fail;
|
||||
if (softc->flags & BNXT_FLAG_SHORT_CMD) {
|
||||
rc = bnxt_alloc_hwrm_short_cmd_req(softc);
|
||||
if (rc)
|
||||
goto hwrm_short_cmd_alloc_fail;
|
||||
}
|
||||
|
||||
/* Get NVRAM info */
|
||||
if (BNXT_PF(softc)) {
|
||||
softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info),
|
||||
M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (softc->nvm_info == NULL) {
|
||||
rc = ENOMEM;
|
||||
device_printf(softc->dev,
|
||||
"Unable to allocate space for NVRAM info\n");
|
||||
goto nvm_alloc_fail;
|
||||
}
|
||||
|
||||
rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id,
|
||||
&softc->nvm_info->device_id, &softc->nvm_info->sector_size,
|
||||
&softc->nvm_info->size, &softc->nvm_info->reserved_size,
|
||||
&softc->nvm_info->available_size);
|
||||
}
|
||||
rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id,
|
||||
&softc->nvm_info->device_id, &softc->nvm_info->sector_size,
|
||||
&softc->nvm_info->size, &softc->nvm_info->reserved_size,
|
||||
&softc->nvm_info->available_size);
|
||||
|
||||
/* Register the driver with the FW */
|
||||
rc = bnxt_hwrm_func_drv_rgtr(softc);
|
||||
@ -859,9 +885,11 @@ bnxt_attach_pre(if_ctx_t ctx)
|
||||
rc = bnxt_init_sysctl_ctx(softc);
|
||||
if (rc)
|
||||
goto init_sysctl_failed;
|
||||
rc = bnxt_create_nvram_sysctls(softc->nvm_info);
|
||||
if (rc)
|
||||
goto failed;
|
||||
if (BNXT_PF(softc)) {
|
||||
rc = bnxt_create_nvram_sysctls(softc->nvm_info);
|
||||
if (rc)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0);
|
||||
softc->vnic_info.rss_hash_type =
|
||||
@ -894,8 +922,11 @@ bnxt_attach_pre(if_ctx_t ctx)
|
||||
init_sysctl_failed:
|
||||
bnxt_hwrm_func_drv_unrgtr(softc, false);
|
||||
drv_rgtr_fail:
|
||||
free(softc->nvm_info, M_DEVBUF);
|
||||
if (BNXT_PF(softc))
|
||||
free(softc->nvm_info, M_DEVBUF);
|
||||
nvm_alloc_fail:
|
||||
bnxt_free_hwrm_short_cmd_req(softc);
|
||||
hwrm_short_cmd_alloc_fail:
|
||||
ver_fail:
|
||||
free(softc->ver_info, M_DEVBUF);
|
||||
ver_alloc_fail:
|
||||
@ -963,10 +994,12 @@ bnxt_detach(if_ctx_t ctx)
|
||||
for (i = 0; i < softc->nrxqsets; i++)
|
||||
free(softc->rx_rings[i].tpa_start, M_DEVBUF);
|
||||
free(softc->ver_info, M_DEVBUF);
|
||||
free(softc->nvm_info, M_DEVBUF);
|
||||
if (BNXT_PF(softc))
|
||||
free(softc->nvm_info, M_DEVBUF);
|
||||
|
||||
bnxt_hwrm_func_drv_unrgtr(softc, false);
|
||||
bnxt_free_hwrm_dma_mem(softc);
|
||||
bnxt_free_hwrm_short_cmd_req(softc);
|
||||
BNXT_HWRM_LOCK_DESTROY(softc);
|
||||
|
||||
pci_disable_busmaster(softc->dev);
|
||||
@ -2052,8 +2085,13 @@ bnxt_add_media_types(struct bnxt_softc *softc)
|
||||
break;
|
||||
|
||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN:
|
||||
default:
|
||||
/* Only Autoneg is supported for TYPE_UNKNOWN */
|
||||
device_printf(softc->dev, "Unknown phy type\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Only Autoneg is supported for new phy type values */
|
||||
device_printf(softc->dev, "phy type %d not supported by driver\n", phy_type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2191,6 +2229,10 @@ bnxt_report_link(struct bnxt_softc *softc)
|
||||
link_info->last_flow_ctrl.tx = link_info->flow_ctrl.tx;
|
||||
link_info->last_flow_ctrl.rx = link_info->flow_ctrl.rx;
|
||||
link_info->last_flow_ctrl.autoneg = link_info->flow_ctrl.autoneg;
|
||||
/* update media types */
|
||||
ifmedia_removeall(softc->media);
|
||||
bnxt_add_media_types(softc);
|
||||
ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -120,3 +120,4 @@ extern devclass_t cs_devclass;
|
||||
DRIVER_MODULE(cs, isa, cs_isa_driver, cs_devclass, 0, 0);
|
||||
MODULE_DEPEND(cs, isa, 1, 1, 1);
|
||||
MODULE_DEPEND(cs, ether, 1, 1, 1);
|
||||
ISA_PNP_INFO(cs_ids);
|
||||
|
@ -169,9 +169,6 @@ enum {
|
||||
DOOMED = (1 << 0),
|
||||
VI_INIT_DONE = (1 << 1),
|
||||
VI_SYSCTL_CTX = (1 << 2),
|
||||
INTR_RXQ = (1 << 4), /* All NIC rxq's take interrupts */
|
||||
INTR_OFLD_RXQ = (1 << 5), /* All TOE rxq's take interrupts */
|
||||
INTR_ALL = (INTR_RXQ | INTR_OFLD_RXQ),
|
||||
|
||||
/* adapter debug_flags */
|
||||
DF_DUMP_MBOX = (1 << 0), /* Log all mbox cmd/rpl. */
|
||||
@ -349,7 +346,7 @@ enum {
|
||||
/* iq flags */
|
||||
IQ_ALLOCATED = (1 << 0), /* firmware resources allocated */
|
||||
IQ_HAS_FL = (1 << 1), /* iq associated with a freelist */
|
||||
IQ_INTR = (1 << 2), /* iq takes direct interrupt */
|
||||
/* 1 << 2 Used to be IQ_INTR */
|
||||
IQ_LRO_ENABLED = (1 << 3), /* iq is an eth rxq with LRO enabled */
|
||||
IQ_ADJ_CREDIT = (1 << 4), /* hw is off by 1 credit for this iq */
|
||||
|
||||
@ -956,6 +953,13 @@ struct adapter {
|
||||
/* One for firmware events */
|
||||
#define T4VF_EXTRA_INTR 1
|
||||
|
||||
static inline int
|
||||
forwarding_intr_to_fwq(struct adapter *sc)
|
||||
{
|
||||
|
||||
return (sc->intr_count == 1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
t4_read_reg(struct adapter *sc, uint32_t reg)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ enum {
|
||||
EC_LEN = 16, /* E/C length */
|
||||
ID_LEN = 16, /* ID length */
|
||||
PN_LEN = 16, /* Part Number length */
|
||||
MD_LEN = 16, /* MFG diags version length */
|
||||
MACADDR_LEN = 12, /* MAC Address length */
|
||||
};
|
||||
|
||||
@ -258,6 +259,7 @@ struct vpd_params {
|
||||
u8 id[ID_LEN + 1];
|
||||
u8 pn[PN_LEN + 1];
|
||||
u8 na[MACADDR_LEN + 1];
|
||||
u8 md[MD_LEN + 1];
|
||||
};
|
||||
|
||||
struct pci_params {
|
||||
@ -590,7 +592,7 @@ int t4_get_vpd_version(struct adapter *adapter, u32 *vers);
|
||||
int t4_get_version_info(struct adapter *adapter);
|
||||
int t4_init_hw(struct adapter *adapter, u32 fw_params);
|
||||
const struct chip_params *t4_get_chip_params(int chipid);
|
||||
int t4_prep_adapter(struct adapter *adapter, u8 *buf);
|
||||
int t4_prep_adapter(struct adapter *adapter, u32 *buf);
|
||||
int t4_shutdown_adapter(struct adapter *adapter);
|
||||
int t4_init_devlog_params(struct adapter *adapter, int fw_attach);
|
||||
int t4_init_sge_params(struct adapter *adapter);
|
||||
|
@ -2664,13 +2664,16 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
|
||||
}
|
||||
|
||||
/*
|
||||
* Partial EEPROM Vital Product Data structure. Includes only the ID and
|
||||
* VPD-R sections.
|
||||
* Partial EEPROM Vital Product Data structure. The VPD starts with one ID
|
||||
* header followed by one or more VPD-R sections, each with its own header.
|
||||
*/
|
||||
struct t4_vpd_hdr {
|
||||
u8 id_tag;
|
||||
u8 id_len[2];
|
||||
u8 id_data[ID_LEN];
|
||||
};
|
||||
|
||||
struct t4_vpdr_hdr {
|
||||
u8 vpdr_tag;
|
||||
u8 vpdr_len[2];
|
||||
};
|
||||
@ -2905,32 +2908,43 @@ int t4_seeprom_wp(struct adapter *adapter, int enable)
|
||||
|
||||
/**
|
||||
* get_vpd_keyword_val - Locates an information field keyword in the VPD
|
||||
* @v: Pointer to buffered vpd data structure
|
||||
* @vpd: Pointer to buffered vpd data structure
|
||||
* @kw: The keyword to search for
|
||||
* @region: VPD region to search (starting from 0)
|
||||
*
|
||||
* Returns the value of the information field keyword or
|
||||
* -ENOENT otherwise.
|
||||
*/
|
||||
static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
|
||||
static int get_vpd_keyword_val(const u8 *vpd, const char *kw, int region)
|
||||
{
|
||||
int i;
|
||||
unsigned int offset , len;
|
||||
const u8 *buf = (const u8 *)v;
|
||||
const u8 *vpdr_len = &v->vpdr_len[0];
|
||||
offset = sizeof(struct t4_vpd_hdr);
|
||||
len = (u16)vpdr_len[0] + ((u16)vpdr_len[1] << 8);
|
||||
int i, tag;
|
||||
unsigned int offset, len;
|
||||
const struct t4_vpdr_hdr *vpdr;
|
||||
|
||||
if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
|
||||
offset = sizeof(struct t4_vpd_hdr);
|
||||
vpdr = (const void *)(vpd + offset);
|
||||
tag = vpdr->vpdr_tag;
|
||||
len = (u16)vpdr->vpdr_len[0] + ((u16)vpdr->vpdr_len[1] << 8);
|
||||
while (region--) {
|
||||
offset += sizeof(struct t4_vpdr_hdr) + len;
|
||||
vpdr = (const void *)(vpd + offset);
|
||||
if (++tag != vpdr->vpdr_tag)
|
||||
return -ENOENT;
|
||||
len = (u16)vpdr->vpdr_len[0] + ((u16)vpdr->vpdr_len[1] << 8);
|
||||
}
|
||||
offset += sizeof(struct t4_vpdr_hdr);
|
||||
|
||||
if (offset + len > VPD_LEN) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
|
||||
if(memcmp(buf + i , kw , 2) == 0){
|
||||
if (memcmp(vpd + i , kw , 2) == 0){
|
||||
i += VPD_INFO_FLD_HDR_SIZE;
|
||||
return i;
|
||||
}
|
||||
|
||||
i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
|
||||
i += VPD_INFO_FLD_HDR_SIZE + vpd[i+2];
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
@ -2946,18 +2960,18 @@ static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
|
||||
* Reads card parameters stored in VPD EEPROM.
|
||||
*/
|
||||
static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
u8 *vpd)
|
||||
u32 *buf)
|
||||
{
|
||||
int i, ret, addr;
|
||||
int ec, sn, pn, na;
|
||||
int ec, sn, pn, na, md;
|
||||
u8 csum;
|
||||
const struct t4_vpd_hdr *v;
|
||||
const u8 *vpd = (const u8 *)buf;
|
||||
|
||||
/*
|
||||
* Card information normally starts at VPD_BASE but early cards had
|
||||
* it at 0.
|
||||
*/
|
||||
ret = t4_seeprom_read(adapter, VPD_BASE, (u32 *)(vpd));
|
||||
ret = t4_seeprom_read(adapter, VPD_BASE, buf);
|
||||
if (ret)
|
||||
return (ret);
|
||||
|
||||
@ -2971,14 +2985,13 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
|
||||
|
||||
for (i = 0; i < VPD_LEN; i += 4) {
|
||||
ret = t4_seeprom_read(adapter, addr + i, (u32 *)(vpd + i));
|
||||
ret = t4_seeprom_read(adapter, addr + i, buf++);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
v = (const struct t4_vpd_hdr *)vpd;
|
||||
|
||||
#define FIND_VPD_KW(var,name) do { \
|
||||
var = get_vpd_keyword_val(v , name); \
|
||||
var = get_vpd_keyword_val(vpd, name, 0); \
|
||||
if (var < 0) { \
|
||||
CH_ERR(adapter, "missing VPD keyword " name "\n"); \
|
||||
return -EINVAL; \
|
||||
@ -3001,7 +3014,7 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
FIND_VPD_KW(na, "NA");
|
||||
#undef FIND_VPD_KW
|
||||
|
||||
memcpy(p->id, v->id_data, ID_LEN);
|
||||
memcpy(p->id, vpd + offsetof(struct t4_vpd_hdr, id_data), ID_LEN);
|
||||
strstrip(p->id);
|
||||
memcpy(p->ec, vpd + ec, EC_LEN);
|
||||
strstrip(p->ec);
|
||||
@ -3015,6 +3028,14 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
memcpy(p->na, vpd + na, min(i, MACADDR_LEN));
|
||||
strstrip((char *)p->na);
|
||||
|
||||
md = get_vpd_keyword_val(vpd, "VF", 1);
|
||||
if (md < 0) {
|
||||
snprintf(p->md, sizeof(p->md), "unknown");
|
||||
} else {
|
||||
i = vpd[md - VPD_INFO_FLD_HDR_SIZE + 2];
|
||||
memcpy(p->md, vpd + md, min(i, MD_LEN));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -7997,7 +8018,7 @@ const struct chip_params *t4_get_chip_params(int chipid)
|
||||
* values for some adapter tunables, take PHYs out of reset, and
|
||||
* initialize the MDIO interface.
|
||||
*/
|
||||
int t4_prep_adapter(struct adapter *adapter, u8 *buf)
|
||||
int t4_prep_adapter(struct adapter *adapter, u32 *buf)
|
||||
{
|
||||
int ret;
|
||||
uint16_t device_id;
|
||||
|
@ -470,7 +470,6 @@ struct intrs_and_queues {
|
||||
uint16_t intr_type; /* INTx, MSI, or MSI-X */
|
||||
uint16_t num_vis; /* number of VIs for each port */
|
||||
uint16_t nirq; /* Total # of vectors */
|
||||
uint16_t intr_flags; /* Interrupt flags for each port */
|
||||
uint16_t ntxq; /* # of NIC txq's for each port */
|
||||
uint16_t nrxq; /* # of NIC rxq's for each port */
|
||||
uint16_t nofldtxq; /* # of TOE txq's for each port */
|
||||
@ -836,7 +835,7 @@ t4_attach(device_t dev)
|
||||
struct make_dev_args mda;
|
||||
struct intrs_and_queues iaq;
|
||||
struct sge *s;
|
||||
uint8_t *buf;
|
||||
uint32_t *buf;
|
||||
#ifdef TCP_OFFLOAD
|
||||
int ofld_rqidx, ofld_tqidx;
|
||||
#endif
|
||||
@ -1118,7 +1117,6 @@ t4_attach(device_t dev)
|
||||
vi->first_txq = tqidx;
|
||||
vi->tmr_idx = t4_tmr_idx;
|
||||
vi->pktc_idx = t4_pktc_idx;
|
||||
vi->flags |= iaq.intr_flags & INTR_RXQ;
|
||||
vi->nrxq = j == 0 ? iaq.nrxq : iaq.nrxq_vi;
|
||||
vi->ntxq = j == 0 ? iaq.ntxq : iaq.ntxq_vi;
|
||||
|
||||
@ -1135,7 +1133,6 @@ t4_attach(device_t dev)
|
||||
vi->ofld_pktc_idx = t4_pktc_idx_ofld;
|
||||
vi->first_ofld_rxq = ofld_rqidx;
|
||||
vi->first_ofld_txq = ofld_tqidx;
|
||||
vi->flags |= iaq.intr_flags & INTR_OFLD_RXQ;
|
||||
vi->nofldrxq = j == 0 ? iaq.nofldrxq : iaq.nofldrxq_vi;
|
||||
vi->nofldtxq = j == 0 ? iaq.nofldtxq : iaq.nofldtxq_vi;
|
||||
|
||||
@ -2648,26 +2645,43 @@ fixup_devlog_params(struct adapter *sc)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
static void
|
||||
update_nirq(struct intrs_and_queues *iaq, int nports)
|
||||
{
|
||||
int rc, itype, navail, nrxq, nports, n;
|
||||
int nofldrxq = 0;
|
||||
int extra = T4_EXTRA_INTR;
|
||||
|
||||
iaq->nirq = extra;
|
||||
iaq->nirq += nports * (iaq->nrxq + iaq->nofldrxq);
|
||||
iaq->nirq += nports * (iaq->num_vis - 1) *
|
||||
max(iaq->nrxq_vi, iaq->nnmrxq_vi);
|
||||
iaq->nirq += nports * (iaq->num_vis - 1) * iaq->nofldrxq_vi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust requirements to fit the number of interrupts available.
|
||||
*/
|
||||
static void
|
||||
calculate_iaq(struct adapter *sc, struct intrs_and_queues *iaq, int itype,
|
||||
int navail)
|
||||
{
|
||||
int old_nirq;
|
||||
const int nports = sc->params.nports;
|
||||
|
||||
nports = sc->params.nports;
|
||||
MPASS(nports > 0);
|
||||
MPASS(navail > 0);
|
||||
|
||||
bzero(iaq, sizeof(*iaq));
|
||||
iaq->intr_type = itype;
|
||||
iaq->num_vis = t4_num_vis;
|
||||
iaq->ntxq = t4_ntxq;
|
||||
iaq->ntxq_vi = t4_ntxq_vi;
|
||||
iaq->nrxq = nrxq = t4_nrxq;
|
||||
iaq->nrxq = t4_nrxq;
|
||||
iaq->nrxq_vi = t4_nrxq_vi;
|
||||
#ifdef TCP_OFFLOAD
|
||||
if (is_offload(sc)) {
|
||||
iaq->nofldtxq = t4_nofldtxq;
|
||||
iaq->nofldtxq_vi = t4_nofldtxq_vi;
|
||||
iaq->nofldrxq = nofldrxq = t4_nofldrxq;
|
||||
iaq->nofldrxq = t4_nofldrxq;
|
||||
iaq->nofldrxq_vi = t4_nofldrxq_vi;
|
||||
}
|
||||
#endif
|
||||
@ -2676,6 +2690,105 @@ cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
iaq->nnmrxq_vi = t4_nnmrxq_vi;
|
||||
#endif
|
||||
|
||||
update_nirq(iaq, nports);
|
||||
if (iaq->nirq <= navail &&
|
||||
(itype != INTR_MSI || powerof2(iaq->nirq))) {
|
||||
/*
|
||||
* This is the normal case -- there are enough interrupts for
|
||||
* everything.
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* If extra VIs have been configured try reducing their count and see if
|
||||
* that works.
|
||||
*/
|
||||
while (iaq->num_vis > 1) {
|
||||
iaq->num_vis--;
|
||||
update_nirq(iaq, nports);
|
||||
if (iaq->nirq <= navail &&
|
||||
(itype != INTR_MSI || powerof2(iaq->nirq))) {
|
||||
device_printf(sc->dev, "virtual interfaces per port "
|
||||
"reduced to %d from %d. nrxq=%u, nofldrxq=%u, "
|
||||
"nrxq_vi=%u nofldrxq_vi=%u, nnmrxq_vi=%u. "
|
||||
"itype %d, navail %u, nirq %d.\n",
|
||||
iaq->num_vis, t4_num_vis, iaq->nrxq, iaq->nofldrxq,
|
||||
iaq->nrxq_vi, iaq->nofldrxq_vi, iaq->nnmrxq_vi,
|
||||
itype, navail, iaq->nirq);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extra VIs will not be created. Log a message if they were requested.
|
||||
*/
|
||||
MPASS(iaq->num_vis == 1);
|
||||
iaq->ntxq_vi = iaq->nrxq_vi = 0;
|
||||
iaq->nofldtxq_vi = iaq->nofldrxq_vi = 0;
|
||||
iaq->nnmtxq_vi = iaq->nnmrxq_vi = 0;
|
||||
if (iaq->num_vis != t4_num_vis) {
|
||||
device_printf(sc->dev, "extra virtual interfaces disabled. "
|
||||
"nrxq=%u, nofldrxq=%u, nrxq_vi=%u nofldrxq_vi=%u, "
|
||||
"nnmrxq_vi=%u. itype %d, navail %u, nirq %d.\n",
|
||||
iaq->nrxq, iaq->nofldrxq, iaq->nrxq_vi, iaq->nofldrxq_vi,
|
||||
iaq->nnmrxq_vi, itype, navail, iaq->nirq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep reducing the number of NIC rx queues to the next lower power of
|
||||
* 2 (for even RSS distribution) and halving the TOE rx queues and see
|
||||
* if that works.
|
||||
*/
|
||||
do {
|
||||
if (iaq->nrxq > 1) {
|
||||
do {
|
||||
iaq->nrxq--;
|
||||
} while (!powerof2(iaq->nrxq));
|
||||
}
|
||||
if (iaq->nofldrxq > 1)
|
||||
iaq->nofldrxq >>= 1;
|
||||
|
||||
old_nirq = iaq->nirq;
|
||||
update_nirq(iaq, nports);
|
||||
if (iaq->nirq <= navail &&
|
||||
(itype != INTR_MSI || powerof2(iaq->nirq))) {
|
||||
device_printf(sc->dev, "running with reduced number of "
|
||||
"rx queues because of shortage of interrupts. "
|
||||
"nrxq=%u, nofldrxq=%u. "
|
||||
"itype %d, navail %u, nirq %d.\n", iaq->nrxq,
|
||||
iaq->nofldrxq, itype, navail, iaq->nirq);
|
||||
goto done;
|
||||
}
|
||||
} while (old_nirq != iaq->nirq);
|
||||
|
||||
/* One interrupt for everything. Ugh. */
|
||||
device_printf(sc->dev, "running with minimal number of queues. "
|
||||
"itype %d, navail %u.\n", itype, navail);
|
||||
iaq->nirq = 1;
|
||||
MPASS(iaq->nrxq == 1);
|
||||
iaq->ntxq = 1;
|
||||
if (iaq->nofldrxq > 1)
|
||||
iaq->nofldtxq = 1;
|
||||
done:
|
||||
MPASS(iaq->num_vis > 0);
|
||||
if (iaq->num_vis > 1) {
|
||||
MPASS(iaq->nrxq_vi > 0);
|
||||
MPASS(iaq->ntxq_vi > 0);
|
||||
}
|
||||
MPASS(iaq->nirq > 0);
|
||||
MPASS(iaq->nrxq > 0);
|
||||
MPASS(iaq->ntxq > 0);
|
||||
if (itype == INTR_MSI) {
|
||||
MPASS(powerof2(iaq->nirq));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
{
|
||||
int rc, itype, navail, nalloc;
|
||||
|
||||
for (itype = INTR_MSIX; itype; itype >>= 1) {
|
||||
|
||||
if ((itype & t4_intr_types) == 0)
|
||||
@ -2691,126 +2804,33 @@ cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
if (navail == 0)
|
||||
continue;
|
||||
|
||||
iaq->intr_type = itype;
|
||||
iaq->intr_flags = 0;
|
||||
|
||||
/*
|
||||
* Best option: an interrupt vector for errors, one for the
|
||||
* firmware event queue, and one for every rxq (NIC and TOE) of
|
||||
* every VI. The VIs that support netmap use the same
|
||||
* interrupts for the NIC rx queues and the netmap rx queues
|
||||
* because only one set of queues is active at a time.
|
||||
*/
|
||||
iaq->nirq = T4_EXTRA_INTR;
|
||||
iaq->nirq += nports * (nrxq + nofldrxq);
|
||||
iaq->nirq += nports * (iaq->num_vis - 1) *
|
||||
max(iaq->nrxq_vi, iaq->nnmrxq_vi); /* See comment above. */
|
||||
iaq->nirq += nports * (iaq->num_vis - 1) * iaq->nofldrxq_vi;
|
||||
if (iaq->nirq <= navail &&
|
||||
(itype != INTR_MSI || powerof2(iaq->nirq))) {
|
||||
iaq->intr_flags = INTR_ALL;
|
||||
goto allocate;
|
||||
}
|
||||
|
||||
/* Disable the VIs (and netmap) if there aren't enough intrs */
|
||||
if (iaq->num_vis > 1) {
|
||||
device_printf(sc->dev, "virtual interfaces disabled "
|
||||
"because num_vis=%u with current settings "
|
||||
"(nrxq=%u, nofldrxq=%u, nrxq_vi=%u nofldrxq_vi=%u, "
|
||||
"nnmrxq_vi=%u) would need %u interrupts but "
|
||||
"only %u are available.\n", iaq->num_vis, nrxq,
|
||||
nofldrxq, iaq->nrxq_vi, iaq->nofldrxq_vi,
|
||||
iaq->nnmrxq_vi, iaq->nirq, navail);
|
||||
iaq->num_vis = 1;
|
||||
iaq->ntxq_vi = iaq->nrxq_vi = 0;
|
||||
iaq->nofldtxq_vi = iaq->nofldrxq_vi = 0;
|
||||
iaq->nnmtxq_vi = iaq->nnmrxq_vi = 0;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second best option: a vector for errors, one for the firmware
|
||||
* event queue, and vectors for either all the NIC rx queues or
|
||||
* all the TOE rx queues. The queues that don't get vectors
|
||||
* will forward their interrupts to those that do.
|
||||
*/
|
||||
iaq->nirq = T4_EXTRA_INTR;
|
||||
if (nrxq >= nofldrxq) {
|
||||
iaq->intr_flags = INTR_RXQ;
|
||||
iaq->nirq += nports * nrxq;
|
||||
} else {
|
||||
iaq->intr_flags = INTR_OFLD_RXQ;
|
||||
iaq->nirq += nports * nofldrxq;
|
||||
}
|
||||
if (iaq->nirq <= navail &&
|
||||
(itype != INTR_MSI || powerof2(iaq->nirq)))
|
||||
goto allocate;
|
||||
|
||||
/*
|
||||
* Next best option: an interrupt vector for errors, one for the
|
||||
* firmware event queue, and at least one per main-VI. At this
|
||||
* point we know we'll have to downsize nrxq and/or nofldrxq to
|
||||
* fit what's available to us.
|
||||
*/
|
||||
iaq->nirq = T4_EXTRA_INTR;
|
||||
iaq->nirq += nports;
|
||||
if (iaq->nirq <= navail) {
|
||||
int leftover = navail - iaq->nirq;
|
||||
int target = max(nrxq, nofldrxq);
|
||||
|
||||
iaq->intr_flags = nrxq >= nofldrxq ?
|
||||
INTR_RXQ : INTR_OFLD_RXQ;
|
||||
|
||||
n = 1;
|
||||
while (n < target && leftover >= nports) {
|
||||
leftover -= nports;
|
||||
iaq->nirq += nports;
|
||||
n++;
|
||||
}
|
||||
iaq->nrxq = min(n, nrxq);
|
||||
#ifdef TCP_OFFLOAD
|
||||
iaq->nofldrxq = min(n, nofldrxq);
|
||||
#endif
|
||||
|
||||
if (itype != INTR_MSI || powerof2(iaq->nirq))
|
||||
goto allocate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Least desirable option: one interrupt vector for everything.
|
||||
*/
|
||||
iaq->nirq = iaq->nrxq = 1;
|
||||
iaq->intr_flags = 0;
|
||||
#ifdef TCP_OFFLOAD
|
||||
if (is_offload(sc))
|
||||
iaq->nofldrxq = 1;
|
||||
#endif
|
||||
allocate:
|
||||
navail = iaq->nirq;
|
||||
calculate_iaq(sc, iaq, itype, navail);
|
||||
nalloc = iaq->nirq;
|
||||
rc = 0;
|
||||
if (itype == INTR_MSIX)
|
||||
rc = pci_alloc_msix(sc->dev, &navail);
|
||||
rc = pci_alloc_msix(sc->dev, &nalloc);
|
||||
else if (itype == INTR_MSI)
|
||||
rc = pci_alloc_msi(sc->dev, &navail);
|
||||
rc = pci_alloc_msi(sc->dev, &nalloc);
|
||||
|
||||
if (rc == 0) {
|
||||
if (navail == iaq->nirq)
|
||||
if (rc == 0 && nalloc > 0) {
|
||||
if (nalloc == iaq->nirq)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Didn't get the number requested. Use whatever number
|
||||
* the kernel is willing to allocate (it's in navail).
|
||||
* the kernel is willing to allocate.
|
||||
*/
|
||||
device_printf(sc->dev, "fewer vectors than requested, "
|
||||
"type=%d, req=%d, rcvd=%d; will downshift req.\n",
|
||||
itype, iaq->nirq, navail);
|
||||
itype, iaq->nirq, nalloc);
|
||||
pci_release_msi(sc->dev);
|
||||
navail = nalloc;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
device_printf(sc->dev,
|
||||
"failed to allocate vectors:%d, type=%d, req=%d, rcvd=%d\n",
|
||||
itype, rc, iaq->nirq, navail);
|
||||
itype, rc, iaq->nirq, nalloc);
|
||||
}
|
||||
|
||||
device_printf(sc->dev,
|
||||
@ -4352,7 +4372,7 @@ t4_setup_intr_handlers(struct adapter *sc)
|
||||
*/
|
||||
irq = &sc->irq[0];
|
||||
rid = sc->intr_type == INTR_INTX ? 0 : 1;
|
||||
if (sc->intr_count == 1)
|
||||
if (forwarding_intr_to_fwq(sc))
|
||||
return (t4_alloc_irq(sc, irq, rid, t4_intr_all, sc, "all"));
|
||||
|
||||
/* Multiple interrupts. */
|
||||
@ -4387,8 +4407,6 @@ t4_setup_intr_handlers(struct adapter *sc)
|
||||
if (vi->nnmrxq > 0) {
|
||||
int n = max(vi->nrxq, vi->nnmrxq);
|
||||
|
||||
MPASS(vi->flags & INTR_RXQ);
|
||||
|
||||
rxq = &sge->rxq[vi->first_rxq];
|
||||
#ifdef DEV_NETMAP
|
||||
nm_rxq = &sge->nm_rxq[vi->first_nm_rxq];
|
||||
@ -4406,11 +4424,17 @@ t4_setup_intr_handlers(struct adapter *sc)
|
||||
t4_vi_intr, irq, s);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
#ifdef RSS
|
||||
if (q < vi->nrxq) {
|
||||
bus_bind_intr(sc->dev, irq->res,
|
||||
rss_getcpu(q % nbuckets));
|
||||
}
|
||||
#endif
|
||||
irq++;
|
||||
rid++;
|
||||
vi->nintr++;
|
||||
}
|
||||
} else if (vi->flags & INTR_RXQ) {
|
||||
} else {
|
||||
for_each_rxq(vi, q, rxq) {
|
||||
snprintf(s, sizeof(s), "%x%c%x", p,
|
||||
'a' + v, q);
|
||||
@ -4428,18 +4452,15 @@ t4_setup_intr_handlers(struct adapter *sc)
|
||||
}
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
if (vi->flags & INTR_OFLD_RXQ) {
|
||||
for_each_ofld_rxq(vi, q, ofld_rxq) {
|
||||
snprintf(s, sizeof(s), "%x%c%x", p,
|
||||
'A' + v, q);
|
||||
rc = t4_alloc_irq(sc, irq, rid,
|
||||
t4_intr, ofld_rxq, s);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
irq++;
|
||||
rid++;
|
||||
vi->nintr++;
|
||||
}
|
||||
for_each_ofld_rxq(vi, q, ofld_rxq) {
|
||||
snprintf(s, sizeof(s), "%x%c%x", p, 'A' + v, q);
|
||||
rc = t4_alloc_irq(sc, irq, rid, t4_intr,
|
||||
ofld_rxq, s);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
irq++;
|
||||
rid++;
|
||||
vi->nintr++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -5127,6 +5148,9 @@ t4_sysctls(struct adapter *sc)
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "ec",
|
||||
CTLFLAG_RD, sc->params.vpd.ec, 0, "engineering change");
|
||||
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "md_version",
|
||||
CTLFLAG_RD, sc->params.vpd.md, 0, "manufacturing diags version");
|
||||
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "na",
|
||||
CTLFLAG_RD, sc->params.vpd.na, 0, "network address");
|
||||
|
||||
|
@ -108,16 +108,10 @@ alloc_nm_rxq_hwq(struct vi_info *vi, struct sge_nm_rxq *nm_rxq, int cong)
|
||||
V_FW_IQ_CMD_VFN(0));
|
||||
c.alloc_to_len16 = htobe32(F_FW_IQ_CMD_ALLOC | F_FW_IQ_CMD_IQSTART |
|
||||
FW_LEN16(c));
|
||||
if (vi->flags & INTR_RXQ) {
|
||||
KASSERT(nm_rxq->intr_idx < sc->intr_count,
|
||||
("%s: invalid direct intr_idx %d", __func__,
|
||||
nm_rxq->intr_idx));
|
||||
v = V_FW_IQ_CMD_IQANDSTINDEX(nm_rxq->intr_idx);
|
||||
} else {
|
||||
CXGBE_UNIMPLEMENTED(__func__); /* XXXNM: needs review */
|
||||
v = V_FW_IQ_CMD_IQANDSTINDEX(nm_rxq->intr_idx) |
|
||||
F_FW_IQ_CMD_IQANDST;
|
||||
}
|
||||
MPASS(!forwarding_intr_to_fwq(sc));
|
||||
KASSERT(nm_rxq->intr_idx < sc->intr_count,
|
||||
("%s: invalid direct intr_idx %d", __func__, nm_rxq->intr_idx));
|
||||
v = V_FW_IQ_CMD_IQANDSTINDEX(nm_rxq->intr_idx);
|
||||
c.type_to_iqandstindex = htobe32(v |
|
||||
V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) |
|
||||
V_FW_IQ_CMD_VIID(vi->viid) |
|
||||
|
@ -953,70 +953,6 @@ t4_teardown_adapter_queues(struct adapter *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
first_vector(struct vi_info *vi)
|
||||
{
|
||||
struct adapter *sc = vi->pi->adapter;
|
||||
|
||||
if (sc->intr_count == 1)
|
||||
return (0);
|
||||
|
||||
return (vi->first_intr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an arbitrary "index," come up with an iq that can be used by other
|
||||
* queues (of this VI) for interrupt forwarding, SGE egress updates, etc.
|
||||
* The iq returned is guaranteed to be something that takes direct interrupts.
|
||||
*/
|
||||
static struct sge_iq *
|
||||
vi_intr_iq(struct vi_info *vi, int idx)
|
||||
{
|
||||
struct adapter *sc = vi->pi->adapter;
|
||||
struct sge *s = &sc->sge;
|
||||
struct sge_iq *iq = NULL;
|
||||
int nintr, i;
|
||||
|
||||
if (sc->intr_count == 1)
|
||||
return (&sc->sge.fwq);
|
||||
|
||||
nintr = vi->nintr;
|
||||
#ifdef DEV_NETMAP
|
||||
/* Do not consider any netmap-only interrupts */
|
||||
if (vi->flags & INTR_RXQ && vi->nnmrxq > vi->nrxq)
|
||||
nintr -= vi->nnmrxq - vi->nrxq;
|
||||
#endif
|
||||
KASSERT(nintr != 0,
|
||||
("%s: vi %p has no exclusive interrupts, total interrupts = %d",
|
||||
__func__, vi, sc->intr_count));
|
||||
i = idx % nintr;
|
||||
|
||||
if (vi->flags & INTR_RXQ) {
|
||||
if (i < vi->nrxq) {
|
||||
iq = &s->rxq[vi->first_rxq + i].iq;
|
||||
goto done;
|
||||
}
|
||||
i -= vi->nrxq;
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
if (vi->flags & INTR_OFLD_RXQ) {
|
||||
if (i < vi->nofldrxq) {
|
||||
iq = &s->ofld_rxq[vi->first_ofld_rxq + i].iq;
|
||||
goto done;
|
||||
}
|
||||
i -= vi->nofldrxq;
|
||||
}
|
||||
#endif
|
||||
panic("%s: vi %p, intr_flags 0x%lx, idx %d, total intr %d\n", __func__,
|
||||
vi, vi->flags & INTR_ALL, idx, nintr);
|
||||
done:
|
||||
MPASS(iq != NULL);
|
||||
KASSERT(iq->flags & IQ_INTR,
|
||||
("%s: iq %p (vi %p, intr_flags 0x%lx, idx %d)", __func__, iq, vi,
|
||||
vi->flags & INTR_ALL, idx));
|
||||
return (iq);
|
||||
}
|
||||
|
||||
/* Maximum payload that can be delivered with a single iq descriptor */
|
||||
static inline int
|
||||
mtu_to_max_payload(struct adapter *sc, int mtu, const int toe)
|
||||
@ -1042,7 +978,7 @@ mtu_to_max_payload(struct adapter *sc, int mtu, const int toe)
|
||||
int
|
||||
t4_setup_vi_queues(struct vi_info *vi)
|
||||
{
|
||||
int rc = 0, i, j, intr_idx, iqid;
|
||||
int rc = 0, i, intr_idx, iqidx;
|
||||
struct sge_rxq *rxq;
|
||||
struct sge_txq *txq;
|
||||
struct sge_wrq *ctrlq;
|
||||
@ -1064,14 +1000,14 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
int maxp, mtu = ifp->if_mtu;
|
||||
|
||||
/* Interrupt vector to start from (when using multiple vectors) */
|
||||
intr_idx = first_vector(vi);
|
||||
intr_idx = vi->first_intr;
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
saved_idx = intr_idx;
|
||||
if (ifp->if_capabilities & IFCAP_NETMAP) {
|
||||
|
||||
/* netmap is supported with direct interrupts only. */
|
||||
MPASS(vi->flags & INTR_RXQ);
|
||||
MPASS(!forwarding_intr_to_fwq(sc));
|
||||
|
||||
/*
|
||||
* We don't have buffers to back the netmap rx queues
|
||||
@ -1090,8 +1026,8 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "nm_txq",
|
||||
CTLFLAG_RD, NULL, "tx queues");
|
||||
for_each_nm_txq(vi, i, nm_txq) {
|
||||
iqid = vi->first_nm_rxq + (i % vi->nnmrxq);
|
||||
rc = alloc_nm_txq(vi, nm_txq, iqid, i, oid);
|
||||
iqidx = vi->first_nm_rxq + (i % vi->nnmrxq);
|
||||
rc = alloc_nm_txq(vi, nm_txq, iqidx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
}
|
||||
@ -1102,15 +1038,12 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* First pass over all NIC and TOE rx queues:
|
||||
* a) initialize iq and fl
|
||||
* b) allocate queue iff it will take direct interrupts.
|
||||
* Allocate rx queues first because a default iqid is required when
|
||||
* creating a tx queue.
|
||||
*/
|
||||
maxp = mtu_to_max_payload(sc, mtu, 0);
|
||||
if (vi->flags & INTR_RXQ) {
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "rxq",
|
||||
CTLFLAG_RD, NULL, "rx queues");
|
||||
}
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "rxq",
|
||||
CTLFLAG_RD, NULL, "rx queues");
|
||||
for_each_rxq(vi, i, rxq) {
|
||||
|
||||
init_iq(&rxq->iq, sc, vi->tmr_idx, vi->pktc_idx, vi->qsize_rxq);
|
||||
@ -1119,13 +1052,11 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
device_get_nameunit(vi->dev), i);
|
||||
init_fl(sc, &rxq->fl, vi->qsize_rxq / 8, maxp, name);
|
||||
|
||||
if (vi->flags & INTR_RXQ) {
|
||||
rxq->iq.flags |= IQ_INTR;
|
||||
rc = alloc_rxq(vi, rxq, intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
intr_idx++;
|
||||
}
|
||||
rc = alloc_rxq(vi, rxq,
|
||||
forwarding_intr_to_fwq(sc) ? -1 : intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
intr_idx++;
|
||||
}
|
||||
#ifdef DEV_NETMAP
|
||||
if (ifp->if_capabilities & IFCAP_NETMAP)
|
||||
@ -1133,11 +1064,8 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
#endif
|
||||
#ifdef TCP_OFFLOAD
|
||||
maxp = mtu_to_max_payload(sc, mtu, 1);
|
||||
if (vi->flags & INTR_OFLD_RXQ) {
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ofld_rxq",
|
||||
CTLFLAG_RD, NULL,
|
||||
"rx queues for offloaded TCP connections");
|
||||
}
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ofld_rxq",
|
||||
CTLFLAG_RD, NULL, "rx queues for offloaded TCP connections");
|
||||
for_each_ofld_rxq(vi, i, ofld_rxq) {
|
||||
|
||||
init_iq(&ofld_rxq->iq, sc, vi->ofld_tmr_idx, vi->ofld_pktc_idx,
|
||||
@ -1147,70 +1075,29 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
device_get_nameunit(vi->dev), i);
|
||||
init_fl(sc, &ofld_rxq->fl, vi->qsize_rxq / 8, maxp, name);
|
||||
|
||||
if (vi->flags & INTR_OFLD_RXQ) {
|
||||
ofld_rxq->iq.flags |= IQ_INTR;
|
||||
rc = alloc_ofld_rxq(vi, ofld_rxq, intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
intr_idx++;
|
||||
}
|
||||
rc = alloc_ofld_rxq(vi, ofld_rxq,
|
||||
forwarding_intr_to_fwq(sc) ? -1 : intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
intr_idx++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Second pass over all NIC and TOE rx queues. The queues forwarding
|
||||
* their interrupts are allocated now.
|
||||
*/
|
||||
j = 0;
|
||||
if (!(vi->flags & INTR_RXQ)) {
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "rxq",
|
||||
CTLFLAG_RD, NULL, "rx queues");
|
||||
for_each_rxq(vi, i, rxq) {
|
||||
MPASS(!(rxq->iq.flags & IQ_INTR));
|
||||
|
||||
intr_idx = vi_intr_iq(vi, j)->abs_id;
|
||||
|
||||
rc = alloc_rxq(vi, rxq, intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
if (vi->nofldrxq != 0 && !(vi->flags & INTR_OFLD_RXQ)) {
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ofld_rxq",
|
||||
CTLFLAG_RD, NULL,
|
||||
"rx queues for offloaded TCP connections");
|
||||
for_each_ofld_rxq(vi, i, ofld_rxq) {
|
||||
MPASS(!(ofld_rxq->iq.flags & IQ_INTR));
|
||||
|
||||
intr_idx = vi_intr_iq(vi, j)->abs_id;
|
||||
|
||||
rc = alloc_ofld_rxq(vi, ofld_rxq, intr_idx, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now the tx queues. Only one pass needed.
|
||||
* Now the tx queues.
|
||||
*/
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "txq", CTLFLAG_RD,
|
||||
NULL, "tx queues");
|
||||
j = 0;
|
||||
for_each_txq(vi, i, txq) {
|
||||
iqid = vi_intr_iq(vi, j)->cntxt_id;
|
||||
iqidx = vi->first_rxq + (i % vi->nrxq);
|
||||
snprintf(name, sizeof(name), "%s txq%d",
|
||||
device_get_nameunit(vi->dev), i);
|
||||
init_eq(sc, &txq->eq, EQ_ETH, vi->qsize_txq, pi->tx_chan, iqid,
|
||||
name);
|
||||
init_eq(sc, &txq->eq, EQ_ETH, vi->qsize_txq, pi->tx_chan,
|
||||
sc->sge.rxq[iqidx].iq.cntxt_id, name);
|
||||
|
||||
rc = alloc_txq(vi, txq, i, oid);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
j++;
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ofld_txq",
|
||||
@ -1218,11 +1105,11 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
for_each_ofld_txq(vi, i, ofld_txq) {
|
||||
struct sysctl_oid *oid2;
|
||||
|
||||
iqid = vi_intr_iq(vi, j)->cntxt_id;
|
||||
iqidx = vi->first_ofld_rxq + (i % vi->nofldrxq);
|
||||
snprintf(name, sizeof(name), "%s ofld_txq%d",
|
||||
device_get_nameunit(vi->dev), i);
|
||||
init_eq(sc, &ofld_txq->eq, EQ_OFLD, vi->qsize_txq, pi->tx_chan,
|
||||
iqid, name);
|
||||
sc->sge.ofld_rxq[iqidx].iq.cntxt_id, name);
|
||||
|
||||
snprintf(name, sizeof(name), "%d", i);
|
||||
oid2 = SYSCTL_ADD_NODE(&vi->ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
|
||||
@ -1231,7 +1118,6 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
rc = alloc_wrq(sc, vi, ofld_txq, oid2);
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
j++;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1243,10 +1129,9 @@ t4_setup_vi_queues(struct vi_info *vi)
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ctrlq", CTLFLAG_RD,
|
||||
NULL, "ctrl queue");
|
||||
ctrlq = &sc->sge.ctrlq[pi->port_id];
|
||||
iqid = vi_intr_iq(vi, 0)->cntxt_id;
|
||||
snprintf(name, sizeof(name), "%s ctrlq", device_get_nameunit(vi->dev));
|
||||
init_eq(sc, &ctrlq->eq, EQ_CTRL, CTRL_EQ_QSIZE, pi->tx_chan, iqid,
|
||||
name);
|
||||
init_eq(sc, &ctrlq->eq, EQ_CTRL, CTRL_EQ_QSIZE, pi->tx_chan,
|
||||
sc->sge.rxq[vi->first_rxq].iq.cntxt_id, name);
|
||||
rc = alloc_wrq(sc, vi, ctrlq, oid);
|
||||
|
||||
done:
|
||||
@ -1312,33 +1197,15 @@ t4_teardown_vi_queues(struct vi_info *vi)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Then take down the rx queues that forward their interrupts, as they
|
||||
* reference other rx queues.
|
||||
* Then take down the rx queues.
|
||||
*/
|
||||
|
||||
for_each_rxq(vi, i, rxq) {
|
||||
if ((rxq->iq.flags & IQ_INTR) == 0)
|
||||
free_rxq(vi, rxq);
|
||||
free_rxq(vi, rxq);
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
for_each_ofld_rxq(vi, i, ofld_rxq) {
|
||||
if ((ofld_rxq->iq.flags & IQ_INTR) == 0)
|
||||
free_ofld_rxq(vi, ofld_rxq);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Then take down the rx queues that take direct interrupts.
|
||||
*/
|
||||
|
||||
for_each_rxq(vi, i, rxq) {
|
||||
if (rxq->iq.flags & IQ_INTR)
|
||||
free_rxq(vi, rxq);
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
for_each_ofld_rxq(vi, i, ofld_rxq) {
|
||||
if (ofld_rxq->iq.flags & IQ_INTR)
|
||||
free_ofld_rxq(vi, ofld_rxq);
|
||||
free_ofld_rxq(vi, ofld_rxq);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2715,9 +2582,9 @@ free_ring(struct adapter *sc, bus_dma_tag_t tag, bus_dmamap_t map,
|
||||
* Returns errno on failure. Resources allocated up to that point may still be
|
||||
* allocated. Caller is responsible for cleanup in case this function fails.
|
||||
*
|
||||
* If the ingress queue will take interrupts directly (iq->flags & IQ_INTR) then
|
||||
* the intr_idx specifies the vector, starting from 0. Otherwise it specifies
|
||||
* the abs_id of the ingress queue to which its interrupts should be forwarded.
|
||||
* If the ingress queue will take interrupts directly then the intr_idx
|
||||
* specifies the vector, starting from 0. -1 means the interrupts for this
|
||||
* queue should be forwarded to the fwq.
|
||||
*/
|
||||
static int
|
||||
alloc_iq_fl(struct vi_info *vi, struct sge_iq *iq, struct sge_fl *fl,
|
||||
@ -2749,12 +2616,15 @@ alloc_iq_fl(struct vi_info *vi, struct sge_iq *iq, struct sge_fl *fl,
|
||||
if (iq == &sc->sge.fwq)
|
||||
v |= F_FW_IQ_CMD_IQASYNCH;
|
||||
|
||||
if (iq->flags & IQ_INTR) {
|
||||
if (intr_idx < 0) {
|
||||
/* Forwarded interrupts, all headed to fwq */
|
||||
v |= F_FW_IQ_CMD_IQANDST;
|
||||
v |= V_FW_IQ_CMD_IQANDSTINDEX(sc->sge.fwq.cntxt_id);
|
||||
} else {
|
||||
KASSERT(intr_idx < sc->intr_count,
|
||||
("%s: invalid direct intr_idx %d", __func__, intr_idx));
|
||||
} else
|
||||
v |= F_FW_IQ_CMD_IQANDST;
|
||||
v |= V_FW_IQ_CMD_IQANDSTINDEX(intr_idx);
|
||||
v |= V_FW_IQ_CMD_IQANDSTINDEX(intr_idx);
|
||||
}
|
||||
|
||||
c.type_to_iqandstindex = htobe32(v |
|
||||
V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) |
|
||||
@ -3004,7 +2874,6 @@ alloc_fwq(struct adapter *sc)
|
||||
struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid);
|
||||
|
||||
init_iq(fwq, sc, 0, 0, FW_IQ_QSIZE);
|
||||
fwq->flags |= IQ_INTR; /* always */
|
||||
if (sc->flags & IS_VF)
|
||||
intr_idx = 0;
|
||||
else {
|
||||
|
@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
|
||||
struct intrs_and_queues {
|
||||
uint16_t intr_type; /* MSI, or MSI-X */
|
||||
uint16_t nirq; /* Total # of vectors */
|
||||
uint16_t intr_flags; /* Interrupt flags for each port */
|
||||
uint16_t ntxq; /* # of NIC txq's for each port */
|
||||
uint16_t nrxq; /* # of NIC rxq's for each port */
|
||||
};
|
||||
@ -330,7 +329,6 @@ cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
continue;
|
||||
|
||||
iaq->intr_type = itype;
|
||||
iaq->intr_flags = 0;
|
||||
|
||||
/*
|
||||
* XXX: The Linux driver reserves an Ingress Queue for
|
||||
@ -438,7 +436,6 @@ cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
return (rc);
|
||||
}
|
||||
if (navail == iaq->nirq) {
|
||||
iaq->intr_flags = INTR_RXQ;
|
||||
return (0);
|
||||
}
|
||||
pci_release_msi(sc->dev);
|
||||
@ -455,7 +452,6 @@ cfg_itype_and_nqueues(struct adapter *sc, struct intrs_and_queues *iaq)
|
||||
device_printf(sc->dev,
|
||||
"failed to allocate vectors:%d, type=%d, req=%d, rcvd=%d\n",
|
||||
itype, rc, iaq->nirq, navail);
|
||||
iaq->intr_flags = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
@ -702,7 +698,6 @@ t4vf_attach(device_t dev)
|
||||
vi->first_txq = tqidx;
|
||||
vi->tmr_idx = t4_tmr_idx;
|
||||
vi->pktc_idx = t4_pktc_idx;
|
||||
vi->flags |= iaq.intr_flags & INTR_RXQ;
|
||||
vi->nrxq = j == 0 ? iaq.nrxq: 1;
|
||||
vi->ntxq = j == 0 ? iaq.ntxq: 1;
|
||||
|
||||
|
@ -1236,8 +1236,8 @@ MODULE_DEPEND(i915kms, agp, 1, 1, 1);
|
||||
MODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
|
||||
MODULE_DEPEND(i915kms, iic, 1, 1, 1);
|
||||
MODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
|
||||
MODULE_PNP_INFO("U32:vendor;U32:device;P:#;D:human", vgapci, i915, pciidlist,
|
||||
sizeof(pciidlist[0]), nitems(pciidlist));
|
||||
MODULE_PNP_INFO("U32:vendor;U32:device;P:#;D:#", vgapci, i915, pciidlist,
|
||||
sizeof(pciidlist[0]), nitems(pciidlist) - 1);
|
||||
|
||||
/* We give fast paths for the really cool registers */
|
||||
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
|
||||
|
@ -401,5 +401,5 @@ MODULE_DEPEND(radeonkms, iicbus, 1, 1, 1);
|
||||
MODULE_DEPEND(radeonkms, iic, 1, 1, 1);
|
||||
MODULE_DEPEND(radeonkms, iicbb, 1, 1, 1);
|
||||
MODULE_DEPEND(radeonkms, firmware, 1, 1, 1);
|
||||
MODULE_PNP_INFO("U32:vendor;U32:device;P:#;D:human", vgapci, radeonkms,
|
||||
pciidlist, sizeof(pciidlist[0]), nitems(pciidlist));
|
||||
MODULE_PNP_INFO("U32:vendor;U32:device;P:#;D:#", vgapci, radeonkms,
|
||||
pciidlist, sizeof(pciidlist[0]), nitems(pciidlist) - 1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2016-2017 Matt Macy <mmacy@nextbsd.org>
|
||||
* Copyright (c) 2016-2017 Matthew Macy <mmacy@mattmacy.io>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org>
|
||||
* Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org>
|
||||
* Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org>
|
||||
* Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -203,6 +203,4 @@ static driver_t ed_isa_driver = {
|
||||
DRIVER_MODULE(ed, isa, ed_isa_driver, ed_devclass, 0, 0);
|
||||
MODULE_DEPEND(ed, isa, 1, 1, 1);
|
||||
MODULE_DEPEND(ed, ether, 1, 1, 1);
|
||||
MODULE_PNP_INFO("E:pnpid;", isa, ed, ed_ids, sizeof(ed_ids[0]),
|
||||
nitems(ed_ids) - 1);
|
||||
|
||||
ISA_PNP_INFO(ed_ids);
|
||||
|
@ -145,6 +145,6 @@ static driver_t ed_pci_driver = {
|
||||
DRIVER_MODULE(ed, pci, ed_pci_driver, ed_devclass, 0, 0);
|
||||
MODULE_DEPEND(ed, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(ed, ether, 1, 1, 1);
|
||||
MODULE_PNP_INFO("W32:vendor/device;D:human", pci, ed, pci_ids, sizeof(pci_ids[0]),
|
||||
MODULE_PNP_INFO("W32:vendor/device;D:#", pci, ed, pci_ids, sizeof(pci_ids[0]),
|
||||
nitems(pci_ids) - 1);
|
||||
|
||||
|
@ -395,3 +395,4 @@ DRIVER_MODULE(ep, isa, ep_isa_driver, ep_devclass, 0, 0);
|
||||
#ifdef __i386__
|
||||
MODULE_DEPEND(ep, elink, 1, 1, 1);
|
||||
#endif
|
||||
ISA_PNP_INFO(ep_ids);
|
||||
|
@ -82,8 +82,6 @@ static driver_t ex_isa_driver = {
|
||||
sizeof(struct ex_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0);
|
||||
|
||||
static struct isa_pnp_id ex_ids[] = {
|
||||
{ 0x3110d425, NULL }, /* INT1031 */
|
||||
{ 0x3010d425, NULL }, /* INT1030 */
|
||||
@ -337,3 +335,6 @@ ex_look_for_card(struct ex_softc *sc)
|
||||
|
||||
return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits));
|
||||
}
|
||||
|
||||
DRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0);
|
||||
ISA_PNP_INFO(ex_ids);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Michal Meloun
|
||||
* Copyright (c) 2017 Kyle Evans <kevans@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
77
sys/dev/extres/syscon/syscon.h
Normal file
77
sys/dev/extres/syscon/syscon.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* Copyright 2017 Kyle Evans <kevans@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 ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef DEV_SYSCON_H
|
||||
#define DEV_SYSCON_H
|
||||
|
||||
#include "opt_platform.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kobj.h>
|
||||
#ifdef FDT
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#endif
|
||||
|
||||
struct syscon {
|
||||
KOBJ_FIELDS;
|
||||
|
||||
TAILQ_ENTRY(syscon) syscon_link; /* Global list entry */
|
||||
|
||||
device_t pdev; /* provider device */
|
||||
#ifdef FDT
|
||||
phandle_t ofw_node; /* OFW node for syscon */
|
||||
#endif
|
||||
void *softc; /* provider softc */
|
||||
};
|
||||
|
||||
/*
|
||||
* Shorthands for constructing method tables.
|
||||
*/
|
||||
#define SYSCONMETHOD KOBJMETHOD
|
||||
#define SYSCONMETHOD_END KOBJMETHOD_END
|
||||
#define syscon_method_t kobj_method_t
|
||||
#define syscon_class_t kobj_class_t
|
||||
DECLARE_CLASS(syscon_class);
|
||||
|
||||
void *syscon_get_softc(struct syscon *syscon);
|
||||
|
||||
/*
|
||||
* Provider interface
|
||||
*/
|
||||
struct syscon *syscon_create(device_t pdev, syscon_class_t syscon_class);
|
||||
struct syscon *syscon_register(struct syscon *syscon);
|
||||
int syscon_unregister(struct syscon *syscon);
|
||||
|
||||
#ifdef FDT
|
||||
struct syscon *syscon_create_ofw_node(device_t pdev,
|
||||
syscon_class_t syscon_class, phandle_t node);
|
||||
phandle_t syscon_get_ofw_node(struct syscon *syscon);
|
||||
int syscon_get_by_ofw_property(device_t consumer, phandle_t node, char *name,
|
||||
struct syscon **syscon);
|
||||
#endif
|
||||
|
||||
#endif /* DEV_SYSCON_H */
|
211
sys/dev/extres/syscon/syscon_generic.c
Normal file
211
sys/dev/extres/syscon/syscon_generic.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Michal Meloun
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a generic syscon driver, whose purpose is to provide access to
|
||||
* various unrelated bits packed in a single register space. It is usually used
|
||||
* as a fallback to more specific driver, but works well enough for simple
|
||||
* access.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include "syscon_if.h"
|
||||
#include "syscon.h"
|
||||
|
||||
MALLOC_DECLARE(M_SYSCON);
|
||||
|
||||
static uint32_t syscon_generic_read_4(struct syscon *syscon, bus_size_t offset);
|
||||
static int syscon_generic_write_4(struct syscon *syscon, bus_size_t offset,
|
||||
uint32_t val);
|
||||
static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
|
||||
uint32_t clear_bits, uint32_t set_bits);
|
||||
|
||||
/*
|
||||
* Generic syscon driver (FDT)
|
||||
*/
|
||||
struct syscon_generic_softc {
|
||||
device_t dev;
|
||||
struct syscon *syscon;
|
||||
struct resource *mem_res;
|
||||
struct mtx mtx;
|
||||
};
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"syscon", 1},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
#define SYSCON_LOCK(_sc) mtx_lock(&(_sc)->mtx)
|
||||
#define SYSCON_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
|
||||
#define SYSCON_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \
|
||||
device_get_nameunit((_sc)->dev), "syscon", MTX_DEF)
|
||||
#define SYSCON_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx);
|
||||
#define SYSCON_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED);
|
||||
#define SYSCON_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
|
||||
|
||||
static syscon_method_t syscon_generic_methods[] = {
|
||||
SYSCONMETHOD(syscon_read_4, syscon_generic_read_4),
|
||||
SYSCONMETHOD(syscon_write_4, syscon_generic_write_4),
|
||||
SYSCONMETHOD(syscon_modify_4, syscon_generic_modify_4),
|
||||
|
||||
SYSCONMETHOD_END
|
||||
};
|
||||
DEFINE_CLASS_1(syscon_generic, syscon_generic_class, syscon_generic_methods,
|
||||
0, syscon_class);
|
||||
|
||||
static uint32_t
|
||||
syscon_generic_read_4(struct syscon *syscon, bus_size_t offset)
|
||||
{
|
||||
struct syscon_generic_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = device_get_softc(syscon->pdev);
|
||||
|
||||
SYSCON_LOCK(sc);
|
||||
val = bus_read_4(sc->mem_res, offset);
|
||||
SYSCON_UNLOCK(sc);
|
||||
return (val);
|
||||
}
|
||||
|
||||
static int
|
||||
syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
|
||||
{
|
||||
struct syscon_generic_softc *sc;
|
||||
|
||||
sc = device_get_softc(syscon->pdev);
|
||||
|
||||
SYSCON_LOCK(sc);
|
||||
bus_write_4(sc->mem_res, offset, val);
|
||||
SYSCON_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
|
||||
uint32_t clear_bits, uint32_t set_bits)
|
||||
{
|
||||
struct syscon_generic_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = device_get_softc(syscon->pdev);
|
||||
|
||||
SYSCON_LOCK(sc);
|
||||
val = bus_read_4(sc->mem_res, offset);
|
||||
val &= ~clear_bits;
|
||||
val |= set_bits;
|
||||
bus_write_4(sc->mem_res, offset, val);
|
||||
SYSCON_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
syscon_generic_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "syscon");
|
||||
return (BUS_PROBE_GENERIC);
|
||||
}
|
||||
|
||||
static int
|
||||
syscon_generic_attach(device_t dev)
|
||||
{
|
||||
struct syscon_generic_softc *sc;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
rid = 0;
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
device_printf(dev, "Cannot allocate memory resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
SYSCON_LOCK_INIT(sc);
|
||||
sc->syscon = syscon_create_ofw_node(dev, &syscon_generic_class,
|
||||
ofw_bus_get_node(dev));
|
||||
if (sc->syscon == NULL) {
|
||||
device_printf(dev, "Failed to create/register syscon\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
syscon_generic_detach(device_t dev)
|
||||
{
|
||||
struct syscon_generic_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (sc->syscon != NULL) {
|
||||
syscon_unregister(sc->syscon);
|
||||
free(sc->syscon, M_SYSCON);
|
||||
}
|
||||
|
||||
SYSCON_LOCK_DESTROY(sc);
|
||||
|
||||
if (sc->mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t syscon_generic_dmethods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, syscon_generic_probe),
|
||||
DEVMETHOD(device_attach, syscon_generic_attach),
|
||||
DEVMETHOD(device_detach, syscon_generic_detach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(syscon_generic, syscon_generic_driver, syscon_generic_dmethods,
|
||||
sizeof(struct syscon_generic_softc));
|
||||
static devclass_t syscon_generic_devclass;
|
||||
EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver,
|
||||
syscon_generic_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LATE);
|
||||
MODULE_VERSION(syscon_generic, 1);
|
@ -30,25 +30,34 @@
|
||||
|
||||
INTERFACE syscon;
|
||||
|
||||
HEADER {
|
||||
struct syscon;
|
||||
}
|
||||
|
||||
METHOD int init {
|
||||
struct syscon *syscon;
|
||||
};
|
||||
|
||||
METHOD int uninit {
|
||||
struct syscon *syscon;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessor functions for syscon register space
|
||||
*/
|
||||
METHOD uint32_t read_4 {
|
||||
device_t dev;
|
||||
device_t consumer;
|
||||
struct syscon *syscon;
|
||||
bus_size_t offset;
|
||||
};
|
||||
|
||||
METHOD void write_4 {
|
||||
device_t dev;
|
||||
device_t consumer;
|
||||
METHOD int write_4 {
|
||||
struct syscon *syscon;
|
||||
bus_size_t offset;
|
||||
uint32_t val;
|
||||
};
|
||||
|
||||
METHOD void modify_4 {
|
||||
device_t dev;
|
||||
device_t consumer;
|
||||
METHOD int modify_4 {
|
||||
struct syscon *syscon;
|
||||
bus_size_t offset;
|
||||
uint32_t clear_bits;
|
||||
uint32_t set_bits;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user