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 347bb08900SAndrew Boyer ionic_qcq_disable_nowait(struct ionic_qcq *qcq, 357bb08900SAndrew Boyer struct ionic_admin_ctx *ctx) 3601a6c311SAlfredo Cardigliano { 377bb08900SAndrew Boyer int err; 387bb08900SAndrew Boyer 3901a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 404ad56b7aSAndrew Boyer struct ionic_lif *lif = qcq->lif; 417bb08900SAndrew Boyer 427bb08900SAndrew Boyer *ctx = (struct ionic_admin_ctx) { 4301a6c311SAlfredo Cardigliano .pending_work = true, 4401a6c311SAlfredo Cardigliano .cmd.q_control = { 4501a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 4601a6c311SAlfredo Cardigliano .type = q->type, 4709f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 4801a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 4901a6c311SAlfredo Cardigliano }, 5001a6c311SAlfredo Cardigliano }; 5101a6c311SAlfredo Cardigliano 527bb08900SAndrew Boyer /* Does not wait for command completion */ 537bb08900SAndrew Boyer err = ionic_adminq_post(lif, ctx); 547bb08900SAndrew Boyer if (err) 557bb08900SAndrew Boyer ctx->pending_work = false; 567bb08900SAndrew Boyer return err; 5701a6c311SAlfredo Cardigliano } 5801a6c311SAlfredo Cardigliano 59be63459eSAndrew Boyer void 60be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif) 61598f6726SAlfredo Cardigliano { 627bb08900SAndrew Boyer struct rte_eth_dev *dev = lif->eth_dev; 637bb08900SAndrew Boyer uint32_t i, j, chunk; 64a0a99f21SAndrew Boyer 65be63459eSAndrew Boyer IONIC_PRINT_CALL(); 66598f6726SAlfredo Cardigliano 67be63459eSAndrew Boyer lif->state &= ~IONIC_LIF_F_UP; 68a0a99f21SAndrew Boyer 697bb08900SAndrew Boyer chunk = ionic_adminq_space_avail(lif); 707bb08900SAndrew Boyer 717bb08900SAndrew Boyer for (i = 0; i < lif->nrxqcqs; i += chunk) { 727bb08900SAndrew Boyer for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) 737bb08900SAndrew Boyer ionic_dev_rx_queue_stop_firsthalf(dev, i + j); 747bb08900SAndrew Boyer 757bb08900SAndrew Boyer for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) 767bb08900SAndrew Boyer ionic_dev_rx_queue_stop_secondhalf(dev, i + j); 77a0a99f21SAndrew Boyer } 78a0a99f21SAndrew Boyer 797bb08900SAndrew Boyer for (i = 0; i < lif->ntxqcqs; i += chunk) { 807bb08900SAndrew Boyer for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) 817bb08900SAndrew Boyer ionic_dev_tx_queue_stop_firsthalf(dev, i + j); 827bb08900SAndrew Boyer 837bb08900SAndrew Boyer for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) 847bb08900SAndrew Boyer ionic_dev_tx_queue_stop_secondhalf(dev, i + j); 85a0a99f21SAndrew Boyer } 86598f6726SAlfredo Cardigliano } 87598f6726SAlfredo Cardigliano 88598f6726SAlfredo Cardigliano void 89598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif) 90598f6726SAlfredo Cardigliano { 91598f6726SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 9275f96902SAndrew Boyer int err; 93598f6726SAlfredo Cardigliano 94598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 95598f6726SAlfredo Cardigliano 9600b65da5SAndrew Boyer ionic_dev_cmd_lif_reset(idev); 9775f96902SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 9875f96902SAndrew Boyer if (err) 994ae96cb8SAndrew Boyer IONIC_PRINT(WARNING, "Failed to reset %s", lif->name); 100598f6726SAlfredo Cardigliano } 101598f6726SAlfredo Cardigliano 1023cdfd905SAlfredo Cardigliano static void 1033cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats) 1043cdfd905SAlfredo Cardigliano { 1053cdfd905SAlfredo Cardigliano struct ionic_lif_stats *ls = &lif->info->stats; 1063cdfd905SAlfredo Cardigliano uint32_t i; 1073cdfd905SAlfredo Cardigliano uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t) 1083cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1093cdfd905SAlfredo Cardigliano uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t) 1103cdfd905SAlfredo Cardigliano RTE_ETHDEV_QUEUE_STAT_CNTRS); 1113cdfd905SAlfredo Cardigliano 1123cdfd905SAlfredo Cardigliano memset(stats, 0, sizeof(*stats)); 1133cdfd905SAlfredo Cardigliano 1143cdfd905SAlfredo Cardigliano if (ls == NULL) { 1153cdfd905SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized", 1163cdfd905SAlfredo Cardigliano lif->port_id); 1173cdfd905SAlfredo Cardigliano return; 1183cdfd905SAlfredo Cardigliano } 1193cdfd905SAlfredo Cardigliano 1203cdfd905SAlfredo Cardigliano /* RX */ 1213cdfd905SAlfredo Cardigliano 1223cdfd905SAlfredo Cardigliano stats->ipackets = ls->rx_ucast_packets + 1233cdfd905SAlfredo Cardigliano ls->rx_mcast_packets + 1243cdfd905SAlfredo Cardigliano ls->rx_bcast_packets; 1253cdfd905SAlfredo Cardigliano 1263cdfd905SAlfredo Cardigliano stats->ibytes = ls->rx_ucast_bytes + 1273cdfd905SAlfredo Cardigliano ls->rx_mcast_bytes + 1283cdfd905SAlfredo Cardigliano ls->rx_bcast_bytes; 1293cdfd905SAlfredo Cardigliano 1303cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 131be39f75cSAndrew Boyer struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats; 13226cc5dc2SAndrew Boyer stats->ierrors += 1333cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1343cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1353cdfd905SAlfredo Cardigliano } 1363cdfd905SAlfredo Cardigliano 1373cdfd905SAlfredo Cardigliano stats->imissed += 1383cdfd905SAlfredo Cardigliano ls->rx_ucast_drop_packets + 1393cdfd905SAlfredo Cardigliano ls->rx_mcast_drop_packets + 1403cdfd905SAlfredo Cardigliano ls->rx_bcast_drop_packets; 1413cdfd905SAlfredo Cardigliano 14226cc5dc2SAndrew Boyer stats->ierrors += 1433cdfd905SAlfredo Cardigliano ls->rx_dma_error + 1443cdfd905SAlfredo Cardigliano ls->rx_desc_fetch_error + 1453cdfd905SAlfredo Cardigliano ls->rx_desc_data_error; 1463cdfd905SAlfredo Cardigliano 1473cdfd905SAlfredo Cardigliano for (i = 0; i < num_rx_q_counters; i++) { 148be39f75cSAndrew Boyer struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats; 1493cdfd905SAlfredo Cardigliano stats->q_ipackets[i] = rx_stats->packets; 1503cdfd905SAlfredo Cardigliano stats->q_ibytes[i] = rx_stats->bytes; 1513cdfd905SAlfredo Cardigliano stats->q_errors[i] = 1523cdfd905SAlfredo Cardigliano rx_stats->bad_cq_status + 1533cdfd905SAlfredo Cardigliano rx_stats->bad_len; 1543cdfd905SAlfredo Cardigliano } 1553cdfd905SAlfredo Cardigliano 1563cdfd905SAlfredo Cardigliano /* TX */ 1573cdfd905SAlfredo Cardigliano 1583cdfd905SAlfredo Cardigliano stats->opackets = ls->tx_ucast_packets + 1593cdfd905SAlfredo Cardigliano ls->tx_mcast_packets + 1603cdfd905SAlfredo Cardigliano ls->tx_bcast_packets; 1613cdfd905SAlfredo Cardigliano 1623cdfd905SAlfredo Cardigliano stats->obytes = ls->tx_ucast_bytes + 1633cdfd905SAlfredo Cardigliano ls->tx_mcast_bytes + 1643cdfd905SAlfredo Cardigliano ls->tx_bcast_bytes; 1653cdfd905SAlfredo Cardigliano 1663cdfd905SAlfredo Cardigliano for (i = 0; i < lif->ntxqcqs; i++) { 167be39f75cSAndrew Boyer struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats; 1683cdfd905SAlfredo Cardigliano stats->oerrors += tx_stats->drop; 1693cdfd905SAlfredo Cardigliano } 1703cdfd905SAlfredo Cardigliano 1713cdfd905SAlfredo Cardigliano stats->oerrors += 1723cdfd905SAlfredo Cardigliano ls->tx_ucast_drop_packets + 1733cdfd905SAlfredo Cardigliano ls->tx_mcast_drop_packets + 1743cdfd905SAlfredo Cardigliano ls->tx_bcast_drop_packets; 1753cdfd905SAlfredo Cardigliano 1763cdfd905SAlfredo Cardigliano stats->oerrors += 1773cdfd905SAlfredo Cardigliano ls->tx_dma_error + 1783cdfd905SAlfredo Cardigliano ls->tx_queue_disabled + 1793cdfd905SAlfredo Cardigliano ls->tx_desc_fetch_error + 1803cdfd905SAlfredo Cardigliano ls->tx_desc_data_error; 1813cdfd905SAlfredo Cardigliano 1823cdfd905SAlfredo Cardigliano for (i = 0; i < num_tx_q_counters; i++) { 183be39f75cSAndrew Boyer struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats; 1843cdfd905SAlfredo Cardigliano stats->q_opackets[i] = tx_stats->packets; 1853cdfd905SAlfredo Cardigliano stats->q_obytes[i] = tx_stats->bytes; 1863cdfd905SAlfredo Cardigliano } 1873cdfd905SAlfredo Cardigliano } 1883cdfd905SAlfredo Cardigliano 1893cdfd905SAlfredo Cardigliano void 1903cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif, 1913cdfd905SAlfredo Cardigliano struct rte_eth_stats *stats) 1923cdfd905SAlfredo Cardigliano { 1933cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, stats); 1943cdfd905SAlfredo Cardigliano 1953cdfd905SAlfredo Cardigliano stats->ipackets -= lif->stats_base.ipackets; 1963cdfd905SAlfredo Cardigliano stats->opackets -= lif->stats_base.opackets; 1973cdfd905SAlfredo Cardigliano stats->ibytes -= lif->stats_base.ibytes; 1983cdfd905SAlfredo Cardigliano stats->obytes -= lif->stats_base.obytes; 1993cdfd905SAlfredo Cardigliano stats->imissed -= lif->stats_base.imissed; 2003cdfd905SAlfredo Cardigliano stats->ierrors -= lif->stats_base.ierrors; 2013cdfd905SAlfredo Cardigliano stats->oerrors -= lif->stats_base.oerrors; 2023cdfd905SAlfredo Cardigliano stats->rx_nombuf -= lif->stats_base.rx_nombuf; 2033cdfd905SAlfredo Cardigliano } 2043cdfd905SAlfredo Cardigliano 2053cdfd905SAlfredo Cardigliano void 2063cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif) 2073cdfd905SAlfredo Cardigliano { 2083cdfd905SAlfredo Cardigliano uint32_t i; 2093cdfd905SAlfredo Cardigliano 2103cdfd905SAlfredo Cardigliano for (i = 0; i < lif->nrxqcqs; i++) { 211be39f75cSAndrew Boyer memset(&lif->rxqcqs[i]->stats, 0, 2123cdfd905SAlfredo Cardigliano sizeof(struct ionic_rx_stats)); 213be39f75cSAndrew Boyer memset(&lif->txqcqs[i]->stats, 0, 2143cdfd905SAlfredo Cardigliano sizeof(struct ionic_tx_stats)); 2153cdfd905SAlfredo Cardigliano } 2163cdfd905SAlfredo Cardigliano 2173cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(lif, &lif->stats_base); 2183cdfd905SAlfredo Cardigliano } 2193cdfd905SAlfredo Cardigliano 2203cdfd905SAlfredo Cardigliano void 2213cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats) 2223cdfd905SAlfredo Cardigliano { 2233cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2243cdfd905SAlfredo Cardigliano uint64_t *stats64 = (uint64_t *)stats; 2253cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2263cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2273cdfd905SAlfredo Cardigliano 2283cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2293cdfd905SAlfredo Cardigliano stats64[i] = lif_stats64[i] - lif_stats64_base[i]; 2303cdfd905SAlfredo Cardigliano } 2313cdfd905SAlfredo Cardigliano 2323cdfd905SAlfredo Cardigliano void 2333cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif) 2343cdfd905SAlfredo Cardigliano { 2353cdfd905SAlfredo Cardigliano uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t); 2363cdfd905SAlfredo Cardigliano uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats; 2373cdfd905SAlfredo Cardigliano uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base; 2383cdfd905SAlfredo Cardigliano 2393cdfd905SAlfredo Cardigliano for (i = 0; i < count; i++) 2403cdfd905SAlfredo Cardigliano lif_stats64_base[i] = lif_stats64[i]; 2413cdfd905SAlfredo Cardigliano } 2423cdfd905SAlfredo Cardigliano 243598f6726SAlfredo Cardigliano static int 24454fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr) 245598f6726SAlfredo Cardigliano { 24654fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 24754fe083fSAlfredo Cardigliano .pending_work = true, 24854fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 24954fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 25009f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC), 25154fe083fSAlfredo Cardigliano }, 25254fe083fSAlfredo Cardigliano }; 25354fe083fSAlfredo Cardigliano int err; 25454fe083fSAlfredo Cardigliano 25554fe083fSAlfredo Cardigliano memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN); 25654fe083fSAlfredo Cardigliano 25754fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 25854fe083fSAlfredo Cardigliano if (err) 25954fe083fSAlfredo Cardigliano return err; 26054fe083fSAlfredo Cardigliano 26154fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add (id %d)", 26209f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 26354fe083fSAlfredo Cardigliano 26454fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 26554fe083fSAlfredo Cardigliano } 26654fe083fSAlfredo Cardigliano 26754fe083fSAlfredo Cardigliano static int 26854fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr) 26954fe083fSAlfredo Cardigliano { 27054fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 27154fe083fSAlfredo Cardigliano .pending_work = true, 27254fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 27354fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 27454fe083fSAlfredo Cardigliano }, 27554fe083fSAlfredo Cardigliano }; 27654fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 27754fe083fSAlfredo Cardigliano int err; 27854fe083fSAlfredo Cardigliano 27954fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 28054fe083fSAlfredo Cardigliano 28154fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 28254fe083fSAlfredo Cardigliano 28354fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_addr(lif, addr); 28454fe083fSAlfredo Cardigliano if (!f) { 28554fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 28654fe083fSAlfredo Cardigliano return -ENOENT; 28754fe083fSAlfredo Cardigliano } 28854fe083fSAlfredo Cardigliano 28909f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 29054fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 29154fe083fSAlfredo Cardigliano 29254fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 29354fe083fSAlfredo Cardigliano 29454fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 29554fe083fSAlfredo Cardigliano if (err) 29654fe083fSAlfredo Cardigliano return err; 29754fe083fSAlfredo Cardigliano 29854fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del (id %d)", 29909f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 300598f6726SAlfredo Cardigliano 301598f6726SAlfredo Cardigliano return 0; 302598f6726SAlfredo Cardigliano } 303598f6726SAlfredo Cardigliano 30454fe083fSAlfredo Cardigliano int 30554fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev, 30654fe083fSAlfredo Cardigliano struct rte_ether_addr *mac_addr, 30754fe083fSAlfredo Cardigliano uint32_t index __rte_unused, uint32_t pool __rte_unused) 308598f6726SAlfredo Cardigliano { 30954fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 31054fe083fSAlfredo Cardigliano 31154fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 31254fe083fSAlfredo Cardigliano 31354fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 31454fe083fSAlfredo Cardigliano } 31554fe083fSAlfredo Cardigliano 31654fe083fSAlfredo Cardigliano void 31775f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index) 31854fe083fSAlfredo Cardigliano { 31954fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 32054fe083fSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 32175f96902SAndrew Boyer struct rte_ether_addr *mac_addr; 32254fe083fSAlfredo Cardigliano 32354fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 32454fe083fSAlfredo Cardigliano 32554fe083fSAlfredo Cardigliano if (index >= adapter->max_mac_addrs) { 32654fe083fSAlfredo Cardigliano IONIC_PRINT(WARNING, 32754fe083fSAlfredo Cardigliano "Index %u is above MAC filter limit %u", 32854fe083fSAlfredo Cardigliano index, adapter->max_mac_addrs); 32954fe083fSAlfredo Cardigliano return; 33054fe083fSAlfredo Cardigliano } 33154fe083fSAlfredo Cardigliano 33275f96902SAndrew Boyer mac_addr = ð_dev->data->mac_addrs[index]; 33375f96902SAndrew Boyer 33475f96902SAndrew Boyer if (!rte_is_valid_assigned_ether_addr(mac_addr)) 33554fe083fSAlfredo Cardigliano return; 33654fe083fSAlfredo Cardigliano 33775f96902SAndrew Boyer ionic_lif_addr_del(lif, (const uint8_t *)mac_addr); 33854fe083fSAlfredo Cardigliano } 33954fe083fSAlfredo Cardigliano 34054fe083fSAlfredo Cardigliano int 34154fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) 34254fe083fSAlfredo Cardigliano { 34354fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 34454fe083fSAlfredo Cardigliano 34554fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 34654fe083fSAlfredo Cardigliano 34754fe083fSAlfredo Cardigliano if (mac_addr == NULL) { 34854fe083fSAlfredo Cardigliano IONIC_PRINT(NOTICE, "New mac is null"); 34954fe083fSAlfredo Cardigliano return -1; 35054fe083fSAlfredo Cardigliano } 35154fe083fSAlfredo Cardigliano 35254fe083fSAlfredo Cardigliano if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) { 35354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Deleting mac addr %pM", 35454fe083fSAlfredo Cardigliano lif->mac_addr); 35554fe083fSAlfredo Cardigliano ionic_lif_addr_del(lif, lif->mac_addr); 35654fe083fSAlfredo Cardigliano memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN); 35754fe083fSAlfredo Cardigliano } 35854fe083fSAlfredo Cardigliano 35954fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "Updating mac addr"); 36054fe083fSAlfredo Cardigliano 36154fe083fSAlfredo Cardigliano rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr); 36254fe083fSAlfredo Cardigliano 36354fe083fSAlfredo Cardigliano return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr); 36454fe083fSAlfredo Cardigliano } 36554fe083fSAlfredo Cardigliano 36654fe083fSAlfredo Cardigliano static int 36754fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid) 36854fe083fSAlfredo Cardigliano { 36954fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 37054fe083fSAlfredo Cardigliano .pending_work = true, 37154fe083fSAlfredo Cardigliano .cmd.rx_filter_add = { 37254fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_ADD, 37309f806e9SAndrew Boyer .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN), 37409f806e9SAndrew Boyer .vlan.vlan = rte_cpu_to_le_16(vid), 37554fe083fSAlfredo Cardigliano }, 37654fe083fSAlfredo Cardigliano }; 37754fe083fSAlfredo Cardigliano int err; 37854fe083fSAlfredo Cardigliano 37954fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 38054fe083fSAlfredo Cardigliano if (err) 38154fe083fSAlfredo Cardigliano return err; 38254fe083fSAlfredo Cardigliano 38354fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid, 38409f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id)); 38554fe083fSAlfredo Cardigliano 38654fe083fSAlfredo Cardigliano return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx); 38754fe083fSAlfredo Cardigliano } 38854fe083fSAlfredo Cardigliano 38954fe083fSAlfredo Cardigliano static int 39054fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid) 39154fe083fSAlfredo Cardigliano { 39254fe083fSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 39354fe083fSAlfredo Cardigliano .pending_work = true, 39454fe083fSAlfredo Cardigliano .cmd.rx_filter_del = { 39554fe083fSAlfredo Cardigliano .opcode = IONIC_CMD_RX_FILTER_DEL, 39654fe083fSAlfredo Cardigliano }, 39754fe083fSAlfredo Cardigliano }; 39854fe083fSAlfredo Cardigliano struct ionic_rx_filter *f; 39954fe083fSAlfredo Cardigliano int err; 40054fe083fSAlfredo Cardigliano 40154fe083fSAlfredo Cardigliano IONIC_PRINT_CALL(); 40254fe083fSAlfredo Cardigliano 40354fe083fSAlfredo Cardigliano rte_spinlock_lock(&lif->rx_filters.lock); 40454fe083fSAlfredo Cardigliano 40554fe083fSAlfredo Cardigliano f = ionic_rx_filter_by_vlan(lif, vid); 40654fe083fSAlfredo Cardigliano if (!f) { 40754fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 40854fe083fSAlfredo Cardigliano return -ENOENT; 40954fe083fSAlfredo Cardigliano } 41054fe083fSAlfredo Cardigliano 41109f806e9SAndrew Boyer ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id); 41254fe083fSAlfredo Cardigliano ionic_rx_filter_free(f); 41354fe083fSAlfredo Cardigliano rte_spinlock_unlock(&lif->rx_filters.lock); 41454fe083fSAlfredo Cardigliano 41554fe083fSAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 41654fe083fSAlfredo Cardigliano if (err) 41754fe083fSAlfredo Cardigliano return err; 41854fe083fSAlfredo Cardigliano 41954fe083fSAlfredo Cardigliano IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid, 42009f806e9SAndrew Boyer rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id)); 421598f6726SAlfredo Cardigliano 422598f6726SAlfredo Cardigliano return 0; 423598f6726SAlfredo Cardigliano } 424598f6726SAlfredo Cardigliano 42554fe083fSAlfredo Cardigliano int 42654fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, 42754fe083fSAlfredo Cardigliano int on) 42854fe083fSAlfredo Cardigliano { 42954fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 43054fe083fSAlfredo Cardigliano int err; 43154fe083fSAlfredo Cardigliano 43254fe083fSAlfredo Cardigliano if (on) 43354fe083fSAlfredo Cardigliano err = ionic_vlan_rx_add_vid(lif, vlan_id); 43454fe083fSAlfredo Cardigliano else 43554fe083fSAlfredo Cardigliano err = ionic_vlan_rx_kill_vid(lif, vlan_id); 43654fe083fSAlfredo Cardigliano 43754fe083fSAlfredo Cardigliano return err; 43854fe083fSAlfredo Cardigliano } 43954fe083fSAlfredo Cardigliano 440598f6726SAlfredo Cardigliano static void 441598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 442598f6726SAlfredo Cardigliano { 443598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 444598f6726SAlfredo Cardigliano .pending_work = true, 445598f6726SAlfredo Cardigliano .cmd.rx_mode_set = { 446598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_RX_MODE_SET, 44709f806e9SAndrew Boyer .rx_mode = rte_cpu_to_le_16(rx_mode), 448598f6726SAlfredo Cardigliano }, 449598f6726SAlfredo Cardigliano }; 450598f6726SAlfredo Cardigliano int err; 451598f6726SAlfredo Cardigliano 452598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_UNICAST) 453598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST"); 454598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_MULTICAST) 455598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST"); 456598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_BROADCAST) 457598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST"); 458598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_PROMISC) 459598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC"); 460598f6726SAlfredo Cardigliano if (rx_mode & IONIC_RX_MODE_F_ALLMULTI) 461598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI"); 462598f6726SAlfredo Cardigliano 463598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 464598f6726SAlfredo Cardigliano if (err) 465598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure setting RX mode"); 466598f6726SAlfredo Cardigliano } 467598f6726SAlfredo Cardigliano 468598f6726SAlfredo Cardigliano static void 469598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode) 470598f6726SAlfredo Cardigliano { 471598f6726SAlfredo Cardigliano if (lif->rx_mode != rx_mode) { 472598f6726SAlfredo Cardigliano lif->rx_mode = rx_mode; 473598f6726SAlfredo Cardigliano ionic_lif_rx_mode(lif, rx_mode); 474598f6726SAlfredo Cardigliano } 475598f6726SAlfredo Cardigliano } 476598f6726SAlfredo Cardigliano 47754fe083fSAlfredo Cardigliano int 47854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(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 IONIC_PRINT_CALL(); 48454fe083fSAlfredo Cardigliano 48554fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_PROMISC; 48654fe083fSAlfredo Cardigliano 48754fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 48854fe083fSAlfredo Cardigliano 48954fe083fSAlfredo Cardigliano return 0; 49054fe083fSAlfredo Cardigliano } 49154fe083fSAlfredo Cardigliano 49254fe083fSAlfredo Cardigliano int 49354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 49454fe083fSAlfredo Cardigliano { 49554fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 49654fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 49754fe083fSAlfredo Cardigliano 49854fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_PROMISC; 49954fe083fSAlfredo Cardigliano 50054fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 50154fe083fSAlfredo Cardigliano 50254fe083fSAlfredo Cardigliano return 0; 50354fe083fSAlfredo Cardigliano } 50454fe083fSAlfredo Cardigliano 50554fe083fSAlfredo Cardigliano int 50654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) 50754fe083fSAlfredo Cardigliano { 50854fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 50954fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 51054fe083fSAlfredo Cardigliano 51154fe083fSAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_ALLMULTI; 51254fe083fSAlfredo Cardigliano 51354fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 51454fe083fSAlfredo Cardigliano 51554fe083fSAlfredo Cardigliano return 0; 51654fe083fSAlfredo Cardigliano } 51754fe083fSAlfredo Cardigliano 51854fe083fSAlfredo Cardigliano int 51954fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) 52054fe083fSAlfredo Cardigliano { 52154fe083fSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 52254fe083fSAlfredo Cardigliano uint32_t rx_mode = lif->rx_mode; 52354fe083fSAlfredo Cardigliano 52454fe083fSAlfredo Cardigliano rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; 52554fe083fSAlfredo Cardigliano 52654fe083fSAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 52754fe083fSAlfredo Cardigliano 52854fe083fSAlfredo Cardigliano return 0; 52954fe083fSAlfredo Cardigliano } 530598f6726SAlfredo Cardigliano 531598f6726SAlfredo Cardigliano int 532b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu) 533598f6726SAlfredo Cardigliano { 534598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 535598f6726SAlfredo Cardigliano .pending_work = true, 536598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 537598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 538598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MTU, 53909f806e9SAndrew Boyer .mtu = rte_cpu_to_le_32(new_mtu), 540598f6726SAlfredo Cardigliano }, 541598f6726SAlfredo Cardigliano }; 542598f6726SAlfredo Cardigliano 543b671e69aSAndrew Boyer return ionic_adminq_post_wait(lif, &ctx); 544598f6726SAlfredo Cardigliano } 545598f6726SAlfredo Cardigliano 546598f6726SAlfredo Cardigliano int 54701a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 54801a6c311SAlfredo Cardigliano { 54901a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 55001a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 55101a6c311SAlfredo Cardigliano unsigned long index; 55201a6c311SAlfredo Cardigliano 55301a6c311SAlfredo Cardigliano /* 55401a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 55501a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 5564ae96cb8SAndrew Boyer * which has index = 0) 55701a6c311SAlfredo Cardigliano */ 55801a6c311SAlfredo Cardigliano 55901a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 56001a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 56101a6c311SAlfredo Cardigliano break; 56201a6c311SAlfredo Cardigliano 56301a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 56401a6c311SAlfredo Cardigliano return -ENOSPC; 56501a6c311SAlfredo Cardigliano 56601a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 56701a6c311SAlfredo Cardigliano 56801a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 56901a6c311SAlfredo Cardigliano 57001a6c311SAlfredo Cardigliano return 0; 57101a6c311SAlfredo Cardigliano } 57201a6c311SAlfredo Cardigliano 57301a6c311SAlfredo Cardigliano static int 5744ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif, 5754ad56b7aSAndrew Boyer uint8_t type, 576be39f75cSAndrew Boyer size_t struct_size, 5778ec5ad7fSAndrew Boyer uint32_t socket_id, 57801a6c311SAlfredo Cardigliano uint32_t index, 5794ad56b7aSAndrew Boyer const char *type_name, 5804ad56b7aSAndrew Boyer uint16_t flags, 5814ad56b7aSAndrew Boyer uint16_t num_descs, 582d5850081SAndrew Boyer uint16_t num_segs, 5834ad56b7aSAndrew Boyer uint16_t desc_size, 5844ad56b7aSAndrew Boyer uint16_t cq_desc_size, 5854ad56b7aSAndrew Boyer uint16_t sg_desc_size, 5861abf69fcSAndrew Boyer struct ionic_qcq **qcq) 58701a6c311SAlfredo Cardigliano { 58801a6c311SAlfredo Cardigliano struct ionic_qcq *new; 58901a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 59090fa040aSNeel Patel void *q_base, *cmb_q_base, *cq_base, *sg_base; 59101a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 59201a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 59301a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 59490fa040aSNeel Patel rte_iova_t cmb_q_base_pa = 0; 59515770e98SAndrew Boyer size_t page_size = rte_mem_page_size(); 59601a6c311SAlfredo Cardigliano int err; 59701a6c311SAlfredo Cardigliano 59801a6c311SAlfredo Cardigliano *qcq = NULL; 59901a6c311SAlfredo Cardigliano 60001a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 60101a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 60201a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 60301a6c311SAlfredo Cardigliano 60415770e98SAndrew Boyer total_size = RTE_ALIGN(q_size, page_size) + 60515770e98SAndrew Boyer RTE_ALIGN(cq_size, page_size); 60601a6c311SAlfredo Cardigliano /* 60701a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 60801a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 60915770e98SAndrew Boyer * Adding page_size. 61001a6c311SAlfredo Cardigliano */ 61115770e98SAndrew Boyer total_size += page_size; 61201a6c311SAlfredo Cardigliano 61301a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 61415770e98SAndrew Boyer total_size += RTE_ALIGN(sg_size, page_size); 61515770e98SAndrew Boyer total_size += page_size; 61601a6c311SAlfredo Cardigliano } 61701a6c311SAlfredo Cardigliano 618c5d0bb79SAndrew Boyer new = rte_zmalloc_socket("ionic", struct_size, 619c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 62001a6c311SAlfredo Cardigliano if (!new) { 62101a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 62201a6c311SAlfredo Cardigliano return -ENOMEM; 62301a6c311SAlfredo Cardigliano } 62401a6c311SAlfredo Cardigliano 62501a6c311SAlfredo Cardigliano new->lif = lif; 62601a6c311SAlfredo Cardigliano 6277b20fc2fSAndrew Boyer /* Most queue types will store 1 ptr per descriptor */ 628be39f75cSAndrew Boyer new->q.info = rte_calloc_socket("ionic", 6294b53e980SAndrew Boyer (uint64_t)num_descs * num_segs, 6304b53e980SAndrew Boyer sizeof(void *), page_size, socket_id); 63101a6c311SAlfredo Cardigliano if (!new->q.info) { 63201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 6334c8f8d57SAndrew Boyer err = -ENOMEM; 6344c8f8d57SAndrew Boyer goto err_out_free_qcq; 63501a6c311SAlfredo Cardigliano } 63601a6c311SAlfredo Cardigliano 637d5850081SAndrew Boyer new->q.num_segs = num_segs; 63801a6c311SAlfredo Cardigliano new->q.type = type; 63901a6c311SAlfredo Cardigliano 6404ad56b7aSAndrew Boyer err = ionic_q_init(&new->q, index, num_descs); 64101a6c311SAlfredo Cardigliano if (err) { 64201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 6434c8f8d57SAndrew Boyer goto err_out_free_info; 64401a6c311SAlfredo Cardigliano } 64501a6c311SAlfredo Cardigliano 6462aed9865SAndrew Boyer err = ionic_cq_init(&new->cq, num_descs); 64701a6c311SAlfredo Cardigliano if (err) { 64801a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 6494c8f8d57SAndrew Boyer goto err_out_free_info; 65001a6c311SAlfredo Cardigliano } 65101a6c311SAlfredo Cardigliano 65201a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 6534ad56b7aSAndrew Boyer type_name, index /* queue_idx */, 65401a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 65501a6c311SAlfredo Cardigliano 65601a6c311SAlfredo Cardigliano if (!new->base_z) { 65701a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 65801a6c311SAlfredo Cardigliano err = -ENOMEM; 6594c8f8d57SAndrew Boyer goto err_out_free_info; 66001a6c311SAlfredo Cardigliano } 66101a6c311SAlfredo Cardigliano 66201a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 66301a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 66401a6c311SAlfredo Cardigliano 66501a6c311SAlfredo Cardigliano q_base = new->base; 66601a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 66701a6c311SAlfredo Cardigliano 66815770e98SAndrew Boyer cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size); 66915770e98SAndrew Boyer cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size); 67001a6c311SAlfredo Cardigliano 67101a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 67201a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 67315770e98SAndrew Boyer page_size); 67415770e98SAndrew Boyer sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size); 67501a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 67601a6c311SAlfredo Cardigliano } 67701a6c311SAlfredo Cardigliano 6789de21005SAndrew Boyer if (flags & IONIC_QCQ_F_CMB) { 6799de21005SAndrew Boyer /* alloc descriptor ring from nic memory */ 6809de21005SAndrew Boyer if (lif->adapter->cmb_offset + q_size > 6819de21005SAndrew Boyer lif->adapter->bars.bar[2].len) { 6829de21005SAndrew Boyer IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem"); 6839de21005SAndrew Boyer return -ENOMEM; 6849de21005SAndrew Boyer } 68590fa040aSNeel Patel cmb_q_base = (void *) 6869de21005SAndrew Boyer ((uintptr_t)lif->adapter->bars.bar[2].vaddr + 6879de21005SAndrew Boyer (uintptr_t)lif->adapter->cmb_offset); 6889de21005SAndrew Boyer /* CMB PA is a relative address */ 68990fa040aSNeel Patel cmb_q_base_pa = lif->adapter->cmb_offset; 6909de21005SAndrew Boyer lif->adapter->cmb_offset += q_size; 69190fa040aSNeel Patel } else { 69290fa040aSNeel Patel cmb_q_base = NULL; 69390fa040aSNeel Patel cmb_q_base_pa = 0; 6949de21005SAndrew Boyer } 6959de21005SAndrew Boyer 6964ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx " 6974ae96cb8SAndrew Boyer "SG-base-PA = %#jx", 69801a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 69901a6c311SAlfredo Cardigliano 70090fa040aSNeel Patel ionic_q_map(&new->q, q_base, q_base_pa, cmb_q_base, cmb_q_base_pa); 70101a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 70201a6c311SAlfredo Cardigliano 70301a6c311SAlfredo Cardigliano *qcq = new; 70401a6c311SAlfredo Cardigliano 70501a6c311SAlfredo Cardigliano return 0; 70601a6c311SAlfredo Cardigliano 7074c8f8d57SAndrew Boyer err_out_free_info: 7084c8f8d57SAndrew Boyer rte_free(new->q.info); 7094c8f8d57SAndrew Boyer err_out_free_qcq: 7104c8f8d57SAndrew Boyer rte_free(new); 71101a6c311SAlfredo Cardigliano 71201a6c311SAlfredo Cardigliano return err; 71301a6c311SAlfredo Cardigliano } 71401a6c311SAlfredo Cardigliano 71501a6c311SAlfredo Cardigliano void 71601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 71701a6c311SAlfredo Cardigliano { 71801a6c311SAlfredo Cardigliano if (qcq->base_z) { 71901a6c311SAlfredo Cardigliano qcq->base = NULL; 72001a6c311SAlfredo Cardigliano qcq->base_pa = 0; 72101a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 72201a6c311SAlfredo Cardigliano qcq->base_z = NULL; 72301a6c311SAlfredo Cardigliano } 72401a6c311SAlfredo Cardigliano 72501a6c311SAlfredo Cardigliano if (qcq->q.info) { 72601a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 72701a6c311SAlfredo Cardigliano qcq->q.info = NULL; 72801a6c311SAlfredo Cardigliano } 72901a6c311SAlfredo Cardigliano 73001a6c311SAlfredo Cardigliano rte_free(qcq); 73101a6c311SAlfredo Cardigliano } 73201a6c311SAlfredo Cardigliano 7337b20fc2fSAndrew Boyer static uint64_t 7347b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif) 7357b20fc2fSAndrew Boyer { 7367b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7377b20fc2fSAndrew Boyer 7387b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7397b20fc2fSAndrew Boyer 7407b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7417b20fc2fSAndrew Boyer rxm.data_off = RTE_PKTMBUF_HEADROOM; 7427b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7437b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7447b20fc2fSAndrew Boyer 7457b20fc2fSAndrew Boyer rte_compiler_barrier(); 7467b20fc2fSAndrew Boyer 7477b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7487b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7497b20fc2fSAndrew Boyer } 7507b20fc2fSAndrew Boyer 7517b20fc2fSAndrew Boyer static uint64_t 7527b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif) 7537b20fc2fSAndrew Boyer { 7547b20fc2fSAndrew Boyer struct rte_mbuf rxm; 7557b20fc2fSAndrew Boyer 7567b20fc2fSAndrew Boyer memset(&rxm, 0, sizeof(rxm)); 7577b20fc2fSAndrew Boyer 7587b20fc2fSAndrew Boyer rte_mbuf_refcnt_set(&rxm, 1); 7597b20fc2fSAndrew Boyer rxm.data_off = 0; /* no headroom */ 7607b20fc2fSAndrew Boyer rxm.nb_segs = 1; 7617b20fc2fSAndrew Boyer rxm.port = lif->port_id; 7627b20fc2fSAndrew Boyer 7637b20fc2fSAndrew Boyer rte_compiler_barrier(); 7647b20fc2fSAndrew Boyer 7657b20fc2fSAndrew Boyer RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t)); 7667b20fc2fSAndrew Boyer return rxm.rearm_data[0]; 7677b20fc2fSAndrew Boyer } 7687b20fc2fSAndrew Boyer 769a27d9013SAlfredo Cardigliano int 7708ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 771d5850081SAndrew Boyer uint16_t nrxq_descs, struct rte_mempool *mb_pool, 772d5850081SAndrew Boyer struct ionic_rx_qcq **rxq_out) 773a27d9013SAlfredo Cardigliano { 774be39f75cSAndrew Boyer struct ionic_rx_qcq *rxq; 775e86a6fccSAndrew Boyer uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1; 776d5850081SAndrew Boyer uint32_t max_mtu; 777be39f75cSAndrew Boyer int err; 778a27d9013SAlfredo Cardigliano 7799de21005SAndrew Boyer if (lif->state & IONIC_LIF_F_Q_IN_CMB) 7809de21005SAndrew Boyer flags |= IONIC_QCQ_F_CMB; 781b671e69aSAndrew Boyer 782d5850081SAndrew Boyer seg_size = rte_pktmbuf_data_room_size(mb_pool); 783d5850081SAndrew Boyer 784d5850081SAndrew Boyer /* The first mbuf needs to leave headroom */ 785d5850081SAndrew Boyer hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM; 786d5850081SAndrew Boyer 787d5850081SAndrew Boyer max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu); 788d5850081SAndrew Boyer 789e86a6fccSAndrew Boyer /* If mbufs are too small to hold received packets, enable SG */ 79051de3175SAndrew Boyer if (max_mtu > hdr_seg_size && 79151de3175SAndrew Boyer !(lif->features & IONIC_ETH_HW_RX_SG)) { 792e86a6fccSAndrew Boyer IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER"); 793e86a6fccSAndrew Boyer lif->eth_dev->data->dev_conf.rxmode.offloads |= 794e86a6fccSAndrew Boyer RTE_ETH_RX_OFFLOAD_SCATTER; 795e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(lif); 796e86a6fccSAndrew Boyer } 797e86a6fccSAndrew Boyer 798e86a6fccSAndrew Boyer if (lif->features & IONIC_ETH_HW_RX_SG) { 799e86a6fccSAndrew Boyer flags |= IONIC_QCQ_F_SG; 800d5850081SAndrew Boyer max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1; 801e86a6fccSAndrew Boyer } 802d5850081SAndrew Boyer 803d5850081SAndrew Boyer /* 804d5850081SAndrew Boyer * Calculate how many fragment pointers might be stored in queue. 8057b20fc2fSAndrew Boyer * This is the worst-case number, so that there's enough room in 8067b20fc2fSAndrew Boyer * the info array. 807d5850081SAndrew Boyer */ 808d5850081SAndrew Boyer max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size; 809d5850081SAndrew Boyer 8107b20fc2fSAndrew Boyer IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u", 8117b20fc2fSAndrew Boyer index, max_mtu, seg_size, max_segs); 812d5850081SAndrew Boyer if (max_segs > max_segs_fw) { 813d5850081SAndrew Boyer IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)", 814d5850081SAndrew Boyer max_segs, max_segs_fw); 815d5850081SAndrew Boyer return -EINVAL; 816d5850081SAndrew Boyer } 817d5850081SAndrew Boyer 8184ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8194ad56b7aSAndrew Boyer IONIC_QTYPE_RXQ, 820be39f75cSAndrew Boyer sizeof(struct ionic_rx_qcq), 8218ec5ad7fSAndrew Boyer socket_id, 8224ad56b7aSAndrew Boyer index, 8234ad56b7aSAndrew Boyer "rx", 8244ad56b7aSAndrew Boyer flags, 825a27d9013SAlfredo Cardigliano nrxq_descs, 826d5850081SAndrew Boyer max_segs, 827a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_desc), 828a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_comp), 829a27d9013SAlfredo Cardigliano sizeof(struct ionic_rxq_sg_desc), 830be39f75cSAndrew Boyer (struct ionic_qcq **)&rxq); 831a27d9013SAlfredo Cardigliano if (err) 832a27d9013SAlfredo Cardigliano return err; 833a27d9013SAlfredo Cardigliano 834be39f75cSAndrew Boyer rxq->flags = flags; 835d5850081SAndrew Boyer rxq->seg_size = seg_size; 836d5850081SAndrew Boyer rxq->hdr_seg_size = hdr_seg_size; 8377b20fc2fSAndrew Boyer rxq->rearm_data = ionic_rx_rearm_data(lif); 8387b20fc2fSAndrew Boyer rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif); 839be39f75cSAndrew Boyer 840be39f75cSAndrew Boyer lif->rxqcqs[index] = rxq; 841be39f75cSAndrew Boyer *rxq_out = rxq; 842a27d9013SAlfredo Cardigliano 843a27d9013SAlfredo Cardigliano return 0; 844a27d9013SAlfredo Cardigliano } 845a27d9013SAlfredo Cardigliano 846a27d9013SAlfredo Cardigliano int 8478ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index, 848be39f75cSAndrew Boyer uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out) 849a27d9013SAlfredo Cardigliano { 850be39f75cSAndrew Boyer struct ionic_tx_qcq *txq; 851e86a6fccSAndrew Boyer uint16_t flags = 0, num_segs_fw = 1; 852be39f75cSAndrew Boyer int err; 853a27d9013SAlfredo Cardigliano 854e86a6fccSAndrew Boyer if (lif->features & IONIC_ETH_HW_TX_SG) { 855e86a6fccSAndrew Boyer flags |= IONIC_QCQ_F_SG; 856e86a6fccSAndrew Boyer num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1; 857e86a6fccSAndrew Boyer } 8589de21005SAndrew Boyer if (lif->state & IONIC_LIF_F_Q_IN_CMB) 8599de21005SAndrew Boyer flags |= IONIC_QCQ_F_CMB; 860e19eea1eSAndrew Boyer 861e86a6fccSAndrew Boyer IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw); 862e19eea1eSAndrew Boyer 8634ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8644ad56b7aSAndrew Boyer IONIC_QTYPE_TXQ, 865be39f75cSAndrew Boyer sizeof(struct ionic_tx_qcq), 8668ec5ad7fSAndrew Boyer socket_id, 8674ad56b7aSAndrew Boyer index, 8684ad56b7aSAndrew Boyer "tx", 8694ad56b7aSAndrew Boyer flags, 870a27d9013SAlfredo Cardigliano ntxq_descs, 871b4beb84aSAndrew Boyer num_segs_fw, 872a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_desc), 873a27d9013SAlfredo Cardigliano sizeof(struct ionic_txq_comp), 87456117636SAndrew Boyer sizeof(struct ionic_txq_sg_desc_v1), 875be39f75cSAndrew Boyer (struct ionic_qcq **)&txq); 876a27d9013SAlfredo Cardigliano if (err) 877a27d9013SAlfredo Cardigliano return err; 878a27d9013SAlfredo Cardigliano 879be39f75cSAndrew Boyer txq->flags = flags; 880e19eea1eSAndrew Boyer txq->num_segs_fw = num_segs_fw; 881be39f75cSAndrew Boyer 882be39f75cSAndrew Boyer lif->txqcqs[index] = txq; 883be39f75cSAndrew Boyer *txq_out = txq; 884a27d9013SAlfredo Cardigliano 885a27d9013SAlfredo Cardigliano return 0; 886a27d9013SAlfredo Cardigliano } 887a27d9013SAlfredo Cardigliano 88801a6c311SAlfredo Cardigliano static int 88901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 89001a6c311SAlfredo Cardigliano { 891be39f75cSAndrew Boyer uint16_t flags = 0; 892be39f75cSAndrew Boyer int err; 89301a6c311SAlfredo Cardigliano 8944ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 8954ad56b7aSAndrew Boyer IONIC_QTYPE_ADMINQ, 896be39f75cSAndrew Boyer sizeof(struct ionic_admin_qcq), 8978ec5ad7fSAndrew Boyer rte_socket_id(), 8984ad56b7aSAndrew Boyer 0, 8994ad56b7aSAndrew Boyer "admin", 9004ad56b7aSAndrew Boyer flags, 90101a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 902d5850081SAndrew Boyer 1, 90301a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 90401a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 90501a6c311SAlfredo Cardigliano 0, 906be39f75cSAndrew Boyer (struct ionic_qcq **)&lif->adminqcq); 90727b942c8SAlfredo Cardigliano if (err) 90827b942c8SAlfredo Cardigliano return err; 90901a6c311SAlfredo Cardigliano 91027b942c8SAlfredo Cardigliano return 0; 91127b942c8SAlfredo Cardigliano } 91227b942c8SAlfredo Cardigliano 91327b942c8SAlfredo Cardigliano static int 91427b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 91527b942c8SAlfredo Cardigliano { 916be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq; 9174c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 918be39f75cSAndrew Boyer uint16_t flags = 0; 919be39f75cSAndrew Boyer int err; 92027b942c8SAlfredo Cardigliano 9214ad56b7aSAndrew Boyer err = ionic_qcq_alloc(lif, 9224ad56b7aSAndrew Boyer IONIC_QTYPE_NOTIFYQ, 923be39f75cSAndrew Boyer sizeof(struct ionic_notify_qcq), 9248ec5ad7fSAndrew Boyer rte_socket_id(), 9254ad56b7aSAndrew Boyer 0, 9264ad56b7aSAndrew Boyer "notify", 92727b942c8SAlfredo Cardigliano flags, 92827b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 929d5850081SAndrew Boyer 1, 93027b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 93127b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 93227b942c8SAlfredo Cardigliano 0, 933be39f75cSAndrew Boyer (struct ionic_qcq **)&nqcq); 93401a6c311SAlfredo Cardigliano if (err) 93501a6c311SAlfredo Cardigliano return err; 93601a6c311SAlfredo Cardigliano 9374c8f8d57SAndrew Boyer err = ionic_intr_alloc(lif, &nqcq->intr); 9384c8f8d57SAndrew Boyer if (err) { 939be39f75cSAndrew Boyer ionic_qcq_free(&nqcq->qcq); 9404c8f8d57SAndrew Boyer return err; 9414c8f8d57SAndrew Boyer } 9424c8f8d57SAndrew Boyer 9434c8f8d57SAndrew Boyer ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index, 9444c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 9454c8f8d57SAndrew Boyer 9464c8f8d57SAndrew Boyer lif->notifyqcq = nqcq; 9474c8f8d57SAndrew Boyer 94801a6c311SAlfredo Cardigliano return 0; 94901a6c311SAlfredo Cardigliano } 95001a6c311SAlfredo Cardigliano 951c5d15850SAndrew Boyer static void 952c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif) 953c5d15850SAndrew Boyer { 954c5d15850SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 955c5d15850SAndrew Boyer struct ionic_dev *idev = &adapter->idev; 956c5d15850SAndrew Boyer union ionic_q_identity *q_ident = &adapter->ident.txq; 957c5d15850SAndrew Boyer uint32_t q_words = RTE_DIM(q_ident->words); 958c5d15850SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 959c5d15850SAndrew Boyer uint32_t i, nwords, qtype; 960c5d15850SAndrew Boyer int err; 961c5d15850SAndrew Boyer 962c5d15850SAndrew Boyer for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) { 963c5d15850SAndrew Boyer struct ionic_qtype_info *qti = &lif->qtype_info[qtype]; 964c5d15850SAndrew Boyer 965c5d15850SAndrew Boyer /* Filter out the types this driver knows about */ 966c5d15850SAndrew Boyer switch (qtype) { 967c5d15850SAndrew Boyer case IONIC_QTYPE_ADMINQ: 968c5d15850SAndrew Boyer case IONIC_QTYPE_NOTIFYQ: 969c5d15850SAndrew Boyer case IONIC_QTYPE_RXQ: 970c5d15850SAndrew Boyer case IONIC_QTYPE_TXQ: 971c5d15850SAndrew Boyer break; 972c5d15850SAndrew Boyer default: 973c5d15850SAndrew Boyer continue; 974c5d15850SAndrew Boyer } 975c5d15850SAndrew Boyer 976c5d15850SAndrew Boyer memset(qti, 0, sizeof(*qti)); 977c5d15850SAndrew Boyer 978c5d15850SAndrew Boyer ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC, 979c5d15850SAndrew Boyer qtype, ionic_qtype_vers[qtype]); 980c5d15850SAndrew Boyer err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 981c5d15850SAndrew Boyer if (err == -EINVAL) { 982c5d15850SAndrew Boyer IONIC_PRINT(ERR, "qtype %d not supported\n", qtype); 983c5d15850SAndrew Boyer continue; 984c5d15850SAndrew Boyer } else if (err == -EIO) { 985c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, older FW\n"); 986c5d15850SAndrew Boyer return; 987c5d15850SAndrew Boyer } else if (err) { 988c5d15850SAndrew Boyer IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n", 989c5d15850SAndrew Boyer qtype, err); 990c5d15850SAndrew Boyer return; 991c5d15850SAndrew Boyer } 992c5d15850SAndrew Boyer 993c5d15850SAndrew Boyer nwords = RTE_MIN(q_words, cmd_words); 994c5d15850SAndrew Boyer for (i = 0; i < nwords; i++) 995c5d15850SAndrew Boyer q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]); 996c5d15850SAndrew Boyer 997c5d15850SAndrew Boyer qti->version = q_ident->version; 998c5d15850SAndrew Boyer qti->supported = q_ident->supported; 999c5d15850SAndrew Boyer qti->features = rte_le_to_cpu_64(q_ident->features); 1000c5d15850SAndrew Boyer qti->desc_sz = rte_le_to_cpu_16(q_ident->desc_sz); 1001c5d15850SAndrew Boyer qti->comp_sz = rte_le_to_cpu_16(q_ident->comp_sz); 1002c5d15850SAndrew Boyer qti->sg_desc_sz = rte_le_to_cpu_16(q_ident->sg_desc_sz); 1003c5d15850SAndrew Boyer qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems); 1004c5d15850SAndrew Boyer qti->sg_desc_stride = 1005c5d15850SAndrew Boyer rte_le_to_cpu_16(q_ident->sg_desc_stride); 1006c5d15850SAndrew Boyer 1007c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].version = %d", 1008c5d15850SAndrew Boyer qtype, qti->version); 1009c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x", 1010c5d15850SAndrew Boyer qtype, qti->supported); 1011c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx", 1012c5d15850SAndrew Boyer qtype, qti->features); 1013c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d", 1014c5d15850SAndrew Boyer qtype, qti->desc_sz); 1015c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d", 1016c5d15850SAndrew Boyer qtype, qti->comp_sz); 1017c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d", 1018c5d15850SAndrew Boyer qtype, qti->sg_desc_sz); 1019c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d", 1020c5d15850SAndrew Boyer qtype, qti->max_sg_elems); 1021c5d15850SAndrew Boyer IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d", 1022c5d15850SAndrew Boyer qtype, qti->sg_desc_stride); 1023c5d15850SAndrew Boyer } 1024c5d15850SAndrew Boyer } 1025c5d15850SAndrew Boyer 1026669c8de6SAlfredo Cardigliano int 1027669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 1028669c8de6SAlfredo Cardigliano { 1029c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 1030669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 103101a6c311SAlfredo Cardigliano int err; 1032669c8de6SAlfredo Cardigliano 10334ae96cb8SAndrew Boyer /* 10344ae96cb8SAndrew Boyer * lif->name was zeroed on allocation. 10354ae96cb8SAndrew Boyer * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated. 10364ae96cb8SAndrew Boyer */ 10374ae96cb8SAndrew Boyer memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1); 10384ae96cb8SAndrew Boyer 10394ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "LIF: %s", lif->name); 1040669c8de6SAlfredo Cardigliano 1041c5d15850SAndrew Boyer ionic_lif_queue_identify(lif); 1042c5d15850SAndrew Boyer 104356117636SAndrew Boyer if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) { 104456117636SAndrew Boyer IONIC_PRINT(ERR, "FW too old, please upgrade"); 104556117636SAndrew Boyer return -ENXIO; 104656117636SAndrew Boyer } 104756117636SAndrew Boyer 10489de21005SAndrew Boyer if (adapter->q_in_cmb) { 10499de21005SAndrew Boyer if (adapter->bars.num_bars >= 3 && 10509de21005SAndrew Boyer lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 && 10519de21005SAndrew Boyer lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) { 10529de21005SAndrew Boyer IONIC_PRINT(INFO, "%s enabled on %s", 10539de21005SAndrew Boyer PMD_IONIC_CMB_KVARG, lif->name); 10549de21005SAndrew Boyer lif->state |= IONIC_LIF_F_Q_IN_CMB; 10559de21005SAndrew Boyer } else { 10569de21005SAndrew Boyer IONIC_PRINT(ERR, "%s not supported on %s, disabled", 10579de21005SAndrew Boyer PMD_IONIC_CMB_KVARG, lif->name); 10589de21005SAndrew Boyer } 10599de21005SAndrew Boyer } 10609de21005SAndrew Boyer 1061669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 1062669c8de6SAlfredo Cardigliano 106301a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 106401a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 106501a6c311SAlfredo Cardigliano 106684cf25bdSAndrew Boyer lif->kern_dbpage = adapter->idev.db_pages; 1067c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 1068c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 1069c67719e1SAlfredo Cardigliano return -ENOMEM; 1070c67719e1SAlfredo Cardigliano } 1071c67719e1SAlfredo Cardigliano 1072c5d0bb79SAndrew Boyer lif->txqcqs = rte_calloc_socket("ionic", 1073c663c7ecSAndrew Boyer adapter->max_ntxqs_per_lif, 1074c5d0bb79SAndrew Boyer sizeof(*lif->txqcqs), 1075c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 1076a27d9013SAlfredo Cardigliano if (!lif->txqcqs) { 1077a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate tx queues array"); 1078a27d9013SAlfredo Cardigliano return -ENOMEM; 1079a27d9013SAlfredo Cardigliano } 1080a27d9013SAlfredo Cardigliano 1081c5d0bb79SAndrew Boyer lif->rxqcqs = rte_calloc_socket("ionic", 1082c663c7ecSAndrew Boyer adapter->max_nrxqs_per_lif, 1083c5d0bb79SAndrew Boyer sizeof(*lif->rxqcqs), 1084c5d0bb79SAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 1085a27d9013SAlfredo Cardigliano if (!lif->rxqcqs) { 1086a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate rx queues array"); 1087a27d9013SAlfredo Cardigliano return -ENOMEM; 1088a27d9013SAlfredo Cardigliano } 1089a27d9013SAlfredo Cardigliano 109027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 109127b942c8SAlfredo Cardigliano 109227b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 109327b942c8SAlfredo Cardigliano if (err) { 109427b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 109527b942c8SAlfredo Cardigliano return err; 109627b942c8SAlfredo Cardigliano } 109727b942c8SAlfredo Cardigliano 109827b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 109927b942c8SAlfredo Cardigliano 110001a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 110101a6c311SAlfredo Cardigliano if (err) { 110201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 110301a6c311SAlfredo Cardigliano return err; 110401a6c311SAlfredo Cardigliano } 110501a6c311SAlfredo Cardigliano 110601a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 110701a6c311SAlfredo Cardigliano 1108924e6b76SThomas Monjalon lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size()); 1109669c8de6SAlfredo Cardigliano 1110669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 1111669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 1112669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 1113669c8de6SAlfredo Cardigliano if (!lif->info_z) { 1114669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 1115669c8de6SAlfredo Cardigliano return -ENOMEM; 1116669c8de6SAlfredo Cardigliano } 1117669c8de6SAlfredo Cardigliano 1118669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 1119669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 1120669c8de6SAlfredo Cardigliano 1121669c8de6SAlfredo Cardigliano return 0; 1122669c8de6SAlfredo Cardigliano } 1123669c8de6SAlfredo Cardigliano 1124669c8de6SAlfredo Cardigliano void 1125669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 1126669c8de6SAlfredo Cardigliano { 112727b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 1128be39f75cSAndrew Boyer ionic_qcq_free(&lif->notifyqcq->qcq); 112927b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 113027b942c8SAlfredo Cardigliano } 113127b942c8SAlfredo Cardigliano 113201a6c311SAlfredo Cardigliano if (lif->adminqcq) { 1133be39f75cSAndrew Boyer ionic_qcq_free(&lif->adminqcq->qcq); 113401a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 113501a6c311SAlfredo Cardigliano } 113601a6c311SAlfredo Cardigliano 1137a27d9013SAlfredo Cardigliano if (lif->txqcqs) { 1138a27d9013SAlfredo Cardigliano rte_free(lif->txqcqs); 1139a27d9013SAlfredo Cardigliano lif->txqcqs = NULL; 1140a27d9013SAlfredo Cardigliano } 1141a27d9013SAlfredo Cardigliano 1142a27d9013SAlfredo Cardigliano if (lif->rxqcqs) { 1143a27d9013SAlfredo Cardigliano rte_free(lif->rxqcqs); 1144a27d9013SAlfredo Cardigliano lif->rxqcqs = NULL; 1145a27d9013SAlfredo Cardigliano } 1146a27d9013SAlfredo Cardigliano 1147669c8de6SAlfredo Cardigliano if (lif->info) { 1148669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 1149669c8de6SAlfredo Cardigliano lif->info = NULL; 1150669c8de6SAlfredo Cardigliano } 1151669c8de6SAlfredo Cardigliano } 1152669c8de6SAlfredo Cardigliano 1153175e4e7eSAndrew Boyer void 1154175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif) 1155175e4e7eSAndrew Boyer { 1156175e4e7eSAndrew Boyer uint32_t i; 1157175e4e7eSAndrew Boyer 1158175e4e7eSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i++) { 11597483341aSXueming Li ionic_dev_tx_queue_release(lif->eth_dev, i); 1160175e4e7eSAndrew Boyer lif->eth_dev->data->tx_queues[i] = NULL; 1161175e4e7eSAndrew Boyer } 1162175e4e7eSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i++) { 11637483341aSXueming Li ionic_dev_rx_queue_release(lif->eth_dev, i); 1164175e4e7eSAndrew Boyer lif->eth_dev->data->rx_queues[i] = NULL; 1165175e4e7eSAndrew Boyer } 1166175e4e7eSAndrew Boyer } 1167175e4e7eSAndrew Boyer 116822e7171bSAlfredo Cardigliano int 116922e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif, 117022e7171bSAlfredo Cardigliano const uint16_t types, const uint8_t *key, const uint32_t *indir) 117122e7171bSAlfredo Cardigliano { 117209f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 117322e7171bSAlfredo Cardigliano struct ionic_admin_ctx ctx = { 117422e7171bSAlfredo Cardigliano .pending_work = true, 117522e7171bSAlfredo Cardigliano .cmd.lif_setattr = { 117622e7171bSAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 117722e7171bSAlfredo Cardigliano .attr = IONIC_LIF_ATTR_RSS, 117809f806e9SAndrew Boyer .rss.types = rte_cpu_to_le_16(types), 117909f806e9SAndrew Boyer .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa), 118022e7171bSAlfredo Cardigliano }, 118122e7171bSAlfredo Cardigliano }; 118222e7171bSAlfredo Cardigliano unsigned int i; 118309f806e9SAndrew Boyer uint16_t tbl_sz = 118409f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 118522e7171bSAlfredo Cardigliano 118622e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 118722e7171bSAlfredo Cardigliano 118822e7171bSAlfredo Cardigliano lif->rss_types = types; 118922e7171bSAlfredo Cardigliano 119022e7171bSAlfredo Cardigliano if (key) 119122e7171bSAlfredo Cardigliano memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); 119222e7171bSAlfredo Cardigliano 119322e7171bSAlfredo Cardigliano if (indir) 119409f806e9SAndrew Boyer for (i = 0; i < tbl_sz; i++) 119522e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = indir[i]; 119622e7171bSAlfredo Cardigliano 119722e7171bSAlfredo Cardigliano memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, 119822e7171bSAlfredo Cardigliano IONIC_RSS_HASH_KEY_SIZE); 119922e7171bSAlfredo Cardigliano 120022e7171bSAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 120122e7171bSAlfredo Cardigliano } 120222e7171bSAlfredo Cardigliano 120322e7171bSAlfredo Cardigliano static int 120422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif) 120522e7171bSAlfredo Cardigliano { 120609f806e9SAndrew Boyer struct ionic_adapter *adapter = lif->adapter; 120722e7171bSAlfredo Cardigliano static const uint8_t toeplitz_symmetric_key[] = { 120822e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 120922e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 121022e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 121122e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 121222e7171bSAlfredo Cardigliano 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 121322e7171bSAlfredo Cardigliano }; 121422e7171bSAlfredo Cardigliano uint32_t i; 121509f806e9SAndrew Boyer uint16_t tbl_sz = 121609f806e9SAndrew Boyer rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz); 121722e7171bSAlfredo Cardigliano 121822e7171bSAlfredo Cardigliano IONIC_PRINT_CALL(); 121922e7171bSAlfredo Cardigliano 12203d845eddSAndrew Boyer if (!lif->rss_ind_tbl_z) { 122122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, 12223d845eddSAndrew Boyer "rss_ind_tbl", 0 /* queue_idx */, 12233d845eddSAndrew Boyer sizeof(*lif->rss_ind_tbl) * tbl_sz, 12243d845eddSAndrew Boyer IONIC_ALIGN, rte_socket_id()); 122522e7171bSAlfredo Cardigliano if (!lif->rss_ind_tbl_z) { 122622e7171bSAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 122722e7171bSAlfredo Cardigliano return -ENOMEM; 122822e7171bSAlfredo Cardigliano } 122922e7171bSAlfredo Cardigliano 123022e7171bSAlfredo Cardigliano lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; 123122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; 12323d845eddSAndrew Boyer } 12333d845eddSAndrew Boyer 12343d845eddSAndrew Boyer if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) { 12353d845eddSAndrew Boyer lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs; 123622e7171bSAlfredo Cardigliano 123722e7171bSAlfredo Cardigliano /* Fill indirection table with 'default' values */ 12383d845eddSAndrew Boyer for (i = 0; i < tbl_sz; i++) 123922e7171bSAlfredo Cardigliano lif->rss_ind_tbl[i] = i % lif->nrxqcqs; 12403d845eddSAndrew Boyer } 124122e7171bSAlfredo Cardigliano 12423d845eddSAndrew Boyer return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, 124322e7171bSAlfredo Cardigliano toeplitz_symmetric_key, NULL); 124422e7171bSAlfredo Cardigliano } 124522e7171bSAlfredo Cardigliano 124622e7171bSAlfredo Cardigliano static void 124722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif) 124822e7171bSAlfredo Cardigliano { 12491a9afd1fSAndrew Boyer if (lif->rss_ind_tbl) { 125022e7171bSAlfredo Cardigliano lif->rss_ind_tbl = NULL; 125122e7171bSAlfredo Cardigliano lif->rss_ind_tbl_pa = 0; 125222e7171bSAlfredo Cardigliano rte_memzone_free(lif->rss_ind_tbl_z); 125322e7171bSAlfredo Cardigliano lif->rss_ind_tbl_z = NULL; 125422e7171bSAlfredo Cardigliano } 125522e7171bSAlfredo Cardigliano } 125622e7171bSAlfredo Cardigliano 1257be39f75cSAndrew Boyer void 12587bb08900SAndrew Boyer ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq *txq) 1259be39f75cSAndrew Boyer { 12607bb08900SAndrew Boyer ionic_qcq_disable_nowait(&txq->qcq, &txq->admin_ctx); 1261e7222f94SAndrew Boyer 1262be39f75cSAndrew Boyer txq->flags &= ~IONIC_QCQ_F_INITED; 1263be39f75cSAndrew Boyer } 1264be39f75cSAndrew Boyer 1265be39f75cSAndrew Boyer void 12667bb08900SAndrew Boyer ionic_lif_txq_stats(struct ionic_tx_qcq *txq) 1267be39f75cSAndrew Boyer { 12687bb08900SAndrew Boyer struct ionic_tx_stats *stats = &txq->stats; 12697bb08900SAndrew Boyer 12707bb08900SAndrew Boyer IONIC_PRINT(DEBUG, "TX queue %u pkts %ju tso %ju", 12717bb08900SAndrew Boyer txq->qcq.q.index, stats->packets, stats->tso); 12727bb08900SAndrew Boyer IONIC_PRINT(DEBUG, "TX queue %u comps %ju (%ju per)", 12737bb08900SAndrew Boyer txq->qcq.q.index, stats->comps, 12747bb08900SAndrew Boyer stats->comps ? stats->packets / stats->comps : 0); 12757bb08900SAndrew Boyer } 12767bb08900SAndrew Boyer 12777bb08900SAndrew Boyer void 12787bb08900SAndrew Boyer ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq *rxq) 12797bb08900SAndrew Boyer { 12807bb08900SAndrew Boyer ionic_qcq_disable_nowait(&rxq->qcq, &rxq->admin_ctx); 1281e7222f94SAndrew Boyer 1282be39f75cSAndrew Boyer rxq->flags &= ~IONIC_QCQ_F_INITED; 1283be39f75cSAndrew Boyer } 1284be39f75cSAndrew Boyer 12857bb08900SAndrew Boyer void 12867bb08900SAndrew Boyer ionic_lif_rxq_stats(struct ionic_rx_qcq *rxq) 12877bb08900SAndrew Boyer { 12887bb08900SAndrew Boyer struct ionic_rx_stats *stats = &rxq->stats; 12897bb08900SAndrew Boyer 12907bb08900SAndrew Boyer IONIC_PRINT(DEBUG, "RX queue %u pkts %ju mtod %ju", 12917bb08900SAndrew Boyer rxq->qcq.q.index, stats->packets, stats->mtods); 12927bb08900SAndrew Boyer } 12937bb08900SAndrew Boyer 129401a6c311SAlfredo Cardigliano static void 1295be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif) 129601a6c311SAlfredo Cardigliano { 1297be39f75cSAndrew Boyer lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED; 12984c8f8d57SAndrew Boyer } 12994c8f8d57SAndrew Boyer 13004c8f8d57SAndrew Boyer static void 13014c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif) 13024c8f8d57SAndrew Boyer { 1303be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 13044c8f8d57SAndrew Boyer struct ionic_dev *idev = &lif->adapter->idev; 13054c8f8d57SAndrew Boyer 13064c8f8d57SAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) 13074c8f8d57SAndrew Boyer return; 13084c8f8d57SAndrew Boyer 13094c8f8d57SAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 13104c8f8d57SAndrew Boyer IONIC_INTR_MASK_SET); 13114c8f8d57SAndrew Boyer 13124c8f8d57SAndrew Boyer nqcq->flags &= ~IONIC_QCQ_F_INITED; 1313a27d9013SAlfredo Cardigliano } 1314a27d9013SAlfredo Cardigliano 131501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 131601a6c311SAlfredo Cardigliano int 131701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 131801a6c311SAlfredo Cardigliano void *cb_arg) 131901a6c311SAlfredo Cardigliano { 132001a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 132101a6c311SAlfredo Cardigliano uint32_t work_done; 132201a6c311SAlfredo Cardigliano 132301a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 132401a6c311SAlfredo Cardigliano 132501a6c311SAlfredo Cardigliano return work_done; 132601a6c311SAlfredo Cardigliano } 132701a6c311SAlfredo Cardigliano 132827b942c8SAlfredo Cardigliano static void 132927b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 133027b942c8SAlfredo Cardigliano { 133127b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 133227b942c8SAlfredo Cardigliano bool link_up; 133327b942c8SAlfredo Cardigliano 133427b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 133527b942c8SAlfredo Cardigliano 133627b942c8SAlfredo Cardigliano if (!lif->info) 133727b942c8SAlfredo Cardigliano return; 133827b942c8SAlfredo Cardigliano 133927b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 134027b942c8SAlfredo Cardigliano 134127b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 134227b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 134327b942c8SAlfredo Cardigliano return; 134427b942c8SAlfredo Cardigliano 134527b942c8SAlfredo Cardigliano if (link_up) { 134609f806e9SAndrew Boyer adapter->link_speed = 134709f806e9SAndrew Boyer rte_le_to_cpu_32(lif->info->status.link_speed); 1348be63459eSAndrew Boyer IONIC_PRINT(DEBUG, "Link up - %d Gbps", 1349be63459eSAndrew Boyer adapter->link_speed); 135027b942c8SAlfredo Cardigliano } else { 135127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 135227b942c8SAlfredo Cardigliano } 135327b942c8SAlfredo Cardigliano 135427b942c8SAlfredo Cardigliano adapter->link_up = link_up; 1355be63459eSAndrew Boyer ionic_dev_link_update(lif->eth_dev, 0); 1356be63459eSAndrew Boyer } 1357be63459eSAndrew Boyer 1358be63459eSAndrew Boyer static void 1359be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif) 1360be63459eSAndrew Boyer { 1361be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_FW_RESET) 1362be63459eSAndrew Boyer return; 1363be63459eSAndrew Boyer 1364be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_FW_RESET; 1365be63459eSAndrew Boyer 1366be63459eSAndrew Boyer if (lif->state & IONIC_LIF_F_UP) { 1367be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1368be63459eSAndrew Boyer "Surprise FW stop, stopping %s\n", lif->name); 1369be63459eSAndrew Boyer ionic_lif_stop(lif); 1370be63459eSAndrew Boyer } 1371be63459eSAndrew Boyer 1372be63459eSAndrew Boyer IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name); 137327b942c8SAlfredo Cardigliano } 137427b942c8SAlfredo Cardigliano 137527b942c8SAlfredo Cardigliano static bool 13764ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg) 137727b942c8SAlfredo Cardigliano { 137827b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 137927b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 138027b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 138127b942c8SAlfredo Cardigliano 138227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 138327b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 138427b942c8SAlfredo Cardigliano 138527b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 138627b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 138727b942c8SAlfredo Cardigliano return false; 138827b942c8SAlfredo Cardigliano 138927b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 139027b942c8SAlfredo Cardigliano 139127b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 139227b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 139327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 1394be63459eSAndrew Boyer "Notifyq IONIC_EVENT_LINK_CHANGE %s " 1395be63459eSAndrew Boyer "eid=%jd link_status=%d link_speed=%d", 1396be63459eSAndrew Boyer lif->name, 139727b942c8SAlfredo Cardigliano cq_desc->event.eid, 139827b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 139927b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 140027b942c8SAlfredo Cardigliano 140127b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 140227b942c8SAlfredo Cardigliano break; 1403be63459eSAndrew Boyer 1404be63459eSAndrew Boyer case IONIC_EVENT_RESET: 1405be63459eSAndrew Boyer IONIC_PRINT(NOTICE, 1406be63459eSAndrew Boyer "Notifyq IONIC_EVENT_RESET %s " 1407be63459eSAndrew Boyer "eid=%jd, reset_code=%d state=%d", 1408be63459eSAndrew Boyer lif->name, 1409be63459eSAndrew Boyer cq_desc->event.eid, 1410be63459eSAndrew Boyer cq_desc->reset.reset_code, 1411be63459eSAndrew Boyer cq_desc->reset.state); 1412be63459eSAndrew Boyer ionic_lif_handle_fw_down(lif); 1413be63459eSAndrew Boyer break; 1414be63459eSAndrew Boyer 141527b942c8SAlfredo Cardigliano default: 141627b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 141727b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 141827b942c8SAlfredo Cardigliano break; 141927b942c8SAlfredo Cardigliano } 142027b942c8SAlfredo Cardigliano 142127b942c8SAlfredo Cardigliano return true; 142227b942c8SAlfredo Cardigliano } 142327b942c8SAlfredo Cardigliano 142427b942c8SAlfredo Cardigliano int 142527b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 142627b942c8SAlfredo Cardigliano { 142727b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1428be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 142927b942c8SAlfredo Cardigliano uint32_t work_done; 143027b942c8SAlfredo Cardigliano 1431be39f75cSAndrew Boyer if (!(nqcq->flags & IONIC_QCQ_F_INITED)) { 143227b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 143327b942c8SAlfredo Cardigliano return -1; 143427b942c8SAlfredo Cardigliano } 143527b942c8SAlfredo Cardigliano 1436be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 143727b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 143827b942c8SAlfredo Cardigliano 1439be39f75cSAndrew Boyer work_done = ionic_qcq_service(&nqcq->qcq, budget, 1440be39f75cSAndrew Boyer ionic_notifyq_cb, lif); 144127b942c8SAlfredo Cardigliano 144227b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 144327b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 144427b942c8SAlfredo Cardigliano 1445be39f75cSAndrew Boyer ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index, 144627b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 144727b942c8SAlfredo Cardigliano 1448be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 144927b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 145027b942c8SAlfredo Cardigliano 145127b942c8SAlfredo Cardigliano return 0; 145227b942c8SAlfredo Cardigliano } 145327b942c8SAlfredo Cardigliano 145401a6c311SAlfredo Cardigliano static int 145501a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 145601a6c311SAlfredo Cardigliano { 145701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1458be39f75cSAndrew Boyer struct ionic_admin_qcq *aqcq = lif->adminqcq; 1459be39f75cSAndrew Boyer struct ionic_queue *q = &aqcq->qcq.q; 146001a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 146113133a28SAndrew Boyer uint32_t retries = 5; 146201a6c311SAlfredo Cardigliano int err; 146301a6c311SAlfredo Cardigliano 146413133a28SAndrew Boyer retry_adminq_init: 1465be39f75cSAndrew Boyer ionic_dev_cmd_adminq_init(idev, &aqcq->qcq); 146601a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 146713133a28SAndrew Boyer if (err == -EAGAIN && retries > 0) { 146813133a28SAndrew Boyer retries--; 146913133a28SAndrew Boyer rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US); 147013133a28SAndrew Boyer goto retry_adminq_init; 147113133a28SAndrew Boyer } 147201a6c311SAlfredo Cardigliano if (err) 147301a6c311SAlfredo Cardigliano return err; 147401a6c311SAlfredo Cardigliano 147501a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 147601a6c311SAlfredo Cardigliano 147701a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 147809f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(comp.hw_index); 147901a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 148001a6c311SAlfredo Cardigliano 148101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 148201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 148301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 148401a6c311SAlfredo Cardigliano 1485be39f75cSAndrew Boyer aqcq->flags |= IONIC_QCQ_F_INITED; 148601a6c311SAlfredo Cardigliano 148701a6c311SAlfredo Cardigliano return 0; 148801a6c311SAlfredo Cardigliano } 148901a6c311SAlfredo Cardigliano 149027b942c8SAlfredo Cardigliano static int 149127b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 149227b942c8SAlfredo Cardigliano { 149327b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1494be39f75cSAndrew Boyer struct ionic_notify_qcq *nqcq = lif->notifyqcq; 1495be39f75cSAndrew Boyer struct ionic_queue *q = &nqcq->qcq.q; 14960a00bdafSAndrew Boyer uint16_t flags = IONIC_QINIT_F_ENA; 149727b942c8SAlfredo Cardigliano int err; 149827b942c8SAlfredo Cardigliano 149927b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 150027b942c8SAlfredo Cardigliano .pending_work = true, 150127b942c8SAlfredo Cardigliano .cmd.q_init = { 150227b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 150327b942c8SAlfredo Cardigliano .type = q->type, 1504c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 150509f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 15060a00bdafSAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 150727b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 150809f806e9SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 150927b942c8SAlfredo Cardigliano } 151027b942c8SAlfredo Cardigliano }; 151127b942c8SAlfredo Cardigliano 15120a00bdafSAndrew Boyer /* Only enable an interrupt if the device supports them */ 15130a00bdafSAndrew Boyer if (lif->adapter->intf->configure_intr != NULL) { 15140a00bdafSAndrew Boyer flags |= IONIC_QINIT_F_IRQ; 15150a00bdafSAndrew Boyer ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index); 15160a00bdafSAndrew Boyer } 15170a00bdafSAndrew Boyer ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags); 15180a00bdafSAndrew Boyer 151909f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index); 152009f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa); 152127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 152227b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 15234ae96cb8SAndrew Boyer IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver); 152427b942c8SAlfredo Cardigliano 152527b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 152627b942c8SAlfredo Cardigliano if (err) 152727b942c8SAlfredo Cardigliano return err; 152827b942c8SAlfredo Cardigliano 152927b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 153009f806e9SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 153127b942c8SAlfredo Cardigliano q->db = NULL; 153227b942c8SAlfredo Cardigliano 153327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 153427b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 153527b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 153627b942c8SAlfredo Cardigliano 1537be39f75cSAndrew Boyer ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index, 153827b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 153927b942c8SAlfredo Cardigliano 1540be39f75cSAndrew Boyer nqcq->flags |= IONIC_QCQ_F_INITED; 154127b942c8SAlfredo Cardigliano 154227b942c8SAlfredo Cardigliano return 0; 154327b942c8SAlfredo Cardigliano } 154427b942c8SAlfredo Cardigliano 1545669c8de6SAlfredo Cardigliano int 1546598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif) 1547598f6726SAlfredo Cardigliano { 1548598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1549598f6726SAlfredo Cardigliano .pending_work = true, 1550598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1551598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1552598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_FEATURES, 155309f806e9SAndrew Boyer .features = rte_cpu_to_le_64(lif->features), 1554598f6726SAlfredo Cardigliano }, 1555598f6726SAlfredo Cardigliano }; 1556598f6726SAlfredo Cardigliano int err; 1557598f6726SAlfredo Cardigliano 1558598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1559598f6726SAlfredo Cardigliano if (err) 1560598f6726SAlfredo Cardigliano return err; 1561598f6726SAlfredo Cardigliano 156209f806e9SAndrew Boyer lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features & 1563598f6726SAlfredo Cardigliano ctx.comp.lif_setattr.features); 1564598f6726SAlfredo Cardigliano 1565598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG) 1566598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG"); 1567598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP) 1568598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP"); 1569598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER) 1570598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER"); 1571598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_HASH) 1572598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH"); 1573598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_SG) 1574598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG"); 1575598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_SG) 1576598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG"); 1577598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TX_CSUM) 1578598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM"); 1579598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_RX_CSUM) 1580598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM"); 1581598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO) 1582598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO"); 1583598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6) 1584598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6"); 1585598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_ECN) 1586598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN"); 1587598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE) 1588598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE"); 1589598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM) 1590598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM"); 1591598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4) 1592598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4"); 1593598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6) 1594598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6"); 1595598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP) 1596598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP"); 1597598f6726SAlfredo Cardigliano if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM) 1598598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM"); 1599598f6726SAlfredo Cardigliano 1600598f6726SAlfredo Cardigliano return 0; 1601598f6726SAlfredo Cardigliano } 1602598f6726SAlfredo Cardigliano 1603a27d9013SAlfredo Cardigliano int 1604*0033e92fSAndrew Boyer ionic_lif_txq_init_nowait(struct ionic_tx_qcq *txq) 1605a27d9013SAlfredo Cardigliano { 1606be39f75cSAndrew Boyer struct ionic_qcq *qcq = &txq->qcq; 1607a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1608a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1609a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1610*0033e92fSAndrew Boyer struct ionic_admin_ctx *ctx = &txq->admin_ctx; 1611*0033e92fSAndrew Boyer int err; 1612*0033e92fSAndrew Boyer 1613*0033e92fSAndrew Boyer *ctx = (struct ionic_admin_ctx) { 1614a27d9013SAlfredo Cardigliano .pending_work = true, 1615a27d9013SAlfredo Cardigliano .cmd.q_init = { 1616a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1617a27d9013SAlfredo Cardigliano .type = q->type, 1618c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 161909f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1620e86a6fccSAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA), 162109f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1622a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 162309f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 162409f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1625a27d9013SAlfredo Cardigliano }, 1626a27d9013SAlfredo Cardigliano }; 1627a27d9013SAlfredo Cardigliano 1628e86a6fccSAndrew Boyer if (txq->flags & IONIC_QCQ_F_SG) 1629*0033e92fSAndrew Boyer ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG); 163090fa040aSNeel Patel if (txq->flags & IONIC_QCQ_F_CMB) { 1631*0033e92fSAndrew Boyer ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB); 1632*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa); 163390fa040aSNeel Patel } else { 1634*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa); 163590fa040aSNeel Patel } 16369de21005SAndrew Boyer 163709f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.index %d", q->index); 163809f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1639a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq_init.ring_size %d", 1640*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_size); 1641*0033e92fSAndrew Boyer IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx->cmd.q_init.ver); 1642a27d9013SAlfredo Cardigliano 1643e7222f94SAndrew Boyer ionic_q_reset(q); 1644e7222f94SAndrew Boyer ionic_cq_reset(cq); 1645e7222f94SAndrew Boyer 1646*0033e92fSAndrew Boyer /* Caller responsible for calling ionic_lif_txq_init_done() */ 1647*0033e92fSAndrew Boyer err = ionic_adminq_post(lif, ctx); 1648a27d9013SAlfredo Cardigliano if (err) 1649*0033e92fSAndrew Boyer ctx->pending_work = false; 1650a27d9013SAlfredo Cardigliano return err; 1651*0033e92fSAndrew Boyer } 1652a27d9013SAlfredo Cardigliano 1653*0033e92fSAndrew Boyer void 1654*0033e92fSAndrew Boyer ionic_lif_txq_init_done(struct ionic_tx_qcq *txq) 1655*0033e92fSAndrew Boyer { 1656*0033e92fSAndrew Boyer struct ionic_lif *lif = txq->qcq.lif; 1657*0033e92fSAndrew Boyer struct ionic_queue *q = &txq->qcq.q; 1658*0033e92fSAndrew Boyer struct ionic_admin_ctx *ctx = &txq->admin_ctx; 1659*0033e92fSAndrew Boyer 1660*0033e92fSAndrew Boyer q->hw_type = ctx->comp.q_init.hw_type; 1661*0033e92fSAndrew 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 1664a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type); 1665a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index); 1666a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "txq->db %p", q->db); 1667a27d9013SAlfredo Cardigliano 1668be39f75cSAndrew Boyer txq->flags |= IONIC_QCQ_F_INITED; 1669a27d9013SAlfredo Cardigliano } 1670a27d9013SAlfredo Cardigliano 1671a27d9013SAlfredo Cardigliano int 1672*0033e92fSAndrew Boyer ionic_lif_rxq_init_nowait(struct ionic_rx_qcq *rxq) 1673a27d9013SAlfredo Cardigliano { 1674be39f75cSAndrew Boyer struct ionic_qcq *qcq = &rxq->qcq; 1675a27d9013SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1676a27d9013SAlfredo Cardigliano struct ionic_lif *lif = qcq->lif; 1677a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 1678*0033e92fSAndrew Boyer struct ionic_admin_ctx *ctx = &rxq->admin_ctx; 1679*0033e92fSAndrew Boyer int err; 1680*0033e92fSAndrew Boyer 1681*0033e92fSAndrew Boyer *ctx = (struct ionic_admin_ctx) { 1682a27d9013SAlfredo Cardigliano .pending_work = true, 1683a27d9013SAlfredo Cardigliano .cmd.q_init = { 1684a27d9013SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 1685a27d9013SAlfredo Cardigliano .type = q->type, 1686c5d15850SAndrew Boyer .ver = lif->qtype_info[q->type].version, 168709f806e9SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 1688e86a6fccSAndrew Boyer .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA), 168909f806e9SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 1690a27d9013SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 169109f806e9SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 169209f806e9SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 1693a27d9013SAlfredo Cardigliano }, 1694a27d9013SAlfredo Cardigliano }; 1695a27d9013SAlfredo Cardigliano 1696e86a6fccSAndrew Boyer if (rxq->flags & IONIC_QCQ_F_SG) 1697*0033e92fSAndrew Boyer ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG); 169890fa040aSNeel Patel if (rxq->flags & IONIC_QCQ_F_CMB) { 1699*0033e92fSAndrew Boyer ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB); 1700*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa); 170190fa040aSNeel Patel } else { 1702*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa); 170390fa040aSNeel Patel } 17049de21005SAndrew Boyer 170509f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index); 170609f806e9SAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa); 1707a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq_init.ring_size %d", 1708*0033e92fSAndrew Boyer ctx->cmd.q_init.ring_size); 1709*0033e92fSAndrew Boyer IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx->cmd.q_init.ver); 1710a27d9013SAlfredo Cardigliano 1711e7222f94SAndrew Boyer ionic_q_reset(q); 1712e7222f94SAndrew Boyer ionic_cq_reset(cq); 1713e7222f94SAndrew Boyer 1714*0033e92fSAndrew Boyer /* Caller responsible for calling ionic_lif_rxq_init_done() */ 1715*0033e92fSAndrew Boyer err = ionic_adminq_post(lif, ctx); 1716a27d9013SAlfredo Cardigliano if (err) 1717*0033e92fSAndrew Boyer ctx->pending_work = false; 1718a27d9013SAlfredo Cardigliano return err; 1719*0033e92fSAndrew Boyer } 1720a27d9013SAlfredo Cardigliano 1721*0033e92fSAndrew Boyer void 1722*0033e92fSAndrew Boyer ionic_lif_rxq_init_done(struct ionic_rx_qcq *rxq) 1723*0033e92fSAndrew Boyer { 1724*0033e92fSAndrew Boyer struct ionic_lif *lif = rxq->qcq.lif; 1725*0033e92fSAndrew Boyer struct ionic_queue *q = &rxq->qcq.q; 1726*0033e92fSAndrew Boyer struct ionic_admin_ctx *ctx = &rxq->admin_ctx; 1727*0033e92fSAndrew Boyer 1728*0033e92fSAndrew Boyer q->hw_type = ctx->comp.q_init.hw_type; 1729*0033e92fSAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx->comp.q_init.hw_index); 1730a27d9013SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 1731a27d9013SAlfredo Cardigliano 1732be39f75cSAndrew Boyer rxq->flags |= IONIC_QCQ_F_INITED; 1733a27d9013SAlfredo Cardigliano 1734a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type); 1735a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index); 1736a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "rxq->db %p", q->db); 1737a27d9013SAlfredo Cardigliano } 1738a27d9013SAlfredo Cardigliano 1739598f6726SAlfredo Cardigliano static int 1740598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif) 1741598f6726SAlfredo Cardigliano { 1742598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1743598f6726SAlfredo Cardigliano .pending_work = true, 1744598f6726SAlfredo Cardigliano .cmd.lif_getattr = { 1745598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_GETATTR, 1746598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_MAC, 1747598f6726SAlfredo Cardigliano }, 1748598f6726SAlfredo Cardigliano }; 1749598f6726SAlfredo Cardigliano int err; 1750598f6726SAlfredo Cardigliano 1751598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 1752598f6726SAlfredo Cardigliano 1753598f6726SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 1754598f6726SAlfredo Cardigliano if (err) 1755598f6726SAlfredo Cardigliano return err; 1756598f6726SAlfredo Cardigliano 1757598f6726SAlfredo Cardigliano memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN); 1758598f6726SAlfredo Cardigliano 1759598f6726SAlfredo Cardigliano return 0; 1760598f6726SAlfredo Cardigliano } 1761598f6726SAlfredo Cardigliano 1762598f6726SAlfredo Cardigliano static void 1763598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif) 1764598f6726SAlfredo Cardigliano { 1765598f6726SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 1766598f6726SAlfredo Cardigliano .pending_work = true, 1767598f6726SAlfredo Cardigliano .cmd.lif_setattr = { 1768598f6726SAlfredo Cardigliano .opcode = IONIC_CMD_LIF_SETATTR, 1769598f6726SAlfredo Cardigliano .attr = IONIC_LIF_ATTR_NAME, 1770598f6726SAlfredo Cardigliano }, 1771598f6726SAlfredo Cardigliano }; 1772598f6726SAlfredo Cardigliano 17734ae96cb8SAndrew Boyer memcpy(ctx.cmd.lif_setattr.name, lif->name, 17744ae96cb8SAndrew Boyer sizeof(ctx.cmd.lif_setattr.name) - 1); 1775598f6726SAlfredo Cardigliano 1776598f6726SAlfredo Cardigliano ionic_adminq_post_wait(lif, &ctx); 1777598f6726SAlfredo Cardigliano } 1778598f6726SAlfredo Cardigliano 1779598f6726SAlfredo Cardigliano int 1780669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 1781669c8de6SAlfredo Cardigliano { 1782669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1783656bfc9aSAndrew Boyer struct ionic_lif_init_comp comp; 178413133a28SAndrew Boyer uint32_t retries = 5; 1785669c8de6SAlfredo Cardigliano int err; 1786669c8de6SAlfredo Cardigliano 17873cdfd905SAlfredo Cardigliano memset(&lif->stats_base, 0, sizeof(lif->stats_base)); 17883cdfd905SAlfredo Cardigliano 178913133a28SAndrew Boyer retry_lif_init: 179000b65da5SAndrew Boyer ionic_dev_cmd_lif_init(idev, lif->info_pa); 1791669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 179213133a28SAndrew Boyer if (err == -EAGAIN && retries > 0) { 179313133a28SAndrew Boyer retries--; 179413133a28SAndrew Boyer rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US); 179513133a28SAndrew Boyer goto retry_lif_init; 179613133a28SAndrew Boyer } 1797669c8de6SAlfredo Cardigliano if (err) 1798669c8de6SAlfredo Cardigliano return err; 1799669c8de6SAlfredo Cardigliano 1800656bfc9aSAndrew Boyer ionic_dev_cmd_comp(idev, &comp); 1801656bfc9aSAndrew Boyer 180209f806e9SAndrew Boyer lif->hw_index = rte_cpu_to_le_16(comp.hw_index); 1803669c8de6SAlfredo Cardigliano 180401a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 180501a6c311SAlfredo Cardigliano if (err) 180601a6c311SAlfredo Cardigliano return err; 180701a6c311SAlfredo Cardigliano 180827b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 180927b942c8SAlfredo Cardigliano if (err) 181027b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 181127b942c8SAlfredo Cardigliano 181218a44465SAndrew Boyer /* 181318a44465SAndrew Boyer * Configure initial feature set 181418a44465SAndrew Boyer * This will be updated later by the dev_configure() step 181518a44465SAndrew Boyer */ 181618a44465SAndrew Boyer lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER; 1817598f6726SAlfredo Cardigliano 1818598f6726SAlfredo Cardigliano err = ionic_lif_set_features(lif); 1819598f6726SAlfredo Cardigliano if (err) 1820598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1821598f6726SAlfredo Cardigliano 182254fe083fSAlfredo Cardigliano err = ionic_rx_filters_init(lif); 1823598f6726SAlfredo Cardigliano if (err) 1824598f6726SAlfredo Cardigliano goto err_out_notifyq_deinit; 1825598f6726SAlfredo Cardigliano 182654fe083fSAlfredo Cardigliano err = ionic_station_set(lif); 182754fe083fSAlfredo Cardigliano if (err) 182854fe083fSAlfredo Cardigliano goto err_out_rx_filter_deinit; 182954fe083fSAlfredo Cardigliano 1830598f6726SAlfredo Cardigliano ionic_lif_set_name(lif); 1831598f6726SAlfredo Cardigliano 1832669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 1833669c8de6SAlfredo Cardigliano 1834669c8de6SAlfredo Cardigliano return 0; 183527b942c8SAlfredo Cardigliano 183654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit: 183754fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 183854fe083fSAlfredo Cardigliano 1839598f6726SAlfredo Cardigliano err_out_notifyq_deinit: 18404c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1841598f6726SAlfredo Cardigliano 184227b942c8SAlfredo Cardigliano err_out_adminq_deinit: 1843be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 184427b942c8SAlfredo Cardigliano 184527b942c8SAlfredo Cardigliano return err; 1846669c8de6SAlfredo Cardigliano } 1847669c8de6SAlfredo Cardigliano 1848669c8de6SAlfredo Cardigliano void 1849669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 1850669c8de6SAlfredo Cardigliano { 1851669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 1852669c8de6SAlfredo Cardigliano return; 1853669c8de6SAlfredo Cardigliano 185454fe083fSAlfredo Cardigliano ionic_rx_filters_deinit(lif); 185522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(lif); 18564c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(lif); 1857be39f75cSAndrew Boyer ionic_lif_adminq_deinit(lif); 185801a6c311SAlfredo Cardigliano 1859669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 1860669c8de6SAlfredo Cardigliano } 1861669c8de6SAlfredo Cardigliano 186218a44465SAndrew Boyer void 186318a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask) 186418a44465SAndrew Boyer { 186518a44465SAndrew Boyer struct rte_eth_dev *eth_dev = lif->eth_dev; 186618a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; 186718a44465SAndrew Boyer 186818a44465SAndrew Boyer /* 186918a44465SAndrew Boyer * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so 1870295968d1SFerruh Yigit * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK 187118a44465SAndrew Boyer */ 1872295968d1SFerruh Yigit rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; 187318a44465SAndrew Boyer 1874295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_STRIP_MASK) { 1875295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 187618a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP; 187718a44465SAndrew Boyer else 187818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP; 187918a44465SAndrew Boyer } 188018a44465SAndrew Boyer } 188118a44465SAndrew Boyer 188218a44465SAndrew Boyer void 1883e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif) 1884e86a6fccSAndrew Boyer { 1885e86a6fccSAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 1886e86a6fccSAndrew Boyer 1887e86a6fccSAndrew Boyer if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) { 1888e86a6fccSAndrew Boyer lif->features |= IONIC_ETH_HW_RX_SG; 1889e86a6fccSAndrew Boyer lif->eth_dev->data->scattered_rx = 1; 1890e86a6fccSAndrew Boyer } else { 1891e86a6fccSAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_SG; 1892e86a6fccSAndrew Boyer lif->eth_dev->data->scattered_rx = 0; 1893e86a6fccSAndrew Boyer } 1894e86a6fccSAndrew Boyer } 1895e86a6fccSAndrew Boyer 1896e86a6fccSAndrew Boyer void 1897598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif) 1898598f6726SAlfredo Cardigliano { 189918a44465SAndrew Boyer struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode; 190018a44465SAndrew Boyer struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode; 190122e7171bSAlfredo Cardigliano struct ionic_identity *ident = &lif->adapter->ident; 190209f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 190322e7171bSAlfredo Cardigliano uint32_t ntxqs_per_lif = 190409f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 190522e7171bSAlfredo Cardigliano uint32_t nrxqs_per_lif = 190609f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 190722e7171bSAlfredo Cardigliano uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; 190822e7171bSAlfredo Cardigliano uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; 190922e7171bSAlfredo Cardigliano 1910598f6726SAlfredo Cardigliano lif->port_id = lif->eth_dev->data->port_id; 1911598f6726SAlfredo Cardigliano 191222e7171bSAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring LIF on port %u", 191322e7171bSAlfredo Cardigliano lif->port_id); 191422e7171bSAlfredo Cardigliano 191522e7171bSAlfredo Cardigliano if (nrxqs > 0) 191622e7171bSAlfredo Cardigliano nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); 191722e7171bSAlfredo Cardigliano 191822e7171bSAlfredo Cardigliano if (ntxqs > 0) 191922e7171bSAlfredo Cardigliano ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); 192022e7171bSAlfredo Cardigliano 192122e7171bSAlfredo Cardigliano lif->nrxqcqs = nrxqs_per_lif; 192222e7171bSAlfredo Cardigliano lif->ntxqcqs = ntxqs_per_lif; 1923a27d9013SAlfredo Cardigliano 192418a44465SAndrew Boyer /* Update the LIF configuration based on the eth_dev */ 192518a44465SAndrew Boyer 192618a44465SAndrew Boyer /* 192718a44465SAndrew Boyer * NB: While it is true that RSS_HASH is always enabled on ionic, 192818a44465SAndrew Boyer * setting this flag unconditionally causes problems in DTS. 1929295968d1SFerruh Yigit * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 193018a44465SAndrew Boyer */ 193118a44465SAndrew Boyer 193218a44465SAndrew Boyer /* RX per-port */ 193318a44465SAndrew Boyer 1934295968d1SFerruh Yigit if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM || 1935295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM || 1936295968d1SFerruh Yigit rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) 193718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_RX_CSUM; 193818a44465SAndrew Boyer else 193918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_RX_CSUM; 194018a44465SAndrew Boyer 1941e86a6fccSAndrew Boyer /* 1942e86a6fccSAndrew Boyer * NB: RX_SG may be enabled later during rx_queue_setup() if 1943e86a6fccSAndrew Boyer * required by the mbuf/mtu configuration 1944e86a6fccSAndrew Boyer */ 1945e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(lif); 194618a44465SAndrew Boyer 194718a44465SAndrew Boyer /* Covers VLAN_STRIP */ 1948295968d1SFerruh Yigit ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK); 194918a44465SAndrew Boyer 195018a44465SAndrew Boyer /* TX per-port */ 195118a44465SAndrew Boyer 1952295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM || 1953295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM || 1954295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM || 1955295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM || 1956295968d1SFerruh Yigit txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) 195718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_CSUM; 195818a44465SAndrew Boyer else 195918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_CSUM; 196018a44465SAndrew Boyer 1961295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) 196218a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_VLAN_TX_TAG; 196318a44465SAndrew Boyer else 196418a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG; 196518a44465SAndrew Boyer 1966295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) 196718a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TX_SG; 196818a44465SAndrew Boyer else 196918a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TX_SG; 197018a44465SAndrew Boyer 1971295968d1SFerruh Yigit if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) { 197218a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO; 197318a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_IPV6; 197418a44465SAndrew Boyer lif->features |= IONIC_ETH_HW_TSO_ECN; 197518a44465SAndrew Boyer } else { 197618a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO; 197718a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_IPV6; 197818a44465SAndrew Boyer lif->features &= ~IONIC_ETH_HW_TSO_ECN; 197918a44465SAndrew Boyer } 1980598f6726SAlfredo Cardigliano } 1981598f6726SAlfredo Cardigliano 1982598f6726SAlfredo Cardigliano int 1983598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif) 1984598f6726SAlfredo Cardigliano { 1985*0033e92fSAndrew Boyer struct rte_eth_dev *dev = lif->eth_dev; 19860578335aSAndrew Boyer uint32_t rx_mode; 1987*0033e92fSAndrew Boyer uint32_t i, j, chunk; 1988a27d9013SAlfredo Cardigliano int err; 1989*0033e92fSAndrew Boyer bool fatal = false; 1990598f6726SAlfredo Cardigliano 199122e7171bSAlfredo Cardigliano err = ionic_lif_rss_setup(lif); 199222e7171bSAlfredo Cardigliano if (err) 199322e7171bSAlfredo Cardigliano return err; 199422e7171bSAlfredo Cardigliano 19950578335aSAndrew Boyer if (!lif->rx_mode) { 19960578335aSAndrew Boyer IONIC_PRINT(DEBUG, "Setting RX mode on %s", 19970578335aSAndrew Boyer lif->name); 1998598f6726SAlfredo Cardigliano 19990578335aSAndrew Boyer rx_mode = IONIC_RX_MODE_F_UNICAST; 2000598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_MULTICAST; 2001598f6726SAlfredo Cardigliano rx_mode |= IONIC_RX_MODE_F_BROADCAST; 2002598f6726SAlfredo Cardigliano 2003598f6726SAlfredo Cardigliano ionic_set_rx_mode(lif, rx_mode); 20040578335aSAndrew Boyer } 2005598f6726SAlfredo Cardigliano 2006a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues " 2007a27d9013SAlfredo Cardigliano "on port %u", 2008a27d9013SAlfredo Cardigliano lif->nrxqcqs, lif->ntxqcqs, lif->port_id); 2009a27d9013SAlfredo Cardigliano 2010*0033e92fSAndrew Boyer chunk = ionic_adminq_space_avail(lif); 2011a27d9013SAlfredo Cardigliano 2012*0033e92fSAndrew Boyer for (i = 0; i < lif->nrxqcqs; i += chunk) { 2013*0033e92fSAndrew Boyer if (lif->rxqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) { 2014*0033e92fSAndrew Boyer IONIC_PRINT(DEBUG, "Rx queue start deferred"); 2015*0033e92fSAndrew Boyer break; 2016*0033e92fSAndrew Boyer } 2017*0033e92fSAndrew Boyer 2018*0033e92fSAndrew Boyer for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) { 2019*0033e92fSAndrew Boyer err = ionic_dev_rx_queue_start_firsthalf(dev, i + j); 2020*0033e92fSAndrew Boyer if (err) { 2021*0033e92fSAndrew Boyer fatal = true; 2022*0033e92fSAndrew Boyer break; 2023*0033e92fSAndrew Boyer } 2024*0033e92fSAndrew Boyer } 2025*0033e92fSAndrew Boyer 2026*0033e92fSAndrew Boyer for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) { 2027*0033e92fSAndrew Boyer /* Commands that failed to post return immediately */ 2028*0033e92fSAndrew Boyer err = ionic_dev_rx_queue_start_secondhalf(dev, i + j); 2029a27d9013SAlfredo Cardigliano if (err) 2030*0033e92fSAndrew Boyer /* Don't break */ 2031*0033e92fSAndrew Boyer fatal = true; 2032*0033e92fSAndrew Boyer } 2033*0033e92fSAndrew Boyer } 2034*0033e92fSAndrew Boyer if (fatal) 2035*0033e92fSAndrew Boyer return -EIO; 2036*0033e92fSAndrew Boyer 2037*0033e92fSAndrew Boyer for (i = 0; i < lif->ntxqcqs; i += chunk) { 2038*0033e92fSAndrew Boyer if (lif->txqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) { 2039*0033e92fSAndrew Boyer IONIC_PRINT(DEBUG, "Tx queue start deferred"); 2040*0033e92fSAndrew Boyer break; 2041*0033e92fSAndrew Boyer } 2042*0033e92fSAndrew Boyer 2043*0033e92fSAndrew Boyer for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) { 2044*0033e92fSAndrew Boyer err = ionic_dev_tx_queue_start_firsthalf(dev, i + j); 2045*0033e92fSAndrew Boyer if (err) { 2046*0033e92fSAndrew Boyer fatal = true; 2047*0033e92fSAndrew Boyer break; 2048a27d9013SAlfredo Cardigliano } 2049a27d9013SAlfredo Cardigliano } 2050a27d9013SAlfredo Cardigliano 2051*0033e92fSAndrew Boyer for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) { 2052*0033e92fSAndrew Boyer /* Commands that failed to post return immediately */ 2053*0033e92fSAndrew Boyer err = ionic_dev_tx_queue_start_secondhalf(dev, i + j); 2054a27d9013SAlfredo Cardigliano if (err) 2055*0033e92fSAndrew Boyer /* Don't break */ 2056*0033e92fSAndrew Boyer fatal = true; 2057a27d9013SAlfredo Cardigliano } 2058a27d9013SAlfredo Cardigliano } 2059*0033e92fSAndrew Boyer if (fatal) 2060*0033e92fSAndrew Boyer return -EIO; 2061a27d9013SAlfredo Cardigliano 2062598f6726SAlfredo Cardigliano /* Carrier ON here */ 2063be63459eSAndrew Boyer lif->state |= IONIC_LIF_F_UP; 2064be63459eSAndrew Boyer 2065be63459eSAndrew Boyer ionic_link_status_check(lif); 2066598f6726SAlfredo Cardigliano 2067598f6726SAlfredo Cardigliano return 0; 2068598f6726SAlfredo Cardigliano } 2069598f6726SAlfredo Cardigliano 2070598f6726SAlfredo Cardigliano int 2071669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 2072669c8de6SAlfredo Cardigliano { 2073669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 2074669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 207509f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 207676276d71SAndrew Boyer uint32_t lif_words = RTE_DIM(ident->lif.words); 207776276d71SAndrew Boyer uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data); 207876276d71SAndrew Boyer uint32_t i, nwords; 2079669c8de6SAlfredo Cardigliano int err; 2080669c8de6SAlfredo Cardigliano 2081669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 2082669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 2083669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 2084669c8de6SAlfredo Cardigliano if (err) 2085669c8de6SAlfredo Cardigliano return (err); 2086669c8de6SAlfredo Cardigliano 2087669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 2088669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 2089669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 2090669c8de6SAlfredo Cardigliano 2091669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 209209f806e9SAndrew Boyer rte_le_to_cpu_64(ident->lif.capabilities)); 2093669c8de6SAlfredo Cardigliano 2094669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 209509f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters)); 2096669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 209709f806e9SAndrew Boyer rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters)); 2098669c8de6SAlfredo Cardigliano 2099669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 210009f806e9SAndrew Boyer rte_le_to_cpu_64(cfg->features)); 2101669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 210209f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ])); 2103669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 210409f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ])); 2105669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 210609f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ])); 2107669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 210809f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ])); 2109669c8de6SAlfredo Cardigliano 2110669c8de6SAlfredo Cardigliano return 0; 2111669c8de6SAlfredo Cardigliano } 2112669c8de6SAlfredo Cardigliano 2113669c8de6SAlfredo Cardigliano int 2114669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 2115669c8de6SAlfredo Cardigliano { 2116669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 211709f806e9SAndrew Boyer union ionic_lif_config *cfg = &ident->lif.eth.config; 211809f806e9SAndrew Boyer uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs); 2119669c8de6SAlfredo Cardigliano 2120669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 212109f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]); 2122669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 212309f806e9SAndrew Boyer rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]); 2124669c8de6SAlfredo Cardigliano 212500b65da5SAndrew Boyer nintrs = 1 /* notifyq */; 2126669c8de6SAlfredo Cardigliano 2127669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 21284ae96cb8SAndrew Boyer IONIC_PRINT(ERR, 21294ae96cb8SAndrew Boyer "At most %d intr supported, minimum req'd is %u", 2130669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 2131669c8de6SAlfredo Cardigliano return -ENOSPC; 2132669c8de6SAlfredo Cardigliano } 2133669c8de6SAlfredo Cardigliano 2134669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 2135669c8de6SAlfredo Cardigliano 2136669c8de6SAlfredo Cardigliano return 0; 2137669c8de6SAlfredo Cardigliano } 2138