+static int
+axgbe_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
+{
+ struct axgbe_port *pdata = dev->data->dev_private;
+ struct xgbe_fc_info fc = pdata->fc;
+ unsigned int reg, reg_val = 0;
+
+ reg = MAC_Q0TFCR;
+ reg_val = AXGMAC_IOREAD(pdata, reg);
+ fc.low_water[0] = AXGMAC_MTL_IOREAD_BITS(pdata, 0, MTL_Q_RQFCR, RFA);
+ fc.high_water[0] = AXGMAC_MTL_IOREAD_BITS(pdata, 0, MTL_Q_RQFCR, RFD);
+ fc.pause_time[0] = AXGMAC_GET_BITS(reg_val, MAC_Q0TFCR, PT);
+ fc.autoneg = pdata->pause_autoneg;
+
+ if (pdata->rx_pause && pdata->tx_pause)
+ fc.mode = RTE_FC_FULL;
+ else if (pdata->rx_pause)
+ fc.mode = RTE_FC_RX_PAUSE;
+ else if (pdata->tx_pause)
+ fc.mode = RTE_FC_TX_PAUSE;
+ else
+ fc.mode = RTE_FC_NONE;
+
+ fc_conf->high_water = (1024 + (fc.low_water[0] << 9)) / 1024;
+ fc_conf->low_water = (1024 + (fc.high_water[0] << 9)) / 1024;
+ fc_conf->pause_time = fc.pause_time[0];
+ fc_conf->send_xon = fc.send_xon;
+ fc_conf->mode = fc.mode;
+
+ return 0;
+}
+
+static int
+axgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
+{
+ struct axgbe_port *pdata = dev->data->dev_private;
+ struct xgbe_fc_info fc = pdata->fc;
+ unsigned int reg, reg_val = 0;
+ reg = MAC_Q0TFCR;
+
+ pdata->pause_autoneg = fc_conf->autoneg;
+ pdata->phy.pause_autoneg = pdata->pause_autoneg;
+ fc.send_xon = fc_conf->send_xon;
+ AXGMAC_MTL_IOWRITE_BITS(pdata, 0, MTL_Q_RQFCR, RFA,
+ AXGMAC_FLOW_CONTROL_VALUE(1024 * fc_conf->high_water));
+ AXGMAC_MTL_IOWRITE_BITS(pdata, 0, MTL_Q_RQFCR, RFD,
+ AXGMAC_FLOW_CONTROL_VALUE(1024 * fc_conf->low_water));
+ AXGMAC_SET_BITS(reg_val, MAC_Q0TFCR, PT, fc_conf->pause_time);
+ AXGMAC_IOWRITE(pdata, reg, reg_val);
+ fc.mode = fc_conf->mode;
+
+ if (fc.mode == RTE_FC_FULL) {
+ pdata->tx_pause = 1;
+ pdata->rx_pause = 1;
+ } else if (fc.mode == RTE_FC_RX_PAUSE) {
+ pdata->tx_pause = 0;
+ pdata->rx_pause = 1;
+ } else if (fc.mode == RTE_FC_TX_PAUSE) {
+ pdata->tx_pause = 1;
+ pdata->rx_pause = 0;
+ } else {
+ pdata->tx_pause = 0;
+ pdata->rx_pause = 0;
+ }
+
+ if (pdata->tx_pause != (unsigned int)pdata->phy.tx_pause)
+ pdata->hw_if.config_tx_flow_control(pdata);
+
+ if (pdata->rx_pause != (unsigned int)pdata->phy.rx_pause)
+ pdata->hw_if.config_rx_flow_control(pdata);
+
+ pdata->hw_if.config_flow_control(pdata);
+ pdata->phy.tx_pause = pdata->tx_pause;
+ pdata->phy.rx_pause = pdata->rx_pause;
+
+ return 0;
+}
+
+static int
+axgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev,
+ struct rte_eth_pfc_conf *pfc_conf)
+{
+ struct axgbe_port *pdata = dev->data->dev_private;
+ struct xgbe_fc_info fc = pdata->fc;
+ uint8_t tc_num;
+
+ tc_num = pdata->pfc_map[pfc_conf->priority];
+
+ if (pfc_conf->priority >= pdata->hw_feat.tc_cnt) {
+ PMD_INIT_LOG(ERR, "Max supported traffic class: %d\n",
+ pdata->hw_feat.tc_cnt);
+ return -EINVAL;
+ }
+
+ pdata->pause_autoneg = pfc_conf->fc.autoneg;
+ pdata->phy.pause_autoneg = pdata->pause_autoneg;
+ fc.send_xon = pfc_conf->fc.send_xon;
+ AXGMAC_MTL_IOWRITE_BITS(pdata, tc_num, MTL_Q_RQFCR, RFA,
+ AXGMAC_FLOW_CONTROL_VALUE(1024 * pfc_conf->fc.high_water));
+ AXGMAC_MTL_IOWRITE_BITS(pdata, tc_num, MTL_Q_RQFCR, RFD,
+ AXGMAC_FLOW_CONTROL_VALUE(1024 * pfc_conf->fc.low_water));
+
+ switch (tc_num) {
+ case 0:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM0R,
+ PSTC0, pfc_conf->fc.pause_time);
+ break;
+ case 1:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM0R,
+ PSTC1, pfc_conf->fc.pause_time);
+ break;
+ case 2:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM0R,
+ PSTC2, pfc_conf->fc.pause_time);
+ break;
+ case 3:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM0R,
+ PSTC3, pfc_conf->fc.pause_time);
+ break;
+ case 4:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM1R,
+ PSTC4, pfc_conf->fc.pause_time);
+ break;
+ case 5:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM1R,
+ PSTC5, pfc_conf->fc.pause_time);
+ break;
+ case 7:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM1R,
+ PSTC6, pfc_conf->fc.pause_time);
+ break;
+ case 6:
+ AXGMAC_IOWRITE_BITS(pdata, MTL_TCPM1R,
+ PSTC7, pfc_conf->fc.pause_time);
+ break;
+ }
+
+ fc.mode = pfc_conf->fc.mode;
+
+ if (fc.mode == RTE_FC_FULL) {
+ pdata->tx_pause = 1;
+ pdata->rx_pause = 1;
+ AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, 1);
+ } else if (fc.mode == RTE_FC_RX_PAUSE) {
+ pdata->tx_pause = 0;
+ pdata->rx_pause = 1;
+ AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, 1);
+ } else if (fc.mode == RTE_FC_TX_PAUSE) {
+ pdata->tx_pause = 1;
+ pdata->rx_pause = 0;
+ AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, 0);
+ } else {
+ pdata->tx_pause = 0;
+ pdata->rx_pause = 0;
+ AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, 0);
+ }
+
+ if (pdata->tx_pause != (unsigned int)pdata->phy.tx_pause)
+ pdata->hw_if.config_tx_flow_control(pdata);
+
+ if (pdata->rx_pause != (unsigned int)pdata->phy.rx_pause)
+ pdata->hw_if.config_rx_flow_control(pdata);
+ pdata->hw_if.config_flow_control(pdata);
+ pdata->phy.tx_pause = pdata->tx_pause;
+ pdata->phy.rx_pause = pdata->rx_pause;
+
+ return 0;
+}
+
+void
+axgbe_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
+ struct rte_eth_rxq_info *qinfo)
+{
+ struct axgbe_rx_queue *rxq;
+
+ rxq = dev->data->rx_queues[queue_id];
+ qinfo->mp = rxq->mb_pool;
+ qinfo->scattered_rx = dev->data->scattered_rx;
+ qinfo->nb_desc = rxq->nb_desc;
+ qinfo->conf.rx_free_thresh = rxq->free_thresh;
+}
+
+void
+axgbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
+ struct rte_eth_txq_info *qinfo)
+{
+ struct axgbe_tx_queue *txq;
+
+ txq = dev->data->tx_queues[queue_id];
+ qinfo->nb_desc = txq->nb_desc;
+ qinfo->conf.tx_free_thresh = txq->free_thresh;
+}
+