Merge ^/head r326936 through r327149.

This commit is contained in:
Dimitry Andric 2017-12-24 13:22:57 +00:00
commit 54b4b13c4a
218 changed files with 5154 additions and 7232 deletions

View File

@ -24,4 +24,3 @@
}
}
}

View File

@ -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

View File

@ -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`

View File

@ -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);

View File

@ -394,6 +394,7 @@ FBSD_1.4 {
FBSD_1.5 {
alphasort;
basename;
daemonfd;
devname;
devname_r;
dirname;

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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.

View 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.

View File

@ -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

View File

@ -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.

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 .

View File

@ -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
View 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

View File

@ -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

View File

@ -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 .

View File

@ -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 .

View File

@ -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 $

View File

@ -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 */

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 */
}

View File

@ -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

View File

@ -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 \

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -232,7 +232,7 @@ main(void)
bios_getsmap();
interact(NULL);
interact();
/* if we ever get here, it is an error */
return (1);

View File

@ -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 \

View File

@ -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);
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
}
/*

View File

@ -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

View File

@ -29,6 +29,8 @@
#ifndef _MACHINE_ATOMIC_H_
#define _MACHINE_ATOMIC_H_
#include <sys/atomic_common.h>
#define isb() __asm __volatile("isb" : : : "memory")
/*

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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.
*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -11,7 +11,7 @@ SECTIONS
/* Read-only sections, merged into text segment: */
. = kernbase;
PROVIDE (begin = . - SIZEOF_HEADERS);
PROVIDE (begin = .);
.text :
{

View File

@ -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

View File

@ -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 ||

View File

@ -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));

View File

@ -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);

View File

@ -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},

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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));
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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");

View File

@ -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) |

View File

@ -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 {

View File

@ -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;

View File

@ -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) \

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View 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 */

View 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);

View File

@ -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