diff options
-rw-r--r-- | share/man/man4/Makefile | 8 | ||||
-rw-r--r-- | share/man/man4/if_ntb.4 | 12 | ||||
-rw-r--r-- | share/man/man4/ntb.4 | 91 | ||||
-rw-r--r-- | share/man/man4/ntb_hw_intel.4 (renamed from share/man/man4/ntb_hw.4) | 66 | ||||
-rw-r--r-- | share/man/man4/ntb_hw_plx.4 | 118 | ||||
-rw-r--r-- | share/man/man4/ntb_transport.4 | 35 | ||||
-rw-r--r-- | sys/amd64/conf/NOTES | 11 | ||||
-rw-r--r-- | sys/conf/files.amd64 | 9 | ||||
-rw-r--r-- | sys/conf/files.i386 | 9 | ||||
-rw-r--r-- | sys/dev/ntb/ntb_hw/ntb_hw_intel.c (renamed from sys/dev/ntb/ntb_hw/ntb_hw.c) | 8 | ||||
-rw-r--r-- | sys/dev/ntb/ntb_hw/ntb_hw_intel.h (renamed from sys/dev/ntb/ntb_hw/ntb_regs.h) | 0 | ||||
-rw-r--r-- | sys/dev/ntb/ntb_hw/ntb_hw_plx.c | 945 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 9 | ||||
-rw-r--r-- | sys/modules/ntb/Makefile | 2 | ||||
-rw-r--r-- | sys/modules/ntb/ntb_hw_intel/Makefile | 9 | ||||
-rw-r--r-- | sys/modules/ntb/ntb_hw_plx/Makefile (renamed from sys/modules/ntb/ntb_hw/Makefile) | 4 |
16 files changed, 1261 insertions, 75 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index c03f24a90015..ad8c5b494ebf 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -373,7 +373,9 @@ MAN= aac.4 \ ng_vlan.4 \ nmdm.4 \ nsp.4 \ - ${_ntb_hw.4} \ + ${_ntb.4} \ + ${_ntb_hw_intel.4} \ + ${_ntb_hw_plx.4} \ ${_ntb_transport.4} \ ${_if_ntb.4} \ null.4 \ @@ -686,7 +688,6 @@ MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 MLINKS+=${_nfe.4} ${_if_nfe.4} MLINKS+=nge.4 if_nge.4 -MLINKS+=${_ntb_hw.4} ${_ntb.4} MLINKS+=${_nxge.4} ${_if_nxge.4} MLINKS+=ow.4 onewire.4 MLINKS+=pccbb.4 cbb.4 @@ -834,7 +835,8 @@ _xnb.4= xnb.4 _if_ntb.4= if_ntb.4 _ioat.4= ioat.4 _ntb.4= ntb.4 -_ntb_hw.4= ntb_hw.4 +_ntb_hw_intel.4= ntb_hw_intel.4 +_ntb_hw_plx.4= ntb_hw_plx.4 _ntb_transport.4=ntb_transport.4 _qlxge.4= qlxge.4 _qlxgb.4= qlxgb.4 diff --git a/share/man/man4/if_ntb.4 b/share/man/man4/if_ntb.4 index 6f52d7774264..78211b0b3549 100644 --- a/share/man/man4/if_ntb.4 +++ b/share/man/man4/if_ntb.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2016 +.Dd August 30, 2017 .Dt IF_NTB 4 .Os .Sh NAME @@ -35,6 +35,8 @@ To compile this driver into your kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent +.Cd "device ntb" +.Cd "device ntb_transport" .Cd "device if_ntb" .Ed .Pp @@ -56,11 +58,11 @@ The .Nm driver attaches on top of the .Xr ntb_transport 4 -driver to utilize its resources to create virtual Ethernet interface between -the systems. -Interface capabilities depend on the underlying transport. +driver to utilize its resources to create virtual Ethernet network interface +between the systems. +It supports as many tx/rx queues as provided by underlying +.Xr ntb_transport 4 . Typical MTU is about 64KB to reduce overhead. -By default one queue is used, but more may be configured. The MAC address for interface is randomly generated. .Pp The diff --git a/share/man/man4/ntb.4 b/share/man/man4/ntb.4 new file mode 100644 index 000000000000..d45d1bd756b5 --- /dev/null +++ b/share/man/man4/ntb.4 @@ -0,0 +1,91 @@ +.\" +.\" Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 30, 2017 +.Dt NTB 4 +.Os +.Sh NAME +.Nm ntb +.Nd Non-Transparent Bridge subsystem +.Sh SYNOPSIS +To compile it into your kernel, +place the following lines in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ntb" +.Ed +.Pp +Or, to load it as a module at boot, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +ntb_load="YES" +.Ed +.Pp +The following tunables are settable from the +.Xr loader 8 : +.Bl -ohang +.It Va hw.ntb.debug_level +Driver debug level. +The default value is 0, higher means more verbose. +.It Va hint.ntb_hw. Ns Ar X Ns Va .config +Configures NTB resources split between several consumer devices. +Configuration of multiple consumer devices separated by commas. +Each device can be configured as: "[<name>][:<mw>[:<spad>[:<db>]]]", where: +.Va name +is a name of the driver which should attach the device (empty means any), +.Va mw +is a number of memory windows to allocate (empty means all available), +.Va spad +is a number of scratchpad registers to allocate (empty means all available), +.Va db +is a number of doorbells to allocate (empty means all available). +The default configuration is empty string, which means single device +with all available resources allowing any driver attachment. +.El +.Sh DESCRIPTION +Non-Transparent Bridges allow to connect two computer systems with PCIe +link(s), providing each of them limited access to others memory space, +scratchpad registers and interrupts. +The +.Nm +subsystem uses those resources provided in generic way by hardware drivers +and splits them between multiple consumer drivers, according to specified +configuration. +.Sh SEE ALSO +.Xr if_ntb 4 , +.Xr ntb_transport 4 , +.Xr ntb_hw_intel 4 , +.Xr ntb_hw_plx 4 +.Sh AUTHORS +.An -nosplit +The +.Nm +subsystem was developed by Intel and originally written by +.An Carl Delsey Aq Mt carl@FreeBSD.org . +Later improvements were done by +.An Conrad E. Meyer Aq Mt cem@FreeBSD.org +and +.An Alexander Motin Aq Mt mav@FreeBSD.org . diff --git a/share/man/man4/ntb_hw.4 b/share/man/man4/ntb_hw_intel.4 index 6bc11ba3f2ef..423dc9650785 100644 --- a/share/man/man4/ntb_hw.4 +++ b/share/man/man4/ntb_hw_intel.4 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2016 Alexander Motin <mav@FreeBSD.org> +.\" Copyright (c) 2016-2017 Alexander Motin <mav@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,66 +25,45 @@ .\" .\" $FreeBSD$ .\" -.Dd July 28, 2016 -.Dt NTB_HW 4 +.Dd August 30, 2017 +.Dt NTB_HW_INTEL 4 .Os .Sh NAME -.Nm ntb , -.Nm ntb_hw +.Nm ntb_hw_intel .Nd Intel(R) Non-Transparent Bridge driver .Sh SYNOPSIS To compile this driver into your kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent -.Cd "device ntb_hw" +.Cd "device ntb" +.Cd "device ntb_hw_intel" .Ed .Pp Or, to load the driver as a module at boot, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent -ntb_hw_load="YES" +ntb_hw_intel_load="YES" .Ed -.Pp -The following tunables are settable from the -.Xr loader 8 : -.Bl -ohang -.It Va hw.ntb.debug_level -Driver debug level. -The default value is 0, higher means more verbose. -.It Va hint.ntb_hw. Ns Ar X Ns Va .config -Configures NTB resources split between several consumer devices. -Configuration of multiple consumer devices separated by commas. -Each device can be configured as: "<name>[:<mw>[:<spad>[:<db>]]]", where: -.Va name -is a name of the driver which should attach the device (empty means any), -.Va mw -is a number of memory windows to allocate (empty means all available), -.Va spad -is a number of scratchpad registers to allocate (empty means all available), -.Va db -is a number of doorbells to allocate (empty means all available). -The default configuration is empty string, which means single device -with all available resources allowing any driver attachment. -.El .Sh DESCRIPTION -The NTB allows you to connect two computer systems using a PCIe link if they -have the correct equipment and connectors. -The -.Nm ntb_hw -driver provides support for the Non-Transparent Bridge (NTB) in the Intel S1200 -and Xeon E3/E5 processor families. The -.Nm -driver hides hardware details, exposing memory windows, scratchpads and -doorbells via hardware independent KPI. +.Nm ntb_hw_intel +driver provides support for the Non-Transparent Bridge (NTB) hardware in +Intel Xeon E3/E5 and S1200 processor families, which allow one of their PCIe +ports to be switched from transparent to non-transparent bridge mode. +In this mode bridge looks not as a PCI bridge, but as PCI endpoint device. +The driver hides hardware details, exposing memory windows, scratchpads +and doorbells of the other side via hardware independent KPI to +.Xr ntb 4 +subsystem. .Pp -The hardware provides 2-3 memory windows to the other system's memory, -16 scratchpad registers and 14/34 doorbells to interrupt the other system. +The hardware provides 2 or 3 memory windows to the other system's memory, +16 scratchpad registers and 14 or 34 doorbells to interrupt the other system. On Xeon processors one of memory windows is typically consumed by the driver -to workaround multiple hardware erratas. +itself to workaround multiple hardware erratas. .Sh CONFIGURATION The NTB configuration should be set by BIOS. -It includes enabling NTB, choosing between NTB-to-NTB or NTB-to-Root Port mode, +It includes enabling NTB, choosing between NTB-to-NTB (back-to-back) or +NTB-to-Root Port mode, enabling split BAR mode (one of two 64-bit BARs can be split into two 32-bit ones) and configuring BAR sizes in bits (from 12 to 29/39) for both NTB sides. .Pp @@ -93,7 +72,8 @@ all BAR sizes are set to 20 (1 MiB). This needs to be done on both systems. .Sh SEE ALSO .Xr if_ntb 4 , -.Xr ntb_transport 4 +.Xr ntb_transport 4 , +.Xr ntb 4 , .Sh AUTHORS .An -nosplit The diff --git a/share/man/man4/ntb_hw_plx.4 b/share/man/man4/ntb_hw_plx.4 new file mode 100644 index 000000000000..54500a11a9a3 --- /dev/null +++ b/share/man/man4/ntb_hw_plx.4 @@ -0,0 +1,118 @@ +.\" +.\" Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 30, 2017 +.Dt NTB_HW_PLX 4 +.Os +.Sh NAME +.Nm ntb_hw_plx +.Nd PLX/Avago/Broadcom Non-Transparent Bridge driver +.Sh SYNOPSIS +To compile this driver into your kernel, +place the following lines in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ntb" +.Cd "device ntb_hw_plx" +.Ed +.Pp +Or, to load the driver as a module at boot, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +ntb_hw_plx_load="YES" +.Ed +.Pp +The following tunables are settable from the +.Xr loader 8 : +.Bl -ohang +.It Va hint.ntb_hw. Ns Ar X Ns Va .b2b +Being set to 1 (default) tells the driver attached to Virtual Interface of the +NTB that it works in NTB-to-NTB (back-to-back) mode, 0 -- NTB-to-Root Port. +Driver attached to Link Interface (visible from Root Port side) switches to +NTB-to-Root Port mode automatically, but one attached to Virtual Interface +can't detect what is on the other side and require external knowledge. +.El +.Sh DESCRIPTION +The +.Nm +driver provides support for the Non-Transparent Bridge (NTB) hardware in +PLX PCIe bridge chips, which allow up to two of their PCIe ports to be +switched from transparent to non-transparent bridge mode. +In this mode bridge looks not as a PCI bridge, but as PCI endpoint device. +The driver hides hardware details, exposing memory windows, scratchpads +and doorbells of the other side via hardware independent KPI to +.Xr ntb 4 +subsystem. +.Pp +Each PLX NTB provides up to 2 64-bit or 4 32-bit memory windows to the +other system's memory, 6 or 12 scratchpad registers and 16 doorbells to +interrupt the other system. +In NTB-to-NTB mode one of memory windows (or half of it, if bigger then 1MB) +is consumed by the driver itself to access scratchpad and doorbell registers +of the other side. +.Sh HARDWARE +The following PLX/Avago/Broadcom chips are supported by the +.Nm +driver: +.Pp +.Bl -bullet -compact +.It +PEX 8713 +.It +PEX 8717 +.It +PEX 8725 +.It +PEX 8733 +.It +PEX 8749 +.El +.Pp +, but it may also work with other compatible ones. +.Sh CONFIGURATION +The basic chip configuration should be done by serial EEPROM or via i2c. +It includes enabling NTB on one or both sides (choosing between NTB-to-NTB +(back-to-back) and NTB-to-Root Port modes) and configuring BARs sizes. +.Pp +The recommended mode is NTB-to-NTB mode, since while NTB-to-Root Port is +generally supported by the driver, it require PCI hotplug handling on the +Root Port, that may be difficult or cause different kinds of problems. +.Sh SEE ALSO +.Xr if_ntb 4 , +.Xr ntb_transport 4 , +.Xr ntb 4 , +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Alexander Motin Aq Mt mav@FreeBSD.org . +.Sh BUGS +There is no way to protect your system from malicious behavior on the other +system once the link is brought up. +Anyone with root or kernel access on the other system can read or write to +any location on your system. +In other words, only connect two systems that completely trust each other. diff --git a/share/man/man4/ntb_transport.4 b/share/man/man4/ntb_transport.4 index 43b412cd8f5f..1a4fc3efba21 100644 --- a/share/man/man4/ntb_transport.4 +++ b/share/man/man4/ntb_transport.4 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2016 Alexander Motin <mav@FreeBSD.org> +.\" Copyright (c) 2016-2017 Alexander Motin <mav@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,14 +25,21 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2016 +.Dd August 30, 2017 .Dt NTB_TRANSPORT 4 .Os .Sh NAME .Nm ntb_transport .Nd Packet-oriented transport for Non-Transparent Bridges .Sh SYNOPSIS -To load the driver as a module at boot, place the following line in +To compile this driver into your kernel, +place the following lines in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ntb" +.Cd "device ntb_transport" +.Ed +.Pp +Or, to load the driver as a module at boot, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent ntb_transport_load="YES" @@ -46,11 +53,11 @@ Driver debug level. The default value is 0, higher means more verbose. .It Va hint.ntb_transport. Ns Ar X Ns Va .config Configures queues allocation for consumer devices, separated by commas. -Each device can be configured as: "<name>[:<queues>]", where: +Each device can be configured as: "[<name>][:<queues>]", where: .Va name is a name of the driver which should attach the device (empty means any), .Va queues -is a number of queues to allocate (empty means automatic), +is a number of queues to allocate (empty means automatic). The default configuration is empty string, which means single device with one queue per memory window allowing any driver attachment. .El @@ -64,9 +71,25 @@ delivering packets between the systems. The primary purpose of this is to be used by .Nm if_ntb network interface, but other consumers may also be developed using KPI. +.Pp +Each +.Nm +require from underlying +.Nm ntb +instance: +.Bl -bullet -compact +.It +1 or more memory windows; +.It +6 scratchpads, plus 2 more for each additional memory window; +.It +1 doorbell for each memory window or configured queue. +.El .Sh SEE ALSO .Xr if_ntb 4 , -.Xr ntb_hw 4 +.Xr ntb 4 , +.Xr ntb_hw_intel 4 , +.Xr ntb_hw_plx 4 .Sh AUTHORS .An -nosplit The diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index 346c20a5be1b..5b7e1155bb0b 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -395,9 +395,14 @@ device iwn6000g2bfw device iwn6050fw device wpifw -# Intel Non-Transparent Bridge (NTB) hardware -device ntb_hw # Hardware Abstraction Layer for the NTB -device if_ntb # Simulated ethernet device using the NTB +# +# Non-Transparent Bridge (NTB) drivers +# +device if_ntb # Virtual NTB network interface +device ntb_transport # NTB packet transport driver +device ntb # NTB hardware interface +device ntb_hw_intel # Intel NTB hardware driver +device ntb_hw_plx # PLX NTB hardware driver # #XXX this stores pointers in a 32bit field that is defined by the hardware diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a9b926f83c97..aae4765eaff7 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -330,10 +330,11 @@ dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv dev/nctgpio/nctgpio.c optional nctgpio dev/nfe/if_nfe.c optional nfe pci dev/ntb/if_ntb/if_ntb.c optional if_ntb -dev/ntb/ntb_transport.c optional if_ntb -dev/ntb/ntb.c optional if_ntb | ntb_hw -dev/ntb/ntb_if.m optional if_ntb | ntb_hw -dev/ntb/ntb_hw/ntb_hw.c optional ntb_hw +dev/ntb/ntb_transport.c optional ntb_transport | if_ntb +dev/ntb/ntb.c optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx | ntb_hw +dev/ntb/ntb_if.m optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx | ntb_hw +dev/ntb/ntb_hw/ntb_hw_intel.c optional ntb_hw_intel | ntb_hw +dev/ntb/ntb_hw/ntb_hw_plx.c optional ntb_hw_plx | ntb_hw dev/nvd/nvd.c optional nvd nvme dev/nvme/nvme.c optional nvme dev/nvme/nvme_ctrlr.c optional nvme diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 294379d000c4..c0ec01b5fcde 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -271,10 +271,11 @@ dev/mse/mse_isa.c optional mse isa dev/nctgpio/nctgpio.c optional nctgpio dev/nfe/if_nfe.c optional nfe pci dev/ntb/if_ntb/if_ntb.c optional if_ntb -dev/ntb/ntb_transport.c optional if_ntb -dev/ntb/ntb.c optional if_ntb | ntb_hw -dev/ntb/ntb_if.m optional if_ntb | ntb_hw -dev/ntb/ntb_hw/ntb_hw.c optional ntb_hw +dev/ntb/ntb_transport.c optional ntb_transport | if_ntb +dev/ntb/ntb.c optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx +dev/ntb/ntb_if.m optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx +dev/ntb/ntb_hw/ntb_hw_intel.c optional ntb_hw_intel +dev/ntb/ntb_hw/ntb_hw_plx.c optional ntb_hw_plx dev/nvd/nvd.c optional nvd nvme dev/nvme/nvme.c optional nvme dev/nvme/nvme_ctrlr.c optional nvme diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c index 9c8314f5a089..2375fb8005e4 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c @@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> -#include "ntb_regs.h" +#include "ntb_hw_intel.h" #include "../ntb.h" #define MAX_MSIX_INTERRUPTS MAX(XEON_DB_COUNT, ATOM_DB_COUNT) @@ -3116,6 +3116,6 @@ static device_method_t ntb_intel_methods[] = { static DEFINE_CLASS_0(ntb_hw, ntb_intel_driver, ntb_intel_methods, sizeof(struct ntb_softc)); -DRIVER_MODULE(ntb_intel, pci, ntb_intel_driver, ntb_hw_devclass, NULL, NULL); -MODULE_DEPEND(ntb_intel, ntb, 1, 1, 1); -MODULE_VERSION(ntb_intel, 1); +DRIVER_MODULE(ntb_hw_intel, pci, ntb_intel_driver, ntb_hw_devclass, NULL, NULL); +MODULE_DEPEND(ntb_hw_intel, ntb, 1, 1, 1); +MODULE_VERSION(ntb_hw_intel, 1); diff --git a/sys/dev/ntb/ntb_hw/ntb_regs.h b/sys/dev/ntb/ntb_hw/ntb_hw_intel.h index a03773627aa3..a03773627aa3 100644 --- a/sys/dev/ntb/ntb_hw/ntb_regs.h +++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.h diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c new file mode 100644 index 000000000000..8b7eb356ba11 --- /dev/null +++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c @@ -0,0 +1,945 @@ +/*- + * Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The Non-Transparent Bridge (NTB) is a device that allows you to connect + * two or more systems using a PCI-e links, providing remote memory access. + * + * This module contains a driver for NTBs in PLX/Avago/Broadcom PCIe bridges. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/sysctl.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/bus.h> +#include <machine/intr_machdep.h> +#include <machine/resource.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include "../ntb.h" + +#define PLX_MAX_BARS 4 /* There are at most 4 data BARs. */ +#define PLX_NUM_SPAD 8 /* There are 8 scratchpads. */ +#define PLX_NUM_SPAD_PATT 4 /* Use test pattern as 4 more. */ +#define PLX_NUM_DB 16 /* There are 16 doorbells. */ + +struct ntb_plx_mw_info { + int mw_bar; + int mw_64bit; + int mw_rid; + struct resource *mw_res; + vm_paddr_t mw_pbase; + caddr_t mw_vbase; + vm_size_t mw_size; + vm_memattr_t mw_map_mode; + bus_addr_t mw_xlat_addr; + size_t mw_xlat_size; +}; + +struct ntb_plx_softc { + /* ntb.c context. Do not move! Must go first! */ + void *ntb_store; + + device_t dev; + struct resource *conf_res; + int conf_rid; + u_int ntx; /* NTx number within chip. */ + u_int link; /* Link v/s Virtual side. */ + u_int port; /* Port number within chip. */ + + int int_rid; + struct resource *int_res; + void *int_tag; + + struct ntb_plx_mw_info mw_info[PLX_MAX_BARS]; + int mw_count; /* Number of memory windows. */ + + int spad_count1; /* Number of standard spads. */ + int spad_count2; /* Number of extra spads. */ + uint32_t spad_off1; /* Offset of our spads. */ + uint32_t spad_off2; /* Offset of our extra spads. */ + uint32_t spad_offp1; /* Offset of peer spads. */ + uint32_t spad_offp2; /* Offset of peer extra spads. */ + + /* Parameters of window shared with peer config access in B2B mode. */ + int b2b_mw; /* Shared window number. */ + uint64_t b2b_off; /* Offset in shared window. */ +}; + +#define PLX_NT0_BASE 0x3E000 +#define PLX_NT1_BASE 0x3C000 +#define PLX_NTX_BASE(sc) ((sc)->ntx ? PLX_NT1_BASE : PLX_NT0_BASE) +#define PLX_NTX_LINK_OFFSET 0x01000 + +/* Bases of NTx our/peer interface registers */ +#define PLX_NTX_OUR(sc) \ + (PLX_NTX_BASE(sc) + ((sc)->link ? PLX_NTX_LINK_OFFSET : 0)) +#define PLX_NTX_PEER(sc) \ + (PLX_NTX_BASE(sc) + ((sc)->link ? 0 : PLX_NTX_LINK_OFFSET)) + +/* Read/write NTx our interface registers */ +#define NTX_READ(sc, reg) \ + bus_read_4((sc)->conf_res, PLX_NTX_OUR(sc) + (reg)) +#define NTX_WRITE(sc, reg, val) \ + bus_write_4((sc)->conf_res, PLX_NTX_OUR(sc) + (reg), (val)) + +/* Read/write NTx peer interface registers */ +#define PNTX_READ(sc, reg) \ + bus_read_4((sc)->conf_res, PLX_NTX_PEER(sc) + (reg)) +#define PNTX_WRITE(sc, reg, val) \ + bus_write_4((sc)->conf_res, PLX_NTX_PEER(sc) + (reg), (val)) + +/* Read/write B2B NTx registers */ +#define BNTX_READ(sc, reg) \ + bus_read_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \ + PLX_NTX_BASE(sc) + (reg)) +#define BNTX_WRITE(sc, reg, val) \ + bus_write_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \ + PLX_NTX_BASE(sc) + (reg), (val)) + +static int ntb_plx_init(device_t dev); +static int ntb_plx_detach(device_t dev); +static int ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx); + +static int +ntb_plx_probe(device_t dev) +{ + + switch (pci_get_devid(dev)) { + case 0x87a010b5: + device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link"); + return (BUS_PROBE_DEFAULT); + case 0x87a110b5: + device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link"); + return (BUS_PROBE_DEFAULT); + case 0x87b010b5: + device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual"); + return (BUS_PROBE_DEFAULT); + case 0x87b110b5: + device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +ntb_plx_init(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + uint64_t val64; + int i; + uint32_t val; + + if (sc->b2b_mw >= 0) { + /* Set peer BAR0/1 size and address for B2B NTx access. */ + mw = &sc->mw_info[sc->b2b_mw]; + if (mw->mw_64bit) { + PNTX_WRITE(sc, 0xe4, 0x3); /* 64-bit */ + val64 = 0x2000000000000000 * mw->mw_bar | 0x4; + PNTX_WRITE(sc, PCIR_BAR(0), val64); + PNTX_WRITE(sc, PCIR_BAR(0) + 4, val64 >> 32); + } else { + PNTX_WRITE(sc, 0xe4, 0x2); /* 32-bit */ + val = 0x20000000 * mw->mw_bar; + PNTX_WRITE(sc, PCIR_BAR(0), val); + } + + /* Set Virtual to Link address translation for B2B. */ + for (i = 0; i < sc->mw_count; i++) { + mw = &sc->mw_info[i]; + if (mw->mw_64bit) { + val64 = 0x2000000000000000 * mw->mw_bar; + NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val64); + NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, val64 >> 32); + } else { + val = 0x20000000 * mw->mw_bar; + NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val); + } + } + + /* Enable Link Interface LUT entry 0 for 0:0.0. */ + PNTX_WRITE(sc, 0xdb4, 1); + } + + /* + * Enable Virtual Interface LUT entry 0 for 0:0.0 and + * entry 1 for our Requester ID reported by chip. + */ + val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001; + NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val); + + /* Set Link to Virtual address translation. */ + for (i = 0; i < sc->mw_count; i++) { + mw = &sc->mw_info[i]; + if (mw->mw_xlat_size != 0) + ntb_plx_mw_set_trans_internal(dev, i); + } + + pci_enable_busmaster(dev); + if (sc->b2b_mw >= 0) + PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + + return (0); +} + +static void +ntb_plx_isr(void *arg) +{ + device_t dev = arg; + struct ntb_plx_softc *sc = device_get_softc(dev); + uint32_t val; + + ntb_db_event((device_t)arg, 0); + + val = NTX_READ(sc, 0xfe0); + if (val == 0) + return; + NTX_WRITE(sc, 0xfe0, val); + if (val & 1) + device_printf(dev, "Correctable Error\n"); + if (val & 2) + device_printf(dev, "Uncorrectable Error\n"); + if (val & 4) { + /* DL_Down resets link side registers, have to reinit. */ + ntb_plx_init(dev); + ntb_link_event(dev); + } + if (val & 8) + device_printf(dev, "Uncorrectable Error Message Drop\n"); +} + +static int +ntb_plx_setup_intr(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + int error; + + /* + * XXX: This hardware supports MSI, but I found it unusable. + * It generates new MSI only when doorbell register goes from + * zero, but does not generate it when another bit is set or on + * partial clear. It makes operation very racy and unreliable. + * The data book mentions some mask juggling magic to workaround + * that, but I failed to make it work. + */ + sc->int_rid = 0; + sc->int_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->int_rid, RF_SHAREABLE|RF_ACTIVE); + if (sc->int_res == NULL) { + device_printf(dev, "bus_alloc_resource failed\n"); + return (ENOMEM); + } + error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC, + NULL, ntb_plx_isr, dev, &sc->int_tag); + if (error != 0) { + device_printf(dev, "bus_setup_intr failed: %d\n", error); + return (error); + } + NTX_WRITE(sc, 0xfe0, 0xf); /* Clear link interrupts. */ + NTX_WRITE(sc, 0xfe4, 0x0); /* Unmask link interrupts. */ + return (0); +} + +static void +ntb_plx_teardown_intr(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + NTX_WRITE(sc, 0xfe4, 0xf); /* Mask link interrupts. */ + if (sc->int_res) { + bus_teardown_intr(dev, sc->int_res, sc->int_tag); + bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid, + sc->int_res); + } +} + +static int +ntb_plx_attach(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + int error = 0, i; + uint32_t val; + char buf[32]; + + /* Identify what we are (what side of what NTx). */ + sc->dev = dev; + val = pci_read_config(dev, 0xc8c, 4); + sc->ntx = (val & 1) != 0; + sc->link = (val & 0x80000000) != 0; + + /* Get access to whole 256KB of chip configuration space via BAR0/1. */ + sc->conf_rid = PCIR_BAR(0); + sc->conf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->conf_rid, RF_ACTIVE); + if (sc->conf_res == NULL) { + device_printf(dev, "Can't allocate configuration BAR.\n"); + return (ENXIO); + } + pmap_change_attr((vm_offset_t)rman_get_start(sc->conf_res), + rman_get_size(sc->conf_res), VM_MEMATTR_UNCACHEABLE); + + /* Identify chip port we are connected to. */ + val = bus_read_4(sc->conf_res, 0x360); + sc->port = (val >> ((sc->ntx == 0) ? 8 : 16)) & 0x1f; + + /* Find configured memory windows at BAR2-5. */ + sc->mw_count = 0; + for (i = 2; i <= 5; i++) { + mw = &sc->mw_info[sc->mw_count]; + mw->mw_bar = i; + mw->mw_rid = PCIR_BAR(mw->mw_bar); + mw->mw_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &mw->mw_rid, RF_ACTIVE); + if (mw->mw_res == NULL) + continue; + mw->mw_pbase = rman_get_start(mw->mw_res); + mw->mw_size = rman_get_size(mw->mw_res); + mw->mw_vbase = rman_get_virtual(mw->mw_res); + mw->mw_map_mode = VM_MEMATTR_UNCACHEABLE; + pmap_change_attr((vm_offset_t)mw->mw_vbase, mw->mw_size, + mw->mw_map_mode); + sc->mw_count++; + + /* Skip over adjacent BAR for 64-bit BARs. */ + val = pci_read_config(dev, PCIR_BAR(mw->mw_bar), 4); + if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) { + mw->mw_64bit = 1; + i++; + } + } + + /* Try to identify B2B mode. */ + i = 1; + snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev), + device_get_unit(dev)); + TUNABLE_INT_FETCH(buf, &i); + if (sc->link) { + device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n"); + sc->b2b_mw = -1; + } else if (i == 0) { + device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n"); + sc->b2b_mw = -1; + } else { + device_printf(dev, "NTB-to-NTB (back-to-back) mode\n"); + + /* We need at least one memory window for B2B peer access. */ + if (sc->mw_count == 0) { + device_printf(dev, "No memory window BARs enabled.\n"); + error = ENXIO; + goto out; + } + sc->b2b_mw = sc->mw_count - 1; + + /* Use half of the window for B2B, but no less then 1MB. */ + mw = &sc->mw_info[sc->b2b_mw]; + if (mw->mw_size >= 2 * 1024 * 1024) + sc->b2b_off = mw->mw_size / 2; + else + sc->b2b_off = 0; + } + + /* + * Use Physical Layer User Test Pattern as additional scratchpad. + * Make sure they are present and enabled by writing to them. + * XXX: Its a hack, but standard 8 registers are not enough. + */ + if (sc->b2b_mw >= 0) { + sc->spad_count1 = PLX_NUM_SPAD; + sc->spad_off1 = PLX_NTX_OUR(sc) + 0xc6c; + sc->spad_off2 = (sc->ntx == 0) ? 0x0020c : 0x0820c; + sc->spad_offp1 = sc->spad_off1; + sc->spad_offp2 = sc->spad_off2; + bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678); + if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678) + sc->spad_count2 = PLX_NUM_SPAD_PATT; + } else { + sc->spad_count1 = PLX_NUM_SPAD / 2; + sc->spad_off1 = PLX_NTX_OUR(sc) + 0xc6c; + sc->spad_off2 = (sc->ntx == 0) ? 0x0020c : 0x0820c; + sc->spad_offp1 = sc->spad_off1; + sc->spad_offp2 = sc->spad_off2; + if (sc->link) { + sc->spad_off1 += PLX_NUM_SPAD / 2 * 4; + sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4; + } else { + sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4; + sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4; + } + bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678); + if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678) + sc->spad_count2 = PLX_NUM_SPAD_PATT / 2; + } + + /* Apply static part of NTB configuration. */ + ntb_plx_init(dev); + + /* Allocate and setup interrupts. */ + error = ntb_plx_setup_intr(dev); + if (error) + goto out; + + /* Attach children to this controller */ + error = ntb_register_device(dev); + +out: + if (error != 0) + ntb_plx_detach(dev); + return (error); +} + +static int +ntb_plx_detach(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + int i; + + /* Detach & delete all children */ + ntb_unregister_device(dev); + + /* Disable and free interrupts. */ + ntb_plx_teardown_intr(dev); + + /* Free memory resources. */ + for (i = 0; i < sc->mw_count; i++) { + mw = &sc->mw_info[i]; + bus_release_resource(dev, SYS_RES_MEMORY, mw->mw_rid, + mw->mw_res); + } + bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res); + return (0); +} + + +static bool +ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width) +{ + uint16_t link; + + link = pcie_read_config(dev, PCIER_LINK_STA, 2); + if (speed != NULL) + *speed = (link & PCIEM_LINK_STA_SPEED); + if (width != NULL) + *width = (link & PCIEM_LINK_STA_WIDTH) >> 4; + return ((link & PCIEM_LINK_STA_WIDTH) != 0); +} + +static int +ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused, + enum ntb_width width __unused) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + uint32_t reg, val; + + /* The fact that we see the Link Interface means link is enabled. */ + if (sc->link) { + ntb_link_event(dev); + return (0); + } + + reg = (sc->port < 8) ? 0x00208 : 0x08208; + val = bus_read_4(sc->conf_res, reg); + if ((val & (1 << (sc->port & 7))) == 0) { + /* If already enabled, generate fake link event and exit. */ + ntb_link_event(dev); + return (0); + } + val &= ~(1 << (sc->port & 7)); + bus_write_4(sc->conf_res, reg, val); + return (0); +} + +static int +ntb_plx_link_disable(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + uint32_t reg, val; + + /* Link disable for Link Interface would be suicidal. */ + if (sc->link) + return (0); + + reg = (sc->port < 8) ? 0x00208 : 0x08208; + val = bus_read_4(sc->conf_res, reg); + val |= (1 << (sc->port & 7)); + bus_write_4(sc->conf_res, reg, val); + return (0); +} + +static bool +ntb_plx_link_enabled(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + uint32_t reg, val; + + /* The fact that we see the Link Interface means link is enabled. */ + if (sc->link) + return (TRUE); + + reg = (sc->port < 8) ? 0x00208 : 0x08208; + val = bus_read_4(sc->conf_res, reg); + return ((val & (1 << (sc->port & 7))) == 0); +} + +static uint8_t +ntb_plx_mw_count(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + if (sc->b2b_mw >= 0 && sc->b2b_off == 0) + return (sc->mw_count - 1); /* B2B consumed whole window. */ + return (sc->mw_count); +} + +static int +ntb_plx_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base, + caddr_t *vbase, size_t *size, size_t *align, size_t *align_size, + bus_addr_t *plimit) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + size_t off; + + if (mw_idx >= sc->mw_count) + return (EINVAL); + off = 0; + if (mw_idx == sc->b2b_mw) { + KASSERT(sc->b2b_off != 0, + ("user shouldn't get non-shared b2b mw")); + off = sc->b2b_off; + } + mw = &sc->mw_info[mw_idx]; + + /* Local to remote memory window parameters. */ + if (base != NULL) + *base = mw->mw_pbase + off; + if (vbase != NULL) + *vbase = mw->mw_vbase + off; + if (size != NULL) + *size = mw->mw_size - off; + + /* + * Remote to local memory window translation address alignment. + * XXX: In B2B mode we can change window size (and so alignmet) + * live, but there is no way to report it, so report safe value. + */ + if (align != NULL) + *align = mw->mw_size - off; + + /* + * Remote to local memory window size alignment. + * XXX: The chip has no limit registers. In B2B case size must be + * power of 2 (since we can reprogram BAR size), but there is no way + * to report it, so report 1MB -- minimal BAR size. In non-B2B case + * there is no control at all, so report the precofigured BAR size. + */ + if (align_size != NULL) { + if (sc->b2b_mw >= 0) + *align_size = 1024 * 1024; + else + *align_size = mw->mw_size - off; + } + + /* Remote to local memory window translation address upper limit. */ + if (plimit != NULL) + *plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR : + BUS_SPACE_MAXADDR_32BIT; + return (0); +} + +static int +ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + uint64_t addr, off, size, val64; + uint32_t val; + + mw = &sc->mw_info[mw_idx]; + addr = mw->mw_xlat_addr; + size = mw->mw_xlat_size; + off = 0; + if (mw_idx == sc->b2b_mw) { + off = sc->b2b_off; + KASSERT(off != 0, ("user shouldn't get non-shared b2b mw")); + + /* + * While generally we can set any BAR size on link side, + * for B2B shared window we can't go above preconfigured + * size due to BAR address alignment requirements. + */ + if (size > mw->mw_size - off) + return (EINVAL); + } + + if (size > 0) { + /* Round BAR size to next power of 2 or at least 1MB. */ + if (!powerof2(size)) + size = 1LL << flsll(size); + if (size < 1024 * 1024) + size = 1024 * 1024; + + /* Hardware requires addr aligned to BAR size. */ + if ((addr & (size - 1)) != 0) + return (EINVAL); + } + + if (mw->mw_64bit) { + if (sc->b2b_mw >= 0) { + /* Set Link Interface BAR size and enable/disable it. */ + val64 = 0; + if (size > 0) + val64 = (~(size - 1) & ~0xfffff); + val64 |= 0x4; + PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64); + PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32); + + /* Set Link Interface BAR address. */ + val64 = 0x2000000000000000 * mw->mw_bar + off; + val64 |= 0x4; + PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64); + PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar) + 4, val64 >> 32); + } + + /* Set Virtual Interface BARs address translation */ + PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr); + PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, addr >> 32); + } else { + /* Make sure we fit into 32-bit address space. */ + if ((addr & UINT32_MAX) != addr) + return (ERANGE); + if (((addr + size) & UINT32_MAX) != (addr + size)) + return (ERANGE); + + if (sc->b2b_mw >= 0) { + /* Set Link Interface BAR size and enable/disable it. */ + val = 0; + if (size > 0) + val = (~(size - 1) & ~0xfffff); + PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val); + + /* Set Link Interface BAR address. */ + val64 = 0x20000000 * mw->mw_bar + off; + PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64); + } + + /* Set Virtual Interface BARs address translation */ + PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr); + } + return (0); +} + +static int +ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + + if (mw_idx >= sc->mw_count) + return (EINVAL); + mw = &sc->mw_info[mw_idx]; + mw->mw_xlat_addr = addr; + mw->mw_xlat_size = size; + return (ntb_plx_mw_set_trans_internal(dev, mw_idx)); +} + +static int +ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx) +{ + + return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0)); +} + +static int +ntb_plx_mw_get_wc(device_t dev, unsigned idx, vm_memattr_t *mode) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + + if (idx >= sc->mw_count) + return (EINVAL); + mw = &sc->mw_info[idx]; + *mode = mw->mw_map_mode; + return (0); +} + +static int +ntb_plx_mw_set_wc(device_t dev, unsigned idx, vm_memattr_t mode) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + uint64_t off; + int rc; + + if (idx >= sc->mw_count) + return (EINVAL); + mw = &sc->mw_info[idx]; + if (mw->mw_map_mode == mode) + return (0); + + off = 0; + if (idx == sc->b2b_mw) { + KASSERT(sc->b2b_off != 0, + ("user shouldn't get non-shared b2b mw")); + off = sc->b2b_off; + } + + rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off, + mw->mw_size - off, mode); + if (rc == 0) + mw->mw_map_mode = mode; + return (rc); +} + +static uint8_t +ntb_plx_spad_count(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + return (sc->spad_count1 + sc->spad_count2); +} + +static int +ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + u_int off; + + if (idx >= sc->spad_count1 + sc->spad_count2) + return (EINVAL); + + if (idx < sc->spad_count1) + off = sc->spad_off1 + idx * 4; + else + off = sc->spad_off2 + (idx - sc->spad_count1) * 4; + bus_write_4(sc->conf_res, off, val); + return (0); +} + +static void +ntb_plx_spad_clear(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + int i; + + for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++) + ntb_plx_spad_write(dev, i, 0); +} + +static int +ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + u_int off; + + if (idx >= sc->spad_count1 + sc->spad_count2) + return (EINVAL); + + if (idx < sc->spad_count1) + off = sc->spad_off1 + idx * 4; + else + off = sc->spad_off2 + (idx - sc->spad_count1) * 4; + *val = bus_read_4(sc->conf_res, off); + return (0); +} + +static int +ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + u_int off; + + if (idx >= sc->spad_count1 + sc->spad_count2) + return (EINVAL); + + if (idx < sc->spad_count1) + off = sc->spad_offp1 + idx * 4; + else + off = sc->spad_offp2 + (idx - sc->spad_count1) * 4; + if (sc->b2b_mw >= 0) + bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val); + else + bus_write_4(sc->conf_res, off, val); + return (0); +} + +static int +ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + u_int off; + + if (idx >= sc->spad_count1 + sc->spad_count2) + return (EINVAL); + + if (idx < sc->spad_count1) + off = sc->spad_offp1 + idx * 4; + else + off = sc->spad_offp2 + (idx - sc->spad_count1) * 4; + if (sc->b2b_mw >= 0) + *val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off); + else + *val = bus_read_4(sc->conf_res, off); + return (0); +} + +static uint64_t +ntb_plx_db_valid_mask(device_t dev) +{ + + return ((1LL << PLX_NUM_DB) - 1); +} + +static int +ntb_plx_db_vector_count(device_t dev) +{ + + return (1); +} + +static uint64_t +ntb_plx_db_vector_mask(device_t dev, uint32_t vector) +{ + + if (vector > 0) + return (0); + return ((1LL << PLX_NUM_DB) - 1); +} + +static void +ntb_plx_db_clear(device_t dev, uint64_t bits) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits); +} + +static void +ntb_plx_db_clear_mask(device_t dev, uint64_t bits) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits); +} + +static uint64_t +ntb_plx_db_read(device_t dev) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c)); +} + +static void +ntb_plx_db_set_mask(device_t dev, uint64_t bits) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits); +} + +static int +ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + struct ntb_plx_mw_info *mw; + + KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL")); + + if (sc->b2b_mw >= 0) { + mw = &sc->mw_info[sc->b2b_mw]; + *db_addr = (uint64_t)mw->mw_pbase + PLX_NTX_BASE(sc) + 0xc4c; + } else { + *db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc); + *db_addr += sc->link ? 0xc4c : 0xc5c; + } + *db_size = 4; + return (0); +} + +static void +ntb_plx_peer_db_set(device_t dev, uint64_t bit) +{ + struct ntb_plx_softc *sc = device_get_softc(dev); + + if (sc->b2b_mw >= 0) + BNTX_WRITE(sc, 0xc4c, bit); + else + NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit); +} + +static device_method_t ntb_plx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ntb_plx_probe), + DEVMETHOD(device_attach, ntb_plx_attach), + DEVMETHOD(device_detach, ntb_plx_detach), + /* NTB interface */ + DEVMETHOD(ntb_link_is_up, ntb_plx_link_is_up), + DEVMETHOD(ntb_link_enable, ntb_plx_link_enable), + DEVMETHOD(ntb_link_disable, ntb_plx_link_disable), + DEVMETHOD(ntb_link_enabled, ntb_plx_link_enabled), + DEVMETHOD(ntb_mw_count, ntb_plx_mw_count), + DEVMETHOD(ntb_mw_get_range, ntb_plx_mw_get_range), + DEVMETHOD(ntb_mw_set_trans, ntb_plx_mw_set_trans), + DEVMETHOD(ntb_mw_clear_trans, ntb_plx_mw_clear_trans), + DEVMETHOD(ntb_mw_get_wc, ntb_plx_mw_get_wc), + DEVMETHOD(ntb_mw_set_wc, ntb_plx_mw_set_wc), + DEVMETHOD(ntb_spad_count, ntb_plx_spad_count), + DEVMETHOD(ntb_spad_clear, ntb_plx_spad_clear), + DEVMETHOD(ntb_spad_write, ntb_plx_spad_write), + DEVMETHOD(ntb_spad_read, ntb_plx_spad_read), + DEVMETHOD(ntb_peer_spad_write, ntb_plx_peer_spad_write), + DEVMETHOD(ntb_peer_spad_read, ntb_plx_peer_spad_read), + DEVMETHOD(ntb_db_valid_mask, ntb_plx_db_valid_mask), + DEVMETHOD(ntb_db_vector_count, ntb_plx_db_vector_count), + DEVMETHOD(ntb_db_vector_mask, ntb_plx_db_vector_mask), + DEVMETHOD(ntb_db_clear, ntb_plx_db_clear), + DEVMETHOD(ntb_db_clear_mask, ntb_plx_db_clear_mask), + DEVMETHOD(ntb_db_read, ntb_plx_db_read), + DEVMETHOD(ntb_db_set_mask, ntb_plx_db_set_mask), + DEVMETHOD(ntb_peer_db_addr, ntb_plx_peer_db_addr), + DEVMETHOD(ntb_peer_db_set, ntb_plx_peer_db_set), + DEVMETHOD_END +}; + +static DEFINE_CLASS_0(ntb_hw, ntb_plx_driver, ntb_plx_methods, + sizeof(struct ntb_plx_softc)); +DRIVER_MODULE(ntb_hw_plx, pci, ntb_plx_driver, ntb_hw_devclass, NULL, NULL); +MODULE_DEPEND(ntb_hw_plx, ntb, 1, 1, 1); +MODULE_VERSION(ntb_hw_plx, 1); diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index ce64f83b03f3..20a1c7db3789 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -658,6 +658,15 @@ device iwn6050fw device wpifw # +# Non-Transparent Bridge (NTB) drivers +# +device if_ntb # Virtual NTB network interface +device ntb_transport # NTB packet transport driver +device ntb # NTB hardware interface +device ntb_hw_intel # Intel NTB hardware driver +device ntb_hw_plx # PLX NTB hardware driver + +# # ATA raid adapters # device pst diff --git a/sys/modules/ntb/Makefile b/sys/modules/ntb/Makefile index 3eaf7516a779..f71ef09d9b35 100644 --- a/sys/modules/ntb/Makefile +++ b/sys/modules/ntb/Makefile @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= ntb ntb_hw ntb_transport if_ntb +SUBDIR= ntb ntb_hw_intel ntb_hw_plx ntb_transport if_ntb .include <bsd.subdir.mk> diff --git a/sys/modules/ntb/ntb_hw_intel/Makefile b/sys/modules/ntb/ntb_hw_intel/Makefile new file mode 100644 index 000000000000..720cb16c5216 --- /dev/null +++ b/sys/modules/ntb/ntb_hw_intel/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/ntb/ntb_hw + +KMOD = ntb_hw_intel +SRCS = ntb_hw_intel.c +SRCS += device_if.h bus_if.h pci_if.h ntb_if.h + +.include <bsd.kmod.mk> diff --git a/sys/modules/ntb/ntb_hw/Makefile b/sys/modules/ntb/ntb_hw_plx/Makefile index ad77e97cc935..4852e7a30fe6 100644 --- a/sys/modules/ntb/ntb_hw/Makefile +++ b/sys/modules/ntb/ntb_hw_plx/Makefile @@ -2,8 +2,8 @@ .PATH: ${SRCTOP}/sys/dev/ntb/ntb_hw -KMOD = ntb_hw -SRCS = ntb_hw.c +KMOD = ntb_hw_plx +SRCS = ntb_hw_plx.c SRCS += device_if.h bus_if.h pci_if.h ntb_if.h .include <bsd.kmod.mk> |