From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F62AC47404 for ; Sat, 12 Oct 2019 00:28:08 +0000 (UTC) Received: from dpdk.org (dpdk.org [92.243.14.124]) by mail.kernel.org (Postfix) with ESMTP id D4D2F2084C for ; Sat, 12 Oct 2019 00:28:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D4D2F2084C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ntop.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=dev-bounces@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A9B371EBA7; Sat, 12 Oct 2019 02:27:18 +0200 (CEST) Received: from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it [93.145.196.230]) by dpdk.org (Postfix) with ESMTP id 6F7AD1EBA7 for ; Sat, 12 Oct 2019 02:27:17 +0200 (CEST) Received: from [192.168.2.134] (localhost6.localdomain6 [IPv6:::1]) by devele.ntop.org (Postfix) with ESMTP id 4B3E36C003C for ; Sat, 12 Oct 2019 02:27:17 +0200 (CEST) From: Alfredo Cardigliano To: dev@dpdk.org Date: Sat, 12 Oct 2019 02:27:17 +0200 Message-ID: <157084003725.11524.17090681919991122444.stgit@devele> In-Reply-To: <157083994018.11524.11276616720287263690.stgit@devele> References: <157083994018.11524.11276616720287263690.stgit@devele> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [dpdk-dev] [PATCH 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 | 315 ++++++++++++++++++++++++++++++++++++ drivers/net/ionic/ionic_lif.c | 268 +++++++++++++++++++++++++++++++ drivers/net/ionic/ionic_lif.h | 9 + drivers/net/ionic/ionic_osdep.h | 2 7 files changed, 602 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 53836be64..05f1df061 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 ada07edff..02fcfdee8 100644 --- a/drivers/net/ionic/ionic_dev.h +++ b/drivers/net/ionic/ionic_dev.h @@ -20,6 +20,9 @@ */ #define IONIC_API_VERSION "3" +#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 6e435fe89..fed332750 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_init; int ionic_logtype_driver; @@ -30,6 +41,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, }; /* @@ -40,6 +60,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_init_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_init_print(WARNING, "Failed to bring port UP\n"); + 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_init_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_init_print(WARNING, "Failed to bring port DOWN\n"); + 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_init_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. @@ -64,6 +182,183 @@ 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); + /* + * Size = MTU + Ethernet header + VLAN + QinQ + * Also add ETHER_CRC_LEN if the adapter is able to keep CRC + */ + uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4; + int err; + + ionic_init_print_call(); + + /* 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; + + /* Update max frame size */ + eth_dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; + + 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_init_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->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_init_print_call(); + + err = ionic_lif_configure(lif); + + if (err) { + ionic_drv_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 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_init_print_call(); + + err = ionic_lif_start(lif); + + if (err) { + ionic_drv_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(eth_dev->data->dev_conf.link_speeds); + + if (speed) + ionic_dev_cmd_port_speed(idev, speed); + } + + 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 (eth_dev->data->dev_conf.link_speeds & ~allowed_speeds) { + ionic_init_print(ERR, "Invalid link setting"); + return -EINVAL; + } + + 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_init_print_call(); + + err = ionic_lif_stop(lif); + + if (err) { + ionic_drv_print(ERR, "Cannot stop LIF: %d", err); + return; + } +} + +/* + * 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_init_print_call(); + + err = ionic_lif_stop(lif); + + if (err) { + ionic_drv_print(ERR, "Cannot stop LIF: %d", err); + return; + } +} + static int eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) { @@ -87,6 +382,20 @@ eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) lif->adapter = adapter; adapter->lifs[adapter->nlifs] = lif; + ionic_init_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_init_print(ERR, "Failed to allocate %u bytes needed to " + "store MAC addresses", + RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs); + return -ENOMEM; + } + err = ionic_lif_alloc(lif); if (err) { @@ -102,6 +411,10 @@ eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) return err; } + /* Copy the MAC address */ + rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr, + ð_dev->data->mac_addrs[0]); + ionic_init_print(DEBUG, "Port %u initialized", eth_dev->data->port_id); return 0; @@ -297,6 +610,8 @@ eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, return err; } + 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 491db56d4..b6b730cef 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) +{ + /* Carrier OFF here */ + + return 0; +} + +void +ionic_lif_reset(struct ionic_lif *lif) +{ + struct ionic_dev *idev = &lif->adapter->idev; + + ionic_drv_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, const uint8_t *addr) +{ + ionic_init_print(INFO, "%s: stubbed\n", __func__); + + return 0; +} + +static int +ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) +{ + ionic_init_print(INFO, "%s: stubbed\n", __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_init_print(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); + if (rx_mode & IONIC_RX_MODE_F_MULTICAST) + ionic_init_print(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); + if (rx_mode & IONIC_RX_MODE_F_BROADCAST) + ionic_init_print(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); + if (rx_mode & IONIC_RX_MODE_F_PROMISC) + ionic_init_print(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); + if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) + ionic_init_print(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); + + err = ionic_adminq_post_wait(lif, &ctx); + + if (err) + ionic_init_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) { @@ -595,6 +697,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_init_print(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); + if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); + if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); + if (lif->hw_features & IONIC_ETH_HW_RX_HASH) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); + if (lif->hw_features & IONIC_ETH_HW_TX_SG) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TX_SG"); + if (lif->hw_features & IONIC_ETH_HW_RX_SG) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_RX_SG"); + if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); + if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); + if (lif->hw_features & IONIC_ETH_HW_TSO) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO"); + if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); + if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); + if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); + if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); + if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); + if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); + if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) + ionic_init_print(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); + if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) + ionic_init_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_init_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_init_print(INFO, "deleting station MAC addr"); + + ionic_lif_addr_del(lif, lif->mac_addr); + } + + memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, ETH_ALEN); + + if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { + ionic_init_print(NOTICE, "empty MAC addr (VF?)"); + return 0; + } + + ionic_init_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) { @@ -620,10 +840,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); @@ -642,6 +879,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_init_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 326cb17d5..f7c51c9ec 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[ETH_ALEN]; uint32_t info_sz; struct ionic_lif_info *info; rte_iova_t info_pa; @@ -84,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_ */ diff --git a/drivers/net/ionic/ionic_osdep.h b/drivers/net/ionic/ionic_osdep.h index 5b8baa67b..39a9cefa9 100644 --- a/drivers/net/ionic/ionic_osdep.h +++ b/drivers/net/ionic/ionic_osdep.h @@ -28,6 +28,8 @@ #define BIT_ULL(nr) (1ULL << (nr)) #define BITS_TO_LONGS(nr) div_round_up(nr, 8 * sizeof(long)) +#define ETH_ALEN 6 + #ifndef PAGE_SHIFT #define PAGE_SHIFT 12 #define PAGE_SIZE (1 << PAGE_SHIFT)