[dpdk-dev] [PATCH v3 10/17] net/ionic: add basic port operations

Alfredo Cardigliano cardigliano at ntop.org
Mon Dec 9 22:46:49 CET 2019


Add support for port start/stop and handle basic features
including mtu and link up/down.

Signed-off-by: Alfredo Cardigliano <cardigliano at ntop.org>
Reviewed-by: Shannon Nelson <snelson at pensando.io>
---
 doc/guides/nics/features/ionic.ini |   4 +
 drivers/net/ionic/ionic.h          |   1 +
 drivers/net/ionic/ionic_dev.h      |   3 +
 drivers/net/ionic/ionic_ethdev.c   | 322 +++++++++++++++++++++++++++++
 drivers/net/ionic/ionic_lif.c      | 270 ++++++++++++++++++++++++
 drivers/net/ionic/ionic_lif.h      |  10 +
 6 files changed, 610 insertions(+)

diff --git a/doc/guides/nics/features/ionic.ini b/doc/guides/nics/features/ionic.ini
index 6915d9c42..c69e5cbed 100644
--- a/doc/guides/nics/features/ionic.ini
+++ b/doc/guides/nics/features/ionic.ini
@@ -4,6 +4,10 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Speed capabilities   = Y
+Link status          = Y
+Link status event    = Y
+MTU update           = Y
 Linux UIO            = Y
 Linux VFIO           = Y
 x86-64               = Y
diff --git a/drivers/net/ionic/ionic.h b/drivers/net/ionic/ionic.h
index e7c8ad34b..ae4f6acc7 100644
--- a/drivers/net/ionic/ionic.h
+++ b/drivers/net/ionic/ionic.h
@@ -54,6 +54,7 @@ struct ionic_adapter {
 	uint32_t nlifs;
 	uint32_t max_ntxqs_per_lif;
 	uint32_t max_nrxqs_per_lif;
+	uint32_t max_mac_addrs;
 	uint32_t link_speed;
 	uint32_t nintrs;
 	bool intrs[IONIC_INTR_CTRL_REGS_MAX];
diff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h
index a832ff405..61576621b 100644
--- a/drivers/net/ionic/ionic_dev.h
+++ b/drivers/net/ionic/ionic_dev.h
@@ -9,6 +9,9 @@
 #include "ionic_if.h"
 #include "ionic_regs.h"
 
+#define IONIC_MIN_MTU			RTE_ETHER_MIN_MTU
+#define IONIC_MAX_MTU			9194
+
 #define IONIC_MAX_RING_DESC		32768
 #define IONIC_MIN_RING_DESC		16
 
diff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c
index 75f5a16b9..3a6c14604 100644
--- a/drivers/net/ionic/ionic_ethdev.c
+++ b/drivers/net/ionic/ionic_ethdev.c
@@ -18,6 +18,17 @@
 
 static int  eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params);
 static int  eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev);
+static int  ionic_dev_info_get(struct rte_eth_dev *eth_dev,
+	struct rte_eth_dev_info *dev_info);
+static int  ionic_dev_configure(struct rte_eth_dev *dev);
+static int  ionic_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static int  ionic_dev_start(struct rte_eth_dev *dev);
+static void ionic_dev_stop(struct rte_eth_dev *dev);
+static void ionic_dev_close(struct rte_eth_dev *dev);
+static int  ionic_dev_set_link_up(struct rte_eth_dev *dev);
+static int  ionic_dev_set_link_down(struct rte_eth_dev *dev);
+static int  ionic_dev_link_update(struct rte_eth_dev *eth_dev,
+	int wait_to_complete);
 
 int ionic_logtype_driver;
 
