patches for DPDK stable branches
 help / color / mirror / Atom feed
* [dpdk-stable] [PATCH v2 2/7] net/qede: fix filtering code
       [not found] <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
@ 2016-12-23  0:48 ` Harish Patil
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 5/7] net/qede: fix RSS related issue Harish Patil
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 4+ messages in thread
From: Harish Patil @ 2016-12-23  0:48 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: Harish Patil, dev, stable, Dept-EngDPDKDev

In qede_mac_addr_add() a check is added to differentiate between
unicast/multicast mac to prevent a multicast mac from being wrongly added
to unicast filter table. Secondly, two separate lists will be used to keep
track of unicast/multicast mac filters to prevent duplicate filter
programming. The other change is to remove filter_config from struct
qed_eth_ops_pass and invoke the base APIs directly. This avoids the need
to have multiple structs and function calls.

Fixes: 2ea6f76aff40 ("qede: add core driver")

Signed-off-by: Harish Patil <harish.patil@qlogic.com>
---
 drivers/net/qede/qede_eth_if.c |  101 +-------------
 drivers/net/qede/qede_eth_if.h |   36 +----
 drivers/net/qede/qede_ethdev.c |  303 ++++++++++++++++++++++++++++------------
 drivers/net/qede/qede_ethdev.h |   15 ++
 4 files changed, 230 insertions(+), 225 deletions(-)

diff --git a/drivers/net/qede/qede_eth_if.c b/drivers/net/qede/qede_eth_if.c
index 1ae6127..30fded0 100644
--- a/drivers/net/qede/qede_eth_if.c
+++ b/drivers/net/qede/qede_eth_if.c
@@ -310,86 +310,11 @@ qed_get_vport_stats(struct ecore_dev *edev, struct ecore_eth_stats *stats)
 	ecore_get_vport_stats(edev, stats);
 }
 
-static int
-qed_configure_filter_ucast(struct ecore_dev *edev,
-			   struct qed_filter_ucast_params *params)
-{
-	struct ecore_filter_ucast ucast;
-
-	if (!params->vlan_valid && !params->mac_valid) {
-		DP_NOTICE(edev, true,
-			  "Tried configuring a unicast filter,"
-			  "but both MAC and VLAN are not set\n");
-		return -EINVAL;
-	}
-
-	memset(&ucast, 0, sizeof(ucast));
-	switch (params->type) {
-	case QED_FILTER_XCAST_TYPE_ADD:
-		ucast.opcode = ECORE_FILTER_ADD;
-		break;
-	case QED_FILTER_XCAST_TYPE_DEL:
-		ucast.opcode = ECORE_FILTER_REMOVE;
-		break;
-	case QED_FILTER_XCAST_TYPE_REPLACE:
-		ucast.opcode = ECORE_FILTER_REPLACE;
-		break;
-	default:
-		DP_NOTICE(edev, true, "Unknown unicast filter type %d\n",
-			  params->type);
-	}
-
-	if (params->vlan_valid && params->mac_valid) {
-		ucast.type = ECORE_FILTER_MAC_VLAN;
-		ether_addr_copy((struct ether_addr *)&params->mac,
-				(struct ether_addr *)&ucast.mac);
-		ucast.vlan = params->vlan;
-	} else if (params->mac_valid) {
-		ucast.type = ECORE_FILTER_MAC;
-		ether_addr_copy((struct ether_addr *)&params->mac,
-				(struct ether_addr *)&ucast.mac);
-	} else {
-		ucast.type = ECORE_FILTER_VLAN;
-		ucast.vlan = params->vlan;
-	}
-
-	ucast.is_rx_filter = true;
-	ucast.is_tx_filter = true;
-
-	return ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB, NULL);
-}
-
-static int
-qed_configure_filter_mcast(struct ecore_dev *edev,
-			   struct qed_filter_mcast_params *params)
-{
-	struct ecore_filter_mcast mcast;
-	int i;
-
-	memset(&mcast, 0, sizeof(mcast));
-	switch (params->type) {
-	case QED_FILTER_XCAST_TYPE_ADD:
-		mcast.opcode = ECORE_FILTER_ADD;
-		break;
-	case QED_FILTER_XCAST_TYPE_DEL:
-		mcast.opcode = ECORE_FILTER_REMOVE;
-		break;
-	default:
-		DP_NOTICE(edev, true, "Unknown multicast filter type %d\n",
-			  params->type);
-	}
-
-	mcast.num_mc_addrs = params->num;
-	for (i = 0; i < mcast.num_mc_addrs; i++)
-		ether_addr_copy((struct ether_addr *)&params->mac[i],
-				(struct ether_addr *)&mcast.mac[i]);
-
-	return ecore_filter_mcast_cmd(edev, &mcast, ECORE_SPQ_MODE_CB, NULL);
-}
-
-int qed_configure_filter_rx_mode(struct ecore_dev *edev,
+int qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev,
 				 enum qed_filter_rx_mode_type type)
 {
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct ecore_filter_accept_flags flags;
 
 	memset(&flags, 0, sizeof(flags));
@@ -422,25 +347,6 @@ int qed_configure_filter_rx_mode(struct ecore_dev *edev,
 				       ECORE_SPQ_MODE_CB, NULL);
 }
 
-static int
-qed_configure_filter(struct ecore_dev *edev, struct qed_filter_params *params)
-{
-	switch (params->type) {
-	case QED_FILTER_TYPE_UCAST:
-		return qed_configure_filter_ucast(edev, &params->filter.ucast);
-	case QED_FILTER_TYPE_MCAST:
-		return qed_configure_filter_mcast(edev, &params->filter.mcast);
-	case QED_FILTER_TYPE_RX_MODE:
-		return qed_configure_filter_rx_mode(edev,
-						    params->filter.
-						    accept_flags);
-	default:
-		DP_NOTICE(edev, true, "Unknown filter type %d\n",
-			  (int)params->type);
-		return -EINVAL;
-	}
-}
-
 static const struct qed_eth_ops qed_eth_ops_pass = {
 	INIT_STRUCT_FIELD(common, &qed_common_ops_pass),
 	INIT_STRUCT_FIELD(fill_dev_info, &qed_fill_eth_dev_info),
@@ -455,7 +361,6 @@ static const struct qed_eth_ops qed_eth_ops_pass = {
 	INIT_STRUCT_FIELD(fastpath_stop, &qed_fastpath_stop),
 	INIT_STRUCT_FIELD(fastpath_start, &qed_fastpath_start),
 	INIT_STRUCT_FIELD(get_vport_stats, &qed_get_vport_stats),
-	INIT_STRUCT_FIELD(filter_config, &qed_configure_filter),
 };
 
 const struct qed_eth_ops *qed_get_eth_ops(void)
diff --git a/drivers/net/qede/qede_eth_if.h b/drivers/net/qede/qede_eth_if.h
index 33655c3..9c0db87 100644
--- a/drivers/net/qede/qede_eth_if.h
+++ b/drivers/net/qede/qede_eth_if.h
@@ -26,12 +26,6 @@ enum qed_filter_rx_mode_type {
 	QED_FILTER_RX_MODE_TYPE_PROMISC,
 };
 
-enum qed_filter_xcast_params_type {
-	QED_FILTER_XCAST_TYPE_ADD,
-	QED_FILTER_XCAST_TYPE_DEL,
-	QED_FILTER_XCAST_TYPE_REPLACE,
-};
-
 enum qed_filter_type {
 	QED_FILTER_TYPE_UCAST,
 	QED_FILTER_TYPE_MCAST,
@@ -93,31 +87,6 @@ struct qed_stop_txq_params {
 	uint8_t tx_queue_id;
 };
 
-struct qed_filter_ucast_params {
-	enum qed_filter_xcast_params_type type;
-	uint8_t vlan_valid;
-	uint16_t vlan;
-	uint8_t mac_valid;
-	unsigned char mac[ETHER_ADDR_LEN];
-};
-
-struct qed_filter_mcast_params {
-	enum qed_filter_xcast_params_type type;
-	uint8_t num;
-	unsigned char mac[QEDE_MAX_MCAST_FILTERS][ETHER_ADDR_LEN];
-};
-
-union qed_filter_type_params {
-	enum qed_filter_rx_mode_type accept_flags;
-	struct qed_filter_ucast_params ucast;
-	struct qed_filter_mcast_params mcast;
-};
-
-struct qed_filter_params {
-	enum qed_filter_type type;
-	union qed_filter_type_params filter;
-};
-
 struct qed_eth_ops {
 	const struct qed_common_ops *common;
 
@@ -162,9 +131,6 @@ struct qed_eth_ops {
 
 	void (*get_vport_stats)(struct ecore_dev *edev,
 				struct ecore_eth_stats *stats);
-
-	int (*filter_config)(struct ecore_dev *edev,
-			     struct qed_filter_params *params);
 };
 
 /* externs */
@@ -173,7 +139,7 @@ extern const struct qed_common_ops qed_common_ops_pass;
 
 const struct qed_eth_ops *qed_get_eth_ops();
 
-int qed_configure_filter_rx_mode(struct ecore_dev *edev,
+int qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev,
 				 enum qed_filter_rx_mode_type type);
 
 #endif /* _QEDE_ETH_IF_H */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 4943358..73f1824 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -222,47 +222,181 @@ static void qede_print_adapter_info(struct qede_dev *qdev)
 	DP_INFO(edev, "*********************************\n");
 }
 
+static void qede_set_ucast_cmn_params(struct ecore_filter_ucast *ucast)
+{
+	memset(ucast, 0, sizeof(struct ecore_filter_ucast));
+	ucast->is_rx_filter = true;
+	ucast->is_tx_filter = true;
+	/* ucast->assert_on_error = true; - For debug */
+}
+
 static int
-qede_set_ucast_rx_mac(struct qede_dev *qdev,
-		      enum qed_filter_xcast_params_type opcode,
-		      uint8_t mac[ETHER_ADDR_LEN])
+qede_ucast_filter(struct rte_eth_dev *eth_dev, struct ecore_filter_ucast *ucast,
+		  bool add)
 {
-	struct ecore_dev *edev = &qdev->edev;
-	struct qed_filter_params filter_cmd;
-
-	memset(&filter_cmd, 0, sizeof(filter_cmd));
-	filter_cmd.type = QED_FILTER_TYPE_UCAST;
-	filter_cmd.filter.ucast.type = opcode;
-	filter_cmd.filter.ucast.mac_valid = 1;
-	rte_memcpy(&filter_cmd.filter.ucast.mac[0], &mac[0], ETHER_ADDR_LEN);
-	return qdev->ops->filter_config(edev, &filter_cmd);
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	struct qede_ucast_entry *tmp = NULL;
+	struct qede_ucast_entry *u;
+	struct ether_addr *mac_addr;
+
+	mac_addr  = (struct ether_addr *)ucast->mac;
+	if (add) {
+		SLIST_FOREACH(tmp, &qdev->uc_list_head, list) {
+			if ((memcmp(mac_addr, &tmp->mac,
+				    ETHER_ADDR_LEN) == 0) &&
+			     ucast->vlan == tmp->vlan) {
+				DP_ERR(edev, "Unicast MAC is already added"
+				       " with vlan = %u, vni = %u\n",
+				       ucast->vlan,  ucast->vni);
+					return -EEXIST;
+			}
+		}
+		u = rte_malloc(NULL, sizeof(struct qede_ucast_entry),
+			       RTE_CACHE_LINE_SIZE);
+		if (!u) {
+			DP_ERR(edev, "Did not allocate memory for ucast\n");
+			return -ENOMEM;
+		}
+		ether_addr_copy(mac_addr, &u->mac);
+		u->vlan = ucast->vlan;
+		SLIST_INSERT_HEAD(&qdev->uc_list_head, u, list);
+		qdev->num_uc_addr++;
+	} else {
+		SLIST_FOREACH(tmp, &qdev->uc_list_head, list) {
+			if ((memcmp(mac_addr, &tmp->mac,
+				    ETHER_ADDR_LEN) == 0) &&
+			    ucast->vlan == tmp->vlan)
+			break;
+		}
+		if (tmp == NULL) {
+			DP_INFO(edev, "Unicast MAC is not found\n");
+			return -EINVAL;
+		}
+		SLIST_REMOVE(&qdev->uc_list_head, tmp, qede_ucast_entry, list);
+		qdev->num_uc_addr--;
+	}
+
+	return 0;
 }
 
-static void
-qede_mac_addr_add(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr,
-		  uint32_t index, __rte_unused uint32_t pool)
+static int
+qede_mcast_filter(struct rte_eth_dev *eth_dev, struct ecore_filter_ucast *mcast,
+		  bool add)
 {
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
-	int rc;
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	struct ether_addr *mac_addr;
+	struct qede_mcast_entry *tmp = NULL;
+	struct qede_mcast_entry *m;
+
+	mac_addr  = (struct ether_addr *)mcast->mac;
+	if (add) {
+		SLIST_FOREACH(tmp, &qdev->mc_list_head, list) {
+			if (memcmp(mac_addr, &tmp->mac, ETHER_ADDR_LEN) == 0) {
+				DP_ERR(edev,
+					"Multicast MAC is already added\n");
+				return -EEXIST;
+			}
+		}
+		m = rte_malloc(NULL, sizeof(struct qede_mcast_entry),
+			RTE_CACHE_LINE_SIZE);
+		if (!m) {
+			DP_ERR(edev,
+				"Did not allocate memory for mcast\n");
+			return -ENOMEM;
+		}
+		ether_addr_copy(mac_addr, &m->mac);
+		SLIST_INSERT_HEAD(&qdev->mc_list_head, m, list);
+		qdev->num_mc_addr++;
+	} else {
+		SLIST_FOREACH(tmp, &qdev->mc_list_head, list) {
+			if (memcmp(mac_addr, &tmp->mac, ETHER_ADDR_LEN) == 0)
+				break;
+		}
+		if (tmp == NULL) {
+			DP_INFO(edev, "Multicast mac is not found\n");
+			return -EINVAL;
+		}
+		SLIST_REMOVE(&qdev->mc_list_head, tmp,
+			     qede_mcast_entry, list);
+		qdev->num_mc_addr--;
+	}
 
-	PMD_INIT_FUNC_TRACE(edev);
+	return 0;
+}
 
-	if (index >= qdev->dev_info.num_mac_addrs) {
-		DP_ERR(edev, "Index %u is above MAC filter limit %u\n",
-		       index, qdev->dev_info.num_mac_addrs);
-		return;
+static enum _ecore_status_t
+qede_mac_int_ops(struct rte_eth_dev *eth_dev, struct ecore_filter_ucast *ucast,
+		 bool add)
+{
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	enum _ecore_status_t rc;
+	struct ecore_filter_mcast mcast;
+	struct qede_mcast_entry *tmp;
+	uint16_t j = 0;
+
+	/* Multicast */
+	if (is_multicast_ether_addr((struct ether_addr *)ucast->mac)) {
+		if (add) {
+			if (qdev->num_mc_addr >= ECORE_MAX_MC_ADDRS) {
+				DP_ERR(edev,
+				       "Mcast filter table limit exceeded, "
+				       "Please enable mcast promisc mode\n");
+				return -ECORE_INVAL;
+			}
+		}
+		rc = qede_mcast_filter(eth_dev, ucast, add);
+		if (rc == 0) {
+			DP_INFO(edev, "num_mc_addrs = %u\n", qdev->num_mc_addr);
+			memset(&mcast, 0, sizeof(mcast));
+			mcast.num_mc_addrs = qdev->num_mc_addr;
+			mcast.opcode = ECORE_FILTER_ADD;
+			SLIST_FOREACH(tmp, &qdev->mc_list_head, list) {
+				ether_addr_copy(&tmp->mac,
+					(struct ether_addr *)&mcast.mac[j]);
+				j++;
+			}
+			rc = ecore_filter_mcast_cmd(edev, &mcast,
+						    ECORE_SPQ_MODE_CB, NULL);
+		}
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(edev, "Failed to add multicast filter"
+			       " rc = %d, op = %d\n", rc, add);
+		}
+	} else { /* Unicast */
+		if (add) {
+			if (qdev->num_uc_addr >= qdev->dev_info.num_mac_addrs) {
+				DP_ERR(edev,
+				       "Ucast filter table limit exceeded,"
+				       " Please enable promisc mode\n");
+				return -ECORE_INVAL;
+			}
+		}
+		rc = qede_ucast_filter(eth_dev, ucast, add);
+		if (rc == 0)
+			rc = ecore_filter_ucast_cmd(edev, ucast,
+						    ECORE_SPQ_MODE_CB, NULL);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(edev, "MAC filter failed, rc = %d, op = %d\n",
+			       rc, add);
+		}
 	}
 
-	/* Adding macaddr even though promiscuous mode is set */
-	if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1)
-		DP_INFO(edev, "Port is in promisc mode, yet adding it\n");
+	return rc;
+}
 
-	/* Add MAC filters according to the unicast secondary macs */
-	rc = qede_set_ucast_rx_mac(qdev, QED_FILTER_XCAST_TYPE_ADD,
-				   mac_addr->addr_bytes);
-	if (rc)
-		DP_ERR(edev, "Unable to add macaddr rc=%d\n", rc);
+static void
+qede_mac_addr_add(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr,
+		  uint32_t index, __rte_unused uint32_t pool)
+{
+	struct ecore_filter_ucast ucast;
+
+	qede_set_ucast_cmn_params(&ucast);
+	ucast.type = ECORE_FILTER_MAC;
+	ether_addr_copy(mac_addr, (struct ether_addr *)&ucast.mac);
+	(void)qede_mac_int_ops(eth_dev, &ucast, 1);
 }
 
 static void
@@ -271,6 +405,7 @@ qede_mac_addr_remove(struct rte_eth_dev *eth_dev, uint32_t index)
 	struct qede_dev *qdev = eth_dev->data->dev_private;
 	struct ecore_dev *edev = &qdev->edev;
 	struct ether_addr mac_addr;
+	struct ecore_filter_ucast ucast;
 	int rc;
 
 	PMD_INIT_FUNC_TRACE(edev);
@@ -281,12 +416,15 @@ qede_mac_addr_remove(struct rte_eth_dev *eth_dev, uint32_t index)
 		return;
 	}
 
+	qede_set_ucast_cmn_params(&ucast);
+	ucast.opcode = ECORE_FILTER_REMOVE;
+	ucast.type = ECORE_FILTER_MAC;
+
 	/* Use the index maintained by rte */
-	ether_addr_copy(&eth_dev->data->mac_addrs[index], &mac_addr);
-	rc = qede_set_ucast_rx_mac(qdev, QED_FILTER_XCAST_TYPE_DEL,
-				   mac_addr.addr_bytes);
-	if (rc)
-		DP_ERR(edev, "Unable to remove macaddr rc=%d\n", rc);
+	ether_addr_copy(&eth_dev->data->mac_addrs[index],
+			(struct ether_addr *)&ucast.mac);
+
+	ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB, NULL);
 }
 
 static void
@@ -294,6 +432,7 @@ qede_mac_addr_set(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	struct ecore_filter_ucast ucast;
 	int rc;
 
 	if (IS_VF(edev) && !ecore_vf_check_mac(ECORE_LEADING_HWFN(edev),
@@ -305,10 +444,13 @@ qede_mac_addr_set(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr)
 	}
 
 	/* First remove the primary mac */
-	rc = qede_set_ucast_rx_mac(qdev, QED_FILTER_XCAST_TYPE_DEL,
-				   qdev->primary_mac.addr_bytes);
-
-	if (rc) {
+	qede_set_ucast_cmn_params(&ucast);
+	ucast.opcode = ECORE_FILTER_REMOVE;
+	ucast.type = ECORE_FILTER_MAC;
+	ether_addr_copy(&qdev->primary_mac,
+			(struct ether_addr *)&ucast.mac);
+	rc = ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB, NULL);
+	if (rc != 0) {
 		DP_ERR(edev, "Unable to remove current macaddr"
 			     " Reverting to previous default mac\n");
 		ether_addr_copy(&qdev->primary_mac,
@@ -317,18 +459,15 @@ qede_mac_addr_set(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr)
 	}
 
 	/* Add new MAC */
-	rc = qede_set_ucast_rx_mac(qdev, QED_FILTER_XCAST_TYPE_ADD,
-				   mac_addr->addr_bytes);
-
-	if (rc)
+	ucast.opcode = ECORE_FILTER_ADD;
+	ether_addr_copy(mac_addr, (struct ether_addr *)&ucast.mac);
+	rc = ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB, NULL);
+	if (rc != 0)
 		DP_ERR(edev, "Unable to add new default mac\n");
 	else
 		ether_addr_copy(mac_addr, &qdev->primary_mac);
 }
 
-
-
-
 static void qede_config_accept_any_vlan(struct qede_dev *qdev, bool action)
 {
 	struct ecore_dev *edev = &qdev->edev;
@@ -414,22 +553,6 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
 }
 
-static int qede_set_ucast_rx_vlan(struct qede_dev *qdev,
-				  enum qed_filter_xcast_params_type opcode,
-				  uint16_t vid)
-{
-	struct qed_filter_params filter_cmd;
-	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
-
-	memset(&filter_cmd, 0, sizeof(filter_cmd));
-	filter_cmd.type = QED_FILTER_TYPE_UCAST;
-	filter_cmd.filter.ucast.type = opcode;
-	filter_cmd.filter.ucast.vlan_valid = 1;
-	filter_cmd.filter.ucast.vlan = vid;
-
-	return qdev->ops->filter_config(edev, &filter_cmd);
-}
-
 static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 				uint16_t vlan_id, int on)
 {
@@ -438,6 +561,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	struct qed_dev_eth_info *dev_info = &qdev->dev_info;
 	struct qede_vlan_entry *tmp = NULL;
 	struct qede_vlan_entry *vlan;
+	struct ecore_filter_ucast ucast;
 	int rc;
 
 	if (on) {
@@ -464,9 +588,13 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 			return -ENOMEM;
 		}
 
-		rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_ADD,
-					    vlan_id);
-		if (rc) {
+		qede_set_ucast_cmn_params(&ucast);
+		ucast.opcode = ECORE_FILTER_ADD;
+		ucast.type = ECORE_FILTER_VLAN;
+		ucast.vlan = vlan_id;
+		rc = ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB,
+					    NULL);
+		if (rc != 0) {
 			DP_ERR(edev, "Failed to add VLAN %u rc %d\n", vlan_id,
 			       rc);
 			rte_free(vlan);
@@ -496,9 +624,13 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 
 		SLIST_REMOVE(&qdev->vlan_list_head, tmp, qede_vlan_entry, list);
 
-		rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_DEL,
-					    vlan_id);
-		if (rc) {
+		qede_set_ucast_cmn_params(&ucast);
+		ucast.opcode = ECORE_FILTER_REMOVE;
+		ucast.type = ECORE_FILTER_VLAN;
+		ucast.vlan = vlan_id;
+		rc = ecore_filter_ucast_cmd(edev, &ucast, ECORE_SPQ_MODE_CB,
+					    NULL);
+		if (rc != 0) {
 			DP_ERR(edev, "Failed to delete VLAN %u rc %d\n",
 			       vlan_id, rc);
 		} else {
@@ -740,22 +872,6 @@ qede_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete)
 	return ((curr->link_status == link.link_up) ? -1 : 0);
 }
 
-static void
-qede_rx_mode_setting(struct rte_eth_dev *eth_dev,
-		     enum qed_filter_rx_mode_type accept_flags)
-{
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
-	struct qed_filter_params rx_mode;
-
-	DP_INFO(edev, "%s mode %u\n", __func__, accept_flags);
-
-	memset(&rx_mode, 0, sizeof(struct qed_filter_params));
-	rx_mode.type = QED_FILTER_TYPE_RX_MODE;
-	rx_mode.filter.accept_flags = accept_flags;
-	qdev->ops->filter_config(edev, &rx_mode);
-}
-
 static void qede_promiscuous_enable(struct rte_eth_dev *eth_dev)
 {
 	struct qede_dev *qdev = eth_dev->data->dev_private;
@@ -768,7 +884,7 @@ static void qede_promiscuous_enable(struct rte_eth_dev *eth_dev)
 	if (rte_eth_allmulticast_get(eth_dev->data->port_id) == 1)
 		type |= QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC;
 
-	qede_rx_mode_setting(eth_dev, type);
+	qed_configure_filter_rx_mode(eth_dev, type);
 }
 
 static void qede_promiscuous_disable(struct rte_eth_dev *eth_dev)
@@ -779,10 +895,11 @@ static void qede_promiscuous_disable(struct rte_eth_dev *eth_dev)
 	PMD_INIT_FUNC_TRACE(edev);
 
 	if (rte_eth_allmulticast_get(eth_dev->data->port_id) == 1)
-		qede_rx_mode_setting(eth_dev,
-				     QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC);
+		qed_configure_filter_rx_mode(eth_dev,
+				QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC);
 	else
-		qede_rx_mode_setting(eth_dev, QED_FILTER_RX_MODE_TYPE_REGULAR);
+		qed_configure_filter_rx_mode(eth_dev,
+				QED_FILTER_RX_MODE_TYPE_REGULAR);
 }
 
 static void qede_poll_sp_sb_cb(void *param)
@@ -1040,15 +1157,17 @@ static void qede_allmulticast_enable(struct rte_eth_dev *eth_dev)
 	if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1)
 		type |= QED_FILTER_RX_MODE_TYPE_PROMISC;
 
-	qede_rx_mode_setting(eth_dev, type);
+	qed_configure_filter_rx_mode(eth_dev, type);
 }
 
 static void qede_allmulticast_disable(struct rte_eth_dev *eth_dev)
 {
 	if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1)
-		qede_rx_mode_setting(eth_dev, QED_FILTER_RX_MODE_TYPE_PROMISC);
+		qed_configure_filter_rx_mode(eth_dev,
+				QED_FILTER_RX_MODE_TYPE_PROMISC);
 	else
-		qede_rx_mode_setting(eth_dev, QED_FILTER_RX_MODE_TYPE_REGULAR);
+		qed_configure_filter_rx_mode(eth_dev,
+				QED_FILTER_RX_MODE_TYPE_REGULAR);
 }
 
 static int qede_flow_ctrl_set(struct rte_eth_dev *eth_dev,
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index a97e3d9..a35ea8b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -123,6 +123,17 @@ struct qede_vlan_entry {
 	uint16_t vid;
 };
 
+struct qede_mcast_entry {
+	struct ether_addr mac;
+	SLIST_ENTRY(qede_mcast_entry) list;
+};
+
+struct qede_ucast_entry {
+	struct ether_addr mac;
+	uint16_t vlan;
+	SLIST_ENTRY(qede_ucast_entry) list;
+};
+
 /*
  *  Structure to store private data for each port.
  */
@@ -147,6 +158,10 @@ struct qede_dev {
 	uint16_t configured_vlans;
 	bool accept_any_vlan;
 	struct ether_addr primary_mac;
+	SLIST_HEAD(mc_list_head, qede_mcast_entry) mc_list_head;
+	uint16_t num_mc_addr;
+	SLIST_HEAD(uc_list_head, qede_ucast_entry) uc_list_head;
+	uint16_t num_uc_addr;
 	bool handle_hw_err;
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 };
-- 
1.7.10.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [dpdk-stable] [PATCH v2 5/7] net/qede: fix RSS related issue
       [not found] <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 2/7] net/qede: fix filtering code Harish Patil
@ 2016-12-23  0:48 ` Harish Patil
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 6/7] net/qede: fix reporting of SR-IOV PF driver as disabled Harish Patil
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 7/7] net/qede: restrict maximum queues for PF/VF Harish Patil
  3 siblings, 0 replies; 4+ messages in thread
