net/ionic: add basic port operations
authorAlfredo Cardigliano <cardigliano@ntop.org>
Sun, 19 Jan 2020 15:53:48 +0000 (16:53 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 20 Jan 2020 17:02:17 +0000 (18:02 +0100)
Add support for port start/stop and handle basic features
including MTU and link up/down.

Signed-off-by: Alfredo Cardigliano <cardigliano@ntop.org>
Reviewed-by: Shannon Nelson <snelson@pensando.io>
doc/guides/nics/features/ionic.ini
drivers/net/ionic/ionic.h
drivers/net/ionic/ionic_dev.h
drivers/net/ionic/ionic_ethdev.c
drivers/net/ionic/ionic_lif.c
drivers/net/ionic/ionic_lif.h

index 6915d9c..c69e5cb 100644 (file)
@@ -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
index 0243ee4..184fc6d 100644 (file)
@@ -55,6 +55,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];
index a832ff4..6157662 100644 (file)
@@ -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
 
index 5719501..8cdef59 100644 (file)
 
 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;
 
@@ -29,8 +40,113 @@ 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,
 };
 
+/*
+ * 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.
@@ -55,6 +171,188 @@ 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);
+       uint32_t max_frame_size;
+       int err;
+
+       IONIC_PRINT_CALL();
+
+       /*
+        * Note: mtu check against IONIC_MIN_MTU, IONIC_MAX_MTU
+        * is done by the the API.
+        */
+
+       /*
+        * Max frame size is MTU + Ethernet header + VLAN + QinQ
+        * (plus ETHER_CRC_LEN if the adapter is able to keep CRC)
+        */
+       max_frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4;
+
+       if (eth_dev->data->dev_conf.rxmode.max_rx_pkt_len < max_frame_size)
+               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)
 {
@@ -78,6 +376,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) {
                IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting",
@@ -91,6 +404,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);
 
        return 0;
@@ -291,6 +608,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",
index c831519..66038bb 100644 (file)
@@ -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,105 @@ 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)
 {
@@ -319,7 +421,6 @@ ionic_lif_alloc(struct ionic_lif *lif)
        IONIC_PRINT(DEBUG, "Allocating Notify Queue");
 
        err = ionic_notify_qcq_alloc(lif);
-
        if (err) {
                IONIC_PRINT(ERR, "Cannot allocate notify queue");
                return err;
@@ -593,6 +694,123 @@ 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)
 {
@@ -616,10 +834,25 @@ 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);
 
@@ -638,6 +871,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)
 {
index 78cf92d..9dbc54e 100644 (file)
@@ -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_ */