DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type
@ 2016-01-28 22:23 Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 2/4] szedata2: add functions for setting link up/down and updating link info Matej Vido
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Matej Vido @ 2016-01-28 22:23 UTC (permalink / raw)
  To: dev; +Cc: pus, viktorin

PMD was of type PMD_VDEV which means that PCI device is not recognised
automatically during EAL initialization, but it has to be created by
EAL option --vdev.
Now, PMD is of type PMD_PDEV which means that PCI device is probed
and recognised during EAL initialization automatically.
Path to szedata2 device file is matched with device and the count
of available RX and TX DMA channels is found out during device
initialization.
Initialization, starting and stopping of queues is changed to better
correspond with Ethernet device API model. Function callbacks
(rx|tx)_queue_(start|stop) are added. Unnecessary items are removed
from ethernet device private data structure.

Signed-off-by: Matej Vido <vido@cesnet.cz>
---
 drivers/net/szedata2/rte_eth_szedata2.c |  900 ++++++++++++-------------------
 drivers/net/szedata2/rte_eth_szedata2.h |    8 +
 2 files changed, 366 insertions(+), 542 deletions(-)

diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index 9f86c99..ef906f3 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -35,6 +35,8 @@
 #include <unistd.h>
 #include <stdbool.h>
 #include <err.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 #include <libsze2.h>
 
@@ -47,10 +49,6 @@
 
 #include "rte_eth_szedata2.h"
 
-#define RTE_ETH_SZEDATA2_DEV_PATH_ARG "dev_path"
-#define RTE_ETH_SZEDATA2_RX_IFACES_ARG "rx_ifaces"
-#define RTE_ETH_SZEDATA2_TX_IFACES_ARG "tx_ifaces"
-
 #define RTE_ETH_SZEDATA2_MAX_RX_QUEUES 32
 #define RTE_ETH_SZEDATA2_MAX_TX_QUEUES 32
 #define RTE_ETH_SZEDATA2_TX_LOCK_SIZE (32 * 1024 * 1024)
@@ -60,6 +58,11 @@
  */
 #define RTE_SZE2_PACKET_HEADER_SIZE_ALIGNED 8
 
