1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2669c8de6SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 3669c8de6SAlfredo Cardigliano */ 4669c8de6SAlfredo Cardigliano 5669c8de6SAlfredo Cardigliano #include <rte_malloc.h> 6669c8de6SAlfredo Cardigliano #include <rte_ethdev_driver.h> 7669c8de6SAlfredo Cardigliano 8669c8de6SAlfredo Cardigliano #include "ionic.h" 9669c8de6SAlfredo Cardigliano #include "ionic_logs.h" 10669c8de6SAlfredo Cardigliano #include "ionic_lif.h" 11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h" 1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h" 13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h" 14669c8de6SAlfredo Cardigliano 15598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr); 16598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr); 17598f6726SAlfredo Cardigliano 1801a6c311SAlfredo Cardigliano int 1901a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq) 2001a6c311SAlfredo Cardigliano { 2101a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 2201a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 2301a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 2401a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 2501a6c311SAlfredo Cardigliano .pending_work = true, 2601a6c311SAlfredo Cardigliano .cmd.q_control = { 2701a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 2801a6c311SAlfredo Cardigliano .type = q->type, 2901a6c311SAlfredo Cardigliano .index = q->index, 3001a6c311SAlfredo Cardigliano .oper = IONIC_Q_ENABLE, 3101a6c311SAlfredo Cardigliano }, 3201a6c311SAlfredo Cardigliano }; 3301a6c311SAlfredo Cardigliano 3401a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 3501a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 3601a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 3701a6c311SAlfredo Cardigliano } 3801a6c311SAlfredo Cardigliano 3901a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 4001a6c311SAlfredo Cardigliano } 4101a6c311SAlfredo Cardigliano 4201a6c311SAlfredo Cardigliano int 4301a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 4401a6c311SAlfredo Cardigliano { 4501a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 4601a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 4701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 4801a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 4901a6c311SAlfredo Cardigliano .pending_work = true, 5001a6c311SAlfredo Cardigliano .cmd.q_control = { 5101a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 5201a6c311SAlfredo Cardigliano .type = q->type, 5301a6c311SAlfredo Cardigliano .index = q->index, 5401a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 5501a6c311SAlfredo Cardigliano }, 5601a6c311SAlfredo Cardigliano }; 5701a6c311SAlfredo Cardigliano 5801a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 5901a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 6001a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 6101a6c311SAlfredo Cardigliano } 6201a6c311SAlfredo Cardigliano 6301a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 6401a6c311SAlfredo Cardigliano } 6501a6c311SAlfredo Cardigliano 66be63459eSAndrew Boyer void 67be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif) 68598f6726SAlfredo Cardigliano { 69*a0a99f21SAndrew Boyer uint32_t i; 70*a0a99f21SAndrew Boyer 71be63459eSAndrew Boyer IONIC_PRINT_CALL(); 72598f6726SAlfredo Cardigliano 73be63459eSAndrew Boyer lif->state &= ~IONIC_LIF_F_UP; 74*a0a99f21SAndrew Boyer 75*a0a99f21SAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 76*a0a99f21SAndrew Boyer struct ionic_qcq *rxq = lif->rxqcqs[i]; 77*a0a99f21SAndrew Boyer if (rxq->flags & IONIC_QCQ_F_INITED) 78*a0a99f21SAndrew Boyer (void)ionic_dev_rx_queue_stop(lif->eth_dev, i); 79*a0a99f21SAndrew Boyer } 80*a0a99f21SAndrew Boyer 81*a0a99f21SAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 82*a0a99f21SAndrew Boyer struct ionic_qcq *txq = lif->txqcqs[i]; 83*a0a99f21SAndrew Boyer if (txq->flags & IONIC_QCQ_F_INITED) 84*a0a99f21SAndrew Boyer (void)ionic_dev_tx_queue_stop(lif->eth_dev, i); 85*a0a99f21SAndrew Boyer } 86598f6726SAlfredo Cardigliano } 87598f6726SAlfredo Cardigliano 88598f6726SAlfredo Cardigliano void 89598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 90598f6726SAlfredo Cardigliano { 91598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 9275f96902SAndrew Boyer int err; 93598f6726SAlfredo Cardigliano 94598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 95598f6726SAlfredo Cardigliano 9600b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 9775f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 9875f96902SAndrew Boyer if (err) 994ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 100598f6726SAlfredo Cardigliano } 101598f6726SAlfredo Cardigliano 1023cdfd905SAlfredo Cardigliano static void 1033cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 1043cdfd905SAlfredo Cardigliano { 1053cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 1063cdfd905SAlfredo Cardigliano uint32_t i; 1073cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 1083cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1093cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 1103cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1113cdfd905SAlfredo Cardigliano 1123cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 1133cdfd905SAlfredo Cardigliano 1143cdfd905SAlfredo Cardigliano if (ls == NULL) { 1153cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1163cdfd905SAlfredo Cardigliano lif->port_id); 1173cdfd905SAlfredo Cardigliano return; 1183cdfd905SAlfredo Cardigliano } 1193cdfd905SAlfredo Cardigliano 1203cdfd905SAlfredo Cardigliano /* RX */ 1213cdfd905SAlfredo Cardigliano 1223cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1233cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1243cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1253cdfd905SAlfredo Cardigliano 1263cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1273cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1283cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1293cdfd905SAlfredo Cardigliano 1303cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1313cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1323cdfd905SAlfredo Cardigliano stats->imissed += 1333cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1343cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1353cdfd905SAlfredo Cardigliano rx_stats->no_room + 1363cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1373cdfd905SAlfredo Cardigliano } 1383cdfd905SAlfredo Cardigliano 1393cdfd905SAlfredo Cardigliano stats->imissed += 1403cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1413cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1423cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1433cdfd905SAlfredo Cardigliano 1443cdfd905SAlfredo Cardigliano stats->imissed += 1453cdfd905SAlfredo Cardigliano ls->rx_queue_empty + 1463cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1473cdfd905SAlfredo Cardigliano ls->rx_queue_disabled + 1483cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1493cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1503cdfd905SAlfredo Cardigliano 1513cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 1523cdfd905SAlfredo Cardigliano struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx; 1533cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1543cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1553cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1563cdfd905SAlfredo Cardigliano rx_stats->no_cb_arg + 1573cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1583cdfd905SAlfredo Cardigliano rx_stats->no_room + 1593cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1603cdfd905SAlfredo Cardigliano } 1613cdfd905SAlfredo Cardigliano 1623cdfd905SAlfredo Cardigliano /* TX */ 1633cdfd905SAlfredo Cardigliano 1643cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1653cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1663cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1673cdfd905SAlfredo Cardigliano 1683cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1693cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1703cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1713cdfd905SAlfredo Cardigliano 1723cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1733cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1743cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1753cdfd905SAlfredo Cardigliano } 1763cdfd905SAlfredo Cardigliano 1773cdfd905SAlfredo Cardigliano stats->oerrors += 1783cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1793cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1803cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1813cdfd905SAlfredo Cardigliano 1823cdfd905SAlfredo Cardigliano stats->oerrors += 1833cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1843cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1853cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1863cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1873cdfd905SAlfredo Cardigliano 1883cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 1893cdfd905SAlfredo Cardigliano struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx; 1903cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1913cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1923cdfd905SAlfredo Cardigliano } 1933cdfd905SAlfredo Cardigliano } 1943cdfd905SAlfredo Cardigliano 1953cdfd905SAlfredo Cardigliano void 1963cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 1973cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 1983cdfd905SAlfredo Cardigliano { 1993cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 2003cdfd905SAlfredo Cardigliano 2013cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 2023cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 2033cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 2043cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 2053cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 2063cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 2073cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 2083cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 2093cdfd905SAlfredo Cardigliano } 2103cdfd905SAlfredo Cardigliano 2113cdfd905SAlfredo Cardigliano void 2123cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 2133cdfd905SAlfredo Cardigliano { 2143cdfd905SAlfredo Cardigliano uint32_t i; 2153cdfd905SAlfredo Cardigliano 2163cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 2173cdfd905SAlfredo Cardigliano memset(&lif->rxqcqs[i]->stats.rx, 0, 2183cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 2193cdfd905SAlfredo Cardigliano memset(&lif->txqcqs[i]->stats.tx, 0, 2203cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2213cdfd905SAlfredo Cardigliano } 2223cdfd905SAlfredo Cardigliano 2233cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2243cdfd905SAlfredo Cardigliano } 2253cdfd905SAlfredo Cardigliano 2263cdfd905SAlfredo Cardigliano void 2273cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2283cdfd905SAlfredo Cardigliano { 2293cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2303cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2313cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2323cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2333cdfd905SAlfredo Cardigliano 2343cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2353cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2363cdfd905SAlfredo Cardigliano } 2373cdfd905SAlfredo Cardigliano 2383cdfd905SAlfredo Cardigliano void 2393cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2403cdfd905SAlfredo Cardigliano { 2413cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2423cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2433cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2443cdfd905SAlfredo Cardigliano 2453cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2463cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2473cdfd905SAlfredo Cardigliano } 2483cdfd905SAlfredo Cardigliano 249598f6726SAlfredo Cardigliano static int 25054fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 251598f6726SAlfredo Cardigliano { 25254fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 25354fe083fSAlfredo Cardigliano .pending_work = true, 25454fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 25554fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 25654fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_MAC, 25754fe083fSAlfredo Cardigliano }, 25854fe083fSAlfredo Cardigliano }; 25954fe083fSAlfredo Cardigliano int err; 26054fe083fSAlfredo Cardigliano 26154fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 26254fe083fSAlfredo Cardigliano 26354fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 26454fe083fSAlfredo Cardigliano if (err) 26554fe083fSAlfredo Cardigliano return err; 26654fe083fSAlfredo Cardigliano 26754fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 26854fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 26954fe083fSAlfredo Cardigliano 27054fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 27154fe083fSAlfredo Cardigliano } 27254fe083fSAlfredo Cardigliano 27354fe083fSAlfredo Cardigliano static int 27454fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 27554fe083fSAlfredo Cardigliano { 27654fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 27754fe083fSAlfredo Cardigliano .pending_work = true, 27854fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 27954fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 28054fe083fSAlfredo Cardigliano }, 28154fe083fSAlfredo Cardigliano }; 28254fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 28354fe083fSAlfredo Cardigliano int err; 28454fe083fSAlfredo Cardigliano 28554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 28654fe083fSAlfredo Cardigliano 28754fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 28854fe083fSAlfredo Cardigliano 28954fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 29054fe083fSAlfredo Cardigliano if (!f) { 29154fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 29254fe083fSAlfredo Cardigliano return -ENOENT; 29354fe083fSAlfredo Cardigliano } 29454fe083fSAlfredo Cardigliano 29554fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 29654fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 29754fe083fSAlfredo Cardigliano 29854fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 29954fe083fSAlfredo Cardigliano 30054fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 30154fe083fSAlfredo Cardigliano if (err) 30254fe083fSAlfredo Cardigliano return err; 30354fe083fSAlfredo Cardigliano 30454fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 30554fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 306598f6726SAlfredo Cardigliano 307598f6726SAlfredo Cardigliano return 0; 308598f6726SAlfredo Cardigliano } 309598f6726SAlfredo Cardigliano 31054fe083fSAlfredo Cardigliano int 31154fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 31254fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 31354fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 314598f6726SAlfredo Cardigliano { 31554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 31654fe083fSAlfredo Cardigliano 31754fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 31854fe083fSAlfredo Cardigliano 31954fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 32054fe083fSAlfredo Cardigliano } 32154fe083fSAlfredo Cardigliano 32254fe083fSAlfredo Cardigliano void 32375f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 32454fe083fSAlfredo Cardigliano { 32554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 32654fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 32775f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 32854fe083fSAlfredo Cardigliano 32954fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 33054fe083fSAlfredo Cardigliano 33154fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 33254fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 33354fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 33454fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 33554fe083fSAlfredo Cardigliano return; 33654fe083fSAlfredo Cardigliano } 33754fe083fSAlfredo Cardigliano 33875f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 33975f96902SAndrew Boyer 34075f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 34154fe083fSAlfredo Cardigliano return; 34254fe083fSAlfredo Cardigliano 34375f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 34454fe083fSAlfredo Cardigliano } 34554fe083fSAlfredo Cardigliano 34654fe083fSAlfredo Cardigliano int 34754fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 34854fe083fSAlfredo Cardigliano { 34954fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 35054fe083fSAlfredo Cardigliano 35154fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 35254fe083fSAlfredo Cardigliano 35354fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 35454fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 35554fe083fSAlfredo Cardigliano return -1; 35654fe083fSAlfredo Cardigliano } 35754fe083fSAlfredo Cardigliano 35854fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 35954fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 36054fe083fSAlfredo Cardigliano lif->mac_addr); 36154fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 36254fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 36354fe083fSAlfredo Cardigliano } 36454fe083fSAlfredo Cardigliano 36554fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 36654fe083fSAlfredo Cardigliano 36754fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 36854fe083fSAlfredo Cardigliano 36954fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 37054fe083fSAlfredo Cardigliano } 37154fe083fSAlfredo Cardigliano 37254fe083fSAlfredo Cardigliano static int 37354fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 37454fe083fSAlfredo Cardigliano { 37554fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 37654fe083fSAlfredo Cardigliano .pending_work = true, 37754fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 37854fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 37954fe083fSAlfredo Cardigliano .match = IONIC_RX_FILTER_MATCH_VLAN, 38054fe083fSAlfredo Cardigliano .vlan.vlan = vid, 38154fe083fSAlfredo Cardigliano }, 38254fe083fSAlfredo Cardigliano }; 38354fe083fSAlfredo Cardigliano int err; 38454fe083fSAlfredo Cardigliano 38554fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 38654fe083fSAlfredo Cardigliano if (err) 38754fe083fSAlfredo Cardigliano return err; 38854fe083fSAlfredo Cardigliano 38954fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 39054fe083fSAlfredo Cardigliano ctx.comp.rx_filter_add.filter_id); 39154fe083fSAlfredo Cardigliano 39254fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 39354fe083fSAlfredo Cardigliano } 39454fe083fSAlfredo Cardigliano 39554fe083fSAlfredo Cardigliano static int 39654fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 39754fe083fSAlfredo Cardigliano { 39854fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 39954fe083fSAlfredo Cardigliano .pending_work = true, 40054fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 40154fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 40254fe083fSAlfredo Cardigliano }, 40354fe083fSAlfredo Cardigliano }; 40454fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 40554fe083fSAlfredo Cardigliano int err; 40654fe083fSAlfredo Cardigliano 40754fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 40854fe083fSAlfredo Cardigliano 40954fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 41054fe083fSAlfredo Cardigliano 41154fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 41254fe083fSAlfredo Cardigliano if (!f) { 41354fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 41454fe083fSAlfredo Cardigliano return -ENOENT; 41554fe083fSAlfredo Cardigliano } 41654fe083fSAlfredo Cardigliano 41754fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id = f->filter_id; 41854fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 41954fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 42054fe083fSAlfredo Cardigliano 42154fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 42254fe083fSAlfredo Cardigliano if (err) 42354fe083fSAlfredo Cardigliano return err; 42454fe083fSAlfredo Cardigliano 42554fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 42654fe083fSAlfredo Cardigliano ctx.cmd.rx_filter_del.filter_id); 427598f6726SAlfredo Cardigliano 428598f6726SAlfredo Cardigliano return 0; 429598f6726SAlfredo Cardigliano } 430598f6726SAlfredo Cardigliano 43154fe083fSAlfredo Cardigliano int 43254fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 43354fe083fSAlfredo Cardigliano int on) 43454fe083fSAlfredo Cardigliano { 43554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 43654fe083fSAlfredo Cardigliano int err; 43754fe083fSAlfredo Cardigliano 43854fe083fSAlfredo Cardigliano if (on) 43954fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 44054fe083fSAlfredo Cardigliano else 44154fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 44254fe083fSAlfredo Cardigliano 44354fe083fSAlfredo Cardigliano return err; 44454fe083fSAlfredo Cardigliano } 44554fe083fSAlfredo Cardigliano 446598f6726SAlfredo Cardigliano static void 447598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 448598f6726SAlfredo Cardigliano { 449598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 450598f6726SAlfredo Cardigliano .pending_work = true, 451598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 452598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 453598f6726SAlfredo Cardigliano .rx_mode = rx_mode, 454598f6726SAlfredo Cardigliano }, 455598f6726SAlfredo Cardigliano }; 456598f6726SAlfredo Cardigliano int err; 457598f6726SAlfredo Cardigliano 458598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 459598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 460598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 461598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 462598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 463598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 464598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 465598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 466598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 467598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 468598f6726SAlfredo Cardigliano 469598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 470598f6726SAlfredo Cardigliano if (err) 471598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 472598f6726SAlfredo Cardigliano } 473598f6726SAlfredo Cardigliano 474598f6726SAlfredo Cardigliano static void 475598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 476598f6726SAlfredo Cardigliano { 477598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 478598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 479598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 480598f6726SAlfredo Cardigliano } 481598f6726SAlfredo Cardigliano } 482598f6726SAlfredo Cardigliano 48354fe083fSAlfredo Cardigliano int 48454fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 48554fe083fSAlfredo Cardigliano { 48654fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 48754fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 48854fe083fSAlfredo Cardigliano 48954fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 49054fe083fSAlfredo Cardigliano 49154fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 49254fe083fSAlfredo Cardigliano 49354fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 49454fe083fSAlfredo Cardigliano 49554fe083fSAlfredo Cardigliano return 0; 49654fe083fSAlfredo Cardigliano } 49754fe083fSAlfredo Cardigliano 49854fe083fSAlfredo Cardigliano int 49954fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 50054fe083fSAlfredo Cardigliano { 50154fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50254fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 50354fe083fSAlfredo Cardigliano 50454fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 50554fe083fSAlfredo Cardigliano 50654fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 50754fe083fSAlfredo Cardigliano 50854fe083fSAlfredo Cardigliano return 0; 50954fe083fSAlfredo Cardigliano } 51054fe083fSAlfredo Cardigliano 51154fe083fSAlfredo Cardigliano int 51254fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 51354fe083fSAlfredo Cardigliano { 51454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 51554fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 51654fe083fSAlfredo Cardigliano 51754fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 51854fe083fSAlfredo Cardigliano 51954fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 52054fe083fSAlfredo Cardigliano 52154fe083fSAlfredo Cardigliano return 0; 52254fe083fSAlfredo Cardigliano } 52354fe083fSAlfredo Cardigliano 52454fe083fSAlfredo Cardigliano int 52554fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 52654fe083fSAlfredo Cardigliano { 52754fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 52854fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 52954fe083fSAlfredo Cardigliano 53054fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 53154fe083fSAlfredo Cardigliano 53254fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 53354fe083fSAlfredo Cardigliano 53454fe083fSAlfredo Cardigliano return 0; 53554fe083fSAlfredo Cardigliano } 536598f6726SAlfredo Cardigliano 537598f6726SAlfredo Cardigliano int 538598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu) 539598f6726SAlfredo Cardigliano { 540598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 541598f6726SAlfredo Cardigliano .pending_work = true, 542598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 543598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 544598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 545598f6726SAlfredo Cardigliano .mtu = new_mtu, 546598f6726SAlfredo Cardigliano }, 547598f6726SAlfredo Cardigliano }; 548598f6726SAlfredo Cardigliano int err; 549598f6726SAlfredo Cardigliano 550598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 551598f6726SAlfredo Cardigliano if (err) 552598f6726SAlfredo Cardigliano return err; 553598f6726SAlfredo Cardigliano 554598f6726SAlfredo Cardigliano return 0; 555598f6726SAlfredo Cardigliano } 556598f6726SAlfredo Cardigliano 557598f6726SAlfredo Cardigliano int 55801a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 55901a6c311SAlfredo Cardigliano { 56001a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 56101a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 56201a6c311SAlfredo Cardigliano unsigned long index; 56301a6c311SAlfredo Cardigliano 56401a6c311SAlfredo Cardigliano /* 56501a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 56601a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5674ae96cb8SAndrew Boyer * which has index = 0) 56801a6c311SAlfredo Cardigliano */ 56901a6c311SAlfredo Cardigliano 57001a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 57101a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 57201a6c311SAlfredo Cardigliano break; 57301a6c311SAlfredo Cardigliano 57401a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 57501a6c311SAlfredo Cardigliano return -ENOSPC; 57601a6c311SAlfredo Cardigliano 57701a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 57801a6c311SAlfredo Cardigliano 57901a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 58001a6c311SAlfredo Cardigliano 58101a6c311SAlfredo Cardigliano return 0; 58201a6c311SAlfredo Cardigliano } 58301a6c311SAlfredo Cardigliano 58401a6c311SAlfredo Cardigliano void 58501a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr) 58601a6c311SAlfredo Cardigliano { 58701a6c311SAlfredo Cardigliano if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED) 58801a6c311SAlfredo Cardigliano lif->adapter->intrs[intr->index] = false; 58901a6c311SAlfredo Cardigliano } 59001a6c311SAlfredo Cardigliano 59101a6c311SAlfredo Cardigliano static int 59201a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type, 59301a6c311SAlfredo Cardigliano uint32_t index, 59401a6c311SAlfredo Cardigliano const char *base, uint32_t flags, 59501a6c311SAlfredo Cardigliano uint32_t num_descs, 59601a6c311SAlfredo Cardigliano uint32_t desc_size, 59701a6c311SAlfredo Cardigliano uint32_t cq_desc_size, 59801a6c311SAlfredo Cardigliano uint32_t sg_desc_size, 5991abf69fcSAndrew Boyer struct ionic_qcq **qcq) 60001a6c311SAlfredo Cardigliano { 60101a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 60201a6c311SAlfredo Cardigliano struct ionic_qcq *new; 60301a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 60401a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 60501a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 60601a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 60701a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 60801a6c311SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 60901a6c311SAlfredo Cardigliano int err; 61001a6c311SAlfredo Cardigliano 61101a6c311SAlfredo Cardigliano *qcq = NULL; 61201a6c311SAlfredo Cardigliano 61301a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 61401a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 61501a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 61601a6c311SAlfredo Cardigliano 61701a6c311SAlfredo Cardigliano total_size = RTE_ALIGN(q_size, PAGE_SIZE) + 61801a6c311SAlfredo Cardigliano RTE_ALIGN(cq_size, PAGE_SIZE); 61901a6c311SAlfredo Cardigliano /* 62001a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 62101a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 62201a6c311SAlfredo Cardigliano * Adding PAGE_SIZE. 62301a6c311SAlfredo Cardigliano */ 62401a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 62501a6c311SAlfredo Cardigliano 62601a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 62701a6c311SAlfredo Cardigliano total_size += RTE_ALIGN(sg_size, PAGE_SIZE); 62801a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 62901a6c311SAlfredo Cardigliano } 63001a6c311SAlfredo Cardigliano 63101a6c311SAlfredo Cardigliano new = rte_zmalloc("ionic", sizeof(*new), 0); 63201a6c311SAlfredo Cardigliano if (!new) { 63301a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 63401a6c311SAlfredo Cardigliano return -ENOMEM; 63501a6c311SAlfredo Cardigliano } 63601a6c311SAlfredo Cardigliano 63701a6c311SAlfredo Cardigliano new->lif = lif; 63801a6c311SAlfredo Cardigliano new->flags = flags; 63901a6c311SAlfredo Cardigliano 64001a6c311SAlfredo Cardigliano new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0); 64101a6c311SAlfredo Cardigliano if (!new->q.info) { 64201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 64301a6c311SAlfredo Cardigliano return -ENOMEM; 64401a6c311SAlfredo Cardigliano } 64501a6c311SAlfredo Cardigliano 64601a6c311SAlfredo Cardigliano new->q.type = type; 64701a6c311SAlfredo Cardigliano 64801a6c311SAlfredo Cardigliano err = ionic_q_init(lif, idev, &new->q, index, num_descs, 6491abf69fcSAndrew Boyer desc_size, sg_desc_size); 65001a6c311SAlfredo Cardigliano if (err) { 65101a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 65201a6c311SAlfredo Cardigliano return err; 65301a6c311SAlfredo Cardigliano } 65401a6c311SAlfredo Cardigliano 65501a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) { 65601a6c311SAlfredo Cardigliano err = ionic_intr_alloc(lif, &new->intr); 65701a6c311SAlfredo Cardigliano if (err) 65801a6c311SAlfredo Cardigliano return err; 65901a6c311SAlfredo Cardigliano 66001a6c311SAlfredo Cardigliano ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index, 66101a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 66201a6c311SAlfredo Cardigliano } else { 66301a6c311SAlfredo Cardigliano new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED; 66401a6c311SAlfredo Cardigliano } 66501a6c311SAlfredo Cardigliano 66601a6c311SAlfredo Cardigliano err = ionic_cq_init(lif, &new->cq, &new->intr, 66701a6c311SAlfredo Cardigliano num_descs, cq_desc_size); 66801a6c311SAlfredo Cardigliano if (err) { 66901a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 67001a6c311SAlfredo Cardigliano goto err_out_free_intr; 67101a6c311SAlfredo Cardigliano } 67201a6c311SAlfredo Cardigliano 67301a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 67401a6c311SAlfredo Cardigliano base /* name */, index /* queue_idx */, 67501a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 67601a6c311SAlfredo Cardigliano 67701a6c311SAlfredo Cardigliano if (!new->base_z) { 67801a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 67901a6c311SAlfredo Cardigliano err = -ENOMEM; 68001a6c311SAlfredo Cardigliano goto err_out_free_intr; 68101a6c311SAlfredo Cardigliano } 68201a6c311SAlfredo Cardigliano 68301a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 68401a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 68501a6c311SAlfredo Cardigliano new->total_size = total_size; 68601a6c311SAlfredo Cardigliano 68701a6c311SAlfredo Cardigliano q_base = new->base; 68801a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 68901a6c311SAlfredo Cardigliano 69001a6c311SAlfredo Cardigliano cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE); 69101a6c311SAlfredo Cardigliano cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE); 69201a6c311SAlfredo Cardigliano 69301a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 69401a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 69501a6c311SAlfredo Cardigliano PAGE_SIZE); 69601a6c311SAlfredo Cardigliano sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE); 69701a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 69801a6c311SAlfredo Cardigliano } 69901a6c311SAlfredo Cardigliano 7004ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 7014ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 70201a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 70301a6c311SAlfredo Cardigliano 70401a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 70501a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 70601a6c311SAlfredo Cardigliano ionic_cq_bind(&new->cq, &new->q); 70701a6c311SAlfredo Cardigliano 70801a6c311SAlfredo Cardigliano *qcq = new; 70901a6c311SAlfredo Cardigliano 71001a6c311SAlfredo Cardigliano return 0; 71101a6c311SAlfredo Cardigliano 71201a6c311SAlfredo Cardigliano err_out_free_intr: 71301a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) 71401a6c311SAlfredo Cardigliano ionic_intr_free(lif, &new->intr); 71501a6c311SAlfredo Cardigliano 71601a6c311SAlfredo Cardigliano return err; 71701a6c311SAlfredo Cardigliano } 71801a6c311SAlfredo Cardigliano 71901a6c311SAlfredo Cardigliano void 72001a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 72101a6c311SAlfredo Cardigliano { 72201a6c311SAlfredo Cardigliano if (qcq->base_z) { 72301a6c311SAlfredo Cardigliano qcq->base = NULL; 72401a6c311SAlfredo Cardigliano qcq->base_pa = 0; 72501a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 72601a6c311SAlfredo Cardigliano qcq->base_z = NULL; 72701a6c311SAlfredo Cardigliano } 72801a6c311SAlfredo Cardigliano 72901a6c311SAlfredo Cardigliano if (qcq->q.info) { 73001a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 73101a6c311SAlfredo Cardigliano qcq->q.info = NULL; 73201a6c311SAlfredo Cardigliano } 73301a6c311SAlfredo Cardigliano 73401a6c311SAlfredo Cardigliano rte_free(qcq); 73501a6c311SAlfredo Cardigliano } 73601a6c311SAlfredo Cardigliano 737a27d9013SAlfredo Cardigliano int 738a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_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_RXQ, index, "rx", flags, 746a27d9013SAlfredo Cardigliano nrxq_descs, 747a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 748a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 749a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 7501abf69fcSAndrew Boyer &lif->rxqcqs[index]); 751a27d9013SAlfredo Cardigliano if (err) 752a27d9013SAlfredo Cardigliano return err; 753a27d9013SAlfredo Cardigliano 754a27d9013SAlfredo Cardigliano *qcq = lif->rxqcqs[index]; 755a27d9013SAlfredo Cardigliano 756a27d9013SAlfredo Cardigliano return 0; 757a27d9013SAlfredo Cardigliano } 758a27d9013SAlfredo Cardigliano 759a27d9013SAlfredo Cardigliano int 760a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs, 761a27d9013SAlfredo Cardigliano struct ionic_qcq **qcq) 762a27d9013SAlfredo Cardigliano { 763a27d9013SAlfredo Cardigliano uint32_t flags; 764a27d9013SAlfredo Cardigliano int err = -ENOMEM; 765a27d9013SAlfredo Cardigliano 766a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 767a27d9013SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags, 768a27d9013SAlfredo Cardigliano ntxq_descs, 769a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 770a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 771a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_sg_desc), 7721abf69fcSAndrew Boyer &lif->txqcqs[index]); 773a27d9013SAlfredo Cardigliano if (err) 774a27d9013SAlfredo Cardigliano return err; 775a27d9013SAlfredo Cardigliano 776a27d9013SAlfredo Cardigliano *qcq = lif->txqcqs[index]; 777a27d9013SAlfredo Cardigliano 778a27d9013SAlfredo Cardigliano return 0; 779a27d9013SAlfredo Cardigliano } 780a27d9013SAlfredo Cardigliano 78101a6c311SAlfredo Cardigliano static int 78201a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 78301a6c311SAlfredo Cardigliano { 78401a6c311SAlfredo Cardigliano uint32_t flags; 78501a6c311SAlfredo Cardigliano int err = -ENOMEM; 78601a6c311SAlfredo Cardigliano 78701a6c311SAlfredo Cardigliano flags = 0; 78801a6c311SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, 78901a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 79001a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 79101a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 79201a6c311SAlfredo Cardigliano 0, 7931abf69fcSAndrew Boyer &lif->adminqcq); 79427b942c8SAlfredo Cardigliano if (err) 79527b942c8SAlfredo Cardigliano return err; 79601a6c311SAlfredo Cardigliano 79727b942c8SAlfredo Cardigliano return 0; 79827b942c8SAlfredo Cardigliano } 79927b942c8SAlfredo Cardigliano 80027b942c8SAlfredo Cardigliano static int 80127b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 80227b942c8SAlfredo Cardigliano { 80327b942c8SAlfredo Cardigliano uint32_t flags; 80427b942c8SAlfredo Cardigliano int err = -ENOMEM; 80527b942c8SAlfredo Cardigliano 80627b942c8SAlfredo Cardigliano flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR; 80727b942c8SAlfredo Cardigliano 80827b942c8SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify", 80927b942c8SAlfredo Cardigliano flags, 81027b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 81127b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 81227b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 81327b942c8SAlfredo Cardigliano 0, 8141abf69fcSAndrew Boyer &lif->notifyqcq); 81501a6c311SAlfredo Cardigliano if (err) 81601a6c311SAlfredo Cardigliano return err; 81701a6c311SAlfredo Cardigliano 81801a6c311SAlfredo Cardigliano return 0; 81901a6c311SAlfredo Cardigliano } 82001a6c311SAlfredo Cardigliano 821c67719e1SAlfredo Cardigliano static void * 822c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num) 823c67719e1SAlfredo Cardigliano { 824c67719e1SAlfredo Cardigliano char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr; 825c67719e1SAlfredo Cardigliano 826c67719e1SAlfredo Cardigliano if (adapter->num_bars <= IONIC_PCI_BAR_DBELL) 827c67719e1SAlfredo Cardigliano return NULL; 828c67719e1SAlfredo Cardigliano 829c67719e1SAlfredo Cardigliano return (void *)&vaddr[page_num << PAGE_SHIFT]; 830c67719e1SAlfredo Cardigliano } 831c67719e1SAlfredo Cardigliano 832669c8de6SAlfredo Cardigliano int 833669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 834669c8de6SAlfredo Cardigliano { 835c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 836669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 83701a6c311SAlfredo Cardigliano int err; 838669c8de6SAlfredo Cardigliano 8394ae96cb8SAndrew Boyer /* 8404ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 8414ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 8424ae96cb8SAndrew Boyer */ 8434ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 8444ae96cb8SAndrew Boyer 8454ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 846669c8de6SAlfredo Cardigliano 847669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 848669c8de6SAlfredo Cardigliano 84901a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 85001a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 85101a6c311SAlfredo Cardigliano 85200b65da5SAndrew Boyer lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0); 853c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 854c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 855c67719e1SAlfredo Cardigliano return -ENOMEM; 856c67719e1SAlfredo Cardigliano } 857c67719e1SAlfredo Cardigliano 858a27d9013SAlfredo Cardigliano lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) * 859a27d9013SAlfredo Cardigliano adapter->max_ntxqs_per_lif, 0); 860a27d9013SAlfredo Cardigliano 861a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 862a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 863a27d9013SAlfredo Cardigliano return -ENOMEM; 864a27d9013SAlfredo Cardigliano } 865a27d9013SAlfredo Cardigliano 866a27d9013SAlfredo Cardigliano lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) * 867a27d9013SAlfredo Cardigliano adapter->max_nrxqs_per_lif, 0); 868a27d9013SAlfredo Cardigliano 869a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 870a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 871a27d9013SAlfredo Cardigliano return -ENOMEM; 872a27d9013SAlfredo Cardigliano } 873a27d9013SAlfredo Cardigliano 87427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 87527b942c8SAlfredo Cardigliano 87627b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 87727b942c8SAlfredo Cardigliano if (err) { 87827b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 87927b942c8SAlfredo Cardigliano return err; 88027b942c8SAlfredo Cardigliano } 88127b942c8SAlfredo Cardigliano 88227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 88327b942c8SAlfredo Cardigliano 88401a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 88501a6c311SAlfredo Cardigliano if (err) { 88601a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 88701a6c311SAlfredo Cardigliano return err; 88801a6c311SAlfredo Cardigliano } 88901a6c311SAlfredo Cardigliano 89001a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 89101a6c311SAlfredo Cardigliano 892669c8de6SAlfredo Cardigliano lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); 893669c8de6SAlfredo Cardigliano 894669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 895669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 896669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 897669c8de6SAlfredo Cardigliano if (!lif->info_z) { 898669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 899669c8de6SAlfredo Cardigliano return -ENOMEM; 900669c8de6SAlfredo Cardigliano } 901669c8de6SAlfredo Cardigliano 902669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 903669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 904669c8de6SAlfredo Cardigliano 905669c8de6SAlfredo Cardigliano return 0; 906669c8de6SAlfredo Cardigliano } 907669c8de6SAlfredo Cardigliano 908669c8de6SAlfredo Cardigliano void 909669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 910669c8de6SAlfredo Cardigliano { 91127b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 91227b942c8SAlfredo Cardigliano ionic_qcq_free(lif->notifyqcq); 91327b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 91427b942c8SAlfredo Cardigliano } 91527b942c8SAlfredo Cardigliano 91601a6c311SAlfredo Cardigliano if (lif->adminqcq) { 91701a6c311SAlfredo Cardigliano ionic_qcq_free(lif->adminqcq); 91801a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 91901a6c311SAlfredo Cardigliano } 92001a6c311SAlfredo Cardigliano 921a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 922a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 923a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 924a27d9013SAlfredo Cardigliano } 925a27d9013SAlfredo Cardigliano 926a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 927a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 928a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 929a27d9013SAlfredo Cardigliano } 930a27d9013SAlfredo Cardigliano 931669c8de6SAlfredo Cardigliano if (lif->info) { 932669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 933669c8de6SAlfredo Cardigliano lif->info = NULL; 934669c8de6SAlfredo Cardigliano } 935669c8de6SAlfredo Cardigliano } 936669c8de6SAlfredo Cardigliano 937175e4e7eSAndrew Boyer void 938175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 939175e4e7eSAndrew Boyer { 940175e4e7eSAndrew Boyer uint32_t i; 941175e4e7eSAndrew Boyer 942175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 943175e4e7eSAndrew Boyer ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]); 944175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 945175e4e7eSAndrew Boyer } 946175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 947175e4e7eSAndrew Boyer ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]); 948175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 949175e4e7eSAndrew Boyer } 950175e4e7eSAndrew Boyer } 951175e4e7eSAndrew Boyer 95222e7171bSAlfredo Cardigliano int 95322e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 95422e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 95522e7171bSAlfredo Cardigliano { 95622e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 95722e7171bSAlfredo Cardigliano .pending_work = true, 95822e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 95922e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 96022e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 96122e7171bSAlfredo Cardigliano .rss.types = types, 96222e7171bSAlfredo Cardigliano .rss.addr = lif->rss_ind_tbl_pa, 96322e7171bSAlfredo Cardigliano }, 96422e7171bSAlfredo Cardigliano }; 96522e7171bSAlfredo Cardigliano unsigned int i; 96622e7171bSAlfredo Cardigliano 96722e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 96822e7171bSAlfredo Cardigliano 96922e7171bSAlfredo Cardigliano lif->rss_types = types; 97022e7171bSAlfredo Cardigliano 97122e7171bSAlfredo Cardigliano if (key) 97222e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 97322e7171bSAlfredo Cardigliano 97422e7171bSAlfredo Cardigliano if (indir) 97522e7171bSAlfredo Cardigliano for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++) 97622e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 97722e7171bSAlfredo Cardigliano 97822e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 97922e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 98022e7171bSAlfredo Cardigliano 98122e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 98222e7171bSAlfredo Cardigliano } 98322e7171bSAlfredo Cardigliano 98422e7171bSAlfredo Cardigliano static int 98522e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 98622e7171bSAlfredo Cardigliano { 98722e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 98822e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 98922e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 99022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 99122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 99222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 99322e7171bSAlfredo Cardigliano }; 99422e7171bSAlfredo Cardigliano uint32_t i; 9953d845eddSAndrew Boyer uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz; 99622e7171bSAlfredo Cardigliano 99722e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 99822e7171bSAlfredo Cardigliano 9993d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 100022e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 10013d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 10023d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 10033d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 100422e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 100522e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 100622e7171bSAlfredo Cardigliano return -ENOMEM; 100722e7171bSAlfredo Cardigliano } 100822e7171bSAlfredo Cardigliano 100922e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 101022e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 10113d845eddSAndrew Boyer } 10123d845eddSAndrew Boyer 10133d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 10143d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 101522e7171bSAlfredo Cardigliano 101622e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 10173d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 101822e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 10193d845eddSAndrew Boyer } 102022e7171bSAlfredo Cardigliano 10213d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 102222e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 102322e7171bSAlfredo Cardigliano } 102422e7171bSAlfredo Cardigliano 102522e7171bSAlfredo Cardigliano static void 102622e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 102722e7171bSAlfredo Cardigliano { 102822e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 102922e7171bSAlfredo Cardigliano return; 103022e7171bSAlfredo Cardigliano 103122e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 103222e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 103322e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 103422e7171bSAlfredo Cardigliano 103522e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 103622e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 103722e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 103822e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 103922e7171bSAlfredo Cardigliano } 104022e7171bSAlfredo Cardigliano } 104122e7171bSAlfredo Cardigliano 104201a6c311SAlfredo Cardigliano static void 104301a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) 104401a6c311SAlfredo Cardigliano { 104501a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 104601a6c311SAlfredo Cardigliano 104701a6c311SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) 104801a6c311SAlfredo Cardigliano return; 104901a6c311SAlfredo Cardigliano 105001a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 105101a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 105201a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 105301a6c311SAlfredo Cardigliano 105401a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 105501a6c311SAlfredo Cardigliano } 105601a6c311SAlfredo Cardigliano 1057a27d9013SAlfredo Cardigliano void 1058a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq) 1059a27d9013SAlfredo Cardigliano { 1060a27d9013SAlfredo Cardigliano ionic_lif_qcq_deinit(qcq->lif, qcq); 1061a27d9013SAlfredo Cardigliano } 1062a27d9013SAlfredo Cardigliano 1063a27d9013SAlfredo Cardigliano void 1064a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq) 1065a27d9013SAlfredo Cardigliano { 1066a27d9013SAlfredo Cardigliano ionic_lif_qcq_deinit(qcq->lif, qcq); 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) { 111527b942c8SAlfredo Cardigliano adapter->link_speed = lif->info->status.link_speed; 1116be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1117be63459eSAndrew Boyer adapter->link_speed); 111827b942c8SAlfredo Cardigliano } else { 111927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 112027b942c8SAlfredo Cardigliano } 112127b942c8SAlfredo Cardigliano 112227b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1123be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1124be63459eSAndrew Boyer } 1125be63459eSAndrew Boyer 1126be63459eSAndrew Boyer static void 1127be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1128be63459eSAndrew Boyer { 1129be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1130be63459eSAndrew Boyer return; 1131be63459eSAndrew Boyer 1132be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1133be63459eSAndrew Boyer 1134be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1135be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1136be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1137be63459eSAndrew Boyer ionic_lif_stop(lif); 1138be63459eSAndrew Boyer } 1139be63459eSAndrew Boyer 1140be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 114127b942c8SAlfredo Cardigliano } 114227b942c8SAlfredo Cardigliano 114327b942c8SAlfredo Cardigliano static bool 114427b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 114527b942c8SAlfredo Cardigliano { 114627b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 114727b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 114827b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 114927b942c8SAlfredo Cardigliano 115027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 115127b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 115227b942c8SAlfredo Cardigliano 115327b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 115427b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 115527b942c8SAlfredo Cardigliano return false; 115627b942c8SAlfredo Cardigliano 115727b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 115827b942c8SAlfredo Cardigliano 115927b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 116027b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 116127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1162be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1163be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1164be63459eSAndrew Boyer lif->name, 116527b942c8SAlfredo Cardigliano cq_desc->event.eid, 116627b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 116727b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 116827b942c8SAlfredo Cardigliano 116927b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 117027b942c8SAlfredo Cardigliano break; 1171be63459eSAndrew Boyer 1172be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1173be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1174be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1175be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1176be63459eSAndrew Boyer lif->name, 1177be63459eSAndrew Boyer cq_desc->event.eid, 1178be63459eSAndrew Boyer cq_desc->reset.reset_code, 1179be63459eSAndrew Boyer cq_desc->reset.state); 1180be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1181be63459eSAndrew Boyer break; 1182be63459eSAndrew Boyer 118327b942c8SAlfredo Cardigliano default: 118427b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 118527b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 118627b942c8SAlfredo Cardigliano break; 118727b942c8SAlfredo Cardigliano } 118827b942c8SAlfredo Cardigliano 118927b942c8SAlfredo Cardigliano return true; 119027b942c8SAlfredo Cardigliano } 119127b942c8SAlfredo Cardigliano 119227b942c8SAlfredo Cardigliano int 119327b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 119427b942c8SAlfredo Cardigliano { 119527b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 119627b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 119727b942c8SAlfredo Cardigliano uint32_t work_done; 119827b942c8SAlfredo Cardigliano 119927b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 120027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 120127b942c8SAlfredo Cardigliano return -1; 120227b942c8SAlfredo Cardigliano } 120327b942c8SAlfredo Cardigliano 120427b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 120527b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 120627b942c8SAlfredo Cardigliano 120727b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 120827b942c8SAlfredo Cardigliano 120927b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 121027b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 121127b942c8SAlfredo Cardigliano 121227b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 121327b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 121427b942c8SAlfredo Cardigliano 121527b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 121627b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 121727b942c8SAlfredo Cardigliano 121827b942c8SAlfredo Cardigliano return 0; 121927b942c8SAlfredo Cardigliano } 122027b942c8SAlfredo Cardigliano 122101a6c311SAlfredo Cardigliano static int 122201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 122301a6c311SAlfredo Cardigliano { 122401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 122501a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 122601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 122701a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 122801a6c311SAlfredo Cardigliano int err; 122901a6c311SAlfredo Cardigliano 123000b65da5SAndrew Boyer ionic_dev_cmd_adminq_init(idev, qcq, qcq->intr.index); 123101a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 123201a6c311SAlfredo Cardigliano if (err) 123301a6c311SAlfredo Cardigliano return err; 123401a6c311SAlfredo Cardigliano 123501a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 123601a6c311SAlfredo Cardigliano 123701a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 123801a6c311SAlfredo Cardigliano q->hw_index = comp.hw_index; 123901a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 124001a6c311SAlfredo Cardigliano 124101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 124201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 124301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 124401a6c311SAlfredo Cardigliano 124501a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 124601a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 124701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 124801a6c311SAlfredo Cardigliano 124901a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 125001a6c311SAlfredo Cardigliano 125101a6c311SAlfredo Cardigliano return 0; 125201a6c311SAlfredo Cardigliano } 125301a6c311SAlfredo Cardigliano 125427b942c8SAlfredo Cardigliano static int 125527b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 125627b942c8SAlfredo Cardigliano { 125727b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 125827b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 125927b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 126027b942c8SAlfredo Cardigliano int err; 126127b942c8SAlfredo Cardigliano 126227b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 126327b942c8SAlfredo Cardigliano .pending_work = true, 126427b942c8SAlfredo Cardigliano .cmd.q_init = { 126527b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 126627b942c8SAlfredo Cardigliano .type = q->type, 126727b942c8SAlfredo Cardigliano .index = q->index, 126827b942c8SAlfredo Cardigliano .flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA), 126927b942c8SAlfredo Cardigliano .intr_index = qcq->intr.index, 127027b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 127127b942c8SAlfredo Cardigliano .ring_base = q->base_pa, 127227b942c8SAlfredo Cardigliano } 127327b942c8SAlfredo Cardigliano }; 127427b942c8SAlfredo Cardigliano 127527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.index %d", 127627b942c8SAlfredo Cardigliano ctx.cmd.q_init.index); 127727b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", 127827b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 127927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 128027b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 12814ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 128227b942c8SAlfredo Cardigliano 128327b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 128427b942c8SAlfredo Cardigliano if (err) 128527b942c8SAlfredo Cardigliano return err; 128627b942c8SAlfredo Cardigliano 128727b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 128827b942c8SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 128927b942c8SAlfredo Cardigliano q->db = NULL; 129027b942c8SAlfredo Cardigliano 129127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 129227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 129327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 129427b942c8SAlfredo Cardigliano 129527b942c8SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 129627b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 129727b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 129827b942c8SAlfredo Cardigliano 129927b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 130027b942c8SAlfredo Cardigliano 130127b942c8SAlfredo Cardigliano return 0; 130227b942c8SAlfredo Cardigliano } 130327b942c8SAlfredo Cardigliano 1304669c8de6SAlfredo Cardigliano int 1305598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1306598f6726SAlfredo Cardigliano { 1307598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1308598f6726SAlfredo Cardigliano .pending_work = true, 1309598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1310598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1311598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 1312598f6726SAlfredo Cardigliano .features = lif->features, 1313598f6726SAlfredo Cardigliano }, 1314598f6726SAlfredo Cardigliano }; 1315598f6726SAlfredo Cardigliano int err; 1316598f6726SAlfredo Cardigliano 1317598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1318598f6726SAlfredo Cardigliano if (err) 1319598f6726SAlfredo Cardigliano return err; 1320598f6726SAlfredo Cardigliano 1321598f6726SAlfredo Cardigliano lif->hw_features = (ctx.cmd.lif_setattr.features & 1322598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1323598f6726SAlfredo Cardigliano 1324598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1325598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1326598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1327598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1328598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1329598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1330598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1331598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1332598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1333598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1334598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1335598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1336598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1337598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1338598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1339598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1340598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1341598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1342598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1343598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1344598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1345598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1346598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1347598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1348598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1349598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1350598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1351598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1352598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1353598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1354598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1355598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1356598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1357598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1358598f6726SAlfredo Cardigliano 1359598f6726SAlfredo Cardigliano return 0; 1360598f6726SAlfredo Cardigliano } 1361598f6726SAlfredo Cardigliano 1362a27d9013SAlfredo Cardigliano int 1363a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq) 1364a27d9013SAlfredo Cardigliano { 1365a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1366a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1367a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1368a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1369a27d9013SAlfredo Cardigliano .pending_work = true, 1370a27d9013SAlfredo Cardigliano .cmd.q_init = { 1371a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1372a27d9013SAlfredo Cardigliano .type = q->type, 1373a27d9013SAlfredo Cardigliano .index = q->index, 1374a27d9013SAlfredo Cardigliano .flags = IONIC_QINIT_F_SG, 1375a27d9013SAlfredo Cardigliano .intr_index = cq->bound_intr->index, 1376a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1377a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1378a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1379a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1380a27d9013SAlfredo Cardigliano }, 1381a27d9013SAlfredo Cardigliano }; 1382a27d9013SAlfredo Cardigliano int err; 1383a27d9013SAlfredo Cardigliano 1384a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index); 1385a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", 1386a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1387a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1388a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 13894ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1390a27d9013SAlfredo Cardigliano 1391a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1392a27d9013SAlfredo Cardigliano if (err) 1393a27d9013SAlfredo Cardigliano return err; 1394a27d9013SAlfredo Cardigliano 1395a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1396a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1397a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1398a27d9013SAlfredo Cardigliano 1399a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1400a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1401a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1402a27d9013SAlfredo Cardigliano 1403a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1404a27d9013SAlfredo Cardigliano 1405a27d9013SAlfredo Cardigliano return 0; 1406a27d9013SAlfredo Cardigliano } 1407a27d9013SAlfredo Cardigliano 1408a27d9013SAlfredo Cardigliano int 1409a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq) 1410a27d9013SAlfredo Cardigliano { 1411a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1412a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1413a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1414a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1415a27d9013SAlfredo Cardigliano .pending_work = true, 1416a27d9013SAlfredo Cardigliano .cmd.q_init = { 1417a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1418a27d9013SAlfredo Cardigliano .type = q->type, 1419a27d9013SAlfredo Cardigliano .index = q->index, 1420a27d9013SAlfredo Cardigliano .flags = IONIC_QINIT_F_SG, 1421a27d9013SAlfredo Cardigliano .intr_index = cq->bound_intr->index, 1422a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 1423a27d9013SAlfredo Cardigliano .ring_base = q->base_pa, 1424a27d9013SAlfredo Cardigliano .cq_ring_base = cq->base_pa, 1425a27d9013SAlfredo Cardigliano .sg_ring_base = q->sg_base_pa, 1426a27d9013SAlfredo Cardigliano }, 1427a27d9013SAlfredo Cardigliano }; 1428a27d9013SAlfredo Cardigliano int err; 1429a27d9013SAlfredo Cardigliano 1430a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index); 1431a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", 1432a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 1433a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1434a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14354ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1436a27d9013SAlfredo Cardigliano 1437a27d9013SAlfredo Cardigliano err = ionic_adminq_post_wait(qcq->lif, &ctx); 1438a27d9013SAlfredo Cardigliano if (err) 1439a27d9013SAlfredo Cardigliano return err; 1440a27d9013SAlfredo Cardigliano 1441a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 1442a27d9013SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 1443a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1444a27d9013SAlfredo Cardigliano 1445a27d9013SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 1446a27d9013SAlfredo Cardigliano 1447a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1448a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1449a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1450a27d9013SAlfredo Cardigliano 1451a27d9013SAlfredo Cardigliano return 0; 1452a27d9013SAlfredo Cardigliano } 1453a27d9013SAlfredo Cardigliano 1454598f6726SAlfredo Cardigliano static int 1455598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1456598f6726SAlfredo Cardigliano { 1457598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1458598f6726SAlfredo Cardigliano .pending_work = true, 1459598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1460598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1461598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1462598f6726SAlfredo Cardigliano }, 1463598f6726SAlfredo Cardigliano }; 1464598f6726SAlfredo Cardigliano int err; 1465598f6726SAlfredo Cardigliano 1466598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1467598f6726SAlfredo Cardigliano 1468598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1469598f6726SAlfredo Cardigliano if (err) 1470598f6726SAlfredo Cardigliano return err; 1471598f6726SAlfredo Cardigliano 1472598f6726SAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *) 1473598f6726SAlfredo Cardigliano lif->mac_addr)) { 1474598f6726SAlfredo Cardigliano IONIC_PRINT(INFO, "deleting station MAC addr"); 1475598f6726SAlfredo Cardigliano 1476598f6726SAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 1477598f6726SAlfredo Cardigliano } 1478598f6726SAlfredo Cardigliano 1479598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1480598f6726SAlfredo Cardigliano 1481598f6726SAlfredo Cardigliano if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 1482598f6726SAlfredo Cardigliano IONIC_PRINT(NOTICE, "empty MAC addr (VF?)"); 1483598f6726SAlfredo Cardigliano return 0; 1484598f6726SAlfredo Cardigliano } 1485598f6726SAlfredo Cardigliano 1486598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adding station MAC addr"); 1487598f6726SAlfredo Cardigliano 1488598f6726SAlfredo Cardigliano ionic_lif_addr_add(lif, lif->mac_addr); 1489598f6726SAlfredo Cardigliano 1490598f6726SAlfredo Cardigliano return 0; 1491598f6726SAlfredo Cardigliano } 1492598f6726SAlfredo Cardigliano 1493598f6726SAlfredo Cardigliano static void 1494598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1495598f6726SAlfredo Cardigliano { 1496598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1497598f6726SAlfredo Cardigliano .pending_work = true, 1498598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1499598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1500598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1501598f6726SAlfredo Cardigliano }, 1502598f6726SAlfredo Cardigliano }; 1503598f6726SAlfredo Cardigliano 15044ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 15054ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1506598f6726SAlfredo Cardigliano 1507598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1508598f6726SAlfredo Cardigliano } 1509598f6726SAlfredo Cardigliano 1510598f6726SAlfredo Cardigliano int 1511669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1512669c8de6SAlfredo Cardigliano { 1513669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1514669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 1515669c8de6SAlfredo Cardigliano int err; 1516669c8de6SAlfredo Cardigliano 15173cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 15183cdfd905SAlfredo Cardigliano 151900b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1520669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1521669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 1522669c8de6SAlfredo Cardigliano if (err) 1523669c8de6SAlfredo Cardigliano return err; 1524669c8de6SAlfredo Cardigliano 1525669c8de6SAlfredo Cardigliano lif->hw_index = comp.hw_index; 1526669c8de6SAlfredo Cardigliano 152701a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 152801a6c311SAlfredo Cardigliano if (err) 152901a6c311SAlfredo Cardigliano return err; 153001a6c311SAlfredo Cardigliano 153127b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 153227b942c8SAlfredo Cardigliano if (err) 153327b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 153427b942c8SAlfredo Cardigliano 1535a27d9013SAlfredo Cardigliano lif->features = 1536a27d9013SAlfredo Cardigliano IONIC_ETH_HW_VLAN_TX_TAG 1537a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_VLAN_RX_STRIP 1538a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_VLAN_RX_FILTER 1539a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_HASH 1540a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TX_SG 1541a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_SG 154264b08152SAlfredo Cardigliano | IONIC_ETH_HW_TX_CSUM 1543a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_RX_CSUM 1544a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO 1545a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO_IPV6 1546a27d9013SAlfredo Cardigliano | IONIC_ETH_HW_TSO_ECN; 1547598f6726SAlfredo Cardigliano 1548598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1549598f6726SAlfredo Cardigliano if (err) 1550598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1551598f6726SAlfredo Cardigliano 155254fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1553598f6726SAlfredo Cardigliano if (err) 1554598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1555598f6726SAlfredo Cardigliano 155654fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 155754fe083fSAlfredo Cardigliano if (err) 155854fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 155954fe083fSAlfredo Cardigliano 1560598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1561598f6726SAlfredo Cardigliano 1562669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1563669c8de6SAlfredo Cardigliano 1564669c8de6SAlfredo Cardigliano return 0; 156527b942c8SAlfredo Cardigliano 156654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 156754fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 156854fe083fSAlfredo Cardigliano 1569598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 1570598f6726SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->notifyqcq); 1571598f6726SAlfredo Cardigliano 157227b942c8SAlfredo Cardigliano err_out_adminq_deinit: 157327b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 157427b942c8SAlfredo Cardigliano 157527b942c8SAlfredo Cardigliano return err; 1576669c8de6SAlfredo Cardigliano } 1577669c8de6SAlfredo Cardigliano 1578669c8de6SAlfredo Cardigliano void 1579669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1580669c8de6SAlfredo Cardigliano { 1581669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1582669c8de6SAlfredo Cardigliano return; 1583669c8de6SAlfredo Cardigliano 158454fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 158522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 158627b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->notifyqcq); 158701a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 158801a6c311SAlfredo Cardigliano 1589669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1590669c8de6SAlfredo Cardigliano } 1591669c8de6SAlfredo Cardigliano 1592669c8de6SAlfredo Cardigliano int 1593598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1594598f6726SAlfredo Cardigliano { 159522e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 159622e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 159722e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 159822e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 159922e7171bSAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 160022e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 160122e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 160222e7171bSAlfredo Cardigliano 1603598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1604598f6726SAlfredo Cardigliano 160522e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 160622e7171bSAlfredo Cardigliano lif->port_id); 160722e7171bSAlfredo Cardigliano 160822e7171bSAlfredo Cardigliano if (nrxqs > 0) 160922e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 161022e7171bSAlfredo Cardigliano 161122e7171bSAlfredo Cardigliano if (ntxqs > 0) 161222e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 161322e7171bSAlfredo Cardigliano 161422e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 161522e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1616a27d9013SAlfredo Cardigliano 1617598f6726SAlfredo Cardigliano return 0; 1618598f6726SAlfredo Cardigliano } 1619598f6726SAlfredo Cardigliano 1620598f6726SAlfredo Cardigliano int 1621598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1622598f6726SAlfredo Cardigliano { 16230578335aSAndrew Boyer uint32_t rx_mode; 1624a27d9013SAlfredo Cardigliano uint32_t i; 1625a27d9013SAlfredo Cardigliano int err; 1626598f6726SAlfredo Cardigliano 162722e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 162822e7171bSAlfredo Cardigliano if (err) 162922e7171bSAlfredo Cardigliano return err; 163022e7171bSAlfredo Cardigliano 16310578335aSAndrew Boyer if (!lif->rx_mode) { 16320578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 16330578335aSAndrew Boyer lif->name); 1634598f6726SAlfredo Cardigliano 16350578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1636598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1637598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1638598f6726SAlfredo Cardigliano 1639598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 16400578335aSAndrew Boyer } 1641598f6726SAlfredo Cardigliano 1642a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1643a27d9013SAlfredo Cardigliano "on port %u", 1644a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1645a27d9013SAlfredo Cardigliano 1646a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1647a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = lif->rxqcqs[i]; 164802eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1649a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1650a27d9013SAlfredo Cardigliano 1651a27d9013SAlfredo Cardigliano if (err) 1652a27d9013SAlfredo Cardigliano return err; 1653a27d9013SAlfredo Cardigliano } 1654a27d9013SAlfredo Cardigliano } 1655a27d9013SAlfredo Cardigliano 1656a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1657a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = lif->txqcqs[i]; 165802eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1659a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1660a27d9013SAlfredo Cardigliano 1661a27d9013SAlfredo Cardigliano if (err) 1662a27d9013SAlfredo Cardigliano return err; 1663a27d9013SAlfredo Cardigliano } 1664a27d9013SAlfredo Cardigliano } 1665a27d9013SAlfredo Cardigliano 1666598f6726SAlfredo Cardigliano /* Carrier ON here */ 1667be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1668be63459eSAndrew Boyer 1669be63459eSAndrew Boyer ionic_link_status_check(lif); 1670598f6726SAlfredo Cardigliano 1671598f6726SAlfredo Cardigliano return 0; 1672598f6726SAlfredo Cardigliano } 1673598f6726SAlfredo Cardigliano 1674598f6726SAlfredo Cardigliano int 1675669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1676669c8de6SAlfredo Cardigliano { 1677669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1678669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1679669c8de6SAlfredo Cardigliano int err; 1680669c8de6SAlfredo Cardigliano unsigned int i; 1681669c8de6SAlfredo Cardigliano unsigned int lif_words = sizeof(ident->lif.words) / 1682669c8de6SAlfredo Cardigliano sizeof(ident->lif.words[0]); 1683669c8de6SAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 1684669c8de6SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 1685669c8de6SAlfredo Cardigliano unsigned int nwords; 1686669c8de6SAlfredo Cardigliano 1687669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1688669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1689669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1690669c8de6SAlfredo Cardigliano if (err) 1691669c8de6SAlfredo Cardigliano return (err); 1692669c8de6SAlfredo Cardigliano 1693669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1694669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1695669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1696669c8de6SAlfredo Cardigliano 1697669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 1698669c8de6SAlfredo Cardigliano ident->lif.capabilities); 1699669c8de6SAlfredo Cardigliano 1700669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 1701669c8de6SAlfredo Cardigliano ident->lif.eth.max_ucast_filters); 1702669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 1703669c8de6SAlfredo Cardigliano ident->lif.eth.max_mcast_filters); 1704669c8de6SAlfredo Cardigliano 1705669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 1706669c8de6SAlfredo Cardigliano ident->lif.eth.config.features); 1707669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 1708669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]); 1709669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 1710669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]); 1711669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 1712669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 1713669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 1714669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 1715669c8de6SAlfredo Cardigliano 1716669c8de6SAlfredo Cardigliano return 0; 1717669c8de6SAlfredo Cardigliano } 1718669c8de6SAlfredo Cardigliano 1719669c8de6SAlfredo Cardigliano int 1720669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1721669c8de6SAlfredo Cardigliano { 1722669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 1723669c8de6SAlfredo Cardigliano uint32_t nintrs, dev_nintrs = ident->dev.nintrs; 1724669c8de6SAlfredo Cardigliano 1725669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 1726669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 1727669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 1728669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 1729669c8de6SAlfredo Cardigliano 173000b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1731669c8de6SAlfredo Cardigliano 1732669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 17334ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 17344ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1735669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1736669c8de6SAlfredo Cardigliano return -ENOSPC; 1737669c8de6SAlfredo Cardigliano } 1738669c8de6SAlfredo Cardigliano 1739669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1740669c8de6SAlfredo Cardigliano 1741669c8de6SAlfredo Cardigliano return 0; 1742669c8de6SAlfredo Cardigliano } 1743