diff options
71 files changed, 606 insertions, 342 deletions
| diff --git a/Documentation/networking/device_drivers/ethernet/pensando/ionic.rst b/Documentation/networking/device_drivers/ethernet/pensando/ionic.rst index 6ec7d686efab..05fe2b11bb18 100644 --- a/Documentation/networking/device_drivers/ethernet/pensando/ionic.rst +++ b/Documentation/networking/device_drivers/ethernet/pensando/ionic.rst @@ -99,6 +99,12 @@ Minimal SR-IOV support is currently offered and can be enabled by setting  the sysfs 'sriov_numvfs' value, if supported by your particular firmware  configuration. +XDP +--- + +Support for XDP includes the basics, plus Jumbo frames, Redirect and +ndo_xmit.  There is no current support for zero-copy sockets or HW offload. +  Statistics  ========== @@ -138,6 +144,12 @@ Driver port specific::       rx_csum_none: 0       rx_csum_complete: 3       rx_csum_error: 0 +     xdp_drop: 0 +     xdp_aborted: 0 +     xdp_pass: 0 +     xdp_tx: 0 +     xdp_redirect: 0 +     xdp_frames: 0  Driver queue specific:: @@ -149,9 +161,12 @@ Driver queue specific::       tx_0_frags: 0       tx_0_tso: 0       tx_0_tso_bytes: 0 +     tx_0_hwstamp_valid: 0 +     tx_0_hwstamp_invalid: 0       tx_0_csum_none: 3       tx_0_csum: 0       tx_0_vlan_inserted: 0 +     tx_0_xdp_frames: 0       rx_0_pkts: 2       rx_0_bytes: 120       rx_0_dma_map_err: 0 @@ -159,8 +174,15 @@ Driver queue specific::       rx_0_csum_none: 0       rx_0_csum_complete: 0       rx_0_csum_error: 0 +     rx_0_hwstamp_valid: 0 +     rx_0_hwstamp_invalid: 0       rx_0_dropped: 0       rx_0_vlan_stripped: 0 +     rx_0_xdp_drop: 0 +     rx_0_xdp_aborted: 0 +     rx_0_xdp_pass: 0 +     rx_0_xdp_tx: 0 +     rx_0_xdp_redirect: 0  Firmware port specific:: diff --git a/Documentation/networking/multi-pf-netdev.rst b/Documentation/networking/multi-pf-netdev.rst index be8e4bcadf11..268819225866 100644 --- a/Documentation/networking/multi-pf-netdev.rst +++ b/Documentation/networking/multi-pf-netdev.rst @@ -87,35 +87,35 @@ all using the same instance under "priv->mdev".  Observability  ============= -The relation between PF, irq, napi, and queue can be observed via netlink spec: +The relation between PF, irq, napi, and queue can be observed via netlink spec:: -$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}' -[{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'}, - {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'}, - {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'}, - {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'rx'}, - {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'rx'}, - {'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'tx'}, - {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'tx'}, - {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'tx'}, - {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'}, - {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}] +  $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}' +  [{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'}, +   {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'}, +   {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'}, +   {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'rx'}, +   {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'rx'}, +   {'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'tx'}, +   {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'tx'}, +   {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'tx'}, +   {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'}, +   {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}] -$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}' -[{'id': 543, 'ifindex': 13, 'irq': 42}, - {'id': 542, 'ifindex': 13, 'irq': 41}, - {'id': 541, 'ifindex': 13, 'irq': 40}, - {'id': 540, 'ifindex': 13, 'irq': 39}, - {'id': 539, 'ifindex': 13, 'irq': 36}] +  $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}' +  [{'id': 543, 'ifindex': 13, 'irq': 42}, +   {'id': 542, 'ifindex': 13, 'irq': 41}, +   {'id': 541, 'ifindex': 13, 'irq': 40}, +   {'id': 540, 'ifindex': 13, 'irq': 39}, +   {'id': 539, 'ifindex': 13, 'irq': 36}] -Here you can clearly observe our channels distribution policy: +Here you can clearly observe our channels distribution policy:: -$ ls /proc/irq/{36,39,40,41,42}/mlx5* -d -1 -/proc/irq/36/mlx5_comp1@pci:0000:08:00.0 -/proc/irq/39/mlx5_comp1@pci:0000:09:00.0 -/proc/irq/40/mlx5_comp2@pci:0000:08:00.0 -/proc/irq/41/mlx5_comp2@pci:0000:09:00.0 -/proc/irq/42/mlx5_comp3@pci:0000:08:00.0 +  $ ls /proc/irq/{36,39,40,41,42}/mlx5* -d -1 +  /proc/irq/36/mlx5_comp1@pci:0000:08:00.0 +  /proc/irq/39/mlx5_comp1@pci:0000:09:00.0 +  /proc/irq/40/mlx5_comp2@pci:0000:08:00.0 +  /proc/irq/41/mlx5_comp2@pci:0000:09:00.0 +  /proc/irq/42/mlx5_comp3@pci:0000:08:00.0  Steering  ======== diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst index dceb49d56a91..70c4fb9d4e5c 100644 --- a/Documentation/networking/net_cachelines/net_device.rst +++ b/Documentation/networking/net_cachelines/net_device.rst @@ -13,7 +13,7 @@ struct_dev_ifalias*                 ifalias  unsigned_long                       mem_end                                                           unsigned_long                       mem_start                                                         unsigned_long                       base_addr                                                        -unsigned_long                       state                                                            +unsigned_long                       state                   read_mostly         read_mostly         netif_running(dev)  struct_list_head                    dev_list                                                          struct_list_head                    napi_list                                                         struct_list_head                    unreg_list                                                       diff --git a/MAINTAINERS b/MAINTAINERS index 5b251bcc91f0..f736af98d7b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15237,7 +15237,6 @@ F:	drivers/net/ethernet/neterion/  NETFILTER  M:	Pablo Neira Ayuso <pablo@netfilter.org>  M:	Jozsef Kadlecsik <kadlec@netfilter.org> -M:	Florian Westphal <fw@strlen.de>  L:	netfilter-devel@vger.kernel.org  L:	coreteam@netfilter.org  S:	Maintained diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index f81b598147b3..7b5028b67cd5 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -370,8 +370,8 @@ static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = {  static const struct kvaser_pciefd_irq_mask kvaser_pciefd_xilinx_irq_mask = {  	.kcan_rx0 = BIT(4), -	.kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) }, -	.all = GENMASK(19, 16) | BIT(4), +	.kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19), BIT(20), BIT(21), BIT(22), BIT(23) }, +	.all = GENMASK(23, 16) | BIT(4),  };  static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = { diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 678b51f9cea6..767f66c37f6b 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -950,20 +950,56 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)  	mutex_unlock(&priv->reg_mutex);  } +/* On page 205, section "8.6.3 Frame filtering" of the active standard, IEEE Std + * 802.1Q™-2022, it is stated that frames with 01:80:C2:00:00:00-0F as MAC DA + * must only be propagated to C-VLAN and MAC Bridge components. That means + * VLAN-aware and VLAN-unaware bridges. On the switch designs with CPU ports, + * these frames are supposed to be processed by the CPU (software). So we make + * the switch only forward them to the CPU port. And if received from a CPU + * port, forward to a single port. The software is responsible of making the + * switch conform to the latter by setting a single port as destination port on + * the special tag. + * + * This switch intellectual property cannot conform to this part of the standard + * fully. Whilst the REV_UN frame tag covers the remaining :04-0D and :0F MAC + * DAs, it also includes :22-FF which the scope of propagation is not supposed + * to be restricted for these MAC DAs. + */  static void  mt753x_trap_frames(struct mt7530_priv *priv)  { -	/* Trap BPDUs to the CPU port(s) */ -	mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, +	/* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them +	 * VLAN-untagged. +	 */ +	mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_EG_TAG_MASK | +		   MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK | +		   MT753X_BPDU_PORT_FW_MASK, +		   MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +		   MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) | +		   MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |  		   MT753X_BPDU_CPU_ONLY); -	/* Trap 802.1X PAE frames to the CPU port(s) */ -	mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_PORT_FW_MASK, -		   MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY)); +	/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress +	 * them VLAN-untagged. +	 */ +	mt7530_rmw(priv, MT753X_RGAC1, MT753X_R02_EG_TAG_MASK | +		   MT753X_R02_PORT_FW_MASK | MT753X_R01_EG_TAG_MASK | +		   MT753X_R01_PORT_FW_MASK, +		   MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +		   MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) | +		   MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +		   MT753X_BPDU_CPU_ONLY); -	/* Trap LLDP frames with :0E MAC DA to the CPU port(s) */ -	mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK, -		   MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY)); +	/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress +	 * them VLAN-untagged. +	 */ +	mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_EG_TAG_MASK | +		   MT753X_R0E_PORT_FW_MASK | MT753X_R03_EG_TAG_MASK | +		   MT753X_R03_PORT_FW_MASK, +		   MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +		   MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) | +		   MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +		   MT753X_BPDU_CPU_ONLY);  }  static void @@ -2192,22 +2228,16 @@ mt7530_setup(struct dsa_switch *ds)  		}  	} -	/* Disable LEDs before reset to prevent the MT7530 sampling a -	 * potentially incorrect HT_XTAL_FSEL value. -	 */ -	mt7530_write(priv, MT7530_LED_EN, 0); -	usleep_range(1000, 1100); -  	/* Reset whole chip through gpio pin or memory-mapped registers for  	 * different type of hardware  	 */  	if (priv->mcm) {  		reset_control_assert(priv->rstc); -		usleep_range(1000, 1100); +		usleep_range(5000, 5100);  		reset_control_deassert(priv->rstc);  	} else {  		gpiod_set_value_cansleep(priv->reset, 0); -		usleep_range(1000, 1100); +		usleep_range(5000, 5100);  		gpiod_set_value_cansleep(priv->reset, 1);  	} @@ -2420,11 +2450,11 @@ mt7531_setup(struct dsa_switch *ds)  	 */  	if (priv->mcm) {  		reset_control_assert(priv->rstc); -		usleep_range(1000, 1100); +		usleep_range(5000, 5100);  		reset_control_deassert(priv->rstc);  	} else {  		gpiod_set_value_cansleep(priv->reset, 0); -		usleep_range(1000, 1100); +		usleep_range(5000, 5100);  		gpiod_set_value_cansleep(priv->reset, 1);  	} diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index a71166e0a7fc..d17b318e6ee4 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -65,14 +65,33 @@ enum mt753x_id {  /* Registers for BPDU and PAE frame control*/  #define MT753X_BPC			0x24 -#define  MT753X_BPDU_PORT_FW_MASK	GENMASK(2, 0) +#define  MT753X_PAE_EG_TAG_MASK		GENMASK(24, 22) +#define  MT753X_PAE_EG_TAG(x)		FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x)  #define  MT753X_PAE_PORT_FW_MASK	GENMASK(18, 16)  #define  MT753X_PAE_PORT_FW(x)		FIELD_PREP(MT753X_PAE_PORT_FW_MASK, x) +#define  MT753X_BPDU_EG_TAG_MASK	GENMASK(8, 6) +#define  MT753X_BPDU_EG_TAG(x)		FIELD_PREP(MT753X_BPDU_EG_TAG_MASK, x) +#define  MT753X_BPDU_PORT_FW_MASK	GENMASK(2, 0) + +/* Register for :01 and :02 MAC DA frame control */ +#define MT753X_RGAC1			0x28 +#define  MT753X_R02_EG_TAG_MASK		GENMASK(24, 22) +#define  MT753X_R02_EG_TAG(x)		FIELD_PREP(MT753X_R02_EG_TAG_MASK, x) +#define  MT753X_R02_PORT_FW_MASK	GENMASK(18, 16) +#define  MT753X_R02_PORT_FW(x)		FIELD_PREP(MT753X_R02_PORT_FW_MASK, x) +#define  MT753X_R01_EG_TAG_MASK		GENMASK(8, 6) +#define  MT753X_R01_EG_TAG(x)		FIELD_PREP(MT753X_R01_EG_TAG_MASK, x) +#define  MT753X_R01_PORT_FW_MASK	GENMASK(2, 0)  /* Register for :03 and :0E MAC DA frame control */  #define MT753X_RGAC2			0x2c +#define  MT753X_R0E_EG_TAG_MASK		GENMASK(24, 22) +#define  MT753X_R0E_EG_TAG(x)		FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x)  #define  MT753X_R0E_PORT_FW_MASK	GENMASK(18, 16)  #define  MT753X_R0E_PORT_FW(x)		FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x) +#define  MT753X_R03_EG_TAG_MASK		GENMASK(8, 6) +#define  MT753X_R03_EG_TAG(x)		FIELD_PREP(MT753X_R03_EG_TAG_MASK, x) +#define  MT753X_R03_PORT_FW_MASK	GENMASK(2, 0)  enum mt753x_bpdu_port_fw {  	MT753X_BPDU_FOLLOW_MFC, @@ -253,6 +272,7 @@ enum mt7530_port_mode {  enum mt7530_vlan_port_eg_tag {  	MT7530_VLAN_EG_DISABLED = 0,  	MT7530_VLAN_EG_CONSISTENT = 1, +	MT7530_VLAN_EG_UNTAGGED = 4,  };  enum mt7530_vlan_port_attr { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index d8b1824c334d..0bc1367fd649 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1002,9 +1002,6 @@ static inline void bnx2x_set_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,  static inline void bnx2x_free_rx_mem_pool(struct bnx2x *bp,  					  struct bnx2x_alloc_pool *pool)  { -	if (!pool->page) -		return; -  	put_page(pool->page);  	pool->page = NULL; @@ -1015,6 +1012,9 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,  {  	int i; +	if (!fp->page_pool.page) +		return; +  	if (fp->mode == TPA_MODE_DISABLED)  		return; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 6c70c8498690..3c0f55b3e48e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -1338,7 +1338,7 @@ static irqreturn_t cgx_fwi_event_handler(int irq, void *data)  		/* Release thread waiting for completion  */  		lmac->cmd_pend = false; -		wake_up_interruptible(&lmac->wq_cmd_cmplt); +		wake_up(&lmac->wq_cmd_cmplt);  		break;  	case CGX_EVT_ASYNC:  		if (cgx_event_is_linkevent(event)) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c index b92264d0a77e..1e5aa5397504 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c @@ -214,11 +214,12 @@ int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid)  }  EXPORT_SYMBOL(otx2_mbox_busy_poll_for_rsp); -void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid) +static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)  {  	struct otx2_mbox_dev *mdev = &mbox->dev[devid];  	struct mbox_hdr *tx_hdr, *rx_hdr;  	void *hw_mbase = mdev->hwbase; +	u64 intr_val;  	tx_hdr = hw_mbase + mbox->tx_start;  	rx_hdr = hw_mbase + mbox->rx_start; @@ -254,14 +255,52 @@ void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)  	spin_unlock(&mdev->mbox_lock); +	/* Check if interrupt pending */ +	intr_val = readq((void __iomem *)mbox->reg_base + +		     (mbox->trigger | (devid << mbox->tr_shift))); + +	intr_val |= data;  	/* The interrupt should be fired after num_msgs is written  	 * to the shared memory  	 */ -	writeq(1, (void __iomem *)mbox->reg_base + +	writeq(intr_val, (void __iomem *)mbox->reg_base +  	       (mbox->trigger | (devid << mbox->tr_shift)));  } + +void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid) +{ +	otx2_mbox_msg_send_data(mbox, devid, MBOX_DOWN_MSG); +}  EXPORT_SYMBOL(otx2_mbox_msg_send); +void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid) +{ +	otx2_mbox_msg_send_data(mbox, devid, MBOX_UP_MSG); +} +EXPORT_SYMBOL(otx2_mbox_msg_send_up); + +bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid) +{ +	u64 data; + +	data = readq((void __iomem *)mbox->reg_base + +		     (mbox->trigger | (devid << mbox->tr_shift))); + +	/* If data is non-zero wait for ~1ms and return to caller +	 * whether data has changed to zero or not after the wait. +	 */ +	if (!data) +		return true; + +	usleep_range(950, 1000); + +	data = readq((void __iomem *)mbox->reg_base + +		     (mbox->trigger | (devid << mbox->tr_shift))); + +	return data == 0; +} +EXPORT_SYMBOL(otx2_mbox_wait_for_zero); +  struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,  					    int size, int size_rsp)  { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index 61ab7f66f053..eb2a20b5a0d0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -16,6 +16,9 @@  #define MBOX_SIZE		SZ_64K +#define MBOX_DOWN_MSG		1 +#define MBOX_UP_MSG		2 +  /* AF/PF: PF initiated, PF/VF VF initiated */  #define MBOX_DOWN_RX_START	0  #define MBOX_DOWN_RX_SIZE	(46 * SZ_1K) @@ -101,6 +104,7 @@ int otx2_mbox_regions_init(struct otx2_mbox *mbox, void __force **hwbase,  			   struct pci_dev *pdev, void __force *reg_base,  			   int direction, int ndevs, unsigned long *bmap);  void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid); +void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid);  int otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid);  int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid);  struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid, @@ -118,6 +122,8 @@ static inline struct mbox_msghdr *otx2_mbox_alloc_msg(struct otx2_mbox *mbox,  	return otx2_mbox_alloc_msg_rsp(mbox, devid, size, 0);  } +bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid); +  /* Mailbox message types */  #define MBOX_MSG_MASK				0xFFFF  #define MBOX_MSG_INVALID			0xFFFE diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c index dfd23580e3b8..d39d86e694cc 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c @@ -121,13 +121,17 @@ int mcs_add_intr_wq_entry(struct mcs *mcs, struct mcs_intr_event *event)  static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)  {  	struct mcs_intr_info *req; -	int err, pf; +	int pf;  	pf = rvu_get_pf(event->pcifunc); +	mutex_lock(&rvu->mbox_lock); +  	req = otx2_mbox_alloc_msg_mcs_intr_notify(rvu, pf); -	if (!req) +	if (!req) { +		mutex_unlock(&rvu->mbox_lock);  		return -ENOMEM; +	}  	req->mcs_id = event->mcs_id;  	req->intr_mask = event->intr_mask; @@ -135,10 +139,11 @@ static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)  	req->hdr.pcifunc = event->pcifunc;  	req->lmac_id = event->lmac_id; -	otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pf); -	err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pf); -	if (err) -		dev_warn(rvu->dev, "MCS notification to pf %d failed\n", pf); +	otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf); + +	otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf); + +	mutex_unlock(&rvu->mbox_lock);  	return 0;  } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 07d4859de53a..ff78251f92d4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -2119,7 +2119,7 @@ bad_message:  	}  } -static void __rvu_mbox_handler(struct rvu_work *mwork, int type) +static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll)  {  	struct rvu *rvu = mwork->rvu;  	int offset, err, id, devid; @@ -2186,6 +2186,9 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)  	}  	mw->mbox_wrk[devid].num_msgs = 0; +	if (poll) +		otx2_mbox_wait_for_zero(mbox, devid); +  	/* Send mbox responses to VF/PF */  	otx2_mbox_msg_send(mbox, devid);  } @@ -2193,15 +2196,18 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)  static inline void rvu_afpf_mbox_handler(struct work_struct *work)  {  	struct rvu_work *mwork = container_of(work, struct rvu_work, work); +	struct rvu *rvu = mwork->rvu; -	__rvu_mbox_handler(mwork, TYPE_AFPF); +	mutex_lock(&rvu->mbox_lock); +	__rvu_mbox_handler(mwork, TYPE_AFPF, true); +	mutex_unlock(&rvu->mbox_lock);  }  static inline void rvu_afvf_mbox_handler(struct work_struct *work)  {  	struct rvu_work *mwork = container_of(work, struct rvu_work, work); -	__rvu_mbox_handler(mwork, TYPE_AFVF); +	__rvu_mbox_handler(mwork, TYPE_AFVF, false);  }  static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type) @@ -2376,6 +2382,8 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,  		}  	} +	mutex_init(&rvu->mbox_lock); +  	mbox_regions = kcalloc(num, sizeof(void *), GFP_KERNEL);  	if (!mbox_regions) {  		err = -ENOMEM; @@ -2525,10 +2533,9 @@ static void rvu_queue_work(struct mbox_wq_info *mw, int first,  	}  } -static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq) +static irqreturn_t rvu_mbox_pf_intr_handler(int irq, void *rvu_irq)  {  	struct rvu *rvu = (struct rvu *)rvu_irq; -	int vfs = rvu->vfs;  	u64 intr;  	intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFAF_MBOX_INT); @@ -2542,6 +2549,18 @@ static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)  	rvu_queue_work(&rvu->afpf_wq_info, 0, rvu->hw->total_pfs, intr); +	return IRQ_HANDLED; +} + +static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq) +{ +	struct rvu *rvu = (struct rvu *)rvu_irq; +	int vfs = rvu->vfs; +	u64 intr; + +	/* Sync with mbox memory region */ +	rmb(); +  	/* Handle VF interrupts */  	if (vfs > 64) {  		intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(1)); @@ -2886,7 +2905,7 @@ static int rvu_register_interrupts(struct rvu *rvu)  	/* Register mailbox interrupt handler */  	sprintf(&rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], "RVUAF Mbox");  	ret = request_irq(pci_irq_vector(rvu->pdev, RVU_AF_INT_VEC_MBOX), -			  rvu_mbox_intr_handler, 0, +			  rvu_mbox_pf_intr_handler, 0,  			  &rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], rvu);  	if (ret) {  		dev_err(rvu->dev, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index f390525a6217..35834687e40f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -591,6 +591,8 @@ struct rvu {  	spinlock_t		mcs_intrq_lock;  	/* CPT interrupt lock */  	spinlock_t		cpt_intr_lock; + +	struct mutex		mbox_lock; /* Serialize mbox up and down msgs */  };  static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 38acdc7a73bb..72e060cf6b61 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -232,7 +232,7 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)  	struct cgx_link_user_info *linfo;  	struct cgx_link_info_msg *msg;  	unsigned long pfmap; -	int err, pfid; +	int pfid;  	linfo = &event->link_uinfo;  	pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id); @@ -255,16 +255,22 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)  			continue;  		} +		mutex_lock(&rvu->mbox_lock); +  		/* Send mbox message to PF */  		msg = otx2_mbox_alloc_msg_cgx_link_event(rvu, pfid); -		if (!msg) +		if (!msg) { +			mutex_unlock(&rvu->mbox_lock);  			continue; +		} +  		msg->link_info = *linfo; -		otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pfid); -		err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pfid); -		if (err) -			dev_warn(rvu->dev, "notification to pf %d failed\n", -				 pfid); + +		otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pfid); + +		otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pfid); + +		mutex_unlock(&rvu->mbox_lock);  	} while (pfmap);  } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 02d0b707aea5..a85ac039d779 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -1592,7 +1592,7 @@ int otx2_detach_resources(struct mbox *mbox)  	detach->partial = false;  	/* Send detach request to AF */ -	otx2_mbox_msg_send(&mbox->mbox, 0); +	otx2_sync_mbox_msg(mbox);  	mutex_unlock(&mbox->lock);  	return 0;  } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 06910307085e..7e16a341ec58 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -815,7 +815,7 @@ static inline int otx2_sync_mbox_up_msg(struct mbox *mbox, int devid)  	if (!otx2_mbox_nonempty(&mbox->mbox_up, devid))  		return 0; -	otx2_mbox_msg_send(&mbox->mbox_up, devid); +	otx2_mbox_msg_send_up(&mbox->mbox_up, devid);  	err = otx2_mbox_wait_for_rsp(&mbox->mbox_up, devid);  	if (err)  		return err; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index e5fe67e73865..b40bd0e46751 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -292,8 +292,8 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs)  	return 0;  } -static void otx2_queue_work(struct mbox *mw, struct workqueue_struct *mbox_wq, -			    int first, int mdevs, u64 intr, int type) +static void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq, +			       int first, int mdevs, u64 intr)  {  	struct otx2_mbox_dev *mdev;  	struct otx2_mbox *mbox; @@ -307,40 +307,26 @@ static void otx2_queue_work(struct mbox *mw, struct workqueue_struct *mbox_wq,  		mbox = &mw->mbox;  		mdev = &mbox->dev[i]; -		if (type == TYPE_PFAF) -			otx2_sync_mbox_bbuf(mbox, i);  		hdr = mdev->mbase + mbox->rx_start;  		/* The hdr->num_msgs is set to zero immediately in the interrupt -		 * handler to  ensure that it holds a correct value next time -		 * when the interrupt handler is called. -		 * pf->mbox.num_msgs holds the data for use in pfaf_mbox_handler -		 * pf>mbox.up_num_msgs holds the data for use in -		 * pfaf_mbox_up_handler. +		 * handler to ensure that it holds a correct value next time +		 * when the interrupt handler is called. pf->mw[i].num_msgs +		 * holds the data for use in otx2_pfvf_mbox_handler and +		 * pf->mw[i].up_num_msgs holds the data for use in +		 * otx2_pfvf_mbox_up_handler.  		 */  		if (hdr->num_msgs) {  			mw[i].num_msgs = hdr->num_msgs;  			hdr->num_msgs = 0; -			if (type == TYPE_PFAF) -				memset(mbox->hwbase + mbox->rx_start, 0, -				       ALIGN(sizeof(struct mbox_hdr), -					     sizeof(u64))); -  			queue_work(mbox_wq, &mw[i].mbox_wrk);  		}  		mbox = &mw->mbox_up;  		mdev = &mbox->dev[i]; -		if (type == TYPE_PFAF) -			otx2_sync_mbox_bbuf(mbox, i);  		hdr = mdev->mbase + mbox->rx_start;  		if (hdr->num_msgs) {  			mw[i].up_num_msgs = hdr->num_msgs;  			hdr->num_msgs = 0; -			if (type == TYPE_PFAF) -				memset(mbox->hwbase + mbox->rx_start, 0, -				       ALIGN(sizeof(struct mbox_hdr), -					     sizeof(u64))); -  			queue_work(mbox_wq, &mw[i].mbox_up_wrk);  		}  	} @@ -356,8 +342,10 @@ static void otx2_forward_msg_pfvf(struct otx2_mbox_dev *mdev,  	/* Msgs are already copied, trigger VF's mbox irq */  	smp_wmb(); +	otx2_mbox_wait_for_zero(pfvf_mbox, devid); +  	offset = pfvf_mbox->trigger | (devid << pfvf_mbox->tr_shift); -	writeq(1, (void __iomem *)pfvf_mbox->reg_base + offset); +	writeq(MBOX_DOWN_MSG, (void __iomem *)pfvf_mbox->reg_base + offset);  	/* Restore VF's mbox bounce buffer region address */  	src_mdev->mbase = bbuf_base; @@ -547,7 +535,7 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)  end:  		offset = mbox->rx_start + msg->next_msgoff;  		if (mdev->msgs_acked == (vf_mbox->up_num_msgs - 1)) -			__otx2_mbox_reset(mbox, 0); +			__otx2_mbox_reset(mbox, vf_idx);  		mdev->msgs_acked++;  	}  } @@ -564,8 +552,7 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)  	if (vfs > 64) {  		intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(1));  		otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(1), intr); -		otx2_queue_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr, -				TYPE_PFVF); +		otx2_queue_vf_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr);  		if (intr)  			trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);  		vfs = 64; @@ -574,7 +561,7 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)  	intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(0));  	otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(0), intr); -	otx2_queue_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr, TYPE_PFVF); +	otx2_queue_vf_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr);  	if (intr)  		trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr); @@ -597,8 +584,9 @@ static int otx2_pfvf_mbox_init(struct otx2_nic *pf, int numvfs)  	if (!pf->mbox_pfvf)  		return -ENOMEM; -	pf->mbox_pfvf_wq = alloc_ordered_workqueue("otx2_pfvf_mailbox", -						   WQ_HIGHPRI | WQ_MEM_RECLAIM); +	pf->mbox_pfvf_wq = alloc_workqueue("otx2_pfvf_mailbox", +					   WQ_UNBOUND | WQ_HIGHPRI | +					   WQ_MEM_RECLAIM, 0);  	if (!pf->mbox_pfvf_wq)  		return -ENOMEM; @@ -821,20 +809,22 @@ static void otx2_pfaf_mbox_handler(struct work_struct *work)  	struct mbox *af_mbox;  	struct otx2_nic *pf;  	int offset, id; +	u16 num_msgs;  	af_mbox = container_of(work, struct mbox, mbox_wrk);  	mbox = &af_mbox->mbox;  	mdev = &mbox->dev[0];  	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +	num_msgs = rsp_hdr->num_msgs;  	offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);  	pf = af_mbox->pfvf; -	for (id = 0; id < af_mbox->num_msgs; id++) { +	for (id = 0; id < num_msgs; id++) {  		msg = (struct mbox_msghdr *)(mdev->mbase + offset);  		otx2_process_pfaf_mbox_msg(pf, msg);  		offset = mbox->rx_start + msg->next_msgoff; -		if (mdev->msgs_acked == (af_mbox->num_msgs - 1)) +		if (mdev->msgs_acked == (num_msgs - 1))  			__otx2_mbox_reset(mbox, 0);  		mdev->msgs_acked++;  	} @@ -945,12 +935,14 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)  	int offset, id, devid = 0;  	struct mbox_hdr *rsp_hdr;  	struct mbox_msghdr *msg; +	u16 num_msgs;  	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +	num_msgs = rsp_hdr->num_msgs;  	offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); -	for (id = 0; id < af_mbox->up_num_msgs; id++) { +	for (id = 0; id < num_msgs; id++) {  		msg = (struct mbox_msghdr *)(mdev->mbase + offset);  		devid = msg->pcifunc & RVU_PFVF_FUNC_MASK; @@ -959,10 +951,11 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)  			otx2_process_mbox_msg_up(pf, msg);  		offset = mbox->rx_start + msg->next_msgoff;  	} -	if (devid) { +	/* Forward to VF iff VFs are really present */ +	if (devid && pci_num_vf(pf->pdev)) {  		otx2_forward_vf_mbox_msgs(pf, &pf->mbox.mbox_up,  					  MBOX_DIR_PFVF_UP, devid - 1, -					  af_mbox->up_num_msgs); +					  num_msgs);  		return;  	} @@ -972,16 +965,49 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)  static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)  {  	struct otx2_nic *pf = (struct otx2_nic *)pf_irq; -	struct mbox *mbox; +	struct mbox *mw = &pf->mbox; +	struct otx2_mbox_dev *mdev; +	struct otx2_mbox *mbox; +	struct mbox_hdr *hdr; +	u64 mbox_data;  	/* Clear the IRQ */  	otx2_write64(pf, RVU_PF_INT, BIT_ULL(0)); -	mbox = &pf->mbox; -	trace_otx2_msg_interrupt(mbox->mbox.pdev, "AF to PF", BIT_ULL(0)); +	mbox_data = otx2_read64(pf, RVU_PF_PFAF_MBOX0); + +	if (mbox_data & MBOX_UP_MSG) { +		mbox_data &= ~MBOX_UP_MSG; +		otx2_write64(pf, RVU_PF_PFAF_MBOX0, mbox_data); + +		mbox = &mw->mbox_up; +		mdev = &mbox->dev[0]; +		otx2_sync_mbox_bbuf(mbox, 0); + +		hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +		if (hdr->num_msgs) +			queue_work(pf->mbox_wq, &mw->mbox_up_wrk); + +		trace_otx2_msg_interrupt(pf->pdev, "UP message from AF to PF", +					 BIT_ULL(0)); +	} + +	if (mbox_data & MBOX_DOWN_MSG) { +		mbox_data &= ~MBOX_DOWN_MSG; +		otx2_write64(pf, RVU_PF_PFAF_MBOX0, mbox_data); + +		mbox = &mw->mbox; +		mdev = &mbox->dev[0]; +		otx2_sync_mbox_bbuf(mbox, 0); + +		hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +		if (hdr->num_msgs) +			queue_work(pf->mbox_wq, &mw->mbox_wrk); -	otx2_queue_work(mbox, pf->mbox_wq, 0, 1, 1, TYPE_PFAF); +		trace_otx2_msg_interrupt(pf->pdev, "DOWN reply from AF to PF", +					 BIT_ULL(0)); +	}  	return IRQ_HANDLED;  } @@ -3087,6 +3113,7 @@ static void otx2_vf_link_event_task(struct work_struct *work)  	struct otx2_vf_config *config;  	struct cgx_link_info_msg *req;  	struct mbox_msghdr *msghdr; +	struct delayed_work *dwork;  	struct otx2_nic *pf;  	int vf_idx; @@ -3095,10 +3122,24 @@ static void otx2_vf_link_event_task(struct work_struct *work)  	vf_idx = config - config->pf->vf_configs;  	pf = config->pf; +	if (config->intf_down) +		return; + +	mutex_lock(&pf->mbox.lock); + +	dwork = &config->link_event_work; + +	if (!otx2_mbox_wait_for_zero(&pf->mbox_pfvf[0].mbox_up, vf_idx)) { +		schedule_delayed_work(dwork, msecs_to_jiffies(100)); +		mutex_unlock(&pf->mbox.lock); +		return; +	} +  	msghdr = otx2_mbox_alloc_msg_rsp(&pf->mbox_pfvf[0].mbox_up, vf_idx,  					 sizeof(*req), sizeof(struct msg_rsp));  	if (!msghdr) {  		dev_err(pf->dev, "Failed to create VF%d link event\n", vf_idx); +		mutex_unlock(&pf->mbox.lock);  		return;  	} @@ -3107,7 +3148,11 @@ static void otx2_vf_link_event_task(struct work_struct *work)  	req->hdr.sig = OTX2_MBOX_REQ_SIG;  	memcpy(&req->link_info, &pf->linfo, sizeof(req->link_info)); +	otx2_mbox_wait_for_zero(&pf->mbox_pfvf[0].mbox_up, vf_idx); +  	otx2_sync_mbox_up_msg(&pf->mbox_pfvf[0], vf_idx); + +	mutex_unlock(&pf->mbox.lock);  }  static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index 35e06048356f..cf0aa16d7540 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -89,16 +89,20 @@ static void otx2vf_vfaf_mbox_handler(struct work_struct *work)  	struct otx2_mbox *mbox;  	struct mbox *af_mbox;  	int offset, id; +	u16 num_msgs;  	af_mbox = container_of(work, struct mbox, mbox_wrk);  	mbox = &af_mbox->mbox;  	mdev = &mbox->dev[0];  	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); -	if (af_mbox->num_msgs == 0) +	num_msgs = rsp_hdr->num_msgs; + +	if (num_msgs == 0)  		return; +  	offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); -	for (id = 0; id < af_mbox->num_msgs; id++) { +	for (id = 0; id < num_msgs; id++) {  		msg = (struct mbox_msghdr *)(mdev->mbase + offset);  		otx2vf_process_vfaf_mbox_msg(af_mbox->pfvf, msg);  		offset = mbox->rx_start + msg->next_msgoff; @@ -151,6 +155,7 @@ static void otx2vf_vfaf_mbox_up_handler(struct work_struct *work)  	struct mbox *vf_mbox;  	struct otx2_nic *vf;  	int offset, id; +	u16 num_msgs;  	vf_mbox = container_of(work, struct mbox, mbox_up_wrk);  	vf = vf_mbox->pfvf; @@ -158,12 +163,14 @@ static void otx2vf_vfaf_mbox_up_handler(struct work_struct *work)  	mdev = &mbox->dev[0];  	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); -	if (vf_mbox->up_num_msgs == 0) +	num_msgs = rsp_hdr->num_msgs; + +	if (num_msgs == 0)  		return;  	offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); -	for (id = 0; id < vf_mbox->up_num_msgs; id++) { +	for (id = 0; id < num_msgs; id++) {  		msg = (struct mbox_msghdr *)(mdev->mbase + offset);  		otx2vf_process_mbox_msg_up(vf, msg);  		offset = mbox->rx_start + msg->next_msgoff; @@ -178,40 +185,48 @@ static irqreturn_t otx2vf_vfaf_mbox_intr_handler(int irq, void *vf_irq)  	struct otx2_mbox_dev *mdev;  	struct otx2_mbox *mbox;  	struct mbox_hdr *hdr; +	u64 mbox_data;  	/* Clear the IRQ */  	otx2_write64(vf, RVU_VF_INT, BIT_ULL(0)); +	mbox_data = otx2_read64(vf, RVU_VF_VFPF_MBOX0); +  	/* Read latest mbox data */  	smp_rmb(); -	/* Check for PF => VF response messages */ -	mbox = &vf->mbox.mbox; -	mdev = &mbox->dev[0]; -	otx2_sync_mbox_bbuf(mbox, 0); +	if (mbox_data & MBOX_DOWN_MSG) { +		mbox_data &= ~MBOX_DOWN_MSG; +		otx2_write64(vf, RVU_VF_VFPF_MBOX0, mbox_data); + +		/* Check for PF => VF response messages */ +		mbox = &vf->mbox.mbox; +		mdev = &mbox->dev[0]; +		otx2_sync_mbox_bbuf(mbox, 0); -	trace_otx2_msg_interrupt(mbox->pdev, "PF to VF", BIT_ULL(0)); +		hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +		if (hdr->num_msgs) +			queue_work(vf->mbox_wq, &vf->mbox.mbox_wrk); -	hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); -	if (hdr->num_msgs) { -		vf->mbox.num_msgs = hdr->num_msgs; -		hdr->num_msgs = 0; -		memset(mbox->hwbase + mbox->rx_start, 0, -		       ALIGN(sizeof(struct mbox_hdr), sizeof(u64))); -		queue_work(vf->mbox_wq, &vf->mbox.mbox_wrk); +		trace_otx2_msg_interrupt(mbox->pdev, "DOWN reply from PF to VF", +					 BIT_ULL(0));  	} -	/* Check for PF => VF notification messages */ -	mbox = &vf->mbox.mbox_up; -	mdev = &mbox->dev[0]; -	otx2_sync_mbox_bbuf(mbox, 0); -	hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); -	if (hdr->num_msgs) { -		vf->mbox.up_num_msgs = hdr->num_msgs; -		hdr->num_msgs = 0; -		memset(mbox->hwbase + mbox->rx_start, 0, -		       ALIGN(sizeof(struct mbox_hdr), sizeof(u64))); -		queue_work(vf->mbox_wq, &vf->mbox.mbox_up_wrk); +	if (mbox_data & MBOX_UP_MSG) { +		mbox_data &= ~MBOX_UP_MSG; +		otx2_write64(vf, RVU_VF_VFPF_MBOX0, mbox_data); + +		/* Check for PF => VF notification messages */ +		mbox = &vf->mbox.mbox_up; +		mdev = &mbox->dev[0]; +		otx2_sync_mbox_bbuf(mbox, 0); + +		hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); +		if (hdr->num_msgs) +			queue_work(vf->mbox_wq, &vf->mbox.mbox_up_wrk); + +		trace_otx2_msg_interrupt(mbox->pdev, "UP message from PF to VF", +					 BIT_ULL(0));  	}  	return IRQ_HANDLED; @@ -760,8 +775,8 @@ static void otx2vf_remove(struct pci_dev *pdev)  	otx2_mcam_flow_del(vf);  	otx2_shutdown_tc(vf);  	otx2_shutdown_qos(vf); -	otx2vf_disable_mbox_intr(vf);  	otx2_detach_resources(&vf->mbox); +	otx2vf_disable_mbox_intr(vf);  	free_percpu(vf->hw.lmt_info);  	if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))  		qmem_free(vf->dev, vf->dync_lmt); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index de123350bd46..caa13b9cedff 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -677,8 +677,7 @@ static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,  	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));  	mcr_new = mcr_cur;  	mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | -		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK | -		   MAC_MCR_RX_FIFO_CLR_DIS; +		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_RX_FIFO_CLR_DIS;  	/* Only update control register when needed! */  	if (mcr_new != mcr_cur) @@ -694,7 +693,7 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,  					   phylink_config);  	u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -	mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); +	mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK);  	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));  } @@ -803,7 +802,7 @@ static void mtk_mac_link_up(struct phylink_config *config,  	if (rx_pause)  		mcr |= MAC_MCR_FORCE_RX_FC; -	mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN; +	mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK;  	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));  } diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index b2a5d9c3733d..6ce0db3a1a92 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -994,7 +994,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe)  			 MTK_PPE_KEEPALIVE_DISABLE) |  	      FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) |  	      FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, -			 MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | +			 MTK_PPE_SCAN_MODE_CHECK_AGE) |  	      FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM,  			 MTK_PPE_ENTRIES_SHIFT);  	if (mtk_is_netsys_v2_or_greater(ppe->eth)) @@ -1090,17 +1090,21 @@ int mtk_ppe_stop(struct mtk_ppe *ppe)  	mtk_ppe_cache_enable(ppe, false); -	/* disable offload engine */ -	ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); -	ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); -  	/* disable aging */  	val = MTK_PPE_TB_CFG_AGE_NON_L4 |  	      MTK_PPE_TB_CFG_AGE_UNBIND |  	      MTK_PPE_TB_CFG_AGE_TCP |  	      MTK_PPE_TB_CFG_AGE_UDP | -	      MTK_PPE_TB_CFG_AGE_TCP_FIN; +	      MTK_PPE_TB_CFG_AGE_TCP_FIN | +		  MTK_PPE_TB_CFG_SCAN_MODE;  	ppe_clear(ppe, MTK_PPE_TB_CFG, val); -	return mtk_ppe_wait_busy(ppe); +	if (mtk_ppe_wait_busy(ppe)) +		return -ETIMEDOUT; + +	/* disable offload engine */ +	ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); +	ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); + +	return 0;  } diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 93295916b1d2..5b5d5e4310d1 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -571,7 +571,7 @@ static int txgbe_clock_register(struct txgbe *txgbe)  	char clk_name[32];  	struct clk *clk; -	snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", +	snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d",  		 pci_dev_id(pdev));  	clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8297ef681bf5..6c6ec9475709 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2831,8 +2831,8 @@ EXPORT_SYMBOL(genphy_resume);  int genphy_loopback(struct phy_device *phydev, bool enable)  {  	if (enable) { -		u16 val, ctl = BMCR_LOOPBACK; -		int ret; +		u16 ctl = BMCR_LOOPBACK; +		int ret, val;  		ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 13d902462d8e..bcdfbf61eb66 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1464,8 +1464,6 @@ static netdev_features_t veth_fix_features(struct net_device *dev,  		if (peer_priv->_xdp_prog)  			features &= ~NETIF_F_GSO_SOFTWARE;  	} -	if (priv->_xdp_prog) -		features |= NETIF_F_GRO;  	return features;  } @@ -1569,14 +1567,6 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,  		}  		if (!old_prog) { -			if (!veth_gro_requested(dev)) { -				/* user-space did not require GRO, but adding -				 * XDP is supposed to get GRO working -				 */ -				dev->features |= NETIF_F_GRO; -				netdev_features_change(dev); -			} -  			peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;  			peer->max_mtu = max_mtu;  		} @@ -1592,14 +1582,6 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,  			if (dev->flags & IFF_UP)  				veth_disable_xdp(dev); -			/* if user-space did not require GRO, since adding XDP -			 * enabled it, clear it now -			 */ -			if (!veth_gro_requested(dev)) { -				dev->features &= ~NETIF_F_GRO; -				netdev_features_change(dev); -			} -  			if (peer) {  				peer->hw_features |= NETIF_F_GSO_SOFTWARE;  				peer->max_mtu = ETH_MAX_MTU; diff --git a/drivers/net/vmxnet3/vmxnet3_xdp.c b/drivers/net/vmxnet3/vmxnet3_xdp.c index 80ddaff759d4..a6c787454a1a 100644 --- a/drivers/net/vmxnet3/vmxnet3_xdp.c +++ b/drivers/net/vmxnet3/vmxnet3_xdp.c @@ -382,12 +382,12 @@ vmxnet3_process_xdp(struct vmxnet3_adapter *adapter,  	page = rbi->page;  	dma_sync_single_for_cpu(&adapter->pdev->dev,  				page_pool_get_dma_addr(page) + -				rq->page_pool->p.offset, rcd->len, +				rq->page_pool->p.offset, rbi->len,  				page_pool_get_dma_dir(rq->page_pool)); -	xdp_init_buff(&xdp, rbi->len, &rq->xdp_rxq); +	xdp_init_buff(&xdp, PAGE_SIZE, &rq->xdp_rxq);  	xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, -			 rcd->len, false); +			 rbi->len, false);  	xdp_buff_clear_frags_flag(&xdp);  	xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 960371df470a..f69b1f579a0c 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -780,7 +780,7 @@ static const struct of_device_id qmc_hdlc_id_table[] = {  	{ .compatible = "fsl,qmc-hdlc" },  	{} /* sentinel */  }; -MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); +MODULE_DEVICE_TABLE(of, qmc_hdlc_id_table);  static struct platform_driver qmc_hdlc_driver = {  	.driver = { diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index deb9636b0ecf..3feb36ee5bfb 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -237,7 +237,6 @@ static const struct net_device_ops netdev_ops = {  	.ndo_open		= wg_open,  	.ndo_stop		= wg_stop,  	.ndo_start_xmit		= wg_xmit, -	.ndo_get_stats64	= dev_get_tstats64  };  static void wg_destruct(struct net_device *dev) @@ -262,7 +261,6 @@ static void wg_destruct(struct net_device *dev)  	rcu_barrier(); /* Wait for all the peers to be actually freed. */  	wg_ratelimiter_uninit();  	memzero_explicit(&wg->static_identity, sizeof(wg->static_identity)); -	free_percpu(dev->tstats);  	kvfree(wg->index_hashtable);  	kvfree(wg->peer_hashtable);  	mutex_unlock(&wg->device_update_lock); @@ -297,6 +295,7 @@ static void wg_setup(struct net_device *dev)  	dev->hw_enc_features |= WG_NETDEV_FEATURES;  	dev->mtu = ETH_DATA_LEN - overhead;  	dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead; +	dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;  	SET_NETDEV_DEVTYPE(dev, &device_type); @@ -331,14 +330,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,  	if (!wg->index_hashtable)  		goto err_free_peer_hashtable; -	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); -	if (!dev->tstats) -		goto err_free_index_hashtable; -  	wg->handshake_receive_wq = alloc_workqueue("wg-kex-%s",  			WQ_CPU_INTENSIVE | WQ_FREEZABLE, 0, dev->name);  	if (!wg->handshake_receive_wq) -		goto err_free_tstats; +		goto err_free_index_hashtable;  	wg->handshake_send_wq = alloc_workqueue("wg-kex-%s",  			WQ_UNBOUND | WQ_FREEZABLE, 0, dev->name); @@ -397,8 +392,6 @@ err_destroy_handshake_send:  	destroy_workqueue(wg->handshake_send_wq);  err_destroy_handshake_receive:  	destroy_workqueue(wg->handshake_receive_wq); -err_free_tstats: -	free_percpu(dev->tstats);  err_free_index_hashtable:  	kvfree(wg->index_hashtable);  err_free_peer_hashtable: diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index e220d761b1f2..f7055180ba4a 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -164,8 +164,8 @@ get_peer(struct wg_peer *peer, struct sk_buff *skb, struct dump_ctx *ctx)  	if (!allowedips_node)  		goto no_allowedips;  	if (!ctx->allowedips_seq) -		ctx->allowedips_seq = peer->device->peer_allowedips.seq; -	else if (ctx->allowedips_seq != peer->device->peer_allowedips.seq) +		ctx->allowedips_seq = ctx->wg->peer_allowedips.seq; +	else if (ctx->allowedips_seq != ctx->wg->peer_allowedips.seq)  		goto no_allowedips;  	allowedips_nest = nla_nest_start(skb, WGPEER_A_ALLOWEDIPS); @@ -255,17 +255,17 @@ static int wg_get_device_dump(struct sk_buff *skb, struct netlink_callback *cb)  	if (!peers_nest)  		goto out;  	ret = 0; -	/* If the last cursor was removed via list_del_init in peer_remove, then +	lockdep_assert_held(&wg->device_update_lock); +	/* If the last cursor was removed in peer_remove or peer_remove_all, then  	 * we just treat this the same as there being no more peers left. The  	 * reason is that seq_nr should indicate to userspace that this isn't a  	 * coherent dump anyway, so they'll try again.  	 */  	if (list_empty(&wg->peer_list) || -	    (ctx->next_peer && list_empty(&ctx->next_peer->peer_list))) { +	    (ctx->next_peer && ctx->next_peer->is_dead)) {  		nla_nest_cancel(skb, peers_nest);  		goto out;  	} -	lockdep_assert_held(&wg->device_update_lock);  	peer = list_prepare_entry(ctx->next_peer, &wg->peer_list, peer_list);  	list_for_each_entry_continue(peer, &wg->peer_list, peer_list) {  		if (get_peer(peer, skb, ctx)) { diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c index df275b4fccb6..eb8851113654 100644 --- a/drivers/net/wireguard/receive.c +++ b/drivers/net/wireguard/receive.c @@ -251,7 +251,7 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)  	if (unlikely(!READ_ONCE(keypair->receiving.is_valid) ||  		  wg_birthdate_has_expired(keypair->receiving.birthdate, REJECT_AFTER_TIME) || -		  keypair->receiving_counter.counter >= REJECT_AFTER_MESSAGES)) { +		  READ_ONCE(keypair->receiving_counter.counter) >= REJECT_AFTER_MESSAGES)) {  		WRITE_ONCE(keypair->receiving.is_valid, false);  		return false;  	} @@ -318,7 +318,7 @@ static bool counter_validate(struct noise_replay_counter *counter, u64 their_cou  		for (i = 1; i <= top; ++i)  			counter->backtrack[(i + index_current) &  				((COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1)] = 0; -		counter->counter = their_counter; +		WRITE_ONCE(counter->counter, their_counter);  	}  	index &= (COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1; @@ -463,7 +463,7 @@ int wg_packet_rx_poll(struct napi_struct *napi, int budget)  			net_dbg_ratelimited("%s: Packet has invalid nonce %llu (max %llu)\n",  					    peer->device->dev->name,  					    PACKET_CB(skb)->nonce, -					    keypair->receiving_counter.counter); +					    READ_ONCE(keypair->receiving_counter.counter));  			goto next;  		} diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 739e4eee6b75..7e9074519ad2 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -991,7 +991,7 @@ struct qman_portal {  	/* linked-list of CSCN handlers. */  	struct list_head cgr_cbs;  	/* list lock */ -	spinlock_t cgr_lock; +	raw_spinlock_t cgr_lock;  	struct work_struct congestion_work;  	struct work_struct mr_work;  	char irqname[MAX_IRQNAME]; @@ -1281,7 +1281,7 @@ static int qman_create_portal(struct qman_portal *portal,  		/* if the given mask is NULL, assume all CGRs can be seen */  		qman_cgrs_fill(&portal->cgrs[0]);  	INIT_LIST_HEAD(&portal->cgr_cbs); -	spin_lock_init(&portal->cgr_lock); +	raw_spin_lock_init(&portal->cgr_lock);  	INIT_WORK(&portal->congestion_work, qm_congestion_task);  	INIT_WORK(&portal->mr_work, qm_mr_process_task);  	portal->bits = 0; @@ -1456,11 +1456,14 @@ static void qm_congestion_task(struct work_struct *work)  	union qm_mc_result *mcr;  	struct qman_cgr *cgr; -	spin_lock(&p->cgr_lock); +	/* +	 * FIXME: QM_MCR_TIMEOUT is 10ms, which is too long for a raw spinlock! +	 */ +	raw_spin_lock_irq(&p->cgr_lock);  	qm_mc_start(&p->p);  	qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION);  	if (!qm_mc_result_timeout(&p->p, &mcr)) { -		spin_unlock(&p->cgr_lock); +		raw_spin_unlock_irq(&p->cgr_lock);  		dev_crit(p->config->dev, "QUERYCONGESTION timeout\n");  		qman_p_irqsource_add(p, QM_PIRQ_CSCI);  		return; @@ -1476,7 +1479,7 @@ static void qm_congestion_task(struct work_struct *work)  	list_for_each_entry(cgr, &p->cgr_cbs, node)  		if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid))  			cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid)); -	spin_unlock(&p->cgr_lock); +	raw_spin_unlock_irq(&p->cgr_lock);  	qman_p_irqsource_add(p, QM_PIRQ_CSCI);  } @@ -2440,7 +2443,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags,  	preempt_enable();  	cgr->chan = p->config->channel; -	spin_lock(&p->cgr_lock); +	raw_spin_lock_irq(&p->cgr_lock);  	if (opts) {  		struct qm_mcc_initcgr local_opts = *opts; @@ -2477,7 +2480,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags,  	    qman_cgrs_get(&p->cgrs[1], cgr->cgrid))  		cgr->cb(p, cgr, 1);  out: -	spin_unlock(&p->cgr_lock); +	raw_spin_unlock_irq(&p->cgr_lock);  	put_affine_portal();  	return ret;  } @@ -2512,7 +2515,7 @@ int qman_delete_cgr(struct qman_cgr *cgr)  		return -EINVAL;  	memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); -	spin_lock_irqsave(&p->cgr_lock, irqflags); +	raw_spin_lock_irqsave(&p->cgr_lock, irqflags);  	list_del(&cgr->node);  	/*  	 * If there are no other CGR objects for this CGRID in the list, @@ -2537,7 +2540,7 @@ int qman_delete_cgr(struct qman_cgr *cgr)  		/* add back to the list */  		list_add(&cgr->node, &p->cgr_cbs);  release_lock: -	spin_unlock_irqrestore(&p->cgr_lock, irqflags); +	raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags);  	put_affine_portal();  	return ret;  } @@ -2577,9 +2580,9 @@ static int qman_update_cgr(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts)  	if (!p)  		return -EINVAL; -	spin_lock_irqsave(&p->cgr_lock, irqflags); +	raw_spin_lock_irqsave(&p->cgr_lock, irqflags);  	ret = qm_modify_cgr(cgr, 0, opts); -	spin_unlock_irqrestore(&p->cgr_lock, irqflags); +	raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags);  	put_affine_portal();  	return ret;  } diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index fb3a9c93ac86..aa4096126553 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -522,17 +522,18 @@ static inline void bitmap_replace(unsigned long *dst,   *   * (Bits 0, 1, 2, 3, 4, 5 are copied to the bits 0, 1, 4, 8, 9, 12)   * - * A more 'visual' description of the operation: - * src:  0000000001011010 - *                 |||||| - *          +------+||||| - *          |  +----+|||| - *          |  |+----+||| - *          |  ||   +-+|| - *          |  ||   |  || - * mask: ...v..vv...v..vv - *       ...0..11...0..10 - * dst:  0000001100000010 + * A more 'visual' description of the operation:: + * + *	src:  0000000001011010 + *	                |||||| + *	         +------+||||| + *	         |  +----+|||| + *	         |  |+----+||| + *	         |  ||   +-+|| + *	         |  ||   |  || + *	mask: ...v..vv...v..vv + *	      ...0..11...0..10 + *	dst:  0000001100000010   *   * A relationship exists between bitmap_scatter() and bitmap_gather().   * bitmap_gather() can be seen as the 'reverse' bitmap_scatter() operation. @@ -568,16 +569,17 @@ static inline void bitmap_scatter(unsigned long *dst, const unsigned long *src,   *   * (Bits 0, 1, 4, 8, 9, 12 are copied to the bits 0, 1, 2, 3, 4, 5)   * - * A more 'visual' description of the operation: - * mask: ...v..vv...v..vv - * src:  0000001100000010 - *          ^  ^^   ^   0 - *          |  ||   |  10 - *          |  ||   > 010 - *          |  |+--> 1010 - *          |  +--> 11010 - *          +----> 011010 - * dst:  0000000000011010 + * A more 'visual' description of the operation:: + * + *	mask: ...v..vv...v..vv + *	src:  0000001100000010 + *	         ^  ^^   ^   0 + *	         |  ||   |  10 + *	         |  ||   > 010 + *	         |  |+--> 1010 + *	         |  +--> 11010 + *	         +----> 011010 + *	dst:  0000000000011010   *   * A relationship exists between bitmap_gather() and bitmap_scatter(). See   * bitmap_scatter() for the bitmap scatter detailed operations. diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c6f6ac779b34..cb37817d6382 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2072,6 +2072,7 @@ struct net_device {  		struct pcpu_sw_netstats __percpu	*tstats;  		struct pcpu_dstats __percpu		*dstats;  	}; +	unsigned long		state;  	unsigned int		flags;  	unsigned short		hard_header_len;  	netdev_features_t	features; @@ -2117,7 +2118,6 @@ struct net_device {  	 *	part of the usual set specified in Space.c.  	 */ -	unsigned long		state;  	struct list_head	dev_list;  	struct list_head	napi_list; diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 16f519914415..17d7ed5f3ae6 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -247,6 +247,37 @@ do { \  	cond_resched(); \  } while (0) +/** + * rcu_softirq_qs_periodic - Report RCU and RCU-Tasks quiescent states + * @old_ts: jiffies at start of processing. + * + * This helper is for long-running softirq handlers, such as NAPI threads in + * networking. The caller should initialize the variable passed in as @old_ts + * at the beginning of the softirq handler. When invoked frequently, this macro + * will invoke rcu_softirq_qs() every 100 milliseconds thereafter, which will + * provide both RCU and RCU-Tasks quiescent states. Note that this macro + * modifies its old_ts argument. + * + * Because regions of code that have disabled softirq act as RCU read-side + * critical sections, this macro should be invoked with softirq (and + * preemption) enabled. + * + * The macro is not needed when CONFIG_PREEMPT_RT is defined. RT kernels would + * have more chance to invoke schedule() calls and provide necessary quiescent + * states. As a contrast, calling cond_resched() only won't achieve the same + * effect because cond_resched() does not provide RCU-Tasks quiescent states. + */ +#define rcu_softirq_qs_periodic(old_ts) \ +do { \ +	if (!IS_ENABLED(CONFIG_PREEMPT_RT) && \ +	    time_after(jiffies, (old_ts) + HZ / 10)) { \ +		preempt_disable(); \ +		rcu_softirq_qs(); \ +		preempt_enable(); \ +		(old_ts) = jiffies; \ +	} \ +} while (0) +  /*   * Infrastructure to implement the synchronize_() primitives in   * TREE_RCU and rcu_barrier_() primitives in TINY_RCU. diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 3023bc2be6a1..0c7c67b3a87b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -822,9 +822,9 @@ typedef unsigned char *sk_buff_data_t;   *	@decrypted: Decrypted SKB   *	@slow_gro: state present at GRO time, slower prepare step required   *	@mono_delivery_time: When set, skb->tstamp has the - *		delivery_time in mono clock base (i.e., EDT) or a clock base chosen - *		by SO_TXTIME. If zero, skb->tstamp has the (rcv) timestamp at - *		ingress. + *		delivery_time in mono clock base (i.e. EDT).  Otherwise, the + *		skb->tstamp has the (rcv) timestamp at ingress and + *		delivery_time at egress.   *	@napi_id: id of the NAPI struct this skb came from   *	@sender_cpu: (aka @napi_id) source CPU in XPS   *	@alloc_cpu: CPU which did the skb allocation. @@ -3524,6 +3524,16 @@ int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,  bool napi_pp_put_page(struct page *page, bool napi_safe);  static inline void +skb_page_unref(const struct sk_buff *skb, struct page *page, bool napi_safe) +{ +#ifdef CONFIG_PAGE_POOL +	if (skb->pp_recycle && napi_pp_put_page(page, napi_safe)) +		return; +#endif +	put_page(page); +} + +static inline void  napi_frag_unref(skb_frag_t *frag, bool recycle, bool napi_safe)  {  	struct page *page = skb_frag_page(frag); diff --git a/include/linux/socket.h b/include/linux/socket.h index cfcb7e2c3813..139c330ccf2c 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -422,13 +422,6 @@ extern long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,  			       struct user_msghdr __user *umsg,  			       struct sockaddr __user *uaddr,  			       unsigned int flags); -extern int sendmsg_copy_msghdr(struct msghdr *msg, -			       struct user_msghdr __user *umsg, unsigned flags, -			       struct iovec **iov); -extern int recvmsg_copy_msghdr(struct msghdr *msg, -			       struct user_msghdr __user *umsg, unsigned flags, -			       struct sockaddr __user **uaddr, -			       struct iovec **iov);  extern int __copy_msghdr(struct msghdr *kmsg,  			 struct user_msghdr *umsg,  			 struct sockaddr __user **save_addr); diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 8839133d6f6b..004e651e6067 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -61,7 +61,11 @@ struct request_sock {  	struct request_sock		*dl_next;  	u16				mss;  	u8				num_retrans; /* number of retransmits */ -	u8				syncookie:1; /* syncookie: encode tcpopts in timestamp */ +	u8				syncookie:1; /* True if +						      * 1) tcpopts needs to be encoded in +						      *    TS of SYN+ACK +						      * 2) ACK is validated by BPF kfunc. +						      */  	u8				num_timeout:7; /* number of timeouts */  	u32				ts_recent;  	struct timer_list		rsk_timer; @@ -144,6 +148,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,  	sk_node_init(&req_to_sk(req)->sk_node);  	sk_tx_queue_clear(req_to_sk(req));  	req->saved_syn = NULL; +	req->syncookie = 0;  	req->timeout = 0;  	req->num_timeout = 0;  	req->num_retrans = 0; diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index 9ee8da477465..a8e34416e960 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c @@ -263,6 +263,7 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,  static int cpu_map_kthread_run(void *data)  {  	struct bpf_cpu_map_entry *rcpu = data; +	unsigned long last_qs = jiffies;  	complete(&rcpu->kthread_running);  	set_current_state(TASK_INTERRUPTIBLE); @@ -288,10 +289,12 @@ static int cpu_map_kthread_run(void *data)  			if (__ptr_ring_empty(rcpu->queue)) {  				schedule();  				sched = 1; +				last_qs = jiffies;  			} else {  				__set_current_state(TASK_RUNNING);  			}  		} else { +			rcu_softirq_qs_periodic(last_qs);  			sched = cond_resched();  		} diff --git a/net/core/dev.c b/net/core/dev.c index 0766a245816b..9a67003e49db 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2245,7 +2245,7 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)  	rcu_read_lock();  again:  	list_for_each_entry_rcu(ptype, ptype_list, list) { -		if (ptype->ignore_outgoing) +		if (READ_ONCE(ptype->ignore_outgoing))  			continue;  		/* Never send packets back to the socket @@ -6743,6 +6743,8 @@ static int napi_threaded_poll(void *data)  	void *have;  	while (!napi_thread_wait(napi)) { +		unsigned long last_qs = jiffies; +  		for (;;) {  			bool repoll = false; @@ -6767,6 +6769,7 @@ static int napi_threaded_poll(void *data)  			if (!repoll)  				break; +			rcu_softirq_qs_periodic(last_qs);  			cond_resched();  		}  	} @@ -11665,11 +11668,12 @@ static void __init net_dev_struct_check(void)  	/* TXRX read-mostly hotpath */  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, lstats); +	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, state);  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, flags);  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, hard_header_len);  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, features);  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, ip6_ptr); -	CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 38); +	CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 46);  	/* RX read-mostly hotpath */  	CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, ptype_specific); diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c index 499885c8b9ca..593605c1b1ef 100644 --- a/net/devlink/netlink.c +++ b/net/devlink/netlink.c @@ -193,12 +193,13 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,  	devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);  	devlinks_xa_for_each_registered_get(net, index, devlink) { -		devl_dev_lock(devlink, dev_lock); -		if (devl_is_registered(devlink) && -		    strcmp(devlink->dev->bus->name, busname) == 0 && -		    strcmp(dev_name(devlink->dev), devname) == 0) -			return devlink; -		devl_dev_unlock(devlink, dev_lock); +		if (strcmp(devlink->dev->bus->name, busname) == 0 && +		    strcmp(dev_name(devlink->dev), devname) == 0) { +			devl_dev_lock(devlink, dev_lock); +			if (devl_is_registered(devlink)) +				return devlink; +			devl_dev_unlock(devlink, dev_lock); +		}  		devlink_put(devlink);  	} diff --git a/net/devlink/port.c b/net/devlink/port.c index 4b2d46ccfe48..118d130d2afd 100644 --- a/net/devlink/port.c +++ b/net/devlink/port.c @@ -889,7 +889,7 @@ int devlink_nl_port_new_doit(struct sk_buff *skb, struct genl_info *info)  		err = -ENOMEM;  		goto err_out_port_del;  	} -	err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW, +	err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW,  				   info->snd_portid, info->snd_seq, 0, NULL);  	if (WARN_ON_ONCE(err))  		goto err_out_msg_free; diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 6d14d935ee82..26329db09210 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -228,6 +228,10 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,  	 */  	if (ethhdr->h_proto == htons(ETH_P_PRP) ||  	    ethhdr->h_proto == htons(ETH_P_HSR)) { +		/* Check if skb contains hsr_ethhdr */ +		if (skb->mac_len < sizeof(struct hsr_ethhdr)) +			return NULL; +  		/* Use the existing sequence_nr from the tag as starting point  		 * for filtering duplicate frames.  		 */ diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c index cb83c8feb746..9756e657bab9 100644 --- a/net/hsr/hsr_main.c +++ b/net/hsr/hsr_main.c @@ -148,14 +148,21 @@ static struct notifier_block hsr_nb = {  static int __init hsr_init(void)  { -	int res; +	int err;  	BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_HLEN); -	register_netdevice_notifier(&hsr_nb); -	res = hsr_netlink_init(); +	err = register_netdevice_notifier(&hsr_nb); +	if (err) +		return err; + +	err = hsr_netlink_init(); +	if (err) { +		unregister_netdevice_notifier(&hsr_nb); +		return err; +	} -	return res; +	return 0;  }  static void __exit hsr_exit(void) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4dd9e5040672..d33d12421814 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -95,7 +95,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,  			     __alignof__(struct scatterlist));  } -static void esp_ssg_unref(struct xfrm_state *x, void *tmp) +static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)  {  	struct crypto_aead *aead = x->data;  	int extralen = 0; @@ -114,7 +114,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)  	 */  	if (req->src != req->dst)  		for (sg = sg_next(req->src); sg; sg = sg_next(sg)) -			put_page(sg_page(sg)); +			skb_page_unref(skb, sg_page(sg), false);  }  #ifdef CONFIG_INET_ESPINTCP @@ -260,7 +260,7 @@ static void esp_output_done(void *data, int err)  	}  	tmp = ESP_SKB_CB(skb)->tmp; -	esp_ssg_unref(x, tmp); +	esp_ssg_unref(x, tmp, skb);  	kfree(tmp);  	if (xo && (xo->flags & XFRM_DEV_RESUME)) { @@ -639,7 +639,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *  	}  	if (sg != dsg) -		esp_ssg_unref(x, tmp); +		esp_ssg_unref(x, tmp, skb);  	if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)  		err = esp_output_tail_tcp(x, skb); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 7498af320164..cf88eca5f1b4 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -1135,7 +1135,7 @@ error:  		sock_prot_inuse_add(net, sk->sk_prot, -1);  		spin_lock(lock); -		sk_nulls_del_node_init_rcu(sk); +		__sk_nulls_del_node_init_rcu(sk);  		spin_unlock(lock);  		sk->sk_hash = 0; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 5befa4de5b24..e8de45d34d56 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -263,12 +263,12 @@ void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo, bool rearm)  }  EXPORT_SYMBOL_GPL(__inet_twsk_schedule); +/* Remove all non full sockets (TIME_WAIT and NEW_SYN_RECV) for dead netns */  void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family)  { -	struct inet_timewait_sock *tw; -	struct sock *sk;  	struct hlist_nulls_node *node;  	unsigned int slot; +	struct sock *sk;  	for (slot = 0; slot <= hashinfo->ehash_mask; slot++) {  		struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; @@ -277,38 +277,35 @@ restart_rcu:  		rcu_read_lock();  restart:  		sk_nulls_for_each_rcu(sk, node, &head->chain) { -			if (sk->sk_state != TCP_TIME_WAIT) { -				/* A kernel listener socket might not hold refcnt for net, -				 * so reqsk_timer_handler() could be fired after net is -				 * freed.  Userspace listener and reqsk never exist here. -				 */ -				if (unlikely(sk->sk_state == TCP_NEW_SYN_RECV && -					     hashinfo->pernet)) { -					struct request_sock *req = inet_reqsk(sk); - -					inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, req); -				} +			int state = inet_sk_state_load(sk); +			if ((1 << state) & ~(TCPF_TIME_WAIT | +					     TCPF_NEW_SYN_RECV))  				continue; -			} -			tw = inet_twsk(sk); -			if ((tw->tw_family != family) || -				refcount_read(&twsk_net(tw)->ns.count)) +			if (sk->sk_family != family || +			    refcount_read(&sock_net(sk)->ns.count))  				continue; -			if (unlikely(!refcount_inc_not_zero(&tw->tw_refcnt))) +			if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))  				continue; -			if (unlikely((tw->tw_family != family) || -				     refcount_read(&twsk_net(tw)->ns.count))) { -				inet_twsk_put(tw); +			if (unlikely(sk->sk_family != family || +				     refcount_read(&sock_net(sk)->ns.count))) { +				sock_gen_put(sk);  				goto restart;  			}  			rcu_read_unlock();  			local_bh_disable(); -			inet_twsk_deschedule_put(tw); +			if (state == TCP_TIME_WAIT) { +				inet_twsk_deschedule_put(inet_twsk(sk)); +			} else { +				struct request_sock *req = inet_reqsk(sk); + +				inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, +								  req); +			}  			local_bh_enable();  			goto restart_rcu;  		} diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 33f93dc730a3..1fe794967211 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1458,7 +1458,6 @@ struct sk_buff *__ip_make_skb(struct sock *sk,  	skb->priority = (cork->tos != -1) ? cork->priority: READ_ONCE(sk->sk_priority);  	skb->mark = cork->mark;  	skb->tstamp = cork->transmit_time; -	skb->mono_delivery_time = !!skb->tstamp;  	/*  	 * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec  	 * on dst refcount diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 42ac434cfcfa..dcb11f22cbf2 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -357,10 +357,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,  		goto error;  	skb_reserve(skb, hlen); +	skb->protocol = htons(ETH_P_IP);  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = sockc->mark;  	skb->tstamp = sockc->transmit_time; -	skb->mono_delivery_time = !!skb->tstamp;  	skb_dst_set(skb, &rt->dst);  	*rtp = NULL; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 7972ad3d7c73..500f665f98cb 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -474,6 +474,9 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)  				  ireq->wscale_ok, &rcv_wscale,  				  dst_metric(&rt->dst, RTAX_INITRWND)); +	/* req->syncookie is set true only if ACK is validated +	 * by BPF kfunc, then, rcv_wscale is already configured. +	 */  	if (!req->syncookie)  		ireq->rcv_wscale = rcv_wscale;  	ireq->ecn_ok &= cookie_ecn_ok(net, &rt->dst); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 52040b0e2616..f0761f060a83 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -398,10 +398,6 @@ void tcp_twsk_purge(struct list_head *net_exit_list, int family)  			/* Even if tw_refcount == 1, we must clean up kernel reqsk */  			inet_twsk_purge(net->ipv4.tcp_death_row.hashinfo, family);  		} else if (!purged_once) { -			/* The last refcount is decremented in tcp_sk_exit_batch() */ -			if (refcount_read(&net->ipv4.tcp_death_row.tw_refcount) == 1) -				continue; -  			inet_twsk_purge(&tcp_hashinfo, family);  			purged_once = true;  		} diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6e6efe026cdc..7371886d4f9f 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -112,7 +112,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,  			     __alignof__(struct scatterlist));  } -static void esp_ssg_unref(struct xfrm_state *x, void *tmp) +static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)  {  	struct crypto_aead *aead = x->data;  	int extralen = 0; @@ -131,7 +131,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)  	 */  	if (req->src != req->dst)  		for (sg = sg_next(req->src); sg; sg = sg_next(sg)) -			put_page(sg_page(sg)); +			skb_page_unref(skb, sg_page(sg), false);  }  #ifdef CONFIG_INET6_ESPINTCP @@ -294,7 +294,7 @@ static void esp_output_done(void *data, int err)  	}  	tmp = ESP_SKB_CB(skb)->tmp; -	esp_ssg_unref(x, tmp); +	esp_ssg_unref(x, tmp, skb);  	kfree(tmp);  	esp_output_encap_csum(skb); @@ -677,7 +677,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info  	}  	if (sg != dsg) -		esp_ssg_unref(x, tmp); +		esp_ssg_unref(x, tmp, skb);  	if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)  		err = esp_output_tail_tcp(x, skb); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 02eeca5492cd..b9dd3a66e423 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1925,7 +1925,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = cork->base.mark;  	skb->tstamp = cork->base.transmit_time; -	skb->mono_delivery_time = !!skb->tstamp; +  	ip6_cork_steal_dst(skb, cork);  	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);  	if (proto == IPPROTO_ICMPV6) { diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ca49e6617afa..0d896ca7b589 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -622,7 +622,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = sockc->mark;  	skb->tstamp = sockc->transmit_time; -	skb->mono_delivery_time = !!skb->tstamp; +  	skb_put(skb, length);  	skb_reset_network_header(skb);  	iph = ipv6_hdr(skb); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 8bad0a44a0a6..6d8286c299c9 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -258,6 +258,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  				  ireq->wscale_ok, &rcv_wscale,  				  dst_metric(dst, RTAX_INITRWND)); +	/* req->syncookie is set true only if ACK is validated +	 * by BPF kfunc, then, rcv_wscale is already configured. +	 */  	if (!req->syncookie)  		ireq->rcv_wscale = rcv_wscale;  	ireq->ecn_ok &= cookie_ecn_ok(net, dst); diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index e93f905e60b6..5fa3d3540c93 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1213,7 +1213,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)  	if (flags & ~NFT_TABLE_F_MASK)  		return -EOPNOTSUPP; -	if (flags == ctx->table->flags) +	if (flags == (ctx->table->flags & NFT_TABLE_F_MASK))  		return 0;  	if ((nft_table_has_owner(ctx->table) && @@ -2631,19 +2631,6 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,  		}  	} -	if (nla[NFTA_CHAIN_COUNTERS]) { -		if (!nft_is_base_chain(chain)) { -			err = -EOPNOTSUPP; -			goto err_hooks; -		} - -		stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); -		if (IS_ERR(stats)) { -			err = PTR_ERR(stats); -			goto err_hooks; -		} -	} -  	if (!(table->flags & NFT_TABLE_F_DORMANT) &&  	    nft_is_base_chain(chain) &&  	    !list_empty(&hook.list)) { @@ -2658,6 +2645,20 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,  	}  	unregister = true; + +	if (nla[NFTA_CHAIN_COUNTERS]) { +		if (!nft_is_base_chain(chain)) { +			err = -EOPNOTSUPP; +			goto err_hooks; +		} + +		stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); +		if (IS_ERR(stats)) { +			err = PTR_ERR(stats); +			goto err_hooks; +		} +	} +  	err = -ENOMEM;  	trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,  				sizeof(struct nft_trans_chain)); diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index c0ceea068936..df8de5090246 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2329,8 +2329,6 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,  	if (m) {  		rcu_barrier(); -		nft_set_pipapo_match_destroy(ctx, set, m); -  		for_each_possible_cpu(cpu)  			pipapo_free_scratch(m, cpu);  		free_percpu(m->scratch); @@ -2342,8 +2340,7 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,  	if (priv->clone) {  		m = priv->clone; -		if (priv->dirty) -			nft_set_pipapo_match_destroy(ctx, set, m); +		nft_set_pipapo_match_destroy(ctx, set, m);  		for_each_possible_cpu(cpu)  			pipapo_free_scratch(priv->clone, cpu); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 61270826b9ac..18f616f487ea 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2057,7 +2057,7 @@ retry:  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = READ_ONCE(sk->sk_mark);  	skb->tstamp = sockc.transmit_time; -	skb->mono_delivery_time = !!skb->tstamp; +  	skb_setup_tx_timestamp(skb, sockc.tsflags);  	if (unlikely(extra_len == 4)) @@ -2586,7 +2586,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,  	skb->priority = READ_ONCE(po->sk.sk_priority);  	skb->mark = READ_ONCE(po->sk.sk_mark);  	skb->tstamp = sockc->transmit_time; -	skb->mono_delivery_time = !!skb->tstamp;  	skb_setup_tx_timestamp(skb, sockc->tsflags);  	skb_zcopy_set_nouarg(skb, ph.raw); @@ -3065,7 +3064,6 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = sockc.mark;  	skb->tstamp = sockc.transmit_time; -	skb->mono_delivery_time = !!skb->tstamp;  	if (unlikely(extra_len == 4))  		skb->no_fcs = 1; @@ -4000,7 +3998,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,  		if (val < 0 || val > 1)  			return -EINVAL; -		po->prot_hook.ignore_outgoing = !!val; +		WRITE_ONCE(po->prot_hook.ignore_outgoing, !!val);  		return 0;  	}  	case PACKET_TX_HAS_OFF: @@ -4134,7 +4132,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,  		       0);  		break;  	case PACKET_IGNORE_OUTGOING: -		val = po->prot_hook.ignore_outgoing; +		val = READ_ONCE(po->prot_hook.ignore_outgoing);  		break;  	case PACKET_ROLLOVER_STATS:  		if (!po->rollover) diff --git a/net/rds/send.c b/net/rds/send.c index 2899def23865..09a280110654 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -103,13 +103,12 @@ EXPORT_SYMBOL_GPL(rds_send_path_reset);  static int acquire_in_xmit(struct rds_conn_path *cp)  { -	return test_and_set_bit(RDS_IN_XMIT, &cp->cp_flags) == 0; +	return test_and_set_bit_lock(RDS_IN_XMIT, &cp->cp_flags) == 0;  }  static void release_in_xmit(struct rds_conn_path *cp)  { -	clear_bit(RDS_IN_XMIT, &cp->cp_flags); -	smp_mb__after_atomic(); +	clear_bit_unlock(RDS_IN_XMIT, &cp->cp_flags);  	/*  	 * We don't use wait_on_bit()/wake_up_bit() because our waking is in a  	 * hot path and finding waiters is very rare.  We don't want to walk diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 6f765768c49c..894b8fa68e5e 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -349,8 +349,8 @@ reload:  			 */  			remain = more ? INT_MAX : msg_data_left(msg);  			txb = call->conn->security->alloc_txbuf(call, remain, sk->sk_allocation); -			if (IS_ERR(txb)) { -				ret = PTR_ERR(txb); +			if (!txb) { +				ret = -ENOMEM;  				goto maybe_error;  			}  		} diff --git a/net/rxrpc/txbuf.c b/net/rxrpc/txbuf.c index b2a82ab756c2..e0679658d9de 100644 --- a/net/rxrpc/txbuf.c +++ b/net/rxrpc/txbuf.c @@ -33,8 +33,8 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_  	total = hoff + sizeof(*whdr) + data_size;  	mutex_lock(&call->conn->tx_data_alloc_lock); -	buf = page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp, -				    ~(data_align - 1) & ~(L1_CACHE_BYTES - 1)); +	buf = __page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp, +				      ~(data_align - 1) & ~(L1_CACHE_BYTES - 1));  	mutex_unlock(&call->conn->tx_data_alloc_lock);  	if (!buf) {  		kfree(txb); diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c index 5b595773e59b..358cf304f4c9 100644 --- a/net/sched/sch_fq_pie.c +++ b/net/sched/sch_fq_pie.c @@ -10,6 +10,7 @@   */  #include <linux/jhash.h> +#include <linux/module.h>  #include <linux/sizes.h>  #include <linux/vmalloc.h>  #include <net/pkt_cls.h> @@ -563,6 +564,7 @@ static struct Qdisc_ops fq_pie_qdisc_ops __read_mostly = {  	.dump_stats	= fq_pie_dump_stats,  	.owner		= THIS_MODULE,  }; +MODULE_ALIAS_NET_SCH("fq_pie");  static int __init fq_pie_module_init(void)  { diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index c5de70efdc86..a0d54b422186 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -997,7 +997,8 @@ static const struct nla_policy entry_policy[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = {  };  static const struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = { -	[TCA_TAPRIO_TC_ENTRY_INDEX]	   = { .type = NLA_U32 }, +	[TCA_TAPRIO_TC_ENTRY_INDEX]	   = NLA_POLICY_MAX(NLA_U32, +							    TC_QOPT_MAX_QUEUE),  	[TCA_TAPRIO_TC_ENTRY_MAX_SDU]	   = { .type = NLA_U32 },  	[TCA_TAPRIO_TC_ENTRY_FP]	   = NLA_POLICY_RANGE(NLA_U32,  							      TC_FP_EXPRESS, diff --git a/net/socket.c b/net/socket.c index 7e9c8fc9a5b4..e5f3af49a8b6 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2600,9 +2600,9 @@ out:  	return err;  } -int sendmsg_copy_msghdr(struct msghdr *msg, -			struct user_msghdr __user *umsg, unsigned flags, -			struct iovec **iov) +static int sendmsg_copy_msghdr(struct msghdr *msg, +			       struct user_msghdr __user *umsg, unsigned flags, +			       struct iovec **iov)  {  	int err; @@ -2753,10 +2753,10 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,  	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);  } -int recvmsg_copy_msghdr(struct msghdr *msg, -			struct user_msghdr __user *umsg, unsigned flags, -			struct sockaddr __user **uaddr, -			struct iovec **iov) +static int recvmsg_copy_msghdr(struct msghdr *msg, +			       struct user_msghdr __user *umsg, unsigned flags, +			       struct sockaddr __user **uaddr, +			       struct iovec **iov)  {  	ssize_t err; diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 653e51ae3964..6346690d5c69 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -407,7 +407,8 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)  	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;  	struct net_device *dev = x->xso.dev; -	if (!x->type_offload) +	if (!x->type_offload || +	    (x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED && x->encap))  		return false;  	if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET || diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index 07373c5a7afe..f4e8eb79c1b8 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -20,6 +20,7 @@ CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h)  CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)  CFLAGS_mptcp_pm:=$(call get_hdr_inc,_LINUX_MPTCP_PM_H,mptcp_pm.h)  CFLAGS_netdev:=$(call get_hdr_inc,_LINUX_NETDEV_H,netdev.h) +CFLAGS_nlctrl:=$(call get_hdr_inc,__LINUX_GENERIC_NETLINK_H,genetlink.h)  CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_NETLINK_H,nfsd_netlink.h)  CFLAGS_ovs_datapath:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h)  CFLAGS_ovs_flow:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h) diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h index cfcb7e2c3813..139c330ccf2c 100644 --- a/tools/perf/trace/beauty/include/linux/socket.h +++ b/tools/perf/trace/beauty/include/linux/socket.h @@ -422,13 +422,6 @@ extern long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,  			       struct user_msghdr __user *umsg,  			       struct sockaddr __user *uaddr,  			       unsigned int flags); -extern int sendmsg_copy_msghdr(struct msghdr *msg, -			       struct user_msghdr __user *umsg, unsigned flags, -			       struct iovec **iov); -extern int recvmsg_copy_msghdr(struct msghdr *msg, -			       struct user_msghdr __user *umsg, unsigned flags, -			       struct sockaddr __user **uaddr, -			       struct iovec **iov);  extern int __copy_msghdr(struct msghdr *kmsg,  			 struct user_msghdr *umsg,  			 struct sockaddr __user **save_addr); diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh index a0bb4524e1e9..a603f7b0a08f 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh @@ -354,7 +354,7 @@ __ping_ipv4()  	# Send 100 packets and verify that at least 100 packets hit the rule,  	# to overcome ARP noise. -	PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip +	PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip  	check_err $? "Ping failed"  	tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100 @@ -410,7 +410,7 @@ __ping_ipv6()  	# Send 100 packets and verify that at least 100 packets hit the rule,  	# to overcome neighbor discovery noise. -	PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip +	PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip  	check_err $? "Ping failed"  	tc_check_at_least_x_packets "dev $rp1 egress" 101 100 diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh index d880df89bc8b..e83fde79f40d 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh @@ -457,7 +457,7 @@ __ping_ipv4()  	# Send 100 packets and verify that at least 100 packets hit the rule,  	# to overcome ARP noise. -	PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip +	PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip  	check_err $? "Ping failed"  	tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100 @@ -522,7 +522,7 @@ __ping_ipv6()  	# Send 100 packets and verify that at least 100 packets hit the rule,  	# to overcome neighbor discovery noise. -	PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip +	PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip  	check_err $? "Ping failed"  	tc_check_at_least_x_packets "dev $rp1 egress" 101 100 diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh index 9cd5e885e91f..380cb15e942e 100755 --- a/tools/testing/selftests/net/udpgro_fwd.sh +++ b/tools/testing/selftests/net/udpgro_fwd.sh @@ -217,6 +217,7 @@ for family in 4 6; do  	cleanup  	create_ns +	ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on  	ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on  	run_test "GRO frag list" $BM_NET$DST 1 0  	cleanup @@ -227,6 +228,7 @@ for family in 4 6; do  	# use NAT to circumvent GRO FWD check  	create_ns  	ip -n $NS_DST addr add dev veth$DST $BM_NET$DST_NAT/$SUFFIX +	ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on  	ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on  	ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $BM_NET$DST_NAT \  					-j DNAT --to-destination $BM_NET$DST @@ -240,6 +242,7 @@ for family in 4 6; do  	cleanup  	create_vxlan_pair +	ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on  	ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on  	run_test "GRO frag list over UDP tunnel" $OL_NET$DST 1 1  	cleanup @@ -247,6 +250,7 @@ for family in 4 6; do  	# use NAT to circumvent GRO FWD check  	create_vxlan_pair  	ip -n $NS_DST addr add dev $VXDEV$DST $OL_NET$DST_NAT/$SUFFIX +	ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on  	ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on  	ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $OL_NET$DST_NAT \  					-j DNAT --to-destination $OL_NET$DST diff --git a/tools/testing/selftests/net/veth.sh b/tools/testing/selftests/net/veth.sh index 5ae85def0739..3a394b43e274 100755 --- a/tools/testing/selftests/net/veth.sh +++ b/tools/testing/selftests/net/veth.sh @@ -249,9 +249,9 @@ cleanup  create_ns  ip -n $NS_DST link set dev veth$DST up  ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp -chk_gro_flag "gro vs xdp while down - gro flag on" $DST on +chk_gro_flag "gro vs xdp while down - gro flag off" $DST off  ip -n $NS_DST link set dev veth$DST down -chk_gro_flag "                      - after down" $DST on +chk_gro_flag "                      - after down" $DST off  ip -n $NS_DST link set dev veth$DST xdp off  chk_gro_flag "                      - after xdp off" $DST off  ip -n $NS_DST link set dev veth$DST up @@ -261,6 +261,21 @@ chk_gro_flag "                      - after peer xdp" $DST off  cleanup  create_ns +ip -n $NS_DST link set dev veth$DST up +ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp +ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on +chk_gro_flag "gro vs xdp while down - gro flag on" $DST on +ip -n $NS_DST link set dev veth$DST down +chk_gro_flag "                      - after down" $DST on +ip -n $NS_DST link set dev veth$DST xdp off +chk_gro_flag "                      - after xdp off" $DST on +ip -n $NS_DST link set dev veth$DST up +chk_gro_flag "                      - after up" $DST on +ip -n $NS_SRC link set dev veth$SRC xdp object ${BPF_FILE} section xdp +chk_gro_flag "                      - after peer xdp" $DST on +cleanup + +create_ns  chk_channels "default channels" $DST 1 1  ip -n $NS_DST link set dev veth$DST down @@ -327,11 +342,14 @@ if [ $CPUS -gt 2 ]; then  fi  ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp 2>/dev/null -chk_gro_flag "with xdp attached - gro flag" $DST on +chk_gro_flag "with xdp attached - gro flag" $DST off  chk_gro_flag "        - peer gro flag" $SRC off  chk_tso_flag "        - tso flag" $SRC off  chk_tso_flag "        - peer tso flag" $DST on  ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on +chk_gro "        - no aggregation" 10 +ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on +chk_gro_flag "        - gro flag with GRO on" $DST on  chk_gro "        - aggregation" 1 diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config index 2fc36efb166d..a7f8e8a95625 100644 --- a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config +++ b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config @@ -3,6 +3,7 @@ CONFIG_ARCH_RV32I=y  CONFIG_MMU=y  CONFIG_FPU=y  CONFIG_SOC_VIRT=y +CONFIG_RISCV_ISA_FALLBACK=y  CONFIG_SERIAL_8250=y  CONFIG_SERIAL_8250_CONSOLE=y  CONFIG_SERIAL_OF_PLATFORM=y diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config index dc266f3b1915..daeb3e5e0965 100644 --- a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config +++ b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config @@ -2,6 +2,7 @@ CONFIG_ARCH_RV64I=y  CONFIG_MMU=y  CONFIG_FPU=y  CONFIG_SOC_VIRT=y +CONFIG_RISCV_ISA_FALLBACK=y  CONFIG_SERIAL_8250=y  CONFIG_SERIAL_8250_CONSOLE=y  CONFIG_SERIAL_OF_PLATFORM=y | 