+#define RTE_SZEDATA2_DRIVER_NAME "rte_szedata2_pmd"
+#define RTE_SZEDATA2_PCI_DRIVER_NAME "rte_szedata2_pmd"
+
+#define SZEDATA2_DEV_PATH_FMT "/dev/szedataII%u"
+
 struct szedata2_rx_queue {
 	struct szedata *sze;
 	uint8_t rx_channel;
@@ -74,57 +77,27 @@ struct szedata2_tx_queue {
 	struct szedata *sze;
 	uint8_t tx_channel;
 	volatile uint64_t tx_pkts;
-	volatile uint64_t err_pkts;
 	volatile uint64_t tx_bytes;
-};
-
-struct rxtx_szedata2 {
-	uint32_t num_of_rx;
-	uint32_t num_of_tx;
-	uint32_t sze_rx_mask_req;
-	uint32_t sze_tx_mask_req;
-	char *sze_dev;
+	volatile uint64_t err_pkts;
 };
 
 struct pmd_internals {
 	struct szedata2_rx_queue rx_queue[RTE_ETH_SZEDATA2_MAX_RX_QUEUES];
 	struct szedata2_tx_queue tx_queue[RTE_ETH_SZEDATA2_MAX_TX_QUEUES];
-	unsigned nb_rx_queues;
-	unsigned nb_tx_queues;
-	uint32_t num_of_rx;
-	uint32_t num_of_tx;
-	uint32_t sze_rx_req;
-	uint32_t sze_tx_req;
-	int if_index;
-	char *sze_dev;
-};
-
-static const char *valid_arguments[] = {
-	RTE_ETH_SZEDATA2_DEV_PATH_ARG,
-	RTE_ETH_SZEDATA2_RX_IFACES_ARG,
-	RTE_ETH_SZEDATA2_TX_IFACES_ARG,
-	NULL
+	uint16_t max_rx_queues;
+	uint16_t max_tx_queues;
+	char sze_dev[PATH_MAX];
 };
 
 static struct ether_addr eth_addr = {
 	.addr_bytes = { 0x00, 0x11, 0x17, 0x00, 0x00, 0x00 }
 };
-static const char *drivername = "SZEdata2 PMD";
 static struct rte_eth_link pmd_link = {
 		.link_speed = ETH_LINK_SPEED_10G,
 		.link_duplex = ETH_LINK_FULL_DUPLEX,
 		.link_status = 0
 };
 
-
-static uint32_t
-count_ones(uint32_t num)
-{
-	num = num - ((num >> 1) & 0x55555555); /* reuse input as temporary */
-	num = (num & 0x33333333) + ((num >> 2) & 0x33333333);        /* temp */
-	return (((num + (num >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; /* count */
-}
-
 static uint16_t
 eth_szedata2_rx(void *queue,
 		struct rte_mbuf **bufs,
@@ -905,288 +878,139 @@ next_packet:
 }
 
 static int
-init_rx_channels(struct rte_eth_dev *dev, int v)
+eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id)
 {
-	struct pmd_internals *internals = dev->data->dev_private;
+	struct szedata2_rx_queue *rxq = dev->data->rx_queues[rxq_id];
 	int ret;
-	uint32_t i;
-	uint32_t count = internals->num_of_rx;
-	uint32_t num_sub = 0;
-	uint32_t x;
-	uint32_t rx;
-	uint32_t tx;
-
-	rx = internals->sze_rx_req;
-	tx = 0;
-
-	for (i = 0; i < count; i++) {
-		/*
-		 * Open, subscribe rx,tx channels and start device
-		 */
-		if (v)
-			RTE_LOG(INFO, PMD, "Opening SZE device %u. time\n", i);
-
-		internals->rx_queue[num_sub].sze =
-			szedata_open(internals->sze_dev);
-		if (internals->rx_queue[num_sub].sze == NULL)
-			return -1;
-
-		/* separate least significant non-zero bit */
-		x = rx & ((~rx) + 1);
-
-		if (v)
-			RTE_LOG(INFO, PMD, "Subscribing rx channel: 0x%x "
-				"tx channel: 0x%x\n", x, tx);
-
-		ret = szedata_subscribe3(internals->rx_queue[num_sub].sze,
-				&x, &tx);
-		if (ret) {
-			szedata_close(internals->rx_queue[num_sub].sze);
-			internals->rx_queue[num_sub].sze = NULL;
-			return -1;
-		}
-
-		if (v)
-			RTE_LOG(INFO, PMD, "Subscribed rx channel: 0x%x "
-				"tx channel: 0x%x\n", x, tx);
-
-		if (x) {
-			if (v)
-				RTE_LOG(INFO, PMD, "Starting SZE device for "
-					"rx queue: %u\n", num_sub);
+	struct pmd_internals *internals = (struct pmd_internals *)
+		dev->data->dev_private;
+
+	if (rxq->sze == NULL) {
+		uint32_t rx = 1 << rxq->rx_channel;
+		uint32_t tx = 0;
+		rxq->sze = szedata_open(internals->sze_dev);
+		if (rxq->sze == NULL)
+			return -EINVAL;
+		ret = szedata_subscribe3(rxq->sze, &rx, &tx);
+		if (ret != 0 || rx == 0)
+			goto err;
+	}
 
-			ret = szedata_start(internals->rx_queue[num_sub].sze);
-			if (ret) {
-				szedata_close(internals->rx_queue[num_sub].sze);
-				internals->rx_queue[num_sub].sze = NULL;
-				return -1;
-			}
+	ret = szedata_start(rxq->sze);
+	if (ret != 0)
+		goto err;
+	dev->data->rx_queue_state[rxq_id] = RTE_ETH_QUEUE_STATE_STARTED;
+	return 0;
 
-			/*
-			 * set to 1 all bits lower than bit set to 1
-			 * and that bit to 0
-			 */
-			x -= 1;
-			internals->rx_queue[num_sub].rx_channel =
-				count_ones(x);
-
-			if (v)
-				RTE_LOG(INFO, PMD, "Subscribed rx channel "
-					"no: %u\n",
-					internals->rx_queue[num_sub].rx_channel
-					);
-
-			num_sub++;
-			internals->nb_rx_queues = num_sub;
-		} else {
-			if (v)
-				RTE_LOG(INFO, PMD,
-					"Could not subscribe any rx channel. "
-					"Closing SZE device\n");
+err:
+	szedata_close(rxq->sze);
+	rxq->sze = NULL;
+	return -EINVAL;
+}
 
-			szedata_close(internals->rx_queue[num_sub].sze);
-			internals->rx_queue[num_sub].sze = NULL;
-		}
+static int
+eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id)
+{
+	struct szedata2_rx_queue *rxq = dev->data->rx_queues[rxq_id];
 
-		/* set least significant non-zero bit to zero */
-		rx = rx & (rx - 1);
+	if (rxq->sze != NULL) {
+		szedata_close(rxq->sze);
+		rxq->sze = NULL;
 	}
 
-	dev->data->nb_rx_queues = (uint16_t)num_sub;
-
-	if (v)
-		RTE_LOG(INFO, PMD, "Successfully opened rx channels: %u\n",
-			num_sub);
-
+	dev->data->rx_queue_state[rxq_id] = RTE_ETH_QUEUE_STATE_STOPPED;
 	return 0;
 }
 
 static int
-init_tx_channels(struct rte_eth_dev *dev, int v)
+eth_tx_queue_start(struct rte_eth_dev *dev, uint16_t txq_id)
 {
-	struct pmd_internals *internals = dev->data->dev_private;
+	struct szedata2_tx_queue *txq = dev->data->tx_queues[txq_id];
 	int ret;
-	uint32_t i;
-	uint32_t count = internals->num_of_tx;
-	uint32_t num_sub = 0;
-	uint32_t x;
-	uint32_t rx;
-	uint32_t tx;
-
-	rx = 0;
-	tx = internals->sze_tx_req;
-
-	for (i = 0; i < count; i++) {
-		/*
-		 * Open, subscribe rx,tx channels and start device
-		 */
-		if (v)
-			RTE_LOG(INFO, PMD, "Opening SZE device %u. time\n",
-				i + internals->num_of_rx);
-
-		internals->tx_queue[num_sub].sze =
-			szedata_open(internals->sze_dev);
-		if (internals->tx_queue[num_sub].sze == NULL)
-			return -1;
-
-		/* separate least significant non-zero bit */
-		x = tx & ((~tx) + 1);
-
-		if (v)
-			RTE_LOG(INFO, PMD, "Subscribing rx channel: 0x%x "
-				"tx channel: 0x%x\n", rx, x);
-
-		ret = szedata_subscribe3(internals->tx_queue[num_sub].sze,
-				&rx, &x);
-		if (ret) {
-			szedata_close(internals->tx_queue[num_sub].sze);
-			internals->tx_queue[num_sub].sze = NULL;
-			return -1;
-		}
-
-		if (v)
-			RTE_LOG(INFO, PMD, "Subscribed rx channel: 0x%x "
-				"tx channel: 0x%x\n", rx, x);
-
-		if (x) {
-			if (v)
-				RTE_LOG(INFO, PMD, "Starting SZE device for "
-					"tx queue: %u\n", num_sub);
-
-			ret = szedata_start(internals->tx_queue[num_sub].sze);
-			if (ret) {
-				szedata_close(internals->tx_queue[num_sub].sze);
-				internals->tx_queue[num_sub].sze = NULL;
-				return -1;
-			}
-
-			/*
-			 * set to 1 all bits lower than bit set to 1
-			 * and that bit to 0
-			 */
-			x -= 1;
-			internals->tx_queue[num_sub].tx_channel =
-				count_ones(x);
-
-			if (v)
-				RTE_LOG(INFO, PMD, "Subscribed tx channel "
-					"no: %u\n",
-					internals->tx_queue[num_sub].tx_channel
-					);
-
-			num_sub++;
-			internals->nb_tx_queues = num_sub;
-		} else {
-			if (v)
-				RTE_LOG(INFO, PMD,
-					"Could not subscribe any tx channel. "
-					"Closing SZE device\n");
-
-			szedata_close(internals->tx_queue[num_sub].sze);
-			internals->tx_queue[num_sub].sze = NULL;
-		}
-
-		/* set least significant non-zero bit to zero */
-		tx = tx & (tx - 1);
+	struct pmd_internals *internals = (struct pmd_internals *)
+		dev->data->dev_private;
+
+	if (txq->sze == NULL) {
+		uint32_t rx = 0;
+		uint32_t tx = 1 << txq->tx_channel;
+		txq->sze = szedata_open(internals->sze_dev);
+		if (txq->sze == NULL)
+			return -EINVAL;
+		ret = szedata_subscribe3(txq->sze, &rx, &tx);
+		if (ret != 0 || tx == 0)
+			goto err;
 	}
 
-	dev->data->nb_tx_queues = (uint16_t)num_sub;
-
-	if (v)
-		RTE_LOG(INFO, PMD, "Successfully opened tx channels: %u\n",
-			num_sub);
-
+	ret = szedata_start(txq->sze);
+	if (ret != 0)
+		goto err;
+	dev->data->tx_queue_state[txq_id] = RTE_ETH_QUEUE_STATE_STARTED;
 	return 0;
-}
 
-static void
-close_rx_channels(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *internals = dev->data->dev_private;
-	uint32_t i;
-	uint32_t num_sub = internals->nb_rx_queues;
-
-	for (i = 0; i < num_sub; i++) {
-		if (internals->rx_queue[i].sze != NULL) {
-			szedata_close(internals->rx_queue[i].sze);
-			internals->rx_queue[i].sze = NULL;
-		}
-	}
-	/* set number of rx queues to zero */
-	internals->nb_rx_queues = 0;
-	dev->data->nb_rx_queues = (uint16_t)0;
+err:
+	szedata_close(txq->sze);
+	txq->sze = NULL;
+	return -EINVAL;
 }
 
-static void
-close_tx_channels(struct rte_eth_dev *dev)
+static int
+eth_tx_queue_stop(struct rte_eth_dev *dev, uint16_t txq_id)
 {
-	struct pmd_internals *internals = dev->data->dev_private;
-	uint32_t i;
-	uint32_t num_sub = internals->nb_tx_queues;
+	struct szedata2_tx_queue *txq = dev->data->tx_queues[txq_id];
 
-	for (i = 0; i < num_sub; i++) {
-		if (internals->tx_queue[i].sze != NULL) {
-			szedata_close(internals->tx_queue[i].sze);
-			internals->tx_queue[i].sze = NULL;
-		}
+	if (txq->sze != NULL) {
+		szedata_close(txq->sze);
+		txq->sze = NULL;
 	}
-	/* set number of rx queues to zero */
-	internals->nb_tx_queues = 0;
-	dev->data->nb_tx_queues = (uint16_t)0;
+
+	dev->data->tx_queue_state[txq_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+	return 0;
 }
 
 static int
 eth_dev_start(struct rte_eth_dev *dev)
 {
-	struct pmd_internals *internals = dev->data->dev_private;
 	int ret;
-
-	if (internals->nb_rx_queues == 0) {
-		ret = init_rx_channels(dev, 0);
-		if (ret != 0) {
-			close_rx_channels(dev);
-			return -1;
-		}
+	uint16_t i;
+	uint16_t nb_rx = dev->data->nb_rx_queues;
+	uint16_t nb_tx = dev->data->nb_tx_queues;
+
+	for (i = 0; i < nb_rx; i++) {
+		ret = eth_rx_queue_start(dev, i);
+		if (ret != 0)
+			goto err_rx;
 	}
 
-	if (internals->nb_tx_queues == 0) {
-		ret = init_tx_channels(dev, 0);
-		if (ret != 0) {
-			close_tx_channels(dev);
-			close_rx_channels(dev);
-			return -1;
-		}
+	for (i = 0; i < nb_tx; i++) {
+		ret = eth_tx_queue_start(dev, i);
+		if (ret != 0)
+			goto err_tx;
 	}
 
 	dev->data->dev_link.link_status = 1;
 	return 0;
+
+err_tx:
+	for (i = 0; i < nb_tx; i++)
+		eth_tx_queue_stop(dev, i);
+err_rx:
+	for (i = 0; i < nb_rx; i++)
+		eth_rx_queue_stop(dev, i);
+	return ret;
 }
 
 static void
 eth_dev_stop(struct rte_eth_dev *dev)
 {
-	unsigned i;
-	struct pmd_internals *internals = dev->data->dev_private;
+	uint16_t i;
+	uint16_t nb_rx = dev->data->nb_rx_queues;
+	uint16_t nb_tx = dev->data->nb_tx_queues;
 
-	for (i = 0; i < internals->nb_rx_queues; i++) {
-		if (internals->rx_queue[i].sze != NULL) {
-			szedata_close(internals->rx_queue[i].sze);
-			internals->rx_queue[i].sze = NULL;
-		}
-	}
+	for (i = 0; i < nb_tx; i++)
+		eth_tx_queue_stop(dev, i);
 
-	for (i = 0; i < internals->nb_tx_queues; i++) {
-		if (internals->tx_queue[i].sze != NULL) {
-			szedata_close(internals->tx_queue[i].sze);
-			internals->tx_queue[i].sze = NULL;
-		}
-	}
-
-	internals->nb_rx_queues = 0;
-	internals->nb_tx_queues = 0;
-
-	dev->data->nb_rx_queues = (uint16_t)0;
-	dev->data->nb_tx_queues = (uint16_t)0;
+	for (i = 0; i < nb_rx; i++)
+		eth_rx_queue_stop(dev, i);
 
 	dev->data->dev_link.link_status = 0;
 }
@@ -1210,44 +1034,42 @@ eth_dev_info(struct rte_eth_dev *dev,
 		struct rte_eth_dev_info *dev_info)
 {
 	struct pmd_internals *internals = dev->data->dev_private;
-	dev_info->driver_name = drivername;
-	dev_info->if_index = internals->if_index;
+	dev_info->if_index = 0;
 	dev_info->max_mac_addrs = 1;
 	dev_info->max_rx_pktlen = (uint32_t)-1;
-	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
-	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->max_rx_queues = internals->max_rx_queues;
+	dev_info->max_tx_queues = internals->max_tx_queues;
 	dev_info->min_rx_bufsize = 0;
-	dev_info->pci_dev = NULL;
 }
 
 static void
 eth_stats_get(struct rte_eth_dev *dev,
 		struct rte_eth_stats *stats)
 {
-	unsigned i;
+	uint16_t i;
+	uint16_t nb_rx = dev->data->nb_rx_queues;
+	uint16_t nb_tx = dev->data->nb_tx_queues;
 	uint64_t rx_total = 0;
 	uint64_t tx_total = 0;
 	uint64_t tx_err_total = 0;
 	uint64_t rx_total_bytes = 0;
 	uint64_t tx_total_bytes = 0;
-	const struct pmd_internals *internal = dev->data->dev_private;
+	const struct pmd_internals *internals = dev->data->dev_private;
 
-	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
-			i < internal->nb_rx_queues; i++) {
-		stats->q_ipackets[i] = internal->rx_queue[i].rx_pkts;
-		stats->q_ibytes[i] = internal->rx_queue[i].rx_bytes;
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < nb_rx; i++) {
+		stats->q_ipackets[i] = internals->rx_queue[i].rx_pkts;
+		stats->q_ibytes[i] = internals->rx_queue[i].rx_bytes;
 		rx_total += stats->q_ipackets[i];
 		rx_total_bytes += stats->q_ibytes[i];
 	}
 
-	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
-			i < internal->nb_tx_queues; i++) {
-		stats->q_opackets[i] = internal->tx_queue[i].tx_pkts;
-		stats->q_errors[i] = internal->tx_queue[i].err_pkts;
-		stats->q_obytes[i] = internal->tx_queue[i].tx_bytes;
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < nb_tx; i++) {
+		stats->q_opackets[i] = internals->tx_queue[i].tx_pkts;
+		stats->q_obytes[i] = internals->tx_queue[i].tx_bytes;
+		stats->q_errors[i] = internals->tx_queue[i].err_pkts;
 		tx_total += stats->q_opackets[i];
-		tx_err_total += stats->q_errors[i];
 		tx_total_bytes += stats->q_obytes[i];
+		tx_err_total += stats->q_errors[i];
 	}
 
 	stats->ipackets = rx_total;
@@ -1260,49 +1082,62 @@ eth_stats_get(struct rte_eth_dev *dev,
 static void
 eth_stats_reset(struct rte_eth_dev *dev)
 {
-	unsigned i;
-	struct pmd_internals *internal = dev->data->dev_private;
-	for (i = 0; i < internal->nb_rx_queues; i++) {
-		internal->rx_queue[i].rx_pkts = 0;
-		internal->rx_queue[i].rx_bytes = 0;
+	uint16_t i;
+	uint16_t nb_rx = dev->data->nb_rx_queues;
+	uint16_t nb_tx = dev->data->nb_tx_queues;
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	for (i = 0; i < nb_rx; i++) {
+		internals->rx_queue[i].rx_pkts = 0;
+		internals->rx_queue[i].rx_bytes = 0;
+		internals->rx_queue[i].err_pkts = 0;
 	}
-	for (i = 0; i < internal->nb_tx_queues; i++) {
-		internal->tx_queue[i].tx_pkts = 0;
-		internal->tx_queue[i].err_pkts = 0;
-		internal->tx_queue[i].tx_bytes = 0;
+	for (i = 0; i < nb_tx; i++) {
+		internals->tx_queue[i].tx_pkts = 0;
+		internals->tx_queue[i].tx_bytes = 0;
+		internals->tx_queue[i].err_pkts = 0;
 	}
 }
 
 static void
-eth_dev_close(struct rte_eth_dev *dev)
+eth_rx_queue_release(void *q)
 {
-	unsigned i;
-	struct pmd_internals *internals = dev->data->dev_private;
-
-	for (i = 0; i < internals->nb_rx_queues; i++) {
-		if (internals->rx_queue[i].sze != NULL) {
-			szedata_close(internals->rx_queue[i].sze);
-			internals->rx_queue[i].sze = NULL;
-		}
+	struct szedata2_rx_queue *rxq = (struct szedata2_rx_queue *)q;
+	if (rxq->sze != NULL) {
+		szedata_close(rxq->sze);
+		rxq->sze = NULL;
 	}
+}
 
-	for (i = 0; i < internals->nb_tx_queues; i++) {
-		if (internals->tx_queue[i].sze != NULL) {
-			szedata_close(internals->tx_queue[i].sze);
-			internals->tx_queue[i].sze = NULL;
-		}
+static void
+eth_tx_queue_release(void *q)
+{
+	struct szedata2_tx_queue *txq = (struct szedata2_tx_queue *)q;
+	if (txq->sze != NULL) {
+		szedata_close(txq->sze);
+		txq->sze = NULL;
 	}
-
-	internals->nb_rx_queues = 0;
-	internals->nb_tx_queues = 0;
-
-	dev->data->nb_rx_queues = (uint16_t)0;
-	dev->data->nb_tx_queues = (uint16_t)0;
 }
 
 static void
-eth_queue_release(void *q __rte_unused)
+eth_dev_close(struct rte_eth_dev *dev)
 {
+	uint16_t i;
+	uint16_t nb_rx = dev->data->nb_rx_queues;
+	uint16_t nb_tx = dev->data->nb_tx_queues;
+
+	eth_dev_stop(dev);
+
+	for (i = 0; i < nb_rx; i++) {
+		eth_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+	dev->data->nb_rx_queues = 0;
+	for (i = 0; i < nb_tx; i++) {
+		eth_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
+	dev->data->nb_tx_queues = 0;
 }
 
 static int
@@ -1321,11 +1156,28 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 		struct rte_mempool *mb_pool)
 {
 	struct pmd_internals *internals = dev->data->dev_private;
-	struct szedata2_rx_queue *szedata2_q =
-		&internals->rx_queue[rx_queue_id];
-	szedata2_q->mb_pool = mb_pool;
-	dev->data->rx_queues[rx_queue_id] = szedata2_q;
-	szedata2_q->in_port = dev->data->port_id;
+	struct szedata2_rx_queue *rxq = &internals->rx_queue[rx_queue_id];
+	int ret;
+	uint32_t rx = 1 << rx_queue_id;
+	uint32_t tx = 0;
+
+	rxq->sze = szedata_open(internals->sze_dev);
+	if (rxq->sze == NULL)
+		return -EINVAL;
+	ret = szedata_subscribe3(rxq->sze, &rx, &tx);
+	if (ret != 0 || rx == 0) {
+		szedata_close(rxq->sze);
+		rxq->sze = NULL;
+		return -EINVAL;
+	}
+	rxq->rx_channel = rx_queue_id;
+	rxq->in_port = dev->data->port_id;
+	rxq->mb_pool = mb_pool;
+	rxq->rx_pkts = 0;
+	rxq->rx_bytes = 0;
+	rxq->err_pkts = 0;
+
+	dev->data->rx_queues[rx_queue_id] = rxq;
 	return 0;
 }
 
@@ -1337,7 +1189,26 @@ eth_tx_queue_setup(struct rte_eth_dev *dev,
 		const struct rte_eth_txconf *tx_conf __rte_unused)
 {
 	struct pmd_internals *internals = dev->data->dev_private;
-	dev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id];
+	struct szedata2_tx_queue *txq = &internals->tx_queue[tx_queue_id];
+	int ret;
+	uint32_t rx = 0;
+	uint32_t tx = 1 << tx_queue_id;
+
+	txq->sze = szedata_open(internals->sze_dev);
+	if (txq->sze == NULL)
+		return -EINVAL;
+	ret = szedata_subscribe3(txq->sze, &rx, &tx);
+	if (ret != 0 || tx == 0) {
+		szedata_close(txq->sze);
+		txq->sze = NULL;
+		return -EINVAL;
+	}
+	txq->tx_channel = tx_queue_id;
+	txq->tx_pkts = 0;
+	txq->tx_bytes = 0;
+	txq->err_pkts = 0;
+
+	dev->data->tx_queues[tx_queue_id] = txq;
 	return 0;
 }
 
@@ -1353,272 +1224,217 @@ static struct eth_dev_ops ops = {
 		.dev_close          = eth_dev_close,
 		.dev_configure      = eth_dev_configure,
 		.dev_infos_get      = eth_dev_info,
+		.rx_queue_start     = eth_rx_queue_start,
+		.rx_queue_stop      = eth_rx_queue_stop,
+		.tx_queue_start     = eth_tx_queue_start,
+		.tx_queue_stop      = eth_tx_queue_stop,
 		.rx_queue_setup     = eth_rx_queue_setup,
 		.tx_queue_setup     = eth_tx_queue_setup,
-		.rx_queue_release   = eth_queue_release,
-		.tx_queue_release   = eth_queue_release,
+		.rx_queue_release   = eth_rx_queue_release,
+		.tx_queue_release   = eth_tx_queue_release,
 		.link_update        = eth_link_update,
 		.stats_get          = eth_stats_get,
 		.stats_reset        = eth_stats_reset,
 		.mac_addr_set       = eth_mac_addr_set,
 };
 
+/*
+ * This function goes through sysfs and looks for an index of szedata2
+ * device file (/dev/szedataIIX, where X is the index).
+ *
+ * @return
+ *           0 on success
+ *          -1 on error
+ */
 static int
-parse_mask(const char *mask_str, uint32_t *mask_num)
-{
-	char *endptr;
-	long int value;
-
-	value = strtol(mask_str, &endptr, 0);
-	if (*endptr != '\0' || value > UINT32_MAX || value < 0)
-		return -1;
-
-	*mask_num = (uint32_t)value;
-	return 0;
-}
-
-static int
-add_rx_mask(const char *key __rte_unused, const char *value, void *extra_args)
-{
-	struct rxtx_szedata2 *szedata2 = extra_args;
-	uint32_t mask;
-
-	if (parse_mask(value, &mask) != 0)
-		return -1;
-
-	szedata2->sze_rx_mask_req |= mask;
-	return 0;
-}
-
-static int
-add_tx_mask(const char *key __rte_unused, const char *value, void *extra_args)
+get_szedata2_index(struct rte_eth_dev *dev, uint32_t *index)
 {
-	struct rxtx_szedata2 *szedata2 = extra_args;
-	uint32_t mask;
-
-	if (parse_mask(value, &mask) != 0)
+	DIR *dir;
+	struct dirent *entry;
+	int ret;
+	uint32_t tmp_index;
+	FILE *fd;
+	char pcislot_path[PATH_MAX];
+	struct rte_pci_addr pcislot_addr = dev->pci_dev->addr;
+	uint32_t domain;
+	uint32_t bus;
+	uint32_t devid;
+	uint32_t function;
+
+	dir = opendir("/sys/class/combo");
+	if (dir == NULL)
 		return -1;
 
-	szedata2->sze_tx_mask_req |= mask;
-	return 0;
-}
-
-static int
-rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues,
-		const unsigned nb_tx_queues,
-		const unsigned numa_node,
-		struct pmd_internals **internals,
-		struct rte_eth_dev **eth_dev)
-{
-	struct rte_eth_dev_data *data = NULL;
-
-	RTE_LOG(INFO, PMD,
-			"Creating szedata2-backed ethdev on numa socket %u\n",
-			numa_node);
-
 	/*
-	 * now do all data allocation - for eth_dev structure
-	 * and internal (private) data
+	 * Iterate through all combosixX directories.
+	 * When the value in /sys/class/combo/combosixX/device/pcislot
+	 * file is the location of the ethernet device dev, "X" is the
+	 * index of the device.
 	 */
-	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
-	if (data == NULL)
-		goto error;
-
-	*internals = rte_zmalloc_socket(name, sizeof(**internals), 0,
-			numa_node);
-	if (*internals == NULL)
-		goto error;
-
-	/* reserve an ethdev entry */
-	*eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
-	if (*eth_dev == NULL)
-		goto error;
-
-	/*
-	 * now put it all together
-	 * - store queue data in internals,
-	 * - store numa_node info in pci_driver
-	 * - point eth_dev_data to internals
-	 * - and point eth_dev structure to new eth_dev_data structure
-	 *
-	 * NOTE: we'll replace the data element, of originally allocated eth_dev
-	 * so the rings are local per-process
-	 */
-
-	(*internals)->nb_rx_queues = nb_rx_queues;
-	(*internals)->nb_tx_queues = nb_tx_queues;
+	while ((entry = readdir(dir)) != NULL) {
+		ret = sscanf(entry->d_name, "combosix%u", &tmp_index);
+		if (ret != 1)
+			continue;
 
-	(*internals)->if_index = 0;
+		snprintf(pcislot_path, PATH_MAX,
+			"/sys/class/combo/combosix%u/device/pcislot",
+			tmp_index);
 
-	data->dev_private = *internals;
-	data->port_id = (*eth_dev)->data->port_id;
-	snprintf(data->name, sizeof(data->name), "%s", (*eth_dev)->data->name);
-	data->nb_rx_queues = (uint16_t)nb_rx_queues;
-	data->nb_tx_queues = (uint16_t)nb_tx_queues;
-	data->dev_link = pmd_link;
-	data->mac_addrs = &eth_addr;
+		fd = fopen(pcislot_path, "r");
+		if (fd == NULL)
+			continue;
 
-	(*eth_dev)->data = data;
-	(*eth_dev)->dev_ops = &ops;
-	(*eth_dev)->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
-	(*eth_dev)->driver = NULL;
-	(*eth_dev)->data->kdrv = RTE_KDRV_NONE;
-	(*eth_dev)->data->drv_name = drivername;
-	(*eth_dev)->data->numa_node = numa_node;
+		ret = fscanf(fd, "%4" PRIx16 ":%2" PRIx8 ":%2" PRIx8 ".%" PRIx8,
+				&domain, &bus, &devid, &function);
+		fclose(fd);
+		if (ret != 4)
+			continue;
 
-	return 0;
+		if (pcislot_addr.domain == domain &&
+				pcislot_addr.bus == bus &&
+				pcislot_addr.devid == devid &&
+				pcislot_addr.function == function) {
+			*index = tmp_index;
+			closedir(dir);
+			return 0;
+		}
+	}
 
-error:
-	rte_free(data);
-	rte_free(*internals);
+	closedir(dir);
 	return -1;
 }
 
 static int
-rte_eth_from_szedata2(const char *name,
-		struct rxtx_szedata2 *szedata2,
-		const unsigned numa_node)
+rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 {
-	struct pmd_internals *internals = NULL;
-	struct rte_eth_dev *eth_dev = NULL;
-	struct rte_eth_dev_data *data = NULL;
+	struct rte_eth_dev_data *data = dev->data;
+	struct pmd_internals *internals = (struct pmd_internals *)
+		data->dev_private;
+	struct szedata *szedata_temp;
 	int ret;
+	uint32_t szedata2_index;
+	struct rte_pci_addr pciaddr = dev->pci_dev->addr;
 
-	if (rte_pmd_init_internals(name, 0, 0, numa_node,
-			&internals, &eth_dev) < 0)
-		return -1;
-
-	data = eth_dev->data;
-
-	internals->sze_dev = szedata2->sze_dev;
-	internals->sze_rx_req = szedata2->sze_rx_mask_req;
-	internals->sze_tx_req = szedata2->sze_tx_mask_req;
-	internals->num_of_rx = szedata2->num_of_rx;
-	internals->num_of_tx = szedata2->num_of_tx;
-
-	RTE_LOG(INFO, PMD, "Number of rx channels to open: %u mask: 0x%x\n",
-			internals->num_of_rx, internals->sze_rx_req);
-	RTE_LOG(INFO, PMD, "Number of tx channels to open: %u mask: 0x%x\n",
-			internals->num_of_tx, internals->sze_tx_req);
+	RTE_LOG(INFO, PMD, "Initializing szedata2 device (" PCI_PRI_FMT ")\n",
+			pciaddr.domain, pciaddr.bus, pciaddr.devid,
+			pciaddr.function);
 
-	ret = init_rx_channels(eth_dev, 1);
+	/* Get index of szedata2 device file and create path to device file */
+	ret = get_szedata2_index(dev, &szedata2_index);
 	if (ret != 0) {
-		close_rx_channels(eth_dev);
-		return -1;
+		RTE_LOG(ERR, PMD, "Failed to get szedata2 device index!\n");
+		return -ENODEV;
 	}
+	snprintf(internals->sze_dev, PATH_MAX, SZEDATA2_DEV_PATH_FMT,
+			szedata2_index);
 
-	ret = init_tx_channels(eth_dev, 1);
-	if (ret != 0) {
-		close_tx_channels(eth_dev);
-		close_rx_channels(eth_dev);
-		return -1;
+	RTE_LOG(INFO, PMD, "SZEDATA2 path: %s\n", internals->sze_dev);
+
+	/*
+	 * Get number of available DMA RX and TX channels, which is maximum
+	 * number of queues that can be created and store it in private device
+	 * data structure.
+	 */
+	szedata_temp = szedata_open(internals->sze_dev);
+	if (szedata_temp == NULL) {
+		RTE_LOG(ERR, PMD, "szedata_open(): failed to open %s",
+				internals->sze_dev);
+		return -EINVAL;
 	}
+	internals->max_rx_queues = szedata_ifaces_available(szedata_temp,
+			SZE2_DIR_RX);
+	internals->max_tx_queues = szedata_ifaces_available(szedata_temp,
+			SZE2_DIR_TX);
+	szedata_close(szedata_temp);
+
+	RTE_LOG(INFO, PMD, "Available DMA channels RX: %u, TX: %u\n",
+			internals->max_rx_queues, internals->max_tx_queues);
 
+	/* Set rx, tx burst functions */
 	if (data->dev_conf.rxmode.enable_scatter == 1 ||
 		data->scattered_rx == 1) {
-		eth_dev->rx_pkt_burst = eth_szedata2_rx_scattered;
+		dev->rx_pkt_burst = eth_szedata2_rx_scattered;
 		data->scattered_rx = 1;
 	} else {
-		eth_dev->rx_pkt_burst = eth_szedata2_rx;
+		dev->rx_pkt_burst = eth_szedata2_rx;
 		data->scattered_rx = 0;
 	}
-	eth_dev->tx_pkt_burst = eth_szedata2_tx;
+	dev->tx_pkt_burst = eth_szedata2_tx;
 
-	return 0;
-}
-
-
-static int
-rte_pmd_szedata2_devinit(const char *name, const char *params)
-{
-	unsigned numa_node;
-	int ret;
-	struct rte_kvargs *kvlist;
-	unsigned k_idx;
-	struct rte_kvargs_pair *pair = NULL;
-	struct rxtx_szedata2 szedata2 = { 0, 0, 0, 0, NULL };
-	bool dev_path_missing = true;
+	/* Set function callbacks for Ethernet API */
+	dev->dev_ops = &ops;
 
-	RTE_LOG(INFO, PMD, "Initializing pmd_szedata2 for %s\n", name);
+	rte_eth_copy_pci_info(dev, dev->pci_dev);
 
-	numa_node = rte_socket_id();
-
-	kvlist = rte_kvargs_parse(params, valid_arguments);
-	if (kvlist == NULL)
-		return -1;
-
-	/*
-	 * Get szedata2 device path and rx,tx channels from passed arguments.
-	 */
-
-	if (rte_kvargs_count(kvlist, RTE_ETH_SZEDATA2_DEV_PATH_ARG) != 1)
-		goto err;
-
-	if (rte_kvargs_count(kvlist, RTE_ETH_SZEDATA2_RX_IFACES_ARG) < 1)
-		goto err;
-
-	if (rte_kvargs_count(kvlist, RTE_ETH_SZEDATA2_TX_IFACES_ARG) < 1)
-		goto err;
+	data->dev_link = pmd_link;
 
-	for (k_idx = 0; k_idx < kvlist->count; k_idx++) {
-		pair = &kvlist->pairs[k_idx];
-		if (strstr(pair->key, RTE_ETH_SZEDATA2_DEV_PATH_ARG) != NULL) {
-			szedata2.sze_dev = pair->value;
-			dev_path_missing = false;
-			break;
-		}
+	data->mac_addrs = rte_zmalloc(data->name, sizeof(struct ether_addr),
+			RTE_CACHE_LINE_SIZE);
+	if (data->mac_addrs == NULL) {
+		RTE_LOG(ERR, PMD, "Could not alloc space for MAC address!\n");
+		return -EINVAL;
 	}
 
-	if (dev_path_missing)
-		goto err;
-
-	ret = rte_kvargs_process(kvlist, RTE_ETH_SZEDATA2_RX_IFACES_ARG,
-			&add_rx_mask, &szedata2);
-	if (ret < 0)
-		goto err;
-
-	ret = rte_kvargs_process(kvlist, RTE_ETH_SZEDATA2_TX_IFACES_ARG,
-			&add_tx_mask, &szedata2);
-	if (ret < 0)
-		goto err;
+	ether_addr_copy(&eth_addr, data->mac_addrs);
 
-	szedata2.num_of_rx = count_ones(szedata2.sze_rx_mask_req);
-	szedata2.num_of_tx = count_ones(szedata2.sze_tx_mask_req);
-
-	RTE_LOG(INFO, PMD, "SZE device found at path %s\n", szedata2.sze_dev);
-
-	return rte_eth_from_szedata2(name, &szedata2, numa_node);
-err:
-	rte_kvargs_free(kvlist);
-	return -1;
+	return 0;
 }
 
 static int
-rte_pmd_szedata2_devuninit(const char *name)
+rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 {
-	struct rte_eth_dev *dev = NULL;
+	rte_free(dev->data->mac_addrs);
+	dev->data->mac_addrs = NULL;
+	return 0;
+}
 
-	RTE_LOG(INFO, PMD, "Uninitializing pmd_szedata2 for %s "
-			"on numa socket %u\n", name, rte_socket_id());
+static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
+	{
+		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE,
+				PCI_DEVICE_ID_NETCOPE_COMBO80G)
+	},
+	{
+		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE,
+				PCI_DEVICE_ID_NETCOPE_COMBO100G)
+	},
+	{
+		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE,
+				PCI_DEVICE_ID_NETCOPE_COMBO100G2)
+	},
+	{
+		.vendor_id = 0,
+	}
+};
 
-	if (name == NULL)
-		return -1;
+static struct eth_driver szedata2_eth_driver = {
+	.pci_drv = {
+		.name     = RTE_SZEDATA2_PCI_DRIVER_NAME,
+		.id_table = rte_szedata2_pci_id_table,
+	},
+	.eth_dev_init     = rte_szedata2_eth_dev_init,
+	.eth_dev_uninit   = rte_szedata2_eth_dev_uninit,
+	.dev_private_size = sizeof(struct pmd_internals),
+};
 
-	dev = rte_eth_dev_allocated(name);
-	if (dev == NULL)
-		return -1;
+static int
+rte_szedata2_init(const char *name __rte_unused,
+		const char *args __rte_unused)
+{
+	rte_eth_driver_register(&szedata2_eth_driver);
+	return 0;
+}
 
-	rte_free(dev->data->dev_private);
-	rte_free(dev->data);
-	rte_eth_dev_release_port(dev);
+static int
+rte_szedata2_uninit(const char *name __rte_unused)
+{
 	return 0;
 }
 
-static struct rte_driver pmd_szedata2_drv = {
-	.name = "eth_szedata2",
-	.type = PMD_VDEV,
-	.init = rte_pmd_szedata2_devinit,
-	.uninit = rte_pmd_szedata2_devuninit,
+static struct rte_driver rte_szedata2_driver = {
+	.type = PMD_PDEV,
+	.name = RTE_SZEDATA2_DRIVER_NAME,
+	.init = rte_szedata2_init,
+	.uninit = rte_szedata2_uninit,
 };
 
-PMD_REGISTER_DRIVER(pmd_szedata2_drv);
+PMD_REGISTER_DRIVER(rte_szedata2_driver);
diff --git a/drivers/net/szedata2/rte_eth_szedata2.h b/drivers/net/szedata2/rte_eth_szedata2.h
index 4d09a98..7137ba2 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.h
+++ b/drivers/net/szedata2/rte_eth_szedata2.h
@@ -34,6 +34,14 @@
 #ifndef RTE_PMD_SZEDATA2_H_
 #define RTE_PMD_SZEDATA2_H_
 
+/* PCI Vendor ID */
+#define PCI_VENDOR_ID_NETCOPE 0x1b26
+
+/* PCI Device IDs */
+#define PCI_DEVICE_ID_NETCOPE_COMBO80G 0xcb80
+#define PCI_DEVICE_ID_NETCOPE_COMBO100G 0xc1c1
+#define PCI_DEVICE_ID_NETCOPE_COMBO100G2 0xc2c1
+
 /* szedata2_packet header length == 4 bytes == 2B segment size + 2B hw size */
 #define RTE_SZE2_PACKET_HEADER_SIZE 4
 
-- 
1.7.1

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

* [dpdk-dev] [PATCH 2/4] szedata2: add functions for setting link up/down and updating link info
  2016-01-28 22:23 [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Matej Vido
@ 2016-01-28 22:23 ` Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 3/4] szedata2: add functions for enabling/disabling promiscuous, allmulticast modes Matej Vido
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Matej Vido @ 2016-01-28 22:23 UTC (permalink / raw)
  To: dev; +Cc: pus, viktorin

Mmap PCI resource file and add inline functions for reading from and
writing to PCI resource address space.
Add description of IBUF and OBUF address space.
Add configuration option for setting which firmware type will be used.
Right address space values for IBUFs and OBUFs offsets are used
according to configuration option CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS.
Setting link up/down and getting info about link status is done through
mmapped PCI resource address space.

Signed-off-by: Matej Vido <vido@cesnet.cz>
---
 config/common_linuxapp                  |   11 +
 drivers/net/szedata2/rte_eth_szedata2.c |  152 +++++++++++++--
 drivers/net/szedata2/rte_eth_szedata2.h |  315 ++++++++++++++++++++++++++++++-
 3 files changed, 462 insertions(+), 16 deletions(-)

diff --git a/config/common_linuxapp b/config/common_linuxapp
index 74bc515..43a795c 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -264,6 +264,17 @@ CONFIG_RTE_LIBRTE_NFP_DEBUG=n
 # Compile software PMD backed by SZEDATA2 device
 #
 CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n
+##
+## Defines firmware type address space.
+## RTE_LIBRTE_PMD_SZEDATA2_AS can be:
+## 0 - for firmwares:
+##         NIC_100G1_LR4
+##         HANIC_100G1_LR4
+##         HANIC_100G1_SR10
+##
+## Other values raise compile time error
+##
+CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
 
 #
 # Compile burst-oriented VIRTIO PMD driver
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index ef906f3..d8c260b 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2015 CESNET
+ *   Copyright (c) 2015 - 2016 CESNET
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,9 @@
 #include <err.h>
 #include <sys/types.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
 
 #include <libsze2.h>
 
@@ -46,6 +49,7 @@
 #include <rte_memcpy.h>
 #include <rte_kvargs.h>
 #include <rte_dev.h>
+#include <rte_atomic.h>
 
 #include "rte_eth_szedata2.h"
 
@@ -92,11 +96,6 @@ struct pmd_internals {
 static struct ether_addr eth_addr = {
 	.addr_bytes = { 0x00, 0x11, 0x17, 0x00, 0x00, 0x00 }
 };
-static struct rte_eth_link pmd_link = {
-		.link_speed = ETH_LINK_SPEED_10G,
-		.link_duplex = ETH_LINK_FULL_DUPLEX,
-		.link_status = 0
-};
 
 static uint16_t
 eth_szedata2_rx(void *queue,
@@ -987,7 +986,6 @@ eth_dev_start(struct rte_eth_dev *dev)
 			goto err_tx;
 	}
 
-	dev->data->dev_link.link_status = 1;
 	return 0;
 
 err_tx:
@@ -1011,8 +1009,6 @@ eth_dev_stop(struct rte_eth_dev *dev)
 
 	for (i = 0; i < nb_rx; i++)
 		eth_rx_queue_stop(dev, i);
-
-	dev->data->dev_link.link_status = 0;
 }
 
 static int
@@ -1141,9 +1137,76 @@ eth_dev_close(struct rte_eth_dev *dev)
 }
 
 static int
-eth_link_update(struct rte_eth_dev *dev __rte_unused,
+eth_link_update(struct rte_eth_dev *dev,
 		int wait_to_complete __rte_unused)
 {
+	struct rte_eth_link link;
+	struct rte_eth_link *link_ptr = &link;
+	struct rte_eth_link *dev_link = &dev->data->dev_link;
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+
+	switch (cgmii_link_speed(ibuf)) {
+	case SZEDATA2_LINK_SPEED_10G:
+		link.link_speed = ETH_LINK_SPEED_10G;
+		break;
+	case SZEDATA2_LINK_SPEED_40G:
+		link.link_speed = ETH_LINK_SPEED_40G;
+		break;
+	case SZEDATA2_LINK_SPEED_100G:
+		/*
+		 * TODO
+		 * If link_speed value from rte_eth_link structure
+		 * will be changed to support 100Gbps speed change
+		 * this value to 100G.
+		 */
+		link.link_speed = ETH_LINK_SPEED_10G;
+		break;
+	default:
+		link.link_speed = ETH_LINK_SPEED_10G;
+		break;
+	}
+
+	/* szedata2 uses only full duplex */
+	link.link_duplex = ETH_LINK_FULL_DUPLEX;
+
+	link.link_status = (cgmii_ibuf_is_enabled(ibuf) &&
+			cgmii_ibuf_is_link_up(ibuf)) ? 1 : 0;
+
+	rte_atomic64_cmpset((uint64_t *)dev_link, *(uint64_t *)dev_link,
+			*(uint64_t *)link_ptr);
+
+	return 0;
+}
+
+static int
+eth_dev_set_link_up(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	volatile struct szedata2_cgmii_obuf *obuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_OBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_obuf *);
+
+	cgmii_ibuf_enable(ibuf);
+	cgmii_obuf_enable(obuf);
+	return 0;
+}
+
+static int
+eth_dev_set_link_down(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	volatile struct szedata2_cgmii_obuf *obuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_OBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_obuf *);
+
+	cgmii_ibuf_disable(ibuf);
+	cgmii_obuf_disable(obuf);
 	return 0;
 }
 
@@ -1221,6 +1284,8 @@ eth_mac_addr_set(struct rte_eth_dev *dev __rte_unused,
 static struct eth_dev_ops ops = {
 		.dev_start          = eth_dev_start,
 		.dev_stop           = eth_dev_stop,
+		.dev_set_link_up    = eth_dev_set_link_up,
+		.dev_set_link_down  = eth_dev_set_link_down,
 		.dev_close          = eth_dev_close,
 		.dev_configure      = eth_dev_configure,
 		.dev_infos_get      = eth_dev_info,
@@ -1313,11 +1378,16 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 	struct szedata *szedata_temp;
 	int ret;
 	uint32_t szedata2_index;
-	struct rte_pci_addr pciaddr = dev->pci_dev->addr;
+	struct rte_pci_addr *pci_addr = &dev->pci_dev->addr;
+	struct rte_pci_resource *pci_rsc =
+		&dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER];
+	char rsc_filename[PATH_MAX];
+	void *pci_resource_ptr = NULL;
+	int fd;
 
 	RTE_LOG(INFO, PMD, "Initializing szedata2 device (" PCI_PRI_FMT ")\n",
-			pciaddr.domain, pciaddr.bus, pciaddr.devid,
-			pciaddr.function);
+			pci_addr->domain, pci_addr->bus, pci_addr->devid,
+			pci_addr->function);
 
 	/* Get index of szedata2 device file and create path to device file */
 	ret = get_szedata2_index(dev, &szedata2_index);
@@ -1347,7 +1417,7 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 			SZE2_DIR_TX);
 	szedata_close(szedata_temp);
 
-	RTE_LOG(INFO, PMD, "Available DMA channels RX: %u, TX: %u\n",
+	RTE_LOG(INFO, PMD, "Available DMA channels RX: %u TX: %u\n",
 			internals->max_rx_queues, internals->max_tx_queues);
 
 	/* Set rx, tx burst functions */
@@ -1366,25 +1436,77 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 
 	rte_eth_copy_pci_info(dev, dev->pci_dev);
 
-	data->dev_link = pmd_link;
+	/* mmap pci resource0 file to rte_pci_resource structure */
+	if (dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].phys_addr ==
+			0) {
+		RTE_LOG(ERR, PMD, "Missing resource%u file\n",
+				PCI_RESOURCE_NUMBER);
+		return -EINVAL;
+	}
+	snprintf(rsc_filename, PATH_MAX,
+		SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%u",
+		pci_addr->domain, pci_addr->bus,
+		pci_addr->devid, pci_addr->function, PCI_RESOURCE_NUMBER);
+	fd = open(rsc_filename, O_RDWR);
+	if (fd < 0) {
+		RTE_LOG(ERR, PMD, "Could not open file %s\n", rsc_filename);
+		return -EINVAL;
+	}
+
+	pci_resource_ptr = mmap(0,
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].len,
+			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	close(fd);
+	if (pci_resource_ptr == NULL) {
+		RTE_LOG(ERR, PMD, "Could not mmap file %s (fd = %d)\n",
+				rsc_filename, fd);
+		return -EINVAL;
+	}
+	dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr =
+		pci_resource_ptr;
+
+	RTE_LOG(DEBUG, PMD, "resource%u phys_addr = 0x%llx len = %llu "
+			"virt addr = %llx\n", PCI_RESOURCE_NUMBER,
+			(unsigned long long)pci_rsc->phys_addr,
+			(unsigned long long)pci_rsc->len,
+			(unsigned long long)pci_rsc->addr);
+
+	eth_link_update(dev, 0);
 
 	data->mac_addrs = rte_zmalloc(data->name, sizeof(struct ether_addr),
 			RTE_CACHE_LINE_SIZE);
 	if (data->mac_addrs == NULL) {
 		RTE_LOG(ERR, PMD, "Could not alloc space for MAC address!\n");
+		munmap(dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr,
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].len);
 		return -EINVAL;
 	}
 
 	ether_addr_copy(&eth_addr, data->mac_addrs);
 
+	RTE_LOG(INFO, PMD, "szedata2 device ("
+			PCI_PRI_FMT ") successfully initialized\n",
+			pci_addr->domain, pci_addr->bus, pci_addr->devid,
+			pci_addr->function);
+
 	return 0;
 }
 
 static int
 rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 {
+	struct rte_pci_addr *pci_addr = &dev->pci_dev->addr;
+
 	rte_free(dev->data->mac_addrs);
 	dev->data->mac_addrs = NULL;
+	munmap(dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr,
+		dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].len);
+
+	RTE_LOG(INFO, PMD, "szedata2 device ("
+			PCI_PRI_FMT ") successfully uninitialized\n",
+			pci_addr->domain, pci_addr->bus, pci_addr->devid,
+			pci_addr->function);
+
 	return 0;
 }
 
diff --git a/drivers/net/szedata2/rte_eth_szedata2.h b/drivers/net/szedata2/rte_eth_szedata2.h
index 7137ba2..39d1c48 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.h
+++ b/drivers/net/szedata2/rte_eth_szedata2.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2015 CESNET
+ *   Copyright (c) 2015 - 2016 CESNET
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,10 @@
 #ifndef RTE_PMD_SZEDATA2_H_
 #define RTE_PMD_SZEDATA2_H_
 
+#include <stdbool.h>
+
+#include <rte_byteorder.h>
+
 /* PCI Vendor ID */
 #define PCI_VENDOR_ID_NETCOPE 0x1b26
 
@@ -42,6 +46,9 @@
 #define PCI_DEVICE_ID_NETCOPE_COMBO100G 0xc1c1
 #define PCI_DEVICE_ID_NETCOPE_COMBO100G2 0xc2c1
 
+/* number of PCI resource used by COMBO card */
+#define PCI_RESOURCE_NUMBER 0
+
 /* szedata2_packet header length == 4 bytes == 2B segment size + 2B hw size */
 #define RTE_SZE2_PACKET_HEADER_SIZE 4
 
@@ -106,5 +113,311 @@ struct szedata {
 	int                         numa_node;
 };
 
+/*
+ * @return Byte from PCI resource at offset "offset".
+ */
+static inline uint8_t
+pci_resource_read8(struct rte_eth_dev *dev, uint32_t offset)
+{
+	return *((uint8_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset));
+}
+
+/*
+ * @return Two bytes from PCI resource starting at offset "offset".
+ */
+static inline uint16_t
+pci_resource_read16(struct rte_eth_dev *dev, uint32_t offset)
+{
+	return rte_le_to_cpu_16(*((uint16_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)));
+}
+
+/*
+ * @return Four bytes from PCI resource starting at offset "offset".
+ */
+static inline uint32_t
+pci_resource_read32(struct rte_eth_dev *dev, uint32_t offset)
+{
+	return rte_le_to_cpu_32(*((uint32_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)));
+}
+
+/*
+ * @return Eight bytes from PCI resource starting at offset "offset".
+ */
+static inline uint64_t
+pci_resource_read64(struct rte_eth_dev *dev, uint32_t offset)
+{
+	return rte_le_to_cpu_64(*((uint64_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)));
+}
+
+/*
+ * Write one byte to PCI resource address space at offset "offset".
+ */
+static inline void
+pci_resource_write8(struct rte_eth_dev *dev, uint32_t offset, uint8_t val)
+{
+	*((uint8_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)) = val;
+}
+
+/*
+ * Write two bytes to PCI resource address space at offset "offset".
+ */
+static inline void
+pci_resource_write16(struct rte_eth_dev *dev, uint32_t offset, uint16_t val)
+{
+	*((uint16_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)) = rte_cpu_to_le_16(val);
+}
+
+/*
+ * Write four bytes to PCI resource address space at offset "offset".
+ */
+static inline void
+pci_resource_write32(struct rte_eth_dev *dev, uint32_t offset, uint32_t val)
+{
+	*((uint32_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)) = rte_cpu_to_le_32(val);
+}
+
+/*
+ * Write eight bytes to PCI resource address space at offset "offset".
+ */
+static inline void
+pci_resource_write64(struct rte_eth_dev *dev, uint32_t offset, uint64_t val)
+{
+	*((uint64_t *)((uint8_t *)
+			dev->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr +
+			offset)) = rte_cpu_to_le_64(val);
+}
+
+#define SZEDATA2_PCI_RESOURCE_PTR(dev, offset, type) \
+	((type)((uint8_t *) \
+	((dev)->pci_dev->mem_resource[PCI_RESOURCE_NUMBER].addr) \
+	+ (offset)))
+
+enum szedata2_link_speed {
+	SZEDATA2_LINK_SPEED_DEFAULT = 0,
+	SZEDATA2_LINK_SPEED_10G,
+	SZEDATA2_LINK_SPEED_40G,
+	SZEDATA2_LINK_SPEED_100G,
+};
+
+/*
+ * Structure describes CGMII IBUF address space
+ */
+struct szedata2_cgmii_ibuf {
+	/** Total Received Frames Counter low part */
+	uint32_t trfcl;
+	/** Correct Frames Counter low part */
+	uint32_t cfcl;
+	/** Discarded Frames Counter low part */
+	uint32_t dfcl;
+	/** Counter of frames discarded due to buffer overflow low part */
+	uint32_t bodfcl;
+	/** Total Received Frames Counter high part */
+	uint32_t trfch;
+	/** Correct Frames Counter high part */
+	uint32_t cfch;
+	/** Discarded Frames Counter high part */
+	uint32_t dfch;
+	/** Counter of frames discarded due to buffer overflow high part */
+	uint32_t bodfch;
+	/** IBUF enable register */
+	uint32_t ibuf_en;
+	/** Error mask register */
+	uint32_t err_mask;
+	/** IBUF status register */
+	uint32_t ibuf_st;
+	/** IBUF command register */
+	uint32_t ibuf_cmd;
+	/** Minimum frame length allowed */
+	uint32_t mfla;
+	/** Frame MTU */
+	uint32_t mtu;
+	/** MAC address check mode */
+	uint32_t mac_chmode;
+	/** Octets Received OK Counter low part */
+	uint32_t orocl;
+	/** Octets Received OK Counter high part */
+	uint32_t oroch;
+} __rte_packed;
+
+/* Offset of CGMII IBUF memory for MAC addresses */
+#define SZEDATA2_CGMII_IBUF_MAC_MEM_OFF 0x80
+
+/*
+ * @return
+ *     true if IBUF is enabled
+ *     false if IBUF is disabled
+ */
+static inline bool
+cgmii_ibuf_is_enabled(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	return ((rte_le_to_cpu_32(ibuf->ibuf_en) & 0x1) != 0) ? true : false;
+}
+
+/*
+ * Enables IBUF.
+ */
+static inline void
+cgmii_ibuf_enable(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	ibuf->ibuf_en =
+		rte_cpu_to_le_32(rte_le_to_cpu_32(ibuf->ibuf_en) | 0x1);
+}
+
+/*
+ * Disables IBUF.
+ */
+static inline void
+cgmii_ibuf_disable(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	ibuf->ibuf_en =
+		rte_cpu_to_le_32(rte_le_to_cpu_32(ibuf->ibuf_en) & ~0x1);
+}
+
+/*
+ * @return
+ *     true if ibuf link is up
+ *     false if ibuf link is down
+ */
+static inline bool
+cgmii_ibuf_is_link_up(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	return ((rte_le_to_cpu_32(ibuf->ibuf_st) & 0x80) != 0) ? true : false;
+}
+
+/*
+ * Structure describes CGMII OBUF address space
+ */
+struct szedata2_cgmii_obuf {
+	/** Total Sent Frames Counter low part */
+	uint32_t tsfcl;
+	/** Octets Sent Counter low part */
+	uint32_t oscl;
+	/** Total Discarded Frames Counter low part */
+	uint32_t tdfcl;
+	/** reserved */
+	uint32_t reserved1;
+	/** Total Sent Frames Counter high part */
+	uint32_t tsfch;
+	/** Octets Sent Counter high part */
+	uint32_t osch;
+	/** Total Discarded Frames Counter high part */
+	uint32_t tdfch;
+	/** reserved */
+	uint32_t reserved2;
+	/** OBUF enable register */
+	uint32_t obuf_en;
+	/** reserved */
+	uint64_t reserved3;
+	/** OBUF control register */
+	uint32_t ctrl;
+	/** OBUF status register */
+	uint32_t obuf_st;
+} __rte_packed;
+
+/*
+ * @return
+ *     true if OBUF is enabled
+ *     false if OBUF is disabled
+ */
+static inline bool
+cgmii_obuf_is_enabled(volatile struct szedata2_cgmii_obuf *obuf)
+{
+	return ((rte_le_to_cpu_32(obuf->obuf_en) & 0x1) != 0) ? true : false;
+}
+
+/*
+ * Enables OBUF.
+ */
+static inline void
+cgmii_obuf_enable(volatile struct szedata2_cgmii_obuf *obuf)
+{
+	obuf->obuf_en =
+		rte_cpu_to_le_32(rte_le_to_cpu_32(obuf->obuf_en) | 0x1);
+}
+
+/*
+ * Disables OBUF.
+ */
+static inline void
+cgmii_obuf_disable(volatile struct szedata2_cgmii_obuf *obuf)
+{
+	obuf->obuf_en =
+		rte_cpu_to_le_32(rte_le_to_cpu_32(obuf->obuf_en) & ~0x1);
+}
+
+/*
+ * Function takes value from IBUF status register. Values in IBUF and OBUF
+ * should be same.
+ *
+ * @return Link speed constant.
+ */
+static inline enum szedata2_link_speed
+cgmii_link_speed(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	uint32_t speed = (rte_le_to_cpu_32(ibuf->ibuf_st) & 0x70) >> 4;
+	switch (speed) {
+	case 0x03:
+		return SZEDATA2_LINK_SPEED_10G;
+	case 0x04:
+		return SZEDATA2_LINK_SPEED_40G;
+	case 0x05:
+		return SZEDATA2_LINK_SPEED_100G;
+	default:
+		return SZEDATA2_LINK_SPEED_DEFAULT;
+	}
+}
+
+/*
+ * IBUFs and OBUFs can generally be located at different offsets in different
+ * firmwares.
+ * This part defines base offsets of IBUFs and OBUFs through various firmwares.
+ * Currently one firmware type is supported.
+ * Type of firmware is set through configuration option
+ * CONFIG_RTE_LIBRTE_PMD_SZEDATA_AS.
+ * Possible values are:
+ * 0 - for firmwares:
+ *     NIC_100G1_LR4
+ *     HANIC_100G1_LR4
+ *     HANIC_100G1_SR10
+ */
+#if !defined(RTE_LIBRTE_PMD_SZEDATA2_AS)
+#error "RTE_LIBRTE_PMD_SZEDATA2_AS has to be defined"
+#elif RTE_LIBRTE_PMD_SZEDATA2_AS == 0
+
+/*
+ * CGMII IBUF offset from the beginning of PCI resource address space.
+ */
+#define SZEDATA2_CGMII_IBUF_BASE_OFF 0x8000
+/*
+ * Size of CGMII IBUF.
+ */
+#define SZEDATA2_CGMII_IBUF_SIZE 0x200
+
+/*
+ * GCMII OBUF offset from the beginning of PCI resource address space.
+ */
+#define SZEDATA2_CGMII_OBUF_BASE_OFF 0x9000
+/*
+ * Size of CGMII OBUF.
+ */
+#define SZEDATA2_CGMII_OBUF_SIZE 0x100
+
+#else
+#error "RTE_LIBRTE_PMD_SZEDATA2_AS has wrong value, see comments in config file"
+#endif
 
 #endif
-- 
1.7.1

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

* [dpdk-dev] [PATCH 3/4] szedata2: add functions for enabling/disabling promiscuous, allmulticast modes
  2016-01-28 22:23 [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 2/4] szedata2: add functions for setting link up/down and updating link info Matej Vido
@ 2016-01-28 22:23 ` Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 4/4] szedata2: update documentation and release notes Matej Vido
  2016-02-17 11:32 ` [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Bruce Richardson
  3 siblings, 0 replies; 5+ messages in thread
From: Matej Vido @ 2016-01-28 22:23 UTC (permalink / raw)
  To: dev; +Cc: pus, viktorin

Signed-off-by: Matej Vido <vido@cesnet.cz>
---
 drivers/net/szedata2/rte_eth_szedata2.c |   45 +++++++++++++++++++++++++++++++
 drivers/net/szedata2/rte_eth_szedata2.h |   39 ++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index d8c260b..81c806e 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1281,6 +1281,42 @@ eth_mac_addr_set(struct rte_eth_dev *dev __rte_unused,
 {
 }
 
+static void
+eth_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	cgmii_ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_PROMISC);
+}
+
+static void
+eth_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	cgmii_ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ONLY_VALID);
+}
+
+static void
+eth_allmulticast_enable(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	cgmii_ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ALL_MULTICAST);
+}
+
+static void
+eth_allmulticast_disable(struct rte_eth_dev *dev)
+{
+	volatile struct szedata2_cgmii_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
+			dev, SZEDATA2_CGMII_IBUF_BASE_OFF,
+			volatile struct szedata2_cgmii_ibuf *);
+	cgmii_ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ONLY_VALID);
+}
+
 static struct eth_dev_ops ops = {
 		.dev_start          = eth_dev_start,
 		.dev_stop           = eth_dev_stop,
@@ -1289,6 +1325,10 @@ static struct eth_dev_ops ops = {
 		.dev_close          = eth_dev_close,
 		.dev_configure      = eth_dev_configure,
 		.dev_infos_get      = eth_dev_info,
+		.promiscuous_enable   = eth_promiscuous_enable,
+		.promiscuous_disable  = eth_promiscuous_disable,
+		.allmulticast_enable  = eth_allmulticast_enable,
+		.allmulticast_disable = eth_allmulticast_disable,
 		.rx_queue_start     = eth_rx_queue_start,
 		.rx_queue_stop      = eth_rx_queue_stop,
 		.tx_queue_start     = eth_tx_queue_start,
@@ -1471,8 +1511,10 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 			(unsigned long long)pci_rsc->len,
 			(unsigned long long)pci_rsc->addr);
 
+	/* Get link state */
 	eth_link_update(dev, 0);
 
+	/* Allocate space for one mac address */
 	data->mac_addrs = rte_zmalloc(data->name, sizeof(struct ether_addr),
 			RTE_CACHE_LINE_SIZE);
 	if (data->mac_addrs == NULL) {
@@ -1484,6 +1526,9 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
 
 	ether_addr_copy(&eth_addr, data->mac_addrs);
 
+	/* At initial state COMBO card is in promiscuous mode so disable it */
+	eth_promiscuous_disable(dev);
+
 	RTE_LOG(INFO, PMD, "szedata2 device ("
 			PCI_PRI_FMT ") successfully initialized\n",
 			pci_addr->domain, pci_addr->bus, pci_addr->devid,
diff --git a/drivers/net/szedata2/rte_eth_szedata2.h b/drivers/net/szedata2/rte_eth_szedata2.h
index 39d1c48..522cf47 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.h
+++ b/drivers/net/szedata2/rte_eth_szedata2.h
@@ -213,6 +213,13 @@ enum szedata2_link_speed {
 	SZEDATA2_LINK_SPEED_100G,
 };
 
+enum szedata2_mac_check_mode {
+	SZEDATA2_MAC_CHMODE_PROMISC       = 0x0,
+	SZEDATA2_MAC_CHMODE_ONLY_VALID    = 0x1,
+	SZEDATA2_MAC_CHMODE_ALL_BROADCAST = 0x2,
+	SZEDATA2_MAC_CHMODE_ALL_MULTICAST = 0x3,
+};
+
 /*
  * Structure describes CGMII IBUF address space
  */
@@ -299,6 +306,38 @@ cgmii_ibuf_is_link_up(volatile struct szedata2_cgmii_ibuf *ibuf)
 }
 
 /*
+ * @return
+ *     MAC address check mode
+ */
+static inline enum szedata2_mac_check_mode
+cgmii_ibuf_mac_mode_read(volatile struct szedata2_cgmii_ibuf *ibuf)
+{
+	switch (rte_le_to_cpu_32(ibuf->mac_chmode) & 0x3) {
+	case 0x0:
+		return SZEDATA2_MAC_CHMODE_PROMISC;
+	case 0x1:
+		return SZEDATA2_MAC_CHMODE_ONLY_VALID;
+	case 0x2:
+		return SZEDATA2_MAC_CHMODE_ALL_BROADCAST;
+	case 0x3:
+		return SZEDATA2_MAC_CHMODE_ALL_MULTICAST;
+	default:
+		return SZEDATA2_MAC_CHMODE_PROMISC;
+	}
+}
+
+/*
+ * Writes "mode" in MAC address check mode register.
+ */
+static inline void
+cgmii_ibuf_mac_mode_write(volatile struct szedata2_cgmii_ibuf *ibuf,
+		enum szedata2_mac_check_mode mode)
+{
+	ibuf->mac_chmode = rte_cpu_to_le_32(
+			(rte_le_to_cpu_32(ibuf->mac_chmode) & ~0x3) | mode);
+}
+
+/*
  * Structure describes CGMII OBUF address space
  */
 struct szedata2_cgmii_obuf {
-- 
1.7.1

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

* [dpdk-dev] [PATCH 4/4] szedata2: update documentation and release notes
  2016-01-28 22:23 [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 2/4] szedata2: add functions for setting link up/down and updating link info Matej Vido
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 3/4] szedata2: add functions for enabling/disabling promiscuous, allmulticast modes Matej Vido
@ 2016-01-28 22:23 ` Matej Vido
  2016-02-17 11:32 ` [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Bruce Richardson
  3 siblings, 0 replies; 5+ messages in thread
From: Matej Vido @ 2016-01-28 22:23 UTC (permalink / raw)
  To: dev; +Cc: pus, viktorin

Add info about change from virtual PMD_VDEV to PMD_PDEV and new
functions to release notes.

Signed-off-by: Matej Vido <vido@cesnet.cz>
---
 doc/guides/nics/szedata2.rst         |   93 +++++++++++++++++++++------------
 doc/guides/rel_notes/release_2_3.rst |    9 +++
 2 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/doc/guides/nics/szedata2.rst b/doc/guides/nics/szedata2.rst
index ee3c3fe..ac512a0 100644
--- a/doc/guides/nics/szedata2.rst
+++ b/doc/guides/nics/szedata2.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright 2015 CESNET
+    Copyright 2015 - 2016 CESNET
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@ SZEDATA2 poll mode driver library
 
 The SZEDATA2 poll mode driver library implements support for cards from COMBO
 family (**COMBO-80G**, **COMBO-100G**).
-The SZEDATA2 PMD is virtual PMD which uses interface provided by libsze2
-library to communicate with COMBO cards over sze2 layer.
+The SZEDATA2 PMD uses interface provided by libsze2 library to communicate
+with COMBO cards over sze2 layer.
 
 More information about family of
 `COMBO cards <https://www.liberouter.org/technologies/cards/>`_
@@ -74,50 +74,41 @@ separately:
    * szedata2_cv3
 
    Kernel modules manage initialization of hardware, allocation and
-   sharing of resources for user space applications:
+   sharing of resources for user space applications.
 
 Information about getting the dependencies can be found `here
 <https://www.liberouter.org/technologies/netcope/access-to-libsze2-library/>`_.
 
+Configuration
+-------------
 
-Using the SZEDATA2 PMD
-----------------------
-
-SZEDATA2 PMD can be created by passing ``--vdev=`` option to EAL in the
-following format:
-
-.. code-block:: console
-
-   --vdev 'DEVICE,dev_path=PATH,rx_ifaces=RX_MASK,tx_ifaces=TX_MASK'
-
-``DEVICE`` and options ``dev_path``, ``rx_ifaces``, ``tx_ifaces`` are mandatory
-and must be separated by commas.
+These configuration options can be modified before compilation in the
+``.config`` file:
 
-*  ``DEVICE``: contains prefix ``eth_szedata2`` followed by numbers or letters,
-   must be unique for each virtual device
+*  ``CONFIG_RTE_LIBRTE_PMD_SZEDATA2`` default value: **n**
 
-*  ``dev_path``: Defines path to szedata2 device.
-   Value is valid path to szedata2 device. Example:
+   Value **y** enables compilation of szedata2 PMD.
 
-   .. code-block:: console
+*  ``CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS`` default value: **0**
 
-      dev_path=/dev/szedataII0
+   This option defines type of firmware address space.
+   Currently supported value is:
 
-*  ``rx_ifaces``: Defines which receive channels will be used.
-   For each channel is created one queue. Value is mask for selecting which
-   receive channels are required. Example:
+   * **0** for firmwares:
 
-   .. code-block:: console
+      * NIC_100G1_LR4
+      * HANIC_100G1_LR4
+      * HANIC_100G1_SR10
 
-      rx_ifaces=0x3
 
-*  ``tx_ifaces``: Defines which transmit channels will be used.
-   For each channel is created one queue. Value is mask for selecting which
-   transmit channels are required. Example:
+Using the SZEDATA2 PMD
+----------------------
 
-   .. code-block:: console
+From DPDK version 2.3.0 the type of SZEDATA2 PMD is changed to PMD_PDEV.
+SZEDATA2 device is automatically recognized during EAL initialization.
+No special command line options are needed.
 
-      tx_ifaces=0x3
+Kernel modules have to be loaded before running the DPDK application.
 
 Example of usage
 ----------------
@@ -128,5 +119,39 @@ transmit channel:
 .. code-block:: console
 
    $RTE_TARGET/app/testpmd -c 0xf -n 2 \
-   --vdev 'eth_szedata20,dev_path=/dev/szedataII0,rx_ifaces=0x3,tx_ifaces=0x3' \
-   -- --port-topology=chained --rxq=2 --txq=2 --nb-cores=2
+   -- --port-topology=chained --rxq=2 --txq=2 --nb-cores=2 -i -a
+
+Example output:
+
+.. code-block:: console
+
+   [...]
+   EAL: PCI device 0000:06:00.0 on NUMA socket -1
+   EAL:   probe driver: 1b26:c1c1 rte_szedata2_pmd
+   PMD: Initializing szedata2 device (0000:06:00.0)
+   PMD: SZEDATA2 path: /dev/szedataII0
+   PMD: Available DMA channels RX: 8 TX: 8
+   PMD: resource0 phys_addr = 0xe8000000 len = 134217728 virt addr = 7f48f8000000
+   PMD: szedata2 device (0000:06:00.0) successfully initialized
+   Interactive-mode selected
+   Auto-start selected
+   Configuring Port 0 (socket 0)
+   Port 0: 00:11:17:00:00:00
+   Checking link statuses...
+   Port 0 Link Up - speed 10000 Mbps - full-duplex
+   Done
+   Start automatic packet forwarding
+     io packet forwarding - CRC stripping disabled - packets/burst=32
+     nb forwarding cores=2 - nb forwarding ports=1
+     RX queues=2 - RX desc=128 - RX free threshold=0
+     RX threshold registers: pthresh=0 hthresh=0 wthresh=0
+     TX queues=2 - TX desc=512 - TX free threshold=0
+     TX threshold registers: pthresh=0 hthresh=0 wthresh=0
+     TX RS bit threshold=0 - TXQ flags=0x0
+   testpmd>
+
+.. note::
+
+   Link speed API currently supports speeds up to 40 Gbps.
+   Therefore there is used 10G constant for 100 Gbps cards until the link speed
+   API is not changed.
diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst
index 99de186..6f22017 100644
--- a/doc/guides/rel_notes/release_2_3.rst
+++ b/doc/guides/rel_notes/release_2_3.rst
@@ -15,6 +15,15 @@ EAL
 Drivers
 ~~~~~~~
 
+* **szedata2: Change type of driver from PMD_VDEV to PMD_PDEV.**
+
+  Previously szedata2 device had to be added by ``--vdev`` option.
+  Now szedata2 PMD recognises the device automatically during EAL
+  initialization.
+
+* **szedata2: Add functions for promiscuous and allmulticast modes.**
+
+* **szedata2: Add functions for setting link up/down.**
 
 Libraries
 ~~~~~~~~~
-- 
1.7.1

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

* Re: [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type
  2016-01-28 22:23 [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Matej Vido
                   ` (2 preceding siblings ...)
  2016-01-28 22:23 ` [dpdk-dev] [PATCH 4/4] szedata2: update documentation and release notes Matej Vido
@ 2016-02-17 11:32 ` Bruce Richardson
  3 siblings, 0 replies; 5+ messages in thread
From: Bruce Richardson @ 2016-02-17 11:32 UTC (permalink / raw)
  To: Matej Vido; +Cc: dev, pus, viktorin

On Thu, Jan 28, 2016 at 11:23:46PM +0100, Matej Vido wrote:
> PMD was of type PMD_VDEV which means that PCI device is not recognised
> automatically during EAL initialization, but it has to be created by
> EAL option --vdev.
> Now, PMD is of type PMD_PDEV which means that PCI device is probed
> and recognised during EAL initialization automatically.
> Path to szedata2 device file is matched with device and the count
> of available RX and TX DMA channels is found out during device
> initialization.
> Initialization, starting and stopping of queues is changed to better
> correspond with Ethernet device API model. Function callbacks
> (rx|tx)_queue_(start|stop) are added. Unnecessary items are removed
> from ethernet device private data structure.
> 
> Signed-off-by: Matej Vido <vido@cesnet.cz>

Series applied to dpdk-net-next/rel_16_04

/Bruce

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

end of thread, other threads:[~2016-02-17 11:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-28 22:23 [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Matej Vido
2016-01-28 22:23 ` [dpdk-dev] [PATCH 2/4] szedata2: add functions for setting link up/down and updating link info Matej Vido
2016-01-28 22:23 ` [dpdk-dev] [PATCH 3/4] szedata2: add functions for enabling/disabling promiscuous, allmulticast modes Matej Vido
2016-01-28 22:23 ` [dpdk-dev] [PATCH 4/4] szedata2: update documentation and release notes Matej Vido
2016-02-17 11:32 ` [dpdk-dev] [PATCH 1/4] szedata2: rewrite PMD from virtual PMD_VDEV type to PMD_PDEV type Bruce Richardson

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).