@@ -29,6 +40,15 @@ static const struct rte_pci_id pci_id_ionic_map[] = {
 };
 
 static const struct eth_dev_ops ionic_eth_dev_ops = {
+	.dev_infos_get          = ionic_dev_info_get,
+	.dev_configure          = ionic_dev_configure,
+	.mtu_set                = ionic_dev_mtu_set,
+	.dev_start              = ionic_dev_start,
+	.dev_stop               = ionic_dev_stop,
+	.dev_close              = ionic_dev_close,
+	.link_update            = ionic_dev_link_update,
+	.dev_set_link_up        = ionic_dev_set_link_up,
+	.dev_set_link_down      = ionic_dev_set_link_down,
 };
 
 /*
@@ -39,6 +59,104 @@ static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =
 		LIST_HEAD_INITIALIZER(ionic_pci_adapters);
 static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;
 
+/*
+ * Set device link up, enable tx.
+ */
+static int
+ionic_dev_set_link_up(struct rte_eth_dev *eth_dev)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	struct ionic_adapter *adapter = lif->adapter;
+	struct ionic_dev *idev = &adapter->idev;
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
+
+	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+
+	if (err) {
+		IONIC_PRINT(WARNING, "Failed to bring port UP");
+		return err;
+	}
+
+	return 0;
+}
+
+/*
+ * Set device link down, disable tx.
+ */
+static int
+ionic_dev_set_link_down(struct rte_eth_dev *eth_dev)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	struct ionic_adapter *adapter = lif->adapter;
+	struct ionic_dev *idev = &adapter->idev;
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_DOWN);
+
+	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+
+	if (err) {
+		IONIC_PRINT(WARNING, "Failed to bring port DOWN");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+ionic_dev_link_update(struct rte_eth_dev *eth_dev,
+		int wait_to_complete __rte_unused)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	struct ionic_adapter *adapter = lif->adapter;
+	struct rte_eth_link link;
+
+	IONIC_PRINT_CALL();
+
+	/* Initialize */
+	memset(&link, 0, sizeof(link));
+	link.link_autoneg = ETH_LINK_AUTONEG;
+
+	if (!adapter->link_up) {
+		/* Interface is down */
+		link.link_status = ETH_LINK_DOWN;
+		link.link_duplex = ETH_LINK_HALF_DUPLEX;
+		link.link_speed = ETH_SPEED_NUM_NONE;
+	} else {
+		/* Interface is up */
+		link.link_status = ETH_LINK_UP;
+		link.link_duplex = ETH_LINK_FULL_DUPLEX;
+		switch (adapter->link_speed) {
+		case  10000:
+			link.link_speed = ETH_SPEED_NUM_10G;
+			break;
+		case  25000:
+			link.link_speed = ETH_SPEED_NUM_25G;
+			break;
+		case  40000:
+			link.link_speed = ETH_SPEED_NUM_40G;
+			break;
+		case  50000:
+			link.link_speed = ETH_SPEED_NUM_50G;
+			break;
+		case 100000:
+			link.link_speed = ETH_SPEED_NUM_100G;
+			break;
+		default:
+			link.link_speed = ETH_SPEED_NUM_NONE;
+			break;
+		}
+	}
+
+	return rte_eth_linkstatus_set(eth_dev, &link);
+}
+
 /**
  * Interrupt handler triggered by NIC for handling
  * specific interrupt.
@@ -63,6 +181,189 @@ ionic_dev_interrupt_handler(void *param)
 	}
 }
 
+static int
+ionic_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	/*
+	 * Max frame size is MTU + Ethernet header + VLAN + QinQ
+	 * (plus ETHER_CRC_LEN if the adapter is able to keep CRC)
+	 * uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4;
+	 */
+
+	/* Check that mtu is within the allowed range */
+	if (mtu < IONIC_MIN_MTU || mtu > IONIC_MAX_MTU)
+		return -EINVAL;
+
+	err = ionic_lif_change_mtu(lif, mtu);
+
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int
+ionic_dev_info_get(struct rte_eth_dev *eth_dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	struct ionic_adapter *adapter = lif->adapter;
+	struct ionic_identity *ident = &adapter->ident;
+
+	IONIC_PRINT_CALL();
+
+	dev_info->max_rx_queues = (uint16_t)
+		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
+	dev_info->max_tx_queues = (uint16_t)
+		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
+	/* Also add ETHER_CRC_LEN if the adapter is able to keep CRC */
+	dev_info->min_rx_bufsize = IONIC_MIN_MTU + RTE_ETHER_HDR_LEN;
+	dev_info->max_rx_pktlen = IONIC_MAX_MTU + RTE_ETHER_HDR_LEN;
+	dev_info->max_mac_addrs = adapter->max_mac_addrs;
+	dev_info->min_mtu = IONIC_MIN_MTU;
+	dev_info->max_mtu = IONIC_MAX_MTU;
+
+	dev_info->speed_capa =
+		ETH_LINK_SPEED_10G |
+		ETH_LINK_SPEED_25G |
+		ETH_LINK_SPEED_40G |
+		ETH_LINK_SPEED_50G |
+		ETH_LINK_SPEED_100G;
+
+	return 0;
+}
+
+static int
+ionic_dev_configure(struct rte_eth_dev *eth_dev)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	err = ionic_lif_configure(lif);
+
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot configure LIF: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static inline uint32_t
+ionic_parse_link_speeds(uint16_t link_speeds)
+{
+	if (link_speeds & ETH_LINK_SPEED_100G)
+		return 100000;
+	else if (link_speeds & ETH_LINK_SPEED_50G)
+		return 50000;
+	else if (link_speeds & ETH_LINK_SPEED_40G)
+		return 40000;
+	else if (link_speeds & ETH_LINK_SPEED_25G)
+		return 25000;
+	else if (link_speeds & ETH_LINK_SPEED_10G)
+		return 10000;
+	else
+		return 0;
+}
+
+/*
+ * Configure device link speed and setup link.
+ * It returns 0 on success.
+ */
+static int
+ionic_dev_start(struct rte_eth_dev *eth_dev)
+{
+	struct rte_eth_conf *dev_conf = &eth_dev->data->dev_conf;
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	struct ionic_adapter *adapter = lif->adapter;
+	struct ionic_dev *idev = &adapter->idev;
+	uint32_t allowed_speeds;
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	allowed_speeds =
+		ETH_LINK_SPEED_FIXED |
+		ETH_LINK_SPEED_10G |
+		ETH_LINK_SPEED_25G |
+		ETH_LINK_SPEED_40G |
+		ETH_LINK_SPEED_50G |
+		ETH_LINK_SPEED_100G;
+
+	if (dev_conf->link_speeds & ~allowed_speeds) {
+		IONIC_PRINT(ERR, "Invalid link setting");
+		return -EINVAL;
+	}
+
+	err = ionic_lif_start(lif);
+
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot start LIF: %d", err);
+		return err;
+	}
+
+	if (eth_dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
+		uint32_t speed = ionic_parse_link_speeds(dev_conf->link_speeds);
+
+		if (speed)
+			ionic_dev_cmd_port_speed(idev, speed);
+	}
+
+	ionic_dev_link_update(eth_dev, 0);
+
+	return 0;
+}
+
+/*
+ * Stop device: disable rx and tx functions to allow for reconfiguring.
+ */
+static void
+ionic_dev_stop(struct rte_eth_dev *eth_dev)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	err = ionic_lif_stop(lif);
+
+	if (err)
+		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
+}
+
+/*
+ * Reset and stop device.
+ */
+static void
+ionic_dev_close(struct rte_eth_dev *eth_dev)
+{
+	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	err = ionic_lif_stop(lif);
+
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
+		return;
+	}
+
+	err = eth_ionic_dev_uninit(eth_dev);
+
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot destroy LIF: %d", err);
+		return;
+	}
+}
+
 static int
 eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
 {
@@ -86,6 +387,21 @@ eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
 	lif->adapter = adapter;
 	adapter->lifs[adapter->nlifs] = lif;
 
+	IONIC_PRINT(DEBUG, "Up to %u MAC addresses supported",
+		adapter->max_mac_addrs);
+
+	/* Allocate memory for storing MAC addresses */
+	eth_dev->data->mac_addrs = rte_zmalloc("ionic",
+		RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs, 0);
+
+	if (eth_dev->data->mac_addrs == NULL) {
+		IONIC_PRINT(ERR, "Failed to allocate %u bytes needed to "
+			"store MAC addresses",
+			RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs);
+		err = -ENOMEM;
+		goto err;
+	}
+
 	err = ionic_lif_alloc(lif);
 
 	if (err) {
@@ -101,6 +417,10 @@ eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
 		goto err_free_lif;
 	}
 
+	/* Copy the MAC address */
+	rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr,
+		&eth_dev->data->mac_addrs[0]);
+
 	IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id);
 
 err_free_lif:
