On Mon, Mar 16, 2020 at 03:03:43PM +0530, Harman Kalra wrote: > From: Vamsi Attunuru <vattun...@marvell.com> > > 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 <vattun...@marvell.com>
Acked-by: Harman Kalra <hka...@marvell.com> > --- > doc/guides/nics/features/octeontx.ini | 1 + > drivers/net/octeontx/base/octeontx_bgx.c | 50 ++++++++ > drivers/net/octeontx/base/octeontx_bgx.h | 28 +++++ > drivers/net/octeontx/octeontx_ethdev.c | 20 ++++ > drivers/net/octeontx/octeontx_ethdev.h | 19 +++ > drivers/net/octeontx/octeontx_ethdev_ops.c | 128 +++++++++++++++++++++ > 6 files changed, 246 insertions(+) > > diff --git a/doc/guides/nics/features/octeontx.ini > b/doc/guides/nics/features/octeontx.ini > index 377bb4d30..6049c1c43 100644 > --- a/doc/guides/nics/features/octeontx.ini > +++ b/doc/guides/nics/features/octeontx.ini > @@ -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 > diff --git a/drivers/net/octeontx/base/octeontx_bgx.c > b/drivers/net/octeontx/base/octeontx_bgx.c > index d8611cb77..ac856ff86 100644 > --- a/drivers/net/octeontx/base/octeontx_bgx.c > +++ b/drivers/net/octeontx/base/octeontx_bgx.c > @@ -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; > +} > diff --git a/drivers/net/octeontx/base/octeontx_bgx.h > b/drivers/net/octeontx/base/octeontx_bgx.h > index 6b7476510..d126a0b7f 100644 > --- a/drivers/net/octeontx/base/octeontx_bgx.h > +++ b/drivers/net/octeontx/base/octeontx_bgx.h > @@ -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__ */ > > diff --git a/drivers/net/octeontx/octeontx_ethdev.c > b/drivers/net/octeontx/octeontx_ethdev.c > index 08c621b4b..191869683 100644 > --- a/drivers/net/octeontx/octeontx_ethdev.c > +++ b/drivers/net/octeontx/octeontx_ethdev.c > @@ -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, > diff --git a/drivers/net/octeontx/octeontx_ethdev.h > b/drivers/net/octeontx/octeontx_ethdev.h > index 186a044f7..dc53b53be 100644 > --- a/drivers/net/octeontx/octeontx_ethdev.h > +++ b/drivers/net/octeontx/octeontx_ethdev.h > @@ -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__ */ > diff --git a/drivers/net/octeontx/octeontx_ethdev_ops.c > b/drivers/net/octeontx/octeontx_ethdev_ops.c > index b5f0bfe8a..ff627a68e 100644 > --- a/drivers/net/octeontx/octeontx_ethdev_ops.c > +++ b/drivers/net/octeontx/octeontx_ethdev_ops.c > @@ -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); > +} > -- > 2.18.0 >