From: Harish Patil @ 2016-12-23  0:48 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: Harish Patil, dev, stable, Dept-EngDPDKDev

This patch includes the following:

- Fix missing hash_key_size advertisement
- Fix RSS hash query function
- Update RSS offload flag
- Accept user provided RSS configuration params via rx_adv_conf
  in dev_configure()
- Decouple RSS configuration from common qed_update_vport() and
  instead make use of existing RSS APIs for default RSS configuration

Fixes: 6d9e26c42c0d ("net/qede: get RSS hash configuration")
Fixes: 9c5d0a669f9b ("net/qede: fix RSS")

Signed-off-by: Harish Patil <harish.patil@qlogic.com>
---
 drivers/net/qede/qede_eth_if.c |   79 +++++--------
 drivers/net/qede/qede_eth_if.h |    9 +-
 drivers/net/qede/qede_ethdev.c |  255 ++++++++++++++++++++++++++++++----------
 drivers/net/qede/qede_ethdev.h |    9 +-
 drivers/net/qede/qede_rxtx.c   |   90 +-------------
 drivers/net/qede/qede_rxtx.h   |   10 +-
 6 files changed, 240 insertions(+), 212 deletions(-)

diff --git a/drivers/net/qede/qede_eth_if.c b/drivers/net/qede/qede_eth_if.c
index 30fded0..7d21200 100644
--- a/drivers/net/qede/qede_eth_if.c
+++ b/drivers/net/qede/qede_eth_if.c
@@ -68,6 +68,33 @@ static int qed_stop_vport(struct ecore_dev *edev, uint8_t vport_id)
 	return 0;
 }
 
