From: Stephen Hemminger <stephen@networkplumber.org>
To: David Marchand <david.marchand@redhat.com>
Cc: Raghavendra Ningoji <raghavendra.ningoji@amd.com>,
dev@dpdk.org, jingjing.wu@intel.com, thomas@monjalon.net,
selwin.sebastian@amd.com, bhagyada.modali@amd.com,
bruce.richardson@intel.com, sachin.saxena@oss.nxp.com,
hemant.agrawal@nxp.com
Subject: Re: [PATCH v4 0/3] raw/ntb: add AMD NTB support
Date: Mon, 26 Oct 2026 10:00:34 -0700 [thread overview]
Message-ID: <20261026100034.0e4497e0@phoenix.local> (raw)
In-Reply-To: <CAJFAV8zYm79ZyWOSP4UNjk7AGo+J4Bor_hk+JoSryZKEdZD0CA@mail.gmail.com>
On Mon, 26 Oct 2026 11:26:01 -0400
David Marchand <david.marchand@redhat.com> wrote:
> >
> > The common NTB code validates the vendor ops once at probe time, and the
> > vendor abstraction is built around a small set of mandatory ops instead
> > of optional hooks with built-in fallbacks:
> >
> > - Patch 1 is a preparation commit that enforces the vendor ops once, at
> > probe time, and removes the per-call NULL checks that are scattered
> > throughout the common code.
> >
> > - Patch 2 generalizes the framework for multiple vendors. The link
> > bring-up/tear-down is now expressed through mandatory ops
> > (dev_handshake, peer_mw_validate, read_peer_config, link_cleanup); the
> > former built-in scratchpad logic moved into the Intel driver. The
> > mw_set_trans op is gone (it is now a vendor-internal concern of the
> > handshake), and there is a single common interrupt handler with just
> > one optional op (handle_hw_event) for vendor-specific hardware events.
> >
> > - Patch 3 adds the AMD hardware driver, its documentation, release note
> > and MAINTAINERS entry.
> >
> > A few AMD-specific hardware details worth noting for reviewers:
> >
> > - Primary/secondary topology. One endpoint enumerates as the primary
> > (device ID 0x14c0) and the other as the secondary (0x14c3), rather
> > than the Intel back-to-back model.
> >
> > - Packed scratchpad handshake. The hardware exposes a single shared
> > 16-register scratchpad bank split into two disjoint 8-register sets
> > (one per side), so the driver uses a packed handshake layout that
> > fits in 8 registers, plugged in through the dev_handshake,
> > peer_mw_validate and read_peer_config ops.
> >
> > - Outbound translation window. AMD NTB uses an outbound translation
> > window: a write to a BARxx memory-window offset is forwarded to
> > (xlat_base | offset) in the peer's memory rather than
> > (xlat_base + offset). The translation base must therefore be aligned
> > to a power of two >= the window length so that no offset bit collides
> > with a set bit in the base. This is reported to applications through
> > the rte_pmd_ntb_get_mem_align() API and honoured by the ntb example
> > when reserving the memory window memzone.
> >
> > - Secondary-side link status. On the secondary side the device's own
> > PCIe link status does not reflect the true inter-host link, so the
> > speed and width are read from the upstream switch port via sysfs.
> >
> > Tested on a two-node setup (primary + secondary EPYC Embedded hosts)
> > with the dpdk-ntb example: the link comes up at the expected speed and
> > width on both sides, and file transfers are byte-correct end to end for
> > both small and large files.
> >
> > Changes since v3:
> >
> > - Simplified the probe-time vendor ops check (patch 1) to a plain
> > per-member macro instead of an offsetof() table.
> >
> > - Removed the mw_size_align field from struct ntb_dev_info entirely
> > (patch 2): applications must now use rte_pmd_ntb_get_mem_align(). This
> > is documented in the API changes section of the release notes.
> >
> > - Removed the unused pmd_private field from struct ntb_hw and the whole
> > struct amd_ntb_hw (patch 3): self_mmio is just ntb->hw_addr, peer_mmio
> > becomes AMD_PEER_MMIO(ntb), the scratchpad offsets become an
> > AMD_SPAD_BASE(ntb, peer) macro, and int_mask/peer_status/ctl_status
> > were unused.
> >
> > - Sorted AMD alphabetically before Intel in meson.build, the ntb_hw
> > header include, the PCI id mapping table and usertools/dpdk-devbind.py.
> >
> > - Moved the primary/secondary topology definitions (NTB_TOPO_PRI/SEC)
> > from patch 2 to patch 3 where they are first used.
> >
> > - Updated the Limitation section of doc/guides/rawdevs/ntb.rst to list
> > the supported AMD processors.
>
> - "external" build was broken for the example as spotted by the CI.
> https://github.com/ovsrobot/dpdk/actions/runs/40296962846/job/121485246438
> This is a known limitation of the .pc provided by DPDK (which Robin
> recently tried to fix).
> I tested and squashed a simple fix:
> https://github.com/david-marchand/dpdk/commit/16b0d741ebf39b22ebb696c07f2ed44ad383bfc9
>
> - Some commitlogs were not updated after the v4 changes, fixed.
>
> - Some strange indentation issues were still there, fixed.
>
> With all those fixes applied, I pushed this driver update.
> Thanks.
I think merge was premature. More detailed AI review reports:
Subject: Re: [PATCH 0/4] raw/ntb: AMD NTB support
Post-merge review of the raw/ntb series (1/4 - 3/4) against current
main. Findings below are for follow-up fixes.
Series summary
--------------
The ops-table refactor in 1/4 and 2/4 is reasonable. The main problems
are a type-confusion hole in the new public API, an unbounded
peer-supplied loop count that writes past peer_mw_base[], and AMD event
handling that cannot actually run as wired.
[PATCH 2/4] raw/ntb: generalize framework for multiple vendors
--------------------------------------------------------------
Error: rte_pmd_ntb_get_mem_align() trusts any rawdev id.
It checks only dev_id < RTE_RAWDEV_MAX_DEVS and dev_private != NULL,
then casts dev_private to struct ntb_hw. Passing the id of an
unattached slot or of a non-NTB rawdev (dpaa2, ifpga, cnxk...) calls
through a garbage ntb_ops pointer. Check the device is valid and is
ours:
if (!rte_rawdev_pmd_is_valid_dev(dev_id))
return 0;
dev = rte_rawdev_pmd_get_dev(dev_id);
if (dev->dev_ops != &ntb_ops)
return 0;
Also, an out of range mw_id returns RTE_CACHE_LINE_SIZE, which
contradicts the doxygen ("0 on error"). Return 0.
Warning: Rx EOP guard leaks the partial chain and desyncs the ring.
On the new "Malformed rx stream" path the descriptors already walked
have advanced last_used/last_avail and been chained under `first`,
but nb_rx is not incremented, so the chain is never returned or
freed. If nb_rx == 0 the refilled descriptors are not published
either (avail_cnt not written) while rxq->last_avail has moved.
The mbuf-alloc failure path has the same bug already; the guard
copies it. Free the partial chain and only advance ring indexes for
completed packets.
The guard also bounds on nb_rx_desc, not on the descriptors the peer
actually published (used_cnt - last_used), so it still reads entries
the peer has not written. This is a fix for code in released
versions; it should be its own patch with Fixes: and
Cc: stable@dpdk.org, not folded into the refactor.
Info: removing mw_size_align changes the layout of the installed
struct ntb_dev_info; note it under ABI Changes as well.
Info: examples/ntb/Makefile adds -lrte_raw_ntb to LDFLAGS, which also
hits the static target. Other examples (l2fwd-crypto,
vm_power_manager) use LDFLAGS_SHARED.
[PATCH 3/4] raw/ntb: support AMD NTB
------------------------------------
Error: peer_used_mws from the scratchpad overflows peer_mw_base[].
amd_ntb_read_peer_config():
ntb->peer_used_mws = (info >> 16) & 0xff;
for (i = 0; i < ntb->peer_used_mws; i++)
...
ntb->peer_mw_base[i] = ...
peer_mw_base is rte_zmalloc'd with mw_cnt (2) entries. A peer
advertising more than 2 (bug, version skew, or just garbage in an
uninitialised scratchpad) writes past the allocation. Intel has the
same pattern; fix both:
if (peer_used_mws > ntb->mw_cnt) {
NTB_LOG(ERR, "Peer used mws %u > mw cnt %u",
peer_used_mws, ntb->mw_cnt);
return -EINVAL;
}
Warning: hardware events are never delivered.
- AMD_INTMASK_OFFSET is defined but never written, so event
delivery depends on the reset default.
- ntb_init_hw() enables db_cnt (16) eventfds; the comment in
amd_ntb_vector_bind() says events have their own MSI-X vectors
(AMD_MSIX_VECTOR_COUNT is 24), and those are never enabled.
- handle_hw_event is only called at the bottom of
ntb_dev_intr_handler(), after doorbells 0/1/2 have already
returned early, so it runs only on a stray doorbell.
As written amd_ntb_handle_hw_event() is effectively dead code.
Either wire up the event vector and INTMASK, or drop it.
Warning: doorbell interrupts with vfio-pci MSI-X.
amd_ntb_vector_bind() is a no-op and doorbells map 1:1 to MSI-X
vectors. The callback is registered on the device intr handle only,
so with vfio-pci only vector 0 (DB0) reaches ntb_dev_intr_handler().
DB1 (peer going down) and DB2 are lost, so the stop handshake in
ntb_dev_stop() never completes. Was this tested with vfio-pci, or
only igb_uio? If uio only, say so in ntb.rst.
Warning: amd_ntb_handle_hw_event() switches on a bitmask.
INTSTAT can have several bits set at once; any combination falls to
default and is logged as unknown and never acked to the SMU. Loop
over the set bits, or ack all of (event & AMD_EVENT_INTMASK) after
handling D0. Also drop the duplicated fallthrough comment; one
/* fallthrough */ is enough.
Warning: ioremap range check is off by one.
addr <= ntb->peer_mw_base[i] + ntb->mw_size[i]
accepts one past the end of the window. Should be <. Copied from
intel_ntb_ioremap(), which needs the same fix.
Warning: ntb->mw_size is never freed.
Allocated in amd_ntb_dev_init(), not freed on later ntb_init_hw()
failure or in ntb_destroy(). Same leak exists on the Intel side;
free it in common code at release.
Info: unused defines in ntb_hw_amd.h: AMD_SPADMUTEX_OFFSET,
AMD_DBFM_OFFSET, AMD_INTMASK_OFFSET, AMD_MSIX_VECTOR_COUNT.
Info: amd_ntb_mw_set_trans() checks IOVA alignment, but
rte_memzone_reserve_aligned() aligns the VA. With IOVA as PA and a
window larger than the hugepage size the IOVA is not guaranteed to
be aligned, and configure fails with -EINVAL. Worth a line in
ntb.rst that large windows need IOVA as VA (or 1G pages).
Info: amd_ntb_peer_mw_validate() only compares the window count; the
Intel version also checks sizes. Mismatched BAR sizes between hosts
go undetected.
next prev parent reply other threads:[~2026-10-26 17:00 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 8:55 [PATCH v4 0/3] raw/ntb: add AMD NTB support Raghavendra Ningoji
2026-10-26 8:55 ` [PATCH v4 1/3] raw/ntb: validate vendor ops at probe Raghavendra Ningoji
2026-10-26 8:55 ` [PATCH v4 2/3] raw/ntb: generalize framework for multiple vendors Raghavendra Ningoji
2026-10-26 8:55 ` [PATCH v4 3/3] raw/ntb: add AMD NTB support Raghavendra Ningoji
2026-10-26 15:26 ` [PATCH v4 0/3] " David Marchand
2026-10-26 17:00 ` Stephen Hemminger [this message]
2026-10-27 9:08 ` David Marchand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261026100034.0e4497e0@phoenix.local \
--to=stephen@networkplumber.org \
--cc=bhagyada.modali@amd.com \
--cc=bruce.richardson@intel.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=hemant.agrawal@nxp.com \
--cc=jingjing.wu@intel.com \
--cc=raghavendra.ningoji@amd.com \
--cc=sachin.saxena@oss.nxp.com \
--cc=selwin.sebastian@amd.com \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.