1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2669c8de6SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 3669c8de6SAlfredo Cardigliano */ 4669c8de6SAlfredo Cardigliano 5669c8de6SAlfredo Cardigliano #include <rte_malloc.h> 6669c8de6SAlfredo Cardigliano #include <rte_ethdev_driver.h> 7669c8de6SAlfredo Cardigliano 8669c8de6SAlfredo Cardigliano #include "ionic.h" 9669c8de6SAlfredo Cardigliano #include "ionic_logs.h" 10669c8de6SAlfredo Cardigliano #include "ionic_lif.h" 11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h" 1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h" 13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h" 14669c8de6SAlfredo Cardigliano 15598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr); 16598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr); 17598f6726SAlfredo Cardigliano 1801a6c311SAlfredo Cardigliano int 1901a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq) 2001a6c311SAlfredo Cardigliano { 2101a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 2201a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 2301a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 2401a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 2501a6c311SAlfredo Cardigliano .pending_work = true, 2601a6c311SAlfredo Cardigliano .cmd.q_control = { 2701a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 2801a6c311SAlfredo Cardigliano .type = q->type, 2901a6c311SAlfredo Cardigliano .index = q->index, 3001a6c311SAlfredo Cardigliano .oper = IONIC_Q_ENABLE, 3101a6c311SAlfredo Cardigliano }, 3201a6c311SAlfredo Cardigliano }; 3301a6c311SAlfredo Cardigliano 3401a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 3501a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 3601a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 3701a6c311SAlfredo Cardigliano } 3801a6c311SAlfredo Cardigliano 3901a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 4001a6c311SAlfredo Cardigliano } 4101a6c311SAlfredo Cardigliano 4201a6c311SAlfredo Cardigliano int 4301a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 4401a6c311SAlfredo Cardigliano { 4501a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 4601a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 4701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 4801a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 4901a6c311SAlfredo Cardigliano .pending_work = true, 5001a6c311SAlfredo Cardigliano .cmd.q_control = { 5101a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 5201a6c311SAlfredo Cardigliano .type = q->type, 5301a6c311SAlfredo Cardigliano .index = q->index, 5401a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 5501a6c311SAlfredo Cardigliano }, 5601a6c311SAlfredo Cardigliano }; 5701a6c311SAlfredo Cardigliano 5801a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 5901a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 6001a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 6101a6c311SAlfredo Cardigliano } 6201a6c311SAlfredo Cardigliano 6301a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 6401a6c311SAlfredo Cardigliano } 6501a6c311SAlfredo Cardigliano 6601a6c311SAlfredo Cardigliano int 67598f6726SAlfredo Cardigliano ionic_lif_stop(struct ionic_lif *lif __rte_unused) 68598f6726SAlfredo Cardigliano { 69598f6726SAlfredo Cardigliano /* Carrier OFF here */ 70598f6726SAlfredo Cardigliano 71598f6726SAlfredo Cardigliano return 0; 72598f6726SAlfredo Cardigliano } 73598f6726SAlfredo Cardigliano 74598f6726SAlfredo Cardigliano void 75598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 76598f6726SAlfredo Cardigliano { 77598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 7875f96902SAndrew Boyer int err; 79598f6726SAlfredo Cardigliano 80598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 81598f6726SAlfredo Cardigliano 82*00b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 8375f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 8475f96902SAndrew Boyer if (err) 854ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 86598f6726SAlfredo Cardigliano } 87598f6726SAlfredo Cardigliano 883cdfd905SAlfredo Cardigliano static void 893cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 903cdfd905SAlfredo Cardigliano { 913cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 923cdfd905SAlfredo Cardigliano uint32_t i; 933cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 943cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 953cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 963cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 973cdfd905SAlfredo Cardigliano 983cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 993cdfd905SAlfredo Cardigliano 1003cdfd905SAlfredo Cardigliano if (ls == NULL) { 1013cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1023cdfd905SAlfredo Cardigliano lif->port_id); 1033cdfd905SAlfredo Cardigliano return; 1043cdfd905SAlfredo Cardigliano } 1053cdfd905SAlfredo Cardigliano 1063cdfd905SAlfredo Cardigliano /* RX */ 1073cdfd905SAlfredo Cardigliano 1083cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1093cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1103cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1113cdfd905SAlfredo Cardigliano 1123cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1133cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1143cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1153cdfd905SAlfredo Cardigliano 1163cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1173cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1183cdfd905SAlfredo Cardigliano stats->imissed += 1193cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1203cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1213cdfd905SAlfredo Cardigliano rx_stats->no_room + 1223cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1233cdfd905SAlfredo Cardigliano } 1243cdfd905SAlfredo Cardigliano 1253cdfd905SAlfredo Cardigliano stats->imissed += 1263cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1273cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1283cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1293cdfd905SAlfredo Cardigliano 1303cdfd905SAlfredo Cardigliano stats->imissed += 1313cdfd905SAlfredo Cardigliano ls->rx_queue_empty + 1323cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1333cdfd905SAlfredo Cardigliano ls->rx_queue_disabled + 1343cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1353cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1363cdfd905SAlfredo Cardigliano 1373cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 1383cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1393cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1403cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1413cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1423cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1433cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1443cdfd905SAlfredo Cardigliano rx_stats->no_room + 1453cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1463cdfd905SAlfredo Cardigliano } 1473cdfd905SAlfredo Cardigliano 1483cdfd905SAlfredo Cardigliano /* TX */ 1493cdfd905SAlfredo Cardigliano 1503cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1513cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1523cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1533cdfd905SAlfredo Cardigliano 1543cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1553cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1563cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1573cdfd905SAlfredo Cardigliano 1583cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1593cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1603cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1613cdfd905SAlfredo Cardigliano } 1623cdfd905SAlfredo Cardigliano 1633cdfd905SAlfredo Cardigliano stats->oerrors += 1643cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1653cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1663cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1673cdfd905SAlfredo Cardigliano 1683cdfd905SAlfredo Cardigliano stats->oerrors += 1693cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1703cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1713cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1723cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1733cdfd905SAlfredo Cardigliano 1743cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 1753cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1763cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1773cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1783cdfd905SAlfredo Cardigliano } 1793cdfd905SAlfredo Cardigliano } 1803cdfd905SAlfredo Cardigliano 1813cdfd905SAlfredo Cardigliano void 1823cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 1833cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 1843cdfd905SAlfredo Cardigliano { 1853cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 1863cdfd905SAlfredo Cardigliano 1873cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 1883cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 1893cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 1903cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 1913cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 1923cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 1933cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 1943cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 1953cdfd905SAlfredo Cardigliano } 1963cdfd905SAlfredo Cardigliano 1973cdfd905SAlfredo Cardigliano void 1983cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 1993cdfd905SAlfredo Cardigliano { 2003cdfd905SAlfredo Cardigliano uint32_t i; 2013cdfd905SAlfredo Cardigliano 2023cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 2033cdfd905SAlfredo Cardigliano memset(&lif->rxqcqs[i]->stats.rx, 0, 2043cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 2053cdfd905SAlfredo Cardigliano memset(&lif->txqcqs[i]->stats.tx, 0, 2063cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2073cdfd905SAlfredo Cardigliano } 2083cdfd905SAlfredo Cardigliano 2093cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2103cdfd905SAlfredo Cardigliano } 2113cdfd905SAlfredo Cardigliano 2123cdfd905SAlfredo Cardigliano void 2133cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2143cdfd905SAlfredo Cardigliano { 2153cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2163cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2173cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2183cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2193cdfd905SAlfredo Cardigliano 2203cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2213cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2223cdfd905SAlfredo Cardigliano } 2233cdfd905SAlfredo Cardigliano 2243cdfd905SAlfredo Cardigliano void 2253cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2263cdfd905SAlfredo Cardigliano { 2273cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2283cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2293cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2303cdfd905SAlfredo Cardigliano 2313cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2323cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2333cdfd905SAlfredo Cardigliano } 2343cdfd905SAlfredo Cardigliano 235598f6726SAlfredo Cardigliano static int 23654fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 237598f6726SAlfredo Cardigliano { 23854fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 23954fe083fSAlfredo Cardigliano .pending_work = true, 24054fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 24154fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 24254fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_MAC, 24354fe083fSAlfredo Cardigliano }, 24454fe083fSAlfredo Cardigliano }; 24554fe083fSAlfredo Cardigliano int err; 24654fe083fSAlfredo Cardigliano 24754fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 24854fe083fSAlfredo Cardigliano 24954fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 25054fe083fSAlfredo Cardigliano if (err) 25154fe083fSAlfredo Cardigliano return err; 25254fe083fSAlfredo Cardigliano 25354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 25454fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 25554fe083fSAlfredo Cardigliano 25654fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 25754fe083fSAlfredo Cardigliano } 25854fe083fSAlfredo Cardigliano 25954fe083fSAlfredo Cardigliano static int 26054fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 26154fe083fSAlfredo Cardigliano { 26254fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 26354fe083fSAlfredo Cardigliano .pending_work = true, 26454fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 26554fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 26654fe083fSAlfredo Cardigliano }, 26754fe083fSAlfredo Cardigliano }; 26854fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 26954fe083fSAlfredo Cardigliano int err; 27054fe083fSAlfredo Cardigliano 27154fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 27254fe083fSAlfredo Cardigliano 27354fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 27454fe083fSAlfredo Cardigliano 27554fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 27654fe083fSAlfredo Cardigliano if (!f) { 27754fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 27854fe083fSAlfredo Cardigliano return -ENOENT; 27954fe083fSAlfredo Cardigliano } 28054fe083fSAlfredo Cardigliano 28154fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 28254fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 28354fe083fSAlfredo Cardigliano 28454fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 28554fe083fSAlfredo Cardigliano 28654fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 28754fe083fSAlfredo Cardigliano if (err) 28854fe083fSAlfredo Cardigliano return err; 28954fe083fSAlfredo Cardigliano 29054fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 29154fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 292598f6726SAlfredo Cardigliano 293598f6726SAlfredo Cardigliano return 0; 294598f6726SAlfredo Cardigliano } 295598f6726SAlfredo Cardigliano 29654fe083fSAlfredo Cardigliano int 29754fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 29854fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 29954fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 300598f6726SAlfredo Cardigliano { 30154fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 30254fe083fSAlfredo Cardigliano 30354fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 30454fe083fSAlfredo Cardigliano 30554fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 30654fe083fSAlfredo Cardigliano } 30754fe083fSAlfredo Cardigliano 30854fe083fSAlfredo Cardigliano void 30975f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 31054fe083fSAlfredo Cardigliano { 31154fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 31254fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 31375f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 31454fe083fSAlfredo Cardigliano 31554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 31654fe083fSAlfredo Cardigliano 31754fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 31854fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 31954fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 32054fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 32154fe083fSAlfredo Cardigliano return; 32254fe083fSAlfredo Cardigliano } 32354fe083fSAlfredo Cardigliano 32475f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 32575f96902SAndrew Boyer 32675f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 32754fe083fSAlfredo Cardigliano return; 32854fe083fSAlfredo Cardigliano 32975f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 33054fe083fSAlfredo Cardigliano } 33154fe083fSAlfredo Cardigliano 33254fe083fSAlfredo Cardigliano int 33354fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 33454fe083fSAlfredo Cardigliano { 33554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 33654fe083fSAlfredo Cardigliano 33754fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 33854fe083fSAlfredo Cardigliano 33954fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 34054fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 34154fe083fSAlfredo Cardigliano return -1; 34254fe083fSAlfredo Cardigliano } 34354fe083fSAlfredo Cardigliano 34454fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 34554fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 34654fe083fSAlfredo Cardigliano lif->mac_addr); 34754fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 34854fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 34954fe083fSAlfredo Cardigliano } 35054fe083fSAlfredo Cardigliano 35154fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 35254fe083fSAlfredo Cardigliano 35354fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 35454fe083fSAlfredo Cardigliano 35554fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 35654fe083fSAlfredo Cardigliano } 35754fe083fSAlfredo Cardigliano 35854fe083fSAlfredo Cardigliano static int 35954fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 36054fe083fSAlfredo Cardigliano { 36154fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 36254fe083fSAlfredo Cardigliano .pending_work = true, 36354fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 36454fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 36554fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_VLAN, 36654fe083fSAlfredo Cardigliano .vlan.vlan = vid, 36754fe083fSAlfredo Cardigliano }, 36854fe083fSAlfredo Cardigliano }; 36954fe083fSAlfredo Cardigliano int err; 37054fe083fSAlfredo Cardigliano 37154fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 37254fe083fSAlfredo Cardigliano if (err) 37354fe083fSAlfredo Cardigliano return err; 37454fe083fSAlfredo Cardigliano 37554fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 37654fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 37754fe083fSAlfredo Cardigliano 37854fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 37954fe083fSAlfredo Cardigliano } 38054fe083fSAlfredo Cardigliano 38154fe083fSAlfredo Cardigliano static int 38254fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 38354fe083fSAlfredo Cardigliano { 38454fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 38554fe083fSAlfredo Cardigliano .pending_work = true, 38654fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 38754fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 38854fe083fSAlfredo Cardigliano }, 38954fe083fSAlfredo Cardigliano }; 39054fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 39154fe083fSAlfredo Cardigliano int err; 39254fe083fSAlfredo Cardigliano 39354fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 39454fe083fSAlfredo Cardigliano 39554fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 39654fe083fSAlfredo Cardigliano 39754fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 39854fe083fSAlfredo Cardigliano if (!f) { 39954fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 40054fe083fSAlfredo Cardigliano return -ENOENT; 40154fe083fSAlfredo Cardigliano } 40254fe083fSAlfredo Cardigliano 40354fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 40454fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 40554fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 40654fe083fSAlfredo Cardigliano 40754fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 40854fe083fSAlfredo Cardigliano if (err) 40954fe083fSAlfredo Cardigliano return err; 41054fe083fSAlfredo Cardigliano 41154fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 41254fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 413598f6726SAlfredo Cardigliano 414598f6726SAlfredo Cardigliano return 0; 415598f6726SAlfredo Cardigliano } 416598f6726SAlfredo Cardigliano 41754fe083fSAlfredo Cardigliano int 41854fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 41954fe083fSAlfredo Cardigliano int on) 42054fe083fSAlfredo Cardigliano { 42154fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 42254fe083fSAlfredo Cardigliano int err; 42354fe083fSAlfredo Cardigliano 42454fe083fSAlfredo Cardigliano if (on) 42554fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 42654fe083fSAlfredo Cardigliano else 42754fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 42854fe083fSAlfredo Cardigliano 42954fe083fSAlfredo Cardigliano return err; 43054fe083fSAlfredo Cardigliano } 43154fe083fSAlfredo Cardigliano 432598f6726SAlfredo Cardigliano static void 433598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 434598f6726SAlfredo Cardigliano { 435598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 436598f6726SAlfredo Cardigliano .pending_work = true, 437598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 438598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 439598f6726SAlfredo Cardigliano .rx_mode = rx_mode, 440598f6726SAlfredo Cardigliano }, 441598f6726SAlfredo Cardigliano }; 442598f6726SAlfredo Cardigliano int err; 443598f6726SAlfredo Cardigliano 444598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 445598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 446598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 447598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 448598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 449598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 450598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 451598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 452598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 453598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 454598f6726SAlfredo Cardigliano 455598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 456598f6726SAlfredo Cardigliano if (err) 457598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 458598f6726SAlfredo Cardigliano } 459598f6726SAlfredo Cardigliano 460598f6726SAlfredo Cardigliano static void 461598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 462598f6726SAlfredo Cardigliano { 463598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 464598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 465598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 466598f6726SAlfredo Cardigliano } 467598f6726SAlfredo Cardigliano } 468598f6726SAlfredo Cardigliano 46954fe083fSAlfredo Cardigliano int 47054fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 47154fe083fSAlfredo Cardigliano { 47254fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 47354fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 47454fe083fSAlfredo Cardigliano 47554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 47654fe083fSAlfredo Cardigliano 47754fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 47854fe083fSAlfredo Cardigliano 47954fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 48054fe083fSAlfredo Cardigliano 48154fe083fSAlfredo Cardigliano return 0; 48254fe083fSAlfredo Cardigliano } 48354fe083fSAlfredo Cardigliano 48454fe083fSAlfredo Cardigliano int 48554fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 48654fe083fSAlfredo Cardigliano { 48754fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 48854fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 48954fe083fSAlfredo Cardigliano 49054fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 49154fe083fSAlfredo Cardigliano 49254fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 49354fe083fSAlfredo Cardigliano 49454fe083fSAlfredo Cardigliano return 0; 49554fe083fSAlfredo Cardigliano } 49654fe083fSAlfredo Cardigliano 49754fe083fSAlfredo Cardigliano int 49854fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 49954fe083fSAlfredo Cardigliano { 50054fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50154fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 50254fe083fSAlfredo Cardigliano 50354fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 50454fe083fSAlfredo Cardigliano 50554fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 50654fe083fSAlfredo Cardigliano 50754fe083fSAlfredo Cardigliano return 0; 50854fe083fSAlfredo Cardigliano } 50954fe083fSAlfredo Cardigliano 51054fe083fSAlfredo Cardigliano int 51154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 51254fe083fSAlfredo Cardigliano { 51354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 51454fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 51554fe083fSAlfredo Cardigliano 51654fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 51754fe083fSAlfredo Cardigliano 51854fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 51954fe083fSAlfredo Cardigliano 52054fe083fSAlfredo Cardigliano return 0; 52154fe083fSAlfredo Cardigliano } 522598f6726SAlfredo Cardigliano 523598f6726SAlfredo Cardigliano int 524598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu) 525598f6726SAlfredo Cardigliano { 526598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 527598f6726SAlfredo Cardigliano .pending_work = true, 528598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 529598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 530598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 531598f6726SAlfredo Cardigliano .mtu = new_mtu, 532598f6726SAlfredo Cardigliano }, 533598f6726SAlfredo Cardigliano }; 534598f6726SAlfredo Cardigliano int err; 535598f6726SAlfredo Cardigliano 536598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 537598f6726SAlfredo Cardigliano if (err) 538598f6726SAlfredo Cardigliano return err; 539598f6726SAlfredo Cardigliano 540598f6726SAlfredo Cardigliano return 0; 541598f6726SAlfredo Cardigliano } 542598f6726SAlfredo Cardigliano 543598f6726SAlfredo Cardigliano int 54401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 54501a6c311SAlfredo Cardigliano { 54601a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 54701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 54801a6c311SAlfredo Cardigliano unsigned long index; 54901a6c311SAlfredo Cardigliano 55001a6c311SAlfredo Cardigliano /* 55101a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 55201a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5534ae96cb8SAndrew Boyer * which has index = 0) 55401a6c311SAlfredo Cardigliano */ 55501a6c311SAlfredo Cardigliano 55601a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 55701a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 55801a6c311SAlfredo Cardigliano break; 55901a6c311SAlfredo Cardigliano 56001a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 56101a6c311SAlfredo Cardigliano return -ENOSPC; 56201a6c311SAlfredo Cardigliano 56301a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 56401a6c311SAlfredo Cardigliano 56501a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 56601a6c311SAlfredo Cardigliano 56701a6c311SAlfredo Cardigliano return 0; 56801a6c311SAlfredo Cardigliano } 56901a6c311SAlfredo Cardigliano 57001a6c311SAlfredo Cardigliano void 57101a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr) 57201a6c311SAlfredo Cardigliano { 57301a6c311SAlfredo Cardigliano if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED) 57401a6c311SAlfredo Cardigliano lif->adapter->intrs[intr->index] = false; 57501a6c311SAlfredo Cardigliano } 57601a6c311SAlfredo Cardigliano 57701a6c311SAlfredo Cardigliano static int 57801a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type, 57901a6c311SAlfredo Cardigliano uint32_t index, 58001a6c311SAlfredo Cardigliano const char *base, uint32_t flags, 58101a6c311SAlfredo Cardigliano uint32_t num_descs, 58201a6c311SAlfredo Cardigliano uint32_t desc_size, 58301a6c311SAlfredo Cardigliano uint32_t cq_desc_size, 58401a6c311SAlfredo Cardigliano uint32_t sg_desc_size, 5851abf69fcSAndrew Boyer struct ionic_qcq **qcq) 58601a6c311SAlfredo Cardigliano { 58701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 58801a6c311SAlfredo Cardigliano struct ionic_qcq *new; 58901a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 59001a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 59101a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 59201a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 59301a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 59401a6c311SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 59501a6c311SAlfredo Cardigliano int err; 59601a6c311SAlfredo Cardigliano 59701a6c311SAlfredo Cardigliano *qcq = NULL; 59801a6c311SAlfredo Cardigliano 59901a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 60001a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 60101a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 60201a6c311SAlfredo Cardigliano 60301a6c311SAlfredo Cardigliano total_size = RTE_ALIGN(q_size, PAGE_SIZE) + 60401a6c311SAlfredo Cardigliano RTE_ALIGN(cq_size, PAGE_SIZE); 60501a6c311SAlfredo Cardigliano /* 60601a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 60701a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 60801a6c311SAlfredo Cardigliano * Adding PAGE_SIZE. 60901a6c311SAlfredo Cardigliano */ 61001a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 61101a6c311SAlfredo Cardigliano 61201a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 61301a6c311SAlfredo Cardigliano total_size += RTE_ALIGN(sg_size, PAGE_SIZE); 61401a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 61501a6c311SAlfredo Cardigliano } 61601a6c311SAlfredo Cardigliano 61701a6c311SAlfredo Cardigliano new = rte_zmalloc("ionic", sizeof(*new), 0); 61801a6c311SAlfredo Cardigliano if (!new) { 61901a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 62001a6c311SAlfredo Cardigliano return -ENOMEM; 62101a6c311SAlfredo Cardigliano } 62201a6c311SAlfredo Cardigliano 62301a6c311SAlfredo Cardigliano new->lif = lif; 62401a6c311SAlfredo Cardigliano new->flags = flags; 62501a6c311SAlfredo Cardigliano 62601a6c311SAlfredo Cardigliano new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0); 62701a6c311SAlfredo Cardigliano if (!new->q.info) { 62801a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 62901a6c311SAlfredo Cardigliano return -ENOMEM; 63001a6c311SAlfredo Cardigliano } 63101a6c311SAlfredo Cardigliano 63201a6c311SAlfredo Cardigliano new->q.type = type; 63301a6c311SAlfredo Cardigliano 63401a6c311SAlfredo Cardigliano err = ionic_q_init(lif, idev, &new->q, index, num_descs, 6351abf69fcSAndrew Boyer desc_size, sg_desc_size); 63601a6c311SAlfredo Cardigliano if (err) { 63701a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 63801a6c311SAlfredo Cardigliano return err; 63901a6c311SAlfredo Cardigliano } 64001a6c311SAlfredo Cardigliano 64101a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) { 64201a6c311SAlfredo Cardigliano err = ionic_intr_alloc(lif, &new->intr); 64301a6c311SAlfredo Cardigliano if (err) 64401a6c311SAlfredo Cardigliano return err; 64501a6c311SAlfredo Cardigliano 64601a6c311SAlfredo Cardigliano ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index, 64701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 64801a6c311SAlfredo Cardigliano } else { 64901a6c311SAlfredo Cardigliano new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED; 65001a6c311SAlfredo Cardigliano } 65101a6c311SAlfredo Cardigliano 65201a6c311SAlfredo Cardigliano err = ionic_cq_init(lif, &new->cq, &new->intr, 65301a6c311SAlfredo Cardigliano num_descs, cq_desc_size); 65401a6c311SAlfredo Cardigliano if (err) { 65501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 65601a6c311SAlfredo Cardigliano goto err_out_free_intr; 65701a6c311SAlfredo Cardigliano } 65801a6c311SAlfredo Cardigliano 65901a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 66001a6c311SAlfredo Cardigliano base /* name */, index /* queue_idx */, 66101a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 66201a6c311SAlfredo Cardigliano 66301a6c311SAlfredo Cardigliano if (!new->base_z) { 66401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 66501a6c311SAlfredo Cardigliano err = -ENOMEM; 66601a6c311SAlfredo Cardigliano goto err_out_free_intr; 66701a6c311SAlfredo Cardigliano } 66801a6c311SAlfredo Cardigliano 66901a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 67001a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 67101a6c311SAlfredo Cardigliano new->total_size = total_size; 67201a6c311SAlfredo Cardigliano 67301a6c311SAlfredo Cardigliano q_base = new->base; 67401a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 67501a6c311SAlfredo Cardigliano 67601a6c311SAlfredo Cardigliano cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE); 67701a6c311SAlfredo Cardigliano cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE); 67801a6c311SAlfredo Cardigliano 67901a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 68001a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 68101a6c311SAlfredo Cardigliano PAGE_SIZE); 68201a6c311SAlfredo Cardigliano sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE); 68301a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 68401a6c311SAlfredo Cardigliano } 68501a6c311SAlfredo Cardigliano 6864ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6874ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 68801a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 68901a6c311SAlfredo Cardigliano 69001a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 69101a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 69201a6c311SAlfredo Cardigliano ionic_cq_bind(&new->cq, &new->q); 69301a6c311SAlfredo Cardigliano 69401a6c311SAlfredo Cardigliano *qcq = new; 69501a6c311SAlfredo Cardigliano 69601a6c311SAlfredo Cardigliano return 0; 69701a6c311SAlfredo Cardigliano 69801a6c311SAlfredo Cardigliano err_out_free_intr: 69901a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) 70001a6c311SAlfredo Cardigliano ionic_intr_free(lif, &new->intr); 70101a6c311SAlfredo Cardigliano 70201a6c311SAlfredo Cardigliano return err; 70301a6c311SAlfredo Cardigliano } 70401a6c311SAlfredo Cardigliano 70501a6c311SAlfredo Cardigliano void 70601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 70701a6c311SAlfredo Cardigliano { 70801a6c311SAlfredo Cardigliano if (qcq->base_z) { 70901a6c311SAlfredo Cardigliano qcq->base = NULL; 71001a6c311SAlfredo Cardigliano qcq->base_pa = 0; 71101a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 71201a6c311SAlfredo Cardigliano qcq->base_z = NULL; 71301a6c311SAlfredo Cardigliano } 71401a6c311SAlfredo Cardigliano 71501a6c311SAlfredo Cardigliano if (qcq->q.info) { 71601a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 71701a6c311SAlfredo Cardigliano qcq->q.info = NULL; 71801a6c311SAlfredo Cardigliano } 71901a6c311SAlfredo Cardigliano 72001a6c311SAlfredo Cardigliano rte_free(qcq); 72101a6c311SAlfredo Cardigliano } 72201a6c311SAlfredo Cardigliano 723a27d9013SAlfredo Cardigliano int 724a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs, 725a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 726a27d9013SAlfredo Cardigliano { 727a27d9013SAlfredo Cardigliano uint32_t flags; 728a27d9013SAlfredo Cardigliano int err = -ENOMEM; 729a27d9013SAlfredo Cardigliano 730a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 731a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags, 732a27d9013SAlfredo Cardigliano nrxq_descs, 733a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 734a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 735a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 7361abf69fcSAndrew Boyer &lif->rxqcqs[index]); 737a27d9013SAlfredo Cardigliano if (err) 738a27d9013SAlfredo Cardigliano return err; 739a27d9013SAlfredo Cardigliano 740a27d9013SAlfredo Cardigliano *qcq = lif->rxqcqs[index]; 741a27d9013SAlfredo Cardigliano 742a27d9013SAlfredo Cardigliano return 0; 743a27d9013SAlfredo Cardigliano } 744a27d9013SAlfredo Cardigliano 745a27d9013SAlfredo Cardigliano int 746a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs, 747a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 748a27d9013SAlfredo Cardigliano { 749a27d9013SAlfredo Cardigliano uint32_t flags; 750a27d9013SAlfredo Cardigliano int err = -ENOMEM; 751a27d9013SAlfredo Cardigliano 752a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 753a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags, 754a27d9013SAlfredo Cardigliano ntxq_descs, 755a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 756a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 757a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_sg_desc), 7581abf69fcSAndrew Boyer &lif->txqcqs[index]); 759a27d9013SAlfredo Cardigliano if (err) 760a27d9013SAlfredo Cardigliano return err; 761a27d9013SAlfredo Cardigliano 762a27d9013SAlfredo Cardigliano *qcq = lif->txqcqs[index]; 763a27d9013SAlfredo Cardigliano 764a27d9013SAlfredo Cardigliano return 0; 765a27d9013SAlfredo Cardigliano } 766a27d9013SAlfredo Cardigliano 76701a6c311SAlfredo Cardigliano static int 76801a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 76901a6c311SAlfredo Cardigliano { 77001a6c311SAlfredo Cardigliano uint32_t flags; 77101a6c311SAlfredo Cardigliano int err = -ENOMEM; 77201a6c311SAlfredo Cardigliano 77301a6c311SAlfredo Cardigliano flags = 0; 77401a6c311SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, 77501a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 77601a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 77701a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 77801a6c311SAlfredo Cardigliano 0, 7791abf69fcSAndrew Boyer &lif->adminqcq); 78027b942c8SAlfredo Cardigliano if (err) 78127b942c8SAlfredo Cardigliano return err; 78201a6c311SAlfredo Cardigliano 78327b942c8SAlfredo Cardigliano return 0; 78427b942c8SAlfredo Cardigliano } 78527b942c8SAlfredo Cardigliano 78627b942c8SAlfredo Cardigliano static int 78727b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 78827b942c8SAlfredo Cardigliano { 78927b942c8SAlfredo Cardigliano uint32_t flags; 79027b942c8SAlfredo Cardigliano int err = -ENOMEM; 79127b942c8SAlfredo Cardigliano 79227b942c8SAlfredo Cardigliano flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR; 79327b942c8SAlfredo Cardigliano 79427b942c8SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify", 79527b942c8SAlfredo Cardigliano flags, 79627b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 79727b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 79827b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 79927b942c8SAlfredo Cardigliano 0, 8001abf69fcSAndrew Boyer &lif->notifyqcq); 80101a6c311SAlfredo Cardigliano if (err) 80201a6c311SAlfredo Cardigliano return err; 80301a6c311SAlfredo Cardigliano 80401a6c311SAlfredo Cardigliano return 0; 80501a6c311SAlfredo Cardigliano } 80601a6c311SAlfredo Cardigliano 807c67719e1SAlfredo Cardigliano static void * 808c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num) 809c67719e1SAlfredo Cardigliano { 810c67719e1SAlfredo Cardigliano char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr; 811c67719e1SAlfredo Cardigliano 812c67719e1SAlfredo Cardigliano if (adapter->num_bars <= IONIC_PCI_BAR_DBELL) 813c67719e1SAlfredo Cardigliano return NULL; 814c67719e1SAlfredo Cardigliano 815c67719e1SAlfredo Cardigliano return (void *)&vaddr[page_num << PAGE_SHIFT]; 816c67719e1SAlfredo Cardigliano } 817c67719e1SAlfredo Cardigliano 818669c8de6SAlfredo Cardigliano int 819669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 820669c8de6SAlfredo Cardigliano { 821c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 822669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 82301a6c311SAlfredo Cardigliano int err; 824669c8de6SAlfredo Cardigliano 8254ae96cb8SAndrew Boyer /* 8264ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 8274ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 8284ae96cb8SAndrew Boyer */ 8294ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 8304ae96cb8SAndrew Boyer 8314ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 832669c8de6SAlfredo Cardigliano 833669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 834669c8de6SAlfredo Cardigliano 83501a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 83601a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 83701a6c311SAlfredo Cardigliano 838*00b65da5SAndrew Boyer lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0); 839c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 840c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 841c67719e1SAlfredo Cardigliano return -ENOMEM; 842c67719e1SAlfredo Cardigliano } 843c67719e1SAlfredo Cardigliano 844a27d9013SAlfredo Cardigliano lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) * 845a27d9013SAlfredo Cardigliano adapter->max_ntxqs_per_lif, 0); 846a27d9013SAlfredo Cardigliano 847a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 848a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 849a27d9013SAlfredo Cardigliano return -ENOMEM; 850a27d9013SAlfredo Cardigliano } 851a27d9013SAlfredo Cardigliano 852a27d9013SAlfredo Cardigliano lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) * 853a27d9013SAlfredo Cardigliano adapter->max_nrxqs_per_lif, 0); 854a27d9013SAlfredo Cardigliano 855a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 856a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 857a27d9013SAlfredo Cardigliano return -ENOMEM; 858a27d9013SAlfredo Cardigliano } 859a27d9013SAlfredo Cardigliano 86027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 86127b942c8SAlfredo Cardigliano 86227b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 86327b942c8SAlfredo Cardigliano if (err) { 86427b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 86527b942c8SAlfredo Cardigliano return err; 86627b942c8SAlfredo Cardigliano } 86727b942c8SAlfredo Cardigliano 86827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 86927b942c8SAlfredo Cardigliano 87001a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 87101a6c311SAlfredo Cardigliano if (err) { 87201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 87301a6c311SAlfredo Cardigliano return err; 87401a6c311SAlfredo Cardigliano } 87501a6c311SAlfredo Cardigliano 87601a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 87701a6c311SAlfredo Cardigliano 878669c8de6SAlfredo Cardigliano lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); 879669c8de6SAlfredo Cardigliano 880669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 881669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 882669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 883669c8de6SAlfredo Cardigliano if (!lif->info_z) { 884669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 885669c8de6SAlfredo Cardigliano return -ENOMEM; 886669c8de6SAlfredo Cardigliano } 887669c8de6SAlfredo Cardigliano 888669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 889669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 890669c8de6SAlfredo Cardigliano 891669c8de6SAlfredo Cardigliano return 0; 892669c8de6SAlfredo Cardigliano } 893669c8de6SAlfredo Cardigliano 894669c8de6SAlfredo Cardigliano void 895669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 896669c8de6SAlfredo Cardigliano { 89727b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 89827b942c8SAlfredo Cardigliano ionic_qcq_free(lif->notifyqcq); 89927b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 90027b942c8SAlfredo Cardigliano } 90127b942c8SAlfredo Cardigliano 90201a6c311SAlfredo Cardigliano if (lif->adminqcq) { 90301a6c311SAlfredo Cardigliano ionic_qcq_free(lif->adminqcq); 90401a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 90501a6c311SAlfredo Cardigliano } 90601a6c311SAlfredo Cardigliano 907a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 908a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 909a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 910a27d9013SAlfredo Cardigliano } 911a27d9013SAlfredo Cardigliano 912a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 913a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 914a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 915a27d9013SAlfredo Cardigliano } 916a27d9013SAlfredo Cardigliano 917669c8de6SAlfredo Cardigliano if (lif->info) { 918669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 919669c8de6SAlfredo Cardigliano lif->info = NULL; 920669c8de6SAlfredo Cardigliano } 921669c8de6SAlfredo Cardigliano } 922669c8de6SAlfredo Cardigliano 92322e7171bSAlfredo Cardigliano int 92422e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 92522e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 92622e7171bSAlfredo Cardigliano { 92722e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 92822e7171bSAlfredo Cardigliano .pending_work = true, 92922e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 93022e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 93122e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 93222e7171bSAlfredo Cardigliano .rss.types = types, 93322e7171bSAlfredo Cardigliano .rss.addr = lif->rss_ind_tbl_pa, 93422e7171bSAlfredo Cardigliano }, 93522e7171bSAlfredo Cardigliano }; 93622e7171bSAlfredo Cardigliano unsigned int i; 93722e7171bSAlfredo Cardigliano 93822e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 93922e7171bSAlfredo Cardigliano 94022e7171bSAlfredo Cardigliano lif->rss_types = types; 94122e7171bSAlfredo Cardigliano 94222e7171bSAlfredo Cardigliano if (key) 94322e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 94422e7171bSAlfredo Cardigliano 94522e7171bSAlfredo Cardigliano if (indir) 94622e7171bSAlfredo Cardigliano for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++) 94722e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 94822e7171bSAlfredo Cardigliano 94922e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 95022e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 95122e7171bSAlfredo Cardigliano 95222e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 95322e7171bSAlfredo Cardigliano } 95422e7171bSAlfredo Cardigliano 95522e7171bSAlfredo Cardigliano static int 95622e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 95722e7171bSAlfredo Cardigliano { 95822e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 95922e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 96022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 96122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 96222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 96322e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 96422e7171bSAlfredo Cardigliano }; 96522e7171bSAlfredo Cardigliano uint32_t i; 9663d845eddSAndrew Boyer uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz; 96722e7171bSAlfredo Cardigliano 96822e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 96922e7171bSAlfredo Cardigliano 9703d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 97122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 9723d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 9733d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 9743d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 97522e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 97622e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 97722e7171bSAlfredo Cardigliano return -ENOMEM; 97822e7171bSAlfredo Cardigliano } 97922e7171bSAlfredo Cardigliano 98022e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 98122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 9823d845eddSAndrew Boyer } 9833d845eddSAndrew Boyer 9843d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 9853d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 98622e7171bSAlfredo Cardigliano 98722e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 9883d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 98922e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 9903d845eddSAndrew Boyer } 99122e7171bSAlfredo Cardigliano 9923d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 99322e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 99422e7171bSAlfredo Cardigliano } 99522e7171bSAlfredo Cardigliano 99622e7171bSAlfredo Cardigliano static void 99722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 99822e7171bSAlfredo Cardigliano { 99922e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 100022e7171bSAlfredo Cardigliano return; 100122e7171bSAlfredo Cardigliano 100222e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 100322e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 100422e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 100522e7171bSAlfredo Cardigliano 100622e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 100722e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 100822e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 100922e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 101022e7171bSAlfredo Cardigliano } 101122e7171bSAlfredo Cardigliano } 101222e7171bSAlfredo Cardigliano 101301a6c311SAlfredo Cardigliano static void 101401a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) 101501a6c311SAlfredo Cardigliano { 101601a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 101701a6c311SAlfredo Cardigliano 101801a6c311SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) 101901a6c311SAlfredo Cardigliano return; 102001a6c311SAlfredo Cardigliano 102101a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 102201a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 102301a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 102401a6c311SAlfredo Cardigliano 102501a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 102601a6c311SAlfredo Cardigliano } 102701a6c311SAlfredo Cardigliano 1028a27d9013SAlfredo Cardigliano void 1029a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq) 1030a27d9013SAlfredo Cardigliano { 1031a27d9013SAlfredo Cardigliano ionic_lif_qcq_deinit(qcq->lif, qcq); 1032a27d9013SAlfredo Cardigliano } 1033a27d9013SAlfredo Cardigliano 1034a27d9013SAlfredo Cardigliano void 1035a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq) 1036a27d9013SAlfredo Cardigliano { 1037a27d9013SAlfredo Cardigliano ionic_lif_qcq_deinit(qcq->lif, qcq); 1038a27d9013SAlfredo Cardigliano } 1039a27d9013SAlfredo Cardigliano 104001a6c311SAlfredo Cardigliano bool 104101a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index, 104201a6c311SAlfredo Cardigliano void *cb_arg __rte_unused) 104301a6c311SAlfredo Cardigliano { 104401a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc_base = cq->base; 104501a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index]; 104601a6c311SAlfredo Cardigliano 104701a6c311SAlfredo Cardigliano if (!color_match(cq_desc->color, cq->done_color)) 104801a6c311SAlfredo Cardigliano return false; 104901a6c311SAlfredo Cardigliano 105001a6c311SAlfredo Cardigliano ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL); 105101a6c311SAlfredo Cardigliano 105201a6c311SAlfredo Cardigliano return true; 105301a6c311SAlfredo Cardigliano } 105401a6c311SAlfredo Cardigliano 105501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 105601a6c311SAlfredo Cardigliano int 105701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 105801a6c311SAlfredo Cardigliano void *cb_arg) 105901a6c311SAlfredo Cardigliano { 106001a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 106101a6c311SAlfredo Cardigliano uint32_t work_done; 106201a6c311SAlfredo Cardigliano 106301a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 106401a6c311SAlfredo Cardigliano 106501a6c311SAlfredo Cardigliano return work_done; 106601a6c311SAlfredo Cardigliano } 106701a6c311SAlfredo Cardigliano 106827b942c8SAlfredo Cardigliano static void 106927b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 107027b942c8SAlfredo Cardigliano { 107127b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 107227b942c8SAlfredo Cardigliano bool link_up; 107327b942c8SAlfredo Cardigliano 107427b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 107527b942c8SAlfredo Cardigliano 107627b942c8SAlfredo Cardigliano if (!lif->info) 107727b942c8SAlfredo Cardigliano return; 107827b942c8SAlfredo Cardigliano 107927b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 108027b942c8SAlfredo Cardigliano 108127b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 108227b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 108327b942c8SAlfredo Cardigliano return; 108427b942c8SAlfredo Cardigliano 108527b942c8SAlfredo Cardigliano if (link_up) { 108627b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link up - %d Gbps", 108727b942c8SAlfredo Cardigliano lif->info->status.link_speed); 108827b942c8SAlfredo Cardigliano adapter->link_speed = lif->info->status.link_speed; 108927b942c8SAlfredo Cardigliano } else { 109027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 109127b942c8SAlfredo Cardigliano } 109227b942c8SAlfredo Cardigliano 109327b942c8SAlfredo Cardigliano adapter->link_up = link_up; 109427b942c8SAlfredo Cardigliano } 109527b942c8SAlfredo Cardigliano 109627b942c8SAlfredo Cardigliano static bool 109727b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 109827b942c8SAlfredo Cardigliano { 109927b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 110027b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 110127b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 110227b942c8SAlfredo Cardigliano 110327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 110427b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 110527b942c8SAlfredo Cardigliano 110627b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 110727b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 110827b942c8SAlfredo Cardigliano return false; 110927b942c8SAlfredo Cardigliano 111027b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 111127b942c8SAlfredo Cardigliano 111227b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 111327b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 111427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 111527b942c8SAlfredo Cardigliano "Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d", 111627b942c8SAlfredo Cardigliano cq_desc->event.eid, 111727b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 111827b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 111927b942c8SAlfredo Cardigliano 112027b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 112127b942c8SAlfredo Cardigliano 112227b942c8SAlfredo Cardigliano break; 112327b942c8SAlfredo Cardigliano default: 112427b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 112527b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 112627b942c8SAlfredo Cardigliano break; 112727b942c8SAlfredo Cardigliano } 112827b942c8SAlfredo Cardigliano 112927b942c8SAlfredo Cardigliano return true; 113027b942c8SAlfredo Cardigliano } 113127b942c8SAlfredo Cardigliano 113227b942c8SAlfredo Cardigliano int 113327b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 113427b942c8SAlfredo Cardigliano { 113527b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 113627b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 113727b942c8SAlfredo Cardigliano uint32_t work_done; 113827b942c8SAlfredo Cardigliano 113927b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 114027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 114127b942c8SAlfredo Cardigliano return -1; 114227b942c8SAlfredo Cardigliano } 114327b942c8SAlfredo Cardigliano 114427b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 114527b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 114627b942c8SAlfredo Cardigliano 114727b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 114827b942c8SAlfredo Cardigliano 114927b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 115027b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 115127b942c8SAlfredo Cardigliano 115227b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 115327b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 115427b942c8SAlfredo Cardigliano 115527b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 115627b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 115727b942c8SAlfredo Cardigliano 115827b942c8SAlfredo Cardigliano return 0; 115927b942c8SAlfredo Cardigliano } 116027b942c8SAlfredo Cardigliano 116101a6c311SAlfredo Cardigliano static int 116201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 116301a6c311SAlfredo Cardigliano { 116401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 116501a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 116601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 116701a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 116801a6c311SAlfredo Cardigliano int err; 116901a6c311SAlfredo Cardigliano 1170*00b65da5SAndrew Boyer ionic_dev_cmd_adminq_init(idev, qcq, qcq->intr.index); 117101a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 117201a6c311SAlfredo Cardigliano if (err) 117301a6c311SAlfredo Cardigliano return err; 117401a6c311SAlfredo Cardigliano 117501a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 117601a6c311SAlfredo Cardigliano 117701a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 117801a6c311SAlfredo Cardigliano q->hw_index = comp.hw_index; 117901a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 118001a6c311SAlfredo Cardigliano 118101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 118201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 118301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 118401a6c311SAlfredo Cardigliano 118501a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 118601a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 118701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 118801a6c311SAlfredo Cardigliano 118901a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 119001a6c311SAlfredo Cardigliano 119101a6c311SAlfredo Cardigliano return 0; 119201a6c311SAlfredo Cardigliano } 119301a6c311SAlfredo Cardigliano 119427b942c8SAlfredo Cardigliano static int 119527b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 119627b942c8SAlfredo Cardigliano { 119727b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 119827b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 119927b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 120027b942c8SAlfredo Cardigliano int err; 120127b942c8SAlfredo Cardigliano 120227b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 120327b942c8SAlfredo Cardigliano .pending_work = true, 120427b942c8SAlfredo Cardigliano .cmd.q_init = { 120527b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 120627b942c8SAlfredo Cardigliano .type = q->type, 120727b942c8SAlfredo Cardigliano .index = q->index, 120827b942c8SAlfredo Cardigliano .flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA), 120927b942c8SAlfredo Cardigliano .intr_index = qcq->intr.index, 121027b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 121127b942c8SAlfredo Cardigliano .ring_base = q->base_pa, 121227b942c8SAlfredo Cardigliano } 121327b942c8SAlfredo Cardigliano }; 121427b942c8SAlfredo Cardigliano 121527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.index %d", 121627b942c8SAlfredo Cardigliano ctx.cmd.q_init.index); 121727b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", 121827b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 121927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 122027b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 12214ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 122227b942c8SAlfredo Cardigliano 122327b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 122427b942c8SAlfredo Cardigliano if (err) 122527b942c8SAlfredo Cardigliano return err; 122627b942c8SAlfredo Cardigliano 122727b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 122827b942c8SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 122927b942c8SAlfredo Cardigliano q->db = NULL; 123027b942c8SAlfredo Cardigliano 123127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 123227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 123327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 123427b942c8SAlfredo Cardigliano 123527b942c8SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 123627b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 123727b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 123827b942c8SAlfredo Cardigliano 123927b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 124027b942c8SAlfredo Cardigliano 124127b942c8SAlfredo Cardigliano return 0; 124227b942c8SAlfredo Cardigliano } 124327b942c8SAlfredo Cardigliano 1244669c8de6SAlfredo Cardigliano int 1245598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1246598f6726SAlfredo Cardigliano { 1247598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1248598f6726SAlfredo Cardigliano .pending_work = true, 1249598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1250598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1251598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 1252598f6726SAlfredo Cardigliano .features = lif->features, 1253598f6726SAlfredo Cardigliano }, 1254598f6726SAlfredo Cardigliano }; 1255598f6726SAlfredo Cardigliano int err; 1256598f6726SAlfredo Cardigliano 1257598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1258598f6726SAlfredo Cardigliano if (err) 1259598f6726SAlfredo Cardigliano return err; 1260598f6726SAlfredo Cardigliano 1261598f6726SAlfredo Cardigliano lif->hw_features = (ctx.cmd.lif_setattr.features & 1262598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1263598f6726SAlfredo Cardigliano 1264598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1265598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1266598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1267598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1268598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1269598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1270598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1271598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1272598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1273598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1274598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1275598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1276598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1277598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1278598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1279598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1280598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1281598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1282598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1283598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1284598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1285598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1286598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1287598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1288598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1289598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1290598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1291598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1292598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1293598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1294598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1295598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1296598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1297598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1298598f6726SAlfredo Cardigliano 1299598f6726SAlfredo Cardigliano return 0; 1300598f6726SAlfredo Cardigliano } 1301598f6726SAlfredo Cardigliano 1302a27d9013SAlfredo Cardigliano int 1303a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq) 1304a27d9013SAlfredo Cardigliano { 1305a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1306a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1307a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1308a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1309a27d9013SAlfredo Cardigliano .pending_work = true, 1310a27d9013SAlfredo Cardigliano .cmd.q_init = { 1311a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1312a27d9013SAlfredo Cardigliano .type = q->type, 1313a27d9013SAlfredo Cardigliano .index = q->index, 1314a27d9013SAlfredo Cardigliano .flags = IONIC_QINIT_F_SG, 1315a27d9013SAlfredo Cardigliano .intr_index = cq->bound_intr->index, 1316a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1317a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1318a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1319a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1320a27d9013SAlfredo Cardigliano }, 1321a27d9013SAlfredo Cardigliano }; 1322a27d9013SAlfredo Cardigliano int err; 1323a27d9013SAlfredo Cardigliano 1324a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index); 1325a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", 1326a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1327a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1328a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13294ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1330a27d9013SAlfredo Cardigliano 1331a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1332a27d9013SAlfredo Cardigliano if (err) 1333a27d9013SAlfredo Cardigliano return err; 1334a27d9013SAlfredo Cardigliano 1335a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1336a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1337a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1338a27d9013SAlfredo Cardigliano 1339a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1340a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1341a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1342a27d9013SAlfredo Cardigliano 1343a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1344a27d9013SAlfredo Cardigliano 1345a27d9013SAlfredo Cardigliano return 0; 1346a27d9013SAlfredo Cardigliano } 1347a27d9013SAlfredo Cardigliano 1348a27d9013SAlfredo Cardigliano int 1349a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq) 1350a27d9013SAlfredo Cardigliano { 1351a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1352a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1353a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1354a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1355a27d9013SAlfredo Cardigliano .pending_work = true, 1356a27d9013SAlfredo Cardigliano .cmd.q_init = { 1357a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1358a27d9013SAlfredo Cardigliano .type = q->type, 1359a27d9013SAlfredo Cardigliano .index = q->index, 1360a27d9013SAlfredo Cardigliano .flags = IONIC_QINIT_F_SG, 1361a27d9013SAlfredo Cardigliano .intr_index = cq->bound_intr->index, 1362a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1363a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1364a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1365a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1366a27d9013SAlfredo Cardigliano }, 1367a27d9013SAlfredo Cardigliano }; 1368a27d9013SAlfredo Cardigliano int err; 1369a27d9013SAlfredo Cardigliano 1370a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index); 1371a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", 1372a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1373a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1374a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13754ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1376a27d9013SAlfredo Cardigliano 1377a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1378a27d9013SAlfredo Cardigliano if (err) 1379a27d9013SAlfredo Cardigliano return err; 1380a27d9013SAlfredo Cardigliano 1381a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1382a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1383a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1384a27d9013SAlfredo Cardigliano 1385a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1386a27d9013SAlfredo Cardigliano 1387a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1388a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1389a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1390a27d9013SAlfredo Cardigliano 1391a27d9013SAlfredo Cardigliano return 0; 1392a27d9013SAlfredo Cardigliano } 1393a27d9013SAlfredo Cardigliano 1394598f6726SAlfredo Cardigliano static int 1395598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1396598f6726SAlfredo Cardigliano { 1397598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1398598f6726SAlfredo Cardigliano .pending_work = true, 1399598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1400598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1401598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1402598f6726SAlfredo Cardigliano }, 1403598f6726SAlfredo Cardigliano }; 1404598f6726SAlfredo Cardigliano int err; 1405598f6726SAlfredo Cardigliano 1406598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1407598f6726SAlfredo Cardigliano 1408598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1409598f6726SAlfredo Cardigliano if (err) 1410598f6726SAlfredo Cardigliano return err; 1411598f6726SAlfredo Cardigliano 1412598f6726SAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *) 1413598f6726SAlfredo Cardigliano lif->mac_addr)) { 1414598f6726SAlfredo Cardigliano IONIC_PRINT(INFO, "deleting station MAC addr"); 1415598f6726SAlfredo Cardigliano 1416598f6726SAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 1417598f6726SAlfredo Cardigliano } 1418598f6726SAlfredo Cardigliano 1419598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1420598f6726SAlfredo Cardigliano 1421598f6726SAlfredo Cardigliano if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 1422598f6726SAlfredo Cardigliano IONIC_PRINT(NOTICE, "empty MAC addr (VF?)"); 1423598f6726SAlfredo Cardigliano return 0; 1424598f6726SAlfredo Cardigliano } 1425598f6726SAlfredo Cardigliano 1426598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adding station MAC addr"); 1427598f6726SAlfredo Cardigliano 1428598f6726SAlfredo Cardigliano ionic_lif_addr_add(lif, lif->mac_addr); 1429598f6726SAlfredo Cardigliano 1430598f6726SAlfredo Cardigliano return 0; 1431598f6726SAlfredo Cardigliano } 1432598f6726SAlfredo Cardigliano 1433598f6726SAlfredo Cardigliano static void 1434598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1435598f6726SAlfredo Cardigliano { 1436598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1437598f6726SAlfredo Cardigliano .pending_work = true, 1438598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1439598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1440598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1441598f6726SAlfredo Cardigliano }, 1442598f6726SAlfredo Cardigliano }; 1443598f6726SAlfredo Cardigliano 14444ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 14454ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1446598f6726SAlfredo Cardigliano 1447598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1448598f6726SAlfredo Cardigliano } 1449598f6726SAlfredo Cardigliano 1450598f6726SAlfredo Cardigliano int 1451669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1452669c8de6SAlfredo Cardigliano { 1453669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1454669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 1455669c8de6SAlfredo Cardigliano int err; 1456669c8de6SAlfredo Cardigliano 14573cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 14583cdfd905SAlfredo Cardigliano 1459*00b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1460669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1461669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 1462669c8de6SAlfredo Cardigliano if (err) 1463669c8de6SAlfredo Cardigliano return err; 1464669c8de6SAlfredo Cardigliano 1465669c8de6SAlfredo Cardigliano lif->hw_index = comp.hw_index; 1466669c8de6SAlfredo Cardigliano 146701a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 146801a6c311SAlfredo Cardigliano if (err) 146901a6c311SAlfredo Cardigliano return err; 147001a6c311SAlfredo Cardigliano 147127b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 147227b942c8SAlfredo Cardigliano if (err) 147327b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 147427b942c8SAlfredo Cardigliano 1475a27d9013SAlfredo Cardigliano lif->features = 1476a27d9013SAlfredo Cardigliano IONIC_ETH_HW_VLAN_TX_TAG 1477a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_VLAN_RX_STRIP 1478a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_VLAN_RX_FILTER 1479a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_HASH 1480a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TX_SG 1481a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_SG 148264b08152SAlfredo Cardigliano | IONIC_ETH_HW_TX_CSUM 1483a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_CSUM 1484a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO 1485a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO_IPV6 1486a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO_ECN; 1487598f6726SAlfredo Cardigliano 1488598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1489598f6726SAlfredo Cardigliano if (err) 1490598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1491598f6726SAlfredo Cardigliano 149254fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1493598f6726SAlfredo Cardigliano if (err) 1494598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1495598f6726SAlfredo Cardigliano 149654fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 149754fe083fSAlfredo Cardigliano if (err) 149854fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 149954fe083fSAlfredo Cardigliano 1500598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1501598f6726SAlfredo Cardigliano 1502669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1503669c8de6SAlfredo Cardigliano 1504669c8de6SAlfredo Cardigliano return 0; 150527b942c8SAlfredo Cardigliano 150654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 150754fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 150854fe083fSAlfredo Cardigliano 1509598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 1510598f6726SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->notifyqcq); 1511598f6726SAlfredo Cardigliano 151227b942c8SAlfredo Cardigliano err_out_adminq_deinit: 151327b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 151427b942c8SAlfredo Cardigliano 151527b942c8SAlfredo Cardigliano return err; 1516669c8de6SAlfredo Cardigliano } 1517669c8de6SAlfredo Cardigliano 1518669c8de6SAlfredo Cardigliano void 1519669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1520669c8de6SAlfredo Cardigliano { 1521669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1522669c8de6SAlfredo Cardigliano return; 1523669c8de6SAlfredo Cardigliano 152454fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 152522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 152627b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->notifyqcq); 152701a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 152801a6c311SAlfredo Cardigliano 1529669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1530669c8de6SAlfredo Cardigliano } 1531669c8de6SAlfredo Cardigliano 1532669c8de6SAlfredo Cardigliano int 1533598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1534598f6726SAlfredo Cardigliano { 153522e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 153622e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 153722e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 153822e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 153922e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 154022e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 154122e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 154222e7171bSAlfredo Cardigliano 1543598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1544598f6726SAlfredo Cardigliano 154522e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 154622e7171bSAlfredo Cardigliano lif->port_id); 154722e7171bSAlfredo Cardigliano 154822e7171bSAlfredo Cardigliano if (nrxqs > 0) 154922e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 155022e7171bSAlfredo Cardigliano 155122e7171bSAlfredo Cardigliano if (ntxqs > 0) 155222e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 155322e7171bSAlfredo Cardigliano 155422e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 155522e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1556a27d9013SAlfredo Cardigliano 1557598f6726SAlfredo Cardigliano return 0; 1558598f6726SAlfredo Cardigliano } 1559598f6726SAlfredo Cardigliano 1560598f6726SAlfredo Cardigliano int 1561598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1562598f6726SAlfredo Cardigliano { 15630578335aSAndrew Boyer uint32_t rx_mode; 1564a27d9013SAlfredo Cardigliano uint32_t i; 1565a27d9013SAlfredo Cardigliano int err; 1566598f6726SAlfredo Cardigliano 156722e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 156822e7171bSAlfredo Cardigliano if (err) 156922e7171bSAlfredo Cardigliano return err; 157022e7171bSAlfredo Cardigliano 15710578335aSAndrew Boyer if (!lif->rx_mode) { 15720578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 15730578335aSAndrew Boyer lif->name); 1574598f6726SAlfredo Cardigliano 15750578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1576598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1577598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1578598f6726SAlfredo Cardigliano 1579598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 15800578335aSAndrew Boyer } 1581598f6726SAlfredo Cardigliano 1582a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1583a27d9013SAlfredo Cardigliano "on port %u", 1584a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1585a27d9013SAlfredo Cardigliano 1586a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1587a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = lif->rxqcqs[i]; 158802eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1589a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1590a27d9013SAlfredo Cardigliano 1591a27d9013SAlfredo Cardigliano if (err) 1592a27d9013SAlfredo Cardigliano return err; 1593a27d9013SAlfredo Cardigliano } 1594a27d9013SAlfredo Cardigliano } 1595a27d9013SAlfredo Cardigliano 1596a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1597a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = lif->txqcqs[i]; 159802eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1599a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1600a27d9013SAlfredo Cardigliano 1601a27d9013SAlfredo Cardigliano if (err) 1602a27d9013SAlfredo Cardigliano return err; 1603a27d9013SAlfredo Cardigliano } 1604a27d9013SAlfredo Cardigliano } 1605a27d9013SAlfredo Cardigliano 1606598f6726SAlfredo Cardigliano ionic_link_status_check(lif); 1607598f6726SAlfredo Cardigliano 1608598f6726SAlfredo Cardigliano /* Carrier ON here */ 1609598f6726SAlfredo Cardigliano 1610598f6726SAlfredo Cardigliano return 0; 1611598f6726SAlfredo Cardigliano } 1612598f6726SAlfredo Cardigliano 1613598f6726SAlfredo Cardigliano int 1614669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1615669c8de6SAlfredo Cardigliano { 1616669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1617669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1618669c8de6SAlfredo Cardigliano int err; 1619669c8de6SAlfredo Cardigliano unsigned int i; 1620669c8de6SAlfredo Cardigliano unsigned int lif_words = sizeof(ident->lif.words) / 1621669c8de6SAlfredo Cardigliano sizeof(ident->lif.words[0]); 1622669c8de6SAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 1623669c8de6SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 1624669c8de6SAlfredo Cardigliano unsigned int nwords; 1625669c8de6SAlfredo Cardigliano 1626669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1627669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1628669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1629669c8de6SAlfredo Cardigliano if (err) 1630669c8de6SAlfredo Cardigliano return (err); 1631669c8de6SAlfredo Cardigliano 1632669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1633669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1634669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1635669c8de6SAlfredo Cardigliano 1636669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 1637669c8de6SAlfredo Cardigliano ident->lif.capabilities); 1638669c8de6SAlfredo Cardigliano 1639669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 1640669c8de6SAlfredo Cardigliano ident->lif.eth.max_ucast_filters); 1641669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 1642669c8de6SAlfredo Cardigliano ident->lif.eth.max_mcast_filters); 1643669c8de6SAlfredo Cardigliano 1644669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 1645669c8de6SAlfredo Cardigliano ident->lif.eth.config.features); 1646669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 1647669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]); 1648669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 1649669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]); 1650669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 1651669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 1652669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 1653669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 1654669c8de6SAlfredo Cardigliano 1655669c8de6SAlfredo Cardigliano return 0; 1656669c8de6SAlfredo Cardigliano } 1657669c8de6SAlfredo Cardigliano 1658669c8de6SAlfredo Cardigliano int 1659669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1660669c8de6SAlfredo Cardigliano { 1661669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1662669c8de6SAlfredo Cardigliano uint32_t nintrs, dev_nintrs = ident->dev.nintrs; 1663669c8de6SAlfredo Cardigliano 1664669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 1665669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 1666669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 1667669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 1668669c8de6SAlfredo Cardigliano 1669*00b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1670669c8de6SAlfredo Cardigliano 1671669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 16724ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 16734ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1674669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1675669c8de6SAlfredo Cardigliano return -ENOSPC; 1676669c8de6SAlfredo Cardigliano } 1677669c8de6SAlfredo Cardigliano 1678669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1679669c8de6SAlfredo Cardigliano 1680669c8de6SAlfredo Cardigliano return 0; 1681669c8de6SAlfredo Cardigliano } 1682