X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_tx.c;h=d75fb84eb7dc8ab580e008e2c9d6c44159c8d025;hb=5eb55bf8a45a3ed92815a5b6dcdbac83cd807bcb;hp=1979e1fafeed294b1340d62b54fb2e52813bc766;hpb=7a4d44a639c99c8350cf738e40e7ae45e58f5960;p=dpdk.git diff --git a/drivers/net/sfc/sfc_tx.c b/drivers/net/sfc/sfc_tx.c index 1979e1fafe..d75fb84eb7 100644 --- a/drivers/net/sfc/sfc_tx.c +++ b/drivers/net/sfc/sfc_tx.c @@ -84,6 +84,13 @@ sfc_tx_qcheck_conf(struct sfc_adapter *sa, uint16_t nb_tx_desc, rc = EINVAL; } + if (((flags & ETH_TXQ_FLAGS_NOMULTSEGS) == 0) && + (~sa->dp_tx->features & SFC_DP_TX_FEAT_MULTI_SEG)) { + sfc_err(sa, "Multi-segment is not supported by %s datapath", + sa->dp_tx->dp.name); + rc = EINVAL; + } + if ((flags & ETH_TXQ_FLAGS_NOVLANOFFL) == 0) { if (!encp->enc_hw_tx_insert_vlan_enabled) { sfc_err(sa, "VLAN offload is not supported"); @@ -127,7 +134,6 @@ sfc_tx_qinit(struct sfc_adapter *sa, unsigned int sw_index, struct sfc_txq_info *txq_info; struct sfc_evq *evq; struct sfc_txq *txq; - unsigned int evq_index = sfc_evq_index_by_txq_sw_index(sa, sw_index); int rc = 0; struct sfc_dp_tx_qcreate_info info; @@ -143,12 +149,11 @@ sfc_tx_qinit(struct sfc_adapter *sa, unsigned int sw_index, SFC_ASSERT(nb_tx_desc <= sa->txq_max_entries); txq_info->entries = nb_tx_desc; - rc = sfc_ev_qinit(sa, evq_index, txq_info->entries, socket_id); + rc = sfc_ev_qinit(sa, SFC_EVQ_TYPE_TX, sw_index, + txq_info->entries, socket_id, &evq); if (rc != 0) goto fail_ev_qinit; - evq = sa->evq_info[evq_index].evq; - rc = ENOMEM; txq = rte_zmalloc_socket("sfc-txq", sizeof(*txq), 0, socket_id); if (txq == NULL) @@ -173,9 +178,14 @@ sfc_tx_qinit(struct sfc_adapter *sa, unsigned int sw_index, info.flags = tx_conf->txq_flags; info.txq_entries = txq_info->entries; info.dma_desc_size_max = encp->enc_tx_dma_desc_size_max; + info.txq_hw_ring = txq->mem.esm_base; + info.evq_entries = txq_info->entries; + info.evq_hw_ring = evq->mem.esm_base; + info.hw_index = txq->hw_index; + info.mem_bar = sa->mem_bar.esb_base; rc = sa->dp_tx->qcreate(sa->eth_dev->data->port_id, sw_index, - &SFC_DEV_TO_PCI(sa->eth_dev)->addr, + &RTE_ETH_DEV_TO_PCI(sa->eth_dev)->addr, socket_id, &info, &txq->dp); if (rc != 0) goto fail_dp_tx_qinit; @@ -196,7 +206,7 @@ fail_dma_alloc: rte_free(txq); fail_txq_alloc: - sfc_ev_qfini(sa, evq_index); + sfc_ev_qfini(evq); fail_ev_qinit: txq_info->entries = 0; @@ -228,6 +238,10 @@ sfc_tx_qfini(struct sfc_adapter *sa, unsigned int sw_index) txq_info->entries = 0; sfc_dma_free(sa, &txq->mem); + + sfc_ev_qfini(txq->evq); + txq->evq = NULL; + rte_free(txq); } @@ -275,14 +289,37 @@ sfc_tx_check_mode(struct sfc_adapter *sa, const struct rte_eth_txmode *txmode) return rc; } +/** + * Destroy excess queues that are no longer needed after reconfiguration + * or complete close. + */ +static void +sfc_tx_fini_queues(struct sfc_adapter *sa, unsigned int nb_tx_queues) +{ + int sw_index; + + SFC_ASSERT(nb_tx_queues <= sa->txq_count); + + sw_index = sa->txq_count; + while (--sw_index >= (int)nb_tx_queues) { + if (sa->txq_info[sw_index].txq != NULL) + sfc_tx_qfini(sa, sw_index); + } + + sa->txq_count = nb_tx_queues; +} + int -sfc_tx_init(struct sfc_adapter *sa) +sfc_tx_configure(struct sfc_adapter *sa) { const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); const struct rte_eth_conf *dev_conf = &sa->eth_dev->data->dev_conf; - unsigned int sw_index; + const unsigned int nb_tx_queues = sa->eth_dev->data->nb_tx_queues; int rc = 0; + sfc_log_init(sa, "nb_tx_queues=%u (old %u)", + nb_tx_queues, sa->txq_count); + /* * The datapath implementation assumes absence of boundary * limits on Tx DMA descriptors. Addition of these checks on @@ -293,35 +330,53 @@ sfc_tx_init(struct sfc_adapter *sa) goto fail_tx_dma_desc_boundary; } - if (~sa->dp_tx->features & SFC_DP_TX_FEAT_TSO) - sa->tso = B_FALSE; - rc = sfc_tx_check_mode(sa, &dev_conf->txmode); if (rc != 0) goto fail_check_mode; - sa->txq_count = sa->eth_dev->data->nb_tx_queues; + if (nb_tx_queues == sa->txq_count) + goto done; - sa->txq_info = rte_calloc_socket("sfc-txqs", sa->txq_count, - sizeof(sa->txq_info[0]), 0, - sa->socket_id); - if (sa->txq_info == NULL) - goto fail_txqs_alloc; + if (sa->txq_info == NULL) { + sa->txq_info = rte_calloc_socket("sfc-txqs", nb_tx_queues, + sizeof(sa->txq_info[0]), 0, + sa->socket_id); + if (sa->txq_info == NULL) + goto fail_txqs_alloc; + } else { + struct sfc_txq_info *new_txq_info; + + if (nb_tx_queues < sa->txq_count) + sfc_tx_fini_queues(sa, nb_tx_queues); + + new_txq_info = + rte_realloc(sa->txq_info, + nb_tx_queues * sizeof(sa->txq_info[0]), 0); + if (new_txq_info == NULL && nb_tx_queues > 0) + goto fail_txqs_realloc; + + sa->txq_info = new_txq_info; + if (nb_tx_queues > sa->txq_count) + memset(&sa->txq_info[sa->txq_count], 0, + (nb_tx_queues - sa->txq_count) * + sizeof(sa->txq_info[0])); + } - for (sw_index = 0; sw_index < sa->txq_count; ++sw_index) { - rc = sfc_tx_qinit_info(sa, sw_index); + while (sa->txq_count < nb_tx_queues) { + rc = sfc_tx_qinit_info(sa, sa->txq_count); if (rc != 0) goto fail_tx_qinit_info; + + sa->txq_count++; } +done: return 0; fail_tx_qinit_info: - rte_free(sa->txq_info); - sa->txq_info = NULL; - +fail_txqs_realloc: fail_txqs_alloc: - sa->txq_count = 0; + sfc_tx_close(sa); fail_check_mode: fail_tx_dma_desc_boundary: @@ -330,19 +385,12 @@ fail_tx_dma_desc_boundary: } void -sfc_tx_fini(struct sfc_adapter *sa) +sfc_tx_close(struct sfc_adapter *sa) { - int sw_index; - - sw_index = sa->txq_count; - while (--sw_index >= 0) { - if (sa->txq_info[sw_index].txq != NULL) - sfc_tx_qfini(sa, sw_index); - } + sfc_tx_fini_queues(sa, 0); rte_free(sa->txq_info); sa->txq_info = NULL; - sa->txq_count = 0; } int @@ -367,7 +415,7 @@ sfc_tx_qstart(struct sfc_adapter *sa, unsigned int sw_index) evq = txq->evq; - rc = sfc_ev_qstart(sa, evq->evq_index); + rc = sfc_ev_qstart(evq, sfc_evq_index_by_txq_sw_index(sa, sw_index)); if (rc != 0) goto fail_ev_qstart; @@ -417,7 +465,7 @@ fail_dp_qstart: efx_tx_qdestroy(txq->common); fail_tx_qcreate: - sfc_ev_qstop(sa, evq->evq_index); + sfc_ev_qstop(evq); fail_ev_qstart: return rc; @@ -485,7 +533,7 @@ sfc_tx_qstop(struct sfc_adapter *sa, unsigned int sw_index) efx_tx_qdestroy(txq->common); - sfc_ev_qstop(sa, txq->evq->evq_index); + sfc_ev_qstop(txq->evq); /* * It seems to be used by DPDK for debug purposes only ('rte_ether') @@ -933,7 +981,8 @@ struct sfc_dp_tx sfc_efx_tx = { .hw_fw_caps = 0, }, .features = SFC_DP_TX_FEAT_VLAN_INSERT | - SFC_DP_TX_FEAT_TSO, + SFC_DP_TX_FEAT_TSO | + SFC_DP_TX_FEAT_MULTI_SEG, .qcreate = sfc_efx_tx_qcreate, .qdestroy = sfc_efx_tx_qdestroy, .qstart = sfc_efx_tx_qstart,