@@ -304,6 +624,8 @@ eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto err_free_adapter;
 	}
 
+	adapter->max_mac_addrs = adapter->ident.lif.eth.max_ucast_filters;
+
 	adapter->nlifs = 0;
 	for (i = 0; i < adapter->ident.dev.nlifs; i++) {
 		snprintf(name, sizeof(name), "net_%s_lif_%lu",
diff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c
index 497b01f1f..bf6a7566c 100644
--- a/drivers/net/ionic/ionic_lif.c
+++ b/drivers/net/ionic/ionic_lif.c
@@ -10,6 +10,9 @@
 #include "ionic_lif.h"
 #include "ionic_ethdev.h"
 
+static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
+static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
+
 int
 ionic_qcq_enable(struct ionic_qcq *qcq)
 {
@@ -60,6 +63,107 @@ ionic_qcq_disable(struct ionic_qcq *qcq)
 	return ionic_adminq_post_wait(lif, &ctx);
 }
 
+int
+ionic_lif_stop(struct ionic_lif *lif __rte_unused)
+{
+	/* Carrier OFF here */
+
+	return 0;
+}
+
+void
+ionic_lif_reset(struct ionic_lif *lif)
+{
+	struct ionic_dev *idev = &lif->adapter->idev;
+
+	IONIC_PRINT_CALL();
+
+	ionic_dev_cmd_lif_reset(idev, lif->index);
+	ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+}
+
+static int
+ionic_lif_addr_add(struct ionic_lif *lif __rte_unused,
+		const uint8_t *addr __rte_unused)
+{
+	IONIC_PRINT(INFO, "%s: stubbed", __func__);
+
+	return 0;
+}
+
+static int
+ionic_lif_addr_del(struct ionic_lif *lif __rte_unused,
+		const uint8_t *addr __rte_unused)
+{
+	IONIC_PRINT(INFO, "%s: stubbed", __func__);
+
+	return 0;
+}
+
+static void
+ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
+{
+	struct ionic_admin_ctx ctx = {
+		.pending_work = true,
+		.cmd.rx_mode_set = {
+			.opcode = IONIC_CMD_RX_MODE_SET,
+			.lif_index = lif->index,
+			.rx_mode = rx_mode,
+		},
+	};
+	int err;
+
+	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
+		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
+	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
+		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
+	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
+		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
+	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
+		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
+	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
+		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
+
+	err = ionic_adminq_post_wait(lif, &ctx);
+
+	if (err)
+		IONIC_PRINT(ERR, "Failure setting RX mode");
+}
+
+static void
+ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
+{
+	if (lif->rx_mode != rx_mode) {
+		lif->rx_mode = rx_mode;
+		ionic_lif_rx_mode(lif, rx_mode);
+	}
+}
+
+
+int
+ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
+{
+	struct ionic_admin_ctx ctx = {
+		.pending_work = true,
+		.cmd.lif_setattr = {
+			.opcode = IONIC_CMD_LIF_SETATTR,
+			.index = lif->index,
+			.attr = IONIC_LIF_ATTR_MTU,
+			.mtu = new_mtu,
+		},
+	};
+	int err;
+
+	err = ionic_adminq_post_wait(lif, &ctx);
+
+	if (err)
+		return err;
+
+	lif->mtu = new_mtu;
+
+	return 0;
+}
+
 int
 ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
 {
@@ -601,6 +705,124 @@ ionic_lif_notifyq_init(struct ionic_lif *lif)
 	return 0;
 }
 
+int
+ionic_lif_set_features(struct ionic_lif *lif)
+{
+	struct ionic_admin_ctx ctx = {
+		.pending_work = true,
+		.cmd.lif_setattr = {
+			.opcode = IONIC_CMD_LIF_SETATTR,
+			.index = lif->index,
+			.attr = IONIC_LIF_ATTR_FEATURES,
+			.features = lif->features,
+		},
+	};
+	int err;
+
+	err = ionic_adminq_post_wait(lif, &ctx);
+	if (err)
+		return err;
+
+	lif->hw_features = (ctx.cmd.lif_setattr.features &
+		ctx.comp.lif_setattr.features);
+
+	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
+	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
+	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
+	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
+	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
+	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
+	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
+	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
+	if (lif->hw_features & IONIC_ETH_HW_TSO)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
+	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
+		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
+
+	return 0;
+}
+
+static int
+ionic_station_set(struct ionic_lif *lif)
+{
+	struct ionic_admin_ctx ctx = {
+		.pending_work = true,
+		.cmd.lif_getattr = {
+			.opcode = IONIC_CMD_LIF_GETATTR,
+			.index = lif->index,
+			.attr = IONIC_LIF_ATTR_MAC,
+		},
+	};
+	int err;
+
+	IONIC_PRINT_CALL();
+
+	err = ionic_adminq_post_wait(lif, &ctx);
+
+	if (err)
+		return err;
+
+	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
+			lif->mac_addr)) {
+		IONIC_PRINT(INFO, "deleting station MAC addr");
+
+		ionic_lif_addr_del(lif, lif->mac_addr);
+	}
+
+	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
+
+	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
+		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
+		return 0;
+	}
+
+	IONIC_PRINT(DEBUG, "adding station MAC addr");
+
+	ionic_lif_addr_add(lif, lif->mac_addr);
+
+	return 0;
+}
+
+static void
+ionic_lif_set_name(struct ionic_lif *lif)
+{
+	struct ionic_admin_ctx ctx = {
+		.pending_work = true,
+		.cmd.lif_setattr = {
+			.opcode = IONIC_CMD_LIF_SETATTR,
+			.index = lif->index,
+			.attr = IONIC_LIF_ATTR_NAME,
+		},
+	};
+
+	snprintf(ctx.cmd.lif_setattr.name, sizeof(ctx.cmd.lif_setattr.name),
+		"%d", lif->port_id);
+
+	ionic_adminq_post_wait(lif, &ctx);
+}
+
 int
 ionic_lif_init(struct ionic_lif *lif)
 {
@@ -626,10 +848,27 @@ ionic_lif_init(struct ionic_lif *lif)
 	if (err)
 		goto err_out_adminq_deinit;
 
+	lif->features = 0;
+
+	err = ionic_lif_set_features(lif);
+
+	if (err)
+		goto err_out_notifyq_deinit;
+
+	err = ionic_station_set(lif);
+
+	if (err)
+		goto err_out_notifyq_deinit;
+
+	ionic_lif_set_name(lif);
+
 	lif->state |= IONIC_LIF_F_INITED;
 
 	return 0;
 
+err_out_notifyq_deinit:
+	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
+
 err_out_adminq_deinit:
 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
 
@@ -648,6 +887,37 @@ ionic_lif_deinit(struct ionic_lif *lif)
 	lif->state &= ~IONIC_LIF_F_INITED;
 }
 
