[v12,06/11] ethdev: add simple power management API

Message ID 8f06ba8347a3b464eba41ee4985b83934422c89a.1608213657.git.anatoly.burakov@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Add PMD power management |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anatoly Burakov Dec. 17, 2020, 2:05 p.m. UTC
  From: Liang Ma <liang.j.ma@intel.com>

Add a simple API to allow getting the monitor conditions for
power-optimized monitoring of the RX queues from the PMD, as well as
release notes information.

Signed-off-by: Liang Ma <liang.j.ma@intel.com>
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---

Notes:
    v6:
    - Rebase on top of latest main
    - Ensure the API checks queue ID (Konstantin)
    - Removed accidental inclusion of unrelated release notes
    v5:
    - Bring function format in line with other functions in the file
    - Ensure the API is supported by the driver before calling it (Konstantin)

 doc/guides/rel_notes/release_21_02.rst |  4 ++++
 lib/librte_ethdev/rte_ethdev.c         | 28 ++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h         | 25 +++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h  | 22 ++++++++++++++++++++
 lib/librte_ethdev/version.map          |  3 +++
 5 files changed, 82 insertions(+)
  

Comments

Andrew Rybchenko Dec. 28, 2020, 11 a.m. UTC | #1
On 12/17/20 5:05 PM, Anatoly Burakov wrote:
> From: Liang Ma <liang.j.ma@intel.com>
> 
> Add a simple API to allow getting the monitor conditions for
> power-optimized monitoring of the RX queues from the PMD, as well as
> release notes information.
> 
> Signed-off-by: Liang Ma <liang.j.ma@intel.com>
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
> 
> Notes:
>     v6:
>     - Rebase on top of latest main
>     - Ensure the API checks queue ID (Konstantin)
>     - Removed accidental inclusion of unrelated release notes
>     v5:
>     - Bring function format in line with other functions in the file
>     - Ensure the API is supported by the driver before calling it (Konstantin)
> 
>  doc/guides/rel_notes/release_21_02.rst |  4 ++++
>  lib/librte_ethdev/rte_ethdev.c         | 28 ++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h         | 25 +++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_driver.h  | 22 ++++++++++++++++++++
>  lib/librte_ethdev/version.map          |  3 +++
>  5 files changed, 82 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_21_02.rst b/doc/guides/rel_notes/release_21_02.rst
> index 638f98168b..feb3ff4f06 100644
> --- a/doc/guides/rel_notes/release_21_02.rst
> +++ b/doc/guides/rel_notes/release_21_02.rst
> @@ -55,6 +55,10 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **ethdev: added 1 new API for PMD power management**

"1 new API" sounds a bit confusing. May be just "a new API"?

> +
> +  * ``rte_eth_get_monitor_addr()``, to be used in conjunction with
> +    ``rte_power_monitor()`` to enable automatic power management for PMD's.

Missing extra empty line here.

