From patchwork Sun Jan 19 15:53:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alfredo Cardigliano X-Patchwork-Id: 64893 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id E9DAFA0520; Sun, 19 Jan 2020 16:56:05 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D6D6C1BE85; Sun, 19 Jan 2020 16:54:33 +0100 (CET) Received: from mail.ntop.org (mail-digitalocean.ntop.org [167.99.215.164]) by dpdk.org (Postfix) with ESMTP id C895D2B98 for ; Sun, 19 Jan 2020 16:54:16 +0100 (CET) Received: from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it [93.145.196.230]) by mail.ntop.org (Postfix) with ESMTPSA id 647124077C; Sun, 19 Jan 2020 16:54:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ntop.org; s=mail; t=1579449256; bh=KasJqxytDd82qn+GC2KGvHH3BeIM/xIoELmLmWyYkdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kmN4uNp7ljK5b3B2Yqd0j1SxV8lGtkRMXIkUwzPfYvJjXwNfAZb3m0ReA+zzBgHir NPsZgi28a8p48jSYsnz7sckH2+t/bp8OH7ySizJa/gS+eUgjb5CZaIwyZQ5PYY/ZSt HNTSN8BRAEuLPZuNCKshNeq4lpYX54DaroEwle6o= From: Alfredo Cardigliano To: Alfredo Cardigliano , John McNamara , Marko Kovacevic Cc: dev@dpdk.org Date: Sun, 19 Jan 2020 16:53:48 +0100 Message-Id: <20200119155356.20403-11-cardigliano@ntop.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200119155356.20403-1-cardigliano@ntop.org> References: <20200119155356.20403-1-cardigliano@ntop.org> Subject: [dpdk-dev] [PATCH v5 10/17] net/ionic: add basic port operations X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support for port start/stop and handle basic features including mtu and link up/down. Signed-off-by: Alfredo Cardigliano Reviewed-by: Shannon Nelson --- 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 | 319 +++++++++++++++++++++++++++++ drivers/net/ionic/ionic_lif.c | 266 +++++++++++++++++++++++- drivers/net/ionic/ionic_lif.h | 10 + 6 files changed, 602 insertions(+), 1 deletion(-) 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 0243ee4ca..184fc6da0 100644 --- a/drivers/net/ionic/ionic.h +++ b/drivers/net/ionic/ionic.h @@ -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]; 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 b57dce1e5..e2c9d1d68 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; @@ -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 = ð_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, + ð_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", diff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c index c831519b7..66038bbdb 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,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) { 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_ */