+bool qed_update_rss_parm_cmt(struct ecore_dev *edev, uint16_t *p_tbl)
+{
+	uint16_t max = 0, k;
+	bool rss_mode = 0; /* disable */
+	int divisor;
+
+	/* Find largest entry, since it's possible RSS needs to
+	 * be disabled [in case only 1 queue per-hwfn]
+	 */
+	for (k = 0; k < ECORE_RSS_IND_TABLE_SIZE; k++)
+		max = (max > p_tbl[k]) ?  max : p_tbl[k];
+
+	/* Either fix RSS values or disable RSS */
+	if (edev->num_hwfns < max + 1) {
+		divisor = (max + edev->num_hwfns - 1) / edev->num_hwfns;
+		DP_VERBOSE(edev, ECORE_MSG_SPQ,
+			   "CMT - fixing RSS values (modulo %02x)\n",
+			   divisor);
+		for (k = 0; k < ECORE_RSS_IND_TABLE_SIZE; k++)
+			p_tbl[k] = p_tbl[k] % divisor;
+
+		rss_mode = 1;
+	}
+
+	return rss_mode;
+}
+
 static int
 qed_update_vport(struct ecore_dev *edev, struct qed_update_vport_params *params)
 {
@@ -94,58 +121,6 @@ qed_update_vport(struct ecore_dev *edev, struct qed_update_vport_params *params)
 	    params->update_accept_any_vlan_flg;
 	sp_params.mtu = params->mtu;
 
-	/* RSS - is a bit tricky, since upper-layer isn't familiar with hwfns.
-	 * We need to re-fix the rss values per engine for CMT.
-	 */
-
-	if (edev->num_hwfns > 1 && params->update_rss_flg) {
-		struct qed_update_vport_rss_params *rss = &params->rss_params;
-		int k, max = 0;
-
-		/* Find largest entry, since it's possible RSS needs to
-		 * be disabled [in case only 1 queue per-hwfn]
-		 */
-		for (k = 0; k < ECORE_RSS_IND_TABLE_SIZE; k++)
-			max = (max > rss->rss_ind_table[k]) ?
-			    max : rss->rss_ind_table[k];
-
-		/* Either fix RSS values or disable RSS */
-		if (edev->num_hwfns < max + 1) {
-			int divisor = (max + edev->num_hwfns - 1) /
-			    edev->num_hwfns;
-
-			DP_VERBOSE(edev, ECORE_MSG_SPQ,
-				   "CMT - fixing RSS values (modulo %02x)\n",
-				   divisor);
-
-			for (k = 0; k < ECORE_RSS_IND_TABLE_SIZE; k++)
-				rss->rss_ind_table[k] =
-				    rss->rss_ind_table[k] % divisor;
-		} else {
-			DP_VERBOSE(edev, ECORE_MSG_SPQ,
-				   "CMT - 1 queue per-hwfn; Disabling RSS\n");
-			params->update_rss_flg = 0;
-		}
-	}
-
-	/* Now, update the RSS configuration for actual configuration */
-	if (params->update_rss_flg) {
-		sp_rss_params.update_rss_config = 1;
-		sp_rss_params.rss_enable = 1;
-		sp_rss_params.update_rss_capabilities = 1;
-		sp_rss_params.update_rss_ind_table = 1;
-		sp_rss_params.update_rss_key = 1;
-		sp_rss_params.rss_caps = ECORE_RSS_IPV4 | ECORE_RSS_IPV6 |
-		    ECORE_RSS_IPV4_TCP | ECORE_RSS_IPV6_TCP;
-		sp_rss_params.rss_table_size_log = 7;	/* 2^7 = 128 */
-		rte_memcpy(sp_rss_params.rss_ind_table,
-		       params->rss_params.rss_ind_table,
-		       ECORE_RSS_IND_TABLE_SIZE * sizeof(uint16_t));
-		rte_memcpy(sp_rss_params.rss_key, params->rss_params.rss_key,
-		       ECORE_RSS_KEY_SIZE * sizeof(uint32_t));
-		sp_params.rss_params = &sp_rss_params;
-	}
-
 	for_each_hwfn(edev, i) {
 		struct ecore_hwfn *p_hwfn = &edev->hwfns[i];
 
diff --git a/drivers/net/qede/qede_eth_if.h b/drivers/net/qede/qede_eth_if.h
index d67b312..f0c489c 100644
--- a/drivers/net/qede/qede_eth_if.h
+++ b/drivers/net/qede/qede_eth_if.h
@@ -47,12 +47,6 @@ struct qed_dev_eth_info {
 	bool is_legacy;
 };
 
-struct qed_update_vport_rss_params {
-	uint16_t rss_ind_table[128];
-	uint32_t rss_key[10];
-	u8 rss_caps;
-};
-
 struct qed_stop_rxq_params {
 	uint8_t rss_id;
 	uint8_t rx_queue_id;
@@ -71,7 +65,6 @@ struct qed_update_vport_params {
 	uint8_t update_accept_any_vlan_flg;
 	uint8_t accept_any_vlan;
 	uint8_t update_rss_flg;
-	struct qed_update_vport_rss_params rss_params;
 	uint16_t mtu;
 };
 
@@ -145,4 +138,6 @@ const struct qed_eth_ops *qed_get_eth_ops();
 int qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev,
 				 enum qed_filter_rx_mode_type type);
 
+bool qed_update_rss_parm_cmt(struct ecore_dev *edev, uint16_t *p_tbl);
+
 #endif /* _QEDE_ETH_IF_H */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index ec48306..00af0f6 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -788,6 +788,54 @@ static int qede_init_vport(struct qede_dev *qdev)
 	return 0;
 }
 
+static void qede_prandom_bytes(uint32_t *buff)
+{
+	uint8_t i;
+
+	srand((unsigned int)time(NULL));
+	for (i = 0; i < ECORE_RSS_KEY_SIZE; i++)
+		buff[i] = rand();
+}
+
+static int qede_config_rss(struct rte_eth_dev *eth_dev)
+{
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	uint32_t def_rss_key[ECORE_RSS_KEY_SIZE];
+	struct rte_eth_rss_reta_entry64 reta_conf[2];
+	struct rte_eth_rss_conf rss_conf;
+	uint32_t i, id, pos, q;
+
+	rss_conf = eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
+	if (!rss_conf.rss_key) {
+		DP_INFO(edev, "Applying driver default key\n");
+		rss_conf.rss_key_len = ECORE_RSS_KEY_SIZE * sizeof(uint32_t);
+		qede_prandom_bytes(&def_rss_key[0]);
+		rss_conf.rss_key = (uint8_t *)&def_rss_key[0];
+	}
+
+	/* Configure RSS hash */
+	if (qede_rss_hash_update(eth_dev, &rss_conf))
+		return -EINVAL;
+
+	/* Configure default RETA */
+	memset(reta_conf, 0, sizeof(reta_conf));
+	for (i = 0; i < ECORE_RSS_IND_TABLE_SIZE; i++)
+		reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX;
+
+	for (i = 0; i < ECORE_RSS_IND_TABLE_SIZE; i++) {
+		id = i / RTE_RETA_GROUP_SIZE;
+		pos = i % RTE_RETA_GROUP_SIZE;
+		q = i % QEDE_RSS_COUNT(qdev);
+		reta_conf[id].reta[pos] = q;
+	}
+	if (qede_rss_reta_update(eth_dev, &reta_conf[0],
+				 ECORE_RSS_IND_TABLE_SIZE))
+		return -EINVAL;
+
+	return 0;
+}
+
 static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 {
 	struct qede_dev *qdev = eth_dev->data->dev_private;
@@ -856,6 +904,26 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	if (rc != 0)
 		return rc;
 
+	/* Do RSS configuration after vport-start */
+	switch (rxmode->mq_mode) {
+	case ETH_MQ_RX_RSS:
+		rc = qede_config_rss(eth_dev);
+		if (rc != 0) {
+			qdev->ops->vport_stop(edev, 0);
+			qede_dealloc_fp_resc(eth_dev);
+			return -EINVAL;
+		}
+	break;
+	case ETH_MQ_RX_NONE:
+		DP_INFO(edev, "RSS is disabled\n");
+	break;
+	default:
+		DP_ERR(edev, "Unsupported RSS mode\n");
+		qdev->ops->vport_stop(edev, 0);
+		qede_dealloc_fp_resc(eth_dev);
+		return -EINVAL;
+	}
+
 	SLIST_INIT(&qdev->vlan_list_head);
 
 	/* Add primary mac for PF */
@@ -913,6 +981,7 @@ qede_dev_info_get(struct rte_eth_dev *eth_dev,
 	else
 		dev_info->max_vfs = (uint16_t)NUM_OF_VFS(&qdev->edev);
 	dev_info->reta_size = ECORE_RSS_IND_TABLE_SIZE;
+	dev_info->hash_key_size = ECORE_RSS_KEY_SIZE * sizeof(uint32_t);
 	dev_info->flow_type_rss_offloads = (uint64_t)QEDE_RSS_OFFLOAD_ALL;
 
 	dev_info->default_txconf = (struct rte_eth_txconf) {
@@ -1367,7 +1436,7 @@ qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 	return NULL;
 }
 
-void qede_init_rss_caps(uint8_t *rss_caps, uint64_t hf)
+static void qede_init_rss_caps(uint8_t *rss_caps, uint64_t hf)
 {
 	*rss_caps = 0;
 	*rss_caps |= (hf & ETH_RSS_IPV4)              ? ECORE_RSS_IPV4 : 0;
@@ -1381,71 +1450,100 @@ void qede_init_rss_caps(uint8_t *rss_caps, uint64_t hf)
 static int qede_rss_hash_update(struct rte_eth_dev *eth_dev,
 				struct rte_eth_rss_conf *rss_conf)
 {
-	struct qed_update_vport_params vport_update_params;
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	struct ecore_sp_vport_update_params vport_update_params;
+	struct ecore_rss_params rss_params;
+	struct ecore_rss_params params;
+	struct ecore_hwfn *p_hwfn;
 	uint32_t *key = (uint32_t *)rss_conf->rss_key;
 	uint64_t hf = rss_conf->rss_hf;
-	int i;
+	uint8_t len = rss_conf->rss_key_len;
+	uint8_t i;
+	int rc;
 
 	memset(&vport_update_params, 0, sizeof(vport_update_params));
+	memset(&rss_params, 0, sizeof(rss_params));
+
+	DP_INFO(edev, "RSS hf = 0x%lx len = %u key = %p\n",
+		(unsigned long)hf, len, key);
 
 	if (hf != 0) {
-		/* Enable RSS */
-		qede_init_rss_caps(&qdev->rss_params.rss_caps, hf);
-		memcpy(&vport_update_params.rss_params, &qdev->rss_params,
-		       sizeof(vport_update_params.rss_params));
-		if (key)
-			memcpy(qdev->rss_params.rss_key, rss_conf->rss_key,
-			       rss_conf->rss_key_len);
-		vport_update_params.update_rss_flg = 1;
-		qdev->rss_enabled = 1;
-	} else {
-		/* Disable RSS */
-		qdev->rss_enabled = 0;
+		/* Enabling RSS */
+		DP_INFO(edev, "Enabling rss\n");
+
+		/* RSS caps */
+		qede_init_rss_caps(&rss_params.rss_caps, hf);
+		rss_params.update_rss_capabilities = 1;
+
+		/* RSS hash key */
+		if (key) {
+			if (len > (ECORE_RSS_KEY_SIZE * sizeof(uint32_t))) {
+				DP_ERR(edev, "RSS key length exceeds limit\n");
+				return -EINVAL;
+			}
+			DP_INFO(edev, "Applying user supplied hash key\n");
+			rss_params.update_rss_key = 1;
+			memcpy(&rss_params.rss_key, key, len);
+		}
+		rss_params.rss_enable = 1;
 	}
 
-	/* If the mapping doesn't fit any supported, return */
-	if (qdev->rss_params.rss_caps == 0 && hf != 0)
-		return -EINVAL;
-
-	DP_INFO(edev, "%s\n", (vport_update_params.update_rss_flg) ?
-				"Enabling RSS" : "Disabling RSS");
-
+	rss_params.update_rss_config = 1;
+	/* tbl_size has to be set with capabilities */
+	rss_params.rss_table_size_log = 7;
 	vport_update_params.vport_id = 0;
+	vport_update_params.rss_params = &rss_params;
+
+	for_each_hwfn(edev, i) {
+		p_hwfn = &edev->hwfns[i];
+		vport_update_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
+		rc = ecore_sp_vport_update(p_hwfn, &vport_update_params,
+					   ECORE_SPQ_MODE_EBLOCK, NULL);
+		if (rc) {
+			DP_ERR(edev, "vport-update for RSS failed\n");
+			return rc;
+		}
+	}
+	qdev->rss_enable = rss_params.rss_enable;
+
+	/* Update local structure for hash query */
+	qdev->rss_conf.rss_hf = hf;
+	qdev->rss_conf.rss_key_len = len;
+	if (qdev->rss_enable) {
+		if  (qdev->rss_conf.rss_key == NULL) {
+			qdev->rss_conf.rss_key = (uint8_t *)malloc(len);
+			if (qdev->rss_conf.rss_key == NULL) {
+				DP_ERR(edev, "No memory to store RSS key\n");
+				return -ENOMEM;
+			}
+		}
+		if (key && len) {
+			DP_INFO(edev, "Storing RSS key\n");
+			memcpy(qdev->rss_conf.rss_key, key, len);
+		}
+	} else if (!qdev->rss_enable && len == 0) {
+		if (qdev->rss_conf.rss_key) {
+			free(qdev->rss_conf.rss_key);
+			qdev->rss_conf.rss_key = NULL;
+			DP_INFO(edev, "Free RSS key\n");
+		}
+	}
 
-	return qdev->ops->vport_update(edev, &vport_update_params);
+	return 0;
 }
 
-int qede_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
+static int qede_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
 			   struct rte_eth_rss_conf *rss_conf)
 {
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	uint64_t hf;
-
-	if (rss_conf->rss_key_len < sizeof(qdev->rss_params.rss_key))
-		return -EINVAL;
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 
-	if (rss_conf->rss_key)
-		memcpy(rss_conf->rss_key, qdev->rss_params.rss_key,
-		       sizeof(qdev->rss_params.rss_key));
-
-	hf = 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV4)     ?
-			ETH_RSS_IPV4 : 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV6)     ?
-			ETH_RSS_IPV6 : 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV6)     ?
-			ETH_RSS_IPV6_EX : 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV4_TCP) ?
-			ETH_RSS_NONFRAG_IPV4_TCP : 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV6_TCP) ?
-			ETH_RSS_NONFRAG_IPV6_TCP : 0;
-	hf |= (qdev->rss_params.rss_caps & ECORE_RSS_IPV6_TCP) ?
-			ETH_RSS_IPV6_TCP_EX : 0;
-
-	rss_conf->rss_hf = hf;
+	rss_conf->rss_hf = qdev->rss_conf.rss_hf;
+	rss_conf->rss_key_len = qdev->rss_conf.rss_key_len;
 
