Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c1a91f1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlx4-802.1ad-accel'



Amir Vadai says:

====================
net/mlx4_en: Hardware accelerated 802.1ad

This patchset by Hadar introduces support in Hardware accelerated 802.1ad, for
ConnectX-3pro NIC's.  In order to support existing deployment, and due to some
hardware limitations, the feature is disabled by default, and needed to be
enabled using a private flag in ethtool. Ofcourse user can enable the private
flag only if hardware has support.
After being enabled, the standard ethtool -k/-K can be used.

Patchset was applied and tested over commit 71790a27 ("hv_netvsc: Add structs
and handlers for VF messages")
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0b42c286 e38af4fa
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -871,7 +871,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
		if (is_eth) {
			wc->sl  = be16_to_cpu(cqe->sl_vid) >> 13;
			if (be32_to_cpu(cqe->vlan_my_qpn) &
					MLX4_CQE_VLAN_PRESENT_MASK) {
					MLX4_CQE_CVLAN_PRESENT_MASK) {
				wc->vlan_id = be16_to_cpu(cqe->sl_vid) &
					MLX4_CQE_VID_MASK;
			} else {
+33 −18
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)

static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
	"blueflame",
	"phv-bit"
};

static const char main_strings[][ETH_GSTRING_LEN] = {
@@ -1797,13 +1798,15 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = priv->mdev;
	bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
	bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
	bool phv_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_PHV);
	bool phv_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_PHV);
	int i;
	int ret = 0;

	if (bf_enabled_new == bf_enabled_old)
		return 0; /* Nothing to do */

	if (bf_enabled_new != bf_enabled_old) {
		if (bf_enabled_new) {
			bool bf_supported = true;

@@ -1825,7 +1828,19 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)

		en_info(priv, "BlueFlame %s\n",
			bf_enabled_new ?  "Enabled" : "Disabled");
	}

	if (phv_enabled_new != phv_enabled_old) {
		ret = set_phv_bit(mdev->dev, priv->port, (int)phv_enabled_new);
		if (ret)
			return ret;
		else if (phv_enabled_new)
			priv->pflags |= MLX4_EN_PRIV_FLAGS_PHV;
		else
			priv->pflags &= ~MLX4_EN_PRIV_FLAGS_PHV;
		en_info(priv, "PHV bit %s\n",
			phv_enabled_new ?  "Enabled" : "Disabled");
	}
	return 0;
}

+46 −0
Original line number Diff line number Diff line
@@ -2184,6 +2184,25 @@ static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	}
}

static netdev_features_t mlx4_en_fix_features(struct net_device *netdev,
					      netdev_features_t features)
{
	struct mlx4_en_priv *en_priv = netdev_priv(netdev);
	struct mlx4_en_dev *mdev = en_priv->mdev;

	/* Since there is no support for separate RX C-TAG/S-TAG vlan accel
	 * enable/disable make sure S-TAG flag is always in same state as
	 * C-TAG.
	 */
	if (features & NETIF_F_HW_VLAN_CTAG_RX &&
	    !(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
		features |= NETIF_F_HW_VLAN_STAG_RX;
	else
		features &= ~NETIF_F_HW_VLAN_STAG_RX;

	return features;
}

static int mlx4_en_set_features(struct net_device *netdev,
		netdev_features_t features)
{
@@ -2218,6 +2237,10 @@ static int mlx4_en_set_features(struct net_device *netdev,
		en_info(priv, "Turn %s TX vlan strip offload\n",
			(features & NETIF_F_HW_VLAN_CTAG_TX) ? "ON" : "OFF");

	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_STAG_TX))
		en_info(priv, "Turn %s TX S-VLAN strip offload\n",
			(features & NETIF_F_HW_VLAN_STAG_TX) ? "ON" : "OFF");

	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_LOOPBACK)) {
		en_info(priv, "Turn %s loopback\n",
			(features & NETIF_F_LOOPBACK) ? "ON" : "OFF");
@@ -2460,6 +2483,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
	.ndo_poll_controller	= mlx4_en_netpoll,
#endif
	.ndo_set_features	= mlx4_en_set_features,
	.ndo_fix_features	= mlx4_en_fix_features,
	.ndo_setup_tc		= mlx4_en_setup_tc,
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	= mlx4_en_filter_rfs,
@@ -2500,6 +2524,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
	.ndo_poll_controller	= mlx4_en_netpoll,
#endif
	.ndo_set_features	= mlx4_en_set_features,
	.ndo_fix_features	= mlx4_en_fix_features,
	.ndo_setup_tc		= mlx4_en_setup_tc,
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	= mlx4_en_filter_rfs,
@@ -2931,6 +2956,27 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
	dev->hw_features |= NETIF_F_LOOPBACK |
			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;

	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
		dev->features |= NETIF_F_HW_VLAN_STAG_RX |
			NETIF_F_HW_VLAN_STAG_FILTER;
		dev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
	}

	if (mlx4_is_slave(mdev->dev)) {
		int phv;

		err = get_phv_bit(mdev->dev, port, &phv);
		if (!err && phv) {
			dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
			priv->pflags |= MLX4_EN_PRIV_FLAGS_PHV;
		}
	} else {
		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
		    !(mdev->dev->caps.flags2 &
		      MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
			dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
	}

	if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP)
		dev->hw_features |= NETIF_F_RXFCS;

