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

Commit 47f01db4 authored by Jon Mason's avatar Jon Mason Committed by David S. Miller
Browse files

vxge: enable rxhash



Enable RSS hashing and add ability to pass up the adapter calculated rx
hash up the network stack (if feature is available).  Add the ability to
enable/disable feature via ethtool, which requires that the adapter is
not running at the time.  Other miscellaneous cleanups and fixes
required to get RSS working.

Signed-off-by: default avatarJon Mason <jon.mason@exar.com>
Signed-off-by: default avatarRam Vepa <ram.vepa@exar.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0c6202b3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3204,6 +3204,8 @@ enum vxge_hw_status vxge_hw_vpath_rts_rth_set(
		     VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
		     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
			0, &data0, &data1);
	if (status != VXGE_HW_OK)
		goto exit;

	data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) |
			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3));
+6 −6
Original line number Diff line number Diff line
@@ -1413,12 +1413,12 @@ enum vxge_hw_rth_algoritms {
 * See also: vxge_hw_vpath_rts_rth_set(), vxge_hw_vpath_rts_rth_get().
 */
struct vxge_hw_rth_hash_types {
	u8 hash_type_tcpipv4_en;
	u8 hash_type_ipv4_en;
	u8 hash_type_tcpipv6_en;
	u8 hash_type_ipv6_en;
	u8 hash_type_tcpipv6ex_en;
	u8 hash_type_ipv6ex_en;
	u8 hash_type_tcpipv4_en:1,
	   hash_type_ipv4_en:1,
	   hash_type_tcpipv6_en:1,
	   hash_type_ipv6_en:1,
	   hash_type_tcpipv6ex_en:1,
	   hash_type_ipv6ex_en:1;
};

void vxge_hw_device_debug_set(
+35 −0
Original line number Diff line number Diff line
@@ -1119,6 +1119,40 @@ static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset)
	}
}

static int vxge_set_flags(struct net_device *dev, u32 data)
{
	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
	enum vxge_hw_status status;

	if (data & ~ETH_FLAG_RXHASH)
		return -EOPNOTSUPP;

	if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
		return 0;

	if (netif_running(dev) || (vdev->config.rth_steering == NO_STEERING))
		return -EINVAL;

	vdev->devh->config.rth_en = !!(data & ETH_FLAG_RXHASH);

	/* Enabling RTH requires some of the logic in vxge_device_register and a
	 * vpath reset.  Due to these restrictions, only allow modification
	 * while the interface is down.
	 */
	status = vxge_reset_all_vpaths(vdev);
	if (status != VXGE_HW_OK) {
		vdev->devh->config.rth_en = !vdev->devh->config.rth_en;
		return -EFAULT;
	}

	if (vdev->devh->config.rth_en)
		dev->features |= NETIF_F_RXHASH;
	else
		dev->features &= ~NETIF_F_RXHASH;

	return 0;
}

