net/octeontx: support flow control
Patch adds ethdev flow control set/get callback ops, pmd enables modifying flow control attributes like rx_pause, tx_pause, high & low water mark. Signed-off-by: Vamsi Attunuru <vattunuru@marvell.com> Acked-by: Harman Kalra <hkalra@marvell.com>
This commit is contained in:
parent
8b42b07eef
commit
241a650061
@ -18,6 +18,7 @@ VLAN filter = Y
|
||||
VLAN offload = P
|
||||
CRC offload = Y
|
||||
Packet type parsing = Y
|
||||
Flow control = Y
|
||||
Basic stats = Y
|
||||
Linux VFIO = Y
|
||||
ARMv8 = Y
|
||||
|
@ -326,3 +326,53 @@ octeontx_bgx_port_mac_entries_get(int port)
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
int octeontx_bgx_port_get_fifo_cfg(int port,
|
||||
octeontx_mbox_bgx_port_fifo_cfg_t *cfg)
|
||||
{
|
||||
int len = sizeof(octeontx_mbox_bgx_port_fifo_cfg_t);
|
||||
octeontx_mbox_bgx_port_fifo_cfg_t conf;
|
||||
struct octeontx_mbox_hdr hdr;
|
||||
|
||||
hdr.coproc = OCTEONTX_BGX_COPROC;
|
||||
hdr.msg = MBOX_BGX_PORT_GET_FIFO_CFG;
|
||||
hdr.vfid = port;
|
||||
|
||||
if (octeontx_mbox_send(&hdr, NULL, 0, &conf, len) < 0)
|
||||
return -EACCES;
|
||||
|
||||
cfg->rx_fifosz = conf.rx_fifosz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int octeontx_bgx_port_flow_ctrl_cfg(int port,
|
||||
octeontx_mbox_bgx_port_fc_cfg_t *cfg)
|
||||
{
|
||||
int len = sizeof(octeontx_mbox_bgx_port_fc_cfg_t);
|
||||
octeontx_mbox_bgx_port_fc_cfg_t conf;
|
||||
struct octeontx_mbox_hdr hdr;
|
||||
|
||||
hdr.coproc = OCTEONTX_BGX_COPROC;
|
||||
hdr.msg = MBOX_BGX_PORT_FLOW_CTRL_CFG;
|
||||
hdr.vfid = port;
|
||||
|
||||
if (cfg->fc_cfg == BGX_PORT_FC_CFG_SET)
|
||||
memcpy(&conf, cfg, len);
|
||||
else
|
||||
memset(&conf, 0, len);
|
||||
|
||||
if (octeontx_mbox_send(&hdr, &conf, len, &conf, len) < 0)
|
||||
return -EACCES;
|
||||
|
||||
if (cfg->fc_cfg == BGX_PORT_FC_CFG_SET)
|
||||
goto done;
|
||||
|
||||
cfg->rx_pause = conf.rx_pause;
|
||||
cfg->tx_pause = conf.tx_pause;
|
||||
cfg->low_water = conf.low_water;
|
||||
cfg->high_water = conf.high_water;
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <octeontx_mbox.h>
|
||||
|
||||
#define OCTEONTX_BGX_RSVD_RX_FIFOBYTES 0x40
|
||||
|
||||
#define OCTEONTX_BGX_COPROC 6
|
||||
|
||||
/* BGX messages */
|
||||
@ -32,6 +34,8 @@
|
||||
#define MBOX_BGX_PORT_ADD_MACADDR 15
|
||||
#define MBOX_BGX_PORT_DEL_MACADDR 16
|
||||
#define MBOX_BGX_PORT_GET_MACADDR_ENTRIES 17
|
||||
#define MBOX_BGX_PORT_GET_FIFO_CFG 18
|
||||
#define MBOX_BGX_PORT_FLOW_CTRL_CFG 19
|
||||
#define MBOX_BGX_PORT_SET_LINK_STATE 20
|
||||
|
||||
/* BGX port configuration parameters: */
|
||||
@ -119,6 +123,26 @@ struct octeontx_mbox_bgx_port_mac_filter {
|
||||
int index;
|
||||
};
|
||||
|
||||
/* BGX port fifo config: */
|
||||
typedef struct octeontx_mbox_bgx_port_fifo_cfg {
|
||||
uint32_t rx_fifosz; /* in Bytes */
|
||||
} octeontx_mbox_bgx_port_fifo_cfg_t;
|
||||
|
||||
typedef enum {
|
||||
BGX_PORT_FC_CFG_GET = 0,
|
||||
BGX_PORT_FC_CFG_SET = 1
|
||||
} bgx_port_fc_t;
|
||||
|
||||
/* BGX port flow control config: */
|
||||
typedef struct octeontx_mbox_bgx_port_fc_cfg {
|
||||
/* BP on/off threshold levels in Bytes, must be a multiple of 16 */
|
||||
uint16_t high_water;
|
||||
uint16_t low_water;
|
||||
uint8_t rx_pause; /* rx_pause = 1/0 to enable/disable fc on Tx */
|
||||
uint8_t tx_pause; /* tx_pause = 1/0 to enable/disable fc on Rx */
|
||||
bgx_port_fc_t fc_cfg;
|
||||
} octeontx_mbox_bgx_port_fc_cfg_t;
|
||||
|
||||
int octeontx_bgx_port_open(int port, octeontx_mbox_bgx_port_conf_t *conf);
|
||||
int octeontx_bgx_port_close(int port);
|
||||
int octeontx_bgx_port_start(int port);
|
||||
@ -135,6 +159,10 @@ int octeontx_bgx_port_mac_del(int port, uint32_t index);
|
||||
int octeontx_bgx_port_mac_entries_get(int port);
|
||||
int octeontx_bgx_port_mtu_set(int port, int mtu);
|
||||
int octeontx_bgx_port_set_link_state(int port, bool en);
|
||||
int octeontx_bgx_port_get_fifo_cfg(int port,
|
||||
octeontx_mbox_bgx_port_fifo_cfg_t *cfg);
|
||||
int octeontx_bgx_port_flow_ctrl_cfg(int port,
|
||||
octeontx_mbox_bgx_port_fc_cfg_t *cfg);
|
||||
|
||||
#endif /* __OCTEONTX_BGX_H__ */
|
||||
|
||||
|
@ -122,6 +122,7 @@ static int
|
||||
octeontx_port_open(struct octeontx_nic *nic)
|
||||
{
|
||||
octeontx_mbox_bgx_port_conf_t bgx_port_conf;
|
||||
octeontx_mbox_bgx_port_fifo_cfg_t fifo_cfg;
|
||||
int res;
|
||||
|
||||
res = 0;
|
||||
@ -147,6 +148,16 @@ octeontx_port_open(struct octeontx_nic *nic)
|
||||
nic->mcast_mode = bgx_port_conf.mcast_mode;
|
||||
nic->speed = bgx_port_conf.mode;
|
||||
|
||||
memset(&fifo_cfg, 0x0, sizeof(fifo_cfg));
|
||||
|
||||
res = octeontx_bgx_port_get_fifo_cfg(nic->port_id, &fifo_cfg);
|
||||
if (res < 0) {
|
||||
octeontx_log_err("failed to get port %d fifo cfg", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
nic->fc.rx_fifosz = fifo_cfg.rx_fifosz;
|
||||
|
||||
memcpy(&nic->mac_addr[0], &bgx_port_conf.macaddr[0],
|
||||
RTE_ETHER_ADDR_LEN);
|
||||
|
||||
@ -482,6 +493,8 @@ octeontx_dev_close(struct rte_eth_dev *dev)
|
||||
|
||||
rte_event_dev_close(nic->evdev);
|
||||
|
||||
octeontx_dev_flow_ctrl_fini(dev);
|
||||
|
||||
octeontx_dev_vlan_offload_fini(dev);
|
||||
|
||||
ret = octeontx_pko_channel_close(nic->base_ochan);
|
||||
@ -1208,6 +1221,7 @@ octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx,
|
||||
octeontx_recheck_rx_offloads(rxq);
|
||||
dev->data->rx_queues[qidx] = rxq;
|
||||
dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1276,6 +1290,8 @@ static const struct eth_dev_ops octeontx_dev_ops = {
|
||||
.dev_supported_ptypes_get = octeontx_dev_supported_ptypes_get,
|
||||
.mtu_set = octeontx_dev_mtu_set,
|
||||
.pool_ops_supported = octeontx_pool_ops,
|
||||
.flow_ctrl_get = octeontx_dev_flow_ctrl_get,
|
||||
.flow_ctrl_set = octeontx_dev_flow_ctrl_set,
|
||||
};
|
||||
|
||||
/* Create Ethdev interface per BGX LMAC ports */
|
||||
@ -1407,6 +1423,10 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
|
||||
/* Update same mac address to BGX CAM table at index 0 */
|
||||
octeontx_bgx_port_mac_add(nic->port_id, nic->mac_addr, 0);
|
||||
|
||||
res = octeontx_dev_flow_ctrl_init(eth_dev);
|
||||
if (res < 0)
|
||||
goto err;
|
||||
|
||||
PMD_INIT_LOG(DEBUG, "ethdev info: ");
|
||||
PMD_INIT_LOG(DEBUG, "port %d, port_ena %d ochan %d num_ochan %d tx_q %d",
|
||||
nic->port_id, nic->port_ena,
|
||||
|
@ -83,6 +83,16 @@ struct octeontx_vlan_info {
|
||||
uint8_t filter_on;
|
||||
};
|
||||
|
||||
struct octeontx_fc_info {
|
||||
enum rte_eth_fc_mode mode; /**< Link flow control mode */
|
||||
enum rte_eth_fc_mode def_mode;
|
||||
uint16_t high_water;
|
||||
uint16_t low_water;
|
||||
uint16_t def_highmark;
|
||||
uint16_t def_lowmark;
|
||||
uint32_t rx_fifosz;
|
||||
};
|
||||
|
||||
/* Octeontx ethdev nic */
|
||||
struct octeontx_nic {
|
||||
struct rte_eth_dev *dev;
|
||||
@ -122,6 +132,7 @@ struct octeontx_nic {
|
||||
uint16_t tx_offload_flags;
|
||||
struct octeontx_vlan_info vlan_info;
|
||||
int print_flag;
|
||||
struct octeontx_fc_info fc;
|
||||
} __rte_cache_aligned;
|
||||
|
||||
struct octeontx_txq {
|
||||
@ -154,4 +165,12 @@ int octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev,
|
||||
int octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev);
|
||||
int octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev);
|
||||
|
||||
/* Flow control */
|
||||
int octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev);
|
||||
int octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev);
|
||||
int octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev,
|
||||
struct rte_eth_fc_conf *fc_conf);
|
||||
int octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev,
|
||||
struct rte_eth_fc_conf *fc_conf);
|
||||
|
||||
#endif /* __OCTEONTX_ETHDEV_H__ */
|
||||
|
@ -213,3 +213,131 @@ octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev)
|
||||
|
||||
return octeontx_bgx_port_set_link_state(nic->port_id, false);
|
||||
}
|
||||
|
||||
int
|
||||
octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev,
|
||||
struct rte_eth_fc_conf *fc_conf)
|
||||
{
|
||||
struct octeontx_nic *nic = octeontx_pmd_priv(dev);
|
||||
octeontx_mbox_bgx_port_fc_cfg_t conf;
|
||||
int rc;
|
||||
|
||||
memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t));
|
||||
|
||||
rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (conf.rx_pause && conf.tx_pause)
|
||||
fc_conf->mode = RTE_FC_FULL;
|
||||
else if (conf.rx_pause)
|
||||
fc_conf->mode = RTE_FC_RX_PAUSE;
|
||||
else if (conf.tx_pause)
|
||||
fc_conf->mode = RTE_FC_TX_PAUSE;
|
||||
else
|
||||
fc_conf->mode = RTE_FC_NONE;
|
||||
|
||||
/* low_water & high_water values are in Bytes */
|
||||
fc_conf->low_water = conf.low_water;
|
||||
fc_conf->high_water = conf.high_water;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev,
|
||||
struct rte_eth_fc_conf *fc_conf)
|
||||
{
|
||||
struct octeontx_nic *nic = octeontx_pmd_priv(dev);
|
||||
struct octeontx_fc_info *fc = &nic->fc;
|
||||
octeontx_mbox_bgx_port_fc_cfg_t conf;
|
||||
uint8_t tx_pause, rx_pause;
|
||||
uint16_t max_high_water;
|
||||
int rc;
|
||||
|
||||
if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd ||
|
||||
fc_conf->autoneg) {
|
||||
octeontx_log_err("Below flowctrl parameters are not supported "
|
||||
"pause_time, mac_ctrl_frame_fwd and autoneg");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fc_conf->high_water == fc->high_water &&
|
||||
fc_conf->low_water == fc->low_water &&
|
||||
fc_conf->mode == fc->mode)
|
||||
return 0;
|
||||
|
||||
max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES;
|
||||
|
||||
if (fc_conf->high_water > max_high_water ||
|
||||
fc_conf->high_water < fc_conf->low_water) {
|
||||
octeontx_log_err("Invalid high/low water values "
|
||||
"High_water(in Bytes) must <= 0x%x ",
|
||||
max_high_water);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) {
|
||||
octeontx_log_err("High/low water value must be multiple of 16");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rx_pause = (fc_conf->mode == RTE_FC_FULL) ||
|
||||
(fc_conf->mode == RTE_FC_RX_PAUSE);
|
||||
tx_pause = (fc_conf->mode == RTE_FC_FULL) ||
|
||||
(fc_conf->mode == RTE_FC_TX_PAUSE);
|
||||
|
||||
conf.high_water = fc_conf->high_water;
|
||||
conf.low_water = fc_conf->low_water;
|
||||
conf.fc_cfg = BGX_PORT_FC_CFG_SET;
|
||||
conf.rx_pause = rx_pause;
|
||||
conf.tx_pause = tx_pause;
|
||||
|
||||
rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
fc->high_water = fc_conf->high_water;
|
||||
fc->low_water = fc_conf->low_water;
|
||||
fc->mode = fc_conf->mode;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct octeontx_nic *nic = octeontx_pmd_priv(dev);
|
||||
struct octeontx_fc_info *fc = &nic->fc;
|
||||
struct rte_eth_fc_conf fc_conf;
|
||||
int rc;
|
||||
|
||||
rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf);
|
||||
if (rc) {
|
||||
octeontx_log_err("Failed to get flow control info");
|
||||
return rc;
|
||||
}
|
||||
|
||||
fc->def_highmark = fc_conf.high_water;
|
||||
fc->def_lowmark = fc_conf.low_water;
|
||||
fc->def_mode = fc_conf.mode;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct octeontx_nic *nic = octeontx_pmd_priv(dev);
|
||||
struct octeontx_fc_info *fc = &nic->fc;
|
||||
struct rte_eth_fc_conf fc_conf;
|
||||
|
||||
memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
|
||||
|
||||
/* Restore flow control parameters with default values */
|
||||
fc_conf.high_water = fc->def_highmark;
|
||||
fc_conf.low_water = fc->def_lowmark;
|
||||
fc_conf.mode = fc->def_mode;
|
||||
|
||||
return octeontx_dev_flow_ctrl_set(dev, &fc_conf);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user