+18 −4
Original line number Diff line number Diff line
@@ -726,7 +726,7 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,

	hw_checksum = csum_unfold((__force __sum16)cqe->checksum);

	if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK) &&
	if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
	    !(dev_features & NETIF_F_HW_VLAN_CTAG_RX)) {
		hw_checksum = get_fixed_vlan_csum(hw_checksum, hdr);
		hdr += sizeof(struct vlan_hdr);
@@ -907,11 +907,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
				gro_skb->csum_level = 1;

			if ((cqe->vlan_my_qpn &
			    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
			    cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK)) &&
			    (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
				u16 vid = be16_to_cpu(cqe->sl_vid);

				__vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid);
			} else if ((be32_to_cpu(cqe->vlan_my_qpn) &
				  MLX4_CQE_SVLAN_PRESENT_MASK) &&
				 (dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
				__vlan_hwaccel_put_tag(gro_skb,
						       htons(ETH_P_8021AD),
						       be16_to_cpu(cqe->sl_vid));
			}

			if (dev->features & NETIF_F_RXHASH)
@@ -970,9 +976,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
					PKT_HASH_TYPE_L3);

		if ((be32_to_cpu(cqe->vlan_my_qpn) &
		    MLX4_CQE_VLAN_PRESENT_MASK) &&
		    MLX4_CQE_CVLAN_PRESENT_MASK) &&
		    (dev->features & NETIF_F_HW_VLAN_CTAG_RX))
			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), be16_to_cpu(cqe->sl_vid));
		else if ((be32_to_cpu(cqe->vlan_my_qpn) &
			  MLX4_CQE_SVLAN_PRESENT_MASK) &&
			 (dev->features & NETIF_F_HW_VLAN_STAG_RX))
			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD),
					       be16_to_cpu(cqe->sl_vid));

		if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
			timestamp = mlx4_en_get_cqe_ts(cqe);
@@ -1070,7 +1081,10 @@ static const int frag_sizes[] = {
void mlx4_en_calc_rx_buf(struct net_device *dev)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN;
	/* VLAN_HLEN is added twice,to support skb vlan tagged with multiple
	 * headers. (For example: ETH_P_8021Q and ETH_P_8021AD).
	 */
	int eff_mtu = dev->mtu + ETH_HLEN + (2 * VLAN_HLEN);
	int buf_size = 0;
	int i = 0;

+9 −4
Original line number Diff line number Diff line
@@ -718,6 +718,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
	u32 index, bf_index;
	__be32 op_own;
	u16 vlan_tag = 0;
	u16 vlan_proto = 0;
	int i_frag;
	int lso_header_size;
	void *fragptr = NULL;
@@ -750,9 +751,10 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
		goto tx_drop;
	}

	if (skb_vlan_tag_present(skb))
	if (skb_vlan_tag_present(skb)) {
		vlan_tag = skb_vlan_tag_get(skb);

		vlan_proto = be16_to_cpu(skb->vlan_proto);
	}

	netdev_txq_bql_enqueue_prefetchw(ring->tx_queue);

@@ -958,8 +960,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
		ring->bf.offset ^= ring->bf.buf_size;
	} else {
		tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
		tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN *
			!!skb_vlan_tag_present(skb);
		if (vlan_proto == ETH_P_8021AD)
			tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN;
		else if (vlan_proto == ETH_P_8021Q)
			tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN;

		tx_desc->ctrl.fence_size = real_size;

		/* Ensure new descriptor hits memory
Loading