>  
>  Removed Items
>  -------------
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 17ddacc78d..58f68321ea 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -5115,6 +5115,34 @@ rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
>  		       dev->dev_ops->tx_burst_mode_get(dev, queue_id, mode));
>  }
>  
> +int
> +rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
> +		struct rte_power_monitor_cond *pmc)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	dev = &rte_eth_devices[port_id];
> +
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_monitor_addr, -ENOTSUP);
> +
> +	if (queue_id >= dev->data->nb_tx_queues) {
> +		RTE_ETHDEV_LOG(ERR, "Invalid TX queue_id=%u\n", queue_id);

Why is Tx queue checked and logged here, but Rx queue is used
below? I guess Rx should be used here as well.

I.e. TX -> Rx

> +		return -EINVAL;
> +	}
> +
> +	if (pmc == NULL) {
> +		RTE_ETHDEV_LOG(ERR, "Invalid power monitor condition=%p\n",
> +				pmc);
> +		return -EINVAL;
> +	}
> +
> +	return eth_err(port_id,
> +		dev->dev_ops->get_monitor_addr(dev->data->rx_queues[queue_id],
> +			pmc));
> +}
> +
>  int
>  rte_eth_dev_set_mc_addr_list(uint16_t port_id,
>  			     struct rte_ether_addr *mc_addr_set,
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index f5f8919186..ca0f91312e 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -157,6 +157,7 @@ extern "C" {
>  #include <rte_common.h>
>  #include <rte_config.h>
>  #include <rte_ether.h>
> +#include <rte_power_intrinsics.h>
>  
>  #include "rte_ethdev_trace_fp.h"
>  #include "rte_dev_info.h"
> @@ -4334,6 +4335,30 @@ __rte_experimental
>  int rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
>  	struct rte_eth_burst_mode *mode);
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Retrieve the monitor condition for a given receive queue.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param queue_id
> + *   The Rx queue on the Ethernet device for which information
> + *   will be retrieved.
> + * @param pmc
> + *   The pointer point to power-optimized monitoring condition structure.
> + *
> + * @return
> + *   - 0: Success.
> + *   -ENOTSUP: Operation not supported.
> + *   -EINVAL: Invalid parameters.
> + *   -ENODEV: Invalid port ID.
> + */
> +__rte_experimental
> +int rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
> +		struct rte_power_monitor_cond *pmc);
> +
>  /**
>   * Retrieve device registers and register attributes (number of registers and
>   * register size)
> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> index 0eacfd8425..ae4f152cf0 100644
> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> @@ -763,6 +763,26 @@ typedef int (*eth_hairpin_queue_peer_unbind_t)
>  	(struct rte_eth_dev *dev, uint16_t cur_queue, uint32_t direction);
>  /**< @internal Unbind peer queue from the current queue. */
>  
> +/**
> + * @internal
> + * Get address of memory location whose contents will change whenever there is
> + * new data to be received on an RX queue.

RX -> Rx

> + *
> + * @param rxq
> + *   Ethdev queue pointer.
> + * @param pmc
> + *   The pointer to power-optimized monitoring condition structure.
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success
> + * @retval -EINVAL
> + *   Invalid parameters
> + */
> +typedef int (*eth_get_monitor_addr_t)(void *rxq,
> +		struct rte_power_monitor_cond *pmc);
> +
>  /**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
> @@ -917,6 +937,8 @@ struct eth_dev_ops {
>  	/**< Set up the connection between the pair of hairpin queues. */
>  	eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
>  	/**< Disconnect the hairpin queues of a pair from each other. */
> +	eth_get_monitor_addr_t get_monitor_addr;
> +	/**< Get next RX queue ring entry address. */

RX -> Rx

>  };
>  
>  /**
> diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map
> index d3f5410806..a124e1e370 100644
> --- a/lib/librte_ethdev/version.map
> +++ b/lib/librte_ethdev/version.map
> @@ -240,6 +240,9 @@ EXPERIMENTAL {
>  	rte_flow_get_restore_info;
>  	rte_flow_tunnel_action_decap_release;
>  	rte_flow_tunnel_item_release;
> +
> +	# added in 21.02
> +	rte_eth_get_monitor_addr;
>  };
>  
>  INTERNAL {
>
  
Anatoly Burakov Jan. 8, 2021, 4:30 p.m. UTC | #2
On 28-Dec-20 11:00 AM, Andrew Rybchenko wrote:
> On 12/17/20 5:05 PM, Anatoly Burakov wrote:
>> From: Liang Ma <liang.j.ma@intel.com>
>>
>> Add a simple API to allow getting the monitor conditions for
>> power-optimized monitoring of the RX queues from the PMD, as well as
>> release notes information.
>>
>> Signed-off-by: Liang Ma <liang.j.ma@intel.com>
>> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>> ---

Hi Andrew,

Thanks for your review!

>> @@ -55,6 +55,10 @@ New Features
>>        Also, make sure to start the actual text at the margin.
>>        =======================================================
>>   
>> +* **ethdev: added 1 new API for PMD power management**
> 
> "1 new API" sounds a bit confusing. May be just "a new API"?
> 
>> +
>> +  * ``rte_eth_get_monitor_addr()``, to be used in conjunction with
>> +    ``rte_power_monitor()`` to enable automatic power management for PMD's.
> 
> Missing extra empty line here.
> 

Will fix.

>>   
>>   Removed Items
>>   -------------
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index 17ddacc78d..58f68321ea 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -5115,6 +5115,34 @@ rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
>>   		       dev->dev_ops->tx_burst_mode_get(dev, queue_id, mode));
>>   }
>>   
>> +int
>> +rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
>> +		struct rte_power_monitor_cond *pmc)
>> +{
>> +	struct rte_eth_dev *dev;
>> +
>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>> +
>> +	dev = &rte_eth_devices[port_id];
>> +
>> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_monitor_addr, -ENOTSUP);
>> +
>> +	if (queue_id >= dev->data->nb_tx_queues) {
>> +		RTE_ETHDEV_LOG(ERR, "Invalid TX queue_id=%u\n", queue_id);
> 
> Why is Tx queue checked and logged here, but Rx queue is used
> below? I guess Rx should be used here as well.
> 
> I.e. TX -> Rx
> 

Yep, fixed already.

>> +		return -EINVAL;
>> +	}
>> +
>> +	if (pmc == NULL) {
>> +		RTE_ETHDEV_LOG(ERR, "Invalid power monitor condition=%p\n",
>> +				pmc);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return eth_err(port_id,
>> +		dev->dev_ops->get_monitor_addr(dev->data->rx_queues[queue_id],
>> +			pmc));
>> +}
>> +
>>   int
>>   rte_eth_dev_set_mc_addr_list(uint16_t port_id,
>>   			     struct rte_ether_addr *mc_addr_set,
>> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
>> index f5f8919186..ca0f91312e 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -157,6 +157,7 @@ extern "C" {
>>   #include <rte_common.h>
>>   #include <rte_config.h>
>>   #include <rte_ether.h>
>> +#include <rte_power_intrinsics.h>
>>   
>>   #include "rte_ethdev_trace_fp.h"
>>   #include "rte_dev_info.h"
>> @@ -4334,6 +4335,30 @@ __rte_experimental
>>   int rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
>>   	struct rte_eth_burst_mode *mode);
>>   
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change without prior notice
>> + *
>> + * Retrieve the monitor condition for a given receive queue.
>> + *
>> + * @param port_id
>> + *   The port identifier of the Ethernet device.
>> + * @param queue_id
>> + *   The Rx queue on the Ethernet device for which information
>> + *   will be retrieved.
>> + * @param pmc
>> + *   The pointer point to power-optimized monitoring condition structure.
>> + *
>> + * @return
>> + *   - 0: Success.
>> + *   -ENOTSUP: Operation not supported.
>> + *   -EINVAL: Invalid parameters.
>> + *   -ENODEV: Invalid port ID.
>> + */
>> +__rte_experimental
>> +int rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
>> +		struct rte_power_monitor_cond *pmc);
>> +
>>   /**
>>    * Retrieve device registers and register attributes (number of registers and
>>    * register size)
>> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
>> index 0eacfd8425..ae4f152cf0 100644
>> --- a/lib/librte_ethdev/rte_ethdev_driver.h
>> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
>> @@ -763,6 +763,26 @@ typedef int (*eth_hairpin_queue_peer_unbind_t)
>>   	(struct rte_eth_dev *dev, uint16_t cur_queue, uint32_t direction);
>>   /**< @internal Unbind peer queue from the current queue. */
>>   
>> +/**
>> + * @internal
>> + * Get address of memory location whose contents will change whenever there is
>> + * new data to be received on an RX queue.
> 
> RX -> Rx
> 

Will fix.

>> + *
>> + * @param rxq
>> + *   Ethdev queue pointer.
>> + * @param pmc
>> + *   The pointer to power-optimized monitoring condition structure.
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success
>> + * @retval -EINVAL
>> + *   Invalid parameters
>> + */
>> +typedef int (*eth_get_monitor_addr_t)(void *rxq,
>> +		struct rte_power_monitor_cond *pmc);
>> +
>>   /**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>> @@ -917,6 +937,8 @@ struct eth_dev_ops {
>>   	/**< Set up the connection between the pair of hairpin queues. */
>>   	eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
>>   	/**< Disconnect the hairpin queues of a pair from each other. */
>> +	eth_get_monitor_addr_t get_monitor_addr;
>> +	/**< Get next RX queue ring entry address. */
> 
> RX -> Rx
> 

Will fix.

>>   };
>>   
>>   /**
>> diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map
>> index d3f5410806..a124e1e370 100644
>> --- a/lib/librte_ethdev/version.map
>> +++ b/lib/librte_ethdev/version.map
>> @@ -240,6 +240,9 @@ EXPERIMENTAL {
>>   	rte_flow_get_restore_info;
>>   	rte_flow_tunnel_action_decap_release;
>>   	rte_flow_tunnel_item_release;
>> +
>> +	# added in 21.02
>> +	rte_eth_get_monitor_addr;
>>   };
>>   
>>   INTERNAL {
>>
>
  
Lance Richardson Jan. 12, 2021, 8:32 p.m. UTC | #3
On Thu, Dec 17, 2020 at 9:08 AM Anatoly Burakov
<anatoly.burakov@intel.com> wrote:
>
> From: Liang Ma <liang.j.ma@intel.com>
>
> Add a simple API to allow getting the monitor conditions for
> power-optimized monitoring of the RX queues from the PMD, as well as
> release notes information.
>
> Signed-off-by: Liang Ma <liang.j.ma@intel.com>
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
<snip>
>  /**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
> @@ -917,6 +937,8 @@ struct eth_dev_ops {
>         /**< Set up the connection between the pair of hairpin queues. */
>         eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
>         /**< Disconnect the hairpin queues of a pair from each other. */
> +       eth_get_monitor_addr_t get_monitor_addr;
> +       /**< Get next RX queue ring entry address. */
>  };
>

The implementation of get_monitor_addr will have much in common with
the rx_descriptor_status API in struct rte_eth_dev, including the property
that it will likely not make sense for it to be called concurrently with
rx_pkt_burst on a given queue. Might it make more sense to have this
API in struct rte_eth_dev instead of struct eth_dev_ops?
  
Anatoly Burakov Jan. 13, 2021, 1:04 p.m. UTC | #4
On 12-Jan-21 8:32 PM, Lance Richardson wrote:
> On Thu, Dec 17, 2020 at 9:08 AM Anatoly Burakov
> <anatoly.burakov@intel.com> wrote:
>>
>> From: Liang Ma <liang.j.ma@intel.com>
>>
>> Add a simple API to allow getting the monitor conditions for
>> power-optimized monitoring of the RX queues from the PMD, as well as
>> release notes information.
>>
>> Signed-off-by: Liang Ma <liang.j.ma@intel.com>
>> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>> ---
> <snip>
>>   /**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>> @@ -917,6 +937,8 @@ struct eth_dev_ops {
>>          /**< Set up the connection between the pair of hairpin queues. */
>>          eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
>>          /**< Disconnect the hairpin queues of a pair from each other. */
>> +       eth_get_monitor_addr_t get_monitor_addr;
>> +       /**< Get next RX queue ring entry address. */
>>   };
>>
> 
> The implementation of get_monitor_addr will have much in common with
> the rx_descriptor_status API in struct rte_eth_dev, including the property
> that it will likely not make sense for it to be called concurrently with
> rx_pkt_burst on a given queue. Might it make more sense to have this
> API in struct rte_eth_dev instead of struct eth_dev_ops?
> 

I don't have an opinion on this as this code isn't really my area of 
expertise. I'm fine with wherever the community thinks this code should 
be. Any other opinions?
  
Ananyev, Konstantin Jan. 13, 2021, 1:25 p.m. UTC | #5
> 
> On 12-Jan-21 8:32 PM, Lance Richardson wrote:
> > On Thu, Dec 17, 2020 at 9:08 AM Anatoly Burakov
> > <anatoly.burakov@intel.com> wrote:
> >>
> >> From: Liang Ma <liang.j.ma@intel.com>
> >>
> >> Add a simple API to allow getting the monitor conditions for
> >> power-optimized monitoring of the RX queues from the PMD, as well as
> >> release notes information.
> >>
> >> Signed-off-by: Liang Ma <liang.j.ma@intel.com>
> >> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> >> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> >> ---
> > <snip>
> >>   /**
> >>    * @internal A structure containing the functions exported by an Ethernet driver.
> >>    */
> >> @@ -917,6 +937,8 @@ struct eth_dev_ops {
> >>          /**< Set up the connection between the pair of hairpin queues. */
> >>          eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
> >>          /**< Disconnect the hairpin queues of a pair from each other. */
> >> +       eth_get_monitor_addr_t get_monitor_addr;
> >> +       /**< Get next RX queue ring entry address. */
> >>   };
> >>
> >
> > The implementation of get_monitor_addr will have much in common with
> > the rx_descriptor_status API in struct rte_eth_dev, including the property
> > that it will likely not make sense for it to be called concurrently with
> > rx_pkt_burst on a given queue. Might it make more sense to have this
> > API in struct rte_eth_dev instead of struct eth_dev_ops?
> >
> 
> I don't have an opinion on this as this code isn't really my area of
> expertise. I'm fine with wherever the community thinks this code should
> be. Any other opinions?
> 

I don't think it is a good idea to  push new members into rte_eth_dev.
It either means an ABI breakage or wasting of one of our reserved fields.
IMO this function is not that performance critical to justify such insersion.
In fact, I think we should look in different direction -
remove rx/tx_descriptor_status() functions from rte_eth_dev,
or even better make rte_eth_dev an opaque pointer.
  

