176668754SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause 2a5205992SAndrew Boyer * Copyright 2018-2022 Advanced Micro Devices, Inc. 3669c8de6SAlfredo Cardigliano */ 4669c8de6SAlfredo Cardigliano 5669c8de6SAlfredo Cardigliano #include <rte_malloc.h> 6df96fd0dSBruce Richardson #include <ethdev_driver.h> 7669c8de6SAlfredo Cardigliano 8669c8de6SAlfredo Cardigliano #include "ionic.h" 9669c8de6SAlfredo Cardigliano #include "ionic_logs.h" 10669c8de6SAlfredo Cardigliano #include "ionic_lif.h" 11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h" 1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h" 13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h" 14669c8de6SAlfredo Cardigliano 15c5d15850SAndrew Boyer /* queuetype support level */ 16c5d15850SAndrew Boyer static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = { 17c5d15850SAndrew Boyer [IONIC_QTYPE_ADMINQ] = 0, /* 0 = Base version with CQ support */ 18c5d15850SAndrew Boyer [IONIC_QTYPE_NOTIFYQ] = 0, /* 0 = Base version */ 19c5d15850SAndrew Boyer [IONIC_QTYPE_RXQ] = 2, /* 0 = Base version with CQ+SG support 20c5d15850SAndrew Boyer * 1 = ... with EQ 21c5d15850SAndrew Boyer * 2 = ... with CMB 22c5d15850SAndrew Boyer */ 23c5d15850SAndrew Boyer [IONIC_QTYPE_TXQ] = 3, /* 0 = Base version with CQ+SG support 24c5d15850SAndrew Boyer * 1 = ... with Tx SG version 1 25c5d15850SAndrew Boyer * 2 = ... with EQ 26c5d15850SAndrew Boyer * 3 = ... with CMB 27c5d15850SAndrew Boyer */ 28c5d15850SAndrew Boyer }; 29c5d15850SAndrew Boyer 30598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr); 31598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr); 32598f6726SAlfredo Cardigliano 33e7222f94SAndrew Boyer static int 3401a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 3501a6c311SAlfredo Cardigliano { 3601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 374ad56b7aSAndrew Boyer struct ionic_lif *lif = qcq->lif; 3801a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 3901a6c311SAlfredo Cardigliano .pending_work = true, 4001a6c311SAlfredo Cardigliano .cmd.q_control = { 4101a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 4201a6c311SAlfredo Cardigliano .type = q->type, 4309f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 4401a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 4501a6c311SAlfredo Cardigliano }, 4601a6c311SAlfredo Cardigliano }; 4701a6c311SAlfredo Cardigliano 4801a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 4901a6c311SAlfredo Cardigliano } 5001a6c311SAlfredo Cardigliano 51be63459eSAndrew Boyer void 52be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif) 53598f6726SAlfredo Cardigliano { 54a0a99f21SAndrew Boyer uint32_t i; 55a0a99f21SAndrew Boyer 56be63459eSAndrew Boyer IONIC_PRINT_CALL(); 57598f6726SAlfredo Cardigliano 58be63459eSAndrew Boyer lif->state &= ~IONIC_LIF_F_UP; 59a0a99f21SAndrew Boyer 60a0a99f21SAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 61be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq = lif->rxqcqs[i]; 62a0a99f21SAndrew Boyer if (rxq->flags & IONIC_QCQ_F_INITED) 63a0a99f21SAndrew Boyer (void)ionic_dev_rx_queue_stop(lif->eth_dev, i); 64a0a99f21SAndrew Boyer } 65a0a99f21SAndrew Boyer 66a0a99f21SAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 67be39f75cSAndrew Boyer struct ionic_tx_qcq *txq = lif->txqcqs[i]; 68a0a99f21SAndrew Boyer if (txq->flags & IONIC_QCQ_F_INITED) 69a0a99f21SAndrew Boyer (void)ionic_dev_tx_queue_stop(lif->eth_dev, i); 70a0a99f21SAndrew Boyer } 71598f6726SAlfredo Cardigliano } 72598f6726SAlfredo Cardigliano 73598f6726SAlfredo Cardigliano void 74598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 75598f6726SAlfredo Cardigliano { 76598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 7775f96902SAndrew Boyer int err; 78598f6726SAlfredo Cardigliano 79598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 80598f6726SAlfredo Cardigliano 8100b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 8275f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 8375f96902SAndrew Boyer if (err) 844ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 85598f6726SAlfredo Cardigliano } 86598f6726SAlfredo Cardigliano 873cdfd905SAlfredo Cardigliano static void 883cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 893cdfd905SAlfredo Cardigliano { 903cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 913cdfd905SAlfredo Cardigliano uint32_t i; 923cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 933cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 943cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 953cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 963cdfd905SAlfredo Cardigliano 973cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 983cdfd905SAlfredo Cardigliano 993cdfd905SAlfredo Cardigliano if (ls == NULL) { 1003cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1013cdfd905SAlfredo Cardigliano lif->port_id); 1023cdfd905SAlfredo Cardigliano return; 1033cdfd905SAlfredo Cardigliano } 1043cdfd905SAlfredo Cardigliano 1053cdfd905SAlfredo Cardigliano /* RX */ 1063cdfd905SAlfredo Cardigliano 1073cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1083cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1093cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1103cdfd905SAlfredo Cardigliano 1113cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1123cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1133cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1143cdfd905SAlfredo Cardigliano 1153cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 116be39f75cSAndrew Boyer struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats; 11726cc5dc2SAndrew Boyer stats->ierrors += 1183cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1193cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1203cdfd905SAlfredo Cardigliano } 1213cdfd905SAlfredo Cardigliano 1223cdfd905SAlfredo Cardigliano stats->imissed += 1233cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1243cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1253cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1263cdfd905SAlfredo Cardigliano 12726cc5dc2SAndrew Boyer stats->ierrors += 1283cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1293cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1303cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1313cdfd905SAlfredo Cardigliano 1323cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 133be39f75cSAndrew Boyer struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats; 1343cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1353cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1363cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1373cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1383cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1393cdfd905SAlfredo Cardigliano } 1403cdfd905SAlfredo Cardigliano 1413cdfd905SAlfredo Cardigliano /* TX */ 1423cdfd905SAlfredo Cardigliano 1433cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1443cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1453cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1463cdfd905SAlfredo Cardigliano 1473cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1483cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1493cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1503cdfd905SAlfredo Cardigliano 1513cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 152be39f75cSAndrew Boyer struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats; 1533cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1543cdfd905SAlfredo Cardigliano } 1553cdfd905SAlfredo Cardigliano 1563cdfd905SAlfredo Cardigliano stats->oerrors += 1573cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1583cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1593cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1603cdfd905SAlfredo Cardigliano 1613cdfd905SAlfredo Cardigliano stats->oerrors += 1623cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1633cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1643cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1653cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1663cdfd905SAlfredo Cardigliano 1673cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 168be39f75cSAndrew Boyer struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats; 1693cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1703cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1713cdfd905SAlfredo Cardigliano } 1723cdfd905SAlfredo Cardigliano } 1733cdfd905SAlfredo Cardigliano 1743cdfd905SAlfredo Cardigliano void 1753cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 1763cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 1773cdfd905SAlfredo Cardigliano { 1783cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 1793cdfd905SAlfredo Cardigliano 1803cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 1813cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 1823cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 1833cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 1843cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 1853cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 1863cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 1873cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 1883cdfd905SAlfredo Cardigliano } 1893cdfd905SAlfredo Cardigliano 1903cdfd905SAlfredo Cardigliano void 1913cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 1923cdfd905SAlfredo Cardigliano { 1933cdfd905SAlfredo Cardigliano uint32_t i; 1943cdfd905SAlfredo Cardigliano 1953cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 196be39f75cSAndrew Boyer memset(&lif->rxqcqs[i]->stats, 0, 1973cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 198be39f75cSAndrew Boyer memset(&lif->txqcqs[i]->stats, 0, 1993cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2003cdfd905SAlfredo Cardigliano } 2013cdfd905SAlfredo Cardigliano 2023cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2033cdfd905SAlfredo Cardigliano } 2043cdfd905SAlfredo Cardigliano 2053cdfd905SAlfredo Cardigliano void 2063cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2073cdfd905SAlfredo Cardigliano { 2083cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2093cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2103cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2113cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2123cdfd905SAlfredo Cardigliano 2133cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2143cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2153cdfd905SAlfredo Cardigliano } 2163cdfd905SAlfredo Cardigliano 2173cdfd905SAlfredo Cardigliano void 2183cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2193cdfd905SAlfredo Cardigliano { 2203cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2213cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2223cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2233cdfd905SAlfredo Cardigliano 2243cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2253cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2263cdfd905SAlfredo Cardigliano } 2273cdfd905SAlfredo Cardigliano 228598f6726SAlfredo Cardigliano static int 22954fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 230598f6726SAlfredo Cardigliano { 23154fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 23254fe083fSAlfredo Cardigliano .pending_work = true, 23354fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 23454fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 23509f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC), 23654fe083fSAlfredo Cardigliano }, 23754fe083fSAlfredo Cardigliano }; 23854fe083fSAlfredo Cardigliano int err; 23954fe083fSAlfredo Cardigliano 24054fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 24154fe083fSAlfredo Cardigliano 24254fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 24354fe083fSAlfredo Cardigliano if (err) 24454fe083fSAlfredo Cardigliano return err; 24554fe083fSAlfredo Cardigliano 24654fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 24709f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 24854fe083fSAlfredo Cardigliano 24954fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 25054fe083fSAlfredo Cardigliano } 25154fe083fSAlfredo Cardigliano 25254fe083fSAlfredo Cardigliano static int 25354fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 25454fe083fSAlfredo Cardigliano { 25554fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 25654fe083fSAlfredo Cardigliano .pending_work = true, 25754fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 25854fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 25954fe083fSAlfredo Cardigliano }, 26054fe083fSAlfredo Cardigliano }; 26154fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 26254fe083fSAlfredo Cardigliano int err; 26354fe083fSAlfredo Cardigliano 26454fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 26554fe083fSAlfredo Cardigliano 26654fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 26754fe083fSAlfredo Cardigliano 26854fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 26954fe083fSAlfredo Cardigliano if (!f) { 27054fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 27154fe083fSAlfredo Cardigliano return -ENOENT; 27254fe083fSAlfredo Cardigliano } 27354fe083fSAlfredo Cardigliano 27409f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 27554fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 27654fe083fSAlfredo Cardigliano 27754fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 27854fe083fSAlfredo Cardigliano 27954fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 28054fe083fSAlfredo Cardigliano if (err) 28154fe083fSAlfredo Cardigliano return err; 28254fe083fSAlfredo Cardigliano 28354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 28409f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 285598f6726SAlfredo Cardigliano 286598f6726SAlfredo Cardigliano return 0; 287598f6726SAlfredo Cardigliano } 288598f6726SAlfredo Cardigliano 28954fe083fSAlfredo Cardigliano int 29054fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 29154fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 29254fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 293598f6726SAlfredo Cardigliano { 29454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 29554fe083fSAlfredo Cardigliano 29654fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 29754fe083fSAlfredo Cardigliano 29854fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 29954fe083fSAlfredo Cardigliano } 30054fe083fSAlfredo Cardigliano 30154fe083fSAlfredo Cardigliano void 30275f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 30354fe083fSAlfredo Cardigliano { 30454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 30554fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 30675f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 30754fe083fSAlfredo Cardigliano 30854fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 30954fe083fSAlfredo Cardigliano 31054fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 31154fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 31254fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 31354fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 31454fe083fSAlfredo Cardigliano return; 31554fe083fSAlfredo Cardigliano } 31654fe083fSAlfredo Cardigliano 31775f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 31875f96902SAndrew Boyer 31975f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 32054fe083fSAlfredo Cardigliano return; 32154fe083fSAlfredo Cardigliano 32275f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 32354fe083fSAlfredo Cardigliano } 32454fe083fSAlfredo Cardigliano 32554fe083fSAlfredo Cardigliano int 32654fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 32754fe083fSAlfredo Cardigliano { 32854fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 32954fe083fSAlfredo Cardigliano 33054fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 33154fe083fSAlfredo Cardigliano 33254fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 33354fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 33454fe083fSAlfredo Cardigliano return -1; 33554fe083fSAlfredo Cardigliano } 33654fe083fSAlfredo Cardigliano 33754fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 33854fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 33954fe083fSAlfredo Cardigliano lif->mac_addr); 34054fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 34154fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 34254fe083fSAlfredo Cardigliano } 34354fe083fSAlfredo Cardigliano 34454fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 34554fe083fSAlfredo Cardigliano 34654fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 34754fe083fSAlfredo Cardigliano 34854fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 34954fe083fSAlfredo Cardigliano } 35054fe083fSAlfredo Cardigliano 35154fe083fSAlfredo Cardigliano static int 35254fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 35354fe083fSAlfredo Cardigliano { 35454fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 35554fe083fSAlfredo Cardigliano .pending_work = true, 35654fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 35754fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 35809f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN), 35909f806e9SAndrew Boyer .vlan.vlan = rte_cpu_to_le_16(vid), 36054fe083fSAlfredo Cardigliano }, 36154fe083fSAlfredo Cardigliano }; 36254fe083fSAlfredo Cardigliano int err; 36354fe083fSAlfredo Cardigliano 36454fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 36554fe083fSAlfredo Cardigliano if (err) 36654fe083fSAlfredo Cardigliano return err; 36754fe083fSAlfredo Cardigliano 36854fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 36909f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 37054fe083fSAlfredo Cardigliano 37154fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 37254fe083fSAlfredo Cardigliano } 37354fe083fSAlfredo Cardigliano 37454fe083fSAlfredo Cardigliano static int 37554fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 37654fe083fSAlfredo Cardigliano { 37754fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 37854fe083fSAlfredo Cardigliano .pending_work = true, 37954fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 38054fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 38154fe083fSAlfredo Cardigliano }, 38254fe083fSAlfredo Cardigliano }; 38354fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 38454fe083fSAlfredo Cardigliano int err; 38554fe083fSAlfredo Cardigliano 38654fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 38754fe083fSAlfredo Cardigliano 38854fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 38954fe083fSAlfredo Cardigliano 39054fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 39154fe083fSAlfredo Cardigliano if (!f) { 39254fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 39354fe083fSAlfredo Cardigliano return -ENOENT; 39454fe083fSAlfredo Cardigliano } 39554fe083fSAlfredo Cardigliano 39609f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 39754fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 39854fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 39954fe083fSAlfredo Cardigliano 40054fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 40154fe083fSAlfredo Cardigliano if (err) 40254fe083fSAlfredo Cardigliano return err; 40354fe083fSAlfredo Cardigliano 40454fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 40509f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 406598f6726SAlfredo Cardigliano 407598f6726SAlfredo Cardigliano return 0; 408598f6726SAlfredo Cardigliano } 409598f6726SAlfredo Cardigliano 41054fe083fSAlfredo Cardigliano int 41154fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 41254fe083fSAlfredo Cardigliano int on) 41354fe083fSAlfredo Cardigliano { 41454fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 41554fe083fSAlfredo Cardigliano int err; 41654fe083fSAlfredo Cardigliano 41754fe083fSAlfredo Cardigliano if (on) 41854fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 41954fe083fSAlfredo Cardigliano else 42054fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 42154fe083fSAlfredo Cardigliano 42254fe083fSAlfredo Cardigliano return err; 42354fe083fSAlfredo Cardigliano } 42454fe083fSAlfredo Cardigliano 425598f6726SAlfredo Cardigliano static void 426598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 427598f6726SAlfredo Cardigliano { 428598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 429598f6726SAlfredo Cardigliano .pending_work = true, 430598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 431598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 43209f806e9SAndrew Boyer .rx_mode = rte_cpu_to_le_16(rx_mode), 433598f6726SAlfredo Cardigliano }, 434598f6726SAlfredo Cardigliano }; 435598f6726SAlfredo Cardigliano int err; 436598f6726SAlfredo Cardigliano 437598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 438598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 439598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 440598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 441598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 442598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 443598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 444598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 445598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 446598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 447598f6726SAlfredo Cardigliano 448598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 449598f6726SAlfredo Cardigliano if (err) 450598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 451598f6726SAlfredo Cardigliano } 452598f6726SAlfredo Cardigliano 453598f6726SAlfredo Cardigliano static void 454598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 455598f6726SAlfredo Cardigliano { 456598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 457598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 458598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 459598f6726SAlfredo Cardigliano } 460598f6726SAlfredo Cardigliano } 461598f6726SAlfredo Cardigliano 46254fe083fSAlfredo Cardigliano int 46354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 46454fe083fSAlfredo Cardigliano { 46554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 46654fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 46754fe083fSAlfredo Cardigliano 46854fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 46954fe083fSAlfredo Cardigliano 47054fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 47154fe083fSAlfredo Cardigliano 47254fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 47354fe083fSAlfredo Cardigliano 47454fe083fSAlfredo Cardigliano return 0; 47554fe083fSAlfredo Cardigliano } 47654fe083fSAlfredo Cardigliano 47754fe083fSAlfredo Cardigliano int 47854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 47954fe083fSAlfredo Cardigliano { 48054fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 48154fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 48254fe083fSAlfredo Cardigliano 48354fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 48454fe083fSAlfredo Cardigliano 48554fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 48654fe083fSAlfredo Cardigliano 48754fe083fSAlfredo Cardigliano return 0; 48854fe083fSAlfredo Cardigliano } 48954fe083fSAlfredo Cardigliano 49054fe083fSAlfredo Cardigliano int 49154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 49254fe083fSAlfredo Cardigliano { 49354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 49454fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 49554fe083fSAlfredo Cardigliano 49654fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 49754fe083fSAlfredo Cardigliano 49854fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 49954fe083fSAlfredo Cardigliano 50054fe083fSAlfredo Cardigliano return 0; 50154fe083fSAlfredo Cardigliano } 50254fe083fSAlfredo Cardigliano 50354fe083fSAlfredo Cardigliano int 50454fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 50554fe083fSAlfredo Cardigliano { 50654fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50754fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 50854fe083fSAlfredo Cardigliano 50954fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 51054fe083fSAlfredo Cardigliano 51154fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 51254fe083fSAlfredo Cardigliano 51354fe083fSAlfredo Cardigliano return 0; 51454fe083fSAlfredo Cardigliano } 515598f6726SAlfredo Cardigliano 516598f6726SAlfredo Cardigliano int 517b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu) 518598f6726SAlfredo Cardigliano { 519598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 520598f6726SAlfredo Cardigliano .pending_work = true, 521598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 522598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 523598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 52409f806e9SAndrew Boyer .mtu = rte_cpu_to_le_32(new_mtu), 525598f6726SAlfredo Cardigliano }, 526598f6726SAlfredo Cardigliano }; 527598f6726SAlfredo Cardigliano 528b671e69aSAndrew Boyer return ionic_adminq_post_wait(lif, &ctx); 529598f6726SAlfredo Cardigliano } 530598f6726SAlfredo Cardigliano 531598f6726SAlfredo Cardigliano int 53201a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 53301a6c311SAlfredo Cardigliano { 53401a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 53501a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 53601a6c311SAlfredo Cardigliano unsigned long index; 53701a6c311SAlfredo Cardigliano 53801a6c311SAlfredo Cardigliano /* 53901a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 54001a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5414ae96cb8SAndrew Boyer * which has index = 0) 54201a6c311SAlfredo Cardigliano */ 54301a6c311SAlfredo Cardigliano 54401a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 54501a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 54601a6c311SAlfredo Cardigliano break; 54701a6c311SAlfredo Cardigliano 54801a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 54901a6c311SAlfredo Cardigliano return -ENOSPC; 55001a6c311SAlfredo Cardigliano 55101a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 55201a6c311SAlfredo Cardigliano 55301a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 55401a6c311SAlfredo Cardigliano 55501a6c311SAlfredo Cardigliano return 0; 55601a6c311SAlfredo Cardigliano } 55701a6c311SAlfredo Cardigliano 55801a6c311SAlfredo Cardigliano static int 5594ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif, 5604ad56b7aSAndrew Boyer uint8_t type, 561be39f75cSAndrew Boyer size_t struct_size, 5628ec5ad7fSAndrew Boyer uint32_t socket_id, 56301a6c311SAlfredo Cardigliano uint32_t index, 5644ad56b7aSAndrew Boyer const char *type_name, 5654ad56b7aSAndrew Boyer uint16_t flags, 5664ad56b7aSAndrew Boyer uint16_t num_descs, 567d5850081SAndrew Boyer uint16_t num_segs, 5684ad56b7aSAndrew Boyer uint16_t desc_size, 5694ad56b7aSAndrew Boyer uint16_t cq_desc_size, 5704ad56b7aSAndrew Boyer uint16_t sg_desc_size, 5711abf69fcSAndrew Boyer struct ionic_qcq **qcq) 57201a6c311SAlfredo Cardigliano { 57301a6c311SAlfredo Cardigliano struct ionic_qcq *new; 57401a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 57501a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 57601a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 57701a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 57801a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 57901a6c311SAlfredo Cardigliano int err; 58001a6c311SAlfredo Cardigliano 58101a6c311SAlfredo Cardigliano *qcq = NULL; 58201a6c311SAlfredo Cardigliano 58301a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 58401a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 58501a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 58601a6c311SAlfredo Cardigliano 587924e6b76SThomas Monjalon total_size = RTE_ALIGN(q_size, rte_mem_page_size()) + 588924e6b76SThomas Monjalon RTE_ALIGN(cq_size, rte_mem_page_size()); 58901a6c311SAlfredo Cardigliano /* 59001a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 59101a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 592924e6b76SThomas Monjalon * Adding rte_mem_page_size(). 59301a6c311SAlfredo Cardigliano */ 594924e6b76SThomas Monjalon total_size += rte_mem_page_size(); 59501a6c311SAlfredo Cardigliano 59601a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 597924e6b76SThomas Monjalon total_size += RTE_ALIGN(sg_size, rte_mem_page_size()); 598924e6b76SThomas Monjalon total_size += rte_mem_page_size(); 59901a6c311SAlfredo Cardigliano } 60001a6c311SAlfredo Cardigliano 601be39f75cSAndrew Boyer new = rte_zmalloc("ionic", struct_size, 0); 60201a6c311SAlfredo Cardigliano if (!new) { 60301a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 60401a6c311SAlfredo Cardigliano return -ENOMEM; 60501a6c311SAlfredo Cardigliano } 60601a6c311SAlfredo Cardigliano 60701a6c311SAlfredo Cardigliano new->lif = lif; 60801a6c311SAlfredo Cardigliano 6097b20fc2fSAndrew Boyer /* Most queue types will store 1 ptr per descriptor */ 610be39f75cSAndrew Boyer new->q.info = rte_calloc_socket("ionic", 6117b20fc2fSAndrew Boyer num_descs * num_segs, sizeof(void *), 612924e6b76SThomas Monjalon rte_mem_page_size(), socket_id); 61301a6c311SAlfredo Cardigliano if (!new->q.info) { 61401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 6154c8f8d57SAndrew Boyer err = -ENOMEM; 6164c8f8d57SAndrew Boyer goto err_out_free_qcq; 61701a6c311SAlfredo Cardigliano } 61801a6c311SAlfredo Cardigliano 619d5850081SAndrew Boyer new->q.num_segs = num_segs; 62001a6c311SAlfredo Cardigliano new->q.type = type; 62101a6c311SAlfredo Cardigliano 6224ad56b7aSAndrew Boyer err = ionic_q_init(&new->q, index, num_descs); 62301a6c311SAlfredo Cardigliano if (err) { 62401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 6254c8f8d57SAndrew Boyer goto err_out_free_info; 62601a6c311SAlfredo Cardigliano } 62701a6c311SAlfredo Cardigliano 6282aed9865SAndrew Boyer err = ionic_cq_init(&new->cq, num_descs); 62901a6c311SAlfredo Cardigliano if (err) { 63001a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 6314c8f8d57SAndrew Boyer goto err_out_free_info; 63201a6c311SAlfredo Cardigliano } 63301a6c311SAlfredo Cardigliano 63401a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 6354ad56b7aSAndrew Boyer type_name, index /* queue_idx */, 63601a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 63701a6c311SAlfredo Cardigliano 63801a6c311SAlfredo Cardigliano if (!new->base_z) { 63901a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 64001a6c311SAlfredo Cardigliano err = -ENOMEM; 6414c8f8d57SAndrew Boyer goto err_out_free_info; 64201a6c311SAlfredo Cardigliano } 64301a6c311SAlfredo Cardigliano 64401a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 64501a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 64601a6c311SAlfredo Cardigliano 64701a6c311SAlfredo Cardigliano q_base = new->base; 64801a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 64901a6c311SAlfredo Cardigliano 650924e6b76SThomas Monjalon cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, 651924e6b76SThomas Monjalon rte_mem_page_size()); 652924e6b76SThomas Monjalon cq_base_pa = RTE_ALIGN(q_base_pa + q_size, 653924e6b76SThomas Monjalon rte_mem_page_size()); 65401a6c311SAlfredo Cardigliano 65501a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 65601a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 657924e6b76SThomas Monjalon rte_mem_page_size()); 658924e6b76SThomas Monjalon sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, 659924e6b76SThomas Monjalon rte_mem_page_size()); 66001a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 66101a6c311SAlfredo Cardigliano } 66201a6c311SAlfredo Cardigliano 6634ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6644ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 66501a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 66601a6c311SAlfredo Cardigliano 66701a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 66801a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 66901a6c311SAlfredo Cardigliano 67001a6c311SAlfredo Cardigliano *qcq = new; 67101a6c311SAlfredo Cardigliano 67201a6c311SAlfredo Cardigliano return 0; 67301a6c311SAlfredo Cardigliano 6744c8f8d57SAndrew Boyer err_out_free_info: 6754c8f8d57SAndrew Boyer rte_free(new->q.info); 6764c8f8d57SAndrew Boyer err_out_free_qcq: 6774c8f8d57SAndrew Boyer rte_free(new); 67801a6c311SAlfredo Cardigliano 67901a6c311SAlfredo Cardigliano return err; 68001a6c311SAlfredo Cardigliano } 68101a6c311SAlfredo Cardigliano 68201a6c311SAlfredo Cardigliano void 68301a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 68401a6c311SAlfredo Cardigliano { 68501a6c311SAlfredo Cardigliano if (qcq->base_z) { 68601a6c311SAlfredo Cardigliano qcq->base = NULL; 68701a6c311SAlfredo Cardigliano qcq->base_pa = 0; 68801a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 68901a6c311SAlfredo Cardigliano qcq->base_z = NULL; 69001a6c311SAlfredo Cardigliano } 69101a6c311SAlfredo Cardigliano 69201a6c311SAlfredo Cardigliano if (qcq->q.info) { 69301a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 69401a6c311SAlfredo Cardigliano qcq->q.info = NULL; 69501a6c311SAlfredo Cardigliano } 69601a6c311SAlfredo Cardigliano 69701a6c311SAlfredo Cardigliano rte_free(qcq); 69801a6c311SAlfredo Cardigliano } 69901a6c311SAlfredo Cardigliano 7007b20fc2fSAndrew Boyer static uint64_t 7017b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif) 7027b20fc2fSAndrew Boyer { 7037b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7047b20fc2fSAndrew Boyer 7057b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7067b20fc2fSAndrew Boyer 7077b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7087b20fc2fSAndrew Boyer rxm.data_off = RTE_PKTMBUF_HEADROOM; 7097b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7107b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7117b20fc2fSAndrew Boyer 7127b20fc2fSAndrew Boyer rte_compiler_barrier(); 7137b20fc2fSAndrew Boyer 7147b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7157b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7167b20fc2fSAndrew Boyer } 7177b20fc2fSAndrew Boyer 7187b20fc2fSAndrew Boyer static uint64_t 7197b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif) 7207b20fc2fSAndrew Boyer { 7217b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7227b20fc2fSAndrew Boyer 7237b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7247b20fc2fSAndrew Boyer 7257b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7267b20fc2fSAndrew Boyer rxm.data_off = 0; /* no headroom */ 7277b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7287b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7297b20fc2fSAndrew Boyer 7307b20fc2fSAndrew Boyer rte_compiler_barrier(); 7317b20fc2fSAndrew Boyer 7327b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7337b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7347b20fc2fSAndrew Boyer } 7357b20fc2fSAndrew Boyer 736a27d9013SAlfredo Cardigliano int 7378ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 738d5850081SAndrew Boyer uint16_t nrxq_descs, struct rte_mempool *mb_pool, 739d5850081SAndrew Boyer struct ionic_rx_qcq **rxq_out) 740a27d9013SAlfredo Cardigliano { 741be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq; 742d5850081SAndrew Boyer uint16_t flags, seg_size, hdr_seg_size, max_segs, max_segs_fw; 743d5850081SAndrew Boyer uint32_t max_mtu; 744be39f75cSAndrew Boyer int err; 745a27d9013SAlfredo Cardigliano 746a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 747b671e69aSAndrew Boyer 748d5850081SAndrew Boyer seg_size = rte_pktmbuf_data_room_size(mb_pool); 749d5850081SAndrew Boyer 750d5850081SAndrew Boyer /* The first mbuf needs to leave headroom */ 751d5850081SAndrew Boyer hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM; 752d5850081SAndrew Boyer 753d5850081SAndrew Boyer max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu); 754d5850081SAndrew Boyer 755d5850081SAndrew Boyer max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1; 756d5850081SAndrew Boyer 757d5850081SAndrew Boyer /* 758d5850081SAndrew Boyer * Calculate how many fragment pointers might be stored in queue. 7597b20fc2fSAndrew Boyer * This is the worst-case number, so that there's enough room in 7607b20fc2fSAndrew Boyer * the info array. 761d5850081SAndrew Boyer */ 762d5850081SAndrew Boyer max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size; 763d5850081SAndrew Boyer 7647b20fc2fSAndrew Boyer IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u", 7657b20fc2fSAndrew Boyer index, max_mtu, seg_size, max_segs); 766d5850081SAndrew Boyer if (max_segs > max_segs_fw) { 767d5850081SAndrew Boyer IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)", 768d5850081SAndrew Boyer max_segs, max_segs_fw); 769d5850081SAndrew Boyer return -EINVAL; 770d5850081SAndrew Boyer } 771d5850081SAndrew Boyer 7724ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 7734ad56b7aSAndrew Boyer IONIC_QTYPE_RXQ, 774be39f75cSAndrew Boyer sizeof(struct ionic_rx_qcq), 7758ec5ad7fSAndrew Boyer socket_id, 7764ad56b7aSAndrew Boyer index, 7774ad56b7aSAndrew Boyer "rx", 7784ad56b7aSAndrew Boyer flags, 779a27d9013SAlfredo Cardigliano nrxq_descs, 780d5850081SAndrew Boyer max_segs, 781a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 782a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 783a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 784be39f75cSAndrew Boyer (struct ionic_qcq **)&rxq); 785a27d9013SAlfredo Cardigliano if (err) 786a27d9013SAlfredo Cardigliano return err; 787a27d9013SAlfredo Cardigliano 788be39f75cSAndrew Boyer rxq->flags = flags; 789d5850081SAndrew Boyer rxq->seg_size = seg_size; 790d5850081SAndrew Boyer rxq->hdr_seg_size = hdr_seg_size; 7917b20fc2fSAndrew Boyer rxq->rearm_data = ionic_rx_rearm_data(lif); 7927b20fc2fSAndrew Boyer rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif); 793be39f75cSAndrew Boyer 794be39f75cSAndrew Boyer lif->rxqcqs[index] = rxq; 795be39f75cSAndrew Boyer *rxq_out = rxq; 796a27d9013SAlfredo Cardigliano 797a27d9013SAlfredo Cardigliano return 0; 798a27d9013SAlfredo Cardigliano } 799a27d9013SAlfredo Cardigliano 800a27d9013SAlfredo Cardigliano int 8018ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 802be39f75cSAndrew Boyer uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out) 803a27d9013SAlfredo Cardigliano { 804be39f75cSAndrew Boyer struct ionic_tx_qcq *txq; 805e19eea1eSAndrew Boyer uint16_t flags, num_segs_fw; 806be39f75cSAndrew Boyer int err; 807a27d9013SAlfredo Cardigliano 808a27d9013SAlfredo Cardigliano flags = IONIC_QCQ_F_SG; 809e19eea1eSAndrew Boyer 810e19eea1eSAndrew Boyer num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1; 811e19eea1eSAndrew Boyer 8124ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8134ad56b7aSAndrew Boyer IONIC_QTYPE_TXQ, 814be39f75cSAndrew Boyer sizeof(struct ionic_tx_qcq), 8158ec5ad7fSAndrew Boyer socket_id, 8164ad56b7aSAndrew Boyer index, 8174ad56b7aSAndrew Boyer "tx", 8184ad56b7aSAndrew Boyer flags, 819a27d9013SAlfredo Cardigliano ntxq_descs, 820*b4beb84aSAndrew Boyer num_segs_fw, 821a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 822a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 82356117636SAndrew Boyer sizeof(struct ionic_txq_sg_desc_v1), 824be39f75cSAndrew Boyer (struct ionic_qcq **)&txq); 825a27d9013SAlfredo Cardigliano if (err) 826a27d9013SAlfredo Cardigliano return err; 827a27d9013SAlfredo Cardigliano 828be39f75cSAndrew Boyer txq->flags = flags; 829e19eea1eSAndrew Boyer txq->num_segs_fw = num_segs_fw; 830be39f75cSAndrew Boyer 831be39f75cSAndrew Boyer lif->txqcqs[index] = txq; 832be39f75cSAndrew Boyer *txq_out = txq; 833a27d9013SAlfredo Cardigliano 834a27d9013SAlfredo Cardigliano return 0; 835a27d9013SAlfredo Cardigliano } 836a27d9013SAlfredo Cardigliano 83701a6c311SAlfredo Cardigliano static int 83801a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 83901a6c311SAlfredo Cardigliano { 840be39f75cSAndrew Boyer uint16_t flags = 0; 841be39f75cSAndrew Boyer int err; 84201a6c311SAlfredo Cardigliano 8434ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8444ad56b7aSAndrew Boyer IONIC_QTYPE_ADMINQ, 845be39f75cSAndrew Boyer sizeof(struct ionic_admin_qcq), 8468ec5ad7fSAndrew Boyer rte_socket_id(), 8474ad56b7aSAndrew Boyer 0, 8484ad56b7aSAndrew Boyer "admin", 8494ad56b7aSAndrew Boyer flags, 85001a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 851d5850081SAndrew Boyer 1, 85201a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 85301a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 85401a6c311SAlfredo Cardigliano 0, 855be39f75cSAndrew Boyer (struct ionic_qcq **)&lif->adminqcq); 85627b942c8SAlfredo Cardigliano if (err) 85727b942c8SAlfredo Cardigliano return err; 85801a6c311SAlfredo Cardigliano 85927b942c8SAlfredo Cardigliano return 0; 86027b942c8SAlfredo Cardigliano } 86127b942c8SAlfredo Cardigliano 86227b942c8SAlfredo Cardigliano static int 86327b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 86427b942c8SAlfredo Cardigliano { 865be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq; 8664c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 867be39f75cSAndrew Boyer uint16_t flags = 0; 868be39f75cSAndrew Boyer int err; 86927b942c8SAlfredo Cardigliano 8704ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8714ad56b7aSAndrew Boyer IONIC_QTYPE_NOTIFYQ, 872be39f75cSAndrew Boyer sizeof(struct ionic_notify_qcq), 8738ec5ad7fSAndrew Boyer rte_socket_id(), 8744ad56b7aSAndrew Boyer 0, 8754ad56b7aSAndrew Boyer "notify", 87627b942c8SAlfredo Cardigliano flags, 87727b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 878d5850081SAndrew Boyer 1, 87927b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 88027b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 88127b942c8SAlfredo Cardigliano 0, 882be39f75cSAndrew Boyer (struct ionic_qcq **)&nqcq); 88301a6c311SAlfredo Cardigliano if (err) 88401a6c311SAlfredo Cardigliano return err; 88501a6c311SAlfredo Cardigliano 8864c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 8874c8f8d57SAndrew Boyer if (err) { 888be39f75cSAndrew Boyer ionic_qcq_free(&nqcq->qcq); 8894c8f8d57SAndrew Boyer return err; 8904c8f8d57SAndrew Boyer } 8914c8f8d57SAndrew Boyer 8924c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 8934c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 8944c8f8d57SAndrew Boyer 8954c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 8964c8f8d57SAndrew Boyer 89701a6c311SAlfredo Cardigliano return 0; 89801a6c311SAlfredo Cardigliano } 89901a6c311SAlfredo Cardigliano 900c5d15850SAndrew Boyer static void 901c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif) 902c5d15850SAndrew Boyer { 903c5d15850SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 904c5d15850SAndrew Boyer struct ionic_dev *idev = &adapter->idev; 905c5d15850SAndrew Boyer union ionic_q_identity *q_ident = &adapter->ident.txq; 906c5d15850SAndrew Boyer uint32_t q_words = RTE_DIM(q_ident->words); 907c5d15850SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 908c5d15850SAndrew Boyer uint32_t i, nwords, qtype; 909c5d15850SAndrew Boyer int err; 910c5d15850SAndrew Boyer 911c5d15850SAndrew Boyer for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) { 912c5d15850SAndrew Boyer struct ionic_qtype_info *qti = &lif->qtype_info[qtype]; 913c5d15850SAndrew Boyer 914c5d15850SAndrew Boyer /* Filter out the types this driver knows about */ 915c5d15850SAndrew Boyer switch (qtype) { 916c5d15850SAndrew Boyer case IONIC_QTYPE_ADMINQ: 917c5d15850SAndrew Boyer case IONIC_QTYPE_NOTIFYQ: 918c5d15850SAndrew Boyer case IONIC_QTYPE_RXQ: 919c5d15850SAndrew Boyer case IONIC_QTYPE_TXQ: 920c5d15850SAndrew Boyer break; 921c5d15850SAndrew Boyer default: 922c5d15850SAndrew Boyer continue; 923c5d15850SAndrew Boyer } 924c5d15850SAndrew Boyer 925c5d15850SAndrew Boyer memset(qti, 0, sizeof(*qti)); 926c5d15850SAndrew Boyer 927c5d15850SAndrew Boyer ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC, 928c5d15850SAndrew Boyer qtype, ionic_qtype_vers[qtype]); 929c5d15850SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 930c5d15850SAndrew Boyer if (err == -EINVAL) { 931c5d15850SAndrew Boyer IONIC_PRINT(ERR, "qtype %d not supported\n", qtype); 932c5d15850SAndrew Boyer continue; 933c5d15850SAndrew Boyer } else if (err == -EIO) { 934c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, older FW\n"); 935c5d15850SAndrew Boyer return; 936c5d15850SAndrew Boyer } else if (err) { 937c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n", 938c5d15850SAndrew Boyer qtype, err); 939c5d15850SAndrew Boyer return; 940c5d15850SAndrew Boyer } 941c5d15850SAndrew Boyer 942c5d15850SAndrew Boyer nwords = RTE_MIN(q_words, cmd_words); 943c5d15850SAndrew Boyer for (i = 0; i < nwords; i++) 944c5d15850SAndrew Boyer q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]); 945c5d15850SAndrew Boyer 946c5d15850SAndrew Boyer qti->version = q_ident->version; 947c5d15850SAndrew Boyer qti->supported = q_ident->supported; 948c5d15850SAndrew Boyer qti->features = rte_le_to_cpu_64(q_ident->features); 949c5d15850SAndrew Boyer qti->desc_sz = rte_le_to_cpu_16(q_ident->desc_sz); 950c5d15850SAndrew Boyer qti->comp_sz = rte_le_to_cpu_16(q_ident->comp_sz); 951c5d15850SAndrew Boyer qti->sg_desc_sz = rte_le_to_cpu_16(q_ident->sg_desc_sz); 952c5d15850SAndrew Boyer qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems); 953c5d15850SAndrew Boyer qti->sg_desc_stride = 954c5d15850SAndrew Boyer rte_le_to_cpu_16(q_ident->sg_desc_stride); 955c5d15850SAndrew Boyer 956c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].version = %d", 957c5d15850SAndrew Boyer qtype, qti->version); 958c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x", 959c5d15850SAndrew Boyer qtype, qti->supported); 960c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx", 961c5d15850SAndrew Boyer qtype, qti->features); 962c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d", 963c5d15850SAndrew Boyer qtype, qti->desc_sz); 964c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d", 965c5d15850SAndrew Boyer qtype, qti->comp_sz); 966c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d", 967c5d15850SAndrew Boyer qtype, qti->sg_desc_sz); 968c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d", 969c5d15850SAndrew Boyer qtype, qti->max_sg_elems); 970c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d", 971c5d15850SAndrew Boyer qtype, qti->sg_desc_stride); 972c5d15850SAndrew Boyer } 973c5d15850SAndrew Boyer } 974c5d15850SAndrew Boyer 975669c8de6SAlfredo Cardigliano int 976669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 977669c8de6SAlfredo Cardigliano { 978c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 979669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 98001a6c311SAlfredo Cardigliano int err; 981669c8de6SAlfredo Cardigliano 9824ae96cb8SAndrew Boyer /* 9834ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 9844ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 9854ae96cb8SAndrew Boyer */ 9864ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 9874ae96cb8SAndrew Boyer 9884ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 989669c8de6SAlfredo Cardigliano 990c5d15850SAndrew Boyer ionic_lif_queue_identify(lif); 991c5d15850SAndrew Boyer 99256117636SAndrew Boyer if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) { 99356117636SAndrew Boyer IONIC_PRINT(ERR, "FW too old, please upgrade"); 99456117636SAndrew Boyer return -ENXIO; 99556117636SAndrew Boyer } 99656117636SAndrew Boyer 997669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 998669c8de6SAlfredo Cardigliano 99901a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 100001a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 100101a6c311SAlfredo Cardigliano 100284cf25bdSAndrew Boyer lif->kern_dbpage = adapter->idev.db_pages; 1003c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 1004c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 1005c67719e1SAlfredo Cardigliano return -ENOMEM; 1006c67719e1SAlfredo Cardigliano } 1007c67719e1SAlfredo Cardigliano 1008a27d9013SAlfredo Cardigliano lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) * 1009a27d9013SAlfredo Cardigliano adapter->max_ntxqs_per_lif, 0); 1010a27d9013SAlfredo Cardigliano 1011a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 1012a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 1013a27d9013SAlfredo Cardigliano return -ENOMEM; 1014a27d9013SAlfredo Cardigliano } 1015a27d9013SAlfredo Cardigliano 1016a27d9013SAlfredo Cardigliano lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) * 1017a27d9013SAlfredo Cardigliano adapter->max_nrxqs_per_lif, 0); 1018a27d9013SAlfredo Cardigliano 1019a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 1020a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 1021a27d9013SAlfredo Cardigliano return -ENOMEM; 1022a27d9013SAlfredo Cardigliano } 1023a27d9013SAlfredo Cardigliano 102427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 102527b942c8SAlfredo Cardigliano 102627b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 102727b942c8SAlfredo Cardigliano if (err) { 102827b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 102927b942c8SAlfredo Cardigliano return err; 103027b942c8SAlfredo Cardigliano } 103127b942c8SAlfredo Cardigliano 103227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 103327b942c8SAlfredo Cardigliano 103401a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 103501a6c311SAlfredo Cardigliano if (err) { 103601a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 103701a6c311SAlfredo Cardigliano return err; 103801a6c311SAlfredo Cardigliano } 103901a6c311SAlfredo Cardigliano 104001a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 104101a6c311SAlfredo Cardigliano 1042924e6b76SThomas Monjalon lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size()); 1043669c8de6SAlfredo Cardigliano 1044669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 1045669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 1046669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 1047669c8de6SAlfredo Cardigliano if (!lif->info_z) { 1048669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 1049669c8de6SAlfredo Cardigliano return -ENOMEM; 1050669c8de6SAlfredo Cardigliano } 1051669c8de6SAlfredo Cardigliano 1052669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 1053669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 1054669c8de6SAlfredo Cardigliano 1055669c8de6SAlfredo Cardigliano return 0; 1056669c8de6SAlfredo Cardigliano } 1057669c8de6SAlfredo Cardigliano 1058669c8de6SAlfredo Cardigliano void 1059669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 1060669c8de6SAlfredo Cardigliano { 106127b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 1062be39f75cSAndrew Boyer ionic_qcq_free(&lif->notifyqcq->qcq); 106327b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 106427b942c8SAlfredo Cardigliano } 106527b942c8SAlfredo Cardigliano 106601a6c311SAlfredo Cardigliano if (lif->adminqcq) { 1067be39f75cSAndrew Boyer ionic_qcq_free(&lif->adminqcq->qcq); 106801a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 106901a6c311SAlfredo Cardigliano } 107001a6c311SAlfredo Cardigliano 1071a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 1072a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 1073a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 1074a27d9013SAlfredo Cardigliano } 1075a27d9013SAlfredo Cardigliano 1076a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 1077a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 1078a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 1079a27d9013SAlfredo Cardigliano } 1080a27d9013SAlfredo Cardigliano 1081669c8de6SAlfredo Cardigliano if (lif->info) { 1082669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 1083669c8de6SAlfredo Cardigliano lif->info = NULL; 1084669c8de6SAlfredo Cardigliano } 1085669c8de6SAlfredo Cardigliano } 1086669c8de6SAlfredo Cardigliano 1087175e4e7eSAndrew Boyer void 1088175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 1089175e4e7eSAndrew Boyer { 1090175e4e7eSAndrew Boyer uint32_t i; 1091175e4e7eSAndrew Boyer 1092175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 10937483341aSXueming Li ionic_dev_tx_queue_release(lif->eth_dev, i); 1094175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 1095175e4e7eSAndrew Boyer } 1096175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 10977483341aSXueming Li ionic_dev_rx_queue_release(lif->eth_dev, i); 1098175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 1099175e4e7eSAndrew Boyer } 1100175e4e7eSAndrew Boyer } 1101175e4e7eSAndrew Boyer 110222e7171bSAlfredo Cardigliano int 110322e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 110422e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 110522e7171bSAlfredo Cardigliano { 110609f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 110722e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 110822e7171bSAlfredo Cardigliano .pending_work = true, 110922e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 111022e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 111122e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 111209f806e9SAndrew Boyer .rss.types = rte_cpu_to_le_16(types), 111309f806e9SAndrew Boyer .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa), 111422e7171bSAlfredo Cardigliano }, 111522e7171bSAlfredo Cardigliano }; 111622e7171bSAlfredo Cardigliano unsigned int i; 111709f806e9SAndrew Boyer uint16_t tbl_sz = 111809f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 111922e7171bSAlfredo Cardigliano 112022e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 112122e7171bSAlfredo Cardigliano 112222e7171bSAlfredo Cardigliano lif->rss_types = types; 112322e7171bSAlfredo Cardigliano 112422e7171bSAlfredo Cardigliano if (key) 112522e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 112622e7171bSAlfredo Cardigliano 112722e7171bSAlfredo Cardigliano if (indir) 112809f806e9SAndrew Boyer for (i = 0; i < tbl_sz; i++) 112922e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 113022e7171bSAlfredo Cardigliano 113122e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 113222e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 113322e7171bSAlfredo Cardigliano 113422e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 113522e7171bSAlfredo Cardigliano } 113622e7171bSAlfredo Cardigliano 113722e7171bSAlfredo Cardigliano static int 113822e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 113922e7171bSAlfredo Cardigliano { 114009f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 114122e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 114222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 114322e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 114422e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 114522e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 114622e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 114722e7171bSAlfredo Cardigliano }; 114822e7171bSAlfredo Cardigliano uint32_t i; 114909f806e9SAndrew Boyer uint16_t tbl_sz = 115009f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 115122e7171bSAlfredo Cardigliano 115222e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 115322e7171bSAlfredo Cardigliano 11543d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 115522e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 11563d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 11573d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 11583d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 115922e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 116022e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 116122e7171bSAlfredo Cardigliano return -ENOMEM; 116222e7171bSAlfredo Cardigliano } 116322e7171bSAlfredo Cardigliano 116422e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 116522e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 11663d845eddSAndrew Boyer } 11673d845eddSAndrew Boyer 11683d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 11693d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 117022e7171bSAlfredo Cardigliano 117122e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 11723d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 117322e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 11743d845eddSAndrew Boyer } 117522e7171bSAlfredo Cardigliano 11763d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 117722e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 117822e7171bSAlfredo Cardigliano } 117922e7171bSAlfredo Cardigliano 118022e7171bSAlfredo Cardigliano static void 118122e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 118222e7171bSAlfredo Cardigliano { 118322e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 118422e7171bSAlfredo Cardigliano return; 118522e7171bSAlfredo Cardigliano 118622e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 118722e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 118822e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 118922e7171bSAlfredo Cardigliano 119022e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 119122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 119222e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 119322e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 119422e7171bSAlfredo Cardigliano } 119522e7171bSAlfredo Cardigliano } 119622e7171bSAlfredo Cardigliano 1197be39f75cSAndrew Boyer void 1198be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq) 1199be39f75cSAndrew Boyer { 1200e7222f94SAndrew Boyer ionic_qcq_disable(&txq->qcq); 1201e7222f94SAndrew Boyer 1202be39f75cSAndrew Boyer txq->flags &= ~IONIC_QCQ_F_INITED; 1203be39f75cSAndrew Boyer } 1204be39f75cSAndrew Boyer 1205be39f75cSAndrew Boyer void 1206be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq) 1207be39f75cSAndrew Boyer { 1208e7222f94SAndrew Boyer ionic_qcq_disable(&rxq->qcq); 1209e7222f94SAndrew Boyer 1210be39f75cSAndrew Boyer rxq->flags &= ~IONIC_QCQ_F_INITED; 1211be39f75cSAndrew Boyer } 1212be39f75cSAndrew Boyer 121301a6c311SAlfredo Cardigliano static void 1214be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif) 121501a6c311SAlfredo Cardigliano { 1216be39f75cSAndrew Boyer lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED; 12174c8f8d57SAndrew Boyer } 12184c8f8d57SAndrew Boyer 12194c8f8d57SAndrew Boyer static void 12204c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 12214c8f8d57SAndrew Boyer { 1222be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 12234c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 12244c8f8d57SAndrew Boyer 12254c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 12264c8f8d57SAndrew Boyer return; 12274c8f8d57SAndrew Boyer 12284c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 12294c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 12304c8f8d57SAndrew Boyer 12314c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1232a27d9013SAlfredo Cardigliano } 1233a27d9013SAlfredo Cardigliano 123401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 123501a6c311SAlfredo Cardigliano int 123601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 123701a6c311SAlfredo Cardigliano void *cb_arg) 123801a6c311SAlfredo Cardigliano { 123901a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 124001a6c311SAlfredo Cardigliano uint32_t work_done; 124101a6c311SAlfredo Cardigliano 124201a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 124301a6c311SAlfredo Cardigliano 124401a6c311SAlfredo Cardigliano return work_done; 124501a6c311SAlfredo Cardigliano } 124601a6c311SAlfredo Cardigliano 124727b942c8SAlfredo Cardigliano static void 124827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 124927b942c8SAlfredo Cardigliano { 125027b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 125127b942c8SAlfredo Cardigliano bool link_up; 125227b942c8SAlfredo Cardigliano 125327b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 125427b942c8SAlfredo Cardigliano 125527b942c8SAlfredo Cardigliano if (!lif->info) 125627b942c8SAlfredo Cardigliano return; 125727b942c8SAlfredo Cardigliano 125827b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 125927b942c8SAlfredo Cardigliano 126027b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 126127b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 126227b942c8SAlfredo Cardigliano return; 126327b942c8SAlfredo Cardigliano 126427b942c8SAlfredo Cardigliano if (link_up) { 126509f806e9SAndrew Boyer adapter->link_speed = 126609f806e9SAndrew Boyer rte_le_to_cpu_32(lif->info->status.link_speed); 1267be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1268be63459eSAndrew Boyer adapter->link_speed); 126927b942c8SAlfredo Cardigliano } else { 127027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 127127b942c8SAlfredo Cardigliano } 127227b942c8SAlfredo Cardigliano 127327b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1274be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1275be63459eSAndrew Boyer } 1276be63459eSAndrew Boyer 1277be63459eSAndrew Boyer static void 1278be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1279be63459eSAndrew Boyer { 1280be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1281be63459eSAndrew Boyer return; 1282be63459eSAndrew Boyer 1283be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1284be63459eSAndrew Boyer 1285be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1286be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1287be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1288be63459eSAndrew Boyer ionic_lif_stop(lif); 1289be63459eSAndrew Boyer } 1290be63459eSAndrew Boyer 1291be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 129227b942c8SAlfredo Cardigliano } 129327b942c8SAlfredo Cardigliano 129427b942c8SAlfredo Cardigliano static bool 12954ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg) 129627b942c8SAlfredo Cardigliano { 129727b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 129827b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 129927b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 130027b942c8SAlfredo Cardigliano 130127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 130227b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 130327b942c8SAlfredo Cardigliano 130427b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 130527b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 130627b942c8SAlfredo Cardigliano return false; 130727b942c8SAlfredo Cardigliano 130827b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 130927b942c8SAlfredo Cardigliano 131027b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 131127b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 131227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1313be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1314be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1315be63459eSAndrew Boyer lif->name, 131627b942c8SAlfredo Cardigliano cq_desc->event.eid, 131727b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 131827b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 131927b942c8SAlfredo Cardigliano 132027b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 132127b942c8SAlfredo Cardigliano break; 1322be63459eSAndrew Boyer 1323be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1324be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1325be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1326be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1327be63459eSAndrew Boyer lif->name, 1328be63459eSAndrew Boyer cq_desc->event.eid, 1329be63459eSAndrew Boyer cq_desc->reset.reset_code, 1330be63459eSAndrew Boyer cq_desc->reset.state); 1331be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1332be63459eSAndrew Boyer break; 1333be63459eSAndrew Boyer 133427b942c8SAlfredo Cardigliano default: 133527b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 133627b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 133727b942c8SAlfredo Cardigliano break; 133827b942c8SAlfredo Cardigliano } 133927b942c8SAlfredo Cardigliano 134027b942c8SAlfredo Cardigliano return true; 134127b942c8SAlfredo Cardigliano } 134227b942c8SAlfredo Cardigliano 134327b942c8SAlfredo Cardigliano int 134427b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 134527b942c8SAlfredo Cardigliano { 134627b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1347be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 134827b942c8SAlfredo Cardigliano uint32_t work_done; 134927b942c8SAlfredo Cardigliano 1350be39f75cSAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) { 135127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 135227b942c8SAlfredo Cardigliano return -1; 135327b942c8SAlfredo Cardigliano } 135427b942c8SAlfredo Cardigliano 1355be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 135627b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 135727b942c8SAlfredo Cardigliano 1358be39f75cSAndrew Boyer work_done = ionic_qcq_service(&nqcq->qcq, budget, 1359be39f75cSAndrew Boyer ionic_notifyq_cb, lif); 136027b942c8SAlfredo Cardigliano 136127b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 136227b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 136327b942c8SAlfredo Cardigliano 1364be39f75cSAndrew Boyer ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index, 136527b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 136627b942c8SAlfredo Cardigliano 1367be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 136827b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 136927b942c8SAlfredo Cardigliano 137027b942c8SAlfredo Cardigliano return 0; 137127b942c8SAlfredo Cardigliano } 137227b942c8SAlfredo Cardigliano 137301a6c311SAlfredo Cardigliano static int 137401a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 137501a6c311SAlfredo Cardigliano { 137601a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1377be39f75cSAndrew Boyer struct ionic_admin_qcq *aqcq = lif->adminqcq; 1378be39f75cSAndrew Boyer struct ionic_queue *q = &aqcq->qcq.q; 137901a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 138001a6c311SAlfredo Cardigliano int err; 138101a6c311SAlfredo Cardigliano 1382be39f75cSAndrew Boyer ionic_dev_cmd_adminq_init(idev, &aqcq->qcq); 138301a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 138401a6c311SAlfredo Cardigliano if (err) 138501a6c311SAlfredo Cardigliano return err; 138601a6c311SAlfredo Cardigliano 138701a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 138801a6c311SAlfredo Cardigliano 138901a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 139009f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(comp.hw_index); 139101a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 139201a6c311SAlfredo Cardigliano 139301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 139401a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 139501a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 139601a6c311SAlfredo Cardigliano 1397be39f75cSAndrew Boyer aqcq->flags |= IONIC_QCQ_F_INITED; 139801a6c311SAlfredo Cardigliano 139901a6c311SAlfredo Cardigliano return 0; 140001a6c311SAlfredo Cardigliano } 140101a6c311SAlfredo Cardigliano 140227b942c8SAlfredo Cardigliano static int 140327b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 140427b942c8SAlfredo Cardigliano { 140527b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1406be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 1407be39f75cSAndrew Boyer struct ionic_queue *q = &nqcq->qcq.q; 14080a00bdafSAndrew Boyer uint16_t flags = IONIC_QINIT_F_ENA; 140927b942c8SAlfredo Cardigliano int err; 141027b942c8SAlfredo Cardigliano 141127b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 141227b942c8SAlfredo Cardigliano .pending_work = true, 141327b942c8SAlfredo Cardigliano .cmd.q_init = { 141427b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 141527b942c8SAlfredo Cardigliano .type = q->type, 1416c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 141709f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 14180a00bdafSAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 141927b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 142009f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 142127b942c8SAlfredo Cardigliano } 142227b942c8SAlfredo Cardigliano }; 142327b942c8SAlfredo Cardigliano 14240a00bdafSAndrew Boyer /* Only enable an interrupt if the device supports them */ 14250a00bdafSAndrew Boyer if (lif->adapter->intf->configure_intr != NULL) { 14260a00bdafSAndrew Boyer flags |= IONIC_QINIT_F_IRQ; 14270a00bdafSAndrew Boyer ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index); 14280a00bdafSAndrew Boyer } 14290a00bdafSAndrew Boyer ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags); 14300a00bdafSAndrew Boyer 143109f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index); 143209f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa); 143327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 143427b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14354ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 143627b942c8SAlfredo Cardigliano 143727b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 143827b942c8SAlfredo Cardigliano if (err) 143927b942c8SAlfredo Cardigliano return err; 144027b942c8SAlfredo Cardigliano 144127b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 144209f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 144327b942c8SAlfredo Cardigliano q->db = NULL; 144427b942c8SAlfredo Cardigliano 144527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 144627b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 144727b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 144827b942c8SAlfredo Cardigliano 1449be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 145027b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 145127b942c8SAlfredo Cardigliano 1452be39f75cSAndrew Boyer nqcq->flags |= IONIC_QCQ_F_INITED; 145327b942c8SAlfredo Cardigliano 145427b942c8SAlfredo Cardigliano return 0; 145527b942c8SAlfredo Cardigliano } 145627b942c8SAlfredo Cardigliano 1457669c8de6SAlfredo Cardigliano int 1458598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1459598f6726SAlfredo Cardigliano { 1460598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1461598f6726SAlfredo Cardigliano .pending_work = true, 1462598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1463598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1464598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 146509f806e9SAndrew Boyer .features = rte_cpu_to_le_64(lif->features), 1466598f6726SAlfredo Cardigliano }, 1467598f6726SAlfredo Cardigliano }; 1468598f6726SAlfredo Cardigliano int err; 1469598f6726SAlfredo Cardigliano 1470598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1471598f6726SAlfredo Cardigliano if (err) 1472598f6726SAlfredo Cardigliano return err; 1473598f6726SAlfredo Cardigliano 147409f806e9SAndrew Boyer lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features & 1475598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1476598f6726SAlfredo Cardigliano 1477598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1478598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1479598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1480598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1481598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1482598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1483598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1484598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1485598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1486598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1487598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1488598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1489598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1490598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1491598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1492598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1493598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1494598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1495598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1496598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1497598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1498598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1499598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1500598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1501598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1502598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1503598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1504598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1505598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1506598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1507598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1508598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1509598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1510598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1511598f6726SAlfredo Cardigliano 1512598f6726SAlfredo Cardigliano return 0; 1513598f6726SAlfredo Cardigliano } 1514598f6726SAlfredo Cardigliano 1515a27d9013SAlfredo Cardigliano int 1516be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq) 1517a27d9013SAlfredo Cardigliano { 1518be39f75cSAndrew Boyer struct ionic_qcq *qcq = &txq->qcq; 1519a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1520a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1521a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1522a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1523a27d9013SAlfredo Cardigliano .pending_work = true, 1524a27d9013SAlfredo Cardigliano .cmd.q_init = { 1525a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1526a27d9013SAlfredo Cardigliano .type = q->type, 1527c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 152809f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 152909f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 153009f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 153109f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1532a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 153309f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 153409f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 153509f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1536a27d9013SAlfredo Cardigliano }, 1537a27d9013SAlfredo Cardigliano }; 1538a27d9013SAlfredo Cardigliano int err; 1539a27d9013SAlfredo Cardigliano 154009f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.index %d", q->index); 154109f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1542a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1543a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 15444ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1545a27d9013SAlfredo Cardigliano 1546e7222f94SAndrew Boyer ionic_q_reset(q); 1547e7222f94SAndrew Boyer ionic_cq_reset(cq); 1548e7222f94SAndrew Boyer 1549be39f75cSAndrew Boyer err = ionic_adminq_post_wait(lif, &ctx); 1550a27d9013SAlfredo Cardigliano if (err) 1551a27d9013SAlfredo Cardigliano return err; 1552a27d9013SAlfredo Cardigliano 1553a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 155409f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1555a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1556a27d9013SAlfredo Cardigliano 1557a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1558a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1559a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1560a27d9013SAlfredo Cardigliano 1561be39f75cSAndrew Boyer txq->flags |= IONIC_QCQ_F_INITED; 1562a27d9013SAlfredo Cardigliano 1563a27d9013SAlfredo Cardigliano return 0; 1564a27d9013SAlfredo Cardigliano } 1565a27d9013SAlfredo Cardigliano 1566a27d9013SAlfredo Cardigliano int 1567be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq) 1568a27d9013SAlfredo Cardigliano { 1569be39f75cSAndrew Boyer struct ionic_qcq *qcq = &rxq->qcq; 1570a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1571a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1572a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1573a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1574a27d9013SAlfredo Cardigliano .pending_work = true, 1575a27d9013SAlfredo Cardigliano .cmd.q_init = { 1576a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1577a27d9013SAlfredo Cardigliano .type = q->type, 1578c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 157909f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 158009f806e9SAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG | 158109f806e9SAndrew Boyer IONIC_QINIT_F_ENA), 158209f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1583a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 158409f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 158509f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 158609f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1587a27d9013SAlfredo Cardigliano }, 1588a27d9013SAlfredo Cardigliano }; 1589a27d9013SAlfredo Cardigliano int err; 1590a27d9013SAlfredo Cardigliano 159109f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index); 159209f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1593a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1594a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 15954ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1596a27d9013SAlfredo Cardigliano 1597e7222f94SAndrew Boyer ionic_q_reset(q); 1598e7222f94SAndrew Boyer ionic_cq_reset(cq); 1599e7222f94SAndrew Boyer 1600be39f75cSAndrew Boyer err = ionic_adminq_post_wait(lif, &ctx); 1601a27d9013SAlfredo Cardigliano if (err) 1602a27d9013SAlfredo Cardigliano return err; 1603a27d9013SAlfredo Cardigliano 1604a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 160509f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1606a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1607a27d9013SAlfredo Cardigliano 1608be39f75cSAndrew Boyer rxq->flags |= IONIC_QCQ_F_INITED; 1609a27d9013SAlfredo Cardigliano 1610a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1611a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1612a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1613a27d9013SAlfredo Cardigliano 1614a27d9013SAlfredo Cardigliano return 0; 1615a27d9013SAlfredo Cardigliano } 1616a27d9013SAlfredo Cardigliano 1617598f6726SAlfredo Cardigliano static int 1618598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1619598f6726SAlfredo Cardigliano { 1620598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1621598f6726SAlfredo Cardigliano .pending_work = true, 1622598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1623598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1624598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1625598f6726SAlfredo Cardigliano }, 1626598f6726SAlfredo Cardigliano }; 1627598f6726SAlfredo Cardigliano int err; 1628598f6726SAlfredo Cardigliano 1629598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1630598f6726SAlfredo Cardigliano 1631598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1632598f6726SAlfredo Cardigliano if (err) 1633598f6726SAlfredo Cardigliano return err; 1634598f6726SAlfredo Cardigliano 1635598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1636598f6726SAlfredo Cardigliano 1637598f6726SAlfredo Cardigliano return 0; 1638598f6726SAlfredo Cardigliano } 1639598f6726SAlfredo Cardigliano 1640598f6726SAlfredo Cardigliano static void 1641598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1642598f6726SAlfredo Cardigliano { 1643598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1644598f6726SAlfredo Cardigliano .pending_work = true, 1645598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1646598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1647598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1648598f6726SAlfredo Cardigliano }, 1649598f6726SAlfredo Cardigliano }; 1650598f6726SAlfredo Cardigliano 16514ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 16524ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1653598f6726SAlfredo Cardigliano 1654598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1655598f6726SAlfredo Cardigliano } 1656598f6726SAlfredo Cardigliano 1657598f6726SAlfredo Cardigliano int 1658669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1659669c8de6SAlfredo Cardigliano { 1660669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1661656bfc9aSAndrew Boyer struct ionic_lif_init_comp comp; 1662669c8de6SAlfredo Cardigliano int err; 1663669c8de6SAlfredo Cardigliano 16643cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 16653cdfd905SAlfredo Cardigliano 166600b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1667669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1668669c8de6SAlfredo Cardigliano if (err) 1669669c8de6SAlfredo Cardigliano return err; 1670669c8de6SAlfredo Cardigliano 1671656bfc9aSAndrew Boyer ionic_dev_cmd_comp(idev, &comp); 1672656bfc9aSAndrew Boyer 167309f806e9SAndrew Boyer lif->hw_index = rte_cpu_to_le_16(comp.hw_index); 1674669c8de6SAlfredo Cardigliano 167501a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 167601a6c311SAlfredo Cardigliano if (err) 167701a6c311SAlfredo Cardigliano return err; 167801a6c311SAlfredo Cardigliano 167927b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 168027b942c8SAlfredo Cardigliano if (err) 168127b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 168227b942c8SAlfredo Cardigliano 168318a44465SAndrew Boyer /* 168418a44465SAndrew Boyer * Configure initial feature set 168518a44465SAndrew Boyer * This will be updated later by the dev_configure() step 168618a44465SAndrew Boyer */ 168718a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1688598f6726SAlfredo Cardigliano 1689598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1690598f6726SAlfredo Cardigliano if (err) 1691598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1692598f6726SAlfredo Cardigliano 169354fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1694598f6726SAlfredo Cardigliano if (err) 1695598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1696598f6726SAlfredo Cardigliano 169754fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 169854fe083fSAlfredo Cardigliano if (err) 169954fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 170054fe083fSAlfredo Cardigliano 1701598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1702598f6726SAlfredo Cardigliano 1703669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1704669c8de6SAlfredo Cardigliano 1705669c8de6SAlfredo Cardigliano return 0; 170627b942c8SAlfredo Cardigliano 170754fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 170854fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 170954fe083fSAlfredo Cardigliano 1710598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 17114c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1712598f6726SAlfredo Cardigliano 171327b942c8SAlfredo Cardigliano err_out_adminq_deinit: 1714be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 171527b942c8SAlfredo Cardigliano 171627b942c8SAlfredo Cardigliano return err; 1717669c8de6SAlfredo Cardigliano } 1718669c8de6SAlfredo Cardigliano 1719669c8de6SAlfredo Cardigliano void 1720669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1721669c8de6SAlfredo Cardigliano { 1722669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1723669c8de6SAlfredo Cardigliano return; 1724669c8de6SAlfredo Cardigliano 172554fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 172622e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 17274c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1728be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 172901a6c311SAlfredo Cardigliano 1730669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1731669c8de6SAlfredo Cardigliano } 1732669c8de6SAlfredo Cardigliano 173318a44465SAndrew Boyer void 173418a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 173518a44465SAndrew Boyer { 173618a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 173718a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 173818a44465SAndrew Boyer 173918a44465SAndrew Boyer /* 174018a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 1741295968d1SFerruh Yigit * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK 174218a44465SAndrew Boyer */ 1743295968d1SFerruh Yigit rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; 174418a44465SAndrew Boyer 1745295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_STRIP_MASK) { 1746295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 174718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 174818a44465SAndrew Boyer else 174918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 175018a44465SAndrew Boyer } 175118a44465SAndrew Boyer } 175218a44465SAndrew Boyer 175318a44465SAndrew Boyer void 1754598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1755598f6726SAlfredo Cardigliano { 175618a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 175718a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 175822e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 175909f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 176022e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 176109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 176222e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 176309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 176422e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 176522e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 176622e7171bSAlfredo Cardigliano 1767598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1768598f6726SAlfredo Cardigliano 176922e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 177022e7171bSAlfredo Cardigliano lif->port_id); 177122e7171bSAlfredo Cardigliano 177222e7171bSAlfredo Cardigliano if (nrxqs > 0) 177322e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 177422e7171bSAlfredo Cardigliano 177522e7171bSAlfredo Cardigliano if (ntxqs > 0) 177622e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 177722e7171bSAlfredo Cardigliano 177822e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 177922e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1780a27d9013SAlfredo Cardigliano 178118a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 178218a44465SAndrew Boyer 178318a44465SAndrew Boyer /* 178418a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 178518a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 1786295968d1SFerruh Yigit * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 178718a44465SAndrew Boyer */ 178818a44465SAndrew Boyer 178918a44465SAndrew Boyer /* RX per-port */ 179018a44465SAndrew Boyer 1791295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM || 1792295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM || 1793295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) 179418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 179518a44465SAndrew Boyer else 179618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 179718a44465SAndrew Boyer 1798295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) { 179918a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 180018a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 180118a44465SAndrew Boyer } else { 180218a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 180318a44465SAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 180418a44465SAndrew Boyer } 180518a44465SAndrew Boyer 180618a44465SAndrew Boyer /* Covers VLAN_STRIP */ 1807295968d1SFerruh Yigit ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK); 180818a44465SAndrew Boyer 180918a44465SAndrew Boyer /* TX per-port */ 181018a44465SAndrew Boyer 1811295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM || 1812295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM || 1813295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM || 1814295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM || 1815295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) 181618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 181718a44465SAndrew Boyer else 181818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 181918a44465SAndrew Boyer 1820295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) 182118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 182218a44465SAndrew Boyer else 182318a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 182418a44465SAndrew Boyer 1825295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) 182618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 182718a44465SAndrew Boyer else 182818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 182918a44465SAndrew Boyer 1830295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) { 183118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 183218a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 183318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 183418a44465SAndrew Boyer } else { 183518a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 183618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 183718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 183818a44465SAndrew Boyer } 1839598f6726SAlfredo Cardigliano } 1840598f6726SAlfredo Cardigliano 1841598f6726SAlfredo Cardigliano int 1842598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1843598f6726SAlfredo Cardigliano { 18440578335aSAndrew Boyer uint32_t rx_mode; 1845a27d9013SAlfredo Cardigliano uint32_t i; 1846a27d9013SAlfredo Cardigliano int err; 1847598f6726SAlfredo Cardigliano 184822e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 184922e7171bSAlfredo Cardigliano if (err) 185022e7171bSAlfredo Cardigliano return err; 185122e7171bSAlfredo Cardigliano 18520578335aSAndrew Boyer if (!lif->rx_mode) { 18530578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 18540578335aSAndrew Boyer lif->name); 1855598f6726SAlfredo Cardigliano 18560578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1857598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1858598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1859598f6726SAlfredo Cardigliano 1860598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 18610578335aSAndrew Boyer } 1862598f6726SAlfredo Cardigliano 1863a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1864a27d9013SAlfredo Cardigliano "on port %u", 1865a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1866a27d9013SAlfredo Cardigliano 1867a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1868be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq = lif->rxqcqs[i]; 186902eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1870a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1871a27d9013SAlfredo Cardigliano 1872a27d9013SAlfredo Cardigliano if (err) 1873a27d9013SAlfredo Cardigliano return err; 1874a27d9013SAlfredo Cardigliano } 1875a27d9013SAlfredo Cardigliano } 1876a27d9013SAlfredo Cardigliano 1877a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1878be39f75cSAndrew Boyer struct ionic_tx_qcq *txq = lif->txqcqs[i]; 187902eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1880a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1881a27d9013SAlfredo Cardigliano 1882a27d9013SAlfredo Cardigliano if (err) 1883a27d9013SAlfredo Cardigliano return err; 1884a27d9013SAlfredo Cardigliano } 1885a27d9013SAlfredo Cardigliano } 1886a27d9013SAlfredo Cardigliano 1887598f6726SAlfredo Cardigliano /* Carrier ON here */ 1888be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1889be63459eSAndrew Boyer 1890be63459eSAndrew Boyer ionic_link_status_check(lif); 1891598f6726SAlfredo Cardigliano 1892598f6726SAlfredo Cardigliano return 0; 1893598f6726SAlfredo Cardigliano } 1894598f6726SAlfredo Cardigliano 1895598f6726SAlfredo Cardigliano int 1896669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1897669c8de6SAlfredo Cardigliano { 1898669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1899669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 190009f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 190176276d71SAndrew Boyer uint32_t lif_words = RTE_DIM(ident->lif.words); 190276276d71SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 190376276d71SAndrew Boyer uint32_t i, nwords; 1904669c8de6SAlfredo Cardigliano int err; 1905669c8de6SAlfredo Cardigliano 1906669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1907669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1908669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1909669c8de6SAlfredo Cardigliano if (err) 1910669c8de6SAlfredo Cardigliano return (err); 1911669c8de6SAlfredo Cardigliano 1912669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1913669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1914669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1915669c8de6SAlfredo Cardigliano 1916669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 191709f806e9SAndrew Boyer rte_le_to_cpu_64(ident->lif.capabilities)); 1918669c8de6SAlfredo Cardigliano 1919669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 192009f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters)); 1921669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 192209f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters)); 1923669c8de6SAlfredo Cardigliano 1924669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 192509f806e9SAndrew Boyer rte_le_to_cpu_64(cfg->features)); 1926669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 192709f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ])); 1928669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 192909f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ])); 1930669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 193109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ])); 1932669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 193309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ])); 1934669c8de6SAlfredo Cardigliano 1935669c8de6SAlfredo Cardigliano return 0; 1936669c8de6SAlfredo Cardigliano } 1937669c8de6SAlfredo Cardigliano 1938669c8de6SAlfredo Cardigliano int 1939669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 1940669c8de6SAlfredo Cardigliano { 1941669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 194209f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 194309f806e9SAndrew Boyer uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs); 1944669c8de6SAlfredo Cardigliano 1945669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 194609f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 1947669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 194809f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 1949669c8de6SAlfredo Cardigliano 195000b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 1951669c8de6SAlfredo Cardigliano 1952669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 19534ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 19544ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 1955669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 1956669c8de6SAlfredo Cardigliano return -ENOSPC; 1957669c8de6SAlfredo Cardigliano } 1958669c8de6SAlfredo Cardigliano 1959669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 1960669c8de6SAlfredo Cardigliano 1961669c8de6SAlfredo Cardigliano return 0; 1962669c8de6SAlfredo Cardigliano } 1963