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:
parent
7b9891769f
commit
cdbb29cf4b
@ -5,6 +5,7 @@
|
|||||||
;
|
;
|
||||||
[Features]
|
[Features]
|
||||||
Link status = Y
|
Link status = Y
|
||||||
|
Flow control = Y
|
||||||
L3 checksum offload = P
|
L3 checksum offload = P
|
||||||
L4 checksum offload = P
|
L4 checksum offload = P
|
||||||
Basic stats = Y
|
Basic stats = Y
|
||||||
|
@ -53,6 +53,8 @@ SFC EFX PMD has support for:
|
|||||||
- Extended statistics (see Solarflare Server Adapter User's Guide for
|
- Extended statistics (see Solarflare Server Adapter User's Guide for
|
||||||
the statistics description)
|
the statistics description)
|
||||||
|
|
||||||
|
- Basic flow control
|
||||||
|
|
||||||
|
|
||||||
Non-supported Features
|
Non-supported Features
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -452,6 +452,102 @@ sfc_xstats_get_names(struct rte_eth_dev *dev,
|
|||||||
return nstats;
|
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 = {
|
static const struct eth_dev_ops sfc_eth_dev_ops = {
|
||||||
.dev_configure = sfc_dev_configure,
|
.dev_configure = sfc_dev_configure,
|
||||||
.dev_start = sfc_dev_start,
|
.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,
|
.rx_queue_release = sfc_rx_queue_release,
|
||||||
.tx_queue_setup = sfc_tx_queue_setup,
|
.tx_queue_setup = sfc_tx_queue_setup,
|
||||||
.tx_queue_release = sfc_tx_queue_release,
|
.tx_queue_release = sfc_tx_queue_release,
|
||||||
|
.flow_ctrl_get = sfc_flow_ctrl_get,
|
||||||
|
.flow_ctrl_set = sfc_flow_ctrl_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -79,6 +79,13 @@ sfc_port_start(struct sfc_adapter *sa)
|
|||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto fail_port_init;
|
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);
|
sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
|
||||||
rc = efx_mac_pdu_set(sa->nic, port->pdu);
|
rc = efx_mac_pdu_set(sa->nic, port->pdu);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
@ -124,6 +131,7 @@ fail_mac_stats_periodic:
|
|||||||
fail_mac_filter_set:
|
fail_mac_filter_set:
|
||||||
fail_mac_addr_set:
|
fail_mac_addr_set:
|
||||||
fail_mac_pdu_set:
|
fail_mac_pdu_set:
|
||||||
|
fail_mac_fcntl_set:
|
||||||
efx_port_fini(sa->nic);
|
efx_port_fini(sa->nic);
|
||||||
|
|
||||||
fail_port_init:
|
fail_port_init:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user