Patch

diff --git a/doc/guides/rel_notes/release_21_02.rst b/doc/guides/rel_notes/release_21_02.rst
index 638f98168b..feb3ff4f06 100644
--- a/doc/guides/rel_notes/release_21_02.rst
+++ b/doc/guides/rel_notes/release_21_02.rst
@@ -55,6 +55,10 @@  New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **ethdev: added 1 new API for PMD power management**
+
+  * ``rte_eth_get_monitor_addr()``, to be used in conjunction with
+    ``rte_power_monitor()`` to enable automatic power management for PMD's.
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 17ddacc78d..58f68321ea 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -5115,6 +5115,34 @@  rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
 		       dev->dev_ops->tx_burst_mode_get(dev, queue_id, mode));
 }
 
+int
+rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
+		struct rte_power_monitor_cond *pmc)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_monitor_addr, -ENOTSUP);
+
+	if (queue_id >= dev->data->nb_tx_queues) {
+		RTE_ETHDEV_LOG(ERR, "Invalid TX queue_id=%u\n", queue_id);
+		return -EINVAL;
+	}
+
+	if (pmc == NULL) {
+		RTE_ETHDEV_LOG(ERR, "Invalid power monitor condition=%p\n",
+				pmc);
+		return -EINVAL;
+	}
+
+	return eth_err(port_id,
+		dev->dev_ops->get_monitor_addr(dev->data->rx_queues[queue_id],
+			pmc));
+}
+
 int
 rte_eth_dev_set_mc_addr_list(uint16_t port_id,
 			     struct rte_ether_addr *mc_addr_set,
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index f5f8919186..ca0f91312e 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -157,6 +157,7 @@  extern "C" {
 #include <rte_common.h>
 #include <rte_config.h>
 #include <rte_ether.h>
+#include <rte_power_intrinsics.h>
 
 #include "rte_ethdev_trace_fp.h"
 #include "rte_dev_info.h"
@@ -4334,6 +4335,30 @@  __rte_experimental
 int rte_eth_tx_burst_mode_get(uint16_t port_id, uint16_t queue_id,
 	struct rte_eth_burst_mode *mode);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Retrieve the monitor condition for a given receive queue.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param queue_id
+ *   The Rx queue on the Ethernet device for which information
+ *   will be retrieved.
+ * @param pmc
+ *   The pointer point to power-optimized monitoring condition structure.
+ *
+ * @return
+ *   - 0: Success.
+ *   -ENOTSUP: Operation not supported.
+ *   -EINVAL: Invalid parameters.
+ *   -ENODEV: Invalid port ID.
+ */
+__rte_experimental
+int rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,
+		struct rte_power_monitor_cond *pmc);
+
 /**
  * Retrieve device registers and register attributes (number of registers and
  * register size)
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 0eacfd8425..ae4f152cf0 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -763,6 +763,26 @@  typedef int (*eth_hairpin_queue_peer_unbind_t)
 	(struct rte_eth_dev *dev, uint16_t cur_queue, uint32_t direction);
 /**< @internal Unbind peer queue from the current queue. */
 
+/**
+ * @internal
+ * Get address of memory location whose contents will change whenever there is
+ * new data to be received on an RX queue.
+ *
+ * @param rxq
+ *   Ethdev queue pointer.
+ * @param pmc
+ *   The pointer to power-optimized monitoring condition structure.
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success
+ * @retval -EINVAL
+ *   Invalid parameters
+ */
+typedef int (*eth_get_monitor_addr_t)(void *rxq,
+		struct rte_power_monitor_cond *pmc);
+
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
@@ -917,6 +937,8 @@  struct eth_dev_ops {
 	/**< Set up the connection between the pair of hairpin queues. */
 	eth_hairpin_queue_peer_unbind_t hairpin_queue_peer_unbind;
 	/**< Disconnect the hairpin queues of a pair from each other. */
+	eth_get_monitor_addr_t get_monitor_addr;
+	/**< Get next RX queue ring entry address. */
 };
 
 /**
diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map
index d3f5410806..a124e1e370 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -240,6 +240,9 @@  EXPERIMENTAL {
 	rte_flow_get_restore_info;
 	rte_flow_tunnel_action_decap_release;
 	rte_flow_tunnel_item_release;
+
+	# added in 21.02
+	rte_eth_get_monitor_addr;
 };
 
 INTERNAL {