+	if (rss_conf->rss_key && qdev->rss_conf.rss_key)
+		memcpy(rss_conf->rss_key, qdev->rss_conf.rss_key,
+		       rss_conf->rss_key_len);
 	return 0;
 }
 
@@ -1453,10 +1551,14 @@ static int qede_rss_reta_update(struct rte_eth_dev *eth_dev,
 				struct rte_eth_rss_reta_entry64 *reta_conf,
 				uint16_t reta_size)
 {
-	struct qed_update_vport_params vport_update_params;
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	struct ecore_sp_vport_update_params vport_update_params;
+	struct ecore_rss_params params;
+	struct ecore_hwfn *p_hwfn;
 	uint16_t i, idx, shift;
+	uint8_t entry;
+	int rc;
 
 	if (reta_size > ETH_RSS_RETA_SIZE_128) {
 		DP_ERR(edev, "reta_size %d is not supported by hardware\n",
@@ -1465,42 +1567,67 @@ static int qede_rss_reta_update(struct rte_eth_dev *eth_dev,
 	}
 
 	memset(&vport_update_params, 0, sizeof(vport_update_params));
-	memcpy(&vport_update_params.rss_params, &qdev->rss_params,
-	       sizeof(vport_update_params.rss_params));
+	memset(&params, 0, sizeof(params));
 
 	for (i = 0; i < reta_size; i++) {
 		idx = i / RTE_RETA_GROUP_SIZE;
 		shift = i % RTE_RETA_GROUP_SIZE;
 		if (reta_conf[idx].mask & (1ULL << shift)) {
-			uint8_t entry = reta_conf[idx].reta[shift];
-			qdev->rss_params.rss_ind_table[i] = entry;
+			entry = reta_conf[idx].reta[shift];
+			params.rss_ind_table[i] = entry;
 		}
 	}
 
-	vport_update_params.update_rss_flg = 1;
+	/* Fix up RETA for CMT mode device */
+	if (edev->num_hwfns > 1)
+		qdev->rss_enable = qed_update_rss_parm_cmt(edev,
+					&params.rss_ind_table[0]);
+	params.update_rss_ind_table = 1;
+	params.rss_table_size_log = 7;
+	params.update_rss_config = 1;
 	vport_update_params.vport_id = 0;
+	/* Use the current value of rss_enable */
+	params.rss_enable = qdev->rss_enable;
+	vport_update_params.rss_params = &params;
+
+	for_each_hwfn(edev, i) {
+		p_hwfn = &edev->hwfns[i];
+		vport_update_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
+		rc = ecore_sp_vport_update(p_hwfn, &vport_update_params,
+					   ECORE_SPQ_MODE_EBLOCK, NULL);
+		if (rc) {
+			DP_ERR(edev, "vport-update for RSS failed\n");
+			return rc;
+		}
+	}
 
-	return qdev->ops->vport_update(edev, &vport_update_params);
+	/* Update the local copy for RETA query command */
+	memcpy(qdev->rss_ind_table, params.rss_ind_table,
+	       sizeof(params.rss_ind_table));
+
+	return 0;
 }
 
-int qede_rss_reta_query(struct rte_eth_dev *eth_dev,
-			struct rte_eth_rss_reta_entry64 *reta_conf,
-			uint16_t reta_size)
+static int qede_rss_reta_query(struct rte_eth_dev *eth_dev,
+			       struct rte_eth_rss_reta_entry64 *reta_conf,
+			       uint16_t reta_size)
 {
 	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
 	uint16_t i, idx, shift;
+	uint8_t entry;
 
 	if (reta_size > ETH_RSS_RETA_SIZE_128) {
-		struct ecore_dev *edev = &qdev->edev;
 		DP_ERR(edev, "reta_size %d is not supported\n",
 		       reta_size);
+		return -EINVAL;
 	}
 
 	for (i = 0; i < reta_size; i++) {
 		idx = i / RTE_RETA_GROUP_SIZE;
 		shift = i % RTE_RETA_GROUP_SIZE;
 		if (reta_conf[idx].mask & (1ULL << shift)) {
-			uint8_t entry = qdev->rss_params.rss_ind_table[i];
+			entry = qdev->rss_ind_table[i];
 			reta_conf[idx].reta[shift] = entry;
 		}
 	}
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index d736246..bd85ba3 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -152,8 +152,11 @@ struct qede_dev {
 	struct qede_fastpath *fp_array;
 	uint8_t num_tc;
 	uint16_t mtu;
-	bool rss_enabled;
-	struct qed_update_vport_rss_params rss_params;
+	bool rss_enable;
+	struct rte_eth_rss_conf rss_conf;
+	uint16_t rss_ind_table[ECORE_RSS_IND_TABLE_SIZE];
+	uint64_t rss_hf;
+	uint8_t rss_key_len;
 	uint32_t flags;
 	bool gro_disable;
 	uint16_t num_queues;
@@ -185,6 +188,8 @@ static int qede_rss_reta_update(struct rte_eth_dev *eth_dev,
 				struct rte_eth_rss_reta_entry64 *reta_conf,
 				uint16_t reta_size);
 
+static void qede_init_rss_caps(uint8_t *rss_caps, uint64_t hf);
+
 static inline uint32_t qede_rx_cqe_to_pkt_type(uint16_t flags);
 
 /* Non-static functions */
diff --git a/drivers/net/qede/qede_rxtx.c b/drivers/net/qede/qede_rxtx.c
index 828d3cc..2a8939a 100644
--- a/drivers/net/qede/qede_rxtx.c
+++ b/drivers/net/qede/qede_rxtx.c
@@ -507,83 +507,11 @@ qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq)
 	PMD_RX_LOG(DEBUG, rxq, "bd_prod %u  cqe_prod %u\n", bd_prod, cqe_prod);
 }
 
-static inline uint32_t
-qede_rxfh_indir_default(uint32_t index, uint32_t n_rx_rings)
-{
-	return index % n_rx_rings;
-}
-
-static void qede_prandom_bytes(uint32_t *buff, size_t bytes)
-{
-	unsigned int i;
-
-	srand((unsigned int)time(NULL));
-
-	for (i = 0; i < ECORE_RSS_KEY_SIZE; i++)
-		buff[i] = rand();
-}
-
-static bool
-qede_check_vport_rss_enable(struct rte_eth_dev *eth_dev,
-			    struct qed_update_vport_rss_params *rss_params)
-{
-	struct rte_eth_rss_conf rss_conf;
-	enum rte_eth_rx_mq_mode mode = eth_dev->data->dev_conf.rxmode.mq_mode;
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
-	uint8_t rss_caps;
-	unsigned int i;
-	uint64_t hf;
-	uint32_t *key;
-
-	PMD_INIT_FUNC_TRACE(edev);
-
-	rss_conf = eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
-	key = (uint32_t *)rss_conf.rss_key;
-	hf = rss_conf.rss_hf;
-
-	/* Check if RSS conditions are met.
-	 * Note: Even though its meaningless to enable RSS with one queue, it
-	 * could be used to produce RSS Hash, so skipping that check.
-	 */
-	if (!(mode & ETH_MQ_RX_RSS)) {
-		DP_INFO(edev, "RSS flag is not set\n");
-		return false;
-	}
-
-	if (hf == 0) {
-		DP_INFO(edev, "Request to disable RSS\n");
-		return false;
-	}
-
-	memset(rss_params, 0, sizeof(*rss_params));
-
-	for (i = 0; i < ECORE_RSS_IND_TABLE_SIZE; i++)
-		rss_params->rss_ind_table[i] = qede_rxfh_indir_default(i,
-							QEDE_RSS_COUNT(qdev));
-
-	if (!key)
-		qede_prandom_bytes(rss_params->rss_key,
-				   sizeof(rss_params->rss_key));
-	else
-		memcpy(rss_params->rss_key, rss_conf.rss_key,
-		       rss_conf.rss_key_len);
-
-	qede_init_rss_caps(&rss_caps, hf);
-
-	rss_params->rss_caps = rss_caps;
-
-	DP_INFO(edev, "RSS conditions are met\n");
-
-	return true;
-}
-
 static int qede_start_queues(struct rte_eth_dev *eth_dev, bool clear_stats)
 {
 	struct qede_dev *qdev = eth_dev->data->dev_private;
 	struct ecore_dev *edev = &qdev->edev;
 	struct ecore_queue_start_common_params q_params;
-	struct qed_update_vport_rss_params *rss_params = &qdev->rss_params;
 	struct qed_dev_info *qed_info = &qdev->dev_info.common;
 	struct qed_update_vport_params vport_update_params;
 	struct qede_tx_queue *txq;
@@ -682,16 +610,6 @@ static int qede_start_queues(struct rte_eth_dev *eth_dev, bool clear_stats)
 		vport_update_params.tx_switching_flg = 1;
 	}
 
-	if (qede_check_vport_rss_enable(eth_dev, rss_params)) {
-		vport_update_params.update_rss_flg = 1;
-		qdev->rss_enabled = 1;
-	} else {
-		qdev->rss_enabled = 0;
-	}
-
-	rte_memcpy(&vport_update_params.rss_params, rss_params,
-	       sizeof(*rss_params));
-
 	rc = qdev->ops->vport_update(edev, &vport_update_params);
 	if (rc) {
 		DP_ERR(edev, "Update V-PORT failed %d\n", rc);
@@ -1091,7 +1009,7 @@ qede_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 		htype = (uint8_t)GET_FIELD(fp_cqe->bitfields,
 				ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE);
-		if (qdev->rss_enabled && htype) {
+		if (qdev->rss_enable && htype) {
 			rx_mb->ol_flags |= PKT_RX_RSS_HASH;
 			rx_mb->hash.rss = rte_le_to_cpu_32(fp_cqe->rss_hash);
 			PMD_RX_LOG(DEBUG, rxq, "Hash result 0x%x\n",
@@ -1410,7 +1328,7 @@ int qede_dev_start(struct rte_eth_dev *eth_dev)
 	struct ecore_dev *edev = &qdev->edev;
 	struct qed_link_output link_output;
 	struct qede_fastpath *fp;
-	int rc, i;
+	int rc;
 
 	DP_INFO(edev, "Device state is %d\n", qdev->state);
 
@@ -1620,10 +1538,14 @@ void qede_free_mem_load(struct rte_eth_dev *eth_dev)
 	for_each_queue(id) {
 		fp = &qdev->fp_array[id];
 		if (fp->type & QEDE_FASTPATH_RX) {
+			if (!fp->rxq)
+				continue;
 			qede_rx_queue_release(fp->rxq);
 			eth_dev->data->rx_queues[id] = NULL;
 		} else {
 			for (tc = 0; tc < qdev->num_tc; tc++) {
+				if (!fp->txqs[tc])
+					continue;
 				txq_idx = fp->txqs[tc]->queue_id;
 				qede_tx_queue_release(fp->txqs[tc]);
 				eth_dev->data->tx_queues[txq_idx] = NULL;
diff --git a/drivers/net/qede/qede_rxtx.h b/drivers/net/qede/qede_rxtx.h
index 3e1e977..2a8645a 100644
--- a/drivers/net/qede/qede_rxtx.h
+++ b/drivers/net/qede/qede_rxtx.h
@@ -64,9 +64,13 @@
 
 #define QEDE_ETH_OVERHEAD       (ETHER_HDR_LEN + 8 + 8 + QEDE_FW_RX_ALIGN_END)
 
-/* TBD: Excluding IPV6 */
-#define QEDE_RSS_OFFLOAD_ALL    (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | \
-				 ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_VXLAN)
+#define QEDE_RSS_OFFLOAD_ALL    (ETH_RSS_IPV4			|\
+				 ETH_RSS_NONFRAG_IPV4_TCP	|\
+				 ETH_RSS_NONFRAG_IPV4_UDP	|\
+				 ETH_RSS_IPV6			|\
+				 ETH_RSS_NONFRAG_IPV6_TCP	|\
+				 ETH_RSS_NONFRAG_IPV6_UDP	|\
+				 ETH_RSS_VXLAN)
 
 #define QEDE_TXQ_FLAGS		((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS)
 
-- 
1.7.10.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [dpdk-stable] [PATCH v2 6/7] net/qede: fix reporting of SR-IOV PF driver as disabled
       [not found] <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 2/7] net/qede: fix filtering code Harish Patil
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 5/7] net/qede: fix RSS related issue Harish Patil
@ 2016-12-23  0:48 ` Harish Patil
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 7/7] net/qede: restrict maximum queues for PF/VF Harish Patil
  3 siblings, 0 replies; 4+ messages in thread
From: Harish Patil @ 2016-12-23  0:48 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: Harish Patil, dev, stable, Dept-EngDPDKDev

qede PMD does not support SR-IOV PF driver functionality, so
max_vfs is set to 0 to imply the same.

Fixes: 2ea6f76aff40 ("qede: add core driver")

Signed-off-by: Harish Patil <harish.patil@qlogic.com>
---
 drivers/net/qede/qede_ethdev.c |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 00af0f6..93817ac 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -976,10 +976,7 @@ qede_dev_info_get(struct rte_eth_dev *eth_dev,
 	dev_info->max_rx_queues = (uint16_t)QEDE_MAX_RSS_CNT(qdev);
 	dev_info->max_tx_queues = dev_info->max_rx_queues;
 	dev_info->max_mac_addrs = qdev->dev_info.num_mac_addrs;
-	if (IS_VF(edev))
-		dev_info->max_vfs = 0;
-	else
-		dev_info->max_vfs = (uint16_t)NUM_OF_VFS(&qdev->edev);
+	dev_info->max_vfs = 0;
 	dev_info->reta_size = ECORE_RSS_IND_TABLE_SIZE;
 	dev_info->hash_key_size = ECORE_RSS_KEY_SIZE * sizeof(uint32_t);
 	dev_info->flow_type_rss_offloads = (uint64_t)QEDE_RSS_OFFLOAD_ALL;
-- 
1.7.10.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [dpdk-stable] [PATCH v2 7/7] net/qede: restrict maximum queues for PF/VF
       [not found] <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
                   ` (2 preceding siblings ...)
  2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 6/7] net/qede: fix reporting of SR-IOV PF driver as disabled Harish Patil
@ 2016-12-23  0:48 ` Harish Patil
  3 siblings, 0 replies; 4+ messages in thread
From: Harish Patil @ 2016-12-23  0:48 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: Harish Patil, dev, stable, Dept-EngDPDKDev

HW can support upto 128 queues based on the NIC config/personality.
But most of the testing is done with 32 queues for PF and 16 for VF
device across different qede devices, so change here is to advertise
only those many instead of returning max queues supported by HW.

Fixes: 2ea6f76aff40 ("qede: add core driver")

Signed-off-by: Harish Patil <harish.patil@qlogic.com>
---
 drivers/net/qede/qede_ethdev.c |   13 ++++++++++---
 drivers/net/qede/qede_ethdev.h |    3 +++
 drivers/net/qede/qede_main.c   |    5 -----
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 93817ac..d748d54 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -973,8 +973,15 @@ qede_dev_info_get(struct rte_eth_dev *eth_dev,
 	dev_info->max_rx_pktlen = (uint32_t)ETH_TX_MAX_NON_LSO_PKT_LEN;
 	dev_info->rx_desc_lim = qede_rx_desc_lim;
 	dev_info->tx_desc_lim = qede_tx_desc_lim;
-	dev_info->max_rx_queues = (uint16_t)QEDE_MAX_RSS_CNT(qdev);
+
+	if (IS_PF(edev))
+		dev_info->max_rx_queues = (uint16_t)RTE_MIN(
+			QEDE_MAX_RSS_CNT(qdev), QEDE_PF_NUM_CONNS / 2);
+	else
+		dev_info->max_rx_queues = (uint16_t)RTE_MIN(
+			QEDE_MAX_RSS_CNT(qdev), ECORE_MAX_VF_CHAINS_PER_PF);
 	dev_info->max_tx_queues = dev_info->max_rx_queues;
+
 	dev_info->max_mac_addrs = qdev->dev_info.num_mac_addrs;
 	dev_info->max_vfs = 0;
 	dev_info->reta_size = ECORE_RSS_IND_TABLE_SIZE;
@@ -2016,9 +2023,9 @@ static const struct eth_dev_ops qede_eth_vf_dev_ops = {
 static void qede_update_pf_params(struct ecore_dev *edev)
 {
 	struct ecore_pf_params pf_params;
-	/* 32 rx + 32 tx */
+
 	memset(&pf_params, 0, sizeof(struct ecore_pf_params));
-	pf_params.eth_pf_params.num_cons = 64;
+	pf_params.eth_pf_params.num_cons = QEDE_PF_NUM_CONNS;
 	qed_ops->common->update_pf_params(edev, &pf_params);
 }
 
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index bd85ba3..95e06ef 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -115,6 +115,9 @@
 
 extern char fw_file[];
 
+/* Number of PF connections - 32 RX + 32 TX */
+#define QEDE_PF_NUM_CONNS		(64)
+
 /* Port/function states */
 enum qede_dev_state {
 	QEDE_DEV_INIT, /* Init the chip and Slowpath */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index b769673..491c921 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -402,11 +402,6 @@ qed_fill_eth_dev_info(struct ecore_dev *edev, struct qed_dev_eth_info *info)
 		if (edev->num_hwfns > 1) {
 			ecore_vf_get_num_rxqs(&edev->hwfns[1], &queues);
 			info->num_queues += queues;
-			/* Restrict 100G VF to advertise 16 queues till the
-			 * required support is available to go beyond 16.
-			 */
-			info->num_queues = RTE_MIN(info->num_queues,
-						   ECORE_MAX_VF_CHAINS_PER_PF);
 		}
 
 		ecore_vf_get_num_vlan_filters(&edev->hwfns[0],
-- 
1.7.10.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-12-23  0:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 2/7] net/qede: fix filtering code Harish Patil
2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 5/7] net/qede: fix RSS related issue Harish Patil
2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 6/7] net/qede: fix reporting of SR-IOV PF driver as disabled Harish Patil
2016-12-23  0:48 ` [dpdk-stable] [PATCH v2 7/7] net/qede: restrict maximum queues for PF/VF Harish Patil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).