net/dpaa2: add support for flow control
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
This commit is contained in:
parent
a1f3a12cd5
commit
977d0006ad
@ -12,6 +12,7 @@ Allmulticast mode = Y
|
||||
Unicast MAC filter = Y
|
||||
RSS hash = Y
|
||||
VLAN filter = Y
|
||||
Flow control = Y
|
||||
VLAN offload = Y
|
||||
L3 checksum offload = Y
|
||||
L4 checksum offload = Y
|
||||
|
@ -1105,6 +1105,146 @@ dpaa2_dev_set_link_down(struct rte_eth_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dpaa2_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dpaa2_dev_priv *priv;
|
||||
struct fsl_mc_io *dpni;
|
||||
struct dpni_link_state state = {0};
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
priv = dev->data->dev_private;
|
||||
dpni = (struct fsl_mc_io *)priv->hw;
|
||||
|
||||
if (dpni == NULL || fc_conf == NULL) {
|
||||
RTE_LOG(ERR, PMD, "device not configured");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
|
||||
if (ret) {
|
||||
RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(fc_conf, 0, sizeof(struct rte_eth_fc_conf));
|
||||
if (state.options & DPNI_LINK_OPT_PAUSE) {
|
||||
/* DPNI_LINK_OPT_PAUSE set
|
||||
* if ASYM_PAUSE not set,
|
||||
* RX Side flow control (handle received Pause frame)
|
||||
* TX side flow control (send Pause frame)
|
||||
* if ASYM_PAUSE set,
|
||||
* RX Side flow control (handle received Pause frame)
|
||||
* No TX side flow control (send Pause frame disabled)
|
||||
*/
|
||||
if (!(state.options & DPNI_LINK_OPT_ASYM_PAUSE))
|
||||
fc_conf->mode = RTE_FC_FULL;
|
||||
else
|
||||
fc_conf->mode = RTE_FC_RX_PAUSE;
|
||||
} else {
|
||||
/* DPNI_LINK_OPT_PAUSE not set
|
||||
* if ASYM_PAUSE set,
|
||||
* TX side flow control (send Pause frame)
|
||||
* No RX side flow control (No action on pause frame rx)
|
||||
* if ASYM_PAUSE not set,
|
||||
* Flow control disabled
|
||||
*/
|
||||
if (state.options & DPNI_LINK_OPT_ASYM_PAUSE)
|
||||
fc_conf->mode = RTE_FC_TX_PAUSE;
|
||||
else
|
||||
fc_conf->mode = RTE_FC_NONE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dpaa2_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dpaa2_dev_priv *priv;
|
||||
struct fsl_mc_io *dpni;
|
||||
struct dpni_link_state state = {0};
|
||||
struct dpni_link_cfg cfg = {0};
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
priv = dev->data->dev_private;
|
||||
dpni = (struct fsl_mc_io *)priv->hw;
|
||||
|
||||
if (dpni == NULL) {
|
||||
RTE_LOG(ERR, PMD, "dpni is NULL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* It is necessary to obtain the current state before setting fc_conf
|
||||
* as MC would return error in case rate, autoneg or duplex values are
|
||||
* different.
|
||||
*/
|
||||
ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
|
||||
if (ret) {
|
||||
RTE_LOG(ERR, PMD, "Unable to get link state (err=%d)", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Disable link before setting configuration */
|
||||
dpaa2_dev_set_link_down(dev);
|
||||
|
||||
/* Based on fc_conf, update cfg */
|
||||
cfg.rate = state.rate;
|
||||
cfg.options = state.options;
|
||||
|
||||
/* update cfg with fc_conf */
|
||||
switch (fc_conf->mode) {
|
||||
case RTE_FC_FULL:
|
||||
/* Full flow control;
|
||||
* OPT_PAUSE set, ASYM_PAUSE not set
|
||||
*/
|
||||
cfg.options |= DPNI_LINK_OPT_PAUSE;
|
||||
cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
|
||||
case RTE_FC_TX_PAUSE:
|
||||
/* Enable RX flow control
|
||||
* OPT_PAUSE not set;
|
||||
* ASYM_PAUSE set;
|
||||
*/
|
||||
cfg.options |= DPNI_LINK_OPT_ASYM_PAUSE;
|
||||
cfg.options &= ~DPNI_LINK_OPT_PAUSE;
|
||||
break;
|
||||
case RTE_FC_RX_PAUSE:
|
||||
/* Enable TX Flow control
|
||||
* OPT_PAUSE set
|
||||
* ASYM_PAUSE set
|
||||
*/
|
||||
cfg.options |= DPNI_LINK_OPT_PAUSE;
|
||||
cfg.options |= DPNI_LINK_OPT_ASYM_PAUSE;
|
||||
break;
|
||||
case RTE_FC_NONE:
|
||||
/* Disable Flow control
|
||||
* OPT_PAUSE not set
|
||||
* ASYM_PAUSE not set
|
||||
*/
|
||||
cfg.options &= ~DPNI_LINK_OPT_PAUSE;
|
||||
cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
|
||||
break;
|
||||
default:
|
||||
RTE_LOG(ERR, PMD, "Incorrect Flow control flag (%d)",
|
||||
fc_conf->mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = dpni_set_link_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg);
|
||||
if (ret)
|
||||
RTE_LOG(ERR, PMD, "Unable to set Link configuration (err=%d)",
|
||||
ret);
|
||||
|
||||
/* Enable link */
|
||||
dpaa2_dev_set_link_up(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct eth_dev_ops dpaa2_ethdev_ops = {
|
||||
.dev_configure = dpaa2_eth_dev_configure,
|
||||
.dev_start = dpaa2_dev_start,
|
||||
@ -1128,6 +1268,8 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
|
||||
.rx_queue_release = dpaa2_dev_rx_queue_release,
|
||||
.tx_queue_setup = dpaa2_dev_tx_queue_setup,
|
||||
.tx_queue_release = dpaa2_dev_tx_queue_release,
|
||||
.flow_ctrl_get = dpaa2_flow_ctrl_get,
|
||||
.flow_ctrl_set = dpaa2_flow_ctrl_set,
|
||||
.mac_addr_add = dpaa2_dev_add_mac_addr,
|
||||
.mac_addr_remove = dpaa2_dev_remove_mac_addr,
|
||||
.mac_addr_set = dpaa2_dev_set_mac_addr,
|
||||
|
@ -444,6 +444,24 @@ int dpni_get_qdid(struct fsl_mc_io *mc_io,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
|
||||
uint32_t cmd_flags,
|
||||
uint16_t token,
|
||||
const struct dpni_link_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
|
||||
cmd_flags,
|
||||
token);
|
||||
DPNI_CMD_SET_LINK_CFG(cmd, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_link_state(struct fsl_mc_io *mc_io,
|
||||
uint32_t cmd_flags,
|
||||
uint16_t token,
|
||||
|
@ -739,6 +739,30 @@ union dpni_statistics {
|
||||
*/
|
||||
#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
|
||||
|
||||
/**
|
||||
* struct - Structure representing DPNI link configuration
|
||||
* @rate: Rate
|
||||
* @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values
|
||||
*/
|
||||
struct dpni_link_cfg {
|
||||
uint32_t rate;
|
||||
uint64_t options;
|
||||
};
|
||||
|
||||
/**
|
||||
* dpni_set_link_cfg() - set the link configuration.
|
||||
* @mc_io: Pointer to MC portal's I/O object
|
||||
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
|
||||
* @token: Token of DPNI object
|
||||
* @cfg: Link configuration
|
||||
*
|
||||
* Return: '0' on Success; Error code otherwise.
|
||||
*/
|
||||
int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
|
||||
uint32_t cmd_flags,
|
||||
uint16_t token,
|
||||
const struct dpni_link_cfg *cfg);
|
||||
|
||||
/**
|
||||
* struct dpni_link_state - Structure representing DPNI link state
|
||||
* @rate: Rate
|
||||
|
@ -64,6 +64,7 @@
|
||||
#define DPNI_CMDID_GET_LINK_STATE ((0x215 << 4) | (0x1))
|
||||
#define DPNI_CMDID_SET_MAX_FRAME_LENGTH ((0x216 << 4) | (0x1))
|
||||
#define DPNI_CMDID_GET_MAX_FRAME_LENGTH ((0x217 << 4) | (0x1))
|
||||
#define DPNI_CMDID_SET_LINK_CFG ((0x21a << 4) | (0x1))
|
||||
|
||||
#define DPNI_CMDID_SET_MCAST_PROMISC ((0x220 << 4) | (0x1))
|
||||
#define DPNI_CMDID_GET_MCAST_PROMISC ((0x221 << 4) | (0x1))
|
||||
@ -237,6 +238,13 @@ do { \
|
||||
MC_RSP_OP(cmd, 6, 0, 64, uint64_t, (stat)->raw.counter[6]); \
|
||||
} while (0)
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \
|
||||
do { \
|
||||
MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\
|
||||
MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\
|
||||
} while (0)
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPNI_RSP_GET_LINK_STATE(cmd, state) \
|
||||
do { \
|
||||
|
Loading…
Reference in New Issue
Block a user