net/dpaa2: add support for flow control

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
This commit is contained in:
Hemant Agrawal 2017-05-26 12:21:21 +05:30 committed by Ferruh Yigit
parent a1f3a12cd5
commit 977d0006ad
5 changed files with 193 additions and 0 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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 { \