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, 28*09f806e9SAndrew Boyer .index = rte_cpu_to_le_32(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, 46*09f806e9SAndrew Boyer .index = rte_cpu_to_le_32(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, 244*09f806e9SAndrew Boyer .match = rte_cpu_to_le_16(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)", 256*09f806e9SAndrew Boyer rte_le_to_cpu_32(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 283*09f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(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)", 293*09f806e9SAndrew Boyer rte_le_to_cpu_32(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, 367*09f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN), 368*09f806e9SAndrew Boyer .vlan.vlan = rte_cpu_to_le_16(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, 378*09f806e9SAndrew Boyer rte_le_to_cpu_32(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 405*09f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(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, 414*09f806e9SAndrew Boyer rte_le_to_cpu_32(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, 441*09f806e9SAndrew Boyer .rx_mode = rte_cpu_to_le_16(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, 533*09f806e9SAndrew Boyer .mtu = rte_cpu_to_le_32(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 { 5754c8f8d57SAndrew 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"); 6314c8f8d57SAndrew Boyer err = -ENOMEM; 6324c8f8d57SAndrew 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"); 6414c8f8d57SAndrew Boyer goto err_out_free_info; 64201a6c311SAlfredo Cardigliano } 64301a6c311SAlfredo Cardigliano 6444c8f8d57SAndrew 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"); 6474c8f8d57SAndrew 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; 6574c8f8d57SAndrew 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 6894c8f8d57SAndrew Boyer err_out_free_info: 6904c8f8d57SAndrew Boyer rte_free(new->q.info); 6914c8f8d57SAndrew Boyer err_out_free_qcq: 6924c8f8d57SAndrew 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 { 7814c8f8d57SAndrew Boyer struct ionic_qcq *nqcq; 7824c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 7834c8f8d57SAndrew 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, 7924c8f8d57SAndrew Boyer &nqcq); 79301a6c311SAlfredo Cardigliano if (err) 79401a6c311SAlfredo Cardigliano return err; 79501a6c311SAlfredo Cardigliano 7964c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 7974c8f8d57SAndrew Boyer if (err) { 7984c8f8d57SAndrew Boyer ionic_qcq_free(nqcq); 7994c8f8d57SAndrew Boyer return err; 8004c8f8d57SAndrew Boyer } 8014c8f8d57SAndrew Boyer 8024c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 8034c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 8044c8f8d57SAndrew Boyer 8054c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 8064c8f8d57SAndrew 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 { 945*09f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 94622e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 94722e7171bSAlfredo Cardigliano .pending_work = true, 94822e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 94922e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 95022e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 951*09f806e9SAndrew Boyer .rss.types = rte_cpu_to_le_16(types), 952*09f806e9SAndrew Boyer .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa), 95322e7171bSAlfredo Cardigliano }, 95422e7171bSAlfredo Cardigliano }; 95522e7171bSAlfredo Cardigliano unsigned int i; 956*09f806e9SAndrew Boyer uint16_t tbl_sz = 957*09f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 95822e7171bSAlfredo Cardigliano 95922e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 96022e7171bSAlfredo Cardigliano 96122e7171bSAlfredo Cardigliano lif->rss_types = types; 96222e7171bSAlfredo Cardigliano 96322e7171bSAlfredo Cardigliano if (key) 96422e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 96522e7171bSAlfredo Cardigliano 96622e7171bSAlfredo Cardigliano if (indir) 967*09f806e9SAndrew Boyer for (i = 0; i < tbl_sz; i++) 96822e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 96922e7171bSAlfredo Cardigliano 97022e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 97122e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 97222e7171bSAlfredo Cardigliano 97322e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 97422e7171bSAlfredo Cardigliano } 97522e7171bSAlfredo Cardigliano 97622e7171bSAlfredo Cardigliano static int 97722e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 97822e7171bSAlfredo Cardigliano { 979*09f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 98022e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 98122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98322e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98422e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98522e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98622e7171bSAlfredo Cardigliano }; 98722e7171bSAlfredo Cardigliano uint32_t i; 988*09f806e9SAndrew Boyer uint16_t tbl_sz = 989*09f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 99022e7171bSAlfredo Cardigliano 99122e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 99222e7171bSAlfredo Cardigliano 9933d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 99422e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 9953d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 9963d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 9973d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 99822e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 99922e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 100022e7171bSAlfredo Cardigliano return -ENOMEM; 100122e7171bSAlfredo Cardigliano } 100222e7171bSAlfredo Cardigliano 100322e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 100422e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 10053d845eddSAndrew Boyer } 10063d845eddSAndrew Boyer 10073d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 10083d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 100922e7171bSAlfredo Cardigliano 101022e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 10113d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 101222e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 10133d845eddSAndrew Boyer } 101422e7171bSAlfredo Cardigliano 10153d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 101622e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 101722e7171bSAlfredo Cardigliano } 101822e7171bSAlfredo Cardigliano 101922e7171bSAlfredo Cardigliano static void 102022e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 102122e7171bSAlfredo Cardigliano { 102222e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 102322e7171bSAlfredo Cardigliano return; 102422e7171bSAlfredo Cardigliano 102522e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 102622e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 102722e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 102822e7171bSAlfredo Cardigliano 102922e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 103022e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 103122e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 103222e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 103322e7171bSAlfredo Cardigliano } 103422e7171bSAlfredo Cardigliano } 103522e7171bSAlfredo Cardigliano 103601a6c311SAlfredo Cardigliano static void 10374c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq) 103801a6c311SAlfredo Cardigliano { 103901a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 104001a6c311SAlfredo Cardigliano } 104101a6c311SAlfredo Cardigliano 1042a27d9013SAlfredo Cardigliano void 1043a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq) 1044a27d9013SAlfredo Cardigliano { 10454c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 1046a27d9013SAlfredo Cardigliano } 1047a27d9013SAlfredo Cardigliano 1048a27d9013SAlfredo Cardigliano void 1049a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq) 1050a27d9013SAlfredo Cardigliano { 10514c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(qcq); 10524c8f8d57SAndrew Boyer } 10534c8f8d57SAndrew Boyer 10544c8f8d57SAndrew Boyer static void 10554c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 10564c8f8d57SAndrew Boyer { 10574c8f8d57SAndrew Boyer struct ionic_qcq *nqcq = lif->notifyqcq; 10584c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 10594c8f8d57SAndrew Boyer 10604c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 10614c8f8d57SAndrew Boyer return; 10624c8f8d57SAndrew Boyer 10634c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 10644c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 10654c8f8d57SAndrew Boyer 10664c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1067a27d9013SAlfredo Cardigliano } 1068a27d9013SAlfredo Cardigliano 106901a6c311SAlfredo Cardigliano bool 107001a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index, 107101a6c311SAlfredo Cardigliano void *cb_arg __rte_unused) 107201a6c311SAlfredo Cardigliano { 107301a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc_base = cq->base; 107401a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index]; 107501a6c311SAlfredo Cardigliano 107601a6c311SAlfredo Cardigliano if (!color_match(cq_desc->color, cq->done_color)) 107701a6c311SAlfredo Cardigliano return false; 107801a6c311SAlfredo Cardigliano 107901a6c311SAlfredo Cardigliano ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL); 108001a6c311SAlfredo Cardigliano 108101a6c311SAlfredo Cardigliano return true; 108201a6c311SAlfredo Cardigliano } 108301a6c311SAlfredo Cardigliano 108401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 108501a6c311SAlfredo Cardigliano int 108601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 108701a6c311SAlfredo Cardigliano void *cb_arg) 108801a6c311SAlfredo Cardigliano { 108901a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 109001a6c311SAlfredo Cardigliano uint32_t work_done; 109101a6c311SAlfredo Cardigliano 109201a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 109301a6c311SAlfredo Cardigliano 109401a6c311SAlfredo Cardigliano return work_done; 109501a6c311SAlfredo Cardigliano } 109601a6c311SAlfredo Cardigliano 109727b942c8SAlfredo Cardigliano static void 109827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 109927b942c8SAlfredo Cardigliano { 110027b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 110127b942c8SAlfredo Cardigliano bool link_up; 110227b942c8SAlfredo Cardigliano 110327b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 110427b942c8SAlfredo Cardigliano 110527b942c8SAlfredo Cardigliano if (!lif->info) 110627b942c8SAlfredo Cardigliano return; 110727b942c8SAlfredo Cardigliano 110827b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 110927b942c8SAlfredo Cardigliano 111027b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 111127b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 111227b942c8SAlfredo Cardigliano return; 111327b942c8SAlfredo Cardigliano 111427b942c8SAlfredo Cardigliano if (link_up) { 1115*09f806e9SAndrew Boyer adapter->link_speed = 1116*09f806e9SAndrew Boyer rte_le_to_cpu_32(lif->info->status.link_speed); 1117be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1118be63459eSAndrew Boyer adapter->link_speed); 111927b942c8SAlfredo Cardigliano } else { 112027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 112127b942c8SAlfredo Cardigliano } 112227b942c8SAlfredo Cardigliano 112327b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1124be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1125be63459eSAndrew Boyer } 1126be63459eSAndrew Boyer 1127be63459eSAndrew Boyer static void 1128be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1129be63459eSAndrew Boyer { 1130be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1131be63459eSAndrew Boyer return; 1132be63459eSAndrew Boyer 1133be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1134be63459eSAndrew Boyer 1135be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1136be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1137be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1138be63459eSAndrew Boyer ionic_lif_stop(lif); 1139be63459eSAndrew Boyer } 1140be63459eSAndrew Boyer 1141be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 114227b942c8SAlfredo Cardigliano } 114327b942c8SAlfredo Cardigliano 114427b942c8SAlfredo Cardigliano static bool 114527b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 114627b942c8SAlfredo Cardigliano { 114727b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 114827b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 114927b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 115027b942c8SAlfredo Cardigliano 115127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 115227b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 115327b942c8SAlfredo Cardigliano 115427b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 115527b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 115627b942c8SAlfredo Cardigliano return false; 115727b942c8SAlfredo Cardigliano 115827b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 115927b942c8SAlfredo Cardigliano 116027b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 116127b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 116227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1163be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1164be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1165be63459eSAndrew Boyer lif->name, 116627b942c8SAlfredo Cardigliano cq_desc->event.eid, 116727b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 116827b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 116927b942c8SAlfredo Cardigliano 117027b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 117127b942c8SAlfredo Cardigliano break; 1172be63459eSAndrew Boyer 1173be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1174be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1175be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1176be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1177be63459eSAndrew Boyer lif->name, 1178be63459eSAndrew Boyer cq_desc->event.eid, 1179be63459eSAndrew Boyer cq_desc->reset.reset_code, 1180be63459eSAndrew Boyer cq_desc->reset.state); 1181be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1182be63459eSAndrew Boyer break; 1183be63459eSAndrew Boyer 118427b942c8SAlfredo Cardigliano default: 118527b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 118627b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 118727b942c8SAlfredo Cardigliano break; 118827b942c8SAlfredo Cardigliano } 118927b942c8SAlfredo Cardigliano 119027b942c8SAlfredo Cardigliano return true; 119127b942c8SAlfredo Cardigliano } 119227b942c8SAlfredo Cardigliano 119327b942c8SAlfredo Cardigliano int 119427b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 119527b942c8SAlfredo Cardigliano { 119627b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 119727b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 119827b942c8SAlfredo Cardigliano uint32_t work_done; 119927b942c8SAlfredo Cardigliano 120027b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 120127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 120227b942c8SAlfredo Cardigliano return -1; 120327b942c8SAlfredo Cardigliano } 120427b942c8SAlfredo Cardigliano 120527b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 120627b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 120727b942c8SAlfredo Cardigliano 120827b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 120927b942c8SAlfredo Cardigliano 121027b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 121127b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 121227b942c8SAlfredo Cardigliano 121327b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 121427b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 121527b942c8SAlfredo Cardigliano 121627b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 121727b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 121827b942c8SAlfredo Cardigliano 121927b942c8SAlfredo Cardigliano return 0; 122027b942c8SAlfredo Cardigliano } 122127b942c8SAlfredo Cardigliano 122201a6c311SAlfredo Cardigliano static int 122301a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 122401a6c311SAlfredo Cardigliano { 122501a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 122601a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 122701a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 122801a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 122901a6c311SAlfredo Cardigliano int err; 123001a6c311SAlfredo Cardigliano 12314c8f8d57SAndrew Boyer ionic_dev_cmd_adminq_init(idev, qcq); 123201a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 123301a6c311SAlfredo Cardigliano if (err) 123401a6c311SAlfredo Cardigliano return err; 123501a6c311SAlfredo Cardigliano 123601a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 123701a6c311SAlfredo Cardigliano 123801a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 1239*09f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(comp.hw_index); 124001a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 124101a6c311SAlfredo Cardigliano 124201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 124301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 124401a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 124501a6c311SAlfredo Cardigliano 124601a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 124701a6c311SAlfredo Cardigliano 124801a6c311SAlfredo Cardigliano return 0; 124901a6c311SAlfredo Cardigliano } 125001a6c311SAlfredo Cardigliano 125127b942c8SAlfredo Cardigliano static int 125227b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 125327b942c8SAlfredo Cardigliano { 125427b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 125527b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 125627b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 125727b942c8SAlfredo Cardigliano int err; 125827b942c8SAlfredo Cardigliano 125927b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 126027b942c8SAlfredo Cardigliano .pending_work = true, 126127b942c8SAlfredo Cardigliano .cmd.q_init = { 126227b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 126327b942c8SAlfredo Cardigliano .type = q->type, 1264*09f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1265*09f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(qcq->intr.index), 1266*09f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ | 1267*09f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 126827b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1269*09f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 127027b942c8SAlfredo Cardigliano } 127127b942c8SAlfredo Cardigliano }; 127227b942c8SAlfredo Cardigliano 1273*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index); 1274*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa); 127527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 127627b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 12774ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 127827b942c8SAlfredo Cardigliano 127927b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 128027b942c8SAlfredo Cardigliano if (err) 128127b942c8SAlfredo Cardigliano return err; 128227b942c8SAlfredo Cardigliano 128327b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1284*09f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 128527b942c8SAlfredo Cardigliano q->db = NULL; 128627b942c8SAlfredo Cardigliano 128727b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 128827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 128927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 129027b942c8SAlfredo Cardigliano 129127b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 129227b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 129327b942c8SAlfredo Cardigliano 129427b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 129527b942c8SAlfredo Cardigliano 129627b942c8SAlfredo Cardigliano return 0; 129727b942c8SAlfredo Cardigliano } 129827b942c8SAlfredo Cardigliano 1299669c8de6SAlfredo Cardigliano int 1300598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1301598f6726SAlfredo Cardigliano { 1302598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1303598f6726SAlfredo Cardigliano .pending_work = true, 1304598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1305598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1306598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 1307*09f806e9SAndrew Boyer .features = rte_cpu_to_le_64(lif->features), 1308598f6726SAlfredo Cardigliano }, 1309598f6726SAlfredo Cardigliano }; 1310598f6726SAlfredo Cardigliano int err; 1311598f6726SAlfredo Cardigliano 1312598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1313598f6726SAlfredo Cardigliano if (err) 1314598f6726SAlfredo Cardigliano return err; 1315598f6726SAlfredo Cardigliano 1316*09f806e9SAndrew Boyer lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features & 1317598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1318598f6726SAlfredo Cardigliano 1319598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1320598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1321598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1322598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1323598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1324598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1325598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1326598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1327598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1328598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1329598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1330598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1331598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1332598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1333598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1334598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1335598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1336598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1337598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1338598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1339598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1340598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1341598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1342598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1343598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1344598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1345598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1346598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1347598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1348598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1349598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1350598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1351598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1352598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1353598f6726SAlfredo Cardigliano 1354598f6726SAlfredo Cardigliano return 0; 1355598f6726SAlfredo Cardigliano } 1356598f6726SAlfredo Cardigliano 1357a27d9013SAlfredo Cardigliano int 1358a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq) 1359a27d9013SAlfredo Cardigliano { 1360a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1361a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1362a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1363a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1364a27d9013SAlfredo Cardigliano .pending_work = true, 1365a27d9013SAlfredo Cardigliano .cmd.q_init = { 1366a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1367a27d9013SAlfredo Cardigliano .type = q->type, 1368*09f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1369*09f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 1370*09f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 1371*09f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1372a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1373*09f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 1374*09f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 1375*09f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1376a27d9013SAlfredo Cardigliano }, 1377a27d9013SAlfredo Cardigliano }; 1378a27d9013SAlfredo Cardigliano int err; 1379a27d9013SAlfredo Cardigliano 1380*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.index %d", q->index); 1381*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1382a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1383a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13844ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1385a27d9013SAlfredo Cardigliano 1386a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1387a27d9013SAlfredo Cardigliano if (err) 1388a27d9013SAlfredo Cardigliano return err; 1389a27d9013SAlfredo Cardigliano 1390a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1391*09f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1392a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1393a27d9013SAlfredo Cardigliano 1394a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1395a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1396a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1397a27d9013SAlfredo Cardigliano 1398a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1399a27d9013SAlfredo Cardigliano 1400a27d9013SAlfredo Cardigliano return 0; 1401a27d9013SAlfredo Cardigliano } 1402a27d9013SAlfredo Cardigliano 1403a27d9013SAlfredo Cardigliano int 1404a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq) 1405a27d9013SAlfredo Cardigliano { 1406a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1407a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1408a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1409a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1410a27d9013SAlfredo Cardigliano .pending_work = true, 1411a27d9013SAlfredo Cardigliano .cmd.q_init = { 1412a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1413a27d9013SAlfredo Cardigliano .type = q->type, 1414*09f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1415*09f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 1416*09f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 1417*09f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1418a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1419*09f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 1420*09f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 1421*09f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1422a27d9013SAlfredo Cardigliano }, 1423a27d9013SAlfredo Cardigliano }; 1424a27d9013SAlfredo Cardigliano int err; 1425a27d9013SAlfredo Cardigliano 1426*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index); 1427*09f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1428a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1429a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14304ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1431a27d9013SAlfredo Cardigliano 1432a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1433a27d9013SAlfredo Cardigliano if (err) 1434a27d9013SAlfredo Cardigliano return err; 1435a27d9013SAlfredo Cardigliano 1436a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1437*09f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1438a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1439a27d9013SAlfredo Cardigliano 1440a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1441a27d9013SAlfredo Cardigliano 1442a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1443a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1444a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1445a27d9013SAlfredo Cardigliano 1446a27d9013SAlfredo Cardigliano return 0; 1447a27d9013SAlfredo Cardigliano } 1448a27d9013SAlfredo Cardigliano 1449598f6726SAlfredo Cardigliano static int 1450598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1451598f6726SAlfredo Cardigliano { 1452598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1453598f6726SAlfredo Cardigliano .pending_work = true, 1454598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1455598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1456598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1457598f6726SAlfredo Cardigliano }, 1458598f6726SAlfredo Cardigliano }; 1459598f6726SAlfredo Cardigliano int err; 1460598f6726SAlfredo Cardigliano 1461598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1462598f6726SAlfredo Cardigliano 1463598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1464598f6726SAlfredo Cardigliano if (err) 1465598f6726SAlfredo Cardigliano return err; 1466598f6726SAlfredo Cardigliano 1467598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1468598f6726SAlfredo Cardigliano 1469598f6726SAlfredo Cardigliano return 0; 1470598f6726SAlfredo Cardigliano } 1471598f6726SAlfredo Cardigliano 1472598f6726SAlfredo Cardigliano static void 1473598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1474598f6726SAlfredo Cardigliano { 1475598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1476598f6726SAlfredo Cardigliano .pending_work = true, 1477598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1478598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1479598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1480598f6726SAlfredo Cardigliano }, 1481598f6726SAlfredo Cardigliano }; 1482598f6726SAlfredo Cardigliano 14834ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 14844ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1485598f6726SAlfredo Cardigliano 1486598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1487598f6726SAlfredo Cardigliano } 1488598f6726SAlfredo Cardigliano 1489598f6726SAlfredo Cardigliano int 1490669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1491669c8de6SAlfredo Cardigliano { 1492669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1493669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 1494669c8de6SAlfredo Cardigliano int err; 1495669c8de6SAlfredo Cardigliano 14963cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 14973cdfd905SAlfredo Cardigliano 149800b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1499669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1500669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 1501669c8de6SAlfredo Cardigliano if (err) 1502669c8de6SAlfredo Cardigliano return err; 1503669c8de6SAlfredo Cardigliano 1504*09f806e9SAndrew Boyer lif->hw_index = rte_cpu_to_le_16(comp.hw_index); 1505669c8de6SAlfredo Cardigliano 150601a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 150701a6c311SAlfredo Cardigliano if (err) 150801a6c311SAlfredo Cardigliano return err; 150901a6c311SAlfredo Cardigliano 151027b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 151127b942c8SAlfredo Cardigliano if (err) 151227b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 151327b942c8SAlfredo Cardigliano 151418a44465SAndrew Boyer /* 151518a44465SAndrew Boyer * Configure initial feature set 151618a44465SAndrew Boyer * This will be updated later by the dev_configure() step 151718a44465SAndrew Boyer */ 151818a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1519598f6726SAlfredo Cardigliano 1520598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1521598f6726SAlfredo Cardigliano if (err) 1522598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1523598f6726SAlfredo Cardigliano 152454fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1525598f6726SAlfredo Cardigliano if (err) 1526598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1527598f6726SAlfredo Cardigliano 152854fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 152954fe083fSAlfredo Cardigliano if (err) 153054fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 153154fe083fSAlfredo Cardigliano 1532598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1533598f6726SAlfredo Cardigliano 1534669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1535669c8de6SAlfredo Cardigliano 1536669c8de6SAlfredo Cardigliano return 0; 153727b942c8SAlfredo Cardigliano 153854fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 153954fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 154054fe083fSAlfredo Cardigliano 1541598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 15424c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1543598f6726SAlfredo Cardigliano 154427b942c8SAlfredo Cardigliano err_out_adminq_deinit: 15454c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 154627b942c8SAlfredo Cardigliano 154727b942c8SAlfredo Cardigliano return err; 1548669c8de6SAlfredo Cardigliano } 1549669c8de6SAlfredo Cardigliano 1550669c8de6SAlfredo Cardigliano void 1551669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1552669c8de6SAlfredo Cardigliano { 1553669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1554669c8de6SAlfredo Cardigliano return; 1555669c8de6SAlfredo Cardigliano 155654fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 155722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 15584c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 15594c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(lif->adminqcq); 156001a6c311SAlfredo Cardigliano 1561669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1562669c8de6SAlfredo Cardigliano } 1563669c8de6SAlfredo Cardigliano 156418a44465SAndrew Boyer void 156518a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 156618a44465SAndrew Boyer { 156718a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 156818a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 156918a44465SAndrew Boyer 157018a44465SAndrew Boyer /* 157118a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 157218a44465SAndrew Boyer * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK 157318a44465SAndrew Boyer */ 157418a44465SAndrew Boyer rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 157518a44465SAndrew Boyer 157618a44465SAndrew Boyer if (mask & ETH_VLAN_STRIP_MASK) { 157718a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) 157818a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 157918a44465SAndrew Boyer else 158018a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 158118a44465SAndrew Boyer } 158218a44465SAndrew Boyer } 158318a44465SAndrew Boyer 158418a44465SAndrew Boyer void 1585598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1586598f6726SAlfredo Cardigliano { 158718a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 158818a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 158922e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 1590*09f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 159122e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 1592*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 159322e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 1594*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 159522e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 159622e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 159722e7171bSAlfredo Cardigliano 1598598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1599598f6726SAlfredo Cardigliano 160022e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 160122e7171bSAlfredo Cardigliano lif->port_id); 160222e7171bSAlfredo Cardigliano 160322e7171bSAlfredo Cardigliano if (nrxqs > 0) 160422e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 160522e7171bSAlfredo Cardigliano 160622e7171bSAlfredo Cardigliano if (ntxqs > 0) 160722e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 160822e7171bSAlfredo Cardigliano 160922e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 161022e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1611a27d9013SAlfredo Cardigliano 161218a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 161318a44465SAndrew Boyer 161418a44465SAndrew Boyer /* 161518a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 161618a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 161718a44465SAndrew Boyer * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH; 161818a44465SAndrew Boyer */ 161918a44465SAndrew Boyer 162018a44465SAndrew Boyer /* RX per-port */ 162118a44465SAndrew Boyer 162218a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM || 162318a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM || 162418a44465SAndrew Boyer rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM) 162518a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 162618a44465SAndrew Boyer else 162718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 162818a44465SAndrew Boyer 162918a44465SAndrew Boyer if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) { 163018a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 163118a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 163218a44465SAndrew Boyer } else { 163318a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 163418a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 163518a44465SAndrew Boyer } 163618a44465SAndrew Boyer 163718a44465SAndrew Boyer /* Covers VLAN_STRIP */ 163818a44465SAndrew Boyer ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK); 163918a44465SAndrew Boyer 164018a44465SAndrew Boyer /* TX per-port */ 164118a44465SAndrew Boyer 164218a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM || 164318a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM || 164418a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM || 164518a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM || 164618a44465SAndrew Boyer txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) 164718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 164818a44465SAndrew Boyer else 164918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 165018a44465SAndrew Boyer 165118a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT) 165218a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 165318a44465SAndrew Boyer else 165418a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 165518a44465SAndrew Boyer 165618a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS) 165718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 165818a44465SAndrew Boyer else 165918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 166018a44465SAndrew Boyer 166118a44465SAndrew Boyer if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) { 166218a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 166318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 166418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 166518a44465SAndrew Boyer } else { 166618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 166718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 166818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 166918a44465SAndrew Boyer } 1670598f6726SAlfredo Cardigliano } 1671598f6726SAlfredo Cardigliano 1672598f6726SAlfredo Cardigliano int 1673598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1674598f6726SAlfredo Cardigliano { 16750578335aSAndrew Boyer uint32_t rx_mode; 1676a27d9013SAlfredo Cardigliano uint32_t i; 1677a27d9013SAlfredo Cardigliano int err; 1678598f6726SAlfredo Cardigliano 167922e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 168022e7171bSAlfredo Cardigliano if (err) 168122e7171bSAlfredo Cardigliano return err; 168222e7171bSAlfredo Cardigliano 16830578335aSAndrew Boyer if (!lif->rx_mode) { 16840578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 16850578335aSAndrew Boyer lif->name); 1686598f6726SAlfredo Cardigliano 16870578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1688598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1689598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1690598f6726SAlfredo Cardigliano 1691598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 16920578335aSAndrew Boyer } 1693598f6726SAlfredo Cardigliano 1694a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1695a27d9013SAlfredo Cardigliano "on port %u", 1696a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1697a27d9013SAlfredo Cardigliano 1698a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1699a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = lif->rxqcqs[i]; 170002eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1701a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1702a27d9013SAlfredo Cardigliano 1703a27d9013SAlfredo Cardigliano if (err) 1704a27d9013SAlfredo Cardigliano return err; 1705a27d9013SAlfredo Cardigliano } 1706a27d9013SAlfredo Cardigliano } 1707a27d9013SAlfredo Cardigliano 1708a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1709a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = lif->txqcqs[i]; 171002eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1711a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1712a27d9013SAlfredo Cardigliano 1713a27d9013SAlfredo Cardigliano if (err) 1714a27d9013SAlfredo Cardigliano return err; 1715a27d9013SAlfredo Cardigliano } 1716a27d9013SAlfredo Cardigliano } 1717a27d9013SAlfredo Cardigliano 1718598f6726SAlfredo Cardigliano /* Carrier ON here */ 1719be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1720be63459eSAndrew Boyer 1721be63459eSAndrew Boyer ionic_link_status_check(lif); 1722598f6726SAlfredo Cardigliano 1723598f6726SAlfredo Cardigliano return 0; 1724598f6726SAlfredo Cardigliano } 1725598f6726SAlfredo Cardigliano 1726598f6726SAlfredo Cardigliano int 1727669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1728669c8de6SAlfredo Cardigliano { 1729669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1730669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1731*09f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 1732669c8de6SAlfredo Cardigliano int err; 1733669c8de6SAlfredo Cardigliano unsigned int i; 1734669c8de6SAlfredo Cardigliano unsigned int lif_words = sizeof(ident->lif.words) / 1735669c8de6SAlfredo Cardigliano sizeof(ident->lif.words[0]); 1736669c8de6SAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 1737669c8de6SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 1738669c8de6SAlfredo Cardigliano unsigned int nwords; 1739669c8de6SAlfredo Cardigliano 1740669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1741669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1742669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1743669c8de6SAlfredo Cardigliano if (err) 1744669c8de6SAlfredo Cardigliano return (err); 1745669c8de6SAlfredo Cardigliano 1746669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1747669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1748669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1749669c8de6SAlfredo Cardigliano 1750669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 1751*09f806e9SAndrew Boyer rte_le_to_cpu_64(ident->lif.capabilities)); 1752669c8de6SAlfredo Cardigliano 1753669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 1754*09f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters)); 1755669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 1756*09f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters)); 1757669c8de6SAlfredo Cardigliano 1758669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 1759*09f806e9SAndrew Boyer rte_le_to_cpu_64(cfg->features)); 1760669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 1761*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ])); 1762669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 1763*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ])); 1764669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 1765*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ])); 1766669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 1767*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ])); 1768669c8de6SAlfredo Cardigliano 1769669c8de6SAlfredo Cardigliano return 0; 1770669c8de6SAlfredo Cardigliano } 1771669c8de6SAlfredo Cardigliano 1772669c8de6SAlfredo Cardigliano int 1773669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1774669c8de6SAlfredo Cardigliano { 1775669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1776*09f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 1777*09f806e9SAndrew Boyer uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs); 1778669c8de6SAlfredo Cardigliano 1779669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 1780*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 1781669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 1782*09f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 1783669c8de6SAlfredo Cardigliano 178400b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1785669c8de6SAlfredo Cardigliano 1786669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 17874ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 17884ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1789669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1790669c8de6SAlfredo Cardigliano return -ENOSPC; 1791669c8de6SAlfredo Cardigliano } 1792669c8de6SAlfredo Cardigliano 1793669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1794669c8de6SAlfredo Cardigliano 1795669c8de6SAlfredo Cardigliano return 0; 1796669c8de6SAlfredo Cardigliano } 1797