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 15598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr); 16598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr); 17598f6726SAlfredo Cardigliano 1801a6c311SAlfredo Cardigliano int 1901a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq) 2001a6c311SAlfredo Cardigliano { 2101a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 2201a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 2301a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 2401a6c311SAlfredo Cardigliano .pending_work = true, 2501a6c311SAlfredo Cardigliano .cmd.q_control = { 2601a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 2701a6c311SAlfredo Cardigliano .type = q->type, 2801a6c311SAlfredo Cardigliano .index = q->index, 2901a6c311SAlfredo Cardigliano .oper = IONIC_Q_ENABLE, 3001a6c311SAlfredo Cardigliano }, 3101a6c311SAlfredo Cardigliano }; 3201a6c311SAlfredo Cardigliano 3301a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 3401a6c311SAlfredo Cardigliano } 3501a6c311SAlfredo Cardigliano 3601a6c311SAlfredo Cardigliano int 3701a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 3801a6c311SAlfredo Cardigliano { 3901a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 4001a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 4101a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 4201a6c311SAlfredo Cardigliano .pending_work = true, 4301a6c311SAlfredo Cardigliano .cmd.q_control = { 4401a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 4501a6c311SAlfredo Cardigliano .type = q->type, 4601a6c311SAlfredo Cardigliano .index = q->index, 4701a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 4801a6c311SAlfredo Cardigliano }, 4901a6c311SAlfredo Cardigliano }; 5001a6c311SAlfredo Cardigliano 5101a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 5201a6c311SAlfredo Cardigliano } 5301a6c311SAlfredo Cardigliano 54be63459eSAndrew Boyer void 55be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif) 56598f6726SAlfredo Cardigliano { 57a0a99f21SAndrew Boyer uint32_t i; 58a0a99f21SAndrew Boyer 59be63459eSAndrew Boyer IONIC_PRINT_CALL(); 60598f6726SAlfredo Cardigliano 61be63459eSAndrew Boyer lif->state &= ~IONIC_LIF_F_UP; 62a0a99f21SAndrew Boyer 63a0a99f21SAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 64a0a99f21SAndrew Boyer struct ionic_qcq *rxq = lif->rxqcqs[i]; 65a0a99f21SAndrew Boyer if (rxq->flags & IONIC_QCQ_F_INITED) 66a0a99f21SAndrew Boyer (void)ionic_dev_rx_queue_stop(lif->eth_dev, i); 67a0a99f21SAndrew Boyer } 68a0a99f21SAndrew Boyer 69a0a99f21SAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 70a0a99f21SAndrew Boyer struct ionic_qcq *txq = lif->txqcqs[i]; 71a0a99f21SAndrew Boyer if (txq->flags & IONIC_QCQ_F_INITED) 72a0a99f21SAndrew Boyer (void)ionic_dev_tx_queue_stop(lif->eth_dev, i); 73a0a99f21SAndrew Boyer } 74598f6726SAlfredo Cardigliano } 75598f6726SAlfredo Cardigliano 76598f6726SAlfredo Cardigliano void 77598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 78598f6726SAlfredo Cardigliano { 79598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 8075f96902SAndrew Boyer int err; 81598f6726SAlfredo Cardigliano 82598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 83598f6726SAlfredo Cardigliano 8400b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 8575f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 8675f96902SAndrew Boyer if (err) 874ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 88598f6726SAlfredo Cardigliano } 89598f6726SAlfredo Cardigliano 903cdfd905SAlfredo Cardigliano static void 913cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 923cdfd905SAlfredo Cardigliano { 933cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 943cdfd905SAlfredo Cardigliano uint32_t i; 953cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 963cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 973cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 983cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 993cdfd905SAlfredo Cardigliano 1003cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 1013cdfd905SAlfredo Cardigliano 1023cdfd905SAlfredo Cardigliano if (ls == NULL) { 1033cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1043cdfd905SAlfredo Cardigliano lif->port_id); 1053cdfd905SAlfredo Cardigliano return; 1063cdfd905SAlfredo Cardigliano } 1073cdfd905SAlfredo Cardigliano 1083cdfd905SAlfredo Cardigliano /* RX */ 1093cdfd905SAlfredo Cardigliano 1103cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1113cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1123cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1133cdfd905SAlfredo Cardigliano 1143cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1153cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1163cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1173cdfd905SAlfredo Cardigliano 1183cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1193cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1203cdfd905SAlfredo Cardigliano stats->imissed += 1213cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1223cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1233cdfd905SAlfredo Cardigliano rx_stats->no_room + 1243cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1253cdfd905SAlfredo Cardigliano } 1263cdfd905SAlfredo Cardigliano 1273cdfd905SAlfredo Cardigliano stats->imissed += 1283cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1293cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1303cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1313cdfd905SAlfredo Cardigliano 1323cdfd905SAlfredo Cardigliano stats->imissed += 1333cdfd905SAlfredo Cardigliano ls->rx_queue_empty + 1343cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1353cdfd905SAlfredo Cardigliano ls->rx_queue_disabled + 1363cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1373cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1383cdfd905SAlfredo Cardigliano 1393cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 1403cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1413cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1423cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1433cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1443cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1453cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1463cdfd905SAlfredo Cardigliano rx_stats->no_room + 1473cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1483cdfd905SAlfredo Cardigliano } 1493cdfd905SAlfredo Cardigliano 1503cdfd905SAlfredo Cardigliano /* TX */ 1513cdfd905SAlfredo Cardigliano 1523cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1533cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1543cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1553cdfd905SAlfredo Cardigliano 1563cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1573cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1583cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1593cdfd905SAlfredo Cardigliano 1603cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1613cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1623cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1633cdfd905SAlfredo Cardigliano } 1643cdfd905SAlfredo Cardigliano 1653cdfd905SAlfredo Cardigliano stats->oerrors += 1663cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1673cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1683cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1693cdfd905SAlfredo Cardigliano 1703cdfd905SAlfredo Cardigliano stats->oerrors += 1713cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1723cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1733cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1743cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1753cdfd905SAlfredo Cardigliano 1763cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 1773cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1783cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1793cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1803cdfd905SAlfredo Cardigliano } 1813cdfd905SAlfredo Cardigliano } 1823cdfd905SAlfredo Cardigliano 1833cdfd905SAlfredo Cardigliano void 1843cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 1853cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 1863cdfd905SAlfredo Cardigliano { 1873cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 1883cdfd905SAlfredo Cardigliano 1893cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 1903cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 1913cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 1923cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 1933cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 1943cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 1953cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 1963cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 1973cdfd905SAlfredo Cardigliano } 1983cdfd905SAlfredo Cardigliano 1993cdfd905SAlfredo Cardigliano void 2003cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 2013cdfd905SAlfredo Cardigliano { 2023cdfd905SAlfredo Cardigliano uint32_t i; 2033cdfd905SAlfredo Cardigliano 2043cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 2053cdfd905SAlfredo Cardigliano memset(&lif->rxqcqs[i]->stats.rx, 0, 2063cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 2073cdfd905SAlfredo Cardigliano memset(&lif->txqcqs[i]->stats.tx, 0, 2083cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2093cdfd905SAlfredo Cardigliano } 2103cdfd905SAlfredo Cardigliano 2113cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2123cdfd905SAlfredo Cardigliano } 2133cdfd905SAlfredo Cardigliano 2143cdfd905SAlfredo Cardigliano void 2153cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2163cdfd905SAlfredo Cardigliano { 2173cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2183cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2193cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2203cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2213cdfd905SAlfredo Cardigliano 2223cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2233cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2243cdfd905SAlfredo Cardigliano } 2253cdfd905SAlfredo Cardigliano 2263cdfd905SAlfredo Cardigliano void 2273cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2283cdfd905SAlfredo Cardigliano { 2293cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2303cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2313cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2323cdfd905SAlfredo Cardigliano 2333cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2343cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2353cdfd905SAlfredo Cardigliano } 2363cdfd905SAlfredo Cardigliano 237598f6726SAlfredo Cardigliano static int 23854fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 239598f6726SAlfredo Cardigliano { 24054fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 24154fe083fSAlfredo Cardigliano .pending_work = true, 24254fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 24354fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 24454fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_MAC, 24554fe083fSAlfredo Cardigliano }, 24654fe083fSAlfredo Cardigliano }; 24754fe083fSAlfredo Cardigliano int err; 24854fe083fSAlfredo Cardigliano 24954fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 25054fe083fSAlfredo Cardigliano 25154fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 25254fe083fSAlfredo Cardigliano if (err) 25354fe083fSAlfredo Cardigliano return err; 25454fe083fSAlfredo Cardigliano 25554fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 25654fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 25754fe083fSAlfredo Cardigliano 25854fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 25954fe083fSAlfredo Cardigliano } 26054fe083fSAlfredo Cardigliano 26154fe083fSAlfredo Cardigliano static int 26254fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 26354fe083fSAlfredo Cardigliano { 26454fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 26554fe083fSAlfredo Cardigliano .pending_work = true, 26654fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 26754fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 26854fe083fSAlfredo Cardigliano }, 26954fe083fSAlfredo Cardigliano }; 27054fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 27154fe083fSAlfredo Cardigliano int err; 27254fe083fSAlfredo Cardigliano 27354fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 27454fe083fSAlfredo Cardigliano 27554fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 27654fe083fSAlfredo Cardigliano 27754fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 27854fe083fSAlfredo Cardigliano if (!f) { 27954fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 28054fe083fSAlfredo Cardigliano return -ENOENT; 28154fe083fSAlfredo Cardigliano } 28254fe083fSAlfredo Cardigliano 28354fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 28454fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 28554fe083fSAlfredo Cardigliano 28654fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 28754fe083fSAlfredo Cardigliano 28854fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 28954fe083fSAlfredo Cardigliano if (err) 29054fe083fSAlfredo Cardigliano return err; 29154fe083fSAlfredo Cardigliano 29254fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 29354fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 294598f6726SAlfredo Cardigliano 295598f6726SAlfredo Cardigliano return 0; 296598f6726SAlfredo Cardigliano } 297598f6726SAlfredo Cardigliano 29854fe083fSAlfredo Cardigliano int 29954fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 30054fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 30154fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 302598f6726SAlfredo Cardigliano { 30354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 30454fe083fSAlfredo Cardigliano 30554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 30654fe083fSAlfredo Cardigliano 30754fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 30854fe083fSAlfredo Cardigliano } 30954fe083fSAlfredo Cardigliano 31054fe083fSAlfredo Cardigliano void 31175f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 31254fe083fSAlfredo Cardigliano { 31354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 31454fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 31575f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 31654fe083fSAlfredo Cardigliano 31754fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 31854fe083fSAlfredo Cardigliano 31954fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 32054fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 32154fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 32254fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 32354fe083fSAlfredo Cardigliano return; 32454fe083fSAlfredo Cardigliano } 32554fe083fSAlfredo Cardigliano 32675f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 32775f96902SAndrew Boyer 32875f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 32954fe083fSAlfredo Cardigliano return; 33054fe083fSAlfredo Cardigliano 33175f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 33254fe083fSAlfredo Cardigliano } 33354fe083fSAlfredo Cardigliano 33454fe083fSAlfredo Cardigliano int 33554fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 33654fe083fSAlfredo Cardigliano { 33754fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 33854fe083fSAlfredo Cardigliano 33954fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 34054fe083fSAlfredo Cardigliano 34154fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 34254fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 34354fe083fSAlfredo Cardigliano return -1; 34454fe083fSAlfredo Cardigliano } 34554fe083fSAlfredo Cardigliano 34654fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 34754fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 34854fe083fSAlfredo Cardigliano lif->mac_addr); 34954fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 35054fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 35154fe083fSAlfredo Cardigliano } 35254fe083fSAlfredo Cardigliano 35354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 35454fe083fSAlfredo Cardigliano 35554fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 35654fe083fSAlfredo Cardigliano 35754fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 35854fe083fSAlfredo Cardigliano } 35954fe083fSAlfredo Cardigliano 36054fe083fSAlfredo Cardigliano static int 36154fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 36254fe083fSAlfredo Cardigliano { 36354fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 36454fe083fSAlfredo Cardigliano .pending_work = true, 36554fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 36654fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 36754fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_VLAN, 36854fe083fSAlfredo Cardigliano .vlan.vlan = vid, 36954fe083fSAlfredo Cardigliano }, 37054fe083fSAlfredo Cardigliano }; 37154fe083fSAlfredo Cardigliano int err; 37254fe083fSAlfredo Cardigliano 37354fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 37454fe083fSAlfredo Cardigliano if (err) 37554fe083fSAlfredo Cardigliano return err; 37654fe083fSAlfredo Cardigliano 37754fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 37854fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 37954fe083fSAlfredo Cardigliano 38054fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 38154fe083fSAlfredo Cardigliano } 38254fe083fSAlfredo Cardigliano 38354fe083fSAlfredo Cardigliano static int 38454fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 38554fe083fSAlfredo Cardigliano { 38654fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 38754fe083fSAlfredo Cardigliano .pending_work = true, 38854fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 38954fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 39054fe083fSAlfredo Cardigliano }, 39154fe083fSAlfredo Cardigliano }; 39254fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 39354fe083fSAlfredo Cardigliano int err; 39454fe083fSAlfredo Cardigliano 39554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 39654fe083fSAlfredo Cardigliano 39754fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 39854fe083fSAlfredo Cardigliano 39954fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 40054fe083fSAlfredo Cardigliano if (!f) { 40154fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 40254fe083fSAlfredo Cardigliano return -ENOENT; 40354fe083fSAlfredo Cardigliano } 40454fe083fSAlfredo Cardigliano 40554fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 40654fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 40754fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 40854fe083fSAlfredo Cardigliano 40954fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 41054fe083fSAlfredo Cardigliano if (err) 41154fe083fSAlfredo Cardigliano return err; 41254fe083fSAlfredo Cardigliano 41354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 41454fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 415598f6726SAlfredo Cardigliano 416598f6726SAlfredo Cardigliano return 0; 417598f6726SAlfredo Cardigliano } 418598f6726SAlfredo Cardigliano 41954fe083fSAlfredo Cardigliano int 42054fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 42154fe083fSAlfredo Cardigliano int on) 42254fe083fSAlfredo Cardigliano { 42354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 42454fe083fSAlfredo Cardigliano int err; 42554fe083fSAlfredo Cardigliano 42654fe083fSAlfredo Cardigliano if (on) 42754fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 42854fe083fSAlfredo Cardigliano else 42954fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 43054fe083fSAlfredo Cardigliano 43154fe083fSAlfredo Cardigliano return err; 43254fe083fSAlfredo Cardigliano } 43354fe083fSAlfredo Cardigliano 434598f6726SAlfredo Cardigliano static void 435598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 436598f6726SAlfredo Cardigliano { 437598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 438598f6726SAlfredo Cardigliano .pending_work = true, 439598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 440598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 441598f6726SAlfredo Cardigliano .rx_mode = rx_mode, 442598f6726SAlfredo Cardigliano }, 443598f6726SAlfredo Cardigliano }; 444598f6726SAlfredo Cardigliano int err; 445598f6726SAlfredo Cardigliano 446598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 447598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 448598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 449598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 450598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 451598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 452598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 453598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 454598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 455598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 456598f6726SAlfredo Cardigliano 457598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 458598f6726SAlfredo Cardigliano if (err) 459598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 460598f6726SAlfredo Cardigliano } 461598f6726SAlfredo Cardigliano 462598f6726SAlfredo Cardigliano static void 463598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 464598f6726SAlfredo Cardigliano { 465598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 466598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 467598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 468598f6726SAlfredo Cardigliano } 469598f6726SAlfredo Cardigliano } 470598f6726SAlfredo Cardigliano 47154fe083fSAlfredo Cardigliano int 47254fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 47354fe083fSAlfredo Cardigliano { 47454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 47554fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 47654fe083fSAlfredo Cardigliano 47754fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 47854fe083fSAlfredo Cardigliano 47954fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 48054fe083fSAlfredo Cardigliano 48154fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 48254fe083fSAlfredo Cardigliano 48354fe083fSAlfredo Cardigliano return 0; 48454fe083fSAlfredo Cardigliano } 48554fe083fSAlfredo Cardigliano 48654fe083fSAlfredo Cardigliano int 48754fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(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 rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 49354fe083fSAlfredo Cardigliano 49454fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 49554fe083fSAlfredo Cardigliano 49654fe083fSAlfredo Cardigliano return 0; 49754fe083fSAlfredo Cardigliano } 49854fe083fSAlfredo Cardigliano 49954fe083fSAlfredo Cardigliano int 50054fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 50154fe083fSAlfredo Cardigliano { 50254fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50354fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 50454fe083fSAlfredo Cardigliano 50554fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 50654fe083fSAlfredo Cardigliano 50754fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 50854fe083fSAlfredo Cardigliano 50954fe083fSAlfredo Cardigliano return 0; 51054fe083fSAlfredo Cardigliano } 51154fe083fSAlfredo Cardigliano 51254fe083fSAlfredo Cardigliano int 51354fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 51454fe083fSAlfredo Cardigliano { 51554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 51654fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 51754fe083fSAlfredo Cardigliano 51854fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 51954fe083fSAlfredo Cardigliano 52054fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 52154fe083fSAlfredo Cardigliano 52254fe083fSAlfredo Cardigliano return 0; 52354fe083fSAlfredo Cardigliano } 524598f6726SAlfredo Cardigliano 525598f6726SAlfredo Cardigliano int 526598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu) 527598f6726SAlfredo Cardigliano { 528598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 529598f6726SAlfredo Cardigliano .pending_work = true, 530598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 531598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 532598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 533598f6726SAlfredo Cardigliano .mtu = new_mtu, 534598f6726SAlfredo Cardigliano }, 535598f6726SAlfredo Cardigliano }; 536598f6726SAlfredo Cardigliano int err; 537598f6726SAlfredo Cardigliano 538598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 539598f6726SAlfredo Cardigliano if (err) 540598f6726SAlfredo Cardigliano return err; 541598f6726SAlfredo Cardigliano 542598f6726SAlfredo Cardigliano return 0; 543598f6726SAlfredo Cardigliano } 544598f6726SAlfredo Cardigliano 545598f6726SAlfredo Cardigliano int 54601a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 54701a6c311SAlfredo Cardigliano { 54801a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 54901a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 55001a6c311SAlfredo Cardigliano unsigned long index; 55101a6c311SAlfredo Cardigliano 55201a6c311SAlfredo Cardigliano /* 55301a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 55401a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5554ae96cb8SAndrew Boyer * which has index = 0) 55601a6c311SAlfredo Cardigliano */ 55701a6c311SAlfredo Cardigliano 55801a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 55901a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 56001a6c311SAlfredo Cardigliano break; 56101a6c311SAlfredo Cardigliano 56201a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 56301a6c311SAlfredo Cardigliano return -ENOSPC; 56401a6c311SAlfredo Cardigliano 56501a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 56601a6c311SAlfredo Cardigliano 56701a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 56801a6c311SAlfredo Cardigliano 56901a6c311SAlfredo Cardigliano return 0; 57001a6c311SAlfredo Cardigliano } 57101a6c311SAlfredo Cardigliano 57201a6c311SAlfredo Cardigliano void 57301a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr) 57401a6c311SAlfredo Cardigliano { 575*4c8f8d57SAndrew Boyer if (intr->index != IONIC_INTR_NONE) 57601a6c311SAlfredo Cardigliano lif->adapter->intrs[intr->index] = false; 57701a6c311SAlfredo Cardigliano } 57801a6c311SAlfredo Cardigliano 57901a6c311SAlfredo Cardigliano static int 58001a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type, 58101a6c311SAlfredo Cardigliano uint32_t index, 58201a6c311SAlfredo Cardigliano const char *base, uint32_t flags, 58301a6c311SAlfredo Cardigliano uint32_t num_descs, 58401a6c311SAlfredo Cardigliano uint32_t desc_size, 58501a6c311SAlfredo Cardigliano uint32_t cq_desc_size, 58601a6c311SAlfredo Cardigliano uint32_t sg_desc_size, 5871abf69fcSAndrew Boyer struct ionic_qcq **qcq) 58801a6c311SAlfredo Cardigliano { 58901a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 59001a6c311SAlfredo Cardigliano struct ionic_qcq *new; 59101a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 59201a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 59301a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 59401a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 59501a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 59601a6c311SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 59701a6c311SAlfredo Cardigliano int err; 59801a6c311SAlfredo Cardigliano 59901a6c311SAlfredo Cardigliano *qcq = NULL; 60001a6c311SAlfredo Cardigliano 60101a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 60201a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 60301a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 60401a6c311SAlfredo Cardigliano 60501a6c311SAlfredo Cardigliano total_size = RTE_ALIGN(q_size, PAGE_SIZE) + 60601a6c311SAlfredo Cardigliano RTE_ALIGN(cq_size, PAGE_SIZE); 60701a6c311SAlfredo Cardigliano /* 60801a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 60901a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 61001a6c311SAlfredo Cardigliano * Adding PAGE_SIZE. 61101a6c311SAlfredo Cardigliano */ 61201a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 61301a6c311SAlfredo Cardigliano 61401a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 61501a6c311SAlfredo Cardigliano total_size += RTE_ALIGN(sg_size, PAGE_SIZE); 61601a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 61701a6c311SAlfredo Cardigliano } 61801a6c311SAlfredo Cardigliano 61901a6c311SAlfredo Cardigliano new = rte_zmalloc("ionic", sizeof(*new), 0); 62001a6c311SAlfredo Cardigliano if (!new) { 62101a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 62201a6c311SAlfredo Cardigliano return -ENOMEM; 62301a6c311SAlfredo Cardigliano } 62401a6c311SAlfredo Cardigliano 62501a6c311SAlfredo Cardigliano new->lif = lif; 62601a6c311SAlfredo Cardigliano new->flags = flags; 62701a6c311SAlfredo Cardigliano 62801a6c311SAlfredo Cardigliano new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0); 62901a6c311SAlfredo Cardigliano if (!new->q.info) { 63001a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 631*4c8f8d57SAndrew Boyer err = -ENOMEM; 632*4c8f8d57SAndrew Boyer goto err_out_free_qcq; 63301a6c311SAlfredo Cardigliano } 63401a6c311SAlfredo Cardigliano 63501a6c311SAlfredo Cardigliano new->q.type = type; 63601a6c311SAlfredo Cardigliano 63701a6c311SAlfredo Cardigliano err = ionic_q_init(lif, idev, &new->q, index, num_descs, 6381abf69fcSAndrew Boyer desc_size, sg_desc_size); 63901a6c311SAlfredo Cardigliano if (err) { 64001a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 641*4c8f8d57SAndrew Boyer goto err_out_free_info; 64201a6c311SAlfredo Cardigliano } 64301a6c311SAlfredo Cardigliano 644*4c8f8d57SAndrew Boyer err = ionic_cq_init(lif, &new->cq, num_descs, cq_desc_size); 64501a6c311SAlfredo Cardigliano if (err) { 64601a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 647*4c8f8d57SAndrew Boyer goto err_out_free_info; 64801a6c311SAlfredo Cardigliano } 64901a6c311SAlfredo Cardigliano 65001a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 65101a6c311SAlfredo Cardigliano base /* name */, index /* queue_idx */, 65201a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 65301a6c311SAlfredo Cardigliano 65401a6c311SAlfredo Cardigliano if (!new->base_z) { 65501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 65601a6c311SAlfredo Cardigliano err = -ENOMEM; 657*4c8f8d57SAndrew Boyer goto err_out_free_info; 65801a6c311SAlfredo Cardigliano } 65901a6c311SAlfredo Cardigliano 66001a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 66101a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 66201a6c311SAlfredo Cardigliano new->total_size = total_size; 66301a6c311SAlfredo Cardigliano 66401a6c311SAlfredo Cardigliano q_base = new->base; 66501a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 66601a6c311SAlfredo Cardigliano 66701a6c311SAlfredo Cardigliano cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE); 66801a6c311SAlfredo Cardigliano cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE); 66901a6c311SAlfredo Cardigliano 67001a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 67101a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 67201a6c311SAlfredo Cardigliano PAGE_SIZE); 67301a6c311SAlfredo Cardigliano sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE); 67401a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 67501a6c311SAlfredo Cardigliano } 67601a6c311SAlfredo Cardigliano 6774ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6784ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 67901a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 68001a6c311SAlfredo Cardigliano 68101a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 68201a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 68301a6c311SAlfredo Cardigliano ionic_cq_bind(&new->cq, &new->q); 68401a6c311SAlfredo Cardigliano 68501a6c311SAlfredo Cardigliano *qcq = new; 68601a6c311SAlfredo Cardigliano 68701a6c311SAlfredo Cardigliano return 0; 68801a6c311SAlfredo Cardigliano 689*4c8f8d57SAndrew Boyer err_out_free_info: 690*4c8f8d57SAndrew Boyer rte_free(new->q.info); 691*4c8f8d57SAndrew Boyer err_out_free_qcq: 692*4c8f8d57SAndrew Boyer rte_free(new); 69301a6c311SAlfredo Cardigliano 69401a6c311SAlfredo Cardigliano return err; 69501a6c311SAlfredo Cardigliano } 69601a6c311SAlfredo Cardigliano 69701a6c311SAlfredo Cardigliano void 69801a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 69901a6c311SAlfredo Cardigliano { 70001a6c311SAlfredo Cardigliano if (qcq->base_z) { 70101a6c311SAlfredo Cardigliano qcq->base = NULL; 70201a6c311SAlfredo Cardigliano qcq->base_pa = 0; 70301a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 70401a6c311SAlfredo Cardigliano qcq->base_z = NULL; 70501a6c311SAlfredo Cardigliano } 70601a6c311SAlfredo Cardigliano 70701a6c311SAlfredo Cardigliano if (qcq->q.info) { 70801a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 70901a6c311SAlfredo Cardigliano qcq->q.info = NULL; 71001a6c311SAlfredo Cardigliano } 71101a6c311SAlfredo Cardigliano 71201a6c311SAlfredo Cardigliano rte_free(qcq); 71301a6c311SAlfredo Cardigliano } 71401a6c311SAlfredo Cardigliano 715a27d9013SAlfredo Cardigliano int 716a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs, 717a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 718a27d9013SAlfredo Cardigliano { 719a27d9013SAlfredo Cardigliano uint32_t flags; 720a27d9013SAlfredo Cardigliano int err = -ENOMEM; 721a27d9013SAlfredo Cardigliano 722a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 723a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags, 724a27d9013SAlfredo Cardigliano nrxq_descs, 725a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 726a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 727a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 7281abf69fcSAndrew Boyer &lif->rxqcqs[index]); 729a27d9013SAlfredo Cardigliano if (err) 730a27d9013SAlfredo Cardigliano return err; 731a27d9013SAlfredo Cardigliano 732a27d9013SAlfredo Cardigliano *qcq = lif->rxqcqs[index]; 733a27d9013SAlfredo Cardigliano 734a27d9013SAlfredo Cardigliano return 0; 735a27d9013SAlfredo Cardigliano } 736a27d9013SAlfredo Cardigliano 737a27d9013SAlfredo Cardigliano int 738a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs, 739a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 740a27d9013SAlfredo Cardigliano { 741a27d9013SAlfredo Cardigliano uint32_t flags; 742a27d9013SAlfredo Cardigliano int err = -ENOMEM; 743a27d9013SAlfredo Cardigliano 744a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 745a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags, 746a27d9013SAlfredo Cardigliano ntxq_descs, 747a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 748a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 749a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_sg_desc), 7501abf69fcSAndrew Boyer &lif->txqcqs[index]); 751a27d9013SAlfredo Cardigliano if (err) 752a27d9013SAlfredo Cardigliano return err; 753a27d9013SAlfredo Cardigliano 754a27d9013SAlfredo Cardigliano *qcq = lif->txqcqs[index]; 755a27d9013SAlfredo Cardigliano 756a27d9013SAlfredo Cardigliano return 0; 757a27d9013SAlfredo Cardigliano } 758a27d9013SAlfredo Cardigliano 75901a6c311SAlfredo Cardigliano static int 76001a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 76101a6c311SAlfredo Cardigliano { 76201a6c311SAlfredo Cardigliano uint32_t flags; 76301a6c311SAlfredo Cardigliano int err = -ENOMEM; 76401a6c311SAlfredo Cardigliano 76501a6c311SAlfredo Cardigliano flags = 0; 76601a6c311SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, 76701a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 76801a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 76901a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 77001a6c311SAlfredo Cardigliano 0, 7711abf69fcSAndrew Boyer &lif->adminqcq); 77227b942c8SAlfredo Cardigliano if (err) 77327b942c8SAlfredo Cardigliano return err; 77401a6c311SAlfredo Cardigliano 77527b942c8SAlfredo Cardigliano return 0; 77627b942c8SAlfredo Cardigliano } 77727b942c8SAlfredo Cardigliano 77827b942c8SAlfredo Cardigliano static int 77927b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 78027b942c8SAlfredo Cardigliano { 781*4c8f8d57SAndrew Boyer struct ionic_qcq *nqcq; 782*4c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 783*4c8f8d57SAndrew Boyer uint32_t flags = 0; 78427b942c8SAlfredo Cardigliano int err = -ENOMEM; 78527b942c8SAlfredo Cardigliano 78627b942c8SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify", 78727b942c8SAlfredo Cardigliano flags, 78827b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 78927b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 79027b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 79127b942c8SAlfredo Cardigliano 0, 792*4c8f8d57SAndrew Boyer &nqcq); 79301a6c311SAlfredo Cardigliano if (err) 79401a6c311SAlfredo Cardigliano return err; 79501a6c311SAlfredo Cardigliano 796*4c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 797*4c8f8d57SAndrew Boyer if (err) { 798*4c8f8d57SAndrew Boyer ionic_qcq_free(nqcq); 799*4c8f8d57SAndrew Boyer return err; 800*4c8f8d57SAndrew Boyer } 801*4c8f8d57SAndrew Boyer 802*4c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 803*4c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 804*4c8f8d57SAndrew Boyer 805*4c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 806*4c8f8d57SAndrew Boyer 80701a6c311SAlfredo Cardigliano return 0; 80801a6c311SAlfredo Cardigliano } 80901a6c311SAlfredo Cardigliano 810c67719e1SAlfredo Cardigliano static void * 811c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num) 812c67719e1SAlfredo Cardigliano { 813c67719e1SAlfredo Cardigliano char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr; 814c67719e1SAlfredo Cardigliano 815c67719e1SAlfredo Cardigliano if (adapter->num_bars <= IONIC_PCI_BAR_DBELL) 816c67719e1SAlfredo Cardigliano return NULL; 817c67719e1SAlfredo Cardigliano 818c67719e1SAlfredo Cardigliano return (void *)&vaddr[page_num << PAGE_SHIFT]; 819c67719e1SAlfredo Cardigliano } 820c67719e1SAlfredo Cardigliano 821669c8de6SAlfredo Cardigliano int 822669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 823669c8de6SAlfredo Cardigliano { 824c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 825669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 82601a6c311SAlfredo Cardigliano int err; 827669c8de6SAlfredo Cardigliano 8284ae96cb8SAndrew Boyer /* 8294ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 8304ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 8314ae96cb8SAndrew Boyer */ 8324ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 8334ae96cb8SAndrew Boyer 8344ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 835669c8de6SAlfredo Cardigliano 836669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 837669c8de6SAlfredo Cardigliano 83801a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 83901a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 84001a6c311SAlfredo Cardigliano 84100b65da5SAndrew Boyer lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0); 842c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 843c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 844c67719e1SAlfredo Cardigliano return -ENOMEM; 845c67719e1SAlfredo Cardigliano } 846c67719e1SAlfredo Cardigliano 847a27d9013SAlfredo Cardigliano lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) * 848a27d9013SAlfredo Cardigliano adapter->max_ntxqs_per_lif, 0); 849a27d9013SAlfredo Cardigliano 850a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 851a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 852a27d9013SAlfredo Cardigliano return -ENOMEM; 853a27d9013SAlfredo Cardigliano } 854a27d9013SAlfredo Cardigliano 855a27d9013SAlfredo Cardigliano lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) * 856a27d9013SAlfredo Cardigliano adapter->max_nrxqs_per_lif, 0); 857a27d9013SAlfredo Cardigliano 858a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 859a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 860a27d9013SAlfredo Cardigliano return -ENOMEM; 861a27d9013SAlfredo Cardigliano } 862a27d9013SAlfredo Cardigliano 86327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 86427b942c8SAlfredo Cardigliano 86527b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 86627b942c8SAlfredo Cardigliano if (err) { 86727b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 86827b942c8SAlfredo Cardigliano return err; 86927b942c8SAlfredo Cardigliano } 87027b942c8SAlfredo Cardigliano 87127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 87227b942c8SAlfredo Cardigliano 87301a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 87401a6c311SAlfredo Cardigliano if (err) { 87501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 87601a6c311SAlfredo Cardigliano return err; 87701a6c311SAlfredo Cardigliano } 87801a6c311SAlfredo Cardigliano 87901a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 88001a6c311SAlfredo Cardigliano 881669c8de6SAlfredo Cardigliano lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); 882669c8de6SAlfredo Cardigliano 883669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 884669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 885669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 886669c8de6SAlfredo Cardigliano if (!lif->info_z) { 887669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 888669c8de6SAlfredo Cardigliano return -ENOMEM; 889669c8de6SAlfredo Cardigliano } 890669c8de6SAlfredo Cardigliano 891669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 892669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 893669c8de6SAlfredo Cardigliano 894669c8de6SAlfredo Cardigliano return 0; 895669c8de6SAlfredo Cardigliano } 896669c8de6SAlfredo Cardigliano 897669c8de6SAlfredo Cardigliano void 898669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 899669c8de6SAlfredo Cardigliano { 90027b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 90127b942c8SAlfredo Cardigliano ionic_qcq_free(lif->notifyqcq); 90227b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 90327b942c8SAlfredo Cardigliano } 90427b942c8SAlfredo Cardigliano 90501a6c311SAlfredo Cardigliano if (lif->adminqcq) { 90601a6c311SAlfredo Cardigliano ionic_qcq_free(lif->adminqcq); 90701a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 90801a6c311SAlfredo Cardigliano } 90901a6c311SAlfredo Cardigliano 910a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 911a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 912a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 913a27d9013SAlfredo Cardigliano } 914a27d9013SAlfredo Cardigliano 915a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 916a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 917a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 918a27d9013SAlfredo Cardigliano } 919a27d9013SAlfredo Cardigliano 920669c8de6SAlfredo Cardigliano if (lif->info) { 921669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 922669c8de6SAlfredo Cardigliano lif->info = NULL; 923669c8de6SAlfredo Cardigliano } 924669c8de6SAlfredo Cardigliano } 925669c8de6SAlfredo Cardigliano 926175e4e7eSAndrew Boyer void 927175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 928175e4e7eSAndrew Boyer { 929175e4e7eSAndrew Boyer uint32_t i; 930175e4e7eSAndrew Boyer 931175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 932175e4e7eSAndrew Boyer ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]); 933175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 934175e4e7eSAndrew Boyer } 935175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 936175e4e7eSAndrew Boyer ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]); 937175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 938175e4e7eSAndrew Boyer } 939175e4e7eSAndrew Boyer } 940175e4e7eSAndrew Boyer 94122e7171bSAlfredo Cardigliano int 94222e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 94322e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 94422e7171bSAlfredo Cardigliano { 94522e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 94622e7171bSAlfredo Cardigliano .pending_work = true, 94722e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 94822e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 94922e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 95022e7171bSAlfredo Cardigliano .rss.types = types, 95122e7171bSAlfredo Cardigliano .rss.addr = lif->rss_ind_tbl_pa, 95222e7171bSAlfredo Cardigliano }, 95322e7171bSAlfredo Cardigliano }; 95422e7171bSAlfredo Cardigliano unsigned int i; 95522e7171bSAlfredo Cardigliano 95622e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 95722e7171bSAlfredo Cardigliano 95822e7171bSAlfredo Cardigliano lif->rss_types = types; 95922e7171bSAlfredo Cardigliano 96022e7171bSAlfredo Cardigliano if (key) 96122e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 96222e7171bSAlfredo Cardigliano 96322e7171bSAlfredo Cardigliano if (indir) 96422e7171bSAlfredo Cardigliano for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++) 96522e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 96622e7171bSAlfredo Cardigliano 96722e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 96822e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 96922e7171bSAlfredo Cardigliano 97022e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 97122e7171bSAlfredo Cardigliano } 97222e7171bSAlfredo Cardigliano 97322e7171bSAlfredo Cardigliano static int 97422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 97522e7171bSAlfredo Cardigliano { 97622e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 97722e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 97822e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 97922e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98222e7171bSAlfredo Cardigliano }; 98322e7171bSAlfredo Cardigliano uint32_t i; 9843d845eddSAndrew Boyer uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz; 98522e7171bSAlfredo Cardigliano 98622e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 98722e7171bSAlfredo Cardigliano 9883d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 98922e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 9903d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 9913d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 9923d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 99322e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 99422e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 99522e7171bSAlfredo Cardigliano return -ENOMEM; 99622e7171bSAlfredo Cardigliano } 99722e7171bSAlfredo Cardigliano 99822e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 99922e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 10003d845eddSAndrew Boyer } 10013d845eddSAndrew Boyer 10023d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 10033d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 100422e7171bSAlfredo Cardigliano 100522e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 10063d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 100722e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 10083d845eddSAndrew Boyer } 100922e7171bSAlfredo Cardigliano 10103d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 101122e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 101222e7171bSAlfredo Cardigliano } 101322e7171bSAlfredo Cardigliano 101422e7171bSAlfredo Cardigliano static void 101522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 101622e7171bSAlfredo Cardigliano { 101722e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 101822e7171bSAlfredo Cardigliano return; 101922e7171bSAlfredo Cardigliano 102022e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 102122e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 102222e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 102322e7171bSAlfredo Cardigliano 102422e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 102522e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 102622e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 102722e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 102822e7171bSAlfredo Cardigliano } 102922e7171bSAlfredo Cardigliano } 103022e7171bSAlfredo Cardigliano 103101a6c311SAlfredo Cardigliano static void 1032*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq) 103301a6c311SAlfredo Cardigliano { 103401a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 103501a6c311SAlfredo Cardigliano } 103601a6c311SAlfredo Cardigliano 1037a27d9013SAlfredo Cardigliano void 1038a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq) 1039a27d9013SAlfredo Cardigliano { 1040*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 1041a27d9013SAlfredo Cardigliano } 1042a27d9013SAlfredo Cardigliano 1043a27d9013SAlfredo Cardigliano void 1044a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq) 1045a27d9013SAlfredo Cardigliano { 1046*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 1047*4c8f8d57SAndrew Boyer } 1048*4c8f8d57SAndrew Boyer 1049*4c8f8d57SAndrew Boyer static void 1050*4c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 1051*4c8f8d57SAndrew Boyer { 1052*4c8f8d57SAndrew Boyer struct ionic_qcq *nqcq = lif->notifyqcq; 1053*4c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 1054*4c8f8d57SAndrew Boyer 1055*4c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 1056*4c8f8d57SAndrew Boyer return; 1057*4c8f8d57SAndrew Boyer 1058*4c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 1059*4c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 1060*4c8f8d57SAndrew Boyer 1061*4c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1062a27d9013SAlfredo Cardigliano } 1063a27d9013SAlfredo Cardigliano 106401a6c311SAlfredo Cardigliano bool 106501a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index, 106601a6c311SAlfredo Cardigliano void *cb_arg __rte_unused) 106701a6c311SAlfredo Cardigliano { 106801a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc_base = cq->base; 106901a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index]; 107001a6c311SAlfredo Cardigliano 107101a6c311SAlfredo Cardigliano if (!color_match(cq_desc->color, cq->done_color)) 107201a6c311SAlfredo Cardigliano return false; 107301a6c311SAlfredo Cardigliano 107401a6c311SAlfredo Cardigliano ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL); 107501a6c311SAlfredo Cardigliano 107601a6c311SAlfredo Cardigliano return true; 107701a6c311SAlfredo Cardigliano } 107801a6c311SAlfredo Cardigliano 107901a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 108001a6c311SAlfredo Cardigliano int 108101a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 108201a6c311SAlfredo Cardigliano void *cb_arg) 108301a6c311SAlfredo Cardigliano { 108401a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 108501a6c311SAlfredo Cardigliano uint32_t work_done; 108601a6c311SAlfredo Cardigliano 108701a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 108801a6c311SAlfredo Cardigliano 108901a6c311SAlfredo Cardigliano return work_done; 109001a6c311SAlfredo Cardigliano } 109101a6c311SAlfredo Cardigliano 109227b942c8SAlfredo Cardigliano static void 109327b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 109427b942c8SAlfredo Cardigliano { 109527b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 109627b942c8SAlfredo Cardigliano bool link_up; 109727b942c8SAlfredo Cardigliano 109827b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 109927b942c8SAlfredo Cardigliano 110027b942c8SAlfredo Cardigliano if (!lif->info) 110127b942c8SAlfredo Cardigliano return; 110227b942c8SAlfredo Cardigliano 110327b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 110427b942c8SAlfredo Cardigliano 110527b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 110627b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 110727b942c8SAlfredo Cardigliano return; 110827b942c8SAlfredo Cardigliano 110927b942c8SAlfredo Cardigliano if (link_up) { 111027b942c8SAlfredo Cardigliano adapter->link_speed = lif->info->status.link_speed; 1111be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1112be63459eSAndrew Boyer adapter->link_speed); 111327b942c8SAlfredo Cardigliano } else { 111427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 111527b942c8SAlfredo Cardigliano } 111627b942c8SAlfredo Cardigliano 111727b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1118be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1119be63459eSAndrew Boyer } 1120be63459eSAndrew Boyer 1121be63459eSAndrew Boyer static void 1122be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1123be63459eSAndrew Boyer { 1124be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1125be63459eSAndrew Boyer return; 1126be63459eSAndrew Boyer 1127be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1128be63459eSAndrew Boyer 1129be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1130be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1131be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1132be63459eSAndrew Boyer ionic_lif_stop(lif); 1133be63459eSAndrew Boyer } 1134be63459eSAndrew Boyer 1135be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 113627b942c8SAlfredo Cardigliano } 113727b942c8SAlfredo Cardigliano 113827b942c8SAlfredo Cardigliano static bool 113927b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 114027b942c8SAlfredo Cardigliano { 114127b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 114227b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 114327b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 114427b942c8SAlfredo Cardigliano 114527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 114627b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 114727b942c8SAlfredo Cardigliano 114827b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 114927b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 115027b942c8SAlfredo Cardigliano return false; 115127b942c8SAlfredo Cardigliano 115227b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 115327b942c8SAlfredo Cardigliano 115427b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 115527b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 115627b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1157be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1158be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1159be63459eSAndrew Boyer lif->name, 116027b942c8SAlfredo Cardigliano cq_desc->event.eid, 116127b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 116227b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 116327b942c8SAlfredo Cardigliano 116427b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 116527b942c8SAlfredo Cardigliano break; 1166be63459eSAndrew Boyer 1167be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1168be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1169be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1170be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1171be63459eSAndrew Boyer lif->name, 1172be63459eSAndrew Boyer cq_desc->event.eid, 1173be63459eSAndrew Boyer cq_desc->reset.reset_code, 1174be63459eSAndrew Boyer cq_desc->reset.state); 1175be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1176be63459eSAndrew Boyer break; 1177be63459eSAndrew Boyer 117827b942c8SAlfredo Cardigliano default: 117927b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 118027b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 118127b942c8SAlfredo Cardigliano break; 118227b942c8SAlfredo Cardigliano } 118327b942c8SAlfredo Cardigliano 118427b942c8SAlfredo Cardigliano return true; 118527b942c8SAlfredo Cardigliano } 118627b942c8SAlfredo Cardigliano 118727b942c8SAlfredo Cardigliano int 118827b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 118927b942c8SAlfredo Cardigliano { 119027b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 119127b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 119227b942c8SAlfredo Cardigliano uint32_t work_done; 119327b942c8SAlfredo Cardigliano 119427b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 119527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 119627b942c8SAlfredo Cardigliano return -1; 119727b942c8SAlfredo Cardigliano } 119827b942c8SAlfredo Cardigliano 119927b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 120027b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 120127b942c8SAlfredo Cardigliano 120227b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 120327b942c8SAlfredo Cardigliano 120427b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 120527b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 120627b942c8SAlfredo Cardigliano 120727b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 120827b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 120927b942c8SAlfredo Cardigliano 121027b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 121127b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 121227b942c8SAlfredo Cardigliano 121327b942c8SAlfredo Cardigliano return 0; 121427b942c8SAlfredo Cardigliano } 121527b942c8SAlfredo Cardigliano 121601a6c311SAlfredo Cardigliano static int 121701a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 121801a6c311SAlfredo Cardigliano { 121901a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 122001a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 122101a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 122201a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 122301a6c311SAlfredo Cardigliano int err; 122401a6c311SAlfredo Cardigliano 1225*4c8f8d57SAndrew Boyer ionic_dev_cmd_adminq_init(idev, qcq); 122601a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 122701a6c311SAlfredo Cardigliano if (err) 122801a6c311SAlfredo Cardigliano return err; 122901a6c311SAlfredo Cardigliano 123001a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 123101a6c311SAlfredo Cardigliano 123201a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 123301a6c311SAlfredo Cardigliano q->hw_index = comp.hw_index; 123401a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 123501a6c311SAlfredo Cardigliano 123601a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 123701a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 123801a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 123901a6c311SAlfredo Cardigliano 124001a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 124101a6c311SAlfredo Cardigliano 124201a6c311SAlfredo Cardigliano return 0; 124301a6c311SAlfredo Cardigliano } 124401a6c311SAlfredo Cardigliano 124527b942c8SAlfredo Cardigliano static int 124627b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 124727b942c8SAlfredo Cardigliano { 124827b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 124927b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 125027b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 125127b942c8SAlfredo Cardigliano int err; 125227b942c8SAlfredo Cardigliano 125327b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 125427b942c8SAlfredo Cardigliano .pending_work = true, 125527b942c8SAlfredo Cardigliano .cmd.q_init = { 125627b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 125727b942c8SAlfredo Cardigliano .type = q->type, 125827b942c8SAlfredo Cardigliano .index = q->index, 125927b942c8SAlfredo Cardigliano .flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA), 126027b942c8SAlfredo Cardigliano .intr_index = qcq->intr.index, 126127b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 126227b942c8SAlfredo Cardigliano .ring_base = q->base_pa, 126327b942c8SAlfredo Cardigliano } 126427b942c8SAlfredo Cardigliano }; 126527b942c8SAlfredo Cardigliano 126627b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.index %d", 126727b942c8SAlfredo Cardigliano ctx.cmd.q_init.index); 126827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", 126927b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 127027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 127127b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 12724ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 127327b942c8SAlfredo Cardigliano 127427b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 127527b942c8SAlfredo Cardigliano if (err) 127627b942c8SAlfredo Cardigliano return err; 127727b942c8SAlfredo Cardigliano 127827b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 127927b942c8SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 128027b942c8SAlfredo Cardigliano q->db = NULL; 128127b942c8SAlfredo Cardigliano 128227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 128327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 128427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 128527b942c8SAlfredo Cardigliano 128627b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 128727b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 128827b942c8SAlfredo Cardigliano 128927b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 129027b942c8SAlfredo Cardigliano 129127b942c8SAlfredo Cardigliano return 0; 129227b942c8SAlfredo Cardigliano } 129327b942c8SAlfredo Cardigliano 1294669c8de6SAlfredo Cardigliano int 1295598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1296598f6726SAlfredo Cardigliano { 1297598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1298598f6726SAlfredo Cardigliano .pending_work = true, 1299598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1300598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1301598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 1302598f6726SAlfredo Cardigliano .features = lif->features, 1303598f6726SAlfredo Cardigliano }, 1304598f6726SAlfredo Cardigliano }; 1305598f6726SAlfredo Cardigliano int err; 1306598f6726SAlfredo Cardigliano 1307598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1308598f6726SAlfredo Cardigliano if (err) 1309598f6726SAlfredo Cardigliano return err; 1310598f6726SAlfredo Cardigliano 1311598f6726SAlfredo Cardigliano lif->hw_features = (ctx.cmd.lif_setattr.features & 1312598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1313598f6726SAlfredo Cardigliano 1314598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1315598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1316598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1317598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1318598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1319598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1320598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1321598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1322598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1323598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1324598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1325598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1326598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1327598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1328598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1329598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1330598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1331598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1332598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1333598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1334598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1335598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1336598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1337598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1338598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1339598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1340598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1341598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1342598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1343598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1344598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1345598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1346598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1347598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1348598f6726SAlfredo Cardigliano 1349598f6726SAlfredo Cardigliano return 0; 1350598f6726SAlfredo Cardigliano } 1351598f6726SAlfredo Cardigliano 1352a27d9013SAlfredo Cardigliano int 1353a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq) 1354a27d9013SAlfredo Cardigliano { 1355a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1356a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1357a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1358a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1359a27d9013SAlfredo Cardigliano .pending_work = true, 1360a27d9013SAlfredo Cardigliano .cmd.q_init = { 1361a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1362a27d9013SAlfredo Cardigliano .type = q->type, 1363a27d9013SAlfredo Cardigliano .index = q->index, 1364b5d9a4f0SAndrew Boyer .flags = IONIC_QINIT_F_SG | IONIC_QINIT_F_ENA, 1365*4c8f8d57SAndrew Boyer .intr_index = IONIC_INTR_NONE, 1366a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1367a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1368a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1369a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1370a27d9013SAlfredo Cardigliano }, 1371a27d9013SAlfredo Cardigliano }; 1372a27d9013SAlfredo Cardigliano int err; 1373a27d9013SAlfredo Cardigliano 1374a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index); 1375a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", 1376a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1377a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1378a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13794ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1380a27d9013SAlfredo Cardigliano 1381a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1382a27d9013SAlfredo Cardigliano if (err) 1383a27d9013SAlfredo Cardigliano return err; 1384a27d9013SAlfredo Cardigliano 1385a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1386a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1387a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1388a27d9013SAlfredo Cardigliano 1389a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1390a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1391a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1392a27d9013SAlfredo Cardigliano 1393a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1394a27d9013SAlfredo Cardigliano 1395a27d9013SAlfredo Cardigliano return 0; 1396a27d9013SAlfredo Cardigliano } 1397a27d9013SAlfredo Cardigliano 1398a27d9013SAlfredo Cardigliano int 1399a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq) 1400a27d9013SAlfredo Cardigliano { 1401a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1402a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1403a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1404a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1405a27d9013SAlfredo Cardigliano .pending_work = true, 1406a27d9013SAlfredo Cardigliano .cmd.q_init = { 1407a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1408a27d9013SAlfredo Cardigliano .type = q->type, 1409a27d9013SAlfredo Cardigliano .index = q->index, 1410b5d9a4f0SAndrew Boyer .flags = IONIC_QINIT_F_SG | IONIC_QINIT_F_ENA, 1411*4c8f8d57SAndrew Boyer .intr_index = IONIC_INTR_NONE, 1412a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1413a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1414a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1415a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1416a27d9013SAlfredo Cardigliano }, 1417a27d9013SAlfredo Cardigliano }; 1418a27d9013SAlfredo Cardigliano int err; 1419a27d9013SAlfredo Cardigliano 1420a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index); 1421a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", 1422a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1423a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1424a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14254ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1426a27d9013SAlfredo Cardigliano 1427a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1428a27d9013SAlfredo Cardigliano if (err) 1429a27d9013SAlfredo Cardigliano return err; 1430a27d9013SAlfredo Cardigliano 1431a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1432a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1433a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1434a27d9013SAlfredo Cardigliano 1435a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1436a27d9013SAlfredo Cardigliano 1437a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1438a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1439a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1440a27d9013SAlfredo Cardigliano 1441a27d9013SAlfredo Cardigliano return 0; 1442a27d9013SAlfredo Cardigliano } 1443a27d9013SAlfredo Cardigliano 1444598f6726SAlfredo Cardigliano static int 1445598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1446598f6726SAlfredo Cardigliano { 1447598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1448598f6726SAlfredo Cardigliano .pending_work = true, 1449598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1450598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1451598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1452598f6726SAlfredo Cardigliano }, 1453598f6726SAlfredo Cardigliano }; 1454598f6726SAlfredo Cardigliano int err; 1455598f6726SAlfredo Cardigliano 1456598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1457598f6726SAlfredo Cardigliano 1458598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1459598f6726SAlfredo Cardigliano if (err) 1460598f6726SAlfredo Cardigliano return err; 1461598f6726SAlfredo Cardigliano 1462598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1463598f6726SAlfredo Cardigliano 1464598f6726SAlfredo Cardigliano return 0; 1465598f6726SAlfredo Cardigliano } 1466598f6726SAlfredo Cardigliano 1467598f6726SAlfredo Cardigliano static void 1468598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1469598f6726SAlfredo Cardigliano { 1470598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1471598f6726SAlfredo Cardigliano .pending_work = true, 1472598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1473598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1474598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1475598f6726SAlfredo Cardigliano }, 1476598f6726SAlfredo Cardigliano }; 1477598f6726SAlfredo Cardigliano 14784ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 14794ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1480598f6726SAlfredo Cardigliano 1481598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1482598f6726SAlfredo Cardigliano } 1483598f6726SAlfredo Cardigliano 1484598f6726SAlfredo Cardigliano int 1485669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1486669c8de6SAlfredo Cardigliano { 1487669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1488669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 1489669c8de6SAlfredo Cardigliano int err; 1490669c8de6SAlfredo Cardigliano 14913cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 14923cdfd905SAlfredo Cardigliano 149300b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1494669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1495669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 1496669c8de6SAlfredo Cardigliano if (err) 1497669c8de6SAlfredo Cardigliano return err; 1498669c8de6SAlfredo Cardigliano 1499669c8de6SAlfredo Cardigliano lif->hw_index = comp.hw_index; 1500669c8de6SAlfredo Cardigliano 150101a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 150201a6c311SAlfredo Cardigliano if (err) 150301a6c311SAlfredo Cardigliano return err; 150401a6c311SAlfredo Cardigliano 150527b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 150627b942c8SAlfredo Cardigliano if (err) 150727b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 150827b942c8SAlfredo Cardigliano 150918a44465SAndrew Boyer /* 151018a44465SAndrew Boyer * Configure initial feature set 151118a44465SAndrew Boyer * This will be updated later by the dev_configure() step 151218a44465SAndrew Boyer */ 151318a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1514598f6726SAlfredo Cardigliano 1515598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1516598f6726SAlfredo Cardigliano if (err) 1517598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1518598f6726SAlfredo Cardigliano 151954fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1520598f6726SAlfredo Cardigliano if (err) 1521598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1522598f6726SAlfredo Cardigliano 152354fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 152454fe083fSAlfredo Cardigliano if (err) 152554fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 152654fe083fSAlfredo Cardigliano 1527598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1528598f6726SAlfredo Cardigliano 1529669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1530669c8de6SAlfredo Cardigliano 1531669c8de6SAlfredo Cardigliano return 0; 153227b942c8SAlfredo Cardigliano 153354fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 153454fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 153554fe083fSAlfredo Cardigliano 1536598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 1537*4c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1538598f6726SAlfredo Cardigliano 153927b942c8SAlfredo Cardigliano err_out_adminq_deinit: 1540*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 154127b942c8SAlfredo Cardigliano 154227b942c8SAlfredo Cardigliano return err; 1543669c8de6SAlfredo Cardigliano } 1544669c8de6SAlfredo Cardigliano 1545669c8de6SAlfredo Cardigliano void 1546669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1547669c8de6SAlfredo Cardigliano { 1548669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1549669c8de6SAlfredo Cardigliano return; 1550669c8de6SAlfredo Cardigliano 155154fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 155222e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 1553*4c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1554*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 155501a6c311SAlfredo Cardigliano 1556669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1557669c8de6SAlfredo Cardigliano } 1558669c8de6SAlfredo Cardigliano 155918a44465SAndrew Boyer void 156018a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 156118a44465SAndrew Boyer { 156218a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 156318a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 156418a44465SAndrew Boyer 156518a44465SAndrew Boyer /* 156618a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 156718a44465SAndrew Boyer * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK 156818a44465SAndrew Boyer */ 156918a44465SAndrew Boyer rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 157018a44465SAndrew Boyer 157118a44465SAndrew Boyer if (mask & ETH_VLAN_STRIP_MASK) { 157218a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) 157318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 157418a44465SAndrew Boyer else 157518a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 157618a44465SAndrew Boyer } 157718a44465SAndrew Boyer } 157818a44465SAndrew Boyer 157918a44465SAndrew Boyer void 1580598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1581598f6726SAlfredo Cardigliano { 158218a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 158318a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 158422e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 158522e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 158622e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 158722e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 158822e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 158922e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 159022e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 159122e7171bSAlfredo Cardigliano 1592598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1593598f6726SAlfredo Cardigliano 159422e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 159522e7171bSAlfredo Cardigliano lif->port_id); 159622e7171bSAlfredo Cardigliano 159722e7171bSAlfredo Cardigliano if (nrxqs > 0) 159822e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 159922e7171bSAlfredo Cardigliano 160022e7171bSAlfredo Cardigliano if (ntxqs > 0) 160122e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 160222e7171bSAlfredo Cardigliano 160322e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 160422e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1605a27d9013SAlfredo Cardigliano 160618a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 160718a44465SAndrew Boyer 160818a44465SAndrew Boyer /* 160918a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 161018a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 161118a44465SAndrew Boyer * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH; 161218a44465SAndrew Boyer */ 161318a44465SAndrew Boyer 161418a44465SAndrew Boyer /* RX per-port */ 161518a44465SAndrew Boyer 161618a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM || 161718a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM || 161818a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM) 161918a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 162018a44465SAndrew Boyer else 162118a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 162218a44465SAndrew Boyer 162318a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) { 162418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 162518a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 162618a44465SAndrew Boyer } else { 162718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 162818a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 162918a44465SAndrew Boyer } 163018a44465SAndrew Boyer 163118a44465SAndrew Boyer /* Covers VLAN_STRIP */ 163218a44465SAndrew Boyer ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK); 163318a44465SAndrew Boyer 163418a44465SAndrew Boyer /* TX per-port */ 163518a44465SAndrew Boyer 163618a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM || 163718a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM || 163818a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM || 163918a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM || 164018a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) 164118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 164218a44465SAndrew Boyer else 164318a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 164418a44465SAndrew Boyer 164518a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT) 164618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 164718a44465SAndrew Boyer else 164818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 164918a44465SAndrew Boyer 165018a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS) 165118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 165218a44465SAndrew Boyer else 165318a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 165418a44465SAndrew Boyer 165518a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) { 165618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 165718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 165818a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 165918a44465SAndrew Boyer } else { 166018a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 166118a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 166218a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 166318a44465SAndrew Boyer } 1664598f6726SAlfredo Cardigliano } 1665598f6726SAlfredo Cardigliano 1666598f6726SAlfredo Cardigliano int 1667598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1668598f6726SAlfredo Cardigliano { 16690578335aSAndrew Boyer uint32_t rx_mode; 1670a27d9013SAlfredo Cardigliano uint32_t i; 1671a27d9013SAlfredo Cardigliano int err; 1672598f6726SAlfredo Cardigliano 167322e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 167422e7171bSAlfredo Cardigliano if (err) 167522e7171bSAlfredo Cardigliano return err; 167622e7171bSAlfredo Cardigliano 16770578335aSAndrew Boyer if (!lif->rx_mode) { 16780578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 16790578335aSAndrew Boyer lif->name); 1680598f6726SAlfredo Cardigliano 16810578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1682598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1683598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1684598f6726SAlfredo Cardigliano 1685598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 16860578335aSAndrew Boyer } 1687598f6726SAlfredo Cardigliano 1688a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1689a27d9013SAlfredo Cardigliano "on port %u", 1690a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1691a27d9013SAlfredo Cardigliano 1692a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1693a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = lif->rxqcqs[i]; 169402eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1695a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1696a27d9013SAlfredo Cardigliano 1697a27d9013SAlfredo Cardigliano if (err) 1698a27d9013SAlfredo Cardigliano return err; 1699a27d9013SAlfredo Cardigliano } 1700a27d9013SAlfredo Cardigliano } 1701a27d9013SAlfredo Cardigliano 1702a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1703a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = lif->txqcqs[i]; 170402eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1705a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1706a27d9013SAlfredo Cardigliano 1707a27d9013SAlfredo Cardigliano if (err) 1708a27d9013SAlfredo Cardigliano return err; 1709a27d9013SAlfredo Cardigliano } 1710a27d9013SAlfredo Cardigliano } 1711a27d9013SAlfredo Cardigliano 1712598f6726SAlfredo Cardigliano /* Carrier ON here */ 1713be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1714be63459eSAndrew Boyer 1715be63459eSAndrew Boyer ionic_link_status_check(lif); 1716598f6726SAlfredo Cardigliano 1717598f6726SAlfredo Cardigliano return 0; 1718598f6726SAlfredo Cardigliano } 1719598f6726SAlfredo Cardigliano 1720598f6726SAlfredo Cardigliano int 1721669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1722669c8de6SAlfredo Cardigliano { 1723669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1724669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1725669c8de6SAlfredo Cardigliano int err; 1726669c8de6SAlfredo Cardigliano unsigned int i; 1727669c8de6SAlfredo Cardigliano unsigned int lif_words = sizeof(ident->lif.words) / 1728669c8de6SAlfredo Cardigliano sizeof(ident->lif.words[0]); 1729669c8de6SAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 1730669c8de6SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 1731669c8de6SAlfredo Cardigliano unsigned int nwords; 1732669c8de6SAlfredo Cardigliano 1733669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1734669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1735669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1736669c8de6SAlfredo Cardigliano if (err) 1737669c8de6SAlfredo Cardigliano return (err); 1738669c8de6SAlfredo Cardigliano 1739669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1740669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1741669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1742669c8de6SAlfredo Cardigliano 1743669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 1744669c8de6SAlfredo Cardigliano ident->lif.capabilities); 1745669c8de6SAlfredo Cardigliano 1746669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 1747669c8de6SAlfredo Cardigliano ident->lif.eth.max_ucast_filters); 1748669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 1749669c8de6SAlfredo Cardigliano ident->lif.eth.max_mcast_filters); 1750669c8de6SAlfredo Cardigliano 1751669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 1752669c8de6SAlfredo Cardigliano ident->lif.eth.config.features); 1753669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 1754669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]); 1755669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 1756669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]); 1757669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 1758669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 1759669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 1760669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 1761669c8de6SAlfredo Cardigliano 1762669c8de6SAlfredo Cardigliano return 0; 1763669c8de6SAlfredo Cardigliano } 1764669c8de6SAlfredo Cardigliano 1765669c8de6SAlfredo Cardigliano int 1766669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1767669c8de6SAlfredo Cardigliano { 1768669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1769669c8de6SAlfredo Cardigliano uint32_t nintrs, dev_nintrs = ident->dev.nintrs; 1770669c8de6SAlfredo Cardigliano 1771669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 1772669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 1773669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 1774669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 1775669c8de6SAlfredo Cardigliano 177600b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1777669c8de6SAlfredo Cardigliano 1778669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 17794ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 17804ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1781669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1782669c8de6SAlfredo Cardigliano return -ENOSPC; 1783669c8de6SAlfredo Cardigliano } 1784669c8de6SAlfredo Cardigliano 1785669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1786669c8de6SAlfredo Cardigliano 1787669c8de6SAlfredo Cardigliano return 0; 1788669c8de6SAlfredo Cardigliano } 1789