[PATCH net-next v7 11/14] net: lan966x: add PCIe FDMA MTU change support
Daniel Machon
daniel.machon at microchip.com
Wed Sep 23 02:46:22 PDT 2026
> Thank you for your contribution! Sashiko AI review found 4 potential
> issue(s) to consider.
>
> Critical: 0 · High: 2 (2) · Medium: 1 (1) · Low: 1
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] MTU change during or after PCIe FDMA teardown runs the full
> reload on freed/quiesced state: unbounded napi_disable() while holding…
> - [High] The new resize readiness check publishes lan966x->rx.lan966x
> before the PCI FDMA rings exist, so an MTU change can race with ring…
> - [Medium] The new PCIe resize path retires DMA rings and tears down
> their ATU outbound window without ever confirming the hardware is…
> - [Low] FDMA_PCI_DB_SIZE_MAX / FDMA_PCI_MAX_MTU perform unsigned
> arithmetic with no underflow guard and no BUILD_BUG_ON, even though…
>
> Pre-existing issues:
> - [High] The hazard the new PCIe reload path documents and avoids is
> still live in the sibling platform reload path, which this series…
> - [High] The two implementers of lan966x_fdma_ops::fdma_resize now
> disagree about the 'rings not built yet' precondition, and the…
> - [Medium] Window in which DEV_MAC_MAXLEN_CFG exceeds the DCB buffer
> size, combined with a missing SOF/EOF check in…
>
> --
>
> net: lan966x: add PCIe FDMA MTU change support
>
> This adds MTU change support to the PCIe FDMA path by reallocating the
> contiguous ATU-mapped RX and TX rings at the new size and falling back to
> the old buffers on failure. It also caps the PCIe DCB ring at 256 entries
> and advertises a derived dev->max_mtu (FDMA_PCI_MAX_MTU) when the FDMA is
> in use.
>
> A few questions below about the new reload path and the new size macros.
>
> > diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma_pci.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma_pci.c
> > index 5d6902459f20..940425beec2f 100644
> > --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma_pci.c
> > +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma_pci.c
> > @@ -358,7 +358,7 @@ static int lan966x_fdma_pci_init(struct lan966x *lan966x)
> > lan966x->rx.lan966x = lan966x;
> > lan966x->rx.max_mtu = lan966x_fdma_get_max_frame(lan966x);
> > rx_fdma->channel_id = FDMA_XTR_CHANNEL;
> > - rx_fdma->n_dcbs = FDMA_DCB_MAX;
> > + rx_fdma->n_dcbs = FDMA_PCI_DCB_MAX;
> > rx_fdma->n_dbs = FDMA_RX_DCB_MAX_DBS;
> > rx_fdma->priv = lan966x;
> > rx_fdma->db_size = FDMA_PCI_DB_SIZE(lan966x->rx.max_mtu);
>
> [Severity: High]
> Can an MTU change race with ring construction here? lan966x_fdma_pci_init()
> sets rx.lan966x before it fills in channel_id/n_dcbs/n_dbs/db_size/size and
> before the two sleeping allocations in lan966x_fdma_pci_rx_alloc() and
> lan966x_fdma_pci_tx_alloc().
>
> The netdevs are already live at that point: lan966x_probe() runs the whole
> port loop, including lan966x_probe_port()->register_netdev() and
> lan966x_port_init()->lan966x_fdma_netdev_init()->netif_napi_add()+
> napi_enable(), and only calls ops->fdma_init() afterwards, without holding
> RTNL.
>
> So an rtnl-held ndo_change_mtu in that window sees rx.lan966x != NULL, passes
> the new guard in lan966x_fdma_pci_resize(), finds a max_mtu that differs from
> the partially initialised rx.max_mtu, and enters __lan966x_fdma_pci_reload().
> Both contexts then write the same lan966x->rx.fdma / lan966x->tx.fdma:
>
> lan966x_fdma_pci_reload()
> lan966x_fdma_rx_disable(&lan966x->rx) /* channel_id still 0 */
> lan966x->rx.fdma.atu_region = NULL; /* under probe's feet */
> lan966x_fdma_pci_rx_alloc(&lan966x->rx) /* second ring */
>
> Does this leak probe's ring plus its ATU region (only
> FDMA_PCI_ATU_REGION_MAX == 6 exist), or trip WARN_ON(fdma->atu_region) /
> -ENOSPC in fdma_pci_atu_region_map()? And on the failure branch,
> lan966x_fdma_pci_reset_mem() dereferences tx->fdma.atu_region->base_addr,
> which is NULL in a snapshot taken before probe allocated it.
Yes, same issue as adressed in #4. Theres a race because netdevs are registered
before initialization (in this case FDMA) has happened. The proper fix is a
reordering of the probe initialization.
>
> [ ... ]
>
> > @@ -391,9 +391,156 @@ static int lan966x_fdma_pci_init(struct lan966x *lan966x)
> > return 0;
> > }
> >
> > +/* Reset existing rx and tx buffers. */
> > +static void lan966x_fdma_pci_reset_mem(struct lan966x *lan966x)
> > +{
> > + struct lan966x_rx *rx = &lan966x->rx;
> > + struct lan966x_tx *tx = &lan966x->tx;
> > +
> > + memset(rx->fdma.dcbs, 0, rx->fdma.size);
> > + memset(tx->fdma.dcbs, 0, tx->fdma.size);
> > +
> > + fdma_dcbs_init(&rx->fdma,
> > + FDMA_DCB_INFO_DATAL(rx->fdma.db_size - XDP_PACKET_HEADROOM),
> > + FDMA_DCB_STATUS_INTR);
> > +
> > + fdma_dcbs_init(&tx->fdma,
> > + FDMA_DCB_INFO_DATAL(tx->fdma.db_size),
> > + FDMA_DCB_STATUS_DONE);
> > +
> > + lan966x_fdma_llp_configure(lan966x,
> > + tx->fdma.atu_region->base_addr,
> > + tx->fdma.channel_id);
> > + lan966x_fdma_llp_configure(lan966x,
> > + rx->fdma.atu_region->base_addr,
> > + rx->fdma.channel_id);
> > +}
> > +
>
> [ ... ]
>
> > +static int lan966x_fdma_pci_reload(struct lan966x *lan966x, int new_mtu)
> > +{
> > + struct fdma tx_fdma_old = lan966x->tx.fdma;
> > + struct fdma rx_fdma_old = lan966x->rx.fdma;
> > + u32 old_mtu = lan966x->rx.max_mtu;
> > + int err;
> > +
> > + napi_disable(&lan966x->napi);
> > + lan966x_fdma_tx_disable_netdev(lan966x);
> > + lan966x_fdma_rx_disable(&lan966x->rx);
> > + lan966x_fdma_tx_disable(&lan966x->tx);
>
> [Severity: High]
> What happens if an MTU change lands after the PCIe FDMA has already been torn
> down? lan966x_fdma_pci_deinit() disables NAPI and frees both coherent rings,
> but it leaves lan966x->rx.lan966x set, lan966x->fdma true and fdma->dcbs
> dangling. It also runs before the netdevs are unregistered and without RTNL:
>
> lan966x_remove()
> lan966x->ops->fdma_deinit(lan966x);
> lan966x_cleanup_ports(lan966x); /* unregister_netdev() here */
>
> The new guard in lan966x_fdma_pci_resize() only rejects "rings not built
> yet", so an ndo_change_mtu in that window passes it and reaches this
> function. Three things then follow in order:
>
> napi_disable(&lan966x->napi) on an already-disabled NAPI. Does
> napi_disable_locked() spin forever in
>
> while (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC))
> usleep_range(20, 200);
>
> since nothing clears those bits until napi_enable()? That task holds RTNL,
> so unregister_netdev() in lan966x_remove() can never complete.
>
> If that is somehow passed, the success path below calls
> fdma_free_coherent_and_unmap() on the stale rx_fdma_old/tx_fdma_old
> snapshots, so dma_free_coherent(dev, fdma->size, fdma->dcbs, fdma->dma) runs
> a second time on the multi-MB blocks deinit already released.
>
> And the restore: path calls lan966x_fdma_pci_reset_mem(), which memsets up to
> rx->fdma.size bytes into freed DMA memory and then dereferences
> tx->fdma.atu_region->base_addr, which fdma_free_coherent_and_unmap() already
> set to NULL.
>
> Would a "rings are live" state check (or clearing rx.lan966x and dcbs in
> deinit, or unregistering the netdevs before fdma_deinit) close this?
lan966x_remove() is not touched by this series (apart from calling
ops->fdma_deinit), so I'd say pre-existing. But I believe this issue will also
disappear, when we refactor probe init as described above.
>
> [Severity: Medium]
> Is the hardware guaranteed to be quiesced at this point? Both
> lan966x_fdma_rx_disable() and lan966x_fdma_tx_disable() are void and swallow
> the result of
>
> readx_poll_timeout_atomic(lan966x_fdma_channel_active, lan966x,
> val, !(val & BIT(fdma->channel_id)),
> READL_SLEEP_US, READL_TIMEOUT_US);
>
> so a -ETIMEDOUT never reaches this caller, and the EQ_AVAIL drain poll in
> __lan966x_fdma_pci_reload() is discarded too (see below). If either poll
> times out, the extraction/injection engine still owns the old DCB ring while
> this function reprograms FDMA_DCB_LLP and then calls
> fdma_free_coherent_and_unmap(&rx_fdma_old), which does:
>
> fdma_free_coherent_and_unmap()
> fdma_pci_atu_region_unmap(fdma->atu_region); /* ENA=0, translation cleared */
> fdma->atu_region = NULL;
> fdma_free_coherent(dev, fdma); /* pages returned */
>
> On the PCIe path the ATU window is the address translation itself, so
> in-flight writes land on a disabled outbound window or into memory already
> handed back to the DMA allocator. Should a timeout abort the resize and
> propagate the error so the MTU change is rejected instead?
I believe the quiesce poll before teardown is also discarded on lan966x, lan969x
and sparx5 alltogether, same pattern. READL_TIMEOUT_US is 100 seconds, so a
timeout means the channel was already wedged for a long time.
>
> > +
> > + lan966x->rx.max_mtu = new_mtu;
> > +
> > + /* Must be NULL'ed in order to realloc them. */
> > + lan966x->rx.fdma.atu_region = NULL;
> > + lan966x->tx.fdma.atu_region = NULL;
> > +
> > + lan966x->tx.fdma.db_size = FDMA_PCI_DB_SIZE(lan966x->rx.max_mtu);
> > + lan966x->tx.fdma.size = fdma_get_size_contiguous(&lan966x->tx.fdma);
> > + lan966x->rx.fdma.db_size = FDMA_PCI_DB_SIZE(lan966x->rx.max_mtu);
> > + lan966x->rx.fdma.size = fdma_get_size_contiguous(&lan966x->rx.fdma);
> > +
> > + err = lan966x_fdma_pci_rx_alloc(&lan966x->rx);
> > + if (err)
> > + goto restore;
> > +
> > + err = lan966x_fdma_pci_tx_alloc(&lan966x->tx);
> > + if (err) {
> > + fdma_free_coherent_and_unmap(lan966x->dma_dev,
> > + &lan966x->rx.fdma);
> > + goto restore;
> > + }
> > +
> > + /* Free and unmap old memory. */
> > + fdma_free_coherent_and_unmap(lan966x->dma_dev, &rx_fdma_old);
> > + fdma_free_coherent_and_unmap(lan966x->dma_dev, &tx_fdma_old);
> > +
> > + /* Order matters: napi_enable() must precede the wakes, or a TX that
> > + * completes first clears FDMA_INTR_DB_ENA with nothing scheduled to
> > + * restore it, leaving RX dead until the next reload.
> > + */
> > + napi_enable(&lan966x->napi);
> > + lan966x_fdma_rx_start(&lan966x->rx);
> > + lan966x_fdma_pci_wakeup_netdev(lan966x);
>
> [Severity: High]
> This isn't a bug introduced by this patch, but the hazard this comment
> describes looks like it is still live in the sibling register-path reload,
> which the series leaves untouched and the commit message does not mention.
>
> lan966x_fdma_reload() uses exactly the order this comment forbids, in both
> its success and its restore path:
>
> lan966x_fdma_rx_start(&lan966x->rx); /* re-arms RX bit in DB_ENA */
> ... page_pool_put_full_page() over 512 DCBs ...
> fdma_free_coherent();
> page_pool_destroy();
> lan966x_fdma_wakeup_netdev(lan966x);
> napi_enable(&lan966x->napi);
>
> The mechanism matches what the comment states. lan966x_fdma_irq_handler()
> does:
>
> if (db) {
> lan_wr(0, lan966x, FDMA_INTR_DB_ENA);
> lan_wr(db, lan966x, FDMA_INTR_DB);
>
> napi_schedule(&lan966x->napi);
> }
>
> With NAPI disabled, napi_schedule_prep() returns false and only sets
> NAPIF_STATE_MISSED; napi_enable_locked() clears SCHED/NPSVC but does not
> re-check MISSED, so no poll runs and the only code that restores DB_ENA
> (the lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA) after napi_complete_done()) is
> never reached. Since DB_ENA is now 0, no further DB interrupt can be raised
> either.
>
> The TX channel is not disabled during that window, so an in-flight TX
> completion or RX DB interrupt there appears to mask all FDMA interrupts
> permanently until another MTU change happens to reload. Should the platform
> path get the same ordering fix?
>
> > +
> > + return err;
> > +restore:
> > +
> > + /* No new buffers are allocated at this point. Use the old buffers,
> > + * but reset them before starting the FDMA again.
> > + */
> > +
> > + memcpy(&lan966x->tx.fdma, &tx_fdma_old, sizeof(struct fdma));
> > + memcpy(&lan966x->rx.fdma, &rx_fdma_old, sizeof(struct fdma));
> > +
> > + lan966x->rx.max_mtu = old_mtu;
> > +
> > + lan966x_fdma_pci_reset_mem(lan966x);
> > +
> > + napi_enable(&lan966x->napi);
> > + lan966x_fdma_rx_start(&lan966x->rx);
> > + lan966x_fdma_pci_wakeup_netdev(lan966x);
> > +
> > + return err;
> > +}
>
> [Severity: Medium]
> This is a pre-existing ordering issue, but does this patch widen it
> noticeably? lan966x_port_change_mtu() programs the new frame length before
> the buffers are grown:
>
> lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(new_mtu)),
> lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
> WRITE_ONCE(dev->mtu, new_mtu);
>
> if (!lan966x->fdma)
> return 0;
>
> err = lan966x->ops->fdma_resize(lan966x);
>
> and only restores the old value after the callback returns. On the PCIe path
> the callback now does real work: the CPU-queue flush, a
> usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC), two multi-megabyte coherent
> allocations, and on this restore: path a full RX/TX restart with db_size and
> DATAL back at the old smaller value while the larger MAXLEN is still
> programmed.
>
> With n_dbs == 1 the FDMA bounds each write by DATAL but continues an
> oversized frame in the next DCB, and lan966x_fdma_pci_rx_check_frame() only
> validates BLOCKL:
>
> blockl = FDMA_DCB_STATUS_BLOCKL(db->status);
> if (!lan966x_fdma_pci_rx_size_fits(fdma, blockl))
> return FDMA_ERROR;
>
> It never checks FDMA_DCB_STATUS_SOF/EOF, so a continuation DB is treated as a
> complete frame and lan966x_ifh_get_src_port(virt_addr, src_port) parses
> payload bytes as the IFH source port. src_port is range-checked and data_len
> is bounded, so this is not an out-of-bounds access, but can a remote sender
> that injects an oversized frame in this window get frames delivered to the
> stack attributed to a source port of its choosing?
>
> > +
> > +static int __lan966x_fdma_pci_reload(struct lan966x *lan966x, int max_mtu)
> > +{
> > + int err;
> > + u32 val;
> > +
> > + /* Disable the CPU port. */
> > + lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(0),
> > + QSYS_SW_PORT_MODE_PORT_ENA,
> > + lan966x, QSYS_SW_PORT_MODE(CPU_PORT));
> > +
> > + /* Flush the CPU queues. */
> > + readx_poll_timeout(lan966x_qsys_sw_status,
> > + lan966x,
> > + val,
> > + !(QSYS_SW_STATUS_EQ_AVAIL_GET(val)),
> > + READL_SLEEP_US, READL_TIMEOUT_US);
>
> [Severity: Medium]
> The return value of this readx_poll_timeout() is discarded, so "CPU queues
> drained" is assumed rather than verified before the rings are retired in
> lan966x_fdma_pci_reload(). Should a -ETIMEDOUT here abort the resize?
>
> > +
> > + /* Add a sleep in case there are frames between the queues and the CPU
> > + * port
> > + */
> > + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
> > +
> > + err = lan966x_fdma_pci_reload(lan966x, max_mtu);
> > +
> > + /* Enable back the CPU port. */
> > + lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(1),
> > + QSYS_SW_PORT_MODE_PORT_ENA,
> > + lan966x, QSYS_SW_PORT_MODE(CPU_PORT));
> > +
> > + return err;
> > +}
> > +
> > static int lan966x_fdma_pci_resize(struct lan966x *lan966x)
> > {
> > - return -EOPNOTSUPP;
> > + int max_mtu;
> > +
> > + /* Nothing to resize until fdma_pci_init() has built the rings; it
> > + * sizes them from DEV_MAC_MAXLEN_CFG, which the caller already set.
> > + */
> > + if (!lan966x->rx.lan966x)
> > + return 0;
>
> [Severity: High]
> This is a pre-existing gap in the other callback rather than something this
> patch introduces, but the two implementers of
> lan966x_fdma_ops::fdma_resize now disagree about this precondition. The
> platform one has no equivalent check:
>
> lan966x_fdma.c:lan966x_fdma_change_mtu() {
> max_mtu = lan966x_fdma_get_max_frame(lan966x);
> if (max_mtu == lan966x->rx.max_mtu)
> return 0;
>
> return __lan966x_fdma_reload(lan966x, max_mtu);
> }
>
> lan966x_fdma_init() sets rx.lan966x = lan966x only at its own start, so in
> the window between register_netdev() in lan966x_probe_port() and
> ops->fdma_init() in lan966x_probe(), rx.max_mtu is 0, the comparison always
> differs, and the reload runs against an unbuilt ring:
>
> __lan966x_fdma_reload()->lan966x_fdma_reload()
> lan966x_fdma_rx_disable(&lan966x->rx)
> struct lan966x *lan966x = rx->lan966x; /* NULL */
> lan_rmw(..., lan966x, FDMA_CH_DISABLE); /* lan966x->regs */
>
> lan966x->fdma is already true before the port loop and the NAPI instance is
> added and enabled by lan966x_port_init()->lan966x_fdma_netdev_init(), so
> nothing else stops the path. Would the guard be better placed once in the
> shared caller lan966x_port_change_mtu(), or duplicated in both callbacks?
>
> > +
> > + max_mtu = lan966x_fdma_get_max_frame(lan966x);
> > + if (max_mtu == lan966x->rx.max_mtu)
> > + return 0;
> > +
> > + return __lan966x_fdma_pci_reload(lan966x, max_mtu);
> > }
> >
> > static void lan966x_fdma_pci_deinit(struct lan966x *lan966x)
> > diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> > index c803619d83e2..2177e2bbfbd3 100644
> > --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> > +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> > @@ -823,7 +823,8 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
> > port->chip_port = p;
> > lan966x->ports[p] = port;
> >
> > - dev->max_mtu = ETH_MAX_MTU;
> > + dev->max_mtu = lan966x_is_pci(lan966x) && lan966x->fdma ?
> > + FDMA_PCI_MAX_MTU : ETH_MAX_MTU;
> >
> > dev->netdev_ops = &lan966x_port_netdev_ops;
> > dev->ethtool_ops = &lan966x_ethtool_ops;
> > diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
> > index 16bc28c8f11f..1877f1916d71 100644
> > --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
> > +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
>
> [ ... ]
>
> > @@ -87,6 +88,33 @@
> > #define FDMA_INJ_CHANNEL 0
> > #define FDMA_DCB_MAX 512
> >
> > +/* Ring must fit in one MAX_PAGE_ORDER DMA block; 512 DCBs overflows
> > + * at jumbo MTU.
> > + */
> > +#define FDMA_PCI_DCB_MAX 256
> > +
> > +#define FDMA_OVERHEAD \
> > + (IFH_LEN_BYTES + \
> > + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + \
> > + VLAN_HLEN * 2 + \
> > + XDP_PACKET_HEADROOM)
> > +
> > +/* Largest db_size keeping the ATU-padded ring inside one MAX_PAGE_ORDER
> > + * block and within the 16-bit DCB DATAL field. Inverts ALIGN(x, R) <= L
> > + * into x <= ALIGN_DOWN(L, R) to bound x directly.
> > + */
> > +#define FDMA_PCI_DB_SIZE_MAX \
> > + MIN_T(u32, \
> > + (ALIGN_DOWN(PAGE_SIZE << MAX_PAGE_ORDER, \
> > + FDMA_PCI_ATU_REGION_ALIGN) - \
> > + FDMA_PCI_DCB_MAX * sizeof(struct fdma_dcb)) / \
> > + (FDMA_PCI_DCB_MAX * FDMA_RX_DCB_MAX_DBS), \
> > + ALIGN_DOWN(GENMASK(15, 0), FDMA_PCI_DB_ALIGN))
> > +
> > +#define FDMA_PCI_MAX_MTU \
> > + (FDMA_PCI_DB_SIZE_MAX - FDMA_OVERHEAD - \
> > + (ETH_HLEN + ETH_FCS_LEN))
>
> [Severity: Low]
> Would a BUILD_BUG_ON help here? Both subtractions are unsigned and
> unguarded, and this macro is the only enforcement point for the
> MAX_PAGE_ORDER ring-size limit, the 16-bit DATAL limit, and dev->max_mtu.
>
> FDMA_PCI_DCB_MAX * sizeof(struct fdma_dcb) is 256 * 256 = 65536. If
> PAGE_SIZE << MAX_PAGE_ORDER is at or below 128 KB, the first subtraction
> wraps and MIN_T(u32, ...) then picks the 65408 branch. In between, the
> second subtraction wraps: with 4 KB pages and MAX_PAGE_ORDER == 5 the
> quotient is 256 while FDMA_OVERHEAD + ETH_HLEN + ETH_FCS_LEN is 630, so
> FDMA_PCI_MAX_MTU becomes roughly 4G and is assigned straight into
> dev->max_mtu, so dev_validate_mtu() accepts anything up to INT_MAX and the
> cap this patch installs disappears.
>
> In the other direction, 4 KB pages with MAX_PAGE_ORDER 6 or 7 yield 138 and
> 1162, i.e. dev->max_mtu below ETH_DATA_LEN, so a plain 1500-byte MTU cannot
> be set. Nothing asserts FDMA_PCI_MAX_MTU >= ETH_DATA_LEN.
>
> The default 4 KB-page, MAX_PAGE_ORDER=10 build does give 16128 and MTU 15498
> as the commit message says, and arch/arm/Kconfig declares ARCH_FORCE_MAX_ORDER
> as a plain int prompt with no range constraint (it already ships
> default "8" if SA1111), so these values are at least legal.
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260918-lan966x-pci-fdma-v7-0-0ecc179c8a2c%40microchip.com
More information about the linux-arm-kernel
mailing list