Commit 85069e95 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller
Browse files

octeontx2-pf: Receive side scaling support



Adds receive side scaling (RSS) support to distribute
pkts/flows across multiple queues. Sets up key, indirection
table etc. Also added extraction of HW calculated rxhash and
adding to same to SKB ie NETIF_F_RXHASH offload support.

Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ff7d148
Loading
Loading
Loading
Loading
+122 −0
Original line number Diff line number Diff line
@@ -106,6 +106,126 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
	return err;
}

static int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
{
	struct otx2_rss_info *rss = &pfvf->hw.rss_info;
	struct nix_rss_flowkey_cfg *req;
	int err;

	otx2_mbox_lock(&pfvf->mbox);
	req = otx2_mbox_alloc_msg_nix_rss_flowkey_cfg(&pfvf->mbox);
	if (!req) {
		otx2_mbox_unlock(&pfvf->mbox);
		return -ENOMEM;
	}
	req->mcam_index = -1; /* Default or reserved index */
	req->flowkey_cfg = rss->flowkey_cfg;
	req->group = DEFAULT_RSS_CONTEXT_GROUP;

	err = otx2_sync_mbox_msg(&pfvf->mbox);
	otx2_mbox_unlock(&pfvf->mbox);
	return err;
}

static int otx2_set_rss_table(struct otx2_nic *pfvf)
{
	struct otx2_rss_info *rss = &pfvf->hw.rss_info;
	struct mbox *mbox = &pfvf->mbox;
	struct nix_aq_enq_req *aq;
	int idx, err;

	otx2_mbox_lock(mbox);
	/* Get memory to put this msg */
	for (idx = 0; idx < rss->rss_size; idx++) {
		aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
		if (!aq) {
			/* The shared memory buffer can be full.
			 * Flush it and retry
			 */
			err = otx2_sync_mbox_msg(mbox);
			if (err) {
				otx2_mbox_unlock(mbox);
				return err;
			}
			aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
			if (!aq) {
				otx2_mbox_unlock(mbox);
				return -ENOMEM;
			}
		}

		aq->rss.rq = rss->ind_tbl[idx];

		/* Fill AQ info */
		aq->qidx = idx;
		aq->ctype = NIX_AQ_CTYPE_RSS;
		aq->op = NIX_AQ_INSTOP_INIT;
	}
	err = otx2_sync_mbox_msg(mbox);
	otx2_mbox_unlock(mbox);
	return err;
}

static void otx2_set_rss_key(struct otx2_nic *pfvf)
{
	struct otx2_rss_info *rss = &pfvf->hw.rss_info;
	u64 *key = (u64 *)&rss->key[4];
	int idx;

	/* 352bit or 44byte key needs to be configured as below
	 * NIX_LF_RX_SECRETX0 = key<351:288>
	 * NIX_LF_RX_SECRETX1 = key<287:224>
	 * NIX_LF_RX_SECRETX2 = key<223:160>
	 * NIX_LF_RX_SECRETX3 = key<159:96>
	 * NIX_LF_RX_SECRETX4 = key<95:32>
	 * NIX_LF_RX_SECRETX5<63:32> = key<31:0>
	 */
	otx2_write64(pfvf, NIX_LF_RX_SECRETX(5),
		     (u64)(*((u32 *)&rss->key)) << 32);
	idx = sizeof(rss->key) / sizeof(u64);
	while (idx > 0) {
		idx--;
		otx2_write64(pfvf, NIX_LF_RX_SECRETX(idx), *key++);
	}
}

int otx2_rss_init(struct otx2_nic *pfvf)
{
	struct otx2_rss_info *rss = &pfvf->hw.rss_info;
	int idx, ret = 0;

	rss->rss_size = sizeof(rss->ind_tbl);

	/* Init RSS key if it is not setup already */
	if (!rss->enable)
		netdev_rss_key_fill(rss->key, sizeof(rss->key));
	otx2_set_rss_key(pfvf);

	if (!netif_is_rxfh_configured(pfvf->netdev)) {
		/* Default indirection table */
		for (idx = 0; idx < rss->rss_size; idx++)
			rss->ind_tbl[idx] =
				ethtool_rxfh_indir_default(idx,
							   pfvf->hw.rx_queues);
	}
	ret = otx2_set_rss_table(pfvf);
	if (ret)
		return ret;

	/* Flowkey or hash config to be used for generating flow tag */
	rss->flowkey_cfg = rss->enable ? rss->flowkey_cfg :
			   NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6 |
			   NIX_FLOW_KEY_TYPE_TCP | NIX_FLOW_KEY_TYPE_UDP |
			   NIX_FLOW_KEY_TYPE_SCTP;

	ret = otx2_set_flowkey_cfg(pfvf);
	if (ret)
		return ret;

	rss->enable = true;
	return 0;
}

