[v2,2/3] eal: add ack interrupt API

Message ID 20190717124354.142668-3-ndabilpuram@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series vfio: fix broken msix interrupt initialization |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Nithin Dabilpuram July 17, 2019, 12:43 p.m. UTC
  Add new ack interrupt API to avoid using
VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
acking interrupt purpose for VFIO based interrupt handlers.
This implementation is specific to Linux.

Using rte_intr_enable() for acking interrupt has below issues

 * Time consuming to do for every interrupt received as it will
   free_irq() followed by request_irq() and all other initializations
 * A race condition because of a window between free_irq() and
   request_irq() with packet reception still on and device still
   enabled and would throw warning messages like below.
   [158764.159833] do_IRQ: 9.34 No irq handler for vector

In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI interrupts
as they are edge triggered and kernel would not mask the interrupt before
delivering the event to userspace and we don't need to ack.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Signed-off-by: Jerin Jacob <jerinj@marvell.com>
---
v2:
* No change

 lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
 lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
 lib/librte_eal/linux/eal/eal_interrupts.c      | 81 ++++++++++++++++++++++++++
 lib/librte_eal/rte_eal_version.map             |  1 +
 4 files changed, 113 insertions(+)
  

Comments

Hyong Youb Kim (hyonkim) July 17, 2019, 12:57 p.m. UTC | #1
> -----Original Message-----
> From: Nithin Dabilpuram <ndabilpuram@marvell.com>
> Sent: Wednesday, July 17, 2019 9:44 PM
> To: Hyong Youb Kim (hyonkim) <hyonkim@cisco.com>; David Marchand
> <david.marchand@redhat.com>; Thomas Monjalon
> <thomas@monjalon.net>; Ferruh Yigit <ferruh.yigit@intel.com>; Bruce
> Richardson <bruce.richardson@intel.com>
> Cc: jerinj@marvell.com; John Daley (johndale) <johndale@cisco.com>;
> Shahed Shaikh <shshaikh@marvell.com>; dev@dpdk.org; Nithin Dabilpuram
> <ndabilpuram@marvell.com>
> Subject: [PATCH v2 2/3] eal: add ack interrupt API
> 
> Add new ack interrupt API to avoid using
> VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
> acking interrupt purpose for VFIO based interrupt handlers.
> This implementation is specific to Linux.
> 
> Using rte_intr_enable() for acking interrupt has below issues
> 
>  * Time consuming to do for every interrupt received as it will
>    free_irq() followed by request_irq() and all other initializations
>  * A race condition because of a window between free_irq() and
>    request_irq() with packet reception still on and device still
>    enabled and would throw warning messages like below.
>    [158764.159833] do_IRQ: 9.34 No irq handler for vector
> 
> In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI interrupts
> as they are edge triggered and kernel would not mask the interrupt before
> delivering the event to userspace and we don't need to ack.
> 
> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
> Signed-off-by: Jerin Jacob <jerinj@marvell.com>
> ---
> v2:
> * No change
> 
>  lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
>  lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
>  lib/librte_eal/linux/eal/eal_interrupts.c      | 81
> ++++++++++++++++++++++++++
>  lib/librte_eal/rte_eal_version.map             |  1 +
>  4 files changed, 113 insertions(+)
> 
> diff --git a/lib/librte_eal/common/include/rte_interrupts.h
> b/lib/librte_eal/common/include/rte_interrupts.h
> index c1e912c..93b31cd 100644
> --- a/lib/librte_eal/common/include/rte_interrupts.h
> +++ b/lib/librte_eal/common/include/rte_interrupts.h
> @@ -118,6 +118,28 @@ int rte_intr_enable(const struct rte_intr_handle
> *intr_handle);
>   */
>  int rte_intr_disable(const struct rte_intr_handle *intr_handle);
> 
> +/**
> + * It acks an interrupt raised for the specified handle.
> + *
> + * Call this function to ack an interrupt from interrupt
> + * handler either from application or driver, so that
> + * new interrupts are raised.
> + *
> + * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
> + *    this function is a no-op and returns success without
> + *    changing anything as kernel doesn't expect
> + *    them to be acked.
> + *
[...]

Shouldn't we explain that this really is "unmask" but named "ack" because
of x and y, and that it is expected at end of INTx handler? Ack does
not have a well-defined meaning, whereas everyone knows what unmask
means..

[...]

Thanks.
-Hyong
  
Nithin Dabilpuram July 17, 2019, 2:35 p.m. UTC | #2
On Wed, Jul 17, 2019 at 12:57:29PM +0000, Hyong Youb Kim (hyonkim) wrote:
> External Email
> 
> ----------------------------------------------------------------------
> > -----Original Message-----
> > From: Nithin Dabilpuram <ndabilpuram@marvell.com>
> > Sent: Wednesday, July 17, 2019 9:44 PM
> > To: Hyong Youb Kim (hyonkim) <hyonkim@cisco.com>; David Marchand
> > <david.marchand@redhat.com>; Thomas Monjalon
> > <thomas@monjalon.net>; Ferruh Yigit <ferruh.yigit@intel.com>; Bruce
> > Richardson <bruce.richardson@intel.com>
> > Cc: jerinj@marvell.com; John Daley (johndale) <johndale@cisco.com>;
> > Shahed Shaikh <shshaikh@marvell.com>; dev@dpdk.org; Nithin Dabilpuram
> > <ndabilpuram@marvell.com>
> > Subject: [PATCH v2 2/3] eal: add ack interrupt API
> > 
> > Add new ack interrupt API to avoid using
> > VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
> > acking interrupt purpose for VFIO based interrupt handlers.
> > This implementation is specific to Linux.
> > 
> > Using rte_intr_enable() for acking interrupt has below issues
> > 
> >  * Time consuming to do for every interrupt received as it will
> >    free_irq() followed by request_irq() and all other initializations
> >  * A race condition because of a window between free_irq() and
> >    request_irq() with packet reception still on and device still
> >    enabled and would throw warning messages like below.
> >    [158764.159833] do_IRQ: 9.34 No irq handler for vector
> > 
> > In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI interrupts
> > as they are edge triggered and kernel would not mask the interrupt before
> > delivering the event to userspace and we don't need to ack.
> > 
> > Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
> > Signed-off-by: Jerin Jacob <jerinj@marvell.com>
> > ---
> > v2:
> > * No change
> > 
> >  lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
> >  lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
> >  lib/librte_eal/linux/eal/eal_interrupts.c      | 81
> > ++++++++++++++++++++++++++
> >  lib/librte_eal/rte_eal_version.map             |  1 +
> >  4 files changed, 113 insertions(+)
> > 
> > diff --git a/lib/librte_eal/common/include/rte_interrupts.h
> > b/lib/librte_eal/common/include/rte_interrupts.h
> > index c1e912c..93b31cd 100644
> > --- a/lib/librte_eal/common/include/rte_interrupts.h
> > +++ b/lib/librte_eal/common/include/rte_interrupts.h
> > @@ -118,6 +118,28 @@ int rte_intr_enable(const struct rte_intr_handle
> > *intr_handle);
> >   */
> >  int rte_intr_disable(const struct rte_intr_handle *intr_handle);
> > 
> > +/**
> > + * It acks an interrupt raised for the specified handle.
> > + *
> > + * Call this function to ack an interrupt from interrupt
> > + * handler either from application or driver, so that
> > + * new interrupts are raised.
> > + *
> > + * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
> > + *    this function is a no-op and returns success without
> > + *    changing anything as kernel doesn't expect
> > + *    them to be acked.
> > + *
> [...]
> 
> Shouldn't we explain that this really is "unmask" but named "ack" because
> of x and y, and that it is expected at end of INTx handler? Ack does
> not have a well-defined meaning, whereas everyone knows what unmask
> means..
> 


Ok. Is the below text fine with you ? Or please suggest.

@note For interrupt handle types VFIO_MSIX and VFIO_MSI,
   this function is a no-op and returns success without
   changing anything as kernel doesn't expect 
   them to be acked. 
   This needs be used atleast for PCI devices with INTx interrupt 
   as kernel before passing on event for INTx triggered interrupt, 
   masks the interrupt and expects application to unmask it so that,
   further interrupts can be raised/triggered. This is also due to 
   the fact that INTx is level triggered interrupt where as MSI/MSIx 
   is not. Ideally this should have been called as intr_unmask() 
   representing underlying api, but since unmask operation 
   is not supported and not needed for VFIO MSI/MSIx interrupts 
   after handling, it is named as ack.

> [...]
> 
> Thanks.
> -Hyong
>
  
Hyong Youb Kim (hyonkim) July 17, 2019, 3:05 p.m. UTC | #3
> -----Original Message-----
> From: Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>
> Sent: Wednesday, July 17, 2019 11:36 PM
[...]
> > > Subject: [PATCH v2 2/3] eal: add ack interrupt API
> > >
> > > Add new ack interrupt API to avoid using
> > > VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
> > > acking interrupt purpose for VFIO based interrupt handlers.
> > > This implementation is specific to Linux.
> > >
> > > Using rte_intr_enable() for acking interrupt has below issues
> > >
> > >  * Time consuming to do for every interrupt received as it will
> > >    free_irq() followed by request_irq() and all other initializations
> > >  * A race condition because of a window between free_irq() and
> > >    request_irq() with packet reception still on and device still
> > >    enabled and would throw warning messages like below.
> > >    [158764.159833] do_IRQ: 9.34 No irq handler for vector
> > >
> > > In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI
> interrupts
> > > as they are edge triggered and kernel would not mask the interrupt
> before
> > > delivering the event to userspace and we don't need to ack.
> > >
> > > Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
> > > Signed-off-by: Jerin Jacob <jerinj@marvell.com>
> > > ---
> > > v2:
> > > * No change
> > >
> > >  lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
> > >  lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
> > >  lib/librte_eal/linux/eal/eal_interrupts.c      | 81
> > > ++++++++++++++++++++++++++
> > >  lib/librte_eal/rte_eal_version.map             |  1 +
> > >  4 files changed, 113 insertions(+)
> > >
> > > diff --git a/lib/librte_eal/common/include/rte_interrupts.h
> > > b/lib/librte_eal/common/include/rte_interrupts.h
> > > index c1e912c..93b31cd 100644
> > > --- a/lib/librte_eal/common/include/rte_interrupts.h
> > > +++ b/lib/librte_eal/common/include/rte_interrupts.h
> > > @@ -118,6 +118,28 @@ int rte_intr_enable(const struct rte_intr_handle
> > > *intr_handle);
> > >   */
> > >  int rte_intr_disable(const struct rte_intr_handle *intr_handle);
> > >
> > > +/**
> > > + * It acks an interrupt raised for the specified handle.
> > > + *
> > > + * Call this function to ack an interrupt from interrupt
> > > + * handler either from application or driver, so that
> > > + * new interrupts are raised.
> > > + *
> > > + * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
> > > + *    this function is a no-op and returns success without
> > > + *    changing anything as kernel doesn't expect
> > > + *    them to be acked.
> > > + *
> > [...]
> >
> > Shouldn't we explain that this really is "unmask" but named "ack" because
> > of x and y, and that it is expected at end of INTx handler? Ack does
> > not have a well-defined meaning, whereas everyone knows what unmask
> > means..
> >
> 
> 
> Ok. Is the below text fine with you ? Or please suggest.
> 
> @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
>    this function is a no-op and returns success without
>    changing anything as kernel doesn't expect
>    them to be acked.
>    This needs be used atleast for PCI devices with INTx interrupt
>    as kernel before passing on event for INTx triggered interrupt,
>    masks the interrupt and expects application to unmask it so that,
>    further interrupts can be raised/triggered. This is also due to
>    the fact that INTx is level triggered interrupt where as MSI/MSIx
>    is not. Ideally this should have been called as intr_unmask()
>    representing underlying api, but since unmask operation
>    is not supported and not needed for VFIO MSI/MSIx interrupts
>    after handling, it is named as ack.
> 

How about this?

PMD generally calls this function at the end of its IRQ callback.
Internally, it unmasks the interrupt if possible. For INTx, unmasking
is required as the interrupt is auto-masked prior to invoking
callback. For MSI/MSI-X, unmasking is typically not needed as the
interrupt is not auto-masked. In fact, for interrupt handle types
VFIO_MSIX and VFIO_MSI, this function is no-op.

Thanks for your effort..
-Hyong
  
Nithin Dabilpuram July 17, 2019, 3:16 p.m. UTC | #4
On Wed, Jul 17, 2019 at 03:05:47PM +0000, Hyong Youb Kim (hyonkim) wrote:
> > -----Original Message-----
> > From: Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>
> > Sent: Wednesday, July 17, 2019 11:36 PM
> [...]
> > > > Subject: [PATCH v2 2/3] eal: add ack interrupt API
> > > >
> > > > Add new ack interrupt API to avoid using
> > > > VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
> > > > acking interrupt purpose for VFIO based interrupt handlers.
> > > > This implementation is specific to Linux.
> > > >
> > > > Using rte_intr_enable() for acking interrupt has below issues
> > > >
> > > >  * Time consuming to do for every interrupt received as it will
> > > >    free_irq() followed by request_irq() and all other initializations
> > > >  * A race condition because of a window between free_irq() and
> > > >    request_irq() with packet reception still on and device still
> > > >    enabled and would throw warning messages like below.
> > > >    [158764.159833] do_IRQ: 9.34 No irq handler for vector
> > > >
> > > > In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI
> > interrupts
> > > > as they are edge triggered and kernel would not mask the interrupt
> > before
> > > > delivering the event to userspace and we don't need to ack.
> > > >
> > > > Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
> > > > Signed-off-by: Jerin Jacob <jerinj@marvell.com>
> > > > ---
> > > > v2:
> > > > * No change
> > > >
> > > >  lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
> > > >  lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
> > > >  lib/librte_eal/linux/eal/eal_interrupts.c      | 81
> > > > ++++++++++++++++++++++++++
> > > >  lib/librte_eal/rte_eal_version.map             |  1 +
> > > >  4 files changed, 113 insertions(+)
> > > >
> > > > diff --git a/lib/librte_eal/common/include/rte_interrupts.h
> > > > b/lib/librte_eal/common/include/rte_interrupts.h
> > > > index c1e912c..93b31cd 100644
> > > > --- a/lib/librte_eal/common/include/rte_interrupts.h
> > > > +++ b/lib/librte_eal/common/include/rte_interrupts.h
> > > > @@ -118,6 +118,28 @@ int rte_intr_enable(const struct rte_intr_handle
> > > > *intr_handle);
> > > >   */
> > > >  int rte_intr_disable(const struct rte_intr_handle *intr_handle);
> > > >
> > > > +/**
> > > > + * It acks an interrupt raised for the specified handle.
> > > > + *
> > > > + * Call this function to ack an interrupt from interrupt
> > > > + * handler either from application or driver, so that
> > > > + * new interrupts are raised.
> > > > + *
> > > > + * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
> > > > + *    this function is a no-op and returns success without
> > > > + *    changing anything as kernel doesn't expect
> > > > + *    them to be acked.
> > > > + *
> > > [...]
> > >
> > > Shouldn't we explain that this really is "unmask" but named "ack" because
> > > of x and y, and that it is expected at end of INTx handler? Ack does
> > > not have a well-defined meaning, whereas everyone knows what unmask
> > > means..
> > >
> > 
> > 
> > Ok. Is the below text fine with you ? Or please suggest.
> > 
> > @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
> >    this function is a no-op and returns success without
> >    changing anything as kernel doesn't expect
> >    them to be acked.
> >    This needs be used atleast for PCI devices with INTx interrupt
> >    as kernel before passing on event for INTx triggered interrupt,
> >    masks the interrupt and expects application to unmask it so that,
> >    further interrupts can be raised/triggered. This is also due to
> >    the fact that INTx is level triggered interrupt where as MSI/MSIx
> >    is not. Ideally this should have been called as intr_unmask()
> >    representing underlying api, but since unmask operation
> >    is not supported and not needed for VFIO MSI/MSIx interrupts
> >    after handling, it is named as ack.
> > 
> 
> How about this?
> 
> PMD generally calls this function at the end of its IRQ callback.
> Internally, it unmasks the interrupt if possible. For INTx, unmasking
> is required as the interrupt is auto-masked prior to invoking
> callback. For MSI/MSI-X, unmasking is typically not needed as the
> interrupt is not auto-masked. In fact, for interrupt handle types
> VFIO_MSIX and VFIO_MSI, this function is no-op.
>
Ok. Thanks. Will add this in next revision.

> Thanks for your effort..
> -Hyong
>
  
Burakov, Anatoly July 18, 2019, 10:22 a.m. UTC | #5
On 17-Jul-19 4:05 PM, Hyong Youb Kim (hyonkim) wrote:
>> -----Original Message-----
>> From: Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>
>> Sent: Wednesday, July 17, 2019 11:36 PM
> [...]
>>>> Subject: [PATCH v2 2/3] eal: add ack interrupt API
>>>>
>>>> Add new ack interrupt API to avoid using
>>>> VFIO_IRQ_SET_ACTION_TRIGGER(rte_intr_enable()) for
>>>> acking interrupt purpose for VFIO based interrupt handlers.
>>>> This implementation is specific to Linux.
>>>>
>>>> Using rte_intr_enable() for acking interrupt has below issues
>>>>
>>>>   * Time consuming to do for every interrupt received as it will
>>>>     free_irq() followed by request_irq() and all other initializations
>>>>   * A race condition because of a window between free_irq() and
>>>>     request_irq() with packet reception still on and device still
>>>>     enabled and would throw warning messages like below.
>>>>     [158764.159833] do_IRQ: 9.34 No irq handler for vector
>>>>
>>>> In this patch, rte_intr_ack() is a no-op for VFIO_MSIX/VFIO_MSI
>> interrupts
>>>> as they are edge triggered and kernel would not mask the interrupt
>> before
>>>> delivering the event to userspace and we don't need to ack.
>>>>
>>>> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
>>>> Signed-off-by: Jerin Jacob <jerinj@marvell.com>
>>>> ---
>>>> v2:
>>>> * No change
>>>>
>>>>   lib/librte_eal/common/include/rte_interrupts.h | 22 +++++++
>>>>   lib/librte_eal/freebsd/eal/eal_interrupts.c    |  9 +++
>>>>   lib/librte_eal/linux/eal/eal_interrupts.c      | 81
>>>> ++++++++++++++++++++++++++
>>>>   lib/librte_eal/rte_eal_version.map             |  1 +
>>>>   4 files changed, 113 insertions(+)
>>>>
>>>> diff --git a/lib/librte_eal/common/include/rte_interrupts.h
>>>> b/lib/librte_eal/common/include/rte_interrupts.h
>>>> index c1e912c..93b31cd 100644
>>>> --- a/lib/librte_eal/common/include/rte_interrupts.h
>>>> +++ b/lib/librte_eal/common/include/rte_interrupts.h
>>>> @@ -118,6 +118,28 @@ int rte_intr_enable(const struct rte_intr_handle
>>>> *intr_handle);
>>>>    */
>>>>   int rte_intr_disable(const struct rte_intr_handle *intr_handle);
>>>>
>>>> +/**
>>>> + * It acks an interrupt raised for the specified handle.
>>>> + *
>>>> + * Call this function to ack an interrupt from interrupt
>>>> + * handler either from application or driver, so that
>>>> + * new interrupts are raised.
>>>> + *
>>>> + * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
>>>> + *    this function is a no-op and returns success without
>>>> + *    changing anything as kernel doesn't expect
>>>> + *    them to be acked.
>>>> + *
>>> [...]
>>>
>>> Shouldn't we explain that this really is "unmask" but named "ack" because
>>> of x and y, and that it is expected at end of INTx handler? Ack does
>>> not have a well-defined meaning, whereas everyone knows what unmask
>>> means..
>>>
>>
>>
>> Ok. Is the below text fine with you ? Or please suggest.
>>
>> @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
>>     this function is a no-op and returns success without
>>     changing anything as kernel doesn't expect
>>     them to be acked.
>>     This needs be used atleast for PCI devices with INTx interrupt
>>     as kernel before passing on event for INTx triggered interrupt,
>>     masks the interrupt and expects application to unmask it so that,
>>     further interrupts can be raised/triggered. This is also due to
>>     the fact that INTx is level triggered interrupt where as MSI/MSIx
>>     is not. Ideally this should have been called as intr_unmask()
>>     representing underlying api, but since unmask operation
>>     is not supported and not needed for VFIO MSI/MSIx interrupts
>>     after handling, it is named as ack.
>>
> 
> How about this?
> 
> PMD generally calls this function at the end of its IRQ callback.
> Internally, it unmasks the interrupt if possible. For INTx, unmasking
> is required as the interrupt is auto-masked prior to invoking
> callback. For MSI/MSI-X, unmasking is typically not needed as the
> interrupt is not auto-masked. In fact, for interrupt handle types
> VFIO_MSIX and VFIO_MSI, this function is no-op.
> 

Does the user of this API even cares about these details? I would think 
that it would be eaiser to just mandate calling this function at the end 
of each interrupt callback period, regardless of which interrupt mode is 
used.

Internal details are better explained in the implementation.

> Thanks for your effort..
> -Hyong
> 
>
  

Patch

diff --git a/lib/librte_eal/common/include/rte_interrupts.h b/lib/librte_eal/common/include/rte_interrupts.h
index c1e912c..93b31cd 100644
--- a/lib/librte_eal/common/include/rte_interrupts.h
+++ b/lib/librte_eal/common/include/rte_interrupts.h
@@ -118,6 +118,28 @@  int rte_intr_enable(const struct rte_intr_handle *intr_handle);
  */
 int rte_intr_disable(const struct rte_intr_handle *intr_handle);
 