+int
+ionic_lif_configure(struct ionic_lif *lif)
+{
+	lif->port_id = lif->eth_dev->data->port_id;
+
+	return 0;
+}
+
+int
+ionic_lif_start(struct ionic_lif *lif)
+{
+	uint32_t rx_mode = 0;
+
+	IONIC_PRINT(DEBUG, "Setting RX mode on port %u",
+		lif->port_id);
+
+	rx_mode |= IONIC_RX_MODE_F_UNICAST;
+	rx_mode |= IONIC_RX_MODE_F_MULTICAST;
+	rx_mode |= IONIC_RX_MODE_F_BROADCAST;
+
+	lif->rx_mode = 0; /* set by ionic_set_rx_mode */
+
+	ionic_set_rx_mode(lif, rx_mode);
+
+	ionic_link_status_check(lif);
+
+	/* Carrier ON here */
+
+	return 0;
+}
+
 int
 ionic_lif_identify(struct ionic_adapter *adapter)
 {
diff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h
index 78cf92db8..9dbc54e27 100644
--- a/drivers/net/ionic/ionic_lif.h
+++ b/drivers/net/ionic/ionic_lif.h
@@ -44,6 +44,7 @@ struct ionic_lif {
 	struct ionic_adapter *adapter;
 	struct rte_eth_dev *eth_dev;
 	uint16_t port_id;  /**< Device port identifier */
+	uint16_t mtu;
 	uint32_t index;
 	uint32_t hw_index;
 	uint32_t state;
@@ -54,7 +55,11 @@ struct ionic_lif {
 	struct ionic_qcq *notifyqcq;
 	struct ionic_doorbell __iomem *kern_dbpage;
 	uint64_t last_eid;
+	uint64_t features;
+	uint32_t hw_features;
+	uint32_t rx_mode;
 	char name[IONIC_LIF_NAME_MAX_SZ];
+	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	uint32_t info_sz;
 	struct ionic_lif_info *info;
 	rte_iova_t info_pa;
@@ -71,6 +76,7 @@ int ionic_lif_init(struct ionic_lif *lif);
 void ionic_lif_deinit(struct ionic_lif *lif);
 
 int ionic_lif_start(struct ionic_lif *lif);
+int ionic_lif_stop(struct ionic_lif *lif);
 
 int ionic_lif_configure(struct ionic_lif *lif);
 void ionic_lif_reset(struct ionic_lif *lif);
@@ -83,11 +89,15 @@ bool ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
 int ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
 	void *cb_arg);
 
+int ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu);
+
 void ionic_qcq_free(struct ionic_qcq *qcq);
 
 int ionic_qcq_enable(struct ionic_qcq *qcq);
 int ionic_qcq_disable(struct ionic_qcq *qcq);
 
+int ionic_lif_set_features(struct ionic_lif *lif);
+
 int ionic_notifyq_handler(struct ionic_lif *lif, int budget);
 
 #endif /* _IONIC_LIF_H_ */
-- 
2.17.1



More information about the dev mailing list