From 9c9211a3fc7aa41b2952765b62000443b3bb6f23 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Fri, 10 Dec 2021 16:59:58 +0800 Subject: [PATCH 01/20] net_tstamp: add new flag HWTSTAMP_FLAG_BONDED_PHC_INDEX Since commit 94dd016ae538 ("bond: pass get_ts_info and SIOC[SG]HWTSTAMP ioctl to active device") the user could get bond active interface's PHC index directly. But when there is a failover, the bond active interface will change, thus the PHC index is also changed. This may break the user's program if they did not update the PHC timely. This patch adds a new hwtstamp_config flag HWTSTAMP_FLAG_BONDED_PHC_INDEX. When the user wants to get the bond active interface's PHC, they need to add this flag and be aware the PHC index may be changed. With the new flag. All flag checks in current drivers are removed. Only the checking in net_hwtstamp_validate() is kept. Suggested-by: Jakub Kicinski Signed-off-by: Hangbin Liu Signed-off-by: David S. Miller --- drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c | 4 ---- drivers/net/dsa/mv88e6xxx/hwtstamp.c | 4 ---- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 3 --- drivers/net/ethernet/aquantia/atlantic/aq_main.c | 3 --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 5 ----- drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 3 --- drivers/net/ethernet/broadcom/tg3.c | 3 --- drivers/net/ethernet/cadence/macb_ptp.c | 4 ---- drivers/net/ethernet/cavium/liquidio/lio_main.c | 3 --- .../net/ethernet/cavium/liquidio/lio_vf_main.c | 3 --- drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 3 --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 4 ---- drivers/net/ethernet/engleder/tsnep_ptp.c | 3 --- drivers/net/ethernet/freescale/fec_ptp.c | 4 ---- drivers/net/ethernet/freescale/gianfar.c | 4 ---- drivers/net/ethernet/intel/e1000e/netdev.c | 4 ---- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 4 ---- drivers/net/ethernet/intel/ice/ice_ptp.c | 4 ---- drivers/net/ethernet/intel/igb/igb_ptp.c | 4 ---- drivers/net/ethernet/intel/igc/igc_ptp.c | 4 ---- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 4 ---- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 --- .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 4 ---- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 4 ---- drivers/net/ethernet/microchip/lan743x_ptp.c | 6 ------ drivers/net/ethernet/mscc/ocelot.c | 4 ---- drivers/net/ethernet/neterion/vxge/vxge-main.c | 4 ---- .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 3 --- drivers/net/ethernet/qlogic/qede/qede_ptp.c | 5 ----- drivers/net/ethernet/renesas/ravb_main.c | 4 ---- drivers/net/ethernet/sfc/ptp.c | 3 --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ---- drivers/net/ethernet/ti/cpsw_priv.c | 4 ---- drivers/net/ethernet/ti/netcp_ethss.c | 4 ---- drivers/net/ethernet/xscale/ixp4xx_eth.c | 3 --- drivers/net/phy/dp83640.c | 3 --- drivers/net/phy/mscc/mscc_ptp.c | 3 --- drivers/ptp/ptp_ines.c | 4 ---- include/uapi/linux/net_tstamp.h | 16 +++++++++++++++- net/core/dev_ioctl.c | 2 +- 40 files changed, 16 insertions(+), 144 deletions(-) diff --git a/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c b/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c index 40b41c794dfac..b3bc948d6145b 100644 --- a/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c +++ b/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c @@ -52,10 +52,6 @@ static int hellcreek_set_hwtstamp_config(struct hellcreek *hellcreek, int port, */ clear_bit_unlock(HELLCREEK_HWTSTAMP_ENABLED, &ps->state); - /* Reserved for future extensions */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_ON: tx_tstamp_enable = true; diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c index 8f74ffc7a2799..389f8a6ec0ab3 100644 --- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c +++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c @@ -100,10 +100,6 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port, */ clear_bit_unlock(MV88E6XXX_HWTSTAMP_ENABLED, &ps->state); - /* reserved for future extensions */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: tstamp_enable = false; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 30d24d19f40d1..492ac383f16df 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1508,9 +1508,6 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, if (copy_from_user(&config, ifreq->ifr_data, sizeof(config))) return -EFAULT; - if (config.flags) - return -EINVAL; - mac_tscr = 0; switch (config.tx_type) { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index e22935ce95730..e65ce7199dac9 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c @@ -231,9 +231,6 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic, struct hwtstamp_config *config) { - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_ON: diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index aec666e976831..651bc1d7a57ab 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -15356,11 +15356,6 @@ static int bnx2x_hwtstamp_ioctl(struct bnx2x *bp, struct ifreq *ifr) DP(BNX2X_MSG_PTP, "Requested tx_type: %d, requested rx_filters = %d\n", config.tx_type, config.rx_filter); - if (config.flags) { - BNX2X_ERR("config.flags is reserved for future use\n"); - return -EINVAL; - } - bp->hwtstamp_ioctl_called = true; bp->tx_type = config.tx_type; bp->rx_filter = config.rx_filter; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c index 8388be119f9a0..48520967746ff 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c @@ -417,9 +417,6 @@ int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) return -EFAULT; - if (stmpconf.flags) - return -EINVAL; - if (stmpconf.tx_type != HWTSTAMP_TX_ON && stmpconf.tx_type != HWTSTAMP_TX_OFF) return -ERANGE; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 283f3c1f11950..c28f8cc00d1cf 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -13806,9 +13806,6 @@ static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) return -EFAULT; - if (stmpconf.flags) - return -EINVAL; - if (stmpconf.tx_type != HWTSTAMP_TX_ON && stmpconf.tx_type != HWTSTAMP_TX_OFF) return -ERANGE; diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c index 095c5a2144a71..fb6b27f46b153 100644 --- a/drivers/net/ethernet/cadence/macb_ptp.c +++ b/drivers/net/ethernet/cadence/macb_ptp.c @@ -464,10 +464,6 @@ int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd) sizeof(*tstamp_config))) return -EFAULT; - /* reserved for future extensions */ - if (tstamp_config->flags) - return -EINVAL; - switch (tstamp_config->tx_type) { case HWTSTAMP_TX_OFF: break; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 12eee2bc7f5c8..ba28aa444e5ae 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -2114,9 +2114,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf))) return -EFAULT; - if (conf.flags) - return -EINVAL; - switch (conf.tx_type) { case HWTSTAMP_TX_ON: case HWTSTAMP_TX_OFF: diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index c607756b731f0..568f211d91ccd 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -1254,9 +1254,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf))) return -EFAULT; - if (conf.flags) - return -EINVAL; - switch (conf.tx_type) { case HWTSTAMP_TX_ON: case HWTSTAMP_TX_OFF: diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index 4b4ffdd1044d8..103591dcea1c3 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -702,9 +702,6 @@ static int octeon_mgmt_ioctl_hwtstamp(struct net_device *netdev, if (copy_from_user(&config, rq->ifr_data, sizeof(config))) return -EFAULT; - if (config.flags) /* reserved for future extensions */ - return -EINVAL; - /* Check the status of hardware for tiemstamps */ if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { /* Get the current state of the PTP clock */ diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index bb45d5df2856f..63191692f624c 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1917,10 +1917,6 @@ static int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_ON: diff --git a/drivers/net/ethernet/engleder/tsnep_ptp.c b/drivers/net/ethernet/engleder/tsnep_ptp.c index 4bfb4d8508f58..eaad453d487e1 100644 --- a/drivers/net/ethernet/engleder/tsnep_ptp.c +++ b/drivers/net/ethernet/engleder/tsnep_ptp.c @@ -31,9 +31,6 @@ int tsnep_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_ON: diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index d71eac7e19249..af99017a54539 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -473,10 +473,6 @@ int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: fep->hwts_tx_en = 0; diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index acab58fd3db38..206b7a35eaf55 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2076,10 +2076,6 @@ static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: priv->hwts_tx_en = 0; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 44e2dc8328a22..635a95927e930 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3614,10 +3614,6 @@ static int e1000e_config_hwtstamp(struct e1000_adapter *adapter, if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) return -EINVAL; - /* flags reserved for future extensions - must be zero */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 09b1d5aed1c9f..61e5789d78db7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -1205,10 +1205,6 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, INIT_WORK(&pf->ptp_extts0_work, i40e_ptp_extts0_work); - /* Reserved for future extensions. */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: pf->ptp_tx = false; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index bf7247c6f58e2..dfc7c830acf61 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -1205,10 +1205,6 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) static int ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) { - /* Reserved for future extensions. */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: ice_set_tx_tstamp(pf, false); diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 0011b15e678c3..0ac4cc5eaa2d1 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -1015,10 +1015,6 @@ static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter, bool is_l2 = false; u32 regval; - /* reserved for future extensions */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 30568e3544cda..71813fa8f928a 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -560,10 +560,6 @@ static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter) static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, struct hwtstamp_config *config) { - /* reserved for future extensions */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: igc_ptp_disable_tx_timestamp(adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 23ddfd79fc8b6..336426a67ac1b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -992,10 +992,6 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter, bool is_l2 = false; u32 regval; - /* reserved for future extensions */ - if (config->flags) - return -EINVAL; - switch (config->tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 8e5820d123627..b1cce44252965 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -5142,9 +5142,6 @@ static int mvpp2_set_ts_config(struct mvpp2_port *port, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - if (config.flags) - return -EINVAL; - if (config.tx_type != HWTSTAMP_TX_OFF && config.tx_type != HWTSTAMP_TX_ON) return -ERANGE; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 1333edf1c361c..6080ebd9bd947 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -2002,10 +2002,6 @@ int otx2_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: otx2_config_hw_tx_tstamp(pfvf, false); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f1c10f2bda780..ad1e4caf48bf3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2427,10 +2427,6 @@ static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - /* device doesn't support time stamping */ if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)) return -EINVAL; diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c index 9380e396f6487..8b7a8d879083b 100644 --- a/drivers/net/ethernet/microchip/lan743x_ptp.c +++ b/drivers/net/ethernet/microchip/lan743x_ptp.c @@ -1305,12 +1305,6 @@ int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; - if (config.flags) { - netif_warn(adapter, drv, adapter->netdev, - "ignoring hwtstamp_config.flags == 0x%08X, expected 0\n", - config.flags); - } - switch (config.tx_type) { case HWTSTAMP_TX_OFF: for (index = 0; index < LAN743X_MAX_TX_CHANNELS; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 876a7ecf86eba..9b42187a026a8 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1617,10 +1617,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - /* reserved for future extensions */ - if (cfg.flags) - return -EINVAL; - /* Tx type sanity check */ switch (cfg.tx_type) { case HWTSTAMP_TX_ON: diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 1969009a91e79..2c2e9e56ed4e5 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3159,10 +3159,6 @@ static int vxge_hwtstamp_set(struct vxgedev *vdev, void __user *data) if (copy_from_user(&config, data, sizeof(config))) return -EFAULT; - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - /* Transmit HW Timestamp not supported */ switch (config.tx_type) { case HWTSTAMP_TX_OFF: diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 71d234291fc57..1dc40c5372813 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -210,9 +210,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - if (cfg.flags) /* reserved for future extensions */ - return -EINVAL; - /* Get ieee1588's dev information */ pdev = adapter->ptp_pdev; diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 8c28fabb0ff63..39176e7657676 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -304,11 +304,6 @@ int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *ifr) "HWTSTAMP IOCTL: Requested tx_type = %d, requested rx_filters = %d\n", config.tx_type, config.rx_filter); - if (config.flags) { - DP_ERR(edev, "config.flags is reserved for future use\n"); - return -EINVAL; - } - ptp->hw_ts_ioctl_called = 1; ptp->tx_type = config.tx_type; ptp->rx_filter = config.rx_filter; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ce09bd45527ea..b215cde68e10b 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -2221,10 +2221,6 @@ static int ravb_hwtstamp_set(struct net_device *ndev, struct ifreq *req) if (copy_from_user(&config, req->ifr_data, sizeof(config))) return -EFAULT; - /* Reserved for future extensions */ - if (config.flags) - return -EINVAL; - switch (config.tx_type) { case HWTSTAMP_TX_OFF: tstamp_tx_ctrl = 0; diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 797e51802ccbb..f0ef515e2ade5 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1765,9 +1765,6 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) { int rc; - if (init->flags) - return -EINVAL; - if ((init->tx_type != HWTSTAMP_TX_OFF) && (init->tx_type != HWTSTAMP_TX_ON)) return -ERANGE; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7e3e1bc0f61d1..c26ac288f9814 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -638,10 +638,6 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", __func__, config.flags, config.tx_type, config.rx_filter); - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - if (config.tx_type != HWTSTAMP_TX_OFF && config.tx_type != HWTSTAMP_TX_ON) return -ERANGE; diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c index c99dd9735087d..8624a044776f2 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.c +++ b/drivers/net/ethernet/ti/cpsw_priv.c @@ -626,10 +626,6 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - /* reserved for future extensions */ - if (cfg.flags) - return -EINVAL; - if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON) return -ERANGE; diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 33c1592d5381e..751fb0bc65c50 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2654,10 +2654,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - /* reserved for future extensions */ - if (cfg.flags) - return -EINVAL; - switch (cfg.tx_type) { case HWTSTAMP_TX_OFF: gbe_dev->tx_ts_enabled = 0; diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 65fdad1107fc5..df77a22d1b81c 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -382,9 +382,6 @@ static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - if (cfg.flags) /* reserved for future extensions */ - return -EINVAL; - ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); if (ret) return ret; diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 705c16675b80c..c2d1a85ec5591 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1235,9 +1235,6 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - if (cfg.flags) /* reserved for future extensions */ - return -EINVAL; - if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ONESTEP_SYNC) return -ERANGE; diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c index edb951695b13e..34f829845d067 100644 --- a/drivers/net/phy/mscc/mscc_ptp.c +++ b/drivers/net/phy/mscc/mscc_ptp.c @@ -1057,9 +1057,6 @@ static int vsc85xx_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - if (cfg.flags) - return -EINVAL; - switch (cfg.tx_type) { case HWTSTAMP_TX_ONESTEP_SYNC: one_step = true; diff --git a/drivers/ptp/ptp_ines.c b/drivers/ptp/ptp_ines.c index 6c7c2843ba0b0..61f47fb9d9979 100644 --- a/drivers/ptp/ptp_ines.c +++ b/drivers/ptp/ptp_ines.c @@ -338,10 +338,6 @@ static int ines_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - /* reserved for future extensions */ - if (cfg.flags) - return -EINVAL; - switch (cfg.tx_type) { case HWTSTAMP_TX_OFF: ts_stat_tx = 0; diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h index fcc61c73a6668..e258e52cfd1fc 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h @@ -62,7 +62,7 @@ struct so_timestamping { /** * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter * - * @flags: no flags defined right now, must be zero for %SIOCSHWTSTAMP + * @flags: one of HWTSTAMP_FLAG_* * @tx_type: one of HWTSTAMP_TX_* * @rx_filter: one of HWTSTAMP_FILTER_* * @@ -78,6 +78,20 @@ struct hwtstamp_config { int rx_filter; }; +/* possible values for hwtstamp_config->flags */ +enum hwtstamp_flags { + /* + * With this flag, the user could get bond active interface's + * PHC index. Note this PHC index is not stable as when there + * is a failover, the bond active interface will be changed, so + * will be the PHC index. + */ + HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0), + + HWTSTAMP_FLAG_LAST = HWTSTAMP_FLAG_BONDED_PHC_INDEX, + HWTSTAMP_FLAG_MASK = (HWTSTAMP_FLAG_LAST - 1) | HWTSTAMP_FLAG_LAST +}; + /* possible values for hwtstamp_config->tx_type */ enum hwtstamp_tx_types { /* diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 1d309a6669325..1b807d119da54 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -192,7 +192,7 @@ static int net_hwtstamp_validate(struct ifreq *ifr) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) return -EFAULT; - if (cfg.flags) /* reserved for future extensions */ + if (cfg.flags & ~HWTSTAMP_FLAG_MASK) return -EINVAL; tx_type = cfg.tx_type; From 085d61000845188a9aa9a9524f13a0622a1380d7 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Fri, 10 Dec 2021 16:59:59 +0800 Subject: [PATCH 02/20] Bonding: force user to add HWTSTAMP_FLAG_BONDED_PHC_INDEX when get/set HWTSTAMP When there is a failover, the PHC index of bond active interface will be changed. This may break the user space program if the author didn't aware. By setting this flag, the user should aware that the PHC index get/set by syscall is not stable. And the user space is able to deal with it. Without this flag, the kernel will reject the request forwarding to bonding. Reported-by: Jakub Kicinski Fixes: 94dd016ae538 ("bond: pass get_ts_info and SIOC[SG]HWTSTAMP ioctl to active device") Signed-off-by: Hangbin Liu Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 274f0c4f2dab1..b60e22f6394aa 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4094,6 +4094,7 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm struct mii_ioctl_data *mii = NULL; const struct net_device_ops *ops; struct net_device *real_dev; + struct hwtstamp_config cfg; struct ifreq ifrr; int res = 0; @@ -4124,21 +4125,29 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm break; case SIOCSHWTSTAMP: case SIOCGHWTSTAMP: - rcu_read_lock(); - real_dev = bond_option_active_slave_get_rcu(bond); - rcu_read_unlock(); - if (real_dev) { - strscpy_pad(ifrr.ifr_name, real_dev->name, IFNAMSIZ); - ifrr.ifr_ifru = ifr->ifr_ifru; + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + if (cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX) { + rcu_read_lock(); + real_dev = bond_option_active_slave_get_rcu(bond); + rcu_read_unlock(); + if (real_dev) { + strscpy_pad(ifrr.ifr_name, real_dev->name, IFNAMSIZ); + ifrr.ifr_ifru = ifr->ifr_ifru; + + ops = real_dev->netdev_ops; + if (netif_device_present(real_dev) && ops->ndo_eth_ioctl) { + res = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd); - ops = real_dev->netdev_ops; - if (netif_device_present(real_dev) && ops->ndo_eth_ioctl) - res = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd); + if (!res) + ifr->ifr_ifru = ifrr.ifr_ifru; - if (!res) - ifr->ifr_ifru = ifrr.ifr_ifru; + return res; + } + } } - break; + fallthrough; default: res = -EOPNOTSUPP; } From a9aa5e3320ae9d322091993e4ed1b7e7651f00a1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 13 Dec 2021 17:29:31 +0100 Subject: [PATCH 03/20] net: dev: Change the order of the arguments for the contended condition. Change the order of arguments and make qdisc_is_running() appear first. This is more readable for the general case. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 53bef2aae3782..a855e41bbe392 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3724,7 +3724,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, * sent after the qdisc owner is scheduled again. To prevent this * scenario the task always serialize on the lock. */ - contended = IS_ENABLED(CONFIG_PREEMPT_RT) || qdisc_is_running(q); + contended = qdisc_is_running(q) || IS_ENABLED(CONFIG_PREEMPT_RT); if (unlikely(contended)) spin_lock(&q->busylock); From 0976b888a150476ba955ce4765858824c633cfd2 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 13 Dec 2021 17:39:02 -0800 Subject: [PATCH 04/20] ethtool: fix null-ptr-deref on ref tracker dev can be a NULL here, not all requests set require_dev. Fixes: e4b8954074f6 ("netlink: add net device refcount tracker to struct ethnl_req_info") Signed-off-by: Jakub Kicinski Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ethtool/netlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 23f32a995099a..767fb3f172676 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -141,8 +141,10 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, return -EINVAL; } - req_info->dev = dev; - netdev_tracker_alloc(dev, &req_info->dev_tracker, GFP_KERNEL); + if (dev) { + req_info->dev = dev; + netdev_tracker_alloc(dev, &req_info->dev_tracker, GFP_KERNEL); + } req_info->flags = flags; return 0; } From b4bffa4ceab1be0e4cc39aa56c0746a63e5d3c6f Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Mon, 13 Dec 2021 19:17:17 +0100 Subject: [PATCH 05/20] bareudp: Add extack support to bareudp_configure() Add missing extacks for common configuration errors. Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- drivers/net/bareudp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index f803303613995..ba587e5fc24fc 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -609,7 +609,8 @@ static struct bareudp_dev *bareudp_find_dev(struct bareudp_net *bn, } static int bareudp_configure(struct net *net, struct net_device *dev, - struct bareudp_conf *conf) + struct bareudp_conf *conf, + struct netlink_ext_ack *extack) { struct bareudp_net *bn = net_generic(net, bareudp_net_id); struct bareudp_dev *t, *bareudp = netdev_priv(dev); @@ -618,13 +619,17 @@ static int bareudp_configure(struct net *net, struct net_device *dev, bareudp->net = net; bareudp->dev = dev; t = bareudp_find_dev(bn, conf); - if (t) + if (t) { + NL_SET_ERR_MSG(extack, "Another bareudp device using the same port already exists"); return -EBUSY; + } if (conf->multi_proto_mode && (conf->ethertype != htons(ETH_P_MPLS_UC) && - conf->ethertype != htons(ETH_P_IP))) + conf->ethertype != htons(ETH_P_IP))) { + NL_SET_ERR_MSG(extack, "Cannot set multiproto mode for this ethertype (only IPv4 and unicast MPLS are supported)"); return -EINVAL; + } bareudp->port = conf->port; bareudp->ethertype = conf->ethertype; @@ -671,7 +676,7 @@ static int bareudp_newlink(struct net *net, struct net_device *dev, if (err) return err; - err = bareudp_configure(net, dev, &conf); + err = bareudp_configure(net, dev, &conf, extack); if (err) return err; From e2f01bfe1406f82a45ab0ce8ed90dbef1c464502 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Dec 2021 03:45:34 +0200 Subject: [PATCH 06/20] net: dsa: tag_sja1105: fix zeroization of ds->priv on tag proto disconnect The method was meant to zeroize ds->tagger_data but got the wrong pointer. Fix this. Fixes: c79e84866d2a ("net: dsa: tag_sja1105: convert to tagger-owned data") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/tag_sja1105.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 93d2484b2480e..b7095a033fc44 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -756,7 +756,7 @@ static void sja1105_disconnect(struct dsa_switch_tree *dst) kthread_destroy_worker(priv->xmit_worker); kfree(priv); - dp->ds->priv = NULL; + dp->ds->tagger_data = NULL; } } From c8a2a011cd04054a6577d8cf774adf9e09302876 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Dec 2021 03:45:35 +0200 Subject: [PATCH 07/20] net: dsa: sja1105: fix broken connection with the sja1110 tagger The driver was incorrectly converted assuming that "sja1105" is the only tagger supported by this driver. This results in SJA1110 switches failing to probe: sja1105 spi1.0: Unable to connect to tag protocol "sja1110": -EPROTONOSUPPORT sja1105: probe of spi1.2 failed with error -93 Add DSA_TAG_PROTO_SJA1110 to the list of supported taggers by the sja1105 driver. The sja1105_tagger_data structure format is common for the two tagging protocols. Fixes: c79e84866d2a ("net: dsa: tag_sja1105: convert to tagger-owned data") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_main.c | 16 ++++++++-------- include/linux/dsa/sja1105.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 9171fbea588c3..b513713be6101 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2708,17 +2708,17 @@ static void sja1105_port_deferred_xmit(struct kthread_work *work) static int sja1105_connect_tag_protocol(struct dsa_switch *ds, enum dsa_tag_protocol proto) { + struct sja1105_private *priv = ds->priv; struct sja1105_tagger_data *tagger_data; - switch (proto) { - case DSA_TAG_PROTO_SJA1105: - tagger_data = sja1105_tagger_data(ds); - tagger_data->xmit_work_fn = sja1105_port_deferred_xmit; - tagger_data->meta_tstamp_handler = sja1110_process_meta_tstamp; - return 0; - default: + if (proto != priv->info->tag_proto) return -EPROTONOSUPPORT; - } + + tagger_data = sja1105_tagger_data(ds); + tagger_data->xmit_work_fn = sja1105_port_deferred_xmit; + tagger_data->meta_tstamp_handler = sja1110_process_meta_tstamp; + + return 0; } /* The MAXAGE setting belongs to the L2 Forwarding Parameters table, diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index e9cb1ae6d742a..159e43171cccf 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -70,7 +70,8 @@ struct sja1105_skb_cb { static inline struct sja1105_tagger_data * sja1105_tagger_data(struct dsa_switch *ds) { - BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_SJA1105); + BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_SJA1105 && + ds->dst->tag_ops->proto != DSA_TAG_PROTO_SJA1110); return ds->tagger_data; } From 7f2973149c22e7a6fee4c0c9fa6b8e4108e9c208 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Dec 2021 03:45:36 +0200 Subject: [PATCH 08/20] net: dsa: make tagging protocols connect to individual switches from a tree On the NXP Bluebox 3 board which uses a multi-switch setup with sja1105, the mechanism through which the tagger connects to the switch tree is broken, due to improper DSA code design. At the time when tag_ops->connect() is called in dsa_port_parse_cpu(), DSA hasn't finished "touching" all the ports, so it doesn't know how large the tree is and how many ports it has. It has just seen the first CPU port by this time. As a result, this function will call the tagger's ->connect method too early, and the tagger will connect only to the first switch from the tree. This could be perhaps addressed a bit more simply by just moving the tag_ops->connect(dst) call a bit later (for example in dsa_tree_setup), but there is already a design inconsistency at present: on the switch side, the notification is on a per-switch basis, but on the tagger side, it is on a per-tree basis. Furthermore, the persistent storage itself is per switch (ds->tagger_data). And the tagger connect and disconnect procedures (at least the ones that exist currently) could see a fair bit of simplification if they didn't have to iterate through the switches of a tree. To fix the issue, this change transforms tag_ops->connect(dst) into tag_ops->connect(ds) and moves it somewhere where we already iterate over all switches of a tree. That is in dsa_switch_setup_tag_protocol(), which is a good placement because we already have there the connection call to the switch side of things. As for the dsa_tree_bind_tag_proto() method (called from the code path that changes the tag protocol), things are a bit more complicated because we receive the tree as argument, yet when we unwind on errors, it would be nice to not call tag_ops->disconnect(ds) where we didn't previously call tag_ops->connect(ds). We didn't have this problem before because the tag_ops connection operations passed the entire dst before, and this is more fine grained now. To solve the error rewind case using the new API, we have to create yet one more cross-chip notifier for disconnection, and stay connected with the old tag protocol to all the switches in the tree until we've succeeded to connect with the new one as well. So if something fails half way, the whole tree is still connected to the old tagger. But there may still be leaks if the tagger fails to connect to the 2nd out of 3 switches in a tree: somebody needs to tell the tagger to disconnect from the first switch. Nothing comes for free, and this was previously handled privately by the tagging protocol driver before, but now we need to emit a disconnect cross-chip notifier for that, because DSA has to take care of the unwind path. We assume that the tagging protocol has connected to a switch if it has set ds->tagger_data to something, otherwise we avoid calling its disconnection method in the error rewind path. The rest of the changes are in the tagging protocol drivers, and have to do with the replacement of dst with ds. The iteration is removed and the error unwind path is simplified, as mentioned above. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- include/net/dsa.h | 5 ++- net/dsa/dsa2.c | 44 ++++++++++--------------- net/dsa/dsa_priv.h | 1 + net/dsa/switch.c | 52 +++++++++++++++++++++++++++-- net/dsa/tag_ocelot_8021q.c | 53 +++++++++--------------------- net/dsa/tag_sja1105.c | 67 +++++++++++++------------------------- 6 files changed, 109 insertions(+), 113 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 64d71968aa91a..f16959444ae12 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -82,15 +82,14 @@ enum dsa_tag_protocol { }; struct dsa_switch; -struct dsa_switch_tree; struct dsa_device_ops { struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev); void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, int *offset); - int (*connect)(struct dsa_switch_tree *dst); - void (*disconnect)(struct dsa_switch_tree *dst); + int (*connect)(struct dsa_switch *ds); + void (*disconnect)(struct dsa_switch *ds); unsigned int needed_headroom; unsigned int needed_tailroom; const char *name; diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index cf65661686209..c18b22c0bf55e 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -248,12 +248,8 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) static void dsa_tree_free(struct dsa_switch_tree *dst) { - if (dst->tag_ops) { - if (dst->tag_ops->disconnect) - dst->tag_ops->disconnect(dst); - + if (dst->tag_ops) dsa_tag_driver_put(dst->tag_ops); - } list_del(&dst->list); kfree(dst); } @@ -841,17 +837,29 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) } connect: + if (tag_ops->connect) { + err = tag_ops->connect(ds); + if (err) + return err; + } + if (ds->ops->connect_tag_protocol) { err = ds->ops->connect_tag_protocol(ds, tag_ops->proto); if (err) { dev_err(ds->dev, "Unable to connect to tag protocol \"%s\": %pe\n", tag_ops->name, ERR_PTR(err)); - return err; + goto disconnect; } } return 0; + +disconnect: + if (tag_ops->disconnect) + tag_ops->disconnect(ds); + + return err; } static int dsa_switch_setup(struct dsa_switch *ds) @@ -1160,13 +1168,6 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, dst->tag_ops = tag_ops; - /* Notify the new tagger about the connection to this tree */ - if (tag_ops->connect) { - err = tag_ops->connect(dst); - if (err) - goto out_revert; - } - /* Notify the switches from this tree about the connection * to the new tagger */ @@ -1176,16 +1177,14 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, goto out_disconnect; /* Notify the old tagger about the disconnection from this tree */ - if (old_tag_ops->disconnect) - old_tag_ops->disconnect(dst); + info.tag_ops = old_tag_ops; + dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_DISCONNECT, &info); return 0; out_disconnect: - /* Revert the new tagger's connection to this tree */ - if (tag_ops->disconnect) - tag_ops->disconnect(dst); -out_revert: + info.tag_ops = tag_ops; + dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_DISCONNECT, &info); dst->tag_ops = old_tag_ops; return err; @@ -1318,7 +1317,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, struct dsa_switch_tree *dst = ds->dst; const struct dsa_device_ops *tag_ops; enum dsa_tag_protocol default_proto; - int err; /* Find out which protocol the switch would prefer. */ default_proto = dsa_get_tag_protocol(dp, master); @@ -1366,12 +1364,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, */ dsa_tag_driver_put(tag_ops); } else { - if (tag_ops->connect) { - err = tag_ops->connect(dst); - if (err) - return err; - } - dst->tag_ops = tag_ops; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 0db2b26b0c83c..edfaae7b59672 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -38,6 +38,7 @@ enum { DSA_NOTIFIER_MTU, DSA_NOTIFIER_TAG_PROTO, DSA_NOTIFIER_TAG_PROTO_CONNECT, + DSA_NOTIFIER_TAG_PROTO_DISCONNECT, DSA_NOTIFIER_MRP_ADD, DSA_NOTIFIER_MRP_DEL, DSA_NOTIFIER_MRP_ADD_RING_ROLE, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 06948f5368296..393f2d8a860a9 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -647,15 +647,58 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds, return 0; } -static int dsa_switch_connect_tag_proto(struct dsa_switch *ds, - struct dsa_notifier_tag_proto_info *info) +/* We use the same cross-chip notifiers to inform both the tagger side, as well + * as the switch side, of connection and disconnection events. + * Since ds->tagger_data is owned by the tagger, it isn't a hard error if the + * switch side doesn't support connecting to this tagger, and therefore, the + * fact that we don't disconnect the tagger side doesn't constitute a memory + * leak: the tagger will still operate with persistent per-switch memory, just + * with the switch side unconnected to it. What does constitute a hard error is + * when the switch side supports connecting but fails. + */ +static int +dsa_switch_connect_tag_proto(struct dsa_switch *ds, + struct dsa_notifier_tag_proto_info *info) { const struct dsa_device_ops *tag_ops = info->tag_ops; + int err; + + /* Notify the new tagger about the connection to this switch */ + if (tag_ops->connect) { + err = tag_ops->connect(ds); + if (err) + return err; + } if (!ds->ops->connect_tag_protocol) return -EOPNOTSUPP; - return ds->ops->connect_tag_protocol(ds, tag_ops->proto); + /* Notify the switch about the connection to the new tagger */ + err = ds->ops->connect_tag_protocol(ds, tag_ops->proto); + if (err) { + /* Revert the new tagger's connection to this tree */ + if (tag_ops->disconnect) + tag_ops->disconnect(ds); + return err; + } + + return 0; +} + +static int +dsa_switch_disconnect_tag_proto(struct dsa_switch *ds, + struct dsa_notifier_tag_proto_info *info) +{ + const struct dsa_device_ops *tag_ops = info->tag_ops; + + /* Notify the tagger about the disconnection from this switch */ + if (tag_ops->disconnect && ds->tagger_data) + tag_ops->disconnect(ds); + + /* No need to notify the switch, since it shouldn't have any + * resources to tear down + */ + return 0; } static int dsa_switch_mrp_add(struct dsa_switch *ds, @@ -780,6 +823,9 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_TAG_PROTO_CONNECT: err = dsa_switch_connect_tag_proto(ds, info); break; + case DSA_NOTIFIER_TAG_PROTO_DISCONNECT: + err = dsa_switch_disconnect_tag_proto(ds, info); + break; case DSA_NOTIFIER_MRP_ADD: err = dsa_switch_mrp_add(ds, info); break; diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index fe451f4de7ba8..68982b2789a59 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -81,55 +81,34 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, return skb; } -static void ocelot_disconnect(struct dsa_switch_tree *dst) +static void ocelot_disconnect(struct dsa_switch *ds) { - struct ocelot_8021q_tagger_private *priv; - struct dsa_port *dp; - - list_for_each_entry(dp, &dst->ports, list) { - priv = dp->ds->tagger_data; - - if (!priv) - continue; + struct ocelot_8021q_tagger_private *priv = ds->tagger_data; - if (priv->xmit_worker) - kthread_destroy_worker(priv->xmit_worker); - - kfree(priv); - dp->ds->tagger_data = NULL; - } + kthread_destroy_worker(priv->xmit_worker); + kfree(priv); + ds->tagger_data = NULL; } -static int ocelot_connect(struct dsa_switch_tree *dst) +static int ocelot_connect(struct dsa_switch *ds) { struct ocelot_8021q_tagger_private *priv; - struct dsa_port *dp; int err; - list_for_each_entry(dp, &dst->ports, list) { - if (dp->ds->tagger_data) - continue; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - err = -ENOMEM; - goto out; - } - - priv->xmit_worker = kthread_create_worker(0, "felix_xmit"); - if (IS_ERR(priv->xmit_worker)) { - err = PTR_ERR(priv->xmit_worker); - goto out; - } - - dp->ds->tagger_data = priv; + priv->xmit_worker = kthread_create_worker(0, "felix_xmit"); + if (IS_ERR(priv->xmit_worker)) { + err = PTR_ERR(priv->xmit_worker); + kfree(priv); + return err; } - return 0; + ds->tagger_data = priv; -out: - ocelot_disconnect(dst); - return err; + return 0; } static const struct dsa_device_ops ocelot_8021q_netdev_ops = { diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index b7095a033fc44..72d5e0ef8dcfe 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -741,65 +741,44 @@ static void sja1110_flow_dissect(const struct sk_buff *skb, __be16 *proto, *proto = ((__be16 *)skb->data)[(VLAN_HLEN / 2) - 1]; } -static void sja1105_disconnect(struct dsa_switch_tree *dst) +static void sja1105_disconnect(struct dsa_switch *ds) { - struct sja1105_tagger_private *priv; - struct dsa_port *dp; - - list_for_each_entry(dp, &dst->ports, list) { - priv = dp->ds->tagger_data; - - if (!priv) - continue; + struct sja1105_tagger_private *priv = ds->tagger_data; - if (priv->xmit_worker) - kthread_destroy_worker(priv->xmit_worker); - - kfree(priv); - dp->ds->tagger_data = NULL; - } + kthread_destroy_worker(priv->xmit_worker); + kfree(priv); + ds->tagger_data = NULL; } -static int sja1105_connect(struct dsa_switch_tree *dst) +static int sja1105_connect(struct dsa_switch *ds) { struct sja1105_tagger_data *tagger_data; struct sja1105_tagger_private *priv; struct kthread_worker *xmit_worker; - struct dsa_port *dp; int err; - list_for_each_entry(dp, &dst->ports, list) { - if (dp->ds->tagger_data) - continue; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - err = -ENOMEM; - goto out; - } - - spin_lock_init(&priv->meta_lock); - - xmit_worker = kthread_create_worker(0, "dsa%d:%d_xmit", - dst->index, dp->ds->index); - if (IS_ERR(xmit_worker)) { - err = PTR_ERR(xmit_worker); - goto out; - } + spin_lock_init(&priv->meta_lock); - priv->xmit_worker = xmit_worker; - /* Export functions for switch driver use */ - tagger_data = &priv->data; - tagger_data->rxtstamp_get_state = sja1105_rxtstamp_get_state; - tagger_data->rxtstamp_set_state = sja1105_rxtstamp_set_state; - dp->ds->tagger_data = priv; + xmit_worker = kthread_create_worker(0, "dsa%d:%d_xmit", + ds->dst->index, ds->index); + if (IS_ERR(xmit_worker)) { + err = PTR_ERR(xmit_worker); + kfree(priv); + return err; } - return 0; + priv->xmit_worker = xmit_worker; + /* Export functions for switch driver use */ + tagger_data = &priv->data; + tagger_data->rxtstamp_get_state = sja1105_rxtstamp_get_state; + tagger_data->rxtstamp_set_state = sja1105_rxtstamp_set_state; + ds->tagger_data = priv; -out: - sja1105_disconnect(dst); - return err; + return 0; } static const struct dsa_device_ops sja1105_netdev_ops = { From 13510fef48a3803d9ee8f044b015dacfb06fe0f5 Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Tue, 14 Dec 2021 11:44:47 +0000 Subject: [PATCH 09/20] pktgen: use min() to make code cleaner Use min() in order to make code cleaner. Issue found by coccinelle. Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Reviewed-by: Muchun Song Signed-off-by: David S. Miller --- net/core/pktgen.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 560a5e712dc32..239effb42b617 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2778,8 +2778,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } i = 0; - frag_len = (datalen/frags) < PAGE_SIZE ? - (datalen/frags) : PAGE_SIZE; + frag_len = min(datalen / frags, PAGE_SIZE); while (datalen > 0) { if (unlikely(!pkt_dev->page)) { int node = numa_node_id(); @@ -2796,7 +2795,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, /*last fragment, fill rest of data*/ if (i == (frags - 1)) skb_frag_size_set(&skb_shinfo(skb)->frags[i], - (datalen < PAGE_SIZE ? datalen : PAGE_SIZE)); + min(datalen, PAGE_SIZE)); else skb_frag_size_set(&skb_shinfo(skb)->frags[i], frag_len); datalen -= skb_frag_size(&skb_shinfo(skb)->frags[i]); From dc91e3be837ced738d04a4dc8aefc338e8f79235 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Dec 2021 12:53:41 +0000 Subject: [PATCH 10/20] Revert "pktgen: use min() to make code cleaner" This reverts commit 13510fef48a3803d9ee8f044b015dacfb06fe0f5. Causes build warnings. Signed-off-by: David S. Miller --- net/core/pktgen.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 239effb42b617..560a5e712dc32 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2778,7 +2778,8 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } i = 0; - frag_len = min(datalen / frags, PAGE_SIZE); + frag_len = (datalen/frags) < PAGE_SIZE ? + (datalen/frags) : PAGE_SIZE; while (datalen > 0) { if (unlikely(!pkt_dev->page)) { int node = numa_node_id(); @@ -2795,7 +2796,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, /*last fragment, fill rest of data*/ if (i == (frags - 1)) skb_frag_size_set(&skb_shinfo(skb)->frags[i], - min(datalen, PAGE_SIZE)); + (datalen < PAGE_SIZE ? datalen : PAGE_SIZE)); else skb_frag_size_set(&skb_shinfo(skb)->frags[i], frag_len); datalen -= skb_frag_size(&skb_shinfo(skb)->frags[i]); From b6ee566cf3940883d67c0d142fae8d410e975f47 Mon Sep 17 00:00:00 2001 From: Dany Madden Date: Tue, 14 Dec 2021 00:17:47 -0500 Subject: [PATCH 11/20] ibmvnic: Update driver return codes Update return codes to be more informative. Signed-off-by: Jacob Root Signed-off-by: Dany Madden Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 64 ++++++++++++++++-------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 4ba4c4f3be4f7..59536bd5cab1b 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -308,7 +308,7 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, if (adapter->fw_done_rc) { dev_err(dev, "Couldn't map LTB, rc = %d\n", adapter->fw_done_rc); - rc = -1; + rc = -EIO; goto out; } rc = 0; @@ -540,13 +540,15 @@ static int init_stats_token(struct ibmvnic_adapter *adapter) { struct device *dev = &adapter->vdev->dev; dma_addr_t stok; + int rc; stok = dma_map_single(dev, &adapter->stats, sizeof(struct ibmvnic_statistics), DMA_FROM_DEVICE); - if (dma_mapping_error(dev, stok)) { - dev_err(dev, "Couldn't map stats buffer\n"); - return -1; + rc = dma_mapping_error(dev, stok); + if (rc) { + dev_err(dev, "Couldn't map stats buffer, rc = %d\n", rc); + return rc; } adapter->stats_token = stok; @@ -655,7 +657,7 @@ static int init_rx_pools(struct net_device *netdev) u64 num_pools; u64 pool_size; /* # of buffers in one pool */ u64 buff_size; - int i, j; + int i, j, rc; pool_size = adapter->req_rx_add_entries_per_subcrq; num_pools = adapter->req_rx_queues; @@ -674,7 +676,7 @@ static int init_rx_pools(struct net_device *netdev) GFP_KERNEL); if (!adapter->rx_pool) { dev_err(dev, "Failed to allocate rx pools\n"); - return -1; + return -ENOMEM; } /* Set num_active_rx_pools early. If we fail below after partial @@ -697,6 +699,7 @@ static int init_rx_pools(struct net_device *netdev) GFP_KERNEL); if (!rx_pool->free_map) { dev_err(dev, "Couldn't alloc free_map %d\n", i); + rc = -ENOMEM; goto out_release; } @@ -705,6 +708,7 @@ static int init_rx_pools(struct net_device *netdev) GFP_KERNEL); if (!rx_pool->rx_buff) { dev_err(dev, "Couldn't alloc rx buffers\n"); + rc = -ENOMEM; goto out_release; } } @@ -718,8 +722,9 @@ static int init_rx_pools(struct net_device *netdev) dev_dbg(dev, "Updating LTB for rx pool %d [%d, %d]\n", i, rx_pool->size, rx_pool->buff_size); - if (alloc_long_term_buff(adapter, &rx_pool->long_term_buff, - rx_pool->size * rx_pool->buff_size)) + rc = alloc_long_term_buff(adapter, &rx_pool->long_term_buff, + rx_pool->size * rx_pool->buff_size); + if (rc) goto out; for (j = 0; j < rx_pool->size; ++j) { @@ -756,7 +761,7 @@ static int init_rx_pools(struct net_device *netdev) /* We failed to allocate one or more LTBs or map them on the VIOS. * Hold onto the pools and any LTBs that we did allocate/map. */ - return -1; + return rc; } static void release_vpd_data(struct ibmvnic_adapter *adapter) @@ -817,13 +822,13 @@ static int init_one_tx_pool(struct net_device *netdev, sizeof(struct ibmvnic_tx_buff), GFP_KERNEL); if (!tx_pool->tx_buff) - return -1; + return -ENOMEM; tx_pool->free_map = kcalloc(pool_size, sizeof(int), GFP_KERNEL); if (!tx_pool->free_map) { kfree(tx_pool->tx_buff); tx_pool->tx_buff = NULL; - return -1; + return -ENOMEM; } for (i = 0; i < pool_size; i++) @@ -914,7 +919,7 @@ static int init_tx_pools(struct net_device *netdev) adapter->tx_pool = kcalloc(num_pools, sizeof(struct ibmvnic_tx_pool), GFP_KERNEL); if (!adapter->tx_pool) - return -1; + return -ENOMEM; adapter->tso_pool = kcalloc(num_pools, sizeof(struct ibmvnic_tx_pool), GFP_KERNEL); @@ -924,7 +929,7 @@ static int init_tx_pools(struct net_device *netdev) if (!adapter->tso_pool) { kfree(adapter->tx_pool); adapter->tx_pool = NULL; - return -1; + return -ENOMEM; } /* Set num_active_tx_pools early. If we fail below after partial @@ -1113,7 +1118,7 @@ static int ibmvnic_login(struct net_device *netdev) retry = false; if (retry_count > retries) { netdev_warn(netdev, "Login attempts exceeded\n"); - return -1; + return -EACCES; } adapter->init_done_rc = 0; @@ -1154,25 +1159,26 @@ static int ibmvnic_login(struct net_device *netdev) timeout)) { netdev_warn(netdev, "Capabilities query timed out\n"); - return -1; + return -ETIMEDOUT; } rc = init_sub_crqs(adapter); if (rc) { netdev_warn(netdev, "SCRQ initialization failed\n"); - return -1; + return rc; } rc = init_sub_crq_irqs(adapter); if (rc) { netdev_warn(netdev, "SCRQ irq initialization failed\n"); - return -1; + return rc; } } else if (adapter->init_done_rc) { - netdev_warn(netdev, "Adapter login failed\n"); - return -1; + netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n", + adapter->init_done_rc); + return -EIO; } } while (retry); @@ -1231,7 +1237,7 @@ static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state) if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { netdev_err(netdev, "timeout setting link state\n"); - return -1; + return -ETIMEDOUT; } if (adapter->init_done_rc == PARTIALSUCCESS) { @@ -2288,7 +2294,7 @@ static int do_reset(struct ibmvnic_adapter *adapter, /* If someone else changed the adapter state * when we dropped the rtnl, fail the reset */ - rc = -1; + rc = -EAGAIN; goto out; } adapter->state = VNIC_CLOSED; @@ -2330,10 +2336,8 @@ static int do_reset(struct ibmvnic_adapter *adapter, } rc = ibmvnic_reset_init(adapter, true); - if (rc) { - rc = IBMVNIC_INIT_FAILED; + if (rc) goto out; - } /* If the adapter was in PROBE or DOWN state prior to the reset, * exit here. @@ -3763,7 +3767,7 @@ static int init_sub_crqs(struct ibmvnic_adapter *adapter) allqueues = kcalloc(total_queues, sizeof(*allqueues), GFP_KERNEL); if (!allqueues) - return -1; + return -ENOMEM; for (i = 0; i < total_queues; i++) { allqueues[i] = init_sub_crq_queue(adapter); @@ -3832,7 +3836,7 @@ static int init_sub_crqs(struct ibmvnic_adapter *adapter) for (i = 0; i < registered_queues; i++) release_sub_crq_queue(adapter, allqueues[i], 1); kfree(allqueues); - return -1; + return -ENOMEM; } static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) @@ -4191,7 +4195,7 @@ static int send_login(struct ibmvnic_adapter *adapter) if (!adapter->tx_scrq || !adapter->rx_scrq) { netdev_err(adapter->netdev, "RX or TX queues are not allocated, device login failed\n"); - return -1; + return -ENOMEM; } release_login_buffer(adapter); @@ -4311,7 +4315,7 @@ static int send_login(struct ibmvnic_adapter *adapter) kfree(login_buffer); adapter->login_buf = NULL; buf_alloc_failed: - return -1; + return -ENOMEM; } static int send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr, @@ -5632,7 +5636,7 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset) if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { dev_err(dev, "Initialization sequence timed out\n"); - return -1; + return -ETIMEDOUT; } if (adapter->init_done_rc) { @@ -5643,7 +5647,7 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset) if (adapter->from_passive_init) { adapter->state = VNIC_OPEN; adapter->from_passive_init = false; - return -1; + return -EINVAL; } if (reset && From fe4c82a7e0f06abdf5a6978aa00457b63bd46680 Mon Sep 17 00:00:00 2001 From: Dany Madden Date: Tue, 14 Dec 2021 00:17:48 -0500 Subject: [PATCH 12/20] ibmvnic: remove unused defines IBMVNIC_STATS_TIMEOUT and IBMVNIC_INIT_FAILED are not used in the driver. Remove them. Suggested-by: Sukadev Bhattiprolu Signed-off-by: Dany Madden Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index b8e42f67d897e..4a8f36e0ab076 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -18,8 +18,6 @@ #define IBMVNIC_NAME "ibmvnic" #define IBMVNIC_DRIVER_VERSION "1.0.1" #define IBMVNIC_INVALID_MAP -1 -#define IBMVNIC_STATS_TIMEOUT 1 -#define IBMVNIC_INIT_FAILED 2 #define IBMVNIC_OPEN_FAILED 3 /* basic structures plus 100 2k buffers */ From 8b40a9d53d4f1705899be0a1518368d770ea95cc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 13 Dec 2021 18:58:06 -0800 Subject: [PATCH 13/20] ipv6: use GFP_ATOMIC in rt6_probe() syzbot reminded me that rt6_probe() can run from atomic contexts. stack backtrace: CPU: 1 PID: 7461 Comm: syz-executor.2 Not tainted 5.16.0-rc4-next-20211210-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 print_usage_bug kernel/locking/lockdep.c:203 [inline] valid_state kernel/locking/lockdep.c:3945 [inline] mark_lock_irq kernel/locking/lockdep.c:4148 [inline] mark_lock.cold+0x61/0x8e kernel/locking/lockdep.c:4605 mark_usage kernel/locking/lockdep.c:4500 [inline] __lock_acquire+0x11d5/0x54a0 kernel/locking/lockdep.c:4981 lock_acquire kernel/locking/lockdep.c:5639 [inline] lock_acquire+0x1ab/0x510 kernel/locking/lockdep.c:5604 __fs_reclaim_acquire mm/page_alloc.c:4550 [inline] fs_reclaim_acquire+0x115/0x160 mm/page_alloc.c:4564 might_alloc include/linux/sched/mm.h:253 [inline] slab_pre_alloc_hook mm/slab.h:739 [inline] slab_alloc_node mm/slub.c:3145 [inline] slab_alloc mm/slub.c:3239 [inline] kmem_cache_alloc_trace+0x3b/0x2c0 mm/slub.c:3256 kmalloc include/linux/slab.h:581 [inline] kzalloc include/linux/slab.h:715 [inline] ref_tracker_alloc+0xe1/0x430 lib/ref_tracker.c:74 netdev_tracker_alloc include/linux/netdevice.h:3860 [inline] dev_hold_track include/linux/netdevice.h:3877 [inline] rt6_probe net/ipv6/route.c:661 [inline] find_match.part.0+0xac9/0xd00 net/ipv6/route.c:752 find_match net/ipv6/route.c:825 [inline] __find_rr_leaf+0x17f/0xd20 net/ipv6/route.c:826 find_rr_leaf net/ipv6/route.c:847 [inline] rt6_select net/ipv6/route.c:891 [inline] fib6_table_lookup+0x649/0xa20 net/ipv6/route.c:2185 ip6_pol_route+0x1c5/0x11e0 net/ipv6/route.c:2221 pol_lookup_func include/net/ip6_fib.h:580 [inline] fib6_rule_lookup+0x52a/0x6f0 net/ipv6/fib6_rules.c:120 ip6_route_output_flags_noref+0x2e2/0x380 net/ipv6/route.c:2629 ip6_route_output_flags+0x72/0x320 net/ipv6/route.c:2642 ip6_route_output include/net/ip6_route.h:98 [inline] ip6_dst_lookup_tail+0x5ab/0x1620 net/ipv6/ip6_output.c:1070 ip6_dst_lookup_flow+0x8c/0x1d0 net/ipv6/ip6_output.c:1200 geneve_get_v6_dst+0x46f/0x9a0 drivers/net/geneve.c:858 geneve6_xmit_skb drivers/net/geneve.c:991 [inline] geneve_xmit+0x520/0x3530 drivers/net/geneve.c:1074 __netdev_start_xmit include/linux/netdevice.h:4685 [inline] netdev_start_xmit include/linux/netdevice.h:4699 [inline] xmit_one net/core/dev.c:3473 [inline] dev_hard_start_xmit+0x1eb/0x920 net/core/dev.c:3489 __dev_queue_xmit+0x2983/0x3640 net/core/dev.c:4112 neigh_resolve_output net/core/neighbour.c:1522 [inline] neigh_resolve_output+0x50e/0x820 net/core/neighbour.c:1502 neigh_output include/net/neighbour.h:541 [inline] ip6_finish_output2+0x56e/0x14f0 net/ipv6/ip6_output.c:126 __ip6_finish_output net/ipv6/ip6_output.c:191 [inline] __ip6_finish_output+0x61e/0xe80 net/ipv6/ip6_output.c:170 ip6_finish_output+0x32/0x200 net/ipv6/ip6_output.c:201 NF_HOOK_COND include/linux/netfilter.h:296 [inline] ip6_output+0x1e4/0x530 net/ipv6/ip6_output.c:224 dst_output include/net/dst.h:451 [inline] NF_HOOK include/linux/netfilter.h:307 [inline] ndisc_send_skb+0xa99/0x17f0 net/ipv6/ndisc.c:508 ndisc_send_rs+0x12e/0x6f0 net/ipv6/ndisc.c:702 addrconf_rs_timer+0x3f2/0x820 net/ipv6/addrconf.c:3898 call_timer_fn+0x1a5/0x6b0 kernel/time/timer.c:1421 expire_timers kernel/time/timer.c:1466 [inline] __run_timers.part.0+0x675/0xa20 kernel/time/timer.c:1734 __run_timers kernel/time/timer.c:1715 [inline] run_timer_softirq+0xb3/0x1d0 kernel/time/timer.c:1747 __do_softirq+0x29b/0x9c2 kernel/softirq.c:558 invoke_softirq kernel/softirq.c:432 [inline] __irq_exit_rcu+0x123/0x180 kernel/softirq.c:637 irq_exit_rcu+0x5/0x20 kernel/softirq.c:649 sysvec_apic_timer_interrupt+0x93/0xc0 arch/x86/kernel/apic/apic.c:1097 Fixes: fb67510ba9bd ("ipv6: add net device refcount tracker to rt6_probe_deferred()") Signed-off-by: Eric Dumazet Reported-by: syzbot Link: https://lore.kernel.org/r/20211214025806.3456382-1-eric.dumazet@gmail.com Signed-off-by: Jakub Kicinski --- net/ipv6/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4d02a329ab600..03be0e6b48265 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -658,7 +658,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) } else { INIT_WORK(&work->work, rt6_probe_deferred); work->target = *nh_gw; - dev_hold_track(dev, &work->dev_tracker, GFP_KERNEL); + dev_hold_track(dev, &work->dev_tracker, GFP_ATOMIC); work->dev = dev; schedule_work(&work->work); } From 1d2f3d3c62684b793339d0ae841ac67b555d8c8d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 13 Dec 2021 20:32:08 -0800 Subject: [PATCH 14/20] mptcp: adjust to use netns refcount tracker MPTCP can change sk_net_refcnt after sock_create_kern() call. We need to change its corresponding get_net() to avoid a splat at release time, as in : refcount_t: decrement hit 0; leaking memory. WARNING: CPU: 0 PID: 3599 at lib/refcount.c:31 refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 Modules linked in: CPU: 1 PID: 3599 Comm: syz-fuzzer Not tainted 5.16.0-rc4-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 Code: 1d b1 99 a1 09 31 ff 89 de e8 5d 3a 9c fd 84 db 75 e0 e8 74 36 9c fd 48 c7 c7 60 00 05 8a c6 05 91 99 a1 09 01 e8 cc 4b 27 05 <0f> 0b eb c4 e8 58 36 9c fd 0f b6 1d 80 99 a1 09 31 ff 89 de e8 28 RSP: 0018:ffffc90001f5fab0 EFLAGS: 00010286 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff888021873a00 RSI: ffffffff815f1e28 RDI: fffff520003ebf48 RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 R10: ffffffff815ebbce R11: 0000000000000000 R12: 1ffff920003ebf5b R13: 00000000ffffffef R14: ffffffff8d2fcd94 R15: ffffc90001f5fd10 FS: 000000c00008a090(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f0a5b59e300 CR3: 000000001cbe6000 CR4: 00000000003506e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __refcount_dec include/linux/refcount.h:344 [inline] refcount_dec include/linux/refcount.h:359 [inline] ref_tracker_free+0x4fe/0x610 lib/ref_tracker.c:101 netns_tracker_free include/net/net_namespace.h:327 [inline] put_net_track include/net/net_namespace.h:341 [inline] __sk_destruct+0x4a6/0x920 net/core/sock.c:2042 sk_destruct+0xbd/0xe0 net/core/sock.c:2058 __sk_free+0xef/0x3d0 net/core/sock.c:2069 sk_free+0x78/0xa0 net/core/sock.c:2080 sock_put include/net/sock.h:1911 [inline] __mptcp_close_ssk+0x435/0x590 net/mptcp/protocol.c:2276 __mptcp_destroy_sock+0x35f/0x830 net/mptcp/protocol.c:2702 mptcp_close+0x5f8/0x7f0 net/mptcp/protocol.c:2750 inet_release+0x12e/0x280 net/ipv4/af_inet.c:428 inet6_release+0x4c/0x70 net/ipv6/af_inet6.c:476 __sock_release+0xcd/0x280 net/socket.c:649 sock_close+0x18/0x20 net/socket.c:1314 __fput+0x286/0x9f0 fs/file_table.c:280 task_work_run+0xdd/0x1a0 kernel/task_work.c:164 tracehook_notify_resume include/linux/tracehook.h:189 [inline] exit_to_user_mode_loop kernel/entry/common.c:175 [inline] exit_to_user_mode_prepare+0x27e/0x290 kernel/entry/common.c:207 __syscall_exit_to_user_mode_work kernel/entry/common.c:289 [inline] syscall_exit_to_user_mode+0x19/0x60 kernel/entry/common.c:300 do_syscall_64+0x42/0xb0 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x44/0xae Fixes: ffa84b5ffb37 ("net: add netns refcount tracker to struct sock") Signed-off-by: Eric Dumazet Reported-by: syzbot Cc: Mat Martineau Cc: Florian Westphal Acked-by: Paolo Abeni Reviewed-by: Matthieu Baerts Link: https://lore.kernel.org/r/20211214043208.3543046-1-eric.dumazet@gmail.com Signed-off-by: Jakub Kicinski --- net/mptcp/subflow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index b8dd3441f7d00..24bc9d5e87be4 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1534,7 +1534,7 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock) * needs it. */ sf->sk->sk_net_refcnt = 1; - get_net(net); + get_net_track(net, &sf->sk->ns_tracker, GFP_KERNEL); sock_inuse_add(net, 1); err = tcp_set_ulp(sf->sk, "mptcp"); release_sock(sf->sk); From 123e495ecc25d32cf3e7958f794013236abdf0d4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 13 Dec 2021 21:19:55 -0800 Subject: [PATCH 15/20] net: linkwatch: be more careful about dev->linkwatch_dev_tracker Apparently a concurrent linkwatch_add_event() could run while we are in __linkwatch_run_queue(). We need to free dev->linkwatch_dev_tracker tracker under lweventlist_lock protection to avoid this race. syzbot report: [ 77.935949][ T3661] reference already released. [ 77.941015][ T3661] allocated in: [ 77.944482][ T3661] linkwatch_fire_event+0x202/0x260 [ 77.950318][ T3661] netif_carrier_on+0x9c/0x100 [ 77.955120][ T3661] __ieee80211_sta_join_ibss+0xc52/0x1590 [ 77.960888][ T3661] ieee80211_sta_create_ibss.cold+0xd2/0x11f [ 77.966908][ T3661] ieee80211_ibss_work.cold+0x30e/0x60f [ 77.972483][ T3661] ieee80211_iface_work+0xb70/0xd00 [ 77.977715][ T3661] process_one_work+0x9ac/0x1680 [ 77.982671][ T3661] worker_thread+0x652/0x11c0 [ 77.987371][ T3661] kthread+0x405/0x4f0 [ 77.991465][ T3661] ret_from_fork+0x1f/0x30 [ 77.995895][ T3661] freed in: [ 77.999006][ T3661] linkwatch_do_dev+0x96/0x160 [ 78.004014][ T3661] __linkwatch_run_queue+0x233/0x6a0 [ 78.009496][ T3661] linkwatch_event+0x4a/0x60 [ 78.014099][ T3661] process_one_work+0x9ac/0x1680 [ 78.019034][ T3661] worker_thread+0x652/0x11c0 [ 78.023719][ T3661] kthread+0x405/0x4f0 [ 78.027810][ T3661] ret_from_fork+0x1f/0x30 [ 78.042541][ T3661] ------------[ cut here ]------------ [ 78.048253][ T3661] WARNING: CPU: 0 PID: 3661 at lib/ref_tracker.c:120 ref_tracker_free.cold+0x110/0x14e [ 78.062364][ T3661] Modules linked in: [ 78.066424][ T3661] CPU: 0 PID: 3661 Comm: kworker/0:5 Not tainted 5.16.0-rc4-next-20211210-syzkaller #0 [ 78.076075][ T3661] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 [ 78.090648][ T3661] Workqueue: events linkwatch_event [ 78.095890][ T3661] RIP: 0010:ref_tracker_free.cold+0x110/0x14e [ 78.102191][ T3661] Code: ea 03 48 c1 e0 2a 0f b6 04 02 84 c0 74 04 3c 03 7e 4c 8b 7b 18 e8 6b 54 e9 fa e8 26 4d 57 f8 4c 89 ee 48 89 ef e8 fb 33 36 00 <0f> 0b 41 bd ea ff ff ff e9 bd 60 e9 fa 4c 89 f7 e8 16 45 a2 f8 e9 [ 78.127211][ T3661] RSP: 0018:ffffc90002b5fb18 EFLAGS: 00010246 [ 78.133684][ T3661] RAX: 0000000000000000 RBX: ffff88807467f700 RCX: 0000000000000000 [ 78.141928][ T3661] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000001 [ 78.150087][ T3661] RBP: ffff888057e105b8 R08: 0000000000000001 R09: ffffffff8ffa1967 [ 78.158211][ T3661] R10: 0000000000000001 R11: 0000000000000000 R12: 1ffff9200056bf65 [ 78.166204][ T3661] R13: 0000000000000292 R14: ffff88807467f718 R15: 00000000c0e0008c [ 78.174321][ T3661] FS: 0000000000000000(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000 [ 78.183310][ T3661] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 78.190156][ T3661] CR2: 000000c000208800 CR3: 000000007f7b5000 CR4: 00000000003506f0 [ 78.198235][ T3661] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 78.206214][ T3661] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 78.214328][ T3661] Call Trace: [ 78.217679][ T3661] [ 78.220621][ T3661] ? __sanitizer_cov_trace_const_cmp4+0x1c/0x70 [ 78.226981][ T3661] ? nlmsg_notify+0xbe/0x280 [ 78.231607][ T3661] ? ref_tracker_dir_exit+0x330/0x330 [ 78.237654][ T3661] ? linkwatch_do_dev+0x96/0x160 [ 78.242628][ T3661] ? __linkwatch_run_queue+0x233/0x6a0 [ 78.248170][ T3661] ? linkwatch_event+0x4a/0x60 [ 78.252946][ T3661] ? process_one_work+0x9ac/0x1680 [ 78.258136][ T3661] ? worker_thread+0x853/0x11c0 [ 78.263020][ T3661] ? kthread+0x405/0x4f0 [ 78.267905][ T3661] ? ret_from_fork+0x1f/0x30 [ 78.272670][ T3661] ? netdev_state_change+0xa1/0x130 [ 78.278019][ T3661] ? netdev_exit+0xd0/0xd0 [ 78.282466][ T3661] ? dev_activate+0x420/0xa60 [ 78.287261][ T3661] linkwatch_do_dev+0x96/0x160 [ 78.292043][ T3661] __linkwatch_run_queue+0x233/0x6a0 [ 78.297505][ T3661] ? linkwatch_do_dev+0x160/0x160 [ 78.302561][ T3661] linkwatch_event+0x4a/0x60 [ 78.307225][ T3661] process_one_work+0x9ac/0x1680 [ 78.312292][ T3661] ? pwq_dec_nr_in_flight+0x2a0/0x2a0 [ 78.317757][ T3661] ? rwlock_bug.part.0+0x90/0x90 [ 78.322726][ T3661] ? _raw_spin_lock_irq+0x41/0x50 [ 78.327844][ T3661] worker_thread+0x853/0x11c0 [ 78.332543][ T3661] ? process_one_work+0x1680/0x1680 [ 78.338500][ T3661] kthread+0x405/0x4f0 [ 78.342610][ T3661] ? set_kthread_struct+0x130/0x130 Fixes: 63f13937cbe9 ("net: linkwatch: add net device refcount tracker") Signed-off-by: Eric Dumazet Reported-by: syzbot Link: https://lore.kernel.org/r/20211214051955.3569843-1-eric.dumazet@gmail.com Signed-off-by: Jakub Kicinski --- net/core/link_watch.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/core/link_watch.c b/net/core/link_watch.c index d7d089963b1da..b0f5344d1185b 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -166,7 +166,10 @@ static void linkwatch_do_dev(struct net_device *dev) netdev_state_change(dev); } - dev_put_track(dev, &dev->linkwatch_dev_tracker); + /* Note: our callers are responsible for + * calling netdev_tracker_free(). + */ + dev_put(dev); } static void __linkwatch_run_queue(int urgent_only) @@ -209,6 +212,10 @@ static void __linkwatch_run_queue(int urgent_only) list_add_tail(&dev->link_watch_list, &lweventlist); continue; } + /* We must free netdev tracker under + * the spinlock protection. + */ + netdev_tracker_free(dev, &dev->linkwatch_dev_tracker); spin_unlock_irq(&lweventlist_lock); linkwatch_do_dev(dev); do_dev--; @@ -232,6 +239,10 @@ void linkwatch_forget_dev(struct net_device *dev) if (!list_empty(&dev->link_watch_list)) { list_del_init(&dev->link_watch_list); clean = 1; + /* We must release netdev tracker under + * the spinlock protection. + */ + netdev_tracker_free(dev, &dev->linkwatch_dev_tracker); } spin_unlock_irqrestore(&lweventlist_lock, flags); if (clean) From 9280ac2e6f199cddcd746a9ba459136b8666287b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 14 Dec 2021 07:15:15 -0800 Subject: [PATCH 16/20] net: dev_replace_track() cleanup Use existing helpers (netdev_tracker_free() and netdev_tracker_alloc()) to remove ifdefery. Signed-off-by: Eric Dumazet Link: https://lore.kernel.org/r/20211214151515.312535-1-eric.dumazet@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 235d5d082f1a4..c06e9dc1a3179 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3885,16 +3885,14 @@ static inline void dev_replace_track(struct net_device *odev, netdevice_tracker *tracker, gfp_t gfp) { -#ifdef CONFIG_NET_DEV_REFCNT_TRACKER if (odev) - ref_tracker_free(&odev->refcnt_tracker, tracker); -#endif + netdev_tracker_free(odev, tracker); + dev_hold(ndev); dev_put(odev); -#ifdef CONFIG_NET_DEV_REFCNT_TRACKER + if (ndev) - ref_tracker_alloc(&ndev->refcnt_tracker, tracker, gfp); -#endif + netdev_tracker_alloc(ndev, tracker, gfp); } /* Carrier loss detection, dial on demand. The functions netif_carrier_on From 4db4c3ea56978086ca367a355e440de17d534827 Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 14 Dec 2021 14:45:05 +0100 Subject: [PATCH 17/20] net: dsa: hellcreek: Fix insertion of static FDB entries The insertion of static FDB entries ignores the pass_blocked bit. That bit is evaluated with regards to STP. Add the missing functionality. Fixes: e4b27ebc780f ("net: dsa: Add DSA driver for Hirschmann Hellcreek switches") Signed-off-by: Kurt Kanzenbach Reviewed-by: Vladimir Oltean Acked-by: Richard Cochran Signed-off-by: Jakub Kicinski --- drivers/net/dsa/hirschmann/hellcreek.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 9eecb75295735..c4f840b20adf6 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -711,8 +711,9 @@ static int __hellcreek_fdb_add(struct hellcreek *hellcreek, u16 meta = 0; dev_dbg(hellcreek->dev, "Add static FDB entry: MAC=%pM, MASK=0x%02x, " - "OBT=%d, REPRIO_EN=%d, PRIO=%d\n", entry->mac, entry->portmask, - entry->is_obt, entry->reprio_en, entry->reprio_tc); + "OBT=%d, PASS_BLOCKED=%d, REPRIO_EN=%d, PRIO=%d\n", entry->mac, + entry->portmask, entry->is_obt, entry->pass_blocked, + entry->reprio_en, entry->reprio_tc); /* Add mac address */ hellcreek_write(hellcreek, entry->mac[1] | (entry->mac[0] << 8), HR_FDBWDH); @@ -723,6 +724,8 @@ static int __hellcreek_fdb_add(struct hellcreek *hellcreek, meta |= entry->portmask << HR_FDBWRM0_PORTMASK_SHIFT; if (entry->is_obt) meta |= HR_FDBWRM0_OBT; + if (entry->pass_blocked) + meta |= HR_FDBWRM0_PASS_BLOCKED; if (entry->reprio_en) { meta |= HR_FDBWRM0_REPRIO_EN; meta |= entry->reprio_tc << HR_FDBWRM0_REPRIO_TC_SHIFT; From b7ade35eb53a2455f737a623c24e4b24455b2271 Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 14 Dec 2021 14:45:06 +0100 Subject: [PATCH 18/20] net: dsa: hellcreek: Add STP forwarding rule Treat STP as management traffic. STP traffic is designated for the CPU port only. In addition, STP traffic has to pass blocked ports. Fixes: e4b27ebc780f ("net: dsa: Add DSA driver for Hirschmann Hellcreek switches") Signed-off-by: Kurt Kanzenbach Reviewed-by: Vladimir Oltean Acked-by: Richard Cochran Signed-off-by: Jakub Kicinski --- drivers/net/dsa/hirschmann/hellcreek.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index c4f840b20adf6..17d3a4a3582e6 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1075,6 +1075,17 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ .reprio_en = 1, }; + static struct hellcreek_fdb_entry stp = { + /* MAC: 01-80-C2-00-00-00 */ + .mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, + .pass_blocked = 1, + .is_static = 1, + .reprio_tc = 6, + .reprio_en = 1, + }; int ret; mutex_lock(&hellcreek->reg_lock); @@ -1082,6 +1093,9 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) if (ret) goto out; ret = __hellcreek_fdb_add(hellcreek, &p2p); + if (ret) + goto out; + ret = __hellcreek_fdb_add(hellcreek, &stp); out: mutex_unlock(&hellcreek->reg_lock); From cad1798d2d0811ded37d1e946c6796102e58013b Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 14 Dec 2021 14:45:07 +0100 Subject: [PATCH 19/20] net: dsa: hellcreek: Allow PTP P2P measurements on blocked ports Allow PTP peer delay measurements on blocked ports by STP. In case of topology changes the PTP stack can directly start with the correct delays. Fixes: ddd56dfe52c9 ("net: dsa: hellcreek: Add PTP clock support") Signed-off-by: Kurt Kanzenbach Reviewed-by: Vladimir Oltean Acked-by: Richard Cochran Signed-off-by: Jakub Kicinski --- drivers/net/dsa/hirschmann/hellcreek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 17d3a4a3582e6..cc0e4465bbbf8 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1070,7 +1070,7 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) .portmask = 0x03, /* Management ports */ .age = 0, .is_obt = 0, - .pass_blocked = 0, + .pass_blocked = 1, .is_static = 1, .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ .reprio_en = 1, From 6cf01e451599da630ff1af529d61c5e4db4550ab Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 14 Dec 2021 14:45:08 +0100 Subject: [PATCH 20/20] net: dsa: hellcreek: Add missing PTP via UDP rules The switch supports PTP for UDP transport too. Therefore, add the missing static FDB entries to ensure correct forwarding of these packets. Fixes: ddd56dfe52c9 ("net: dsa: hellcreek: Add PTP clock support") Signed-off-by: Kurt Kanzenbach Acked-by: Richard Cochran Signed-off-by: Jakub Kicinski --- drivers/net/dsa/hirschmann/hellcreek.c | 64 ++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index cc0e4465bbbf8..726f267cb2280 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1053,7 +1053,7 @@ static void hellcreek_setup_tc_identity_mapping(struct hellcreek *hellcreek) static int hellcreek_setup_fdb(struct hellcreek *hellcreek) { - static struct hellcreek_fdb_entry ptp = { + static struct hellcreek_fdb_entry l2_ptp = { /* MAC: 01-1B-19-00-00-00 */ .mac = { 0x01, 0x1b, 0x19, 0x00, 0x00, 0x00 }, .portmask = 0x03, /* Management ports */ @@ -1064,7 +1064,29 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ .reprio_en = 1, }; - static struct hellcreek_fdb_entry p2p = { + static struct hellcreek_fdb_entry udp4_ptp = { + /* MAC: 01-00-5E-00-01-81 */ + .mac = { 0x01, 0x00, 0x5e, 0x00, 0x01, 0x81 }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, + .pass_blocked = 0, + .is_static = 1, + .reprio_tc = 6, + .reprio_en = 1, + }; + static struct hellcreek_fdb_entry udp6_ptp = { + /* MAC: 33-33-00-00-01-81 */ + .mac = { 0x33, 0x33, 0x00, 0x00, 0x01, 0x81 }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, + .pass_blocked = 0, + .is_static = 1, + .reprio_tc = 6, + .reprio_en = 1, + }; + static struct hellcreek_fdb_entry l2_p2p = { /* MAC: 01-80-C2-00-00-0E */ .mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }, .portmask = 0x03, /* Management ports */ @@ -1075,6 +1097,28 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ .reprio_en = 1, }; + static struct hellcreek_fdb_entry udp4_p2p = { + /* MAC: 01-00-5E-00-00-6B */ + .mac = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x6b }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, + .pass_blocked = 1, + .is_static = 1, + .reprio_tc = 6, + .reprio_en = 1, + }; + static struct hellcreek_fdb_entry udp6_p2p = { + /* MAC: 33-33-00-00-00-6B */ + .mac = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x6b }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, + .pass_blocked = 1, + .is_static = 1, + .reprio_tc = 6, + .reprio_en = 1, + }; static struct hellcreek_fdb_entry stp = { /* MAC: 01-80-C2-00-00-00 */ .mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }, @@ -1089,10 +1133,22 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) int ret; mutex_lock(&hellcreek->reg_lock); - ret = __hellcreek_fdb_add(hellcreek, &ptp); + ret = __hellcreek_fdb_add(hellcreek, &l2_ptp); + if (ret) + goto out; + ret = __hellcreek_fdb_add(hellcreek, &udp4_ptp); + if (ret) + goto out; + ret = __hellcreek_fdb_add(hellcreek, &udp6_ptp); + if (ret) + goto out; + ret = __hellcreek_fdb_add(hellcreek, &l2_p2p); + if (ret) + goto out; + ret = __hellcreek_fdb_add(hellcreek, &udp4_p2p); if (ret) goto out; - ret = __hellcreek_fdb_add(hellcreek, &p2p); + ret = __hellcreek_fdb_add(hellcreek, &udp6_p2p); if (ret) goto out; ret = __hellcreek_fdb_add(hellcreek, &stp);