* Re: [PATCH net-next v03 3/6] hinic3: Add ethtool coalesce ops
From: Mohsin Bashir @ 2026-04-01 7:53 UTC (permalink / raw)
To: Fan Gong, Zhu Yikai, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Andrew Lunn,
Ioana Ciornei
Cc: linux-kernel, linux-doc, luosifu, Xin Guo, Zhou Shuai, Wu Like,
Shi Jing, Zheng Jiezhen, Maxime Chevallier
In-Reply-To: <ffc357656b2412abf6e8de4200d289e761f3e6ea.1774940117.git.zhuyikai1@h-partners.com>
> +static int is_coalesce_exceed_limit(struct net_device *netdev,
> + const struct ethtool_coalesce *coal)
> +{
> + const struct {
> + const char *name;
> + u32 value;
> + u32 limit;
> + } coalesce_limits[] = {
> + {"rx_coalesce_usecs",
> + coal->rx_coalesce_usecs,
> + COALESCE_MAX_TIMER_CFG},
> + {"rx_max_coalesced_frames",
> + coal->rx_max_coalesced_frames,
> + COALESCE_MAX_PENDING_LIMIT},
> + {"rx_max_coalesced_frames_low",
> + coal->rx_max_coalesced_frames_low,
> + COALESCE_MAX_PENDING_LIMIT},
> + {"rx_max_coalesced_frames_high",
> + coal->rx_max_coalesced_frames_high,
> + COALESCE_MAX_PENDING_LIMIT},
> + };
> +
> + for (int i = 0; i < ARRAY_SIZE(coalesce_limits); i++) {
> + if (coalesce_limits[i].value > coalesce_limits[i].limit) {
> + netdev_err(netdev, "%s out of range %d-%d\n",
> + coalesce_limits[i].name, 0,
> + coalesce_limits[i].limit);
> + return -EOPNOTSUPP;
Since we are failing a range check, maybe -ERANGE or -EINVAL would be
more appropriate here.
> + }
> + }
> + return 0;
> +}
> +
> +static int is_coalesce_legal(struct net_device *netdev,
> + const struct ethtool_coalesce *coal)
> +{
> + int err;
> +
> + err = is_coalesce_exceed_limit(netdev, coal);
> + if (err)
> + return err;
> +
> + if (coal->rx_max_coalesced_frames_low >=
> + coal->rx_max_coalesced_frames_high &&
> + coal->rx_max_coalesced_frames_high > 0) {
So this would allow non-zero low and zero high. For example, low = 10,
high = 0. Is this expected?
> + netdev_err(netdev, "invalid coalesce frame high %u, low %u, unit %d\n",
> + coal->rx_max_coalesced_frames_high,
> + coal->rx_max_coalesced_frames_low,
> + COALESCE_PENDING_LIMIT_UNIT);
> + return -EOPNOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static void check_coalesce_align(struct net_device *netdev,
> + u32 item, u32 unit, const char *str)
> +{
> + if (item % unit)
> + netdev_warn(netdev, "%s in %d units, change to %u\n",
> + str, unit, item - item % unit);
> +}
> +
> +#define CHECK_COALESCE_ALIGN(member, unit) \
> + check_coalesce_align(netdev, member, unit, #member)
> +
> +static void check_coalesce_changed(struct net_device *netdev,
> + u32 item, u32 unit, u32 ori_val,
> + const char *obj_str, const char *str)
> +{
> + if ((item / unit) != ori_val)
> + netdev_dbg(netdev, "Change %s from %d to %u %s\n",
> + str, ori_val * unit, item - item % unit, obj_str);
> +}
> +
> +#define CHECK_COALESCE_CHANGED(member, unit, ori_val, obj_str) \
> + check_coalesce_changed(netdev, member, unit, ori_val, obj_str, #member)
> +
> +static int hinic3_set_hw_coal_param(struct net_device *netdev,
> + struct hinic3_intr_coal_info *intr_coal)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + int err;
> + u16 i;
> +
> + for (i = 0; i < nic_dev->max_qps; i++) {
> + err = hinic3_set_queue_coalesce(netdev, i, intr_coal);
> + if (err)
> + return err;
> + }
> +
> + return 0;
> +}
> +
> +static int hinic3_get_coalesce(struct net_device *netdev,
> + struct ethtool_coalesce *coal,
> + struct kernel_ethtool_coalesce *kernel_coal,
> + struct netlink_ext_ack *extack)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + struct hinic3_intr_coal_info *interrupt_info;
> +
> + interrupt_info = &nic_dev->intr_coalesce[0];
> +
> + /* TX/RX uses the same interrupt.
> + * So we only declare RX ethtool_coalesce parameters.
> + */
> + coal->rx_coalesce_usecs = interrupt_info->coalesce_timer_cfg *
> + COALESCE_TIMER_CFG_UNIT;
> + coal->rx_max_coalesced_frames = interrupt_info->pending_limit *
> + COALESCE_PENDING_LIMIT_UNIT;
> +
> + coal->use_adaptive_rx_coalesce = nic_dev->adaptive_rx_coal;
> +
> + coal->rx_max_coalesced_frames_high =
> + interrupt_info->rx_pending_limit_high *
> + COALESCE_PENDING_LIMIT_UNIT;
> +
> + coal->rx_max_coalesced_frames_low =
> + interrupt_info->rx_pending_limit_low *
> + COALESCE_PENDING_LIMIT_UNIT;
> +
> + return 0;
> +}
> +
> +static int hinic3_set_coalesce(struct net_device *netdev,
> + struct ethtool_coalesce *coal,
> + struct kernel_ethtool_coalesce *kernel_coal,
> + struct netlink_ext_ack *extack)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + struct hinic3_intr_coal_info *ori_intr_coal;
> + struct hinic3_intr_coal_info intr_coal = {};
> + char obj_str[32];
> + int err;
> +
> + err = is_coalesce_legal(netdev, coal);
> + if (err)
> + return err;
> +
> + CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT);
> + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames,
> + COALESCE_PENDING_LIMIT_UNIT);
> + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_high,
> + COALESCE_PENDING_LIMIT_UNIT);
> + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_low,
> + COALESCE_PENDING_LIMIT_UNIT);
> +
> + ori_intr_coal = &nic_dev->intr_coalesce[0];
> + snprintf(obj_str, sizeof(obj_str), "for netdev");
> +
> + CHECK_COALESCE_CHANGED(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT,
> + ori_intr_coal->coalesce_timer_cfg, obj_str);
> + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames,
> + COALESCE_PENDING_LIMIT_UNIT,
> + ori_intr_coal->pending_limit, obj_str);
> + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames_high,
> + COALESCE_PENDING_LIMIT_UNIT,
> + ori_intr_coal->rx_pending_limit_high, obj_str);
> + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames_low,
> + COALESCE_PENDING_LIMIT_UNIT,
> + ori_intr_coal->rx_pending_limit_low, obj_str);
> +
> + intr_coal.coalesce_timer_cfg =
> + (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
> + intr_coal.pending_limit = (u8)(coal->rx_max_coalesced_frames /
> + COALESCE_PENDING_LIMIT_UNIT);
> +
> + nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
> +
> + intr_coal.rx_pending_limit_high =
> + (u8)(coal->rx_max_coalesced_frames_high /
> + COALESCE_PENDING_LIMIT_UNIT);
> +
> + intr_coal.rx_pending_limit_low =
> + (u8)(coal->rx_max_coalesced_frames_low /
> + COALESCE_PENDING_LIMIT_UNIT);
> +
> + /* coalesce timer or pending set to zero will disable coalesce */
> + if (!nic_dev->adaptive_rx_coal &&
> + (!intr_coal.coalesce_timer_cfg || !intr_coal.pending_limit))
> + netdev_warn(netdev, "Coalesce will be disabled\n");
> +
> + return hinic3_set_hw_coal_param(netdev, &intr_coal);
> +}
> +
> static const struct ethtool_ops hinic3_ethtool_ops = {
> - .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
> - ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
> + .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
> + ETHTOOL_COALESCE_RX_MAX_FRAMES |
> + ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
> + ETHTOOL_COALESCE_RX_MAX_FRAMES_LOW |
> + ETHTOOL_COALESCE_RX_MAX_FRAMES_HIGH,
Looks like ETHTOOL_COALESCE_TX_USECS support got dropped. is it intentional?
> .get_link_ksettings = hinic3_get_link_ksettings,
> .get_drvinfo = hinic3_get_drvinfo,
> .get_msglevel = hinic3_get_msglevel,
> @@ -1004,6 +1231,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
> .get_eth_ctrl_stats = hinic3_get_eth_ctrl_stats,
> .get_rmon_stats = hinic3_get_rmon_stats,
> .get_pause_stats = hinic3_get_pause_stats,
> + .get_coalesce = hinic3_get_coalesce,
> + .set_coalesce = hinic3_set_coalesce,
> };
>
> void hinic3_set_ethtool_ops(struct net_device *netdev)
^ permalink raw reply
* RE: [Intel-wired-lan] [PATCH iwl-next v1 1/2] igb: use napi_schedule_irqoff() instead of napi_schedule()
From: Loktionov, Aleksandr @ 2026-04-01 7:52 UTC (permalink / raw)
To: Daiki Harada, intel-wired-lan@lists.osuosl.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Nguyen, Anthony L, Kitszel, Przemyslaw, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Kohei Enju
In-Reply-To: <20260331103924.36422-2-daiky0325@gmail.com>
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Daiki Harada
> Sent: Tuesday, March 31, 2026 12:39 PM
> To: intel-wired-lan@lists.osuosl.org; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org
> Cc: Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; David S. Miller <davem@davemloft.net>; Eric
> Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo
> Abeni <pabeni@redhat.com>; Daiki Harada <daiky0325@gmail.com>; Kohei
> Enju <kohei@enjuk.jp>
> Subject: [Intel-wired-lan] [PATCH iwl-next v1 1/2] igb: use
> napi_schedule_irqoff() instead of napi_schedule()
>
> Replace napi_schedule() with napi_schedule_irqoff() in the interrupt
> handler path in igb driver
>
> Tested on QEMU with igb NIC emulation (-nic user,model=igb)
>
> Suggested-by: Kohei Enju <kohei@enjuk.jp>
> Signed-off-by: Daiki Harada <daiky0325@gmail.com>
> ---
> drivers/net/ethernet/intel/igb/igb_main.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c
> b/drivers/net/ethernet/intel/igb/igb_main.c
> index ee99fd8fd513..d7a6ae938cc5 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -7158,7 +7158,7 @@ static irqreturn_t igb_msix_ring(int irq, void
> *data)
> /* Write the ITR value calculated from the previous interrupt.
> */
> igb_write_itr(q_vector);
>
> - napi_schedule(&q_vector->napi);
> + napi_schedule_irqoff(&q_vector->napi);
>
> return IRQ_HANDLED;
> }
> @@ -8199,7 +8199,7 @@ static irqreturn_t igb_intr_msi(int irq, void
> *data)
> if (icr & E1000_ICR_TS)
> igb_tsync_interrupt(adapter);
>
> - napi_schedule(&q_vector->napi);
> + napi_schedule_irqoff(&q_vector->napi);
>
> return IRQ_HANDLED;
> }
> @@ -8245,7 +8245,7 @@ static irqreturn_t igb_intr(int irq, void *data)
> if (icr & E1000_ICR_TS)
> igb_tsync_interrupt(adapter);
>
> - napi_schedule(&q_vector->napi);
> + napi_schedule_irqoff(&q_vector->napi);
>
> return IRQ_HANDLED;
> }
> --
> 2.53.0
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
^ permalink raw reply
* Re: [PATCH net-next v03 2/6] hinic3: Add ethtool statistic ops
From: Mohsin Bashir @ 2026-04-01 7:52 UTC (permalink / raw)
To: Fan Gong, Zhu Yikai, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Andrew Lunn,
Ioana Ciornei
Cc: linux-kernel, linux-doc, luosifu, Xin Guo, Zhou Shuai, Wu Like,
Shi Jing, Zheng Jiezhen, Maxime Chevallier
In-Reply-To: <d3256c3049445bfa9c6b98832d25eaa712422ae6.1774940117.git.zhuyikai1@h-partners.com>
> +
> +static void hinic3_get_qp_stats_strings(const struct net_device *netdev,
Any strong reason to add const here? netdev_priv() would just strip it
anyway. No?
> + char *p)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + u8 *data = p;
> + u16 i, j;
> +
> + for (i = 0; i < nic_dev->q_params.num_qps; i++) {
> + for (j = 0; j < ARRAY_SIZE(hinic3_tx_queue_stats); j++)
> + ethtool_sprintf(&data,
> + hinic3_tx_queue_stats[j].name, i);
> + }
> +
> + for (i = 0; i < nic_dev->q_params.num_qps; i++) {
> + for (j = 0; j < ARRAY_SIZE(hinic3_rx_queue_stats); j++)
> + ethtool_sprintf(&data,
> + hinic3_rx_queue_stats[j].name, i);
> + }
> +}
> +
^ permalink raw reply
* Re: [PATCH net-next v03 1/6] hinic3: Add ethtool queue ops
From: Mohsin Bashir @ 2026-04-01 7:52 UTC (permalink / raw)
To: Fan Gong, Zhu Yikai, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Andrew Lunn,
Ioana Ciornei
Cc: linux-kernel, linux-doc, luosifu, Xin Guo, Zhou Shuai, Wu Like,
Shi Jing, Zheng Jiezhen, Maxime Chevallier
In-Reply-To: <17b3bbb0c917ee09ddd7a164cdefca6eb63793ec.1774940117.git.zhuyikai1@h-partners.com>
> +static int hinic3_set_ringparam(struct net_device *netdev,
> + struct ethtool_ringparam *ring,
> + struct kernel_ethtool_ringparam *kernel_ring,
> + struct netlink_ext_ack *extack)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + struct hinic3_dyna_txrxq_params q_params = {};
> + u32 new_sq_depth, new_rq_depth;
> + int err;
> +
> + err = hinic3_check_ringparam_valid(netdev, ring);
> + if (err)
> + return err;
> +
> + new_sq_depth = 1U << ilog2(ring->tx_pending);
> + new_rq_depth = 1U << ilog2(ring->rx_pending);
> + if (new_sq_depth == nic_dev->q_params.sq_depth &&
> + new_rq_depth == nic_dev->q_params.rq_depth)
> + return 0;
> +
So non power of 2 values would trimmed to the nearest power of 2 even
when the driver support these values. If such values are not supported,
should these be rejected here? or if we want to force the nearest power
of 2, should we use NL_SET_ERR_MSG to inform the user about rounding?
> +int
> +hinic3_change_channel_settings(struct net_device *netdev,
> + struct hinic3_dyna_txrxq_params *trxq_params)
> +{
> + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> + struct hinic3_dyna_qp_params new_qp_params = {};
> + struct hinic3_dyna_qp_params cur_qp_params = {};
> + bool need_teardown = false;
> + unsigned long flags;
> + int err;
> +
> + mutex_lock(&nic_dev->channel_cfg_lock);
> +
> + hinic3_config_num_qps(netdev, trxq_params);
> +
> + err = hinic3_alloc_channel_resources(netdev, &new_qp_params,
> + trxq_params);
> + if (err) {
> + netdev_err(netdev, "Failed to alloc channel resources\n");
> + mutex_unlock(&nic_dev->channel_cfg_lock);
> + return err;
> + }
> +
> + spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> + if (!test_and_set_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags))
> + need_teardown = true;
> + spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> + if (need_teardown) {
> + hinic3_vport_down(netdev);
> + hinic3_close_channel(netdev);
> + hinic3_uninit_qps(nic_dev, &cur_qp_params);
> + hinic3_free_channel_resources(netdev, &cur_qp_params,
> + &nic_dev->q_params);
> + }
> +
> + if (nic_dev->num_qp_irq > trxq_params->num_qps)
> + hinic3_qp_irq_change(netdev, trxq_params->num_qps);
> +
> + spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> + nic_dev->q_params = *trxq_params;
[1] Here we are overwriting the old parameters
> + spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> + hinic3_init_qps(nic_dev, &new_qp_params);
> +
> + err = hinic3_open_channel(netdev);
> + if (err)
> + goto err_uninit_qps;
> +
> + err = hinic3_vport_up(netdev);
> + if (err)
> + goto err_close_channel;
> +
> + spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> + clear_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags);
> + spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> + mutex_unlock(&nic_dev->channel_cfg_lock);
> +
> + return 0;
> +
> +err_close_channel:
> + hinic3_close_channel(netdev);
> +err_uninit_qps:
> + spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> + memset(&nic_dev->q_params, 0, sizeof(nic_dev->q_params));
Looks like we are asking for trouble here. The old parameters were
already overwritten at [1] and now we are destroying the new ones?
> + spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> + hinic3_uninit_qps(nic_dev, &new_qp_params);
> + hinic3_free_channel_resources(netdev, &new_qp_params, trxq_params);
> +
> + mutex_unlock(&nic_dev->channel_cfg_lock);
> +
> + return err;
> +}
> +
^ permalink raw reply
* Re: [PATCH net v2 4/4] net: bcmgenet: relax the xmit ring full case
From: Nicolai Buchwitz @ 2026-04-01 7:47 UTC (permalink / raw)
To: Justin Chen
Cc: netdev, pabeni, kuba, edumazet, davem, andrew+netdev,
bcm-kernel-feedback-list, florian.fainelli, opendmb
In-Reply-To: <20260401003840.3112454-5-justin.chen@broadcom.com>
On 1.4.2026 02:38, Justin Chen wrote:
> We have a queue size of 32. If a packet is multiple fragments we can
> run through this queue really quickly. Currently we stop the xmit
> queue at SKB_FRAG_SIZE which by default can take up half the queue.
> Instead lets just look at the incoming packet and freeze the queue
> if the incoming packet has more fragments than free_bds. This will
> relieve some of the queue timeouts we have been seeing.
>
> Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
> Signed-off-by: Justin Chen <justin.chen@broadcom.com>
> ---
> drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index 54f71b1e85fc..a1aa1278842e 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -2018,10 +2018,10 @@ static int bcmgenet_tx_poll(struct napi_struct
> *napi, int budget)
>
> spin_lock(&ring->lock);
> work_done = __bcmgenet_tx_reclaim(ring->priv->dev, ring);
> - if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
> - txq = netdev_get_tx_queue(ring->priv->dev, ring->index);
> + txq = netdev_get_tx_queue(ring->priv->dev, ring->index);
> + if (netif_tx_queue_stopped(txq))
> netif_tx_wake_queue(txq);
> - }
> +
> spin_unlock(&ring->lock);
>
> if (work_done == 0) {
> @@ -2224,9 +2224,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff
> *skb, struct net_device *dev)
>
> netdev_tx_sent_queue(txq, GENET_CB(skb)->bytes_sent);
>
> - if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
> - netif_tx_stop_queue(txq);
> -
With this removed, the only queue stop is the NETDEV_TX_BUSY path at
entry. That means every ring-full hits BUSY and requeues rather than
stopping proactively on the previous transmit.
Would it work to keep the proactive stop but base it on the actual
packet size instead of MAX_SKB_FRAGS?
if (ring->free_bds <= (nr_frags + 1))
netif_tx_stop_queue(txq);
That avoids reserving half the ring for the worst case while still
preventing BUSY from becoming the normal path.
> if (!netdev_xmit_more() || netif_xmit_stopped(txq))
> /* Packets are ready, update producer index */
> bcmgenet_tdma_ring_writel(priv, ring->index,
This wakes unconditionally even if only 1 BD was reclaimed. Combined
with the above, it can create a tight stop/wake/BUSY thrash when the
ring is near-full.
Thanks
Nicolai
^ permalink raw reply
* [PATCH 3/6] net: Guard Legacy IP entry points with CONFIG_LEGACY_IP
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Wrap the IPv4-specific registrations in inet_init() with
CONFIG_LEGACY_IP guards. When LEGACY_IP is disabled, the kernel
will not:
- Register the AF_INET socket family
- Register the ETH_P_IP packet handler (ip_rcv)
- Initialize ARP, ICMP, IGMP, or IPv4 routing
- Register IPv4 protocol handlers (TCP/UDP/ICMP over IPv4)
- Initialize IPv4 multicast routing, proc entries, or fragmentation
The shared INET infrastructure (tcp_prot, udp_prot, tcp_init, etc.)
remains initialized for use by IPv6.
Also update INDIRECT_CALL_INET to not use ip_rcv/ip_list_rcv as
direct call targets when LEGACY_IP is disabled, avoiding a link-time
reference to functions that will eventually be compiled out.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
include/linux/indirect_call_wrapper.h | 4 +++-
net/ipv4/af_inet.c | 20 +++++++++++++-----
net/ipv4/devinet.c | 2 ++
net/ipv4/route.c | 1 -
net/ipv4/tcp_ipv4.c | 30 ++++++++++++++-------------
5 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/include/linux/indirect_call_wrapper.h b/include/linux/indirect_call_wrapper.h
index dc272b514a01..25a3873da462 100644
--- a/include/linux/indirect_call_wrapper.h
+++ b/include/linux/indirect_call_wrapper.h
@@ -57,9 +57,11 @@
* builtin, this macro simplify dealing with indirect calls with only ipv4/ipv6
* alternatives
*/
-#if IS_BUILTIN(CONFIG_IPV6)
+#if IS_BUILTIN(CONFIG_IPV6) && IS_ENABLED(CONFIG_LEGACY_IP)
#define INDIRECT_CALL_INET(f, f2, f1, ...) \
INDIRECT_CALL_2(f, f2, f1, __VA_ARGS__)
+#elif IS_BUILTIN(CONFIG_IPV6)
+#define INDIRECT_CALL_INET(f, f2, f1, ...) INDIRECT_CALL_1(f, f2, __VA_ARGS__)
#elif IS_ENABLED(CONFIG_INET)
#define INDIRECT_CALL_INET(f, f2, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__)
#else
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c7731e300a44..dc358faa1647 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1922,7 +1922,15 @@ static int __init inet_init(void)
/*
* Tell SOCKET that we are alive...
*/
+ /* Initialize the socket-side protocol switch tables. */
+ for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
+ INIT_LIST_HEAD(r);
+
+#ifdef CONFIG_XFRM
+ xfrm_init();
+#endif
+#ifdef CONFIG_LEGACY_IP
(void)sock_register(&inet_family_ops);
#ifdef CONFIG_SYSCTL
@@ -1957,10 +1965,6 @@ static int __init inet_init(void)
pr_crit("%s: Cannot add IGMP protocol\n", __func__);
#endif
- /* Register the socket-side information for inet_create. */
- for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
- INIT_LIST_HEAD(r);
-
for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
inet_register_protosw(q);
@@ -1975,6 +1979,7 @@ static int __init inet_init(void)
*/
ip_init();
+#endif /* CONFIG_LEGACY_IP */
/* Initialise per-cpu ipv4 mibs */
if (init_ipv4_mibs())
@@ -1987,7 +1992,8 @@ static int __init inet_init(void)
udp_init();
/* Add UDP-Lite (RFC 3828) */
- udplite4_register();
+ if (IS_ENABLED(CONFIG_LEGACY_IP))
+ udplite4_register();
raw_init();
@@ -1997,6 +2003,7 @@ static int __init inet_init(void)
* Set the ICMP layer up
*/
+#ifdef CONFIG_LEGACY_IP
if (icmp_init() < 0)
panic("Failed to create the ICMP control socket.\n");
@@ -2007,10 +2014,12 @@ static int __init inet_init(void)
if (ip_mr_init())
pr_crit("%s: Cannot init ipv4 mroute\n", __func__);
#endif
+#endif /* CONFIG_LEGACY_IP */
if (init_inet_pernet_ops())
pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__);
+#ifdef CONFIG_LEGACY_IP
ipv4_proc_init();
ipfrag_init();
@@ -2018,6 +2027,7 @@ static int __init inet_init(void)
dev_add_pack(&ip_packet_type);
ip_tunnel_core_init();
+#endif /* CONFIG_LEGACY_IP */
rc = 0;
out:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 537bb6c315d2..9b9db10e5db2 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -348,7 +348,9 @@ static int __init inet_blackhole_dev_init(void)
return PTR_ERR_OR_ZERO(in_dev);
}
+#ifdef CONFIG_LEGACY_IP
late_initcall(inet_blackhole_dev_init);
+#endif
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
{
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 463236e0dc2d..125614f552c7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3773,7 +3773,6 @@ int __init ip_rt_init(void)
if (ip_rt_proc_init())
pr_err("Unable to create route proc files\n");
#ifdef CONFIG_XFRM
- xfrm_init();
xfrm4_init();
#endif
rtnl_register_many(ip_rt_rtnl_msg_handlers);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c7b2463c2e25..7660bd45aac7 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -3717,25 +3717,27 @@ static void __init bpf_iter_register(void)
void __init tcp_v4_init(void)
{
- int cpu, res;
+ if (IS_ENABLED(CONFIG_LEGACY_IP)) {
+ int cpu, res;
- for_each_possible_cpu(cpu) {
- struct sock *sk;
+ for_each_possible_cpu(cpu) {
+ struct sock *sk;
- res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
- IPPROTO_TCP, &init_net);
- if (res)
- panic("Failed to create the TCP control socket.\n");
- sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
+ res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
+ IPPROTO_TCP, &init_net);
+ if (res)
+ panic("Failed to create the TCP control socket.\n");
+ sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
- /* Please enforce IP_DF and IPID==0 for RST and
- * ACK sent in SYN-RECV and TIME-WAIT state.
- */
- inet_sk(sk)->pmtudisc = IP_PMTUDISC_DO;
+ /* Please enforce IP_DF and IPID==0 for RST and
+ * ACK sent in SYN-RECV and TIME-WAIT state.
+ */
+ inet_sk(sk)->pmtudisc = IP_PMTUDISC_DO;
- sk->sk_clockid = CLOCK_MONOTONIC;
+ sk->sk_clockid = CLOCK_MONOTONIC;
- per_cpu(ipv4_tcp_sk.sock, cpu) = sk;
+ per_cpu(ipv4_tcp_sk.sock, cpu) = sk;
+ }
}
if (register_pernet_subsys(&tcp_sk_ops))
panic("Failed to create the TCP control socket.\n");
--
2.51.0
^ permalink raw reply related
* [PATCH 5/6] net: Change CONFIG_INET to CONFIG_LEGACY_IP for IPv4-only code
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Several functions guarded by CONFIG_INET are actually IPv4-specific
and should be gated by CONFIG_LEGACY_IP instead:
- bpf_out_neigh_v4(): BPF IPv4 neighbour output helper
- bpf_ipv4_fib_lookup(): BPF IPv4 FIB lookup
- case AF_INET in bpf_xdp_fib_lookup/bpf_skb_fib_lookup switch
- br_arp_send(): bridge ARP proxy (ARP is IPv4-only)
This allows the compiler to eliminate these functions when
LEGACY_IP=n.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
net/bridge/br_arp_nd_proxy.c | 2 +-
net/bridge/br_private.h | 8 ++++++++
net/core/filter.c | 10 +++++-----
net/core/sock.c | 2 +-
net/mac80211/main.c | 10 +++++-----
net/netfilter/nfnetlink_queue.c | 2 +-
6 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index 1e2b51769eec..e056fa0cd1fe 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -39,7 +39,7 @@ void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
br_opt_toggle(br, BROPT_NEIGH_SUPPRESS_ENABLED, neigh_suppress);
}
-#if IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_LEGACY_IP)
static void br_arp_send(struct net_bridge *br, struct net_bridge_port *p,
struct net_device *dev, __be32 dest_ip, __be32 src_ip,
const unsigned char *dest_hw,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 9b55d38ea9ed..28131fa0a7c5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -2347,8 +2347,16 @@ static inline void br_switchdev_init(struct net_bridge *br)
/* br_arp_nd_proxy.c */
void br_recalculate_neigh_suppress_enabled(struct net_bridge *br);
+#if IS_ENABLED(CONFIG_LEGACY_IP)
void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p);
+#else
+static inline void br_do_proxy_suppress_arp(struct sk_buff *skb,
+ struct net_bridge *br,
+ u16 vid, struct net_bridge_port *p)
+{
+}
+#endif
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
struct nd_msg *br_is_nd_neigh_msg(const struct sk_buff *skb, struct nd_msg *m);
diff --git a/net/core/filter.c b/net/core/filter.c
index ad71ceefcb5e..ef99bd9fddd6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2310,7 +2310,7 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev,
}
#endif /* CONFIG_IPV6 */
-#if IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_LEGACY_IP)
static int bpf_out_neigh_v4(struct net *net, struct sk_buff *skb,
struct net_device *dev, struct bpf_nh_params *nh)
{
@@ -2419,7 +2419,7 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev,
kfree_skb(skb);
return NET_XMIT_DROP;
}
-#endif /* CONFIG_INET */
+#endif /* CONFIG_LEGACY_IP */
static int __bpf_redirect_neigh(struct sk_buff *skb, struct net_device *dev,
struct bpf_nh_params *nh)
@@ -6095,7 +6095,7 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, u32 mtu)
}
#endif
-#if IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_LEGACY_IP)
static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
u32 flags, bool check_mtu)
{
@@ -6390,7 +6390,7 @@ BPF_CALL_4(bpf_xdp_fib_lookup, struct xdp_buff *, ctx,
return -EINVAL;
switch (params->family) {
-#if IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_LEGACY_IP)
case AF_INET:
return bpf_ipv4_fib_lookup(dev_net(ctx->rxq->dev), params,
flags, true);
@@ -6431,7 +6431,7 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb,
check_mtu = true;
switch (params->family) {
-#if IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_LEGACY_IP)
case AF_INET:
rc = bpf_ipv4_fib_lookup(net, params, flags, check_mtu);
break;
diff --git a/net/core/sock.c b/net/core/sock.c
index 5976100a9d55..6b2914702a38 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -4267,7 +4267,7 @@ int sock_load_diag_module(int family, int protocol)
NETLINK_SOCK_DIAG, family);
}
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
if (family == AF_INET &&
protocol != IPPROTO_RAW &&
protocol < MAX_INET_PROTOS &&
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 616f86b1a7e4..7c1bbbb2c5c7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -558,7 +558,7 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_restart_hw);
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
static int ieee80211_ifa_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
@@ -1624,7 +1624,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
wiphy_unlock(hw->wiphy);
rtnl_unlock();
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
result = register_inetaddr_notifier(&local->ifa_notifier);
if (result)
@@ -1642,11 +1642,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
#if IS_ENABLED(CONFIG_IPV6)
fail_ifa6:
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
unregister_inetaddr_notifier(&local->ifa_notifier);
#endif
#endif
-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
+#if defined(CONFIG_LEGACY_IP) || defined(CONFIG_IPV6)
fail_ifa:
#endif
wiphy_unregister(local->hw.wiphy);
@@ -1673,7 +1673,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
tasklet_kill(&local->tx_pending_tasklet);
tasklet_kill(&local->tasklet);
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
unregister_inetaddr_notifier(&local->ifa_notifier);
#endif
#if IS_ENABLED(CONFIG_IPV6)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 47f7f62906e2..e453fdb2254c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -339,7 +339,7 @@ static struct nf_hook_entries *nf_hook_entries_head(const struct net *net, u8 pf
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
{
-#ifdef CONFIG_INET
+#ifdef CONFIG_LEGACY_IP
const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->state.hook == NF_INET_LOCAL_OUT) {
--
2.51.0
^ permalink raw reply related
* [PATCH 2/6] net: Add CONFIG_LEGACY_IP option
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Add a new CONFIG_LEGACY_IP boolean option under CONFIG_INET that will
gate Legacy IP functionality. When disabled, the kernel will not
register the AF_INET socket family, IPv4 packet handler, ARP, or IPv4
routing, while the shared TCP/UDP/INET socket infrastructure remains
available for IPv6.
This is the first step toward making Legacy IP optional. The option
defaults to y and currently has no effect — subsequent patches will use
it to guard IPv4 entry points.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
net/ipv4/Kconfig | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index df922f9f5289..aef2c5349e62 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -2,6 +2,17 @@
#
# IP configuration
#
+config LEGACY_IP
+ bool "The IPv4 protocol (Legacy IP)"
+ help
+ Support for IP version 4 (IPv4).
+
+ Legacy IP is the protocol used by the early ARPANET, before IPv6
+ was standardised in the final decade of the 1900s. It should only
+ be necessary these days to interoperate with legacy networks.
+
+ If unsure, say N.
+
config IP_MULTICAST
bool "IP: multicasting"
help
--
2.51.0
^ permalink raw reply related
* [PATCH 4/6] net: Make IPv4-only Kconfig options depend on LEGACY_IP
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Add 'depends on LEGACY_IP' to Kconfig options that are purely
IPv4-specific, so they are automatically disabled when LEGACY_IP=n.
IPv4-only options gated:
- IP_MULTICAST, IP_ADVANCED_ROUTER, IP_FIB_TRIE_STATS,
IP_MULTIPLE_TABLES, IP_ROUTE_MULTIPATH, IP_ROUTE_VERBOSE,
IP_ROUTE_CLASSID — IPv4 routing features
- IP_PNP (and children DHCP/BOOTP/RARP) — IPv4 autoconfiguration
- NET_IPIP, NET_IPGRE_DEMUX, NET_IPGRE, NET_IPGRE_BROADCAST — IPv4
tunnels
- IP_MROUTE_COMMON, IP_MROUTE, IP_MROUTE_MULTIPLE_TABLES,
IP_PIMSM_V1, IP_PIMSM_V2 — IPv4 multicast routing
- NET_IPVTI, NET_FOU_IP_TUNNELS — IPv4 VTI and FOU tunnels
- INET_AH, INET_ESP, INET_ESP_OFFLOAD, INET_ESPINTCP,
INET_IPCOMP — IPv4 IPsec (IPv6 has separate INET6_* options)
- INET_XFRM_TUNNEL, INET_TUNNEL — IPv4 tunnel infrastructure
Options intentionally left ungated (shared with IPv6):
- SYN_COOKIES, NET_IP_TUNNEL, NET_UDP_TUNNEL, NET_FOU
- INET_TABLE_PERTURB_ORDER, INET_DIAG and children
- TCP_CONG_*, DEFAULT_TCP_CONG, TCP_SIGPOOL, TCP_AO, TCP_MD5SIG
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
net/ipv4/Kconfig | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index aef2c5349e62..03b5ba75c3cf 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -15,6 +15,7 @@ config LEGACY_IP
config IP_MULTICAST
bool "IP: multicasting"
+ depends on LEGACY_IP
help
This is code for addressing several networked computers at once,
enlarging your kernel by about 2 KB. You need multicasting if you
@@ -25,6 +26,7 @@ config IP_MULTICAST
config IP_ADVANCED_ROUTER
bool "IP: advanced router"
+ depends on LEGACY_IP
help
If you intend to run your Linux box mostly as a router, i.e. as a
computer that forwards and redistributes network packets, say Y; you
@@ -66,6 +68,7 @@ config IP_ADVANCED_ROUTER
config IP_FIB_TRIE_STATS
bool "FIB TRIE statistics"
+ depends on LEGACY_IP
depends on IP_ADVANCED_ROUTER
help
Keep track of statistics on structure of FIB TRIE table.
@@ -73,6 +76,7 @@ config IP_FIB_TRIE_STATS
config IP_MULTIPLE_TABLES
bool "IP: policy routing"
+ depends on LEGACY_IP
depends on IP_ADVANCED_ROUTER
select FIB_RULES
help
@@ -90,6 +94,7 @@ config IP_MULTIPLE_TABLES
config IP_ROUTE_MULTIPATH
bool "IP: equal cost multipath"
+ depends on LEGACY_IP
depends on IP_ADVANCED_ROUTER
help
Normally, the routing tables specify a single action to be taken in
@@ -102,6 +107,7 @@ config IP_ROUTE_MULTIPATH
config IP_ROUTE_VERBOSE
bool "IP: verbose route monitoring"
+ depends on LEGACY_IP
depends on IP_ADVANCED_ROUTER
help
If you say Y here, which is recommended, then the kernel will print
@@ -113,9 +119,11 @@ config IP_ROUTE_VERBOSE
config IP_ROUTE_CLASSID
bool
+ depends on LEGACY_IP
config IP_PNP
bool "IP: kernel level autoconfiguration"
+ depends on LEGACY_IP
help
This enables automatic configuration of IP addresses of devices and
of the routing table during kernel boot, based on either information
@@ -172,6 +180,7 @@ config IP_PNP_RARP
config NET_IPIP
tristate "IP: tunneling"
+ depends on LEGACY_IP
select INET_TUNNEL
select NET_IP_TUNNEL
help
@@ -190,6 +199,7 @@ config NET_IPIP
config NET_IPGRE_DEMUX
tristate "IP: GRE demultiplexer"
+ depends on LEGACY_IP
help
This is helper module to demultiplex GRE packets on GRE version field criteria.
Required by ip_gre and pptp modules.
@@ -202,6 +212,7 @@ config NET_IP_TUNNEL
config NET_IPGRE
tristate "IP: GRE tunnels over IP"
+ depends on LEGACY_IP
depends on (IPV6 || IPV6=n) && NET_IPGRE_DEMUX
select NET_IP_TUNNEL
help
@@ -217,6 +228,7 @@ config NET_IPGRE
config NET_IPGRE_BROADCAST
bool "IP: broadcast GRE over IP"
+ depends on LEGACY_IP
depends on IP_MULTICAST && NET_IPGRE
help
One application of GRE/IP is to construct a broadcast WAN (Wide Area
@@ -226,10 +238,12 @@ config NET_IPGRE_BROADCAST
config IP_MROUTE_COMMON
bool
+ depends on LEGACY_IP
depends on IP_MROUTE || IPV6_MROUTE
config IP_MROUTE
bool "IP: multicast routing"
+ depends on LEGACY_IP
depends on IP_MULTICAST
select IP_MROUTE_COMMON
help
@@ -242,6 +256,7 @@ config IP_MROUTE
config IP_MROUTE_MULTIPLE_TABLES
bool "IP: multicast policy routing"
+ depends on LEGACY_IP
depends on IP_MROUTE && IP_ADVANCED_ROUTER
select FIB_RULES
help
@@ -256,6 +271,7 @@ config IP_MROUTE_MULTIPLE_TABLES
config IP_PIMSM_V1
bool "IP: PIM-SM version 1 support"
+ depends on LEGACY_IP
depends on IP_MROUTE
help
Kernel side support for Sparse Mode PIM (Protocol Independent
@@ -269,6 +285,7 @@ config IP_PIMSM_V1
config IP_PIMSM_V2
bool "IP: PIM-SM version 2 support"
+ depends on LEGACY_IP
depends on IP_MROUTE
help
Kernel side support for Sparse Mode PIM version 2. In order to use
@@ -314,6 +331,7 @@ config SYN_COOKIES
config NET_IPVTI
tristate "Virtual (secure) IP: tunneling"
+ depends on LEGACY_IP
depends on IPV6 || IPV6=n
select INET_TUNNEL
select NET_IP_TUNNEL
@@ -341,6 +359,7 @@ config NET_FOU
config NET_FOU_IP_TUNNELS
bool "IP: FOU encapsulation of IP tunnels"
+ depends on LEGACY_IP
depends on NET_IPIP || NET_IPGRE || IPV6_SIT
select NET_FOU
help
@@ -350,6 +369,7 @@ config NET_FOU_IP_TUNNELS
config INET_AH
tristate "IP: AH transformation"
+ depends on LEGACY_IP
select XFRM_AH
help
Support for IPsec AH (Authentication Header).
@@ -365,6 +385,7 @@ config INET_AH
config INET_ESP
tristate "IP: ESP transformation"
+ depends on LEGACY_IP
select XFRM_ESP
help
Support for IPsec ESP (Encapsulating Security Payload).
@@ -380,6 +401,7 @@ config INET_ESP
config INET_ESP_OFFLOAD
tristate "IP: ESP transformation offload"
+ depends on LEGACY_IP
depends on INET_ESP
select XFRM_OFFLOAD
default n
@@ -393,6 +415,7 @@ config INET_ESP_OFFLOAD
config INET_ESPINTCP
bool "IP: ESP in TCP encapsulation (RFC 8229)"
+ depends on LEGACY_IP
depends on XFRM && INET_ESP
select STREAM_PARSER
select NET_SOCK_MSG
@@ -405,6 +428,7 @@ config INET_ESPINTCP
config INET_IPCOMP
tristate "IP: IPComp transformation"
+ depends on LEGACY_IP
select INET_XFRM_TUNNEL
select XFRM_IPCOMP
help
@@ -425,11 +449,13 @@ config INET_TABLE_PERTURB_ORDER
config INET_XFRM_TUNNEL
tristate
+ depends on LEGACY_IP
select INET_TUNNEL
default n
config INET_TUNNEL
tristate
+ depends on LEGACY_IP
default n
config INET_DIAG
--
2.51.0
^ permalink raw reply related
* [PATCH 6/6] net: Warn when processes listen on AF_INET sockets
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
There is no need to listen on AF_INET sockets; a modern application can
listen on IPv6 (without IPV6_V6ONLY) and will accept connections from
the 20th century via IPv4-mapped addresses (::ffff:x.x.x.x) on the IPv6
socket.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
net/ipv4/af_inet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index dc358faa1647..3838782a8437 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -240,6 +240,9 @@ int inet_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
int err = -EINVAL;
+ pr_warn_once("process '%s' (pid %d) is listening on an AF_INET socket. Consider using AF_INET6 with IPV6_V6ONLY=0 instead.\n",
+ current->comm, task_pid_nr(current));
+
lock_sock(sk);
if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
--
2.51.0
^ permalink raw reply related
* [PATCH 1/6] net: Simplify tautological CONFIG_INET/CONFIG_IPV6 guards
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
In-Reply-To: <20260401074509.1897527-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
CONFIG_IPV6 depends on CONFIG_INET, so:
- 'IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)' simplifies
to just 'IS_ENABLED(CONFIG_IPV6)'
- 'IS_ENABLED(CONFIG_INET) || IS_ENABLED(CONFIG_IPV6)' simplifies
to just 'IS_ENABLED(CONFIG_INET)'
No functional change.
Signed-off-by: David Woodhouse (Kiro) <dwmw@amazon.co.uk>
---
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 6 +++---
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c | 2 +-
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 2 +-
net/core/filter.c | 2 +-
net/core/secure_seq.c | 2 +-
6 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
index a14f216048cd..889dc1785772 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -439,7 +439,7 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
return err;
}
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
struct net_device *dev,
struct mlx5e_tc_tun_route_attr *attr)
@@ -727,7 +727,7 @@ int mlx5e_tc_tun_route_lookup(struct mlx5e_priv *priv,
attr.fl.fl4.daddr = esw_attr->rx_tun_attr->src_ip.v4;
err = mlx5e_route_lookup_ipv4_get(priv, filter_dev, &attr);
}
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
else if (flow_attr->tun_ip_version == 6) {
/* Addresses are swapped for decap */
attr.fl.fl6.saddr = esw_attr->rx_tun_attr->dst_ip.v6;
@@ -762,7 +762,7 @@ int mlx5e_tc_tun_route_lookup(struct mlx5e_priv *priv,
out:
if (flow_attr->tun_ip_version == 4)
mlx5e_route_lookup_ipv4_put(&attr);
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
else if (flow_attr->tun_ip_version == 6)
mlx5e_route_lookup_ipv6_put(&attr);
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
index 6873c1201803..f3c0e2d0f388 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
@@ -73,7 +73,7 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
struct net_device *mirred_dev,
struct mlx5e_encap_entry *e);
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
struct net_device *mirred_dev,
struct mlx5e_encap_entry *e);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index bfd401bee9e8..b2973e8a7df8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -104,7 +104,7 @@ int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow,
if (!tun_attr->dst_ip.v4 || !tun_attr->src_ip.v4)
return 0;
}
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
else if (ip_version == 6) {
int ipv6_size = MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 0cef0e2b85d0..5eb47e1a8d5e 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -814,7 +814,7 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
flow.daddr = payload->ipv6_addr;
flow.flowi6_proto = IPPROTO_UDP;
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow,
NULL);
if (IS_ERR(dst))
diff --git a/net/core/filter.c b/net/core/filter.c
index 78b548158fb0..ad71ceefcb5e 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -6083,7 +6083,7 @@ static const struct bpf_func_proto bpf_skb_get_xfrm_state_proto = {
};
#endif
-#if IS_ENABLED(CONFIG_INET) || IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_INET)
static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, u32 mtu)
{
params->h_vlan_TCI = 0;
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 6a6f2cda5aae..4de049635db0 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -15,7 +15,7 @@
#include <linux/siphash.h>
#include <net/secure_seq.h>
-#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
+#if IS_ENABLED(CONFIG_INET)
#include <linux/in6.h>
#include <net/tcp.h>
--
2.51.0
^ permalink raw reply related
* [PATCH 0/6] Deprecate Legacy IP
From: David Woodhouse @ 2026-04-01 7:44 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Nikolay Aleksandrov, Ido Schimmel,
Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
Neal Cardwell, Johannes Berg, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Guillaume Nault, David Woodhouse, Kees Cook,
Alexei Lazar, Gal Pressman, Paul Moore, netdev, linux-rdma,
linux-kernel, oss-drivers, bridge, bpf, linux-wireless,
netfilter-devel, coreteam, torvalds, jon.maddog.hall
RFC1883, the IPv6 standard, was published in the final decade of the 1900s.
That's closer in time to the Apollo 11 moon landing than it was to today.
Even our esteemed Maddog has worked with computers for longer in the IPv6
era, than he ever did before it.
Yet Linux still can't even be *built* with only IPv6 support and without
support for Legacy IP. This long overdue patch series fixes that, and
immediately marks Legacy IP for deprecation.
It also cleans up a few tautological "INET && IPV6" and "INET || IPV6"
checks, since IPV6 (and now LEGACY_IP) cannot be selected without the
overall CONFIG_INET option.
For now, we only add a warning when a process *listens* on a Legacy IP
socket (since you can listen on IPv6 and still accept connections which
have come through a timewarp from the 20th century. Adding warnings for
making outbound connections or *accepting* on Legacy IP can come later.
'I would be happy if "Legacy IP" ceased to be the "industry standard"
and IPv6 be the default, even if I had to beat IPv6 into the head of
every single network administrator's head with a shovel.' said Jon
'maddog' Hall, ancient supporter of Free and Open Source Software.
David Woodhouse (6):
net: Simplify tautological CONFIG_INET/CONFIG_IPV6 guards
net: Add CONFIG_LEGACY_IP option
net: Guard Legacy IP entry points with CONFIG_LEGACY_IP
net: Make IPv4-only Kconfig options depend on LEGACY_IP
net: Change CONFIG_INET to CONFIG_LEGACY_IP for IPv4-only code
net: Warn when processes listen on AF_INET sockets
.../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 6 ++--
.../net/ethernet/mellanox/mlx5/core/en/tc_tun.h | 2 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_encap.c | 2 +-
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 2 +-
include/linux/indirect_call_wrapper.h | 4 ++-
net/bridge/br_arp_nd_proxy.c | 2 +-
net/bridge/br_private.h | 8 +++++
net/core/filter.c | 12 +++----
net/core/secure_seq.c | 2 +-
net/core/sock.c | 2 +-
net/ipv4/Kconfig | 37 ++++++++++++++++++++++
net/ipv4/af_inet.c | 23 +++++++++++---
net/ipv4/devinet.c | 2 ++
net/ipv4/route.c | 1 -
net/ipv4/tcp_ipv4.c | 30 ++++++++++--------
net/mac80211/main.c | 10 +++---
net/netfilter/nfnetlink_queue.c | 2 +-
17 files changed, 105 insertions(+), 42 deletions(-)
^ permalink raw reply
* Re: RFC: phylink: disable PHY autonomous EEE when MAC manages LPI
From: Russell King (Oracle) @ 2026-04-01 7:43 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Nicolai Buchwitz, netdev
In-Reply-To: <04ff15af-26be-4278-bc2a-889e7802d271@lunn.ch>
On Wed, Apr 01, 2026 at 12:56:08AM +0200, Andrew Lunn wrote:
> On Tue, Mar 31, 2026 at 11:27:20PM +0200, Nicolai Buchwitz wrote:
> > Hi
> >
> > Some PHYs (e.g. Broadcom BCM54xx "AutogrEEEn") manage EEE LPI
> > autonomously without forwarding LPI signaling to the MAC. This works
> > fine when the MAC doesn't support EEE, but conflicts with MACs that
> > implement their own LPI control via phylink's mac_enable_tx_lpi /
> > mac_disable_tx_lpi.
> >
> > When the MAC has lpi_capabilities set, the PHY should use Native EEE
> > mode so the MAC can control LPI entry/exit and observe RX LPI
> > transitions.
> >
> > I'm thinking of a flag on phy_device (similar to mac_managed_pm) that
> > phylink sets when the MAC has lpi_capabilities, and that PHY drivers
> > check in config_init to disable their autonomous EEE mode:
> >
> > /* set by phylink when MAC manages LPI */
> > phydev->mac_managed_lpi = true;
> >
> > /* in bcm54xx_config_init: */
> > if (phydev->mac_managed_lpi)
> > bcm_phy_modify_exp(phydev, MII_BUF_CNTL0,
> > AUTOGREEEN_EN, 0);
> >
> > This came up while adding EEE support to the Cadence macb driver (used
> > on Raspberry Pi 5 with a BCM54210PE PHY). The PHY's AutogrEEEn mode
> > prevented the MAC from tracking LPI state. As a workaround, the
> > Raspberry Pi tree currently carries a downstream patch that
> > unconditionally disables AutogrEEEn for all BCM54xx PHYs, since both
> > genet and macb now support EEE properly. That's obviously not suitable
> > for upstream where other MACs paired with BCM54xx may not have LPI
> > support.
> >
> > Does this seem like a reasonable approach, or is there a better way to
> > handle PHY autonomous EEE within phylink?
>
> You should also think about it from the other direction. What happens
> with the MAC does not indicate it supports EEE, but the PHY has
> autonomous EEE. At some point in the future we are going to want the
> PHY drivers to export API calls so that phylink/phylib can implement
> ethtool set_eee and get_eee using this autonomous EEE.
Indeed - this needs to first be solved in phylib so that non-phylink
drivers can work before adding support to phylink.
> Maybe it makes more sense for Broadcom BCM54xx etc, to implement a
> .set_eee() call which only accepts eee_enable == False, and when
> called so, disables autonomous EEE. .get_eee() can similarly return
> that EEE is disabled. When phylink sees the MAC implements EEE it can
> calll into the PHY driver to turn off autonomous EEE. And we have a
> path to later add support for turning on and fully configuring
> autonomous EEE.
I think the current phylink_ethtool_[sg]et_eee() may eventually need
tweaking - for the case where the MAC eee ops are populated but the
MAC support is disabled for some reason - e.g. the instance doesn't
support EEE but the driver does for other instances.
However, I don't think we can re-use phy_ethtool_set_eee() for this -
even with MAC based EEE, we still call through to phylib's
phy_ethtool_set_eee() which would change the on-PHY EEE support in
ways we wouldn't want. This call remains necessary because of the
requirement to configure the EEE advertisement which happens at phylib
level.
I think we need a separate phylib interface which disables PHY-based
EEE.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* [syzbot] Monthly wireless report (Apr 2026)
From: syzbot @ 2026-04-01 7:42 UTC (permalink / raw)
To: linux-kernel, linux-wireless, netdev, syzkaller-bugs
Hello wireless maintainers/developers,
This is a 31-day syzbot report for the wireless subsystem.
All related reports/information can be found at:
https://syzkaller.appspot.com/upstream/s/wireless
During the period, 2 new issues were detected and 2 were fixed.
In total, 51 issues are still open and 174 have already been fixed.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 28045 Yes WARNING in rate_control_rate_init (3)
https://syzkaller.appspot.com/bug?extid=9bdc0c5998ab45b05030
<2> 14590 No WARNING in kcov_remote_start (6)
https://syzkaller.appspot.com/bug?extid=3f51ad7ac3ae57a6fdcc
<3> 10607 Yes WARNING in __rate_control_send_low (3)
https://syzkaller.appspot.com/bug?extid=34463a129786910405dd
<4> 6950 Yes WARNING in __cfg80211_ibss_joined (2)
https://syzkaller.appspot.com/bug?extid=7f064ba1704c2466e36d
<5> 1226 Yes WARNING in ieee80211_start_next_roc
https://syzkaller.appspot.com/bug?extid=c3a167b5615df4ccd7fb
<6> 872 Yes INFO: task hung in reg_check_chans_work (7)
https://syzkaller.appspot.com/bug?extid=a2de4763f84f61499210
<7> 810 Yes INFO: rcu detected stall in ieee80211_handle_queued_frames
https://syzkaller.appspot.com/bug?extid=1c991592da3ef18957c0
<8> 790 No INFO: task hung in netdev_run_todo (4)
https://syzkaller.appspot.com/bug?extid=894cca71fa925aabfdb2
<9> 719 Yes WARNING in ieee80211_tx_h_rate_ctrl
https://syzkaller.appspot.com/bug?extid=0d516b33238bd97ee864
<10> 619 Yes INFO: task hung in crda_timeout_work (8)
https://syzkaller.appspot.com/bug?extid=d41f74db64598e0b5016
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
You may send multiple commands in a single email message.
^ permalink raw reply
* Re: [PATCH net v2 1/4] net: bcmgenet: fix off-by-one in bcmgenet_put_txcb
From: Nicolai Buchwitz @ 2026-04-01 7:41 UTC (permalink / raw)
To: Justin Chen
Cc: netdev, pabeni, kuba, edumazet, davem, andrew+netdev,
bcm-kernel-feedback-list, florian.fainelli, opendmb
In-Reply-To: <20260401003840.3112454-2-justin.chen@broadcom.com>
On 1.4.2026 02:38, Justin Chen wrote:
> The write_ptr points to the next open tx_cb. We want to return the
> tx_cb that gets rewinded, so we must rewind the pointer first then
> return the tx_cb that it points to. That way the txcb can be correctly
> cleaned up.
>
> Fixes: 876dbadd53a7 ("net: bcmgenet: Fix unmapping of fragments in
> bcmgenet_xmit()")
> Signed-off-by: Justin Chen <justin.chen@broadcom.com>
> ---
> drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index 482a31e7b72b..0f6e4baba25b 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -1819,15 +1819,15 @@ static struct enet_cb *bcmgenet_put_txcb(struct
> bcmgenet_priv *priv,
> {
> struct enet_cb *tx_cb_ptr;
>
> - tx_cb_ptr = ring->cbs;
> - tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
> -
> /* Rewinding local write pointer */
> if (ring->write_ptr == ring->cb_ptr)
> ring->write_ptr = ring->end_ptr;
> else
> ring->write_ptr--;
>
> + tx_cb_ptr = ring->cbs;
> + tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
> +
> return tx_cb_ptr;
> }
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks
Nicolai
^ permalink raw reply
* [PATCH net-next 6/6] can: ucan: refactor endpoint lookup
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Johan Hovold, Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Johan Hovold <johan@kernel.org>
Use the common USB helpers for looking up bulk and interrupt endpoints
(and determining endpoint numbers and max packet sizes) instead of open
coding.
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260330101817.1664787-3-johan@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/usb/ucan.c | 40 +++++++++++---------------------------
1 file changed, 11 insertions(+), 29 deletions(-)
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index 0ea0ac75e42f..506d9e74aa79 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -1302,13 +1302,12 @@ static int ucan_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int ret;
- int i;
u32 protocol_version;
struct usb_device *udev;
struct net_device *netdev;
struct usb_host_interface *iface_desc;
struct ucan_priv *up;
- struct usb_endpoint_descriptor *ep;
+ struct usb_endpoint_descriptor *ep_in, *ep_out;
u16 in_ep_size;
u16 out_ep_size;
u8 in_ep_addr;
@@ -1343,37 +1342,20 @@ static int ucan_probe(struct usb_interface *intf,
}
/* check interface endpoints */
- in_ep_addr = 0;
- out_ep_addr = 0;
- in_ep_size = 0;
- out_ep_size = 0;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- ep = &iface_desc->endpoint[i].desc;
-
- if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != 0) &&
- ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
- /* In Endpoint */
- in_ep_addr = ep->bEndpointAddress;
- in_ep_addr &= USB_ENDPOINT_NUMBER_MASK;
- in_ep_size = le16_to_cpu(ep->wMaxPacketSize);
- } else if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
- 0) &&
- ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
- /* Out Endpoint */
- out_ep_addr = ep->bEndpointAddress;
- out_ep_addr &= USB_ENDPOINT_NUMBER_MASK;
- out_ep_size = le16_to_cpu(ep->wMaxPacketSize);
- }
- }
-
- /* check if interface is sane */
- if (!in_ep_addr || !out_ep_addr) {
+ ret = usb_find_common_endpoints_reverse(iface_desc, &ep_in, &ep_out,
+ NULL, NULL);
+ if (ret) {
dev_err(&udev->dev, "%s: invalid endpoint configuration\n",
UCAN_DRIVER_NAME);
goto err_firmware_needs_update;
}
+
+ in_ep_addr = usb_endpoint_num(ep_in);
+ out_ep_addr = usb_endpoint_num(ep_out);
+ in_ep_size = usb_endpoint_maxp(ep_in);
+ out_ep_size = usb_endpoint_maxp(ep_out);
+
+ /* check if interface is sane */
if (in_ep_size < sizeof(struct ucan_message_in)) {
dev_err(&udev->dev, "%s: invalid in_ep MaxPacketSize\n",
UCAN_DRIVER_NAME);
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 1/6] dt-bindings: can: mcp251xfd: add microchip,xstbyen property
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Viken Dadhaniya, Conor Dooley,
Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Add the boolean property 'microchip,xstbyen' to enable the dedicated
transceiver standby control function on the INT0/GPIO0/XSTBY pin of
the MCP251xFD family.
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://patch.msgid.link/20260321135031.3107408-2-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../devicetree/bindings/net/can/microchip,mcp251xfd.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
index 2d13638ebc6a..28e494262cd9 100644
--- a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
@@ -44,6 +44,14 @@ properties:
signals a pending RX interrupt.
maxItems: 1
+ microchip,xstbyen:
+ type: boolean
+ description:
+ If present, configure the INT0/GPIO0/XSTBY pin as transceiver standby
+ control. The pin is driven low when the controller is active and high
+ when it enters Sleep mode, allowing automatic standby control of an
+ external CAN transceiver connected to this pin.
+
spi-max-frequency:
description:
Must be half or less of "clocks" frequency.
base-commit: f1359c240191e686614847905fc861cbda480b47
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 2/6] net: can: ctucanfd: remove useless copy of PCI_DEVICE_DATA macro
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Ethan Nelson-Moore,
Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
The ctucanfd driver has its own copy of the PCI_DEVICE_DATA macro. I
assume this was done to support older kernel versions where it didn't
exist, but that is irrelevant once the driver is in the mainline
kernel. Remove it.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Link: https://patch.msgid.link/20260130114134.47421-1-enelsonmoore@gmail.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/ctucanfd/ctucanfd_pci.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/drivers/net/can/ctucanfd/ctucanfd_pci.c b/drivers/net/can/ctucanfd/ctucanfd_pci.c
index 7b847b667973..625788fa8976 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c
@@ -22,14 +22,6 @@
#include "ctucanfd.h"
-#ifndef PCI_DEVICE_DATA
-#define PCI_DEVICE_DATA(vend, dev, data) \
-.vendor = PCI_VENDOR_ID_##vend, \
-.device = PCI_DEVICE_ID_##vend##_##dev, \
-.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \
-.driver_data = (kernel_ulong_t)(data)
-#endif
-
#ifndef PCI_VENDOR_ID_TEDIA
#define PCI_VENDOR_ID_TEDIA 0x1760
#endif
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 5/6] can: rcar_can: Convert to FIELD_MODIFY()
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Geert Uytterhoeven,
Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Geert Uytterhoeven <geert+renesas@glider.be>
Use the FIELD_MODIFY() helper instead of open-coding the same operation.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/ee2e6aaacd5e061c972716ecaf8a929be7ef5f2e.1772705647.git.geert+renesas@glider.be
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/rcar/rcar_can.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index fc3df328e877..2727c5ce029c 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -496,8 +496,7 @@ static void rcar_can_start(struct net_device *ndev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Go to operation mode */
- ctlr &= ~RCAR_CAN_CTLR_CANM;
- ctlr |= FIELD_PREP(RCAR_CAN_CTLR_CANM, RCAR_CAN_CTLR_CANM_OPER);
+ FIELD_MODIFY(RCAR_CAN_CTLR_CANM, &ctlr, RCAR_CAN_CTLR_CANM_OPER);
writew(ctlr, &priv->regs->ctlr);
for (i = 0; i < MAX_STR_READS; i++) {
if (!(readw(&priv->regs->str) & RCAR_CAN_STR_RSTST))
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 4/6] can: mcp251xfd: add support for XSTBYEN transceiver standby control
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Viken Dadhaniya,
Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
The MCP251xFD has a dedicated transceiver standby control function on
the INT0/GPIO0/XSTBY pin, controlled by the XSTBYEN bit in IOCON.
When enabled, the hardware automatically manages the transceiver
standby state: the pin is driven low when the controller is active
and high when it enters Sleep mode.
Enable this feature when the 'microchip,xstbyen' device tree property
is present.
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Link: https://patch.msgid.link/20260321135031.3107408-3-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-core.c | 37 +++++++++++++++++++
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 9c86df08c2c5..92a86083c896 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -764,6 +764,31 @@ static void mcp251xfd_chip_stop(struct mcp251xfd_priv *priv,
mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG);
}
+static int mcp251xfd_chip_xstbyen_enable(const struct mcp251xfd_priv *priv)
+{
+ /* Configure the INT0/GPIO0/XSTBY pin as transceiver standby control:
+ *
+ * - XSTBYEN=1: route the pin to the transceiver standby function
+ * - TRIS0=0: set output direction; the reset default is 1 (input),
+ * which leaves the pin floating HIGH and keeps the
+ * transceiver in standby regardless of XSTBYEN
+ * - LAT0=0: drive pin LOW => transceiver active (not in standby)
+ *
+ * All three bits are included in the mask; only XSTBYEN is set in
+ * val, so TRIS0 and LAT0 are cleared to 0 atomically.
+ *
+ * Pin behaviour by mode:
+ * - Config mode: controlled by LAT0 (LAT0=0 => LOW => active)
+ * - Normal mode: hardware drives pin LOW (active)
+ * - Sleep mode: hardware drives pin HIGH (standby)
+ */
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON,
+ MCP251XFD_REG_IOCON_XSTBYEN |
+ MCP251XFD_REG_IOCON_TRIS0 |
+ MCP251XFD_REG_IOCON_LAT0,
+ MCP251XFD_REG_IOCON_XSTBYEN);
+}
+
static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
{
int err;
@@ -796,6 +821,12 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ if (priv->xstbyen) {
+ err = mcp251xfd_chip_xstbyen_enable(priv);
+ if (err)
+ goto out_chip_stop;
+ }
+
err = mcp251xfd_chip_set_normal_mode(priv);
if (err)
goto out_chip_stop;
@@ -1805,6 +1836,11 @@ static int mcp251xfd_gpio_request(struct gpio_chip *chip, unsigned int offset)
u32 pin_mask = MCP251XFD_REG_IOCON_PM(offset);
int ret;
+ if (priv->xstbyen && offset == 0) {
+ netdev_err(priv->ndev, "Can't use GPIO 0 with XSTBYEN!\n");
+ return -EINVAL;
+ }
+
if (priv->rx_int && offset == 1) {
netdev_err(priv->ndev, "Can't use GPIO 1 with RX-INT!\n");
return -EINVAL;
@@ -2271,6 +2307,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
priv->pll_enable = pll_enable;
priv->reg_vdd = reg_vdd;
priv->reg_xceiver = reg_xceiver;
+ priv->xstbyen = device_property_present(&spi->dev, "microchip,xstbyen");
priv->devtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);
/* Errata Reference:
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 085d7101e595..d3f4704e2678 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -672,6 +672,7 @@ struct mcp251xfd_priv {
struct gpio_desc *rx_int;
struct clk *clk;
bool pll_enable;
+ bool xstbyen;
struct regulator *reg_vdd;
struct regulator *reg_xceiver;
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 3/6] can: kvaser_usb: leaf: refactor endpoint lookup
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Johan Hovold, Marc Kleine-Budde
In-Reply-To: <20260401073338.5592-1-mkl@pengutronix.de>
From: Johan Hovold <johan@kernel.org>
Use the common USB helper for looking up bulk and interrupt endpoints
instead of open coding.
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260330101817.1664787-2-johan@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 25 ++++++-------------
1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index fd191ec5738b..df737cfc5ea0 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -1957,27 +1957,18 @@ static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev,
static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
{
- const struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- int i;
+ struct usb_host_interface *iface_desc;
+ int ret;
iface_desc = dev->intf->cur_altsetting;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
+ /* use first bulk endpoint for in and out */
+ ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in, &dev->bulk_out,
+ NULL, NULL);
+ if (ret)
+ return -ENODEV;
- if (!dev->bulk_in && usb_endpoint_is_bulk_in(endpoint))
- dev->bulk_in = endpoint;
-
- if (!dev->bulk_out && usb_endpoint_is_bulk_out(endpoint))
- dev->bulk_out = endpoint;
-
- /* use first bulk endpoint for in and out */
- if (dev->bulk_in && dev->bulk_out)
- return 0;
- }
-
- return -ENODEV;
+ return 0;
}
const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 0/6] pull-request: can-next 2026-04-01
From: Marc Kleine-Budde @ 2026-04-01 7:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel
Hello netdev-team,
this is a pull request of 6 patches for net-next/main.
The first patch is by Ethan Nelson-Moore and removes a useless copy of
PCI_DEVICE_DATA from the ctucanfd driver.
Geert Uytterhoeven's patch for the rcar_can converts the driver to use
the FIELD_MODIFY macro.
Viken Dadhaniya contributes 2 patches for the mcp251xfd driver that
add transceiver standby control.
The last 2 aptches are by Johan Hovold and refactor the usb endpoint
lookup of the kvaser_usb and ucan driver.
regards,
Marc
---
The following changes since commit f1359c240191e686614847905fc861cbda480b47:
net/iucv: Add missing kernel-doc return value descriptions (2026-03-31 20:14:56 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git tags/linux-can-next-for-7.1-20260401
for you to fetch changes up to 50b4927288144fbd2f947b0e4c0ef32949587e67:
Merge patch series "can: refactor USB endpoint lookups" (2026-04-01 09:27:58 +0200)
----------------------------------------------------------------
linux-can-next-for-7.1-20260401
----------------------------------------------------------------
Ethan Nelson-Moore (1):
net: can: ctucanfd: remove useless copy of PCI_DEVICE_DATA macro
Geert Uytterhoeven (1):
can: rcar_can: Convert to FIELD_MODIFY()
Johan Hovold (2):
can: kvaser_usb: leaf: refactor endpoint lookup
can: ucan: refactor endpoint lookup
Marc Kleine-Budde (2):
Merge patch series "can: mcp251xfd: add XSTBYEN transceiver standby control"
Merge patch series "can: refactor USB endpoint lookups"
Viken Dadhaniya (2):
dt-bindings: can: mcp251xfd: add microchip,xstbyen property
can: mcp251xfd: add support for XSTBYEN transceiver standby control
.../bindings/net/can/microchip,mcp251xfd.yaml | 8 +++++
drivers/net/can/ctucanfd/ctucanfd_pci.c | 8 -----
drivers/net/can/rcar/rcar_can.c | 3 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 37 ++++++++++++++++++++
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 1 +
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 25 +++++---------
drivers/net/can/usb/ucan.c | 40 ++++++----------------
7 files changed, 66 insertions(+), 56 deletions(-)
^ permalink raw reply
* Re: [PATCH net-next v2 1/9] net: dsa: add tag driver for LAN9645X
From: Jens Emil Schulz Ostergaard @ 2026-04-01 7:31 UTC (permalink / raw)
To: Jakub Kicinski
Cc: UNGLinuxDriver, andrew, olteanv, davem, edumazet, pabeni, horms,
robh, krzk+dt, conor+dt, woojung.huh, linux, Steen.Hegelund,
daniel.machon, linux-kernel, netdev, devicetree
In-Reply-To: <20260329195620.2789042-1-kuba@kernel.org>
On Sun, 2026-03-29 at 12:56 -0700, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> net: dsa: add tag driver for LAN9645X
>
> Add a tag driver for LAN9645x switches using a front port as the CPU port
> (NPI port). The driver configures a long prefix for extraction and no
> prefix for injection to handle the internal frame header (IFH).
>
> > diff --git a/net/dsa/tag_lan9645x.c b/net/dsa/tag_lan9645x.c
> > new file mode 100644
> > index 000000000000..9130fb0d61be
> > --- /dev/null
> > +++ b/net/dsa/tag_lan9645x.c
>
> [ ... ]
>
> > +static void lan9645x_xmit_get_vlan_info(struct sk_buff *skb,
> > + struct net_device *br,
> > + u32 *vlan_tci, u32 *tag_type)
> > +{
> > + struct vlan_ethhdr *hdr;
> > + u16 proto, tci;
> > +
> > + if (!br || !br_vlan_enabled(br)) {
> > + *vlan_tci = 0;
> > + *tag_type = LAN9645X_IFH_TAG_TYPE_C;
> > + return;
> > + }
> > +
> > + hdr = (struct vlan_ethhdr *)skb_mac_header(skb);
> > + br_vlan_get_proto(br, &proto);
> > +
> > + if (ntohs(hdr->h_vlan_proto) == proto) {
> > + vlan_remove_tag(skb, &tci);
>
> Is it possible for a maliciously crafted packet (e.g., via AF_PACKET) to have a
> length of 14 bytes with h_vlan_proto set to ETH_P_8021Q?
>
> If so, vlan_remove_tag() would read vhdr->h_vlan_TCI at offset 14, causing an
> out-of-bounds read.
>
> Furthermore, if the packet contains fragments and the VLAN header is not in the
> linear data area, vlan_remove_tag() could corrupt the SKB when shifting the MAC
> header.
>
> Would it be safer to use skb_vlan_untag() instead?
>
I think skb_vlan_untag is for the rx path, and will not make sense here. But I
can add a check like
if (skb_headlen(skb) >= VLAN_ETH_HLEN &&
ntohs(hdr->h_vlan_proto) == proto) {
vlan_remove_tag(skb, &tci);
*vlan_tci = tci;
} else {
so we know the linear data area has the bytes.
> > + *vlan_tci = tci;
> > + } else {
> > + rcu_read_lock();
> > + br_vlan_get_pvid_rcu(br, &tci);
> > + rcu_read_unlock();
> > + *vlan_tci = tci;
> > + }
> > +
> > + *tag_type = (proto != ETH_P_8021Q) ? LAN9645X_IFH_TAG_TYPE_S :
> > + LAN9645X_IFH_TAG_TYPE_C;
> > +}
>
> [ ... ]
>
> > +static struct sk_buff *lan9645x_rcv(struct sk_buff *skb,
> > + struct net_device *ndev)
> > +{
> > + u32 src_port, qos_class, vlan_tci, tag_type, popcnt, etype_ofs;
> > + u8 *orig_skb_data = skb->data;
> > + struct dsa_port *dp;
> > + u32 ifh_gap_len = 0;
> > + u16 vlan_tpid;
> > + u8 *ifh;
> > +
> > + /* DSA master already consumed DMAC,SMAC,ETYPE from long prefix. Go back
> > + * to beginning of frame.
> > + */
> > + skb_push(skb, ETH_HLEN);
> > + /* IFH starts after our long prefix */
> > + ifh = skb_pull(skb, LAN9645X_LONG_PREFIX_LEN);
>
> Could skb_pull() return NULL here if skb->len is less than 16 bytes?
>
> If it returns NULL, the blind dereference of ifh in the subsequent
> lan9645x_ifh_get() calls would cause a NULL pointer dereference.
>
> Additionally, is the 44-byte tag (16-byte prefix + 28-byte IFH) guaranteed to
> be in the linear data buffer (skb->data)?
>
> Without calling pskb_may_pull(skb, LAN9645X_TOTAL_TAG_LEN) first, accessing it
> via the ifh pointer might result in out-of-bounds reads if the packet payload
> is in paged fragments.
>
I can add pskb_may_pull calls to ensure skb->data is availble.
> > +
> > + popcnt = lan9645x_ifh_get(ifh, IFH_POP_CNT, IFH_POP_CNT_SZ);
> > + etype_ofs = lan9645x_ifh_get(ifh, IFH_ETYPE_OFS, IFH_ETYPE_OFS_SZ);
> > + src_port = lan9645x_ifh_get(ifh, IFH_SRCPORT, IFH_SRCPORT_SZ);
> --
> pw-bot: cr
^ permalink raw reply
* Re: [PATCH net-next v2 4/5] ipv6: mld: encode multicast exponential fields
From: Ido Schimmel @ 2026-04-01 7:29 UTC (permalink / raw)
To: Ujjal Roy
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, David Ahern, Shuah Khan,
Andy Roulin, Yong Wang, Petr Machata, Ujjal Roy, bridge, netdev,
linux-kernel, linux-kselftest
In-Reply-To: <20260330191611.16929-5-royujjal@gmail.com>
On Mon, Mar 30, 2026 at 07:16:10PM +0000, Ujjal Roy wrote:
> In MLD, QQIC and MRC fields are not currently encoded when
s/currently/correctly/
> generating query packets. Since the receiver of the query
> interprets these fields using the MLDv2 floating-point
> decoding logic, any raw interval value that exceeds the
> linear threshold is currently parsed incorrectly as an
> exponential value, leading to an incorrect interval
> calculation.
[...]
> +static inline u16 mldv2_mrc(unsigned long mrd)
> +{
> + u16 mc_man, mc_exp;
> +
> + /* RFC3810: MRC < 32768 is literal */
> + if (mrd < MLD_MRC_MIN_THRESHOLD)
> + return (u16)mrd;
> +
> + /* Saturate at max representable (mant = 0xFFF, exp = 7) -> 8387584 */
> + if (mrd >= MLD_MRC_MAX_THRESHOLD)
> + return 0xFFFF;
> +
> + mc_exp = (u16)(fls(mrd) - 16);
> + mc_man = (u16)((mrd >> (mc_exp + 3)) & 0x0FFF);
> +
> + return (0x8000 | (mc_exp << 12) | mc_man);
> +}
[...]
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 27010744d7ae..c2d144f6a86e 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -1181,7 +1181,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
> break;
> case 2:
> mld2q = (struct mld2_query *)icmp6_hdr(skb);
> - mld2q->mld2q_mrc = htons((u16)jiffies_to_msecs(interval));
> + mld2q->mld2q_mrc = htons((u16)jiffies_to_msecs(mldv2_mrc(interval)));
This looks wrong. mldv2_mrc() is supposed to receive the maximum
response delay in milliseconds, but you are passing jiffies.
> mld2q->mld2q_type = ICMPV6_MGM_QUERY;
> mld2q->mld2q_code = 0;
> mld2q->mld2q_cksum = 0;
> @@ -1190,7 +1190,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
> mld2q->mld2q_suppress = sflag;
> mld2q->mld2q_qrv = 2;
> mld2q->mld2q_nsrcs = htons(llqt_srcs);
> - mld2q->mld2q_qqic = brmctx->multicast_query_interval / HZ;
> + mld2q->mld2q_qqic = mldv2_qqic(brmctx->multicast_query_interval / HZ);
> mld2q->mld2q_mca = *group;
> csum = &mld2q->mld2q_cksum;
> csum_start = (void *)mld2q;
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH net-next 3/4] ethtool: strset: check nla_len overflow before nla_nest_end
From: Hangbin Liu @ 2026-04-01 7:27 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Donald Hunter, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Andrew Lunn, netdev, linux-kernel
In-Reply-To: <20260331184637.58b968ef@kernel.org>
On Tue, Mar 31, 2026 at 06:46:37PM -0700, Jakub Kicinski wrote:
> On Tue, 31 Mar 2026 11:56:13 +0800 Hangbin Liu wrote:
> > + if (skb_tail_pointer(skb) - (unsigned char *)strings_attr > U16_MAX)
> > + goto nla_put_failure;
>
> bit ugly, let's add a variant of nla_nest_end() which can return
> an error on overflow (without the warning from patch 4) ?
I was tried to not touch nla_nest_end() as it is used everywhere. But it makes
sense to me to add a new function to check this. I'm not very good at naming,
maybe `nla_nest_end_validate()` ? Or any other name if you have?
Thanks
Hangbin
>
> > +
> > nla_nest_end(skb, strings_attr);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox