diff --git a/drivers/net/spnic/base/spnic_nic_cfg.c b/drivers/net/spnic/base/spnic_nic_cfg.c
index 8f4249980b..52ad2d1148 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.c
+++ b/drivers/net/spnic/base/spnic_nic_cfg.c
@@ -440,6 +440,59 @@ int spnic_flush_qps_res(void *hwdev)
 	return 0;
 }
 
+static int spnic_cfg_hw_pause(void *hwdev, u8 opcode,
+			       struct nic_pause_config *nic_pause)
+{
+	struct spnic_cmd_pause_config pause_info;
+	u16 out_size = sizeof(pause_info);
+	int err;
+
+	memset(&pause_info, 0, sizeof(pause_info));
+
+	pause_info.port_id = spnic_physical_port_id(hwdev);
+	pause_info.opcode = opcode;
+	if (opcode == SPNIC_CMD_OP_SET) {
+		pause_info.auto_neg = nic_pause->auto_neg;
+		pause_info.rx_pause = nic_pause->rx_pause;
+		pause_info.tx_pause = nic_pause->tx_pause;
+	}
+
+	err = spnic_l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_CFG_PAUSE_INFO,
+				     &pause_info, sizeof(pause_info),
+				     &pause_info, &out_size);
+	if (err || !out_size || pause_info.msg_head.status) {
+		PMD_DRV_LOG(ERR, "%s pause info failed, err: %d, status: 0x%x, out size: 0x%x\n",
+			    opcode == SPNIC_CMD_OP_SET ? "Set" : "Get",
+			    err, pause_info.msg_head.status, out_size);
+		return -EIO;
+	}
+
+	if (opcode == SPNIC_CMD_OP_GET) {
+		nic_pause->auto_neg = pause_info.auto_neg;
+		nic_pause->rx_pause = pause_info.rx_pause;
+		nic_pause->tx_pause = pause_info.tx_pause;
+	}
+
+	return 0;
+}
+
+int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause)
+{
+	if (!hwdev)
+		return -EINVAL;
+
+	return spnic_cfg_hw_pause(hwdev, SPNIC_CMD_OP_SET, &nic_pause);
+}
+
+int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
+{
+	if (!hwdev || !nic_pause)
+		return -EINVAL;
+
+
+	return spnic_cfg_hw_pause(hwdev, SPNIC_CMD_OP_GET, nic_pause);
+}
+
 static int spnic_set_function_table(void *hwdev, u32 cfg_bitmap,
 				     struct spnic_func_tbl_cfg *cfg)
 {
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.h b/drivers/net/spnic/base/spnic_nic_cfg.h
index 9b926119d8..2e00bdece5 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.h
+++ b/drivers/net/spnic/base/spnic_nic_cfg.h
@@ -560,6 +560,31 @@ int spnic_get_link_state(void *hwdev, u8 *link_state);
  */
 int spnic_flush_qps_res(void *hwdev);
 
+/**
+ * Set pause info
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[in] nic_pause
+ *   Pause info
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause);
+
+/**
+ * Get pause info
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[out] nic_pause
+ *   Pause info
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause);
 
 /**
  * Init nic hwdev
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index b9694b8da8..c9f6612c60 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -1525,6 +1525,81 @@ static int spnic_dev_promiscuous_disable(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int spnic_dev_flow_ctrl_get(struct rte_eth_dev *dev,
+				   struct rte_eth_fc_conf *fc_conf)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct nic_pause_config nic_pause;
+	int err;
+
+	err = spnic_mutex_lock(&nic_dev->pause_mutuex);
+	if (err)
+		return err;
+
+	memset(&nic_pause, 0, sizeof(nic_pause));
+	err = spnic_get_pause_info(nic_dev->hwdev, &nic_pause);
+	if (err) {
+		(void)spnic_mutex_unlock(&nic_dev->pause_mutuex);
+		return err;
+	}
+
+	if (nic_dev->pause_set || !nic_pause.auto_neg) {
+		nic_pause.rx_pause = nic_dev->nic_pause.rx_pause;
+		nic_pause.tx_pause = nic_dev->nic_pause.tx_pause;
+	}
+
+	fc_conf->autoneg = nic_pause.auto_neg;
+
+	if (nic_pause.tx_pause && nic_pause.rx_pause)
+		fc_conf->mode = RTE_FC_FULL;
+	else if (nic_pause.tx_pause)
+		fc_conf->mode = RTE_FC_TX_PAUSE;
+	else if (nic_pause.rx_pause)
+		fc_conf->mode = RTE_FC_RX_PAUSE;
+	else
+		fc_conf->mode = RTE_FC_NONE;
+
+	(void)spnic_mutex_unlock(&nic_dev->pause_mutuex);
+	return 0;
+}
+
+static int spnic_dev_flow_ctrl_set(struct rte_eth_dev *dev,
+				   struct rte_eth_fc_conf *fc_conf)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct nic_pause_config nic_pause;
+	int err;
+
+	err = spnic_mutex_lock(&nic_dev->pause_mutuex);
+	if (err)
+		return err;
+
+	memset(&nic_pause, 0, sizeof(nic_pause));
+	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
+	    (fc_conf->mode & RTE_FC_TX_PAUSE))
+		nic_pause.tx_pause = true;
+
+	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
+	    (fc_conf->mode & RTE_FC_RX_PAUSE))
+		nic_pause.rx_pause = true;
+
+	err = spnic_set_pause_info(nic_dev->hwdev, nic_pause);
+	if (err) {
+		(void)spnic_mutex_unlock(&nic_dev->pause_mutuex);
+		return err;
+	}
+
+	nic_dev->pause_set = true;
+	nic_dev->nic_pause.rx_pause = nic_pause.rx_pause;
+	nic_dev->nic_pause.tx_pause = nic_pause.tx_pause;
+
+	PMD_DRV_LOG(INFO, "Just support set tx or rx pause info, tx: %s, rx: %s\n",
+		    nic_pause.tx_pause ? "on" : "off",
+		    nic_pause.rx_pause ? "on" : "off");
+
+	(void)spnic_mutex_unlock(&nic_dev->pause_mutuex);
+	return 0;
+}
 
 /**
  * Update the RSS hash key and RSS hash type.
@@ -1965,6 +2040,8 @@ static const struct eth_dev_ops spnic_pmd_ops = {
 	.allmulticast_disable          = spnic_dev_allmulticast_disable,
 	.promiscuous_enable            = spnic_dev_promiscuous_enable,
 	.promiscuous_disable           = spnic_dev_promiscuous_disable,
+	.flow_ctrl_get                 = spnic_dev_flow_ctrl_get,
+	.flow_ctrl_set                 = spnic_dev_flow_ctrl_set,
 	.rss_hash_update               = spnic_rss_hash_update,
 	.rss_hash_conf_get             = spnic_rss_conf_get,
 	.reta_update                   = spnic_rss_reta_update,
diff --git a/drivers/net/spnic/spnic_ethdev.h b/drivers/net/spnic/spnic_ethdev.h
index 2b59886942..be429945ac 100644
--- a/drivers/net/spnic/spnic_ethdev.h
+++ b/drivers/net/spnic/spnic_ethdev.h
@@ -76,6 +76,7 @@ struct spnic_nic_dev {
 
 	bool pause_set;
 	pthread_mutex_t pause_mutuex;
+	struct nic_pause_config nic_pause;
 
 	struct rte_ether_addr default_addr;
 	struct rte_ether_addr *mc_list;