void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
{
	/* Configure CQE interrupt coalescing parameters
@@ -608,6 +728,8 @@ int otx2_config_nix(struct otx2_nic *pfvf)
	nixlf->rq_cnt = pfvf->hw.rx_queues;
	nixlf->sq_cnt = pfvf->hw.tx_queues;
	nixlf->cq_cnt = pfvf->qset.cq_cnt;
	nixlf->rss_sz = MAX_RSS_INDIR_TBL_SIZE;
	nixlf->rss_grps = 1; /* Single RSS indir table supported, for now */
	nixlf->xqe_sz = NIX_XQESZ_W16;
	/* We don't know absolute NPA LF idx attached.
	 * AF will replace 'RVU_DEFAULT_PF_FUNC' with
+14 −0
Original line number Diff line number Diff line
@@ -41,6 +41,16 @@ enum arua_mapped_qtypes {
#define NIX_LF_ERR_VEC				0x81
#define NIX_LF_POISON_VEC			0x82

/* RSS configuration */
struct otx2_rss_info {
	u8 enable;
	u32 flowkey_cfg;
	u16 rss_size;
	u8  ind_tbl[MAX_RSS_INDIR_TBL_SIZE];
#define RSS_HASH_KEY_SIZE	44   /* 352 bit key */
	u8  key[RSS_HASH_KEY_SIZE];
};

/* NIX (or NPC) RX errors */
enum otx2_errlvl {
	NPC_ERRLVL_RE,
@@ -95,6 +105,7 @@ struct mbox {

struct otx2_hw {
	struct pci_dev		*pdev;
	struct otx2_rss_info	rss_info;
	u16                     rx_queues;
	u16                     tx_queues;
	u16			max_queues;
@@ -510,6 +521,9 @@ void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);

/* RSS configuration APIs*/
int otx2_rss_init(struct otx2_nic *pfvf);

/* Mbox handlers */
void mbox_handler_msix_offset(struct otx2_nic *pfvf,
			      struct msix_offset_rsp *rsp);
+7 −1
Original line number Diff line number Diff line
@@ -838,6 +838,11 @@ int otx2_open(struct net_device *netdev)
	if (err)
		goto err_disable_napi;

	/* Initialize RSS */
	err = otx2_rss_init(pf);
	if (err)
		goto err_disable_napi;

	/* Register Queue IRQ handlers */
	vec = pf->hw.nix_msixoff + NIX_LF_QINT_VEC_START;
	irq_name = &pf->hw.irq_name[vec * NAME_SIZE];
@@ -1237,7 +1242,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	pf->iommu_domain = iommu_get_domain_for_dev(dev);

	netdev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
			       NETIF_F_IPV6_CSUM | NETIF_F_SG);
			       NETIF_F_IPV6_CSUM | NETIF_F_RXHASH |
			       NETIF_F_SG);
	netdev->features |= netdev->hw_features;

	netdev->hw_features |= NETIF_F_LOOPBACK | NETIF_F_RXALL;
+24 −0
Original line number Diff line number Diff line
@@ -115,6 +115,28 @@ static void otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
			    pfvf->rbsize, DMA_FROM_DEVICE);
}

static void otx2_set_rxhash(struct otx2_nic *pfvf,
			    struct nix_cqe_rx_s *cqe, struct sk_buff *skb)
{
	enum pkt_hash_types hash_type = PKT_HASH_TYPE_NONE;
	struct otx2_rss_info *rss;
	u32 hash = 0;

	if (!(pfvf->netdev->features & NETIF_F_RXHASH))
		return;

	rss = &pfvf->hw.rss_info;
	if (rss->flowkey_cfg) {
		if (rss->flowkey_cfg &
		    ~(NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6))
			hash_type = PKT_HASH_TYPE_L4;
		else
			hash_type = PKT_HASH_TYPE_L3;
		hash = cqe->hdr.flow_tag;
	}
	skb_set_hash(skb, hash, hash_type);
}

static bool otx2_check_rcv_errors(struct otx2_nic *pfvf,
				  struct nix_cqe_rx_s *cqe, int qidx)
{
@@ -194,6 +216,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
	otx2_skb_add_frag(pfvf, skb, cqe->sg.seg_addr, cqe->sg.seg_size);
	cq->pool_ptrs++;

	otx2_set_rxhash(pfvf, cqe, skb);

	skb_record_rx_queue(skb, cq->cq_idx);
	if (pfvf->netdev->features & NETIF_F_RXCSUM)
		skb->ip_summed = CHECKSUM_UNNECESSARY;