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 601c5d0bb79SAndrew Boyer new = rte_zmalloc_socket("ionic", struct_size, 602c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 60301a6c311SAlfredo Cardigliano if (!new) { 60401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 60501a6c311SAlfredo Cardigliano return -ENOMEM; 60601a6c311SAlfredo Cardigliano } 60701a6c311SAlfredo Cardigliano 60801a6c311SAlfredo Cardigliano new->lif = lif; 60901a6c311SAlfredo Cardigliano 6107b20fc2fSAndrew Boyer /* Most queue types will store 1 ptr per descriptor */ 611be39f75cSAndrew Boyer new->q.info = rte_calloc_socket("ionic", 6127b20fc2fSAndrew Boyer num_descs * num_segs, sizeof(void *), 613924e6b76SThomas Monjalon rte_mem_page_size(), socket_id); 61401a6c311SAlfredo Cardigliano if (!new->q.info) { 61501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 6164c8f8d57SAndrew Boyer err = -ENOMEM; 6174c8f8d57SAndrew Boyer goto err_out_free_qcq; 61801a6c311SAlfredo Cardigliano } 61901a6c311SAlfredo Cardigliano 620d5850081SAndrew Boyer new->q.num_segs = num_segs; 62101a6c311SAlfredo Cardigliano new->q.type = type; 62201a6c311SAlfredo Cardigliano 6234ad56b7aSAndrew Boyer err = ionic_q_init(&new->q, index, num_descs); 62401a6c311SAlfredo Cardigliano if (err) { 62501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 6264c8f8d57SAndrew Boyer goto err_out_free_info; 62701a6c311SAlfredo Cardigliano } 62801a6c311SAlfredo Cardigliano 6292aed9865SAndrew Boyer err = ionic_cq_init(&new->cq, num_descs); 63001a6c311SAlfredo Cardigliano if (err) { 63101a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 6324c8f8d57SAndrew Boyer goto err_out_free_info; 63301a6c311SAlfredo Cardigliano } 63401a6c311SAlfredo Cardigliano 63501a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 6364ad56b7aSAndrew Boyer type_name, index /* queue_idx */, 63701a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 63801a6c311SAlfredo Cardigliano 63901a6c311SAlfredo Cardigliano if (!new->base_z) { 64001a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 64101a6c311SAlfredo Cardigliano err = -ENOMEM; 6424c8f8d57SAndrew Boyer goto err_out_free_info; 64301a6c311SAlfredo Cardigliano } 64401a6c311SAlfredo Cardigliano 64501a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 64601a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 64701a6c311SAlfredo Cardigliano 64801a6c311SAlfredo Cardigliano q_base = new->base; 64901a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 65001a6c311SAlfredo Cardigliano 651924e6b76SThomas Monjalon cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, 652924e6b76SThomas Monjalon rte_mem_page_size()); 653924e6b76SThomas Monjalon cq_base_pa = RTE_ALIGN(q_base_pa + q_size, 654924e6b76SThomas Monjalon rte_mem_page_size()); 65501a6c311SAlfredo Cardigliano 65601a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 65701a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 658924e6b76SThomas Monjalon rte_mem_page_size()); 659924e6b76SThomas Monjalon sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, 660924e6b76SThomas Monjalon rte_mem_page_size()); 66101a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 66201a6c311SAlfredo Cardigliano } 66301a6c311SAlfredo Cardigliano 6649de21005SAndrew Boyer if (flags & IONIC_QCQ_F_CMB) { 6659de21005SAndrew Boyer /* alloc descriptor ring from nic memory */ 6669de21005SAndrew Boyer if (lif->adapter->cmb_offset + q_size > 6679de21005SAndrew Boyer lif->adapter->bars.bar[2].len) { 6689de21005SAndrew Boyer IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem"); 6699de21005SAndrew Boyer return -ENOMEM; 6709de21005SAndrew Boyer } 6719de21005SAndrew Boyer q_base = (void *) 6729de21005SAndrew Boyer ((uintptr_t)lif->adapter->bars.bar[2].vaddr + 6739de21005SAndrew Boyer (uintptr_t)lif->adapter->cmb_offset); 6749de21005SAndrew Boyer /* CMB PA is a relative address */ 6759de21005SAndrew Boyer q_base_pa = lif->adapter->cmb_offset; 6769de21005SAndrew Boyer lif->adapter->cmb_offset += q_size; 6779de21005SAndrew Boyer } 6789de21005SAndrew Boyer 6794ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6804ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 68101a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 68201a6c311SAlfredo Cardigliano 68301a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 68401a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 68501a6c311SAlfredo Cardigliano 68601a6c311SAlfredo Cardigliano *qcq = new; 68701a6c311SAlfredo Cardigliano 68801a6c311SAlfredo Cardigliano return 0; 68901a6c311SAlfredo Cardigliano 6904c8f8d57SAndrew Boyer err_out_free_info: 6914c8f8d57SAndrew Boyer rte_free(new->q.info); 6924c8f8d57SAndrew Boyer err_out_free_qcq: 6934c8f8d57SAndrew Boyer rte_free(new); 69401a6c311SAlfredo Cardigliano 69501a6c311SAlfredo Cardigliano return err; 69601a6c311SAlfredo Cardigliano } 69701a6c311SAlfredo Cardigliano 69801a6c311SAlfredo Cardigliano void 69901a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 70001a6c311SAlfredo Cardigliano { 70101a6c311SAlfredo Cardigliano if (qcq->base_z) { 70201a6c311SAlfredo Cardigliano qcq->base = NULL; 70301a6c311SAlfredo Cardigliano qcq->base_pa = 0; 70401a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 70501a6c311SAlfredo Cardigliano qcq->base_z = NULL; 70601a6c311SAlfredo Cardigliano } 70701a6c311SAlfredo Cardigliano 70801a6c311SAlfredo Cardigliano if (qcq->q.info) { 70901a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 71001a6c311SAlfredo Cardigliano qcq->q.info = NULL; 71101a6c311SAlfredo Cardigliano } 71201a6c311SAlfredo Cardigliano 71301a6c311SAlfredo Cardigliano rte_free(qcq); 71401a6c311SAlfredo Cardigliano } 71501a6c311SAlfredo Cardigliano 7167b20fc2fSAndrew Boyer static uint64_t 7177b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif) 7187b20fc2fSAndrew Boyer { 7197b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7207b20fc2fSAndrew Boyer 7217b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7227b20fc2fSAndrew Boyer 7237b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7247b20fc2fSAndrew Boyer rxm.data_off = RTE_PKTMBUF_HEADROOM; 7257b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7267b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7277b20fc2fSAndrew Boyer 7287b20fc2fSAndrew Boyer rte_compiler_barrier(); 7297b20fc2fSAndrew Boyer 7307b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7317b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7327b20fc2fSAndrew Boyer } 7337b20fc2fSAndrew Boyer 7347b20fc2fSAndrew Boyer static uint64_t 7357b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif) 7367b20fc2fSAndrew Boyer { 7377b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7387b20fc2fSAndrew Boyer 7397b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7407b20fc2fSAndrew Boyer 7417b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7427b20fc2fSAndrew Boyer rxm.data_off = 0; /* no headroom */ 7437b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7447b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7457b20fc2fSAndrew Boyer 7467b20fc2fSAndrew Boyer rte_compiler_barrier(); 7477b20fc2fSAndrew Boyer 7487b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7497b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7507b20fc2fSAndrew Boyer } 7517b20fc2fSAndrew Boyer 752a27d9013SAlfredo Cardigliano int 7538ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 754d5850081SAndrew Boyer uint16_t nrxq_descs, struct rte_mempool *mb_pool, 755d5850081SAndrew Boyer struct ionic_rx_qcq **rxq_out) 756a27d9013SAlfredo Cardigliano { 757be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq; 758*e86a6fccSAndrew Boyer uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1; 759d5850081SAndrew Boyer uint32_t max_mtu; 760be39f75cSAndrew Boyer int err; 761a27d9013SAlfredo Cardigliano 7629de21005SAndrew Boyer if (lif->state & IONIC_LIF_F_Q_IN_CMB) 7639de21005SAndrew Boyer flags |= IONIC_QCQ_F_CMB; 764b671e69aSAndrew Boyer 765d5850081SAndrew Boyer seg_size = rte_pktmbuf_data_room_size(mb_pool); 766d5850081SAndrew Boyer 767d5850081SAndrew Boyer /* The first mbuf needs to leave headroom */ 768d5850081SAndrew Boyer hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM; 769d5850081SAndrew Boyer 770d5850081SAndrew Boyer max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu); 771d5850081SAndrew Boyer 772*e86a6fccSAndrew Boyer /* If mbufs are too small to hold received packets, enable SG */ 773*e86a6fccSAndrew Boyer if (max_mtu > hdr_seg_size) { 774*e86a6fccSAndrew Boyer IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER"); 775*e86a6fccSAndrew Boyer lif->eth_dev->data->dev_conf.rxmode.offloads |= 776*e86a6fccSAndrew Boyer RTE_ETH_RX_OFFLOAD_SCATTER; 777*e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(lif); 778*e86a6fccSAndrew Boyer } 779*e86a6fccSAndrew Boyer 780*e86a6fccSAndrew Boyer if (lif->features & IONIC_ETH_HW_RX_SG) { 781*e86a6fccSAndrew Boyer flags |= IONIC_QCQ_F_SG; 782d5850081SAndrew Boyer max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1; 783*e86a6fccSAndrew Boyer } 784d5850081SAndrew Boyer 785d5850081SAndrew Boyer /* 786d5850081SAndrew Boyer * Calculate how many fragment pointers might be stored in queue. 7877b20fc2fSAndrew Boyer * This is the worst-case number, so that there's enough room in 7887b20fc2fSAndrew Boyer * the info array. 789d5850081SAndrew Boyer */ 790d5850081SAndrew Boyer max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size; 791d5850081SAndrew Boyer 7927b20fc2fSAndrew Boyer IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u", 7937b20fc2fSAndrew Boyer index, max_mtu, seg_size, max_segs); 794d5850081SAndrew Boyer if (max_segs > max_segs_fw) { 795d5850081SAndrew Boyer IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)", 796d5850081SAndrew Boyer max_segs, max_segs_fw); 797d5850081SAndrew Boyer return -EINVAL; 798d5850081SAndrew Boyer } 799d5850081SAndrew Boyer 8004ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8014ad56b7aSAndrew Boyer IONIC_QTYPE_RXQ, 802be39f75cSAndrew Boyer sizeof(struct ionic_rx_qcq), 8038ec5ad7fSAndrew Boyer socket_id, 8044ad56b7aSAndrew Boyer index, 8054ad56b7aSAndrew Boyer "rx", 8064ad56b7aSAndrew Boyer flags, 807a27d9013SAlfredo Cardigliano nrxq_descs, 808d5850081SAndrew Boyer max_segs, 809a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 810a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 811a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 812be39f75cSAndrew Boyer (struct ionic_qcq **)&rxq); 813a27d9013SAlfredo Cardigliano if (err) 814a27d9013SAlfredo Cardigliano return err; 815a27d9013SAlfredo Cardigliano 816be39f75cSAndrew Boyer rxq->flags = flags; 817d5850081SAndrew Boyer rxq->seg_size = seg_size; 818d5850081SAndrew Boyer rxq->hdr_seg_size = hdr_seg_size; 8197b20fc2fSAndrew Boyer rxq->rearm_data = ionic_rx_rearm_data(lif); 8207b20fc2fSAndrew Boyer rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif); 821be39f75cSAndrew Boyer 822be39f75cSAndrew Boyer lif->rxqcqs[index] = rxq; 823be39f75cSAndrew Boyer *rxq_out = rxq; 824a27d9013SAlfredo Cardigliano 825a27d9013SAlfredo Cardigliano return 0; 826a27d9013SAlfredo Cardigliano } 827a27d9013SAlfredo Cardigliano 828a27d9013SAlfredo Cardigliano int 8298ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 830be39f75cSAndrew Boyer uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out) 831a27d9013SAlfredo Cardigliano { 832be39f75cSAndrew Boyer struct ionic_tx_qcq *txq; 833*e86a6fccSAndrew Boyer uint16_t flags = 0, num_segs_fw = 1; 834be39f75cSAndrew Boyer int err; 835a27d9013SAlfredo Cardigliano 836*e86a6fccSAndrew Boyer if (lif->features & IONIC_ETH_HW_TX_SG) { 837*e86a6fccSAndrew Boyer flags |= IONIC_QCQ_F_SG; 838*e86a6fccSAndrew Boyer num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1; 839*e86a6fccSAndrew Boyer } 8409de21005SAndrew Boyer if (lif->state & IONIC_LIF_F_Q_IN_CMB) 8419de21005SAndrew Boyer flags |= IONIC_QCQ_F_CMB; 842e19eea1eSAndrew Boyer 843*e86a6fccSAndrew Boyer IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw); 844e19eea1eSAndrew Boyer 8454ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8464ad56b7aSAndrew Boyer IONIC_QTYPE_TXQ, 847be39f75cSAndrew Boyer sizeof(struct ionic_tx_qcq), 8488ec5ad7fSAndrew Boyer socket_id, 8494ad56b7aSAndrew Boyer index, 8504ad56b7aSAndrew Boyer "tx", 8514ad56b7aSAndrew Boyer flags, 852a27d9013SAlfredo Cardigliano ntxq_descs, 853b4beb84aSAndrew Boyer num_segs_fw, 854a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 855a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 85656117636SAndrew Boyer sizeof(struct ionic_txq_sg_desc_v1), 857be39f75cSAndrew Boyer (struct ionic_qcq **)&txq); 858a27d9013SAlfredo Cardigliano if (err) 859a27d9013SAlfredo Cardigliano return err; 860a27d9013SAlfredo Cardigliano 861be39f75cSAndrew Boyer txq->flags = flags; 862e19eea1eSAndrew Boyer txq->num_segs_fw = num_segs_fw; 863be39f75cSAndrew Boyer 864be39f75cSAndrew Boyer lif->txqcqs[index] = txq; 865be39f75cSAndrew Boyer *txq_out = txq; 866a27d9013SAlfredo Cardigliano 867a27d9013SAlfredo Cardigliano return 0; 868a27d9013SAlfredo Cardigliano } 869a27d9013SAlfredo Cardigliano 87001a6c311SAlfredo Cardigliano static int 87101a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 87201a6c311SAlfredo Cardigliano { 873be39f75cSAndrew Boyer uint16_t flags = 0; 874be39f75cSAndrew Boyer int err; 87501a6c311SAlfredo Cardigliano 8764ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8774ad56b7aSAndrew Boyer IONIC_QTYPE_ADMINQ, 878be39f75cSAndrew Boyer sizeof(struct ionic_admin_qcq), 8798ec5ad7fSAndrew Boyer rte_socket_id(), 8804ad56b7aSAndrew Boyer 0, 8814ad56b7aSAndrew Boyer "admin", 8824ad56b7aSAndrew Boyer flags, 88301a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 884d5850081SAndrew Boyer 1, 88501a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 88601a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 88701a6c311SAlfredo Cardigliano 0, 888be39f75cSAndrew Boyer (struct ionic_qcq **)&lif->adminqcq); 88927b942c8SAlfredo Cardigliano if (err) 89027b942c8SAlfredo Cardigliano return err; 89101a6c311SAlfredo Cardigliano 89227b942c8SAlfredo Cardigliano return 0; 89327b942c8SAlfredo Cardigliano } 89427b942c8SAlfredo Cardigliano 89527b942c8SAlfredo Cardigliano static int 89627b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 89727b942c8SAlfredo Cardigliano { 898be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq; 8994c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 900be39f75cSAndrew Boyer uint16_t flags = 0; 901be39f75cSAndrew Boyer int err; 90227b942c8SAlfredo Cardigliano 9034ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 9044ad56b7aSAndrew Boyer IONIC_QTYPE_NOTIFYQ, 905be39f75cSAndrew Boyer sizeof(struct ionic_notify_qcq), 9068ec5ad7fSAndrew Boyer rte_socket_id(), 9074ad56b7aSAndrew Boyer 0, 9084ad56b7aSAndrew Boyer "notify", 90927b942c8SAlfredo Cardigliano flags, 91027b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 911d5850081SAndrew Boyer 1, 91227b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 91327b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 91427b942c8SAlfredo Cardigliano 0, 915be39f75cSAndrew Boyer (struct ionic_qcq **)&nqcq); 91601a6c311SAlfredo Cardigliano if (err) 91701a6c311SAlfredo Cardigliano return err; 91801a6c311SAlfredo Cardigliano 9194c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 9204c8f8d57SAndrew Boyer if (err) { 921be39f75cSAndrew Boyer ionic_qcq_free(&nqcq->qcq); 9224c8f8d57SAndrew Boyer return err; 9234c8f8d57SAndrew Boyer } 9244c8f8d57SAndrew Boyer 9254c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 9264c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 9274c8f8d57SAndrew Boyer 9284c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 9294c8f8d57SAndrew Boyer 93001a6c311SAlfredo Cardigliano return 0; 93101a6c311SAlfredo Cardigliano } 93201a6c311SAlfredo Cardigliano 933c5d15850SAndrew Boyer static void 934c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif) 935c5d15850SAndrew Boyer { 936c5d15850SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 937c5d15850SAndrew Boyer struct ionic_dev *idev = &adapter->idev; 938c5d15850SAndrew Boyer union ionic_q_identity *q_ident = &adapter->ident.txq; 939c5d15850SAndrew Boyer uint32_t q_words = RTE_DIM(q_ident->words); 940c5d15850SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 941c5d15850SAndrew Boyer uint32_t i, nwords, qtype; 942c5d15850SAndrew Boyer int err; 943c5d15850SAndrew Boyer 944c5d15850SAndrew Boyer for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) { 945c5d15850SAndrew Boyer struct ionic_qtype_info *qti = &lif->qtype_info[qtype]; 946c5d15850SAndrew Boyer 947c5d15850SAndrew Boyer /* Filter out the types this driver knows about */ 948c5d15850SAndrew Boyer switch (qtype) { 949c5d15850SAndrew Boyer case IONIC_QTYPE_ADMINQ: 950c5d15850SAndrew Boyer case IONIC_QTYPE_NOTIFYQ: 951c5d15850SAndrew Boyer case IONIC_QTYPE_RXQ: 952c5d15850SAndrew Boyer case IONIC_QTYPE_TXQ: 953c5d15850SAndrew Boyer break; 954c5d15850SAndrew Boyer default: 955c5d15850SAndrew Boyer continue; 956c5d15850SAndrew Boyer } 957c5d15850SAndrew Boyer 958c5d15850SAndrew Boyer memset(qti, 0, sizeof(*qti)); 959c5d15850SAndrew Boyer 960c5d15850SAndrew Boyer ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC, 961c5d15850SAndrew Boyer qtype, ionic_qtype_vers[qtype]); 962c5d15850SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 963c5d15850SAndrew Boyer if (err == -EINVAL) { 964c5d15850SAndrew Boyer IONIC_PRINT(ERR, "qtype %d not supported\n", qtype); 965c5d15850SAndrew Boyer continue; 966c5d15850SAndrew Boyer } else if (err == -EIO) { 967c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, older FW\n"); 968c5d15850SAndrew Boyer return; 969c5d15850SAndrew Boyer } else if (err) { 970c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n", 971c5d15850SAndrew Boyer qtype, err); 972c5d15850SAndrew Boyer return; 973c5d15850SAndrew Boyer } 974c5d15850SAndrew Boyer 975c5d15850SAndrew Boyer nwords = RTE_MIN(q_words, cmd_words); 976c5d15850SAndrew Boyer for (i = 0; i < nwords; i++) 977c5d15850SAndrew Boyer q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]); 978c5d15850SAndrew Boyer 979c5d15850SAndrew Boyer qti->version = q_ident->version; 980c5d15850SAndrew Boyer qti->supported = q_ident->supported; 981c5d15850SAndrew Boyer qti->features = rte_le_to_cpu_64(q_ident->features); 982c5d15850SAndrew Boyer qti->desc_sz = rte_le_to_cpu_16(q_ident->desc_sz); 983c5d15850SAndrew Boyer qti->comp_sz = rte_le_to_cpu_16(q_ident->comp_sz); 984c5d15850SAndrew Boyer qti->sg_desc_sz = rte_le_to_cpu_16(q_ident->sg_desc_sz); 985c5d15850SAndrew Boyer qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems); 986c5d15850SAndrew Boyer qti->sg_desc_stride = 987c5d15850SAndrew Boyer rte_le_to_cpu_16(q_ident->sg_desc_stride); 988c5d15850SAndrew Boyer 989c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].version = %d", 990c5d15850SAndrew Boyer qtype, qti->version); 991c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x", 992c5d15850SAndrew Boyer qtype, qti->supported); 993c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx", 994c5d15850SAndrew Boyer qtype, qti->features); 995c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d", 996c5d15850SAndrew Boyer qtype, qti->desc_sz); 997c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d", 998c5d15850SAndrew Boyer qtype, qti->comp_sz); 999c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d", 1000c5d15850SAndrew Boyer qtype, qti->sg_desc_sz); 1001c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d", 1002c5d15850SAndrew Boyer qtype, qti->max_sg_elems); 1003c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d", 1004c5d15850SAndrew Boyer qtype, qti->sg_desc_stride); 1005c5d15850SAndrew Boyer } 1006c5d15850SAndrew Boyer } 1007c5d15850SAndrew Boyer 1008669c8de6SAlfredo Cardigliano int 1009669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 1010669c8de6SAlfredo Cardigliano { 1011c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 1012669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 101301a6c311SAlfredo Cardigliano int err; 1014669c8de6SAlfredo Cardigliano 10154ae96cb8SAndrew Boyer /* 10164ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 10174ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 10184ae96cb8SAndrew Boyer */ 10194ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 10204ae96cb8SAndrew Boyer 10214ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 1022669c8de6SAlfredo Cardigliano 1023c5d15850SAndrew Boyer ionic_lif_queue_identify(lif); 1024c5d15850SAndrew Boyer 102556117636SAndrew Boyer if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) { 102656117636SAndrew Boyer IONIC_PRINT(ERR, "FW too old, please upgrade"); 102756117636SAndrew Boyer return -ENXIO; 102856117636SAndrew Boyer } 102956117636SAndrew Boyer 10309de21005SAndrew Boyer if (adapter->q_in_cmb) { 10319de21005SAndrew Boyer if (adapter->bars.num_bars >= 3 && 10329de21005SAndrew Boyer lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 && 10339de21005SAndrew Boyer lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) { 10349de21005SAndrew Boyer IONIC_PRINT(INFO, "%s enabled on %s", 10359de21005SAndrew Boyer PMD_IONIC_CMB_KVARG, lif->name); 10369de21005SAndrew Boyer lif->state |= IONIC_LIF_F_Q_IN_CMB; 10379de21005SAndrew Boyer } else { 10389de21005SAndrew Boyer IONIC_PRINT(ERR, "%s not supported on %s, disabled", 10399de21005SAndrew Boyer PMD_IONIC_CMB_KVARG, lif->name); 10409de21005SAndrew Boyer } 10419de21005SAndrew Boyer } 10429de21005SAndrew Boyer 1043669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 1044669c8de6SAlfredo Cardigliano 104501a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 104601a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 104701a6c311SAlfredo Cardigliano 104884cf25bdSAndrew Boyer lif->kern_dbpage = adapter->idev.db_pages; 1049c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 1050c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 1051c67719e1SAlfredo Cardigliano return -ENOMEM; 1052c67719e1SAlfredo Cardigliano } 1053c67719e1SAlfredo Cardigliano 1054c5d0bb79SAndrew Boyer lif->txqcqs = rte_calloc_socket("ionic", 1055c663c7ecSAndrew Boyer adapter->max_ntxqs_per_lif, 1056c5d0bb79SAndrew Boyer sizeof(*lif->txqcqs), 1057c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 1058a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 1059a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 1060a27d9013SAlfredo Cardigliano return -ENOMEM; 1061a27d9013SAlfredo Cardigliano } 1062a27d9013SAlfredo Cardigliano 1063c5d0bb79SAndrew Boyer lif->rxqcqs = rte_calloc_socket("ionic", 1064c663c7ecSAndrew Boyer adapter->max_nrxqs_per_lif, 1065c5d0bb79SAndrew Boyer sizeof(*lif->rxqcqs), 1066c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 1067a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 1068a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 1069a27d9013SAlfredo Cardigliano return -ENOMEM; 1070a27d9013SAlfredo Cardigliano } 1071a27d9013SAlfredo Cardigliano 107227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 107327b942c8SAlfredo Cardigliano 107427b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 107527b942c8SAlfredo Cardigliano if (err) { 107627b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 107727b942c8SAlfredo Cardigliano return err; 107827b942c8SAlfredo Cardigliano } 107927b942c8SAlfredo Cardigliano 108027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 108127b942c8SAlfredo Cardigliano 108201a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 108301a6c311SAlfredo Cardigliano if (err) { 108401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 108501a6c311SAlfredo Cardigliano return err; 108601a6c311SAlfredo Cardigliano } 108701a6c311SAlfredo Cardigliano 108801a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 108901a6c311SAlfredo Cardigliano 1090924e6b76SThomas Monjalon lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size()); 1091669c8de6SAlfredo Cardigliano 1092669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 1093669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 1094669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 1095669c8de6SAlfredo Cardigliano if (!lif->info_z) { 1096669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 1097669c8de6SAlfredo Cardigliano return -ENOMEM; 1098669c8de6SAlfredo Cardigliano } 1099669c8de6SAlfredo Cardigliano 1100669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 1101669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 1102669c8de6SAlfredo Cardigliano 1103669c8de6SAlfredo Cardigliano return 0; 1104669c8de6SAlfredo Cardigliano } 1105669c8de6SAlfredo Cardigliano 1106669c8de6SAlfredo Cardigliano void 1107669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 1108669c8de6SAlfredo Cardigliano { 110927b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 1110be39f75cSAndrew Boyer ionic_qcq_free(&lif->notifyqcq->qcq); 111127b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 111227b942c8SAlfredo Cardigliano } 111327b942c8SAlfredo Cardigliano 111401a6c311SAlfredo Cardigliano if (lif->adminqcq) { 1115be39f75cSAndrew Boyer ionic_qcq_free(&lif->adminqcq->qcq); 111601a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 111701a6c311SAlfredo Cardigliano } 111801a6c311SAlfredo Cardigliano 1119a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 1120a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 1121a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 1122a27d9013SAlfredo Cardigliano } 1123a27d9013SAlfredo Cardigliano 1124a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 1125a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 1126a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 1127a27d9013SAlfredo Cardigliano } 1128a27d9013SAlfredo Cardigliano 1129669c8de6SAlfredo Cardigliano if (lif->info) { 1130669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 1131669c8de6SAlfredo Cardigliano lif->info = NULL; 1132669c8de6SAlfredo Cardigliano } 1133669c8de6SAlfredo Cardigliano } 1134669c8de6SAlfredo Cardigliano 1135175e4e7eSAndrew Boyer void 1136175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 1137175e4e7eSAndrew Boyer { 1138175e4e7eSAndrew Boyer uint32_t i; 1139175e4e7eSAndrew Boyer 1140175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 11417483341aSXueming Li ionic_dev_tx_queue_release(lif->eth_dev, i); 1142175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 1143175e4e7eSAndrew Boyer } 1144175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 11457483341aSXueming Li ionic_dev_rx_queue_release(lif->eth_dev, i); 1146175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 1147175e4e7eSAndrew Boyer } 1148175e4e7eSAndrew Boyer } 1149175e4e7eSAndrew Boyer 115022e7171bSAlfredo Cardigliano int 115122e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 115222e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 115322e7171bSAlfredo Cardigliano { 115409f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 115522e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 115622e7171bSAlfredo Cardigliano .pending_work = true, 115722e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 115822e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 115922e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 116009f806e9SAndrew Boyer .rss.types = rte_cpu_to_le_16(types), 116109f806e9SAndrew Boyer .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa), 116222e7171bSAlfredo Cardigliano }, 116322e7171bSAlfredo Cardigliano }; 116422e7171bSAlfredo Cardigliano unsigned int i; 116509f806e9SAndrew Boyer uint16_t tbl_sz = 116609f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 116722e7171bSAlfredo Cardigliano 116822e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 116922e7171bSAlfredo Cardigliano 117022e7171bSAlfredo Cardigliano lif->rss_types = types; 117122e7171bSAlfredo Cardigliano 117222e7171bSAlfredo Cardigliano if (key) 117322e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 117422e7171bSAlfredo Cardigliano 117522e7171bSAlfredo Cardigliano if (indir) 117609f806e9SAndrew Boyer for (i = 0; i < tbl_sz; i++) 117722e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 117822e7171bSAlfredo Cardigliano 117922e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 118022e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 118122e7171bSAlfredo Cardigliano 118222e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 118322e7171bSAlfredo Cardigliano } 118422e7171bSAlfredo Cardigliano 118522e7171bSAlfredo Cardigliano static int 118622e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 118722e7171bSAlfredo Cardigliano { 118809f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 118922e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 119022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 119122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 119222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 119322e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 119422e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 119522e7171bSAlfredo Cardigliano }; 119622e7171bSAlfredo Cardigliano uint32_t i; 119709f806e9SAndrew Boyer uint16_t tbl_sz = 119809f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 119922e7171bSAlfredo Cardigliano 120022e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 120122e7171bSAlfredo Cardigliano 12023d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 120322e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 12043d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 12053d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 12063d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 120722e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 120822e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 120922e7171bSAlfredo Cardigliano return -ENOMEM; 121022e7171bSAlfredo Cardigliano } 121122e7171bSAlfredo Cardigliano 121222e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 121322e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 12143d845eddSAndrew Boyer } 12153d845eddSAndrew Boyer 12163d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 12173d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 121822e7171bSAlfredo Cardigliano 121922e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 12203d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 122122e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 12223d845eddSAndrew Boyer } 122322e7171bSAlfredo Cardigliano 12243d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 122522e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 122622e7171bSAlfredo Cardigliano } 122722e7171bSAlfredo Cardigliano 122822e7171bSAlfredo Cardigliano static void 122922e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 123022e7171bSAlfredo Cardigliano { 123122e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl) 123222e7171bSAlfredo Cardigliano return; 123322e7171bSAlfredo Cardigliano 123422e7171bSAlfredo Cardigliano if (lif->rss_ind_tbl_z) { 123522e7171bSAlfredo Cardigliano /* Disable RSS on the NIC */ 123622e7171bSAlfredo Cardigliano ionic_lif_rss_config(lif, 0x0, NULL, NULL); 123722e7171bSAlfredo Cardigliano 123822e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 123922e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 124022e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 124122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 124222e7171bSAlfredo Cardigliano } 124322e7171bSAlfredo Cardigliano } 124422e7171bSAlfredo Cardigliano 1245be39f75cSAndrew Boyer void 1246be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq) 1247be39f75cSAndrew Boyer { 1248e7222f94SAndrew Boyer ionic_qcq_disable(&txq->qcq); 1249e7222f94SAndrew Boyer 1250be39f75cSAndrew Boyer txq->flags &= ~IONIC_QCQ_F_INITED; 1251be39f75cSAndrew Boyer } 1252be39f75cSAndrew Boyer 1253be39f75cSAndrew Boyer void 1254be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq) 1255be39f75cSAndrew Boyer { 1256e7222f94SAndrew Boyer ionic_qcq_disable(&rxq->qcq); 1257e7222f94SAndrew Boyer 1258be39f75cSAndrew Boyer rxq->flags &= ~IONIC_QCQ_F_INITED; 1259be39f75cSAndrew Boyer } 1260be39f75cSAndrew Boyer 126101a6c311SAlfredo Cardigliano static void 1262be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif) 126301a6c311SAlfredo Cardigliano { 1264be39f75cSAndrew Boyer lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED; 12654c8f8d57SAndrew Boyer } 12664c8f8d57SAndrew Boyer 12674c8f8d57SAndrew Boyer static void 12684c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 12694c8f8d57SAndrew Boyer { 1270be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 12714c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 12724c8f8d57SAndrew Boyer 12734c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 12744c8f8d57SAndrew Boyer return; 12754c8f8d57SAndrew Boyer 12764c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 12774c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 12784c8f8d57SAndrew Boyer 12794c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1280a27d9013SAlfredo Cardigliano } 1281a27d9013SAlfredo Cardigliano 128201a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 128301a6c311SAlfredo Cardigliano int 128401a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 128501a6c311SAlfredo Cardigliano void *cb_arg) 128601a6c311SAlfredo Cardigliano { 128701a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 128801a6c311SAlfredo Cardigliano uint32_t work_done; 128901a6c311SAlfredo Cardigliano 129001a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 129101a6c311SAlfredo Cardigliano 129201a6c311SAlfredo Cardigliano return work_done; 129301a6c311SAlfredo Cardigliano } 129401a6c311SAlfredo Cardigliano 129527b942c8SAlfredo Cardigliano static void 129627b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 129727b942c8SAlfredo Cardigliano { 129827b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 129927b942c8SAlfredo Cardigliano bool link_up; 130027b942c8SAlfredo Cardigliano 130127b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 130227b942c8SAlfredo Cardigliano 130327b942c8SAlfredo Cardigliano if (!lif->info) 130427b942c8SAlfredo Cardigliano return; 130527b942c8SAlfredo Cardigliano 130627b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 130727b942c8SAlfredo Cardigliano 130827b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 130927b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 131027b942c8SAlfredo Cardigliano return; 131127b942c8SAlfredo Cardigliano 131227b942c8SAlfredo Cardigliano if (link_up) { 131309f806e9SAndrew Boyer adapter->link_speed = 131409f806e9SAndrew Boyer rte_le_to_cpu_32(lif->info->status.link_speed); 1315be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1316be63459eSAndrew Boyer adapter->link_speed); 131727b942c8SAlfredo Cardigliano } else { 131827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 131927b942c8SAlfredo Cardigliano } 132027b942c8SAlfredo Cardigliano 132127b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1322be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1323be63459eSAndrew Boyer } 1324be63459eSAndrew Boyer 1325be63459eSAndrew Boyer static void 1326be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1327be63459eSAndrew Boyer { 1328be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1329be63459eSAndrew Boyer return; 1330be63459eSAndrew Boyer 1331be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1332be63459eSAndrew Boyer 1333be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1334be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1335be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1336be63459eSAndrew Boyer ionic_lif_stop(lif); 1337be63459eSAndrew Boyer } 1338be63459eSAndrew Boyer 1339be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 134027b942c8SAlfredo Cardigliano } 134127b942c8SAlfredo Cardigliano 134227b942c8SAlfredo Cardigliano static bool 13434ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg) 134427b942c8SAlfredo Cardigliano { 134527b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 134627b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 134727b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 134827b942c8SAlfredo Cardigliano 134927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 135027b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 135127b942c8SAlfredo Cardigliano 135227b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 135327b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 135427b942c8SAlfredo Cardigliano return false; 135527b942c8SAlfredo Cardigliano 135627b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 135727b942c8SAlfredo Cardigliano 135827b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 135927b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 136027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1361be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1362be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1363be63459eSAndrew Boyer lif->name, 136427b942c8SAlfredo Cardigliano cq_desc->event.eid, 136527b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 136627b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 136727b942c8SAlfredo Cardigliano 136827b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 136927b942c8SAlfredo Cardigliano break; 1370be63459eSAndrew Boyer 1371be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1372be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1373be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1374be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1375be63459eSAndrew Boyer lif->name, 1376be63459eSAndrew Boyer cq_desc->event.eid, 1377be63459eSAndrew Boyer cq_desc->reset.reset_code, 1378be63459eSAndrew Boyer cq_desc->reset.state); 1379be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1380be63459eSAndrew Boyer break; 1381be63459eSAndrew Boyer 138227b942c8SAlfredo Cardigliano default: 138327b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 138427b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 138527b942c8SAlfredo Cardigliano break; 138627b942c8SAlfredo Cardigliano } 138727b942c8SAlfredo Cardigliano 138827b942c8SAlfredo Cardigliano return true; 138927b942c8SAlfredo Cardigliano } 139027b942c8SAlfredo Cardigliano 139127b942c8SAlfredo Cardigliano int 139227b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 139327b942c8SAlfredo Cardigliano { 139427b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1395be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 139627b942c8SAlfredo Cardigliano uint32_t work_done; 139727b942c8SAlfredo Cardigliano 1398be39f75cSAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) { 139927b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 140027b942c8SAlfredo Cardigliano return -1; 140127b942c8SAlfredo Cardigliano } 140227b942c8SAlfredo Cardigliano 1403be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 140427b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 140527b942c8SAlfredo Cardigliano 1406be39f75cSAndrew Boyer work_done = ionic_qcq_service(&nqcq->qcq, budget, 1407be39f75cSAndrew Boyer ionic_notifyq_cb, lif); 140827b942c8SAlfredo Cardigliano 140927b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 141027b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 141127b942c8SAlfredo Cardigliano 1412be39f75cSAndrew Boyer ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index, 141327b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 141427b942c8SAlfredo Cardigliano 1415be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 141627b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 141727b942c8SAlfredo Cardigliano 141827b942c8SAlfredo Cardigliano return 0; 141927b942c8SAlfredo Cardigliano } 142027b942c8SAlfredo Cardigliano 142101a6c311SAlfredo Cardigliano static int 142201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 142301a6c311SAlfredo Cardigliano { 142401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1425be39f75cSAndrew Boyer struct ionic_admin_qcq *aqcq = lif->adminqcq; 1426be39f75cSAndrew Boyer struct ionic_queue *q = &aqcq->qcq.q; 142701a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 142801a6c311SAlfredo Cardigliano int err; 142901a6c311SAlfredo Cardigliano 1430be39f75cSAndrew Boyer ionic_dev_cmd_adminq_init(idev, &aqcq->qcq); 143101a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 143201a6c311SAlfredo Cardigliano if (err) 143301a6c311SAlfredo Cardigliano return err; 143401a6c311SAlfredo Cardigliano 143501a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 143601a6c311SAlfredo Cardigliano 143701a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 143809f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(comp.hw_index); 143901a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 144001a6c311SAlfredo Cardigliano 144101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 144201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 144301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 144401a6c311SAlfredo Cardigliano 1445be39f75cSAndrew Boyer aqcq->flags |= IONIC_QCQ_F_INITED; 144601a6c311SAlfredo Cardigliano 144701a6c311SAlfredo Cardigliano return 0; 144801a6c311SAlfredo Cardigliano } 144901a6c311SAlfredo Cardigliano 145027b942c8SAlfredo Cardigliano static int 145127b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 145227b942c8SAlfredo Cardigliano { 145327b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1454be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 1455be39f75cSAndrew Boyer struct ionic_queue *q = &nqcq->qcq.q; 14560a00bdafSAndrew Boyer uint16_t flags = IONIC_QINIT_F_ENA; 145727b942c8SAlfredo Cardigliano int err; 145827b942c8SAlfredo Cardigliano 145927b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 146027b942c8SAlfredo Cardigliano .pending_work = true, 146127b942c8SAlfredo Cardigliano .cmd.q_init = { 146227b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 146327b942c8SAlfredo Cardigliano .type = q->type, 1464c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 146509f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 14660a00bdafSAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 146727b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 146809f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 146927b942c8SAlfredo Cardigliano } 147027b942c8SAlfredo Cardigliano }; 147127b942c8SAlfredo Cardigliano 14720a00bdafSAndrew Boyer /* Only enable an interrupt if the device supports them */ 14730a00bdafSAndrew Boyer if (lif->adapter->intf->configure_intr != NULL) { 14740a00bdafSAndrew Boyer flags |= IONIC_QINIT_F_IRQ; 14750a00bdafSAndrew Boyer ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index); 14760a00bdafSAndrew Boyer } 14770a00bdafSAndrew Boyer ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags); 14780a00bdafSAndrew Boyer 147909f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index); 148009f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa); 148127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 148227b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 14834ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 148427b942c8SAlfredo Cardigliano 148527b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 148627b942c8SAlfredo Cardigliano if (err) 148727b942c8SAlfredo Cardigliano return err; 148827b942c8SAlfredo Cardigliano 148927b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 149009f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 149127b942c8SAlfredo Cardigliano q->db = NULL; 149227b942c8SAlfredo Cardigliano 149327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 149427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 149527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 149627b942c8SAlfredo Cardigliano 1497be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 149827b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 149927b942c8SAlfredo Cardigliano 1500be39f75cSAndrew Boyer nqcq->flags |= IONIC_QCQ_F_INITED; 150127b942c8SAlfredo Cardigliano 150227b942c8SAlfredo Cardigliano return 0; 150327b942c8SAlfredo Cardigliano } 150427b942c8SAlfredo Cardigliano 1505669c8de6SAlfredo Cardigliano int 1506598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1507598f6726SAlfredo Cardigliano { 1508598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1509598f6726SAlfredo Cardigliano .pending_work = true, 1510598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1511598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1512598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 151309f806e9SAndrew Boyer .features = rte_cpu_to_le_64(lif->features), 1514598f6726SAlfredo Cardigliano }, 1515598f6726SAlfredo Cardigliano }; 1516598f6726SAlfredo Cardigliano int err; 1517598f6726SAlfredo Cardigliano 1518598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1519598f6726SAlfredo Cardigliano if (err) 1520598f6726SAlfredo Cardigliano return err; 1521598f6726SAlfredo Cardigliano 152209f806e9SAndrew Boyer lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features & 1523598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1524598f6726SAlfredo Cardigliano 1525598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1526598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1527598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1528598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1529598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1530598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1531598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1532598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1533598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1534598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1535598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1536598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1537598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1538598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1539598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1540598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1541598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1542598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1543598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1544598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1545598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1546598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1547598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1548598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1549598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1550598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1551598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1552598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1553598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1554598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1555598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1556598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1557598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1558598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1559598f6726SAlfredo Cardigliano 1560598f6726SAlfredo Cardigliano return 0; 1561598f6726SAlfredo Cardigliano } 1562598f6726SAlfredo Cardigliano 1563a27d9013SAlfredo Cardigliano int 1564be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq) 1565a27d9013SAlfredo Cardigliano { 1566be39f75cSAndrew Boyer struct ionic_qcq *qcq = &txq->qcq; 1567a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1568a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1569a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1570a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1571a27d9013SAlfredo Cardigliano .pending_work = true, 1572a27d9013SAlfredo Cardigliano .cmd.q_init = { 1573a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1574a27d9013SAlfredo Cardigliano .type = q->type, 1575c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 157609f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1577*e86a6fccSAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA), 157809f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1579a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 158009f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 158109f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 158209f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1583a27d9013SAlfredo Cardigliano }, 1584a27d9013SAlfredo Cardigliano }; 1585a27d9013SAlfredo Cardigliano int err; 1586a27d9013SAlfredo Cardigliano 1587*e86a6fccSAndrew Boyer if (txq->flags & IONIC_QCQ_F_SG) 1588*e86a6fccSAndrew Boyer ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG); 15899de21005SAndrew Boyer if (txq->flags & IONIC_QCQ_F_CMB) 15909de21005SAndrew Boyer ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB); 15919de21005SAndrew Boyer 159209f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.index %d", q->index); 159309f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1594a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1595a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 15964ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver); 1597a27d9013SAlfredo Cardigliano 1598e7222f94SAndrew Boyer ionic_q_reset(q); 1599e7222f94SAndrew Boyer ionic_cq_reset(cq); 1600e7222f94SAndrew Boyer 1601be39f75cSAndrew Boyer err = ionic_adminq_post_wait(lif, &ctx); 1602a27d9013SAlfredo Cardigliano if (err) 1603a27d9013SAlfredo Cardigliano return err; 1604a27d9013SAlfredo Cardigliano 1605a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 160609f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1607a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1608a27d9013SAlfredo Cardigliano 1609a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1610a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1611a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1612a27d9013SAlfredo Cardigliano 1613be39f75cSAndrew Boyer txq->flags |= IONIC_QCQ_F_INITED; 1614a27d9013SAlfredo Cardigliano 1615a27d9013SAlfredo Cardigliano return 0; 1616a27d9013SAlfredo Cardigliano } 1617a27d9013SAlfredo Cardigliano 1618a27d9013SAlfredo Cardigliano int 1619be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq) 1620a27d9013SAlfredo Cardigliano { 1621be39f75cSAndrew Boyer struct ionic_qcq *qcq = &rxq->qcq; 1622a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1623a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1624a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1625a27d9013SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1626a27d9013SAlfredo Cardigliano .pending_work = true, 1627a27d9013SAlfredo Cardigliano .cmd.q_init = { 1628a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1629a27d9013SAlfredo Cardigliano .type = q->type, 1630c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 163109f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1632*e86a6fccSAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA), 163309f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1634a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 163509f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 163609f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 163709f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1638a27d9013SAlfredo Cardigliano }, 1639a27d9013SAlfredo Cardigliano }; 1640a27d9013SAlfredo Cardigliano int err; 1641a27d9013SAlfredo Cardigliano 1642*e86a6fccSAndrew Boyer if (rxq->flags & IONIC_QCQ_F_SG) 1643*e86a6fccSAndrew Boyer ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG); 16449de21005SAndrew Boyer if (rxq->flags & IONIC_QCQ_F_CMB) 16459de21005SAndrew Boyer ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB); 16469de21005SAndrew Boyer 164709f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index); 164809f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1649a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1650a27d9013SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 16514ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver); 1652a27d9013SAlfredo Cardigliano 1653e7222f94SAndrew Boyer ionic_q_reset(q); 1654e7222f94SAndrew Boyer ionic_cq_reset(cq); 1655e7222f94SAndrew Boyer 1656be39f75cSAndrew Boyer err = ionic_adminq_post_wait(lif, &ctx); 1657a27d9013SAlfredo Cardigliano if (err) 1658a27d9013SAlfredo Cardigliano return err; 1659a27d9013SAlfredo Cardigliano 1660a27d9013SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 166109f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 1662a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1663a27d9013SAlfredo Cardigliano 1664be39f75cSAndrew Boyer rxq->flags |= IONIC_QCQ_F_INITED; 1665a27d9013SAlfredo Cardigliano 1666a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1667a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1668a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1669a27d9013SAlfredo Cardigliano 1670a27d9013SAlfredo Cardigliano return 0; 1671a27d9013SAlfredo Cardigliano } 1672a27d9013SAlfredo Cardigliano 1673598f6726SAlfredo Cardigliano static int 1674598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1675598f6726SAlfredo Cardigliano { 1676598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1677598f6726SAlfredo Cardigliano .pending_work = true, 1678598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1679598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1680598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1681598f6726SAlfredo Cardigliano }, 1682598f6726SAlfredo Cardigliano }; 1683598f6726SAlfredo Cardigliano int err; 1684598f6726SAlfredo Cardigliano 1685598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1686598f6726SAlfredo Cardigliano 1687598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1688598f6726SAlfredo Cardigliano if (err) 1689598f6726SAlfredo Cardigliano return err; 1690598f6726SAlfredo Cardigliano 1691598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1692598f6726SAlfredo Cardigliano 1693598f6726SAlfredo Cardigliano return 0; 1694598f6726SAlfredo Cardigliano } 1695598f6726SAlfredo Cardigliano 1696598f6726SAlfredo Cardigliano static void 1697598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1698598f6726SAlfredo Cardigliano { 1699598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1700598f6726SAlfredo Cardigliano .pending_work = true, 1701598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1702598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1703598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1704598f6726SAlfredo Cardigliano }, 1705598f6726SAlfredo Cardigliano }; 1706598f6726SAlfredo Cardigliano 17074ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 17084ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1709598f6726SAlfredo Cardigliano 1710598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1711598f6726SAlfredo Cardigliano } 1712598f6726SAlfredo Cardigliano 1713598f6726SAlfredo Cardigliano int 1714669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1715669c8de6SAlfredo Cardigliano { 1716669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1717656bfc9aSAndrew Boyer struct ionic_lif_init_comp comp; 1718669c8de6SAlfredo Cardigliano int err; 1719669c8de6SAlfredo Cardigliano 17203cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 17213cdfd905SAlfredo Cardigliano 172200b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1723669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1724669c8de6SAlfredo Cardigliano if (err) 1725669c8de6SAlfredo Cardigliano return err; 1726669c8de6SAlfredo Cardigliano 1727656bfc9aSAndrew Boyer ionic_dev_cmd_comp(idev, &comp); 1728656bfc9aSAndrew Boyer 172909f806e9SAndrew Boyer lif->hw_index = rte_cpu_to_le_16(comp.hw_index); 1730669c8de6SAlfredo Cardigliano 173101a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 173201a6c311SAlfredo Cardigliano if (err) 173301a6c311SAlfredo Cardigliano return err; 173401a6c311SAlfredo Cardigliano 173527b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 173627b942c8SAlfredo Cardigliano if (err) 173727b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 173827b942c8SAlfredo Cardigliano 173918a44465SAndrew Boyer /* 174018a44465SAndrew Boyer * Configure initial feature set 174118a44465SAndrew Boyer * This will be updated later by the dev_configure() step 174218a44465SAndrew Boyer */ 174318a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1744598f6726SAlfredo Cardigliano 1745598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1746598f6726SAlfredo Cardigliano if (err) 1747598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1748598f6726SAlfredo Cardigliano 174954fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1750598f6726SAlfredo Cardigliano if (err) 1751598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1752598f6726SAlfredo Cardigliano 175354fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 175454fe083fSAlfredo Cardigliano if (err) 175554fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 175654fe083fSAlfredo Cardigliano 1757598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1758598f6726SAlfredo Cardigliano 1759669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1760669c8de6SAlfredo Cardigliano 1761669c8de6SAlfredo Cardigliano return 0; 176227b942c8SAlfredo Cardigliano 176354fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 176454fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 176554fe083fSAlfredo Cardigliano 1766598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 17674c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1768598f6726SAlfredo Cardigliano 176927b942c8SAlfredo Cardigliano err_out_adminq_deinit: 1770be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 177127b942c8SAlfredo Cardigliano 177227b942c8SAlfredo Cardigliano return err; 1773669c8de6SAlfredo Cardigliano } 1774669c8de6SAlfredo Cardigliano 1775669c8de6SAlfredo Cardigliano void 1776669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1777669c8de6SAlfredo Cardigliano { 1778669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1779669c8de6SAlfredo Cardigliano return; 1780669c8de6SAlfredo Cardigliano 178154fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 178222e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 17834c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1784be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 178501a6c311SAlfredo Cardigliano 1786669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1787669c8de6SAlfredo Cardigliano } 1788669c8de6SAlfredo Cardigliano 178918a44465SAndrew Boyer void 179018a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 179118a44465SAndrew Boyer { 179218a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 179318a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 179418a44465SAndrew Boyer 179518a44465SAndrew Boyer /* 179618a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 1797295968d1SFerruh Yigit * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK 179818a44465SAndrew Boyer */ 1799295968d1SFerruh Yigit rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; 180018a44465SAndrew Boyer 1801295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_STRIP_MASK) { 1802295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 180318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 180418a44465SAndrew Boyer else 180518a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 180618a44465SAndrew Boyer } 180718a44465SAndrew Boyer } 180818a44465SAndrew Boyer 180918a44465SAndrew Boyer void 1810*e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif) 1811*e86a6fccSAndrew Boyer { 1812*e86a6fccSAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 1813*e86a6fccSAndrew Boyer 1814*e86a6fccSAndrew Boyer if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) { 1815*e86a6fccSAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 1816*e86a6fccSAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 1817*e86a6fccSAndrew Boyer } else { 1818*e86a6fccSAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 1819*e86a6fccSAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 1820*e86a6fccSAndrew Boyer } 1821*e86a6fccSAndrew Boyer } 1822*e86a6fccSAndrew Boyer 1823*e86a6fccSAndrew Boyer void 1824598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1825598f6726SAlfredo Cardigliano { 182618a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 182718a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 182822e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 182909f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 183022e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 183109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 183222e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 183309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 183422e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 183522e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 183622e7171bSAlfredo Cardigliano 1837598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1838598f6726SAlfredo Cardigliano 183922e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 184022e7171bSAlfredo Cardigliano lif->port_id); 184122e7171bSAlfredo Cardigliano 184222e7171bSAlfredo Cardigliano if (nrxqs > 0) 184322e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 184422e7171bSAlfredo Cardigliano 184522e7171bSAlfredo Cardigliano if (ntxqs > 0) 184622e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 184722e7171bSAlfredo Cardigliano 184822e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 184922e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1850a27d9013SAlfredo Cardigliano 185118a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 185218a44465SAndrew Boyer 185318a44465SAndrew Boyer /* 185418a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 185518a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 1856295968d1SFerruh Yigit * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 185718a44465SAndrew Boyer */ 185818a44465SAndrew Boyer 185918a44465SAndrew Boyer /* RX per-port */ 186018a44465SAndrew Boyer 1861295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM || 1862295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM || 1863295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) 186418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 186518a44465SAndrew Boyer else 186618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 186718a44465SAndrew Boyer 1868*e86a6fccSAndrew Boyer /* 1869*e86a6fccSAndrew Boyer * NB: RX_SG may be enabled later during rx_queue_setup() if 1870*e86a6fccSAndrew Boyer * required by the mbuf/mtu configuration 1871*e86a6fccSAndrew Boyer */ 1872*e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(lif); 187318a44465SAndrew Boyer 187418a44465SAndrew Boyer /* Covers VLAN_STRIP */ 1875295968d1SFerruh Yigit ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK); 187618a44465SAndrew Boyer 187718a44465SAndrew Boyer /* TX per-port */ 187818a44465SAndrew Boyer 1879295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM || 1880295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM || 1881295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM || 1882295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM || 1883295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) 188418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 188518a44465SAndrew Boyer else 188618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 188718a44465SAndrew Boyer 1888295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) 188918a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 189018a44465SAndrew Boyer else 189118a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 189218a44465SAndrew Boyer 1893295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) 189418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 189518a44465SAndrew Boyer else 189618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 189718a44465SAndrew Boyer 1898295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) { 189918a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 190018a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 190118a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 190218a44465SAndrew Boyer } else { 190318a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 190418a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 190518a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 190618a44465SAndrew Boyer } 1907598f6726SAlfredo Cardigliano } 1908598f6726SAlfredo Cardigliano 1909598f6726SAlfredo Cardigliano int 1910598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1911598f6726SAlfredo Cardigliano { 19120578335aSAndrew Boyer uint32_t rx_mode; 1913a27d9013SAlfredo Cardigliano uint32_t i; 1914a27d9013SAlfredo Cardigliano int err; 1915598f6726SAlfredo Cardigliano 191622e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 191722e7171bSAlfredo Cardigliano if (err) 191822e7171bSAlfredo Cardigliano return err; 191922e7171bSAlfredo Cardigliano 19200578335aSAndrew Boyer if (!lif->rx_mode) { 19210578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 19220578335aSAndrew Boyer lif->name); 1923598f6726SAlfredo Cardigliano 19240578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 1925598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 1926598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 1927598f6726SAlfredo Cardigliano 1928598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 19290578335aSAndrew Boyer } 1930598f6726SAlfredo Cardigliano 1931a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 1932a27d9013SAlfredo Cardigliano "on port %u", 1933a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 1934a27d9013SAlfredo Cardigliano 1935a27d9013SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 1936be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq = lif->rxqcqs[i]; 193702eabf57SAndrew Boyer if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) { 1938a27d9013SAlfredo Cardigliano err = ionic_dev_rx_queue_start(lif->eth_dev, i); 1939a27d9013SAlfredo Cardigliano 1940a27d9013SAlfredo Cardigliano if (err) 1941a27d9013SAlfredo Cardigliano return err; 1942a27d9013SAlfredo Cardigliano } 1943a27d9013SAlfredo Cardigliano } 1944a27d9013SAlfredo Cardigliano 1945a27d9013SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 1946be39f75cSAndrew Boyer struct ionic_tx_qcq *txq = lif->txqcqs[i]; 194702eabf57SAndrew Boyer if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) { 1948a27d9013SAlfredo Cardigliano err = ionic_dev_tx_queue_start(lif->eth_dev, i); 1949a27d9013SAlfredo Cardigliano 1950a27d9013SAlfredo Cardigliano if (err) 1951a27d9013SAlfredo Cardigliano return err; 1952a27d9013SAlfredo Cardigliano } 1953a27d9013SAlfredo Cardigliano } 1954a27d9013SAlfredo Cardigliano 1955598f6726SAlfredo Cardigliano /* Carrier ON here */ 1956be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 1957be63459eSAndrew Boyer 1958be63459eSAndrew Boyer ionic_link_status_check(lif); 1959598f6726SAlfredo Cardigliano 1960598f6726SAlfredo Cardigliano return 0; 1961598f6726SAlfredo Cardigliano } 1962598f6726SAlfredo Cardigliano 1963598f6726SAlfredo Cardigliano int 1964669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 1965669c8de6SAlfredo Cardigliano { 1966669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 1967669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 196809f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 196976276d71SAndrew Boyer uint32_t lif_words = RTE_DIM(ident->lif.words); 197076276d71SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 197176276d71SAndrew Boyer uint32_t i, nwords; 1972669c8de6SAlfredo Cardigliano int err; 1973669c8de6SAlfredo Cardigliano 1974669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 1975669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 1976669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 1977669c8de6SAlfredo Cardigliano if (err) 1978669c8de6SAlfredo Cardigliano return (err); 1979669c8de6SAlfredo Cardigliano 1980669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 1981669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 1982669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 1983669c8de6SAlfredo Cardigliano 1984669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 198509f806e9SAndrew Boyer rte_le_to_cpu_64(ident->lif.capabilities)); 1986669c8de6SAlfredo Cardigliano 1987669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 198809f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters)); 1989669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 199009f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters)); 1991669c8de6SAlfredo Cardigliano 1992669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 199309f806e9SAndrew Boyer rte_le_to_cpu_64(cfg->features)); 1994669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 199509f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ])); 1996669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 199709f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ])); 1998669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 199909f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ])); 2000669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 200109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ])); 2002669c8de6SAlfredo Cardigliano 2003669c8de6SAlfredo Cardigliano return 0; 2004669c8de6SAlfredo Cardigliano } 2005669c8de6SAlfredo Cardigliano 2006669c8de6SAlfredo Cardigliano int 2007669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 2008669c8de6SAlfredo Cardigliano { 2009669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 201009f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 201109f806e9SAndrew Boyer uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs); 2012669c8de6SAlfredo Cardigliano 2013669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 201409f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 2015669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 201609f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 2017669c8de6SAlfredo Cardigliano 201800b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 2019669c8de6SAlfredo Cardigliano 2020669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 20214ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 20224ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 2023669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 2024669c8de6SAlfredo Cardigliano return -ENOSPC; 2025669c8de6SAlfredo Cardigliano } 2026669c8de6SAlfredo Cardigliano 2027669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 2028669c8de6SAlfredo Cardigliano 2029669c8de6SAlfredo Cardigliano return 0; 2030669c8de6SAlfredo Cardigliano } 2031