forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
12 KiB
263 lines
12 KiB
=========== |
|
NTB Drivers |
|
=========== |
|
|
|
NTB (Non-Transparent Bridge) is a type of PCI-Express bridge chip that connects |
|
the separate memory systems of two or more computers to the same PCI-Express |
|
fabric. Existing NTB hardware supports a common feature set: doorbell |
|
registers and memory translation windows, as well as non common features like |
|
scratchpad and message registers. Scratchpad registers are read-and-writable |
|
registers that are accessible from either side of the device, so that peers can |
|
exchange a small amount of information at a fixed address. Message registers can |
|
be utilized for the same purpose. Additionally they are provided with |
|
special status bits to make sure the information isn't rewritten by another |
|
peer. Doorbell registers provide a way for peers to send interrupt events. |
|
Memory windows allow translated read and write access to the peer memory. |
|
|
|
NTB Core Driver (ntb) |
|
===================== |
|
|
|
The NTB core driver defines an api wrapping the common feature set, and allows |
|
clients interested in NTB features to discover NTB the devices supported by |
|
hardware drivers. The term "client" is used here to mean an upper layer |
|
component making use of the NTB api. The term "driver," or "hardware driver," |
|
is used here to mean a driver for a specific vendor and model of NTB hardware. |
|
|
|
NTB Client Drivers |
|
================== |
|
|
|
NTB client drivers should register with the NTB core driver. After |
|
registering, the client probe and remove functions will be called appropriately |
|
as ntb hardware, or hardware drivers, are inserted and removed. The |
|
registration uses the Linux Device framework, so it should feel familiar to |
|
anyone who has written a pci driver. |
|
|
|
NTB Typical client driver implementation |
|
---------------------------------------- |
|
|
|
Primary purpose of NTB is to share some peace of memory between at least two |
|
systems. So the NTB device features like Scratchpad/Message registers are |
|
mainly used to perform the proper memory window initialization. Typically |
|
there are two types of memory window interfaces supported by the NTB API: |
|
inbound translation configured on the local ntb port and outbound translation |
|
configured by the peer, on the peer ntb port. The first type is |
|
depicted on the next figure:: |
|
|
|
Inbound translation: |
|
|
|
Memory: Local NTB Port: Peer NTB Port: Peer MMIO: |
|
____________ |
|
| dma-mapped |-ntb_mw_set_trans(addr) | |
|
| memory | _v____________ | ______________ |
|
| (addr) |<======| MW xlat addr |<====| MW base addr |<== memory-mapped IO |
|
|------------| |--------------| | |--------------| |
|
|
|
So typical scenario of the first type memory window initialization looks: |
|
1) allocate a memory region, 2) put translated address to NTB config, |
|
3) somehow notify a peer device of performed initialization, 4) peer device |
|
maps corresponding outbound memory window so to have access to the shared |
|
memory region. |
|
|
|
The second type of interface, that implies the shared windows being |
|
initialized by a peer device, is depicted on the figure:: |
|
|
|
Outbound translation: |
|
|
|
Memory: Local NTB Port: Peer NTB Port: Peer MMIO: |
|
____________ ______________ |
|
| dma-mapped | | | MW base addr |<== memory-mapped IO |
|
| memory | | |--------------| |
|
| (addr) |<===================| MW xlat addr |<-ntb_peer_mw_set_trans(addr) |
|
|------------| | |--------------| |
|
|
|
Typical scenario of the second type interface initialization would be: |
|
1) allocate a memory region, 2) somehow deliver a translated address to a peer |
|
device, 3) peer puts the translated address to NTB config, 4) peer device maps |
|
outbound memory window so to have access to the shared memory region. |
|
|
|
As one can see the described scenarios can be combined in one portable |
|
algorithm. |
|
|
|
Local device: |
|
1) Allocate memory for a shared window |
|
2) Initialize memory window by translated address of the allocated region |
|
(it may fail if local memory window initialization is unsupported) |
|
3) Send the translated address and memory window index to a peer device |
|
|
|
Peer device: |
|
1) Initialize memory window with retrieved address of the allocated |
|
by another device memory region (it may fail if peer memory window |
|
initialization is unsupported) |
|
2) Map outbound memory window |
|
|
|
In accordance with this scenario, the NTB Memory Window API can be used as |
|
follows: |
|
|
|
Local device: |
|
1) ntb_mw_count(pidx) - retrieve number of memory ranges, which can |
|
be allocated for memory windows between local device and peer device |
|
of port with specified index. |
|
2) ntb_get_align(pidx, midx) - retrieve parameters restricting the |
|
shared memory region alignment and size. Then memory can be properly |
|
allocated. |
|
3) Allocate physically contiguous memory region in compliance with |
|
restrictions retrieved in 2). |
|
4) ntb_mw_set_trans(pidx, midx) - try to set translation address of |
|
the memory window with specified index for the defined peer device |
|
(it may fail if local translated address setting is not supported) |
|
5) Send translated base address (usually together with memory window |
|
number) to the peer device using, for instance, scratchpad or message |
|
registers. |
|
|
|
Peer device: |
|
1) ntb_peer_mw_set_trans(pidx, midx) - try to set received from other |
|
device (related to pidx) translated address for specified memory |
|
window. It may fail if retrieved address, for instance, exceeds |
|
maximum possible address or isn't properly aligned. |
|
2) ntb_peer_mw_get_addr(widx) - retrieve MMIO address to map the memory |
|
window so to have an access to the shared memory. |
|
|
|
Also it is worth to note, that method ntb_mw_count(pidx) should return the |
|
same value as ntb_peer_mw_count() on the peer with port index - pidx. |
|
|
|
NTB Transport Client (ntb\_transport) and NTB Netdev (ntb\_netdev) |
|
------------------------------------------------------------------ |
|
|
|
The primary client for NTB is the Transport client, used in tandem with NTB |
|
Netdev. These drivers function together to create a logical link to the peer, |
|
across the ntb, to exchange packets of network data. The Transport client |
|
establishes a logical link to the peer, and creates queue pairs to exchange |
|
messages and data. The NTB Netdev then creates an ethernet device using a |
|
Transport queue pair. Network data is copied between socket buffers and the |
|
Transport queue pair buffer. The Transport client may be used for other things |
|
besides Netdev, however no other applications have yet been written. |
|
|
|
NTB Ping Pong Test Client (ntb\_pingpong) |
|
----------------------------------------- |
|
|
|
The Ping Pong test client serves as a demonstration to exercise the doorbell |
|
and scratchpad registers of NTB hardware, and as an example simple NTB client. |
|
Ping Pong enables the link when started, waits for the NTB link to come up, and |
|
then proceeds to read and write the doorbell scratchpad registers of the NTB. |
|
The peers interrupt each other using a bit mask of doorbell bits, which is |
|
shifted by one in each round, to test the behavior of multiple doorbell bits |
|
and interrupt vectors. The Ping Pong driver also reads the first local |
|
scratchpad, and writes the value plus one to the first peer scratchpad, each |
|
round before writing the peer doorbell register. |
|
|
|
Module Parameters: |
|
|
|
* unsafe - Some hardware has known issues with scratchpad and doorbell |
|
registers. By default, Ping Pong will not attempt to exercise such |
|
hardware. You may override this behavior at your own risk by setting |
|
unsafe=1. |
|
* delay\_ms - Specify the delay between receiving a doorbell |
|
interrupt event and setting the peer doorbell register for the next |
|
round. |
|
* init\_db - Specify the doorbell bits to start new series of rounds. A new |
|
series begins once all the doorbell bits have been shifted out of |
|
range. |
|
* dyndbg - It is suggested to specify dyndbg=+p when loading this module, and |
|
then to observe debugging output on the console. |
|
|
|
NTB Tool Test Client (ntb\_tool) |
|
-------------------------------- |
|
|
|
The Tool test client serves for debugging, primarily, ntb hardware and drivers. |
|
The Tool provides access through debugfs for reading, setting, and clearing the |
|
NTB doorbell, and reading and writing scratchpads. |
|
|
|
The Tool does not currently have any module parameters. |
|
|
|
Debugfs Files: |
|
|
|
* *debugfs*/ntb\_tool/*hw*/ |
|
A directory in debugfs will be created for each |
|
NTB device probed by the tool. This directory is shortened to *hw* |
|
below. |
|
* *hw*/db |
|
This file is used to read, set, and clear the local doorbell. Not |
|
all operations may be supported by all hardware. To read the doorbell, |
|
read the file. To set the doorbell, write `s` followed by the bits to |
|
set (eg: `echo 's 0x0101' > db`). To clear the doorbell, write `c` |
|
followed by the bits to clear. |
|
* *hw*/mask |
|
This file is used to read, set, and clear the local doorbell mask. |
|
See *db* for details. |
|
* *hw*/peer\_db |
|
This file is used to read, set, and clear the peer doorbell. |
|
See *db* for details. |
|
* *hw*/peer\_mask |
|
This file is used to read, set, and clear the peer doorbell |
|
mask. See *db* for details. |
|
* *hw*/spad |
|
This file is used to read and write local scratchpads. To read |
|
the values of all scratchpads, read the file. To write values, write a |
|
series of pairs of scratchpad number and value |
|
(eg: `echo '4 0x123 7 0xabc' > spad` |
|
# to set scratchpads `4` and `7` to `0x123` and `0xabc`, respectively). |
|
* *hw*/peer\_spad |
|
This file is used to read and write peer scratchpads. See |
|
*spad* for details. |
|
|
|
NTB MSI Test Client (ntb\_msi\_test) |
|
------------------------------------ |
|
|
|
The MSI test client serves to test and debug the MSI library which |
|
allows for passing MSI interrupts across NTB memory windows. The |
|
test client is interacted with through the debugfs filesystem: |
|
|
|
* *debugfs*/ntb\_tool/*hw*/ |
|
A directory in debugfs will be created for each |
|
NTB device probed by the tool. This directory is shortened to *hw* |
|
below. |
|
* *hw*/port |
|
This file describes the local port number |
|
* *hw*/irq*_occurrences |
|
One occurrences file exists for each interrupt and, when read, |
|
returns the number of times the interrupt has been triggered. |
|
* *hw*/peer*/port |
|
This file describes the port number for each peer |
|
* *hw*/peer*/count |
|
This file describes the number of interrupts that can be |
|
triggered on each peer |
|
* *hw*/peer*/trigger |
|
Writing an interrupt number (any number less than the value |
|
specified in count) will trigger the interrupt on the |
|
specified peer. That peer's interrupt's occurrence file |
|
should be incremented. |
|
|
|
NTB Hardware Drivers |
|
==================== |
|
|
|
NTB hardware drivers should register devices with the NTB core driver. After |
|
registering, clients probe and remove functions will be called. |
|
|
|
NTB Intel Hardware Driver (ntb\_hw\_intel) |
|
------------------------------------------ |
|
|
|
The Intel hardware driver supports NTB on Xeon and Atom CPUs. |
|
|
|
Module Parameters: |
|
|
|
* b2b\_mw\_idx |
|
If the peer ntb is to be accessed via a memory window, then use |
|
this memory window to access the peer ntb. A value of zero or positive |
|
starts from the first mw idx, and a negative value starts from the last |
|
mw idx. Both sides MUST set the same value here! The default value is |
|
`-1`. |
|
* b2b\_mw\_share |
|
If the peer ntb is to be accessed via a memory window, and if |
|
the memory window is large enough, still allow the client to use the |
|
second half of the memory window for address translation to the peer. |
|
* xeon\_b2b\_usd\_bar2\_addr64 |
|
If using B2B topology on Xeon hardware, use |
|
this 64 bit address on the bus between the NTB devices for the window |
|
at BAR2, on the upstream side of the link. |
|
* xeon\_b2b\_usd\_bar4\_addr64 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_usd\_bar4\_addr32 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_usd\_bar5\_addr32 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_dsd\_bar2\_addr64 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_dsd\_bar4\_addr64 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_dsd\_bar4\_addr32 - See *xeon\_b2b\_bar2\_addr64*. |
|
* xeon\_b2b\_dsd\_bar5\_addr32 - See *xeon\_b2b\_bar2\_addr64*.
|
|
|