static const struct ethtool_ops vxge_ethtool_ops = {
	.get_settings		= vxge_ethtool_gset,
	.set_settings		= vxge_ethtool_sset,
@@ -1140,6 +1174,7 @@ static const struct ethtool_ops vxge_ethtool_ops = {
	.phys_id		= vxge_ethtool_idnic,
	.get_sset_count		= vxge_ethtool_get_sset_count,
	.get_ethtool_stats	= vxge_get_ethtool_stats,
	.set_flags		= vxge_set_flags,
};

void vxge_initialize_ethtool_ops(struct net_device *ndev)
+34 −20
Original line number Diff line number Diff line
@@ -513,6 +513,13 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
		else
			skb_checksum_none_assert(skb);

		/* rth_hash_type and rth_it_hit are non-zero regardless of
		 * whether rss is enabled.  Only the rth_value is zero/non-zero
		 * if rss is disabled/enabled, so key off of that.
		 */
		if (ext_info.rth_value)
			skb->rxhash = ext_info.rth_value;

		vxge_rx_complete(ring, skb, ext_info.vlan,
			pkt_length, &ext_info);

@@ -1689,15 +1696,6 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev)
		mtable[index] = index % vdev->no_of_vpath;
	}

	/* Fill RTH hash types */
	hash_types.hash_type_tcpipv4_en   = vdev->config.rth_hash_type_tcpipv4;
	hash_types.hash_type_ipv4_en      = vdev->config.rth_hash_type_ipv4;
	hash_types.hash_type_tcpipv6_en   = vdev->config.rth_hash_type_tcpipv6;
	hash_types.hash_type_ipv6_en      = vdev->config.rth_hash_type_ipv6;
	hash_types.hash_type_tcpipv6ex_en =
					vdev->config.rth_hash_type_tcpipv6ex;
	hash_types.hash_type_ipv6ex_en    = vdev->config.rth_hash_type_ipv6ex;

	/* set indirection table, bucket-to-vpath mapping */
	status = vxge_hw_vpath_rts_rth_itable_set(vdev->vp_handles,
						vdev->no_of_vpath,
@@ -1710,6 +1708,15 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev)
		return status;
	}

	/* Fill RTH hash types */
	hash_types.hash_type_tcpipv4_en   = vdev->config.rth_hash_type_tcpipv4;
	hash_types.hash_type_ipv4_en      = vdev->config.rth_hash_type_ipv4;
	hash_types.hash_type_tcpipv6_en   = vdev->config.rth_hash_type_tcpipv6;
	hash_types.hash_type_ipv6_en      = vdev->config.rth_hash_type_ipv6;
	hash_types.hash_type_tcpipv6ex_en =
					vdev->config.rth_hash_type_tcpipv6ex;
	hash_types.hash_type_ipv6ex_en    = vdev->config.rth_hash_type_ipv6ex;

	/*
	 * Because the itable_set() method uses the active_table field
	 * for the target virtual path the RTH config should be updated
@@ -2598,6 +2605,8 @@ vxge_open(struct net_device *dev)
			goto out2;
		}
	}
	printk(KERN_INFO "%s: Receive Hashing Offload %s\n", dev->name,
	       hldev->config.rth_en ? "enabled" : "disabled");

	for (i = 0; i < vdev->no_of_vpath; i++) {
		vpath = &vdev->vpaths[i];
@@ -3178,6 +3187,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,

	vxge_initialize_ethtool_ops(ndev);

	if (vdev->config.rth_steering != NO_STEERING) {
		ndev->features |= NETIF_F_RXHASH;
		hldev->config.rth_en = VXGE_HW_RTH_ENABLE;
	}

	/* Allocate memory for vpath */
	vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) *
				no_of_vpath, GFP_KERNEL);
@@ -4163,12 +4177,12 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
	ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS;
	ll_config->addr_learn_en = addr_learn_en;
	ll_config->rth_algorithm = RTH_ALG_JENKINS;
	ll_config->rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4;
	ll_config->rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE;
	ll_config->rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE;
	ll_config->rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE;
	ll_config->rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE;
	ll_config->rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE;
	ll_config->rth_hash_type_tcpipv4 = 1;
	ll_config->rth_hash_type_ipv4 = 0;
	ll_config->rth_hash_type_tcpipv6 = 0;
	ll_config->rth_hash_type_ipv6 = 0;
	ll_config->rth_hash_type_tcpipv6ex = 0;
	ll_config->rth_hash_type_ipv6ex = 0;
	ll_config->rth_bkt_sz = RTH_BUCKET_SIZE;
	ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE;
	ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE;
+9 −9
Original line number Diff line number Diff line
@@ -145,15 +145,15 @@ struct vxge_config {

	int		addr_learn_en;

	int		rth_steering;
	int		rth_algorithm;
	int		rth_hash_type_tcpipv4;
	int		rth_hash_type_ipv4;
	int		rth_hash_type_tcpipv6;
	int		rth_hash_type_ipv6;
	int		rth_hash_type_tcpipv6ex;
	int		rth_hash_type_ipv6ex;
	int		rth_bkt_sz;
	u32		rth_steering:2,
			rth_algorithm:2,
			rth_hash_type_tcpipv4:1,
			rth_hash_type_ipv4:1,
			rth_hash_type_tcpipv6:1,
			rth_hash_type_ipv6:1,
			rth_hash_type_tcpipv6ex:1,
			rth_hash_type_ipv6ex:1,
			rth_bkt_sz:8;
	int		rth_jhash_golden_ratio;
	int		tx_steering_type;
	int 	fifo_indicate_max_pkts;
Loading