DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
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.

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox