net/sfc: support flow control settings

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andrew Lee <alee@solarflare.com>
Reviewed-by: Robert Stonehouse <rstonehouse@solarflare.com>
This commit is contained in:
Andrew Rybchenko 2016-12-15 12:50:56 +00:00 committed by Ferruh Yigit
parent 7b9891769f
commit cdbb29cf4b
4 changed files with 109 additions and 0 deletions

View File

@ -5,6 +5,7 @@
;
[Features]
Link status = Y
Flow control = Y
L3 checksum offload = P
L4 checksum offload = P
Basic stats = Y

View File

@ -53,6 +53,8 @@ SFC EFX PMD has support for:
- Extended statistics (see Solarflare Server Adapter User's Guide for
the statistics description)
- Basic flow control
Non-supported Features
----------------------

View File

@ -452,6 +452,102 @@ sfc_xstats_get_names(struct rte_eth_dev *dev,
return nstats;
}
static int
sfc_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
{
struct sfc_adapter *sa = dev->data->dev_private;
unsigned int wanted_fc, link_fc;
memset(fc_conf, 0, sizeof(*fc_conf));
sfc_adapter_lock(sa);
if (sa->state == SFC_ADAPTER_STARTED)
efx_mac_fcntl_get(sa->nic, &wanted_fc, &link_fc);
else
link_fc = sa->port.flow_ctrl;
switch (link_fc) {
case 0:
fc_conf->mode = RTE_FC_NONE;
break;
case EFX_FCNTL_RESPOND:
fc_conf->mode = RTE_FC_RX_PAUSE;
break;
case EFX_FCNTL_GENERATE:
fc_conf->mode = RTE_FC_TX_PAUSE;
break;
case (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE):
fc_conf->mode = RTE_FC_FULL;
break;
default:
sfc_err(sa, "%s: unexpected flow control value %#x",
__func__, link_fc);
}
fc_conf->autoneg = sa->port.flow_ctrl_autoneg;
sfc_adapter_unlock(sa);
return 0;
}
static int
sfc_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
{
struct sfc_adapter *sa = dev->data->dev_private;
struct sfc_port *port = &sa->port;
unsigned int fcntl;
int rc;
if (fc_conf->high_water != 0 || fc_conf->low_water != 0 ||
fc_conf->pause_time != 0 || fc_conf->send_xon != 0 ||
fc_conf->mac_ctrl_frame_fwd != 0) {
sfc_err(sa, "unsupported flow control settings specified");
rc = EINVAL;
goto fail_inval;
}
switch (fc_conf->mode) {
case RTE_FC_NONE:
fcntl = 0;
break;
case RTE_FC_RX_PAUSE:
fcntl = EFX_FCNTL_RESPOND;
break;
case RTE_FC_TX_PAUSE:
fcntl = EFX_FCNTL_GENERATE;
break;
case RTE_FC_FULL:
fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
break;
default:
rc = EINVAL;
goto fail_inval;
}
sfc_adapter_lock(sa);
if (sa->state == SFC_ADAPTER_STARTED) {
rc = efx_mac_fcntl_set(sa->nic, fcntl, fc_conf->autoneg);
if (rc != 0)
goto fail_mac_fcntl_set;
}
port->flow_ctrl = fcntl;
port->flow_ctrl_autoneg = fc_conf->autoneg;
sfc_adapter_unlock(sa);
return 0;
fail_mac_fcntl_set:
sfc_adapter_unlock(sa);
fail_inval:
SFC_ASSERT(rc > 0);
return -rc;
}
static const struct eth_dev_ops sfc_eth_dev_ops = {
.dev_configure = sfc_dev_configure,
.dev_start = sfc_dev_start,
@ -466,6 +562,8 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
.rx_queue_release = sfc_rx_queue_release,
.tx_queue_setup = sfc_tx_queue_setup,
.tx_queue_release = sfc_tx_queue_release,
.flow_ctrl_get = sfc_flow_ctrl_get,
.flow_ctrl_set = sfc_flow_ctrl_set,
};
static int

View File

@ -79,6 +79,13 @@ sfc_port_start(struct sfc_adapter *sa)
if (rc != 0)
goto fail_port_init;
sfc_log_init(sa, "set flow control to %#x autoneg=%u",
port->flow_ctrl, port->flow_ctrl_autoneg);
rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl,
port->flow_ctrl_autoneg);
if (rc != 0)
goto fail_mac_fcntl_set;
sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
rc = efx_mac_pdu_set(sa->nic, port->pdu);
if (rc != 0)
@ -124,6 +131,7 @@ fail_mac_stats_periodic:
fail_mac_filter_set:
fail_mac_addr_set:
fail_mac_pdu_set:
fail_mac_fcntl_set:
efx_port_fini(sa->nic);
fail_port_init: