From: Igor Romanov Date: Tue, 23 Apr 2019 08:14:30 +0000 (+0100) Subject: net/sfc: fix MTU change to check Rx scatter consistency X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=6c0cc77a2dd3806c5366586d818b1796a610e260;p=dpdk.git net/sfc: fix MTU change to check Rx scatter consistency Rx queue setup function checks configured MTU to make sure that no oversized packets can be received. But a following call to set MTU function might make this check irrelevant. Add a function to check MTU size against Rx buffer size and additional Rx queue info, including Rx scatter offload. Fixes: e961cf425e02 ("net/sfc: support MTU change") Cc: stable@dpdk.org Signed-off-by: Igor Romanov Signed-off-by: Andrew Rybchenko --- diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index ff192314d1..a007d4564c 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -865,6 +865,34 @@ fail_inval: return -rc; } +static int +sfc_check_scatter_on_all_rx_queues(struct sfc_adapter *sa, size_t pdu) +{ + struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); + const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); + boolean_t scatter_enabled; + const char *error; + unsigned int i; + + for (i = 0; i < sas->rxq_count; i++) { + if ((sas->rxq_info[i].state & SFC_RXQ_INITIALIZED) == 0) + continue; + + scatter_enabled = (sas->rxq_info[i].type_flags & + EFX_RXQ_FLAG_SCATTER); + + if (!sfc_rx_check_scatter(pdu, sa->rxq_ctrl[i].buf_size, + encp->enc_rx_prefix_size, + scatter_enabled, &error)) { + sfc_err(sa, "MTU check for RxQ %u failed: %s", i, + error); + return EINVAL; + } + } + + return 0; +} + static int sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) { @@ -891,6 +919,10 @@ sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) sfc_adapter_lock(sa); + rc = sfc_check_scatter_on_all_rx_queues(sa, pdu); + if (rc != 0) + goto fail_check_scatter; + if (pdu != sa->port.pdu) { if (sa->state == SFC_ADAPTER_STARTED) { sfc_stop(sa); @@ -927,6 +959,8 @@ fail_start: sfc_err(sa, "cannot start with neither new (%u) nor old (%u) " "PDU max size - port is stopped", (unsigned int)pdu, (unsigned int)old_pdu); + +fail_check_scatter: sfc_adapter_unlock(sa); fail_inval: diff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c index 5d8c2765c8..f2221119c0 100644 --- a/drivers/net/sfc/sfc_rx.c +++ b/drivers/net/sfc/sfc_rx.c @@ -360,6 +360,18 @@ sfc_efx_rx_qdesc_status(struct sfc_dp_rxq *dp_rxq, uint16_t offset) return RTE_ETH_RX_DESC_UNAVAIL; } +boolean_t +sfc_rx_check_scatter(size_t pdu, size_t rx_buf_size, uint32_t rx_prefix_size, + boolean_t rx_scatter_enabled, const char **error) +{ + if ((rx_buf_size < pdu + rx_prefix_size) && !rx_scatter_enabled) { + *error = "Rx scatter is disabled and RxQ mbuf pool object size is too small"; + return B_FALSE; + } + + return B_TRUE; +} + /** Get Rx datapath ops by the datapath RxQ handle */ const struct sfc_dp_rx * sfc_dp_rx_by_dp_rxq(const struct sfc_dp_rxq *dp_rxq) @@ -975,6 +987,7 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index, struct sfc_dp_rx_qcreate_info info; struct sfc_dp_rx_hw_limits hw_limits; uint16_t rx_free_thresh; + const char *error; memset(&hw_limits, 0, sizeof(hw_limits)); hw_limits.rxq_max_entries = sa->rxq_max_entries; @@ -1005,10 +1018,11 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index, goto fail_bad_conf; } - if ((buf_size < sa->port.pdu + encp->enc_rx_prefix_size) && - (~offloads & DEV_RX_OFFLOAD_SCATTER)) { - sfc_err(sa, "Rx scatter is disabled and RxQ %u mbuf pool " - "object size is too small", sw_index); + if (!sfc_rx_check_scatter(sa->port.pdu, buf_size, + encp->enc_rx_prefix_size, + (offloads & DEV_RX_OFFLOAD_SCATTER), + &error)) { + sfc_err(sa, "RxQ %u MTU check failed: %s", sw_index, error); sfc_err(sa, "RxQ %u calculated Rx buffer size is %u vs " "PDU size %u plus Rx prefix %u bytes", sw_index, buf_size, (unsigned int)sa->port.pdu, diff --git a/drivers/net/sfc/sfc_rx.h b/drivers/net/sfc/sfc_rx.h index ee1402022e..aca0925b5a 100644 --- a/drivers/net/sfc/sfc_rx.h +++ b/drivers/net/sfc/sfc_rx.h @@ -142,6 +142,10 @@ void sfc_rx_hash_fini(struct sfc_adapter *sa); int sfc_rx_hf_rte_to_efx(struct sfc_adapter *sa, uint64_t rte, efx_rx_hash_type_t *efx); uint64_t sfc_rx_hf_efx_to_rte(struct sfc_rss *rss, efx_rx_hash_type_t efx); +boolean_t sfc_rx_check_scatter(size_t pdu, size_t rx_buf_size, + uint32_t rx_prefix_size, + boolean_t rx_scatter_enabled, + const char **error); #ifdef __cplusplus }