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> 6df96fd0dSBruce Richardson #include <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 15c5d15850SAndrew Boyer /* queuetype support level */ 16c5d15850SAndrew Boyer static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = { 17c5d15850SAndrew Boyer [IONIC_QTYPE_ADMINQ] = 0, /* 0 = Base version with CQ support */ 18c5d15850SAndrew Boyer [IONIC_QTYPE_NOTIFYQ] = 0, /* 0 = Base version */ 19c5d15850SAndrew Boyer [IONIC_QTYPE_RXQ] = 2, /* 0 = Base version with CQ+SG support 20c5d15850SAndrew Boyer * 1 = ... with EQ 21c5d15850SAndrew Boyer * 2 = ... with CMB 22c5d15850SAndrew Boyer */ 23c5d15850SAndrew Boyer [IONIC_QTYPE_TXQ] = 3, /* 0 = Base version with CQ+SG support 24c5d15850SAndrew Boyer * 1 = ... with Tx SG version 1 25c5d15850SAndrew Boyer * 2 = ... with EQ 26c5d15850SAndrew Boyer * 3 = ... with CMB 27c5d15850SAndrew Boyer */ 28c5d15850SAndrew Boyer }; 29c5d15850SAndrew Boyer 30598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr); 31598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr); 32598f6726SAlfredo Cardigliano 3301a6c311SAlfredo Cardigliano int 3401a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq) 3501a6c311SAlfredo Cardigliano { 3601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 3701a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 3801a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 3901a6c311SAlfredo Cardigliano .pending_work = true, 4001a6c311SAlfredo Cardigliano .cmd.q_control = { 4101a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 4201a6c311SAlfredo Cardigliano .type = q->type, 4309f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 4401a6c311SAlfredo Cardigliano .oper = IONIC_Q_ENABLE, 4501a6c311SAlfredo Cardigliano }, 4601a6c311SAlfredo Cardigliano }; 4701a6c311SAlfredo Cardigliano 4801a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 4901a6c311SAlfredo Cardigliano } 5001a6c311SAlfredo Cardigliano 5101a6c311SAlfredo Cardigliano int 5201a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 5301a6c311SAlfredo Cardigliano { 5401a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 5501a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 5601a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 5701a6c311SAlfredo Cardigliano .pending_work = true, 5801a6c311SAlfredo Cardigliano .cmd.q_control = { 5901a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 6001a6c311SAlfredo Cardigliano .type = q->type, 6109f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 6201a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 6301a6c311SAlfredo Cardigliano }, 6401a6c311SAlfredo Cardigliano }; 6501a6c311SAlfredo Cardigliano 6601a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 6701a6c311SAlfredo Cardigliano } 6801a6c311SAlfredo Cardigliano 69be63459eSAndrew Boyer void 70be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif) 71598f6726SAlfredo Cardigliano { 72a0a99f21SAndrew Boyer uint32_t i; 73a0a99f21SAndrew Boyer 74be63459eSAndrew Boyer IONIC_PRINT_CALL(); 75598f6726SAlfredo Cardigliano 76be63459eSAndrew Boyer lif->state &= ~IONIC_LIF_F_UP; 77a0a99f21SAndrew Boyer 78a0a99f21SAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 79a0a99f21SAndrew Boyer struct ionic_qcq *rxq = lif->rxqcqs[i]; 80a0a99f21SAndrew Boyer if (rxq->flags & IONIC_QCQ_F_INITED) 81a0a99f21SAndrew Boyer (void)ionic_dev_rx_queue_stop(lif->eth_dev, i); 82a0a99f21SAndrew Boyer } 83a0a99f21SAndrew Boyer 84a0a99f21SAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 85a0a99f21SAndrew Boyer struct ionic_qcq *txq = lif->txqcqs[i]; 86a0a99f21SAndrew Boyer if (txq->flags & IONIC_QCQ_F_INITED) 87a0a99f21SAndrew Boyer (void)ionic_dev_tx_queue_stop(lif->eth_dev, i); 88a0a99f21SAndrew Boyer } 89598f6726SAlfredo Cardigliano } 90598f6726SAlfredo Cardigliano 91598f6726SAlfredo Cardigliano void 92598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 93598f6726SAlfredo Cardigliano { 94598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 9575f96902SAndrew Boyer int err; 96598f6726SAlfredo Cardigliano 97598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 98598f6726SAlfredo Cardigliano 9900b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 10075f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 10175f96902SAndrew Boyer if (err) 1024ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 103598f6726SAlfredo Cardigliano } 104598f6726SAlfredo Cardigliano 1053cdfd905SAlfredo Cardigliano static void 1063cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 1073cdfd905SAlfredo Cardigliano { 1083cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 1093cdfd905SAlfredo Cardigliano uint32_t i; 1103cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 1113cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1123cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 1133cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1143cdfd905SAlfredo Cardigliano 1153cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 1163cdfd905SAlfredo Cardigliano 1173cdfd905SAlfredo Cardigliano if (ls == NULL) { 1183cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1193cdfd905SAlfredo Cardigliano lif->port_id); 1203cdfd905SAlfredo Cardigliano return; 1213cdfd905SAlfredo Cardigliano } 1223cdfd905SAlfredo Cardigliano 1233cdfd905SAlfredo Cardigliano /* RX */ 1243cdfd905SAlfredo Cardigliano 1253cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1263cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1273cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1283cdfd905SAlfredo Cardigliano 1293cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1303cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1313cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1323cdfd905SAlfredo Cardigliano 1333cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1343cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1353cdfd905SAlfredo Cardigliano stats->imissed += 1363cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1373cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1383cdfd905SAlfredo Cardigliano rx_stats->no_room + 1393cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1403cdfd905SAlfredo Cardigliano } 1413cdfd905SAlfredo Cardigliano 1423cdfd905SAlfredo Cardigliano stats->imissed += 1433cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1443cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1453cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1463cdfd905SAlfredo Cardigliano 1473cdfd905SAlfredo Cardigliano stats->imissed += 1483cdfd905SAlfredo Cardigliano ls->rx_queue_empty + 1493cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1503cdfd905SAlfredo Cardigliano ls->rx_queue_disabled + 1513cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1523cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1533cdfd905SAlfredo Cardigliano 1543cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 1553cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1563cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1573cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1583cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1593cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1603cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1613cdfd905SAlfredo Cardigliano rx_stats->no_room + 1623cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1633cdfd905SAlfredo Cardigliano } 1643cdfd905SAlfredo Cardigliano 1653cdfd905SAlfredo Cardigliano /* TX */ 1663cdfd905SAlfredo Cardigliano 1673cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1683cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1693cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1703cdfd905SAlfredo Cardigliano 1713cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1723cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1733cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1743cdfd905SAlfredo Cardigliano 1753cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1763cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1773cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1783cdfd905SAlfredo Cardigliano } 1793cdfd905SAlfredo Cardigliano 1803cdfd905SAlfredo Cardigliano stats->oerrors += 1813cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1823cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1833cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1843cdfd905SAlfredo Cardigliano 1853cdfd905SAlfredo Cardigliano stats->oerrors += 1863cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1873cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1883cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1893cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1903cdfd905SAlfredo Cardigliano 1913cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 1923cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1933cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1943cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1953cdfd905SAlfredo Cardigliano } 1963cdfd905SAlfredo Cardigliano } 1973cdfd905SAlfredo Cardigliano 1983cdfd905SAlfredo Cardigliano void 1993cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 2003cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 2013cdfd905SAlfredo Cardigliano { 2023cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 2033cdfd905SAlfredo Cardigliano 2043cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 2053cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 2063cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 2073cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 2083cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 2093cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 2103cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 2113cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 2123cdfd905SAlfredo Cardigliano } 2133cdfd905SAlfredo Cardigliano 2143cdfd905SAlfredo Cardigliano void 2153cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 2163cdfd905SAlfredo Cardigliano { 2173cdfd905SAlfredo Cardigliano uint32_t i; 2183cdfd905SAlfredo Cardigliano 2193cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 2203cdfd905SAlfredo Cardigliano memset(&lif->rxqcqs[i]->stats.rx, 0, 2213cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 2223cdfd905SAlfredo Cardigliano memset(&lif->txqcqs[i]->stats.tx, 0, 2233cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2243cdfd905SAlfredo Cardigliano } 2253cdfd905SAlfredo Cardigliano 2263cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2273cdfd905SAlfredo Cardigliano } 2283cdfd905SAlfredo Cardigliano 2293cdfd905SAlfredo Cardigliano void 2303cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2313cdfd905SAlfredo Cardigliano { 2323cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2333cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2343cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2353cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2363cdfd905SAlfredo Cardigliano 2373cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2383cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2393cdfd905SAlfredo Cardigliano } 2403cdfd905SAlfredo Cardigliano 2413cdfd905SAlfredo Cardigliano void 2423cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2433cdfd905SAlfredo Cardigliano { 2443cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2453cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2463cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2473cdfd905SAlfredo Cardigliano 2483cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2493cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2503cdfd905SAlfredo Cardigliano } 2513cdfd905SAlfredo Cardigliano 252598f6726SAlfredo Cardigliano static int 25354fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 254598f6726SAlfredo Cardigliano { 25554fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 25654fe083fSAlfredo Cardigliano .pending_work = true, 25754fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 25854fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 25909f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC), 26054fe083fSAlfredo Cardigliano }, 26154fe083fSAlfredo Cardigliano }; 26254fe083fSAlfredo Cardigliano int err; 26354fe083fSAlfredo Cardigliano 26454fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 26554fe083fSAlfredo Cardigliano 26654fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 26754fe083fSAlfredo Cardigliano if (err) 26854fe083fSAlfredo Cardigliano return err; 26954fe083fSAlfredo Cardigliano 27054fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 27109f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 27254fe083fSAlfredo Cardigliano 27354fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 27454fe083fSAlfredo Cardigliano } 27554fe083fSAlfredo Cardigliano 27654fe083fSAlfredo Cardigliano static int 27754fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 27854fe083fSAlfredo Cardigliano { 27954fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 28054fe083fSAlfredo Cardigliano .pending_work = true, 28154fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 28254fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 28354fe083fSAlfredo Cardigliano }, 28454fe083fSAlfredo Cardigliano }; 28554fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 28654fe083fSAlfredo Cardigliano int err; 28754fe083fSAlfredo Cardigliano 28854fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 28954fe083fSAlfredo Cardigliano 29054fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 29154fe083fSAlfredo Cardigliano 29254fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 29354fe083fSAlfredo Cardigliano if (!f) { 29454fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 29554fe083fSAlfredo Cardigliano return -ENOENT; 29654fe083fSAlfredo Cardigliano } 29754fe083fSAlfredo Cardigliano 29809f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 29954fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 30054fe083fSAlfredo Cardigliano 30154fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 30254fe083fSAlfredo Cardigliano 30354fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 30454fe083fSAlfredo Cardigliano if (err) 30554fe083fSAlfredo Cardigliano return err; 30654fe083fSAlfredo Cardigliano 30754fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 30809f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 309598f6726SAlfredo Cardigliano 310598f6726SAlfredo Cardigliano return 0; 311598f6726SAlfredo Cardigliano } 312598f6726SAlfredo Cardigliano 31354fe083fSAlfredo Cardigliano int 31454fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 31554fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 31654fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 317598f6726SAlfredo Cardigliano { 31854fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 31954fe083fSAlfredo Cardigliano 32054fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 32154fe083fSAlfredo Cardigliano 32254fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 32354fe083fSAlfredo Cardigliano } 32454fe083fSAlfredo Cardigliano 32554fe083fSAlfredo Cardigliano void 32675f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 32754fe083fSAlfredo Cardigliano { 32854fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 32954fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 33075f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 33154fe083fSAlfredo Cardigliano 33254fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 33354fe083fSAlfredo Cardigliano 33454fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 33554fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 33654fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 33754fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 33854fe083fSAlfredo Cardigliano return; 33954fe083fSAlfredo Cardigliano } 34054fe083fSAlfredo Cardigliano 34175f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 34275f96902SAndrew Boyer 34375f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 34454fe083fSAlfredo Cardigliano return; 34554fe083fSAlfredo Cardigliano 34675f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 34754fe083fSAlfredo Cardigliano } 34854fe083fSAlfredo Cardigliano 34954fe083fSAlfredo Cardigliano int 35054fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 35154fe083fSAlfredo Cardigliano { 35254fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 35354fe083fSAlfredo Cardigliano 35454fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 35554fe083fSAlfredo Cardigliano 35654fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 35754fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 35854fe083fSAlfredo Cardigliano return -1; 35954fe083fSAlfredo Cardigliano } 36054fe083fSAlfredo Cardigliano 36154fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 36254fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 36354fe083fSAlfredo Cardigliano lif->mac_addr); 36454fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 36554fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 36654fe083fSAlfredo Cardigliano } 36754fe083fSAlfredo Cardigliano 36854fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 36954fe083fSAlfredo Cardigliano 37054fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 37154fe083fSAlfredo Cardigliano 37254fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 37354fe083fSAlfredo Cardigliano } 37454fe083fSAlfredo Cardigliano 37554fe083fSAlfredo Cardigliano static int 37654fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 37754fe083fSAlfredo Cardigliano { 37854fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 37954fe083fSAlfredo Cardigliano .pending_work = true, 38054fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 38154fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 38209f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN), 38309f806e9SAndrew Boyer .vlan.vlan = rte_cpu_to_le_16(vid), 38454fe083fSAlfredo Cardigliano }, 38554fe083fSAlfredo Cardigliano }; 38654fe083fSAlfredo Cardigliano int err; 38754fe083fSAlfredo Cardigliano 38854fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 38954fe083fSAlfredo Cardigliano if (err) 39054fe083fSAlfredo Cardigliano return err; 39154fe083fSAlfredo Cardigliano 39254fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 39309f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 39454fe083fSAlfredo Cardigliano 39554fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 39654fe083fSAlfredo Cardigliano } 39754fe083fSAlfredo Cardigliano 39854fe083fSAlfredo Cardigliano static int 39954fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 40054fe083fSAlfredo Cardigliano { 40154fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 40254fe083fSAlfredo Cardigliano .pending_work = true, 40354fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 40454fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 40554fe083fSAlfredo Cardigliano }, 40654fe083fSAlfredo Cardigliano }; 40754fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 40854fe083fSAlfredo Cardigliano int err; 40954fe083fSAlfredo Cardigliano 41054fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 41154fe083fSAlfredo Cardigliano 41254fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 41354fe083fSAlfredo Cardigliano 41454fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 41554fe083fSAlfredo Cardigliano if (!f) { 41654fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 41754fe083fSAlfredo Cardigliano return -ENOENT; 41854fe083fSAlfredo Cardigliano } 41954fe083fSAlfredo Cardigliano 42009f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 42154fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 42254fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 42354fe083fSAlfredo Cardigliano 42454fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 42554fe083fSAlfredo Cardigliano if (err) 42654fe083fSAlfredo Cardigliano return err; 42754fe083fSAlfredo Cardigliano 42854fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 42909f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 430598f6726SAlfredo Cardigliano 431598f6726SAlfredo Cardigliano return 0; 432598f6726SAlfredo Cardigliano } 433598f6726SAlfredo Cardigliano 43454fe083fSAlfredo Cardigliano int 43554fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 43654fe083fSAlfredo Cardigliano int on) 43754fe083fSAlfredo Cardigliano { 43854fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 43954fe083fSAlfredo Cardigliano int err; 44054fe083fSAlfredo Cardigliano 44154fe083fSAlfredo Cardigliano if (on) 44254fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 44354fe083fSAlfredo Cardigliano else 44454fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 44554fe083fSAlfredo Cardigliano 44654fe083fSAlfredo Cardigliano return err; 44754fe083fSAlfredo Cardigliano } 44854fe083fSAlfredo Cardigliano 449598f6726SAlfredo Cardigliano static void 450598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 451598f6726SAlfredo Cardigliano { 452598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 453598f6726SAlfredo Cardigliano .pending_work = true, 454598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 455598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 45609f806e9SAndrew Boyer .rx_mode = rte_cpu_to_le_16(rx_mode), 457598f6726SAlfredo Cardigliano }, 458598f6726SAlfredo Cardigliano }; 459598f6726SAlfredo Cardigliano int err; 460598f6726SAlfredo Cardigliano 461598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 462598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 463598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 464598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 465598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 466598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 467598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 468598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 469598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 470598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 471598f6726SAlfredo Cardigliano 472598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 473598f6726SAlfredo Cardigliano if (err) 474598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 475598f6726SAlfredo Cardigliano } 476598f6726SAlfredo Cardigliano 477598f6726SAlfredo Cardigliano static void 478598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 479598f6726SAlfredo Cardigliano { 480598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 481598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 482598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 483598f6726SAlfredo Cardigliano } 484598f6726SAlfredo Cardigliano } 485598f6726SAlfredo Cardigliano 48654fe083fSAlfredo Cardigliano int 48754fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 48854fe083fSAlfredo Cardigliano { 48954fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 49054fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 49154fe083fSAlfredo Cardigliano 49254fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 49354fe083fSAlfredo Cardigliano 49454fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 49554fe083fSAlfredo Cardigliano 49654fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 49754fe083fSAlfredo Cardigliano 49854fe083fSAlfredo Cardigliano return 0; 49954fe083fSAlfredo Cardigliano } 50054fe083fSAlfredo Cardigliano 50154fe083fSAlfredo Cardigliano int 50254fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 50354fe083fSAlfredo Cardigliano { 50454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50554fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 50654fe083fSAlfredo Cardigliano 50754fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 50854fe083fSAlfredo Cardigliano 50954fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 51054fe083fSAlfredo Cardigliano 51154fe083fSAlfredo Cardigliano return 0; 51254fe083fSAlfredo Cardigliano } 51354fe083fSAlfredo Cardigliano 51454fe083fSAlfredo Cardigliano int 51554fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 51654fe083fSAlfredo Cardigliano { 51754fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 51854fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 51954fe083fSAlfredo Cardigliano 52054fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 52154fe083fSAlfredo Cardigliano 52254fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 52354fe083fSAlfredo Cardigliano 52454fe083fSAlfredo Cardigliano return 0; 52554fe083fSAlfredo Cardigliano } 52654fe083fSAlfredo Cardigliano 52754fe083fSAlfredo Cardigliano int 52854fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 52954fe083fSAlfredo Cardigliano { 53054fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 53154fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 53254fe083fSAlfredo Cardigliano 53354fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 53454fe083fSAlfredo Cardigliano 53554fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 53654fe083fSAlfredo Cardigliano 53754fe083fSAlfredo Cardigliano return 0; 53854fe083fSAlfredo Cardigliano } 539598f6726SAlfredo Cardigliano 540598f6726SAlfredo Cardigliano int 541598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu) 542598f6726SAlfredo Cardigliano { 543598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 544598f6726SAlfredo Cardigliano .pending_work = true, 545598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 546598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 547598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 54809f806e9SAndrew Boyer .mtu = rte_cpu_to_le_32(new_mtu), 549598f6726SAlfredo Cardigliano }, 550598f6726SAlfredo Cardigliano }; 551598f6726SAlfredo Cardigliano int err; 552598f6726SAlfredo Cardigliano 553598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 554598f6726SAlfredo Cardigliano if (err) 555598f6726SAlfredo Cardigliano return err; 556598f6726SAlfredo Cardigliano 557598f6726SAlfredo Cardigliano return 0; 558598f6726SAlfredo Cardigliano } 559598f6726SAlfredo Cardigliano 560598f6726SAlfredo Cardigliano int 56101a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 56201a6c311SAlfredo Cardigliano { 56301a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 56401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 56501a6c311SAlfredo Cardigliano unsigned long index; 56601a6c311SAlfredo Cardigliano 56701a6c311SAlfredo Cardigliano /* 56801a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 56901a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5704ae96cb8SAndrew Boyer * which has index = 0) 57101a6c311SAlfredo Cardigliano */ 57201a6c311SAlfredo Cardigliano 57301a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 57401a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 57501a6c311SAlfredo Cardigliano break; 57601a6c311SAlfredo Cardigliano 57701a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 57801a6c311SAlfredo Cardigliano return -ENOSPC; 57901a6c311SAlfredo Cardigliano 58001a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 58101a6c311SAlfredo Cardigliano 58201a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 58301a6c311SAlfredo Cardigliano 58401a6c311SAlfredo Cardigliano return 0; 58501a6c311SAlfredo Cardigliano } 58601a6c311SAlfredo Cardigliano 58701a6c311SAlfredo Cardigliano void 58801a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr) 58901a6c311SAlfredo Cardigliano { 5904c8f8d57SAndrew Boyer if (intr->index != IONIC_INTR_NONE) 59101a6c311SAlfredo Cardigliano lif->adapter->intrs[intr->index] = false; 59201a6c311SAlfredo Cardigliano } 59301a6c311SAlfredo Cardigliano 59401a6c311SAlfredo Cardigliano static int 59501a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type, 59601a6c311SAlfredo Cardigliano uint32_t index, 59701a6c311SAlfredo Cardigliano const char *base, uint32_t flags, 59801a6c311SAlfredo Cardigliano uint32_t num_descs, 59901a6c311SAlfredo Cardigliano uint32_t desc_size, 60001a6c311SAlfredo Cardigliano uint32_t cq_desc_size, 60101a6c311SAlfredo Cardigliano uint32_t sg_desc_size, 6021abf69fcSAndrew Boyer struct ionic_qcq **qcq) 60301a6c311SAlfredo Cardigliano { 60401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 60501a6c311SAlfredo Cardigliano struct ionic_qcq *new; 60601a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 60701a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 60801a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 60901a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 61001a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 61101a6c311SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 61201a6c311SAlfredo Cardigliano int err; 61301a6c311SAlfredo Cardigliano 61401a6c311SAlfredo Cardigliano *qcq = NULL; 61501a6c311SAlfredo Cardigliano 61601a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 61701a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 61801a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 61901a6c311SAlfredo Cardigliano 62001a6c311SAlfredo Cardigliano total_size = RTE_ALIGN(q_size, PAGE_SIZE) + 62101a6c311SAlfredo Cardigliano RTE_ALIGN(cq_size, PAGE_SIZE); 62201a6c311SAlfredo Cardigliano /* 62301a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 62401a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 62501a6c311SAlfredo Cardigliano * Adding PAGE_SIZE. 62601a6c311SAlfredo Cardigliano */ 62701a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 62801a6c311SAlfredo Cardigliano 62901a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 63001a6c311SAlfredo Cardigliano total_size += RTE_ALIGN(sg_size, PAGE_SIZE); 63101a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 63201a6c311SAlfredo Cardigliano } 63301a6c311SAlfredo Cardigliano 63401a6c311SAlfredo Cardigliano new = rte_zmalloc("ionic", sizeof(*new), 0); 63501a6c311SAlfredo Cardigliano if (!new) { 63601a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 63701a6c311SAlfredo Cardigliano return -ENOMEM; 63801a6c311SAlfredo Cardigliano } 63901a6c311SAlfredo Cardigliano 64001a6c311SAlfredo Cardigliano new->lif = lif; 64101a6c311SAlfredo Cardigliano new->flags = flags; 64201a6c311SAlfredo Cardigliano 64301a6c311SAlfredo Cardigliano new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0); 64401a6c311SAlfredo Cardigliano if (!new->q.info) { 64501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 6464c8f8d57SAndrew Boyer err = -ENOMEM; 6474c8f8d57SAndrew Boyer goto err_out_free_qcq; 64801a6c311SAlfredo Cardigliano } 64901a6c311SAlfredo Cardigliano 65001a6c311SAlfredo Cardigliano new->q.type = type; 65101a6c311SAlfredo Cardigliano 65201a6c311SAlfredo Cardigliano err = ionic_q_init(lif, idev, &new->q, index, num_descs, 6531abf69fcSAndrew Boyer desc_size, sg_desc_size); 65401a6c311SAlfredo Cardigliano if (err) { 65501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 6564c8f8d57SAndrew Boyer goto err_out_free_info; 65701a6c311SAlfredo Cardigliano } 65801a6c311SAlfredo Cardigliano 659*2aed9865SAndrew Boyer err = ionic_cq_init(&new->cq, num_descs); 66001a6c311SAlfredo Cardigliano if (err) { 66101a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 6624c8f8d57SAndrew Boyer goto err_out_free_info; 66301a6c311SAlfredo Cardigliano } 66401a6c311SAlfredo Cardigliano 66501a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 66601a6c311SAlfredo Cardigliano base /* name */, index /* queue_idx */, 66701a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 66801a6c311SAlfredo Cardigliano 66901a6c311SAlfredo Cardigliano if (!new->base_z) { 67001a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 67101a6c311SAlfredo Cardigliano err = -ENOMEM; 6724c8f8d57SAndrew Boyer goto err_out_free_info; 67301a6c311SAlfredo Cardigliano } 67401a6c311SAlfredo Cardigliano 67501a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 67601a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 67701a6c311SAlfredo Cardigliano new->total_size = total_size; 67801a6c311SAlfredo Cardigliano 67901a6c311SAlfredo Cardigliano q_base = new->base; 68001a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 68101a6c311SAlfredo Cardigliano 68201a6c311SAlfredo Cardigliano cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE); 68301a6c311SAlfredo Cardigliano cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE); 68401a6c311SAlfredo Cardigliano 68501a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 68601a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 68701a6c311SAlfredo Cardigliano PAGE_SIZE); 68801a6c311SAlfredo Cardigliano sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE); 68901a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 69001a6c311SAlfredo Cardigliano } 69101a6c311SAlfredo Cardigliano 6924ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6934ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 69401a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 69501a6c311SAlfredo Cardigliano 69601a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 69701a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 69801a6c311SAlfredo Cardigliano ionic_cq_bind(&new->cq, &new->q); 69901a6c311SAlfredo Cardigliano 70001a6c311SAlfredo Cardigliano *qcq = new; 70101a6c311SAlfredo Cardigliano 70201a6c311SAlfredo Cardigliano return 0; 70301a6c311SAlfredo Cardigliano 7044c8f8d57SAndrew Boyer err_out_free_info: 7054c8f8d57SAndrew Boyer rte_free(new->q.info); 7064c8f8d57SAndrew Boyer err_out_free_qcq: 7074c8f8d57SAndrew Boyer rte_free(new); 70801a6c311SAlfredo Cardigliano 70901a6c311SAlfredo Cardigliano return err; 71001a6c311SAlfredo Cardigliano } 71101a6c311SAlfredo Cardigliano 71201a6c311SAlfredo Cardigliano void 71301a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 71401a6c311SAlfredo Cardigliano { 71501a6c311SAlfredo Cardigliano if (qcq->base_z) { 71601a6c311SAlfredo Cardigliano qcq->base = NULL; 71701a6c311SAlfredo Cardigliano qcq->base_pa = 0; 71801a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 71901a6c311SAlfredo Cardigliano qcq->base_z = NULL; 72001a6c311SAlfredo Cardigliano } 72101a6c311SAlfredo Cardigliano 72201a6c311SAlfredo Cardigliano if (qcq->q.info) { 72301a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 72401a6c311SAlfredo Cardigliano qcq->q.info = NULL; 72501a6c311SAlfredo Cardigliano } 72601a6c311SAlfredo Cardigliano 72701a6c311SAlfredo Cardigliano rte_free(qcq); 72801a6c311SAlfredo Cardigliano } 72901a6c311SAlfredo Cardigliano 730a27d9013SAlfredo Cardigliano int 731a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs, 732a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 733a27d9013SAlfredo Cardigliano { 734a27d9013SAlfredo Cardigliano uint32_t flags; 735a27d9013SAlfredo Cardigliano int err = -ENOMEM; 736a27d9013SAlfredo Cardigliano 737a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 738a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags, 739a27d9013SAlfredo Cardigliano nrxq_descs, 740a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 741a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 742a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 7431abf69fcSAndrew Boyer &lif->rxqcqs[index]); 744a27d9013SAlfredo Cardigliano if (err) 745a27d9013SAlfredo Cardigliano return err; 746a27d9013SAlfredo Cardigliano 747a27d9013SAlfredo Cardigliano *qcq = lif->rxqcqs[index]; 748a27d9013SAlfredo Cardigliano 749a27d9013SAlfredo Cardigliano return 0; 750a27d9013SAlfredo Cardigliano } 751a27d9013SAlfredo Cardigliano 752a27d9013SAlfredo Cardigliano int 753a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs, 754a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 755a27d9013SAlfredo Cardigliano { 756a27d9013SAlfredo Cardigliano uint32_t flags; 757a27d9013SAlfredo Cardigliano int err = -ENOMEM; 758a27d9013SAlfredo Cardigliano 759a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 760a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags, 761a27d9013SAlfredo Cardigliano ntxq_descs, 762a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 763a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 76456117636SAndrew Boyer sizeof(struct ionic_txq_sg_desc_v1), 7651abf69fcSAndrew Boyer &lif->txqcqs[index]); 766a27d9013SAlfredo Cardigliano if (err) 767a27d9013SAlfredo Cardigliano return err; 768a27d9013SAlfredo Cardigliano 769a27d9013SAlfredo Cardigliano *qcq = lif->txqcqs[index]; 770a27d9013SAlfredo Cardigliano 771a27d9013SAlfredo Cardigliano return 0; 772a27d9013SAlfredo Cardigliano } 773a27d9013SAlfredo Cardigliano 77401a6c311SAlfredo Cardigliano static int 77501a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 77601a6c311SAlfredo Cardigliano { 77701a6c311SAlfredo Cardigliano uint32_t flags; 77801a6c311SAlfredo Cardigliano int err = -ENOMEM; 77901a6c311SAlfredo Cardigliano 78001a6c311SAlfredo Cardigliano flags = 0; 78101a6c311SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, 78201a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 78301a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 78401a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 78501a6c311SAlfredo Cardigliano 0, 7861abf69fcSAndrew Boyer &lif->adminqcq); 78727b942c8SAlfredo Cardigliano if (err) 78827b942c8SAlfredo Cardigliano return err; 78901a6c311SAlfredo Cardigliano 79027b942c8SAlfredo Cardigliano return 0; 79127b942c8SAlfredo Cardigliano } 79227b942c8SAlfredo Cardigliano 79327b942c8SAlfredo Cardigliano static int 79427b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 79527b942c8SAlfredo Cardigliano { 7964c8f8d57SAndrew Boyer struct ionic_qcq *nqcq; 7974c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 7984c8f8d57SAndrew Boyer uint32_t flags = 0; 79927b942c8SAlfredo Cardigliano int err = -ENOMEM; 80027b942c8SAlfredo Cardigliano 80127b942c8SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify", 80227b942c8SAlfredo Cardigliano flags, 80327b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 80427b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 80527b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 80627b942c8SAlfredo Cardigliano 0, 8074c8f8d57SAndrew Boyer &nqcq); 80801a6c311SAlfredo Cardigliano if (err) 80901a6c311SAlfredo Cardigliano return err; 81001a6c311SAlfredo Cardigliano 8114c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 8124c8f8d57SAndrew Boyer if (err) { 8134c8f8d57SAndrew Boyer ionic_qcq_free(nqcq); 8144c8f8d57SAndrew Boyer return err; 8154c8f8d57SAndrew Boyer } 8164c8f8d57SAndrew Boyer 8174c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 8184c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 8194c8f8d57SAndrew Boyer 8204c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 8214c8f8d57SAndrew Boyer 82201a6c311SAlfredo Cardigliano return 0; 82301a6c311SAlfredo Cardigliano } 82401a6c311SAlfredo Cardigliano 825c67719e1SAlfredo Cardigliano static void * 826c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num) 827c67719e1SAlfredo Cardigliano { 828c67719e1SAlfredo Cardigliano char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr; 829c67719e1SAlfredo Cardigliano 830c67719e1SAlfredo Cardigliano if (adapter->num_bars <= IONIC_PCI_BAR_DBELL) 831c67719e1SAlfredo Cardigliano return NULL; 832c67719e1SAlfredo Cardigliano 833c67719e1SAlfredo Cardigliano return (void *)&vaddr[page_num << PAGE_SHIFT]; 834c67719e1SAlfredo Cardigliano } 835c67719e1SAlfredo Cardigliano 836c5d15850SAndrew Boyer static void 837c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif) 838c5d15850SAndrew Boyer { 839c5d15850SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 840c5d15850SAndrew Boyer struct ionic_dev *idev = &adapter->idev; 841c5d15850SAndrew Boyer union ionic_q_identity *q_ident = &adapter->ident.txq; 842c5d15850SAndrew Boyer uint32_t q_words = RTE_DIM(q_ident->words); 843c5d15850SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 844c5d15850SAndrew Boyer uint32_t i, nwords, qtype; 845c5d15850SAndrew Boyer int err; 846c5d15850SAndrew Boyer 847c5d15850SAndrew Boyer for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) { 848c5d15850SAndrew Boyer struct ionic_qtype_info *qti = &lif->qtype_info[qtype]; 849c5d15850SAndrew Boyer 850c5d15850SAndrew Boyer /* Filter out the types this driver knows about */ 851c5d15850SAndrew Boyer switch (qtype) { 852c5d15850SAndrew Boyer case IONIC_QTYPE_ADMINQ: 853c5d15850SAndrew Boyer case IONIC_QTYPE_NOTIFYQ: 854c5d15850SAndrew Boyer case IONIC_QTYPE_RXQ: 855c5d15850SAndrew Boyer case IONIC_QTYPE_TXQ: 856c5d15850SAndrew Boyer break; 857c5d15850SAndrew Boyer default: 858c5d15850SAndrew Boyer continue; 859c5d15850SAndrew Boyer } 860c5d15850SAndrew Boyer 861c5d15850SAndrew Boyer memset(qti, 0, sizeof(*qti)); 862c5d15850SAndrew Boyer 863c5d15850SAndrew Boyer ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC, 864c5d15850SAndrew Boyer qtype, ionic_qtype_vers[qtype]); 865c5d15850SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 866c5d15850SAndrew Boyer if (err == -EINVAL) { 867c5d15850SAndrew Boyer IONIC_PRINT(ERR, "qtype %d not supported\n", qtype); 868c5d15850SAndrew Boyer continue; 869c5d15850SAndrew Boyer } else if (err == -EIO) { 870c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, older FW\n"); 871c5d15850SAndrew Boyer return; 872c5d15850SAndrew Boyer } else if (err) { 873c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n", 874c5d15850SAndrew Boyer qtype, err); 875c5d15850SAndrew Boyer return; 876c5d15850SAndrew Boyer } 877c5d15850SAndrew Boyer 878c5d15850SAndrew Boyer nwords = RTE_MIN(q_words, cmd_words); 879c5d15850SAndrew Boyer for (i = 0; i < nwords; i++) 880c5d15850SAndrew Boyer q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]); 881c5d15850SAndrew Boyer 882c5d15850SAndrew Boyer qti->version = q_ident->version; 883c5d15850SAndrew Boyer qti->supported = q_ident->supported; 884c5d15850SAndrew Boyer qti->features = rte_le_to_cpu_64(q_ident->features); 885c5d15850SAndrew Boyer qti->desc_sz = rte_le_to_cpu_16(q_ident->desc_sz); 886c5d15850SAndrew Boyer qti->comp_sz = rte_le_to_cpu_16(q_ident->comp_sz); 887c5d15850SAndrew Boyer qti->sg_desc_sz = rte_le_to_cpu_16(q_ident->sg_desc_sz); 888c5d15850SAndrew Boyer qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems); 889c5d15850SAndrew Boyer qti->sg_desc_stride = 890c5d15850SAndrew Boyer rte_le_to_cpu_16(q_ident->sg_desc_stride); 891c5d15850SAndrew Boyer 892c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].version = %d", 893c5d15850SAndrew Boyer qtype, qti->version); 894c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x", 895c5d15850SAndrew Boyer qtype, qti->supported); 896c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx", 897c5d15850SAndrew Boyer qtype, qti->features); 898c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d", 899c5d15850SAndrew Boyer qtype, qti->desc_sz); 900c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d", 901c5d15850SAndrew Boyer qtype, qti->comp_sz); 902c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d", 903c5d15850SAndrew Boyer qtype, qti->sg_desc_sz); 904c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d", 905c5d15850SAndrew Boyer qtype, qti->max_sg_elems); 906c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d", 907c5d15850SAndrew Boyer qtype, qti->sg_desc_stride); 908c5d15850SAndrew Boyer } 909c5d15850SAndrew Boyer } 910c5d15850SAndrew Boyer 911669c8de6SAlfredo Cardigliano int 912669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 913669c8de6SAlfredo Cardigliano { 914c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 915669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 91601a6c311SAlfredo Cardigliano int err; 917669c8de6SAlfredo Cardigliano 9184ae96cb8SAndrew Boyer /* 9194ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 9204ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 9214ae96cb8SAndrew Boyer */ 9224ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 9234ae96cb8SAndrew Boyer 9244ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 925669c8de6SAlfredo Cardigliano 926c5d15850SAndrew Boyer ionic_lif_queue_identify(lif); 927c5d15850SAndrew Boyer 92856117636SAndrew Boyer if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) { 92956117636SAndrew Boyer IONIC_PRINT(ERR, "FW too old, please upgrade"); 93056117636SAndrew Boyer return -ENXIO; 93156117636SAndrew Boyer } 93256117636SAndrew Boyer 933669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 934669c8de6SAlfredo Cardigliano 93501a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 93601a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 93701a6c311SAlfredo Cardigliano 93800b65da5SAndrew Boyer lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0); 939c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 940c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 941c67719e1SAlfredo Cardigliano return -ENOMEM; 942c67719e1SAlfredo Cardigliano } 943c67719e1SAlfredo Cardigliano 944a27d9013SAlfredo Cardigliano lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) * 945a27d9013SAlfredo Cardigliano adapter->max_ntxqs_per_lif, 0); 946a27d9013SAlfredo Cardigliano 947a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 948a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 949a27d9013SAlfredo Cardigliano return -ENOMEM; 950a27d9013SAlfredo Cardigliano } 951a27d9013SAlfredo Cardigliano 952a27d9013SAlfredo Cardigliano lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) * 953a27d9013SAlfredo Cardigliano adapter->max_nrxqs_per_lif, 0); 954a27d9013SAlfredo Cardigliano 955a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 956a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 957a27d9013SAlfredo Cardigliano return -ENOMEM; 958a27d9013SAlfredo Cardigliano } 959a27d9013SAlfredo Cardigliano 96027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 96127b942c8SAlfredo Cardigliano 96227b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 96327b942c8SAlfredo Cardigliano if (err) { 96427b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 96527b942c8SAlfredo Cardigliano return err; 96627b942c8SAlfredo Cardigliano } 96727b942c8SAlfredo Cardigliano 96827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 96927b942c8SAlfredo Cardigliano 97001a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 97101a6c311SAlfredo Cardigliano if (err) { 97201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 97301a6c311SAlfredo Cardigliano return err; 97401a6c311SAlfredo Cardigliano } 97501a6c311SAlfredo Cardigliano 97601a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 97701a6c311SAlfredo Cardigliano 978669c8de6SAlfredo Cardigliano lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); 979669c8de6SAlfredo Cardigliano 980669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 981669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 982669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 983669c8de6SAlfredo Cardigliano if (!lif->info_z) { 984669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 985669c8de6SAlfredo Cardigliano return -ENOMEM; 986669c8de6SAlfredo Cardigliano } 987669c8de6SAlfredo Cardigliano 988669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 989669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 990669c8de6SAlfredo Cardigliano 991669c8de6SAlfredo Cardigliano return 0; 992669c8de6SAlfredo Cardigliano } 993669c8de6SAlfredo Cardigliano 994669c8de6SAlfredo Cardigliano void 995669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 996669c8de6SAlfredo Cardigliano { 99727b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 99827b942c8SAlfredo Cardigliano ionic_qcq_free(lif->notifyqcq); 99927b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 100027b942c8SAlfredo Cardigliano } 100127b942c8SAlfredo Cardigliano 100201a6c311SAlfredo Cardigliano if (lif->adminqcq) { 100301a6c311SAlfredo Cardigliano ionic_qcq_free(lif->adminqcq); 100401a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 100501a6c311SAlfredo Cardigliano } 100601a6c311SAlfredo Cardigliano 1007a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 1008a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 1009a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 1010a27d9013SAlfredo Cardigliano } 1011a27d9013SAlfredo Cardigliano 1012a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 1013a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 1014a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 1015a27d9013SAlfredo Cardigliano } 1016a27d9013SAlfredo Cardigliano 1017669c8de6SAlfredo Cardigliano if (lif->info) { 1018669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 1019669c8de6SAlfredo Cardigliano lif->info = NULL; 1020669c8de6SAlfredo Cardigliano } 1021669c8de6SAlfredo Cardigliano } 1022669c8de6SAlfredo Cardigliano 1023175e4e7eSAndrew Boyer void 1024175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 1025175e4e7eSAndrew Boyer { 1026175e4e7eSAndrew Boyer uint32_t i; 1027175e4e7eSAndrew Boyer 1028175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 1029175e4e7eSAndrew Boyer ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]); 1030175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 1031175e4e7eSAndrew Boyer } 1032175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 1033175e4e7eSAndrew Boyer ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]); 1034175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 1035175e4e7eSAndrew Boyer } 1036175e4e7eSAndrew Boyer } 1037175e4e7eSAndrew Boyer 103822e7171bSAlfredo Cardigliano int 103922e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 104022e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 104122e7171bSAlfredo Cardigliano { 104209f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 104322e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 104422e7171bSAlfredo Cardigliano .pending_work = true, 104522e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 104622e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 104722e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 104809f806e9SAndrew Boyer .rss.types = rte_cpu_to_le_16(types), 104909f806e9SAndrew Boyer .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa), 105022e7171bSAlfredo Cardigliano }, 105122e7171bSAlfredo Cardigliano }; 105222e7171bSAlfredo Cardigliano unsigned int i; 105309f806e9SAndrew Boyer uint16_t tbl_sz = 105409f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 105522e7171bSAlfredo Cardigliano 105622e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 105722e7171bSAlfredo Cardigliano 105822e7171bSAlfredo Cardigliano lif->rss_types = types; 105922e7171bSAlfredo Cardigliano 106022e7171bSAlfredo Cardigliano if (key) 106122e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 106222e7171bSAlfredo Cardigliano 106322e7171bSAlfredo Cardigliano if (indir) 106409f806e9SAndrew Boyer for (i = 0; i < tbl_sz; i++) 106522e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 106622e7171bSAlfredo Cardigliano 106722e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 106822e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 106922e7171bSAlfredo Cardigliano 107022e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 107122e7171bSAlfredo Cardigliano } 107222e7171bSAlfredo Cardigliano 107322e7171bSAlfredo Cardigliano static int 107422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 107522e7171bSAlfredo Cardigliano { 107609f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 107722e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 107822e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 107922e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 108022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 108122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 108222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 108322e7171bSAlfredo Cardigliano }; 108422e7171bSAlfredo Cardigliano uint32_t i; 108509f806e9SAndrew Boyer uint16_t tbl_sz = 108609f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 108722e7171bSAlfredo Cardigliano 108822e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 108922e7171bSAlfredo Cardigliano 10903d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 109122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 10923d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 10933d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 10943d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 109522e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 109622e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 109722e7171bSAlfredo Cardigliano return -ENOMEM; 109822e7171bSAlfredo Cardigliano } 109922e7171bSAlfredo Cardigliano 110022e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 110122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 11023d845eddSAndrew Boyer } 11033d845eddSAndrew Boyer 11043d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 11053d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 110622e7171bSAlfredo Cardigliano 110722e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 11083d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 110922e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 11103d845eddSAndrew Boyer } 111122e7171bSAlfredo Cardigliano 11123d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 111322e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 111422e7171bSAlfredo Cardigliano } 111522e7171bSAlfredo Cardigliano 111622e7171bSAlfredo Cardigliano static void 111722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 111822e7171bSAlfredo Cardigliano { 111922e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 112022e7171bSAlfredo Cardigliano return; 112122e7171bSAlfredo Cardigliano 112222e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 112322e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 112422e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 112522e7171bSAlfredo Cardigliano 112622e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 112722e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 112822e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 112922e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 113022e7171bSAlfredo Cardigliano } 113122e7171bSAlfredo Cardigliano } 113222e7171bSAlfredo Cardigliano 113301a6c311SAlfredo Cardigliano static void 11344c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq) 113501a6c311SAlfredo Cardigliano { 113601a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 113701a6c311SAlfredo Cardigliano } 113801a6c311SAlfredo Cardigliano 1139a27d9013SAlfredo Cardigliano void 1140a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq) 1141a27d9013SAlfredo Cardigliano { 11424c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 1143a27d9013SAlfredo Cardigliano } 1144a27d9013SAlfredo Cardigliano 1145a27d9013SAlfredo Cardigliano void 1146a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq) 1147a27d9013SAlfredo Cardigliano { 11484c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 11494c8f8d57SAndrew Boyer } 11504c8f8d57SAndrew Boyer 11514c8f8d57SAndrew Boyer static void 11524c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 11534c8f8d57SAndrew Boyer { 11544c8f8d57SAndrew Boyer struct ionic_qcq *nqcq = lif->notifyqcq; 11554c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 11564c8f8d57SAndrew Boyer 11574c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 11584c8f8d57SAndrew Boyer return; 11594c8f8d57SAndrew Boyer 11604c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 11614c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 11624c8f8d57SAndrew Boyer 11634c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1164a27d9013SAlfredo Cardigliano } 1165a27d9013SAlfredo Cardigliano 116601a6c311SAlfredo Cardigliano bool 116701a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index, 116801a6c311SAlfredo Cardigliano void *cb_arg __rte_unused) 116901a6c311SAlfredo Cardigliano { 117001a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc_base = cq->base; 117101a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index]; 1172*2aed9865SAndrew Boyer struct ionic_qcq *qcq = IONIC_CQ_TO_QCQ(cq); 117301a6c311SAlfredo Cardigliano 117401a6c311SAlfredo Cardigliano if (!color_match(cq_desc->color, cq->done_color)) 117501a6c311SAlfredo Cardigliano return false; 117601a6c311SAlfredo Cardigliano 1177*2aed9865SAndrew Boyer ionic_q_service(&qcq->q, cq_desc_index, cq_desc->comp_index, NULL); 117801a6c311SAlfredo Cardigliano 117901a6c311SAlfredo Cardigliano return true; 118001a6c311SAlfredo Cardigliano } 118101a6c311SAlfredo Cardigliano 118201a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 118301a6c311SAlfredo Cardigliano int 118401a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 118501a6c311SAlfredo Cardigliano void *cb_arg) 118601a6c311SAlfredo Cardigliano { 118701a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 118801a6c311SAlfredo Cardigliano uint32_t work_done; 118901a6c311SAlfredo Cardigliano 119001a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 119101a6c311SAlfredo Cardigliano 119201a6c311SAlfredo Cardigliano return work_done; 119301a6c311SAlfredo Cardigliano } 119401a6c311SAlfredo Cardigliano 119527b942c8SAlfredo Cardigliano static void 119627b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 119727b942c8SAlfredo Cardigliano { 119827b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 119927b942c8SAlfredo Cardigliano bool link_up; 120027b942c8SAlfredo Cardigliano 120127b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 120227b942c8SAlfredo Cardigliano 120327b942c8SAlfredo Cardigliano if (!lif->info) 120427b942c8SAlfredo Cardigliano return; 120527b942c8SAlfredo Cardigliano 120627b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 120727b942c8SAlfredo Cardigliano 120827b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 120927b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 121027b942c8SAlfredo Cardigliano return; 121127b942c8SAlfredo Cardigliano 121227b942c8SAlfredo Cardigliano if (link_up) { 121309f806e9SAndrew Boyer adapter->link_speed = 121409f806e9SAndrew Boyer rte_le_to_cpu_32(lif->info->status.link_speed); 1215be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1216be63459eSAndrew Boyer adapter->link_speed); 121727b942c8SAlfredo Cardigliano } else { 121827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 121927b942c8SAlfredo Cardigliano } 122027b942c8SAlfredo Cardigliano 122127b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1222be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1223be63459eSAndrew Boyer } 1224be63459eSAndrew Boyer 1225be63459eSAndrew Boyer static void 1226be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1227be63459eSAndrew Boyer { 1228be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1229be63459eSAndrew Boyer return; 1230be63459eSAndrew Boyer 1231be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1232be63459eSAndrew Boyer 1233be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1234be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1235be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1236be63459eSAndrew Boyer ionic_lif_stop(lif); 1237be63459eSAndrew Boyer } 1238be63459eSAndrew Boyer 1239be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 124027b942c8SAlfredo Cardigliano } 124127b942c8SAlfredo Cardigliano 124227b942c8SAlfredo Cardigliano static bool 124327b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 124427b942c8SAlfredo Cardigliano { 124527b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 124627b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 124727b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 124827b942c8SAlfredo Cardigliano 124927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 125027b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 125127b942c8SAlfredo Cardigliano 125227b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 125327b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 125427b942c8SAlfredo Cardigliano return false; 125527b942c8SAlfredo Cardigliano 125627b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 125727b942c8SAlfredo Cardigliano 125827b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 125927b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 126027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1261be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1262be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1263be63459eSAndrew Boyer lif->name, 126427b942c8SAlfredo Cardigliano cq_desc->event.eid, 126527b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 126627b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 126727b942c8SAlfredo Cardigliano 126827b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 126927b942c8SAlfredo Cardigliano break; 1270be63459eSAndrew Boyer 1271be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1272be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1273be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1274be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1275be63459eSAndrew Boyer lif->name, 1276be63459eSAndrew Boyer cq_desc->event.eid, 1277be63459eSAndrew Boyer cq_desc->reset.reset_code, 1278be63459eSAndrew Boyer cq_desc->reset.state); 1279be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1280be63459eSAndrew Boyer break; 1281be63459eSAndrew Boyer 128227b942c8SAlfredo Cardigliano default: 128327b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 128427b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 128527b942c8SAlfredo Cardigliano break; 128627b942c8SAlfredo Cardigliano } 128727b942c8SAlfredo Cardigliano 128827b942c8SAlfredo Cardigliano return true; 128927b942c8SAlfredo Cardigliano } 129027b942c8SAlfredo Cardigliano 129127b942c8SAlfredo Cardigliano int 129227b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 129327b942c8SAlfredo Cardigliano { 129427b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 129527b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 129627b942c8SAlfredo Cardigliano uint32_t work_done; 129727b942c8SAlfredo Cardigliano 129827b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 129927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 130027b942c8SAlfredo Cardigliano return -1; 130127b942c8SAlfredo Cardigliano } 130227b942c8SAlfredo Cardigliano 130327b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 130427b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 130527b942c8SAlfredo Cardigliano 130627b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 130727b942c8SAlfredo Cardigliano 130827b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 130927b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 131027b942c8SAlfredo Cardigliano 131127b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 131227b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 131327b942c8SAlfredo Cardigliano 131427b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 131527b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 131627b942c8SAlfredo Cardigliano 131727b942c8SAlfredo Cardigliano return 0; 131827b942c8SAlfredo Cardigliano } 131927b942c8SAlfredo Cardigliano 132001a6c311SAlfredo Cardigliano static int 132101a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 132201a6c311SAlfredo Cardigliano { 132301a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 132401a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 132501a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 132601a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 132701a6c311SAlfredo Cardigliano int err; 132801a6c311SAlfredo Cardigliano 13294c8f8d57SAndrew Boyer ionic_dev_cmd_adminq_init(idev, qcq); 133001a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 133101a6c311SAlfredo Cardigliano if (err) 133201a6c311SAlfredo Cardigliano return err; 133301a6c311SAlfredo Cardigliano 133401a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 133501a6c311SAlfredo Cardigliano 133601a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 133709f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(comp.hw_index); 133801a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 133901a6c311SAlfredo Cardigliano 134001a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 134101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 134201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 134301a6c311SAlfredo Cardigliano 134401a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 134501a6c311SAlfredo Cardigliano 134601a6c311SAlfredo Cardigliano return 0; 134701a6c311SAlfredo Cardigliano } 134801a6c311SAlfredo Cardigliano 134927b942c8SAlfredo Cardigliano static int 135027b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 135127b942c8SAlfredo Cardigliano { 135227b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 135327b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 135427b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 135527b942c8SAlfredo Cardigliano int err; 135627b942c8SAlfredo Cardigliano 135727b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 135827b942c8SAlfredo Cardigliano .pending_work = true, 135927b942c8SAlfredo Cardigliano .cmd.q_init = { 136027b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 136127b942c8SAlfredo Cardigliano .type = q->type, 1362c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 136309f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 136409f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(qcq->intr.index), 136509f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ | 136609f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 136727b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 136809f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 136927b942c8SAlfredo Cardigliano } 137027b942c8SAlfredo Cardigliano }; 137127b942c8SAlfredo Cardigliano 137209f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index); 137309f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa); 137427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 137527b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13764ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 137727b942c8SAlfredo Cardigliano 137827b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 137927b942c8SAlfredo Cardigliano if (err) 138027b942c8SAlfredo Cardigliano return err; 138127b942c8SAlfredo Cardigliano 138227b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 138309f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 138427b942c8SAlfredo Cardigliano q->db = NULL; 138527b942c8SAlfredo Cardigliano 138627b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 138727b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 138827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 138927b942c8SAlfredo Cardigliano 139027b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 139127b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 139227b942c8SAlfredo Cardigliano 139327b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 139427b942c8SAlfredo Cardigliano 139527b942c8SAlfredo Cardigliano return 0; 139627b942c8SAlfredo Cardigliano } 139727b942c8SAlfredo Cardigliano 1398669c8de6SAlfredo Cardigliano int 1399598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1400598f6726SAlfredo Cardigliano { 1401598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1402598f6726SAlfredo Cardigliano .pending_work = true, 1403598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1404598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1405598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 140609f806e9SAndrew Boyer .features = rte_cpu_to_le_64(lif->features), 1407598f6726SAlfredo Cardigliano }, 1408598f6726SAlfredo Cardigliano }; 1409598f6726SAlfredo Cardigliano int err; 1410598f6726SAlfredo Cardigliano 1411598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1412598f6726SAlfredo Cardigliano if (err) 1413598f6726SAlfredo Cardigliano return err; 1414598f6726SAlfredo Cardigliano 141509f806e9SAndrew Boyer lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features & 1416598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1417598f6726SAlfredo Cardigliano 1418598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1419598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1420598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1421598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1422598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1423598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1424598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1425598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1426598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1427598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1428598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1429598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1430598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1431598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1432598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1433598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1434598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1435598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1436598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1437598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1438598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1439598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1440598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1441598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1442598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1443598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1444598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1445598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1446598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1447598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1448598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1449598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1450598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1451598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1452598f6726SAlfredo Cardigliano 1453598f6726SAlfredo Cardigliano return 0; 1454598f6726SAlfredo Cardigliano } 1455598f6726SAlfredo Cardigliano 1456a27d9013SAlfredo Cardigliano int 1457a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq) 1458a27d9013SAlfredo Cardigliano { 1459a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1460a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1461a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1462a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1463a27d9013SAlfredo Cardigliano .pending_work = true, 1464a27d9013SAlfredo Cardigliano .cmd.q_init = { 1465a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1466a27d9013SAlfredo Cardigliano .type = q->type, 1467c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 146809f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 146909f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 147009f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 147109f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1472a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 147309f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 147409f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 147509f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1476a27d9013SAlfredo Cardigliano }, 1477a27d9013SAlfredo Cardigliano }; 1478a27d9013SAlfredo Cardigliano int err; 1479a27d9013SAlfredo Cardigliano 148009f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.index %d", q->index); 148109f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1482a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1483a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14844ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1485a27d9013SAlfredo Cardigliano 1486a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1487a27d9013SAlfredo Cardigliano if (err) 1488a27d9013SAlfredo Cardigliano return err; 1489a27d9013SAlfredo Cardigliano 1490a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 149109f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1492a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1493a27d9013SAlfredo Cardigliano 1494a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1495a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1496a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1497a27d9013SAlfredo Cardigliano 1498a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1499a27d9013SAlfredo Cardigliano 1500a27d9013SAlfredo Cardigliano return 0; 1501a27d9013SAlfredo Cardigliano } 1502a27d9013SAlfredo Cardigliano 1503a27d9013SAlfredo Cardigliano int 1504a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq) 1505a27d9013SAlfredo Cardigliano { 1506a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1507a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1508a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1509a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1510a27d9013SAlfredo Cardigliano .pending_work = true, 1511a27d9013SAlfredo Cardigliano .cmd.q_init = { 1512a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1513a27d9013SAlfredo Cardigliano .type = q->type, 1514c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 151509f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 151609f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 151709f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 151809f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1519a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 152009f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 152109f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 152209f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1523a27d9013SAlfredo Cardigliano }, 1524a27d9013SAlfredo Cardigliano }; 1525a27d9013SAlfredo Cardigliano int err; 1526a27d9013SAlfredo Cardigliano 152709f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index); 152809f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1529a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1530a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 15314ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1532a27d9013SAlfredo Cardigliano 1533a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1534a27d9013SAlfredo Cardigliano if (err) 1535a27d9013SAlfredo Cardigliano return err; 1536a27d9013SAlfredo Cardigliano 1537a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 153809f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1539a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1540a27d9013SAlfredo Cardigliano 1541a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1542a27d9013SAlfredo Cardigliano 1543a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1544a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1545a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1546a27d9013SAlfredo Cardigliano 1547a27d9013SAlfredo Cardigliano return 0; 1548a27d9013SAlfredo Cardigliano } 1549a27d9013SAlfredo Cardigliano 1550598f6726SAlfredo Cardigliano static int 1551598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1552598f6726SAlfredo Cardigliano { 1553598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1554598f6726SAlfredo Cardigliano .pending_work = true, 1555598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1556598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1557598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1558598f6726SAlfredo Cardigliano }, 1559598f6726SAlfredo Cardigliano }; 1560598f6726SAlfredo Cardigliano int err; 1561598f6726SAlfredo Cardigliano 1562598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1563598f6726SAlfredo Cardigliano 1564598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1565598f6726SAlfredo Cardigliano if (err) 1566598f6726SAlfredo Cardigliano return err; 1567598f6726SAlfredo Cardigliano 1568598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1569598f6726SAlfredo Cardigliano 1570598f6726SAlfredo Cardigliano return 0; 1571598f6726SAlfredo Cardigliano } 1572598f6726SAlfredo Cardigliano 1573598f6726SAlfredo Cardigliano static void 1574598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1575598f6726SAlfredo Cardigliano { 1576598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1577598f6726SAlfredo Cardigliano .pending_work = true, 1578598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1579598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1580598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1581598f6726SAlfredo Cardigliano }, 1582598f6726SAlfredo Cardigliano }; 1583598f6726SAlfredo Cardigliano 15844ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 15854ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1586598f6726SAlfredo Cardigliano 1587598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1588598f6726SAlfredo Cardigliano } 1589598f6726SAlfredo Cardigliano 1590598f6726SAlfredo Cardigliano int 1591669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1592669c8de6SAlfredo Cardigliano { 1593669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1594669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 1595669c8de6SAlfredo Cardigliano int err; 1596669c8de6SAlfredo Cardigliano 15973cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 15983cdfd905SAlfredo Cardigliano 159900b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1600669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1601669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 1602669c8de6SAlfredo Cardigliano if (err) 1603669c8de6SAlfredo Cardigliano return err; 1604669c8de6SAlfredo Cardigliano 160509f806e9SAndrew Boyer lif->hw_index = rte_cpu_to_le_16(comp.hw_index); 1606669c8de6SAlfredo Cardigliano 160701a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 160801a6c311SAlfredo Cardigliano if (err) 160901a6c311SAlfredo Cardigliano return err; 161001a6c311SAlfredo Cardigliano 161127b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 161227b942c8SAlfredo Cardigliano if (err) 161327b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 161427b942c8SAlfredo Cardigliano 161518a44465SAndrew Boyer /* 161618a44465SAndrew Boyer * Configure initial feature set 161718a44465SAndrew Boyer * This will be updated later by the dev_configure() step 161818a44465SAndrew Boyer */ 161918a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1620598f6726SAlfredo Cardigliano 1621598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1622598f6726SAlfredo Cardigliano if (err) 1623598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1624598f6726SAlfredo Cardigliano 162554fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1626598f6726SAlfredo Cardigliano if (err) 1627598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1628598f6726SAlfredo Cardigliano 162954fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 163054fe083fSAlfredo Cardigliano if (err) 163154fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 163254fe083fSAlfredo Cardigliano 1633598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1634598f6726SAlfredo Cardigliano 1635669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1636669c8de6SAlfredo Cardigliano 1637669c8de6SAlfredo Cardigliano return 0; 163827b942c8SAlfredo Cardigliano 163954fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 164054fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 164154fe083fSAlfredo Cardigliano 1642598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 16434c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1644598f6726SAlfredo Cardigliano 164527b942c8SAlfredo Cardigliano err_out_adminq_deinit: 16464c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 164727b942c8SAlfredo Cardigliano 164827b942c8SAlfredo Cardigliano return err; 1649669c8de6SAlfredo Cardigliano } 1650669c8de6SAlfredo Cardigliano 1651669c8de6SAlfredo Cardigliano void 1652669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1653669c8de6SAlfredo Cardigliano { 1654669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1655669c8de6SAlfredo Cardigliano return; 1656669c8de6SAlfredo Cardigliano 165754fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 165822e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 16594c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 16604c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 166101a6c311SAlfredo Cardigliano 1662669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1663669c8de6SAlfredo Cardigliano } 1664669c8de6SAlfredo Cardigliano 166518a44465SAndrew Boyer void 166618a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 166718a44465SAndrew Boyer { 166818a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 166918a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 167018a44465SAndrew Boyer 167118a44465SAndrew Boyer /* 167218a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 167318a44465SAndrew Boyer * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK 167418a44465SAndrew Boyer */ 167518a44465SAndrew Boyer rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 167618a44465SAndrew Boyer 167718a44465SAndrew Boyer if (mask & ETH_VLAN_STRIP_MASK) { 167818a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) 167918a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 168018a44465SAndrew Boyer else 168118a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 168218a44465SAndrew Boyer } 168318a44465SAndrew Boyer } 168418a44465SAndrew Boyer 168518a44465SAndrew Boyer void 1686598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1687598f6726SAlfredo Cardigliano { 168818a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 168918a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 169022e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 169109f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 169222e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 169309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 169422e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 169509f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 169622e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 169722e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 169822e7171bSAlfredo Cardigliano 1699598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1700598f6726SAlfredo Cardigliano 170122e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 170222e7171bSAlfredo Cardigliano lif->port_id); 170322e7171bSAlfredo Cardigliano 170422e7171bSAlfredo Cardigliano if (nrxqs > 0) 170522e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 170622e7171bSAlfredo Cardigliano 170722e7171bSAlfredo Cardigliano if (ntxqs > 0) 170822e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 170922e7171bSAlfredo Cardigliano 171022e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 171122e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1712a27d9013SAlfredo Cardigliano 171318a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 171418a44465SAndrew Boyer 171518a44465SAndrew Boyer /* 171618a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 171718a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 171818a44465SAndrew Boyer * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH; 171918a44465SAndrew Boyer */ 172018a44465SAndrew Boyer 172118a44465SAndrew Boyer /* RX per-port */ 172218a44465SAndrew Boyer 172318a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM || 172418a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM || 172518a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM) 172618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 172718a44465SAndrew Boyer else 172818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 172918a44465SAndrew Boyer 173018a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) { 173118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 173218a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 173318a44465SAndrew Boyer } else { 173418a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 173518a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 173618a44465SAndrew Boyer } 173718a44465SAndrew Boyer 173818a44465SAndrew Boyer /* Covers VLAN_STRIP */ 173918a44465SAndrew Boyer ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK); 174018a44465SAndrew Boyer 174118a44465SAndrew Boyer /* TX per-port */ 174218a44465SAndrew Boyer 174318a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM || 174418a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM || 174518a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM || 174618a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM || 174718a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) 174818a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 174918a44465SAndrew Boyer else 175018a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 175118a44465SAndrew Boyer 175218a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT) 175318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 175418a44465SAndrew Boyer else 175518a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 175618a44465SAndrew Boyer 175718a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS) 175818a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 175918a44465SAndrew Boyer else 176018a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 176118a44465SAndrew Boyer 176218a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) { 176318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 176418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 176518a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 176618a44465SAndrew Boyer } else { 176718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 176818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 176918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 177018a44465SAndrew Boyer } 1771598f6726SAlfredo Cardigliano } 1772598f6726SAlfredo Cardigliano 1773598f6726SAlfredo Cardigliano int 1774598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1775598f6726SAlfredo Cardigliano { 17760578335aSAndrew Boyer uint32_t rx_mode; 1777a27d9013SAlfredo Cardigliano uint32_t i; 1778a27d9013SAlfredo Cardigliano int err; 1779598f6726SAlfredo Cardigliano 178022e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 178122e7171bSAlfredo Cardigliano if (err) 178222e7171bSAlfredo Cardigliano return err; 178322e7171bSAlfredo Cardigliano 17840578335aSAndrew Boyer if (!lif->rx_mode) { 17850578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 17860578335aSAndrew Boyer lif->name); 1787598f6726SAlfredo Cardigliano 17880578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1789598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1790598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1791598f6726SAlfredo Cardigliano 1792598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 17930578335aSAndrew Boyer } 1794598f6726SAlfredo Cardigliano 1795a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1796a27d9013SAlfredo Cardigliano "on port %u", 1797a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1798a27d9013SAlfredo Cardigliano 1799a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1800a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = lif->rxqcqs[i]; 180102eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1802a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1803a27d9013SAlfredo Cardigliano 1804a27d9013SAlfredo Cardigliano if (err) 1805a27d9013SAlfredo Cardigliano return err; 1806a27d9013SAlfredo Cardigliano } 1807a27d9013SAlfredo Cardigliano } 1808a27d9013SAlfredo Cardigliano 1809a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1810a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = lif->txqcqs[i]; 181102eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1812a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1813a27d9013SAlfredo Cardigliano 1814a27d9013SAlfredo Cardigliano if (err) 1815a27d9013SAlfredo Cardigliano return err; 1816a27d9013SAlfredo Cardigliano } 1817a27d9013SAlfredo Cardigliano } 1818a27d9013SAlfredo Cardigliano 1819598f6726SAlfredo Cardigliano /* Carrier ON here */ 1820be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1821be63459eSAndrew Boyer 1822be63459eSAndrew Boyer ionic_link_status_check(lif); 1823598f6726SAlfredo Cardigliano 1824598f6726SAlfredo Cardigliano return 0; 1825598f6726SAlfredo Cardigliano } 1826598f6726SAlfredo Cardigliano 1827598f6726SAlfredo Cardigliano int 1828669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1829669c8de6SAlfredo Cardigliano { 1830669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1831669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 183209f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 183376276d71SAndrew Boyer uint32_t lif_words = RTE_DIM(ident->lif.words); 183476276d71SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 183576276d71SAndrew Boyer uint32_t i, nwords; 1836669c8de6SAlfredo Cardigliano int err; 1837669c8de6SAlfredo Cardigliano 1838669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1839669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1840669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1841669c8de6SAlfredo Cardigliano if (err) 1842669c8de6SAlfredo Cardigliano return (err); 1843669c8de6SAlfredo Cardigliano 1844669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1845669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1846669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1847669c8de6SAlfredo Cardigliano 1848669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 184909f806e9SAndrew Boyer rte_le_to_cpu_64(ident->lif.capabilities)); 1850669c8de6SAlfredo Cardigliano 1851669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 185209f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters)); 1853669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 185409f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters)); 1855669c8de6SAlfredo Cardigliano 1856669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 185709f806e9SAndrew Boyer rte_le_to_cpu_64(cfg->features)); 1858669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 185909f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ])); 1860669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 186109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ])); 1862669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 186309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ])); 1864669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 186509f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ])); 1866669c8de6SAlfredo Cardigliano 1867669c8de6SAlfredo Cardigliano return 0; 1868669c8de6SAlfredo Cardigliano } 1869669c8de6SAlfredo Cardigliano 1870669c8de6SAlfredo Cardigliano int 1871669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1872669c8de6SAlfredo Cardigliano { 1873669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 187409f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 187509f806e9SAndrew Boyer uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs); 1876669c8de6SAlfredo Cardigliano 1877669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 187809f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 1879669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 188009f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 1881669c8de6SAlfredo Cardigliano 188200b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1883669c8de6SAlfredo Cardigliano 1884669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 18854ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 18864ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1887669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1888669c8de6SAlfredo Cardigliano return -ENOSPC; 1889669c8de6SAlfredo Cardigliano } 1890669c8de6SAlfredo Cardigliano 1891669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1892669c8de6SAlfredo Cardigliano 1893669c8de6SAlfredo Cardigliano return 0; 1894669c8de6SAlfredo Cardigliano } 1895