+/**
+ * It acks an interrupt raised for the specified handle.
+ *
+ * Call this function to ack an interrupt from interrupt
+ * handler either from application or driver, so that
+ * new interrupts are raised.
+ *
+ * @note For interrupt handle types VFIO_MSIX and VFIO_MSI,
+ *    this function is a no-op and returns success without
+ *    changing anything as kernel doesn't expect
+ *    them to be acked.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ */
+__rte_experimental
+int rte_intr_ack(const struct rte_intr_handle *intr_handle);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/freebsd/eal/eal_interrupts.c b/lib/librte_eal/freebsd/eal/eal_interrupts.c
index 10375bd..f6831b7 100644
--- a/lib/librte_eal/freebsd/eal/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal/eal_interrupts.c
@@ -387,6 +387,15 @@  rte_intr_disable(const struct rte_intr_handle *intr_handle)
 	return 0;
 }
 
+int
+rte_intr_ack(const struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle && intr_handle->type == RTE_INTR_HANDLE_VDEV)
+		return 0;
+
+	return -1;
+}
+
 static void
 eal_intr_process_interrupts(struct kevent *events, int nfds)
 {
diff --git a/lib/librte_eal/linux/eal/eal_interrupts.c b/lib/librte_eal/linux/eal/eal_interrupts.c
index 79ad5e8..91e220c 100644
--- a/lib/librte_eal/linux/eal/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal/eal_interrupts.c
@@ -197,6 +197,35 @@  vfio_disable_intx(const struct rte_intr_handle *intr_handle) {
 	return 0;
 }
 
+/* unmask/ack legacy (INTx) interrupts */
+static int
+vfio_ack_intx(const struct rte_intr_handle *intr_handle)
+{
+	struct vfio_irq_set *irq_set;
+	char irq_set_buf[IRQ_SET_BUF_LEN];
+	int len, ret;
+
+	len = sizeof(struct vfio_irq_set);
+
+	/* unmask INTx */
+	irq_set = (struct vfio_irq_set *) irq_set_buf;
+	memset(irq_set, 0, len);
+	irq_set->argsz = len;
+	irq_set->count = 1;
+	irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK;
+	irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+	irq_set->start = 0;
+
+	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+
+	if (ret) {
+		RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd %d\n",
+			intr_handle->fd);
+		return -1;
+	}
+	return 0;
+}
+
 /* enable MSI interrupts */
 static int
 vfio_enable_msi(const struct rte_intr_handle *intr_handle) {
@@ -694,6 +723,58 @@  rte_intr_enable(const struct rte_intr_handle *intr_handle)
 }
 
 int
+rte_intr_ack(const struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle && intr_handle->type == RTE_INTR_HANDLE_VDEV)
+		return 0;
+
+	if (!intr_handle || intr_handle->fd < 0 || intr_handle->uio_cfg_fd < 0)
+		return -1;
+
+	switch (intr_handle->type) {
+	/* Both acking and disabling are same for UIO */
+	case RTE_INTR_HANDLE_UIO:
+		if (uio_intr_enable(intr_handle))
+			return -1;
+		break;
+	case RTE_INTR_HANDLE_UIO_INTX:
+		if (uio_intx_intr_enable(intr_handle))
+			return -1;
+		break;
+	/* not used at this moment */
+	case RTE_INTR_HANDLE_ALARM:
+		return -1;
+#ifdef VFIO_PRESENT
+		/* Since VFIO_MSIX is implicitly acked
+		 * unlike INTx, we report success
+		 */
+	case RTE_INTR_HANDLE_VFIO_MSIX:
+	case RTE_INTR_HANDLE_VFIO_MSI:
+		return 0;
+	case RTE_INTR_HANDLE_VFIO_LEGACY:
+		if (vfio_ack_intx(intr_handle))
+			return -1;
+		break;
+#ifdef HAVE_VFIO_DEV_REQ_INTERFACE
+	case RTE_INTR_HANDLE_VFIO_REQ:
+		return -1;
+#endif
+#endif
+	/* not used at this moment */
+	case RTE_INTR_HANDLE_DEV_EVENT:
+		return -1;
+	/* unknown handle type */
+	default:
+		RTE_LOG(ERR, EAL,
+			"Unknown handle type of fd %d\n",
+					intr_handle->fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
 rte_intr_disable(const struct rte_intr_handle *intr_handle)
 {
 	if (intr_handle && intr_handle->type == RTE_INTR_HANDLE_VDEV)
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 1892d9e..0537a6d 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -407,4 +407,5 @@  EXPERIMENTAL {
 	rte_lcore_to_cpu_id;
 	rte_mcfg_timer_lock;
 	rte_mcfg_timer_unlock;
+	rte_intr_ack;
 };