diff mbox

[RFC,12/17] irq: bypass: Extend skeleton for ARM forwarding control

Message ID 1435843047-6327-13-git-send-email-eric.auger@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Eric Auger July 2, 2015, 1:17 p.m. UTC
- [add,del]_[consumer,producer] updated to takes both the consumer and
  producer handles. This is requested to combine info from both,
  typically to link the source irq owned by the producer with the gsi
  owned by the consumer (forwarded IRQ setup).
- new functions are added: [stop,resume]_[consumer, producer]. Those are
  needed for forwarding since the state change requires to entermingle
  actions at consumer, producer.
- On handshake, we now call connect, disconnect which features the more
  complex sequence.
- new fields are added on producer side: linux irq, vfio_device handle,
  active which reflects whether the source is active (at interrupt
  controller level or at VFIO level - automasked -) and finally an
  opaque pointer which will be used to point to the vfio_platform_device
  in this series.
- new fields on consumer side: the kvm handle, the gsi

Integration of posted interrupt series will help to refine those choices

Signed-off-by: Eric Auger <eric.auger@linaro.org>

---

- connect/disconnect could become a cb too. For forwarding it may make
  sense to have failure at connection: this would happen when the physical
  IRQ is either active at irqchip level or VFIO masked. This means some
  of the cb should return an error and this error management could be
  prod/cons specific. Where to attach the connect/disconnect cb: to the
  cons or prod, to both?
- Hence may be sensible to do the list_add only if connect returns 0
- disconnect would not be allowed to fail.
---
 include/linux/irqbypass.h | 26 ++++++++++++++++++++++---
 kernel/irq/bypass.c       | 48 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 67 insertions(+), 7 deletions(-)

Comments

Paolo Bonzini July 2, 2015, 1:40 p.m. UTC | #1
On 02/07/2015 15:17, Eric Auger wrote:
> - new fields are added on producer side: linux irq, vfio_device handle,
>   active which reflects whether the source is active (at interrupt
>   controller level or at VFIO level - automasked -) and finally an
>   opaque pointer which will be used to point to the vfio_platform_device
>   in this series.

Linux IRQ and active should be okay.  As to the vfio_device handle, you
should link it from the vfio_platform_device instead.  And for the
vfio_platform_device, you can link it from the vfio_platform_irq instead.

Once you've done this, embed the irq_bypass_producer struct in the
vfio_platform_irq struct; in the new kvm_arch_* functions, go back to
the vfio_platform_irq struct via container_of.  From there you can
retrieve pointers to the vfio_platform_device and the vfio_device.

> - new fields on consumer side: the kvm handle, the gsi

You do not need to add these.  Instead, add the kvm handle to irqfd
only.  Like above, embed the irq_bypass_consumer struct in the irqfd
struct; in the new kvm_arch_* functions, go back to the
vfio_platform_irq struct via container_of.

Paolo
Wu, Feng July 3, 2015, 2:19 a.m. UTC | #2
> -----Original Message-----
> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> Sent: Thursday, July 02, 2015 9:41 PM
> To: Eric Auger; eric.auger@st.com; linux-arm-kernel@lists.infradead.org;
> kvmarm@lists.cs.columbia.edu; kvm@vger.kernel.org;
> christoffer.dall@linaro.org; marc.zyngier@arm.com;
> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
> Wu, Feng; joro@8bytes.org; b.reynal@virtualopensystems.com
> Cc: linux-kernel@vger.kernel.org; patches@linaro.org
> Subject: Re: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
> control
> 
> 
> 
> On 02/07/2015 15:17, Eric Auger wrote:
> > - new fields are added on producer side: linux irq, vfio_device handle,
> >   active which reflects whether the source is active (at interrupt
> >   controller level or at VFIO level - automasked -) and finally an
> >   opaque pointer which will be used to point to the vfio_platform_device
> >   in this series.
> 
> Linux IRQ and active should be okay.  As to the vfio_device handle, you
> should link it from the vfio_platform_device instead.  And for the
> vfio_platform_device, you can link it from the vfio_platform_irq instead.
> 
> Once you've done this, embed the irq_bypass_producer struct in the
> vfio_platform_irq struct; in the new kvm_arch_* functions, go back to
> the vfio_platform_irq struct via container_of.  From there you can
> retrieve pointers to the vfio_platform_device and the vfio_device.
> 
> > - new fields on consumer side: the kvm handle, the gsi
> 
> You do not need to add these.  Instead, add the kvm handle to irqfd
> only.  Like above, embed the irq_bypass_consumer struct in the irqfd
> struct; in the new kvm_arch_* functions, go back to the
> vfio_platform_irq struct via container_of.
> 

I also need the gsi field here, for posted-interrupts, I need 'gsi', 'irq' to
update the IRTE.

Thanks,
Feng


> Paolo
Wu, Feng July 3, 2015, 2:24 a.m. UTC | #3
> -----Original Message-----
> From: Wu, Feng
> Sent: Friday, July 03, 2015 10:20 AM
> To: Paolo Bonzini; Eric Auger; eric.auger@st.com;
> linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
> kvm@vger.kernel.org; christoffer.dall@linaro.org; marc.zyngier@arm.com;
> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
> joro@8bytes.org; b.reynal@virtualopensystems.com
> Cc: linux-kernel@vger.kernel.org; patches@linaro.org; Wu, Feng
> Subject: RE: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
> control
> 
> 
> 
> > -----Original Message-----
> > From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> > Sent: Thursday, July 02, 2015 9:41 PM
> > To: Eric Auger; eric.auger@st.com; linux-arm-kernel@lists.infradead.org;
> > kvmarm@lists.cs.columbia.edu; kvm@vger.kernel.org;
> > christoffer.dall@linaro.org; marc.zyngier@arm.com;
> > alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
> > Wu, Feng; joro@8bytes.org; b.reynal@virtualopensystems.com
> > Cc: linux-kernel@vger.kernel.org; patches@linaro.org
> > Subject: Re: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
> > control
> >
> >
> >
> > On 02/07/2015 15:17, Eric Auger wrote:
> > > - new fields are added on producer side: linux irq, vfio_device handle,
> > >   active which reflects whether the source is active (at interrupt
> > >   controller level or at VFIO level - automasked -) and finally an
> > >   opaque pointer which will be used to point to the vfio_platform_device
> > >   in this series.
> >
> > Linux IRQ and active should be okay.  As to the vfio_device handle, you
> > should link it from the vfio_platform_device instead.  And for the
> > vfio_platform_device, you can link it from the vfio_platform_irq instead.
> >
> > Once you've done this, embed the irq_bypass_producer struct in the
> > vfio_platform_irq struct; in the new kvm_arch_* functions, go back to
> > the vfio_platform_irq struct via container_of.  From there you can
> > retrieve pointers to the vfio_platform_device and the vfio_device.
> >
> > > - new fields on consumer side: the kvm handle, the gsi
> >
> > You do not need to add these.  Instead, add the kvm handle to irqfd
> > only.  Like above, embed the irq_bypass_consumer struct in the irqfd
> > struct; in the new kvm_arch_* functions, go back to the
> > vfio_platform_irq struct via container_of.
> >
> 
> I also need the gsi field here, for posted-interrupts, I need 'gsi', 'irq' to
> update the IRTE.

Oh... we can get gsi from irq_bypass_consumer -> _irqfd -> gsi, so it
is not needed in irq_bypass_consumer. Got it! :)

Thanks,
Feng

> 
> Thanks,
> Feng
> 
> 
> > Paolo
Wu, Feng July 3, 2015, 2:43 a.m. UTC | #4
> -----Original Message-----
> From: Eric Auger [mailto:eric.auger@linaro.org]
> Sent: Thursday, July 02, 2015 9:17 PM
> To: eric.auger@st.com; eric.auger@linaro.org;
> linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
> kvm@vger.kernel.org; christoffer.dall@linaro.org; marc.zyngier@arm.com;
> alex.williamson@redhat.com; pbonzini@redhat.com; avi.kivity@gmail.com;
> mtosatti@redhat.com; Wu, Feng; joro@8bytes.org;
> b.reynal@virtualopensystems.com
> Cc: linux-kernel@vger.kernel.org; patches@linaro.org
> Subject: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding control
> 
> - [add,del]_[consumer,producer] updated to takes both the consumer and
>   producer handles. This is requested to combine info from both,
>   typically to link the source irq owned by the producer with the gsi
>   owned by the consumer (forwarded IRQ setup).
> - new functions are added: [stop,resume]_[consumer, producer]. Those are
>   needed for forwarding since the state change requires to entermingle
>   actions at consumer, producer.
> - On handshake, we now call connect, disconnect which features the more
>   complex sequence.
> - new fields are added on producer side: linux irq, vfio_device handle,
>   active which reflects whether the source is active (at interrupt
>   controller level or at VFIO level - automasked -) and finally an
>   opaque pointer which will be used to point to the vfio_platform_device
>   in this series.
> - new fields on consumer side: the kvm handle, the gsi
> 
> Integration of posted interrupt series will help to refine those choices

On PI side, I need another filed as below,

struct irq_bypass_consumer {
       struct list_head node;
       void *token;
+      unsigned irq;	/*got from producer when registered*/
       void (*add_producer)(struct irq_bypass_producer *,
                            struct irq_bypass_consumer *);
       void (*del_producer)(struct irq_bypass_producer *,
                            struct irq_bypass_consumer *);
+      void (*update)(struct irq_bypass_consumer *);
};

'update' is used to update the IRTE, while irq is initialized when
registered, which is used to find the right IRTE.

Thanks,
Feng

> 
> Signed-off-by: Eric Auger <eric.auger@linaro.org>
> 
> ---
> 
> - connect/disconnect could become a cb too. For forwarding it may make
>   sense to have failure at connection: this would happen when the physical
>   IRQ is either active at irqchip level or VFIO masked. This means some
>   of the cb should return an error and this error management could be
>   prod/cons specific. Where to attach the connect/disconnect cb: to the
>   cons or prod, to both?
> - Hence may be sensible to do the list_add only if connect returns 0
> - disconnect would not be allowed to fail.
> ---
>  include/linux/irqbypass.h | 26 ++++++++++++++++++++++---
>  kernel/irq/bypass.c       | 48
> +++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 67 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/irqbypass.h b/include/linux/irqbypass.h
> index 718508e..591ae3f 100644
> --- a/include/linux/irqbypass.h
> +++ b/include/linux/irqbypass.h
> @@ -3,17 +3,37 @@
> 
>  #include <linux/list.h>
> 
> +struct vfio_device;
> +struct irq_bypass_consumer;
> +struct kvm;
> +
>  struct irq_bypass_producer {
>  	struct list_head node;
>  	void *token;
> -	/* TBD */
> +	unsigned int irq; /* host physical irq */
> +	struct vfio_device *vdev; /* vfio device that requested irq */
> +	/* is irq active at irqchip or VFIO masked? */
> +	bool active;
> +	void *opaque;
> +	void (*stop_producer)(struct irq_bypass_producer *);
> +	void (*resume_producer)(struct irq_bypass_producer *);
> +	void (*add_consumer)(struct irq_bypass_producer *,
> +			     struct irq_bypass_consumer *);
> +	void (*del_consumer)(struct irq_bypass_producer *,
> +			     struct irq_bypass_consumer *);
>  };
> 
>  struct irq_bypass_consumer {
>  	struct list_head node;
>  	void *token;
> -	void (*add_producer)(struct irq_bypass_producer *);
> -	void (*del_producer)(struct irq_bypass_producer *);
> +	unsigned int gsi;		/* the guest gsi */
> +	struct kvm *kvm;
> +	void (*stop_consumer)(struct irq_bypass_consumer *);
> +	void (*resume_consumer)(struct irq_bypass_consumer *);
> +	void (*add_producer)(struct irq_bypass_consumer *,
> +			     struct irq_bypass_producer *);
> +	void (*del_producer)(struct irq_bypass_consumer *,
> +			     struct irq_bypass_producer *);
>  };
> 
>  int irq_bypass_register_producer(struct irq_bypass_producer *);
> diff --git a/kernel/irq/bypass.c b/kernel/irq/bypass.c
> index 5d0f92b..fb31fef 100644
> --- a/kernel/irq/bypass.c
> +++ b/kernel/irq/bypass.c
> @@ -19,6 +19,46 @@ static LIST_HEAD(producers);
>  static LIST_HEAD(consumers);
>  static DEFINE_MUTEX(lock);
> 
> +/* lock must be hold when calling connect */
> +static void connect(struct irq_bypass_producer *prod,
> +		    struct irq_bypass_consumer *cons)
> +{
> +	pr_info("++++ %s prod(%d) -> cons(%d)\n",
> +		__func__, prod->irq, cons->gsi);
> +	if (prod->stop_producer)
> +		prod->stop_producer(prod);
> +	if (cons->stop_consumer)
> +		cons->stop_consumer(cons);
> +	if (prod->add_consumer)
> +		prod->add_consumer(prod, cons);
> +	if (cons->add_producer)
> +		cons->add_producer(cons, prod);
> +	if (cons->resume_consumer)
> +		cons->resume_consumer(cons);
> +	if (prod->resume_producer)
> +		prod->resume_producer(prod);
> +}
> +
> +/* lock must be hold when calling disconnect */
> +static void disconnect(struct irq_bypass_producer *prod,
> +		       struct irq_bypass_consumer *cons)
> +{
> +	pr_info("---- %s prod(%d) -> cons(%d)\n",
> +		__func__, prod->irq, cons->gsi);
> +	if (prod->stop_producer)
> +		prod->stop_producer(prod);
> +	if (cons->stop_consumer)
> +		cons->stop_consumer(cons);
> +	if (cons->del_producer)
> +		cons->del_producer(cons, prod);
> +	if (prod->del_consumer)
> +		prod->del_consumer(prod, cons);
> +	if (cons->resume_consumer)
> +		cons->resume_consumer(cons);
> +	if (prod->resume_producer)
> +		prod->resume_producer(prod);
> +}
> +
>  int irq_bypass_register_producer(struct irq_bypass_producer *producer)
>  {
>  	struct irq_bypass_producer *tmp;
> @@ -38,7 +78,7 @@ int irq_bypass_register_producer(struct
> irq_bypass_producer *producer)
> 
>  	list_for_each_entry(consumer, &consumers, node) {
>  		if (consumer->token == producer->token) {
> -			consumer->add_producer(producer);
> +			connect(producer, consumer);
>  			break;
>  		}
>  	}
> @@ -56,7 +96,7 @@ void irq_bypass_unregister_producer(struct
> irq_bypass_producer *producer)
> 
>  	list_for_each_entry(consumer, &consumers, node) {
>  		if (consumer->token == producer->token) {
> -			consumer->del_producer(producer);
> +			disconnect(producer, consumer);
>  			break;
>  		}
>  	}
> @@ -86,7 +126,7 @@ int irq_bypass_register_consumer(struct
> irq_bypass_consumer *consumer)
> 
>  	list_for_each_entry(producer, &producers, node) {
>  		if (producer->token == consumer->token) {
> -			consumer->add_producer(producer);
> +			connect(producer, consumer);
>  			break;
>  		}
>  	}
> @@ -104,7 +144,7 @@ void irq_bypass_unregister_consumer(struct
> irq_bypass_consumer *consumer)
> 
>  	list_for_each_entry(producer, &producers, node) {
>  		if (producer->token == consumer->token) {
> -			consumer->del_producer(producer);
> +			disconnect(producer, consumer);
>  			break;
>  		}
>  	}
> --
> 1.9.1
Paolo Bonzini July 3, 2015, 6:52 a.m. UTC | #5
On 03/07/2015 04:43, Wu, Feng wrote:
> 
> struct irq_bypass_consumer {
>        struct list_head node;
>        void *token;
> +      unsigned irq;	/*got from producer when registered*/
>        void (*add_producer)(struct irq_bypass_producer *,
>                             struct irq_bypass_consumer *);
>        void (*del_producer)(struct irq_bypass_producer *,
>                             struct irq_bypass_consumer *);
> +      void (*update)(struct irq_bypass_consumer *);
> };
> 
> 'update' is used to update the IRTE, while irq is initialized when
> registered, which is used to find the right IRTE.

Feel free to add "update" in your PI patches.  I am not sure if "irq"
belongs here or in the containing struct.  You can play with both and
submit the version that looks better to you.

Paolo
Eric Auger July 3, 2015, 6:54 a.m. UTC | #6
Paolo,
On 07/03/2015 04:24 AM, Wu, Feng wrote:
> 
> 
>> -----Original Message-----
>> From: Wu, Feng
>> Sent: Friday, July 03, 2015 10:20 AM
>> To: Paolo Bonzini; Eric Auger; eric.auger@st.com;
>> linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
>> kvm@vger.kernel.org; christoffer.dall@linaro.org; marc.zyngier@arm.com;
>> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
>> joro@8bytes.org; b.reynal@virtualopensystems.com
>> Cc: linux-kernel@vger.kernel.org; patches@linaro.org; Wu, Feng
>> Subject: RE: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
>> control
>>
>>
>>
>>> -----Original Message-----
>>> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
>>> Sent: Thursday, July 02, 2015 9:41 PM
>>> To: Eric Auger; eric.auger@st.com; linux-arm-kernel@lists.infradead.org;
>>> kvmarm@lists.cs.columbia.edu; kvm@vger.kernel.org;
>>> christoffer.dall@linaro.org; marc.zyngier@arm.com;
>>> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
>>> Wu, Feng; joro@8bytes.org; b.reynal@virtualopensystems.com
>>> Cc: linux-kernel@vger.kernel.org; patches@linaro.org
>>> Subject: Re: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
>>> control
>>>
>>>
>>>
>>> On 02/07/2015 15:17, Eric Auger wrote:
>>>> - new fields are added on producer side: linux irq, vfio_device handle,
>>>>   active which reflects whether the source is active (at interrupt
>>>>   controller level or at VFIO level - automasked -) and finally an
>>>>   opaque pointer which will be used to point to the vfio_platform_device
>>>>   in this series.
>>>
>>> Linux IRQ and active should be okay.  As to the vfio_device handle, you
>>> should link it from the vfio_platform_device instead.  And for the
>>> vfio_platform_device, you can link it from the vfio_platform_irq instead.
>>>
>>> Once you've done this, embed the irq_bypass_producer struct in the
>>> vfio_platform_irq struct; in the new kvm_arch_* functions, go back to
>>> the vfio_platform_irq struct via container_of.  From there you can
>>> retrieve pointers to the vfio_platform_device and the vfio_device.
>>>
>>>> - new fields on consumer side: the kvm handle, the gsi
>>>
>>> You do not need to add these.  Instead, add the kvm handle to irqfd
>>> only.  Like above, embed the irq_bypass_consumer struct in the irqfd
>>> struct; in the new kvm_arch_* functions, go back to the
>>> vfio_platform_irq struct via container_of.
>>>
>>
>> I also need the gsi field here, for posted-interrupts, I need 'gsi', 'irq' to
>> update the IRTE.
> 
> Oh... we can get gsi from irq_bypass_consumer -> _irqfd -> gsi, so it
> is not needed in irq_bypass_consumer. Got it! :)

The issue I have is that struct _irqfd is local to eventfd.c so it
cannot be used in archi specific code. Is it acceptable to move it to
kvm_host.h, naming it something like kvm_kernel_irqfd (as done for
kvm_kernel_irq_routing_entry)? Would also need to move _irqfd_resampler
there (kvm_kernel_irqfd_resampler).

irqfd user struct cannot be used in a standalone manner since we miss
the kvm handle.

Thanks

Eric



> 
> Thanks,
> Feng
> 
>>
>> Thanks,
>> Feng
>>
>>
>>> Paolo
Wu, Feng July 3, 2015, 7 a.m. UTC | #7
> -----Original Message-----
> From: Paolo Bonzini [mailto:paolo.bonzini@gmail.com] On Behalf Of Paolo
> Bonzini
> Sent: Friday, July 03, 2015 2:52 PM
> To: Wu, Feng; Eric Auger; eric.auger@st.com;
> linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
> kvm@vger.kernel.org; christoffer.dall@linaro.org; marc.zyngier@arm.com;
> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
> joro@8bytes.org; b.reynal@virtualopensystems.com
> Cc: linux-kernel@vger.kernel.org; patches@linaro.org
> Subject: Re: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
> control
> 
> 
> 
> On 03/07/2015 04:43, Wu, Feng wrote:
> >
> > struct irq_bypass_consumer {
> >        struct list_head node;
> >        void *token;
> > +      unsigned irq;	/*got from producer when registered*/
> >        void (*add_producer)(struct irq_bypass_producer *,
> >                             struct irq_bypass_consumer *);
> >        void (*del_producer)(struct irq_bypass_producer *,
> >                             struct irq_bypass_consumer *);
> > +      void (*update)(struct irq_bypass_consumer *);
> > };
> >
> > 'update' is used to update the IRTE, while irq is initialized when
> > registered, which is used to find the right IRTE.
> 
> Feel free to add "update" in your PI patches.  I am not sure if "irq"
> belongs here or in the containing struct.  You can play with both and
> submit the version that looks better to you.

Thanks for your review, Paolo. In my understanding, irq comes from
the producer side, while gsi belongs to the consumer, so we need
to get the irq from the producer somewhere. I am not sure adding
irq here is the good way, but what I need is in the 'update' function,
I have irq, gsi in hand. :)

Thanks,
Feng

> 
> Paolo
Paolo Bonzini July 3, 2015, 7:02 a.m. UTC | #8
On 03/07/2015 08:54, Eric Auger wrote:
>> > Oh... we can get gsi from irq_bypass_consumer -> _irqfd -> gsi, so it
>> > is not needed in irq_bypass_consumer. Got it! :)
> The issue I have is that struct _irqfd is local to eventfd.c so it
> cannot be used in archi specific code. Is it acceptable to move it to
> kvm_host.h, naming it something like kvm_kernel_irqfd (as done for
> kvm_kernel_irq_routing_entry)? Would also need to move _irqfd_resampler
> there (kvm_kernel_irqfd_resampler).

Yes, that's okay.  Can you put it in a new header file kvm_irqfd.h though?

Paolo

> irqfd user struct cannot be used in a standalone manner since we miss
> the kvm handle.
Paolo Bonzini July 3, 2015, 7:06 a.m. UTC | #9
On 03/07/2015 09:00, Wu, Feng wrote:
>>> > > struct irq_bypass_consumer {
>>> > >        struct list_head node;
>>> > >        void *token;
>>> > > +      unsigned irq;	/*got from producer when registered*/
>>> > >        void (*add_producer)(struct irq_bypass_producer *,
>>> > >                             struct irq_bypass_consumer *);
>>> > >        void (*del_producer)(struct irq_bypass_producer *,
>>> > >                             struct irq_bypass_consumer *);
>>> > > +      void (*update)(struct irq_bypass_consumer *);
>>> > > };
>>> > >
>>> > > 'update' is used to update the IRTE, while irq is initialized when
>>> > > registered, which is used to find the right IRTE.
>> > 
>> > Feel free to add "update" in your PI patches.  I am not sure if "irq"
>> > belongs here or in the containing struct.  You can play with both and
>> > submit the version that looks better to you.
> Thanks for your review, Paolo. In my understanding, irq comes from
> the producer side, while gsi belongs to the consumer, so we need
> to get the irq from the producer somewhere. I am not sure adding
> irq here is the good way, but what I need is in the 'update' function,
> I have irq, gsi in hand. :)

It's difficult to say without seeing the patches...  The IRQ is stored
in the producer already with Eric's changes.  If you need to store the
old IRQ value, because "update" needs to do something with it, then I
think "irq" belongs in the container struct.

Perhaps "update" needs to have a producer argument as well?

Paolo
Paolo Bonzini July 3, 2015, 7:08 a.m. UTC | #10
On 02/07/2015 15:17, Eric Auger wrote:
> +	void (*stop_producer)(struct irq_bypass_producer *);
> +	void (*resume_producer)(struct irq_bypass_producer *);

Also, can you call these just "stop"/"resume" ...

> +	void (*add_consumer)(struct irq_bypass_producer *,
> +			     struct irq_bypass_consumer *);
> +	void (*del_consumer)(struct irq_bypass_producer *,
> +			     struct irq_bypass_consumer *);
>  };
>  
>  struct irq_bypass_consumer {
>  	struct list_head node;
>  	void *token;
> -	void (*add_producer)(struct irq_bypass_producer *);
> -	void (*del_producer)(struct irq_bypass_producer *);
> +	unsigned int gsi;		/* the guest gsi */
> +	struct kvm *kvm;
> +	void (*stop_consumer)(struct irq_bypass_consumer *);
> +	void (*resume_consumer)(struct irq_bypass_consumer *);

... and same here?  The KVM functions could be named

- kvm_arch_irq_bypass_add_producer
- kvm_arch_irq_bypass_del_producer
- kvm_arch_irq_bypass_stop
- kvm_arch_irq_bypass_resume

Paolo
Wu, Feng July 3, 2015, 7:16 a.m. UTC | #11
> -----Original Message-----
> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> Sent: Friday, July 03, 2015 3:06 PM
> To: Wu, Feng; Eric Auger; eric.auger@st.com;
> linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
> kvm@vger.kernel.org; christoffer.dall@linaro.org; marc.zyngier@arm.com;
> alex.williamson@redhat.com; avi.kivity@gmail.com; mtosatti@redhat.com;
> joro@8bytes.org; b.reynal@virtualopensystems.com
> Cc: linux-kernel@vger.kernel.org; patches@linaro.org
> Subject: Re: [RFC 12/17] irq: bypass: Extend skeleton for ARM forwarding
> control
> 
> 
> 
> On 03/07/2015 09:00, Wu, Feng wrote:
> >>> > > struct irq_bypass_consumer {
> >>> > >        struct list_head node;
> >>> > >        void *token;
> >>> > > +      unsigned irq;	/*got from producer when registered*/
> >>> > >        void (*add_producer)(struct irq_bypass_producer *,
> >>> > >                             struct irq_bypass_consumer *);
> >>> > >        void (*del_producer)(struct irq_bypass_producer *,
> >>> > >                             struct irq_bypass_consumer *);
> >>> > > +      void (*update)(struct irq_bypass_consumer *);
> >>> > > };
> >>> > >
> >>> > > 'update' is used to update the IRTE, while irq is initialized when
> >>> > > registered, which is used to find the right IRTE.
> >> >
> >> > Feel free to add "update" in your PI patches.  I am not sure if "irq"
> >> > belongs here or in the containing struct.  You can play with both and
> >> > submit the version that looks better to you.
> > Thanks for your review, Paolo. In my understanding, irq comes from
> > the producer side, while gsi belongs to the consumer, so we need
> > to get the irq from the producer somewhere. I am not sure adding
> > irq here is the good way, but what I need is in the 'update' function,
> > I have irq, gsi in hand. :)
> 
> It's difficult to say without seeing the patches...  The IRQ is stored
> in the producer already with Eric's changes.  If you need to store the
> old IRQ value, because "update" needs to do something with it, then I
> think "irq" belongs in the container struct.
> 
> Perhaps "update" needs to have a producer argument as well?

I also consider this method, basically, I will call 'update' in irqfd_update(),
but seems I need do extra things to get the producer structure (such as,
iterate the producer list to find the one with the same 'token') before
calling 'update' from consumer side. I am not sure it is worth doing
that way.

Thanks,
Feng

> 
> Paolo
Eric Auger July 3, 2015, 1:12 p.m. UTC | #12
Hi Paolo,
On 07/02/2015 03:40 PM, Paolo Bonzini wrote:
> 
> 
> On 02/07/2015 15:17, Eric Auger wrote:
>> - new fields are added on producer side: linux irq, vfio_device handle,
>>   active which reflects whether the source is active (at interrupt
>>   controller level or at VFIO level - automasked -) and finally an
>>   opaque pointer which will be used to point to the vfio_platform_device
>>   in this series.
> 
> Linux IRQ and active should be okay.  As to the vfio_device handle, you
> should link it from the vfio_platform_device instead.  And for the
> vfio_platform_device, you can link it from the vfio_platform_irq instead.
For this last one, I don't think this is achievable since if I store the
vfio_platform_irq in the opaque, it matches irqs[i] of
vfio_platform_device and I don't have any mean to retrieve "i" when
calling container_of.


	struct vfio_platform_irq *irq =
		container_of(prod, struct vfio_platform_irq, producer);
	struct vfio_platform_device *vpdev =
		container_of(irq, struct vfio_platform_device,  irqs[i?]);


struct vfio_platform_device {
../..
        struct vfio_platform_irq        *irqs;
../..
}
So I think I still need to pass vfio_platform_device in the opaque and
look on irqs array to identify the right vfio_platform_irq *.

Do I miss sthg?

- Eric


> 
> Once you've done this, embed the irq_bypass_producer struct in the
> vfio_platform_irq struct; in the new kvm_arch_* functions, go back to
> the vfio_platform_irq struct via container_of.  From there you can
> retrieve pointers to the vfio_platform_device and the vfio_device.
> 
>> - new fields on consumer side: the kvm handle, the gsi
> 
> You do not need to add these.  Instead, add the kvm handle to irqfd
> only.  Like above, embed the irq_bypass_consumer struct in the irqfd
> struct; in the new kvm_arch_* functions, go back to the
> vfio_platform_irq struct via container_of.
> 
> Paolo
>
Paolo Bonzini July 3, 2015, 5:20 p.m. UTC | #13
On 03/07/2015 15:12, Eric Auger wrote:
>> > Linux IRQ and active should be okay.  As to the vfio_device handle, you
>> > should link it from the vfio_platform_device instead.  And for the
>> > vfio_platform_device, you can link it from the vfio_platform_irq instead.
> For this last one, I don't think this is achievable since if I store the
> vfio_platform_irq in the opaque, it matches irqs[i] of
> vfio_platform_device and I don't have any mean to retrieve "i" when
> calling container_of.

Right, notice I said "link it":

	struct vfio_platform_irq *irq =
		container_of(prod, struct vfio_platform_irq, producer);
	struct vfio_platform_device *vpdev = irq->vpdev;
	struct vfio_device *vdev = vpdev->vdev;

Would this be okay?

Paolo
Eric Auger July 3, 2015, 5:23 p.m. UTC | #14
On 07/03/2015 07:20 PM, Paolo Bonzini wrote:
> 
> 
> On 03/07/2015 15:12, Eric Auger wrote:
>>>> Linux IRQ and active should be okay.  As to the vfio_device handle, you
>>>> should link it from the vfio_platform_device instead.  And for the
>>>> vfio_platform_device, you can link it from the vfio_platform_irq instead.
>> For this last one, I don't think this is achievable since if I store the
>> vfio_platform_irq in the opaque, it matches irqs[i] of
>> vfio_platform_device and I don't have any mean to retrieve "i" when
>> calling container_of.
> 
> Right, notice I said "link it":
> 
> 	struct vfio_platform_irq *irq =
> 		container_of(prod, struct vfio_platform_irq, producer);
> 	struct vfio_platform_device *vpdev = irq->vpdev;
> 	struct vfio_device *vdev = vpdev->vdev;
> 
> Would this be okay?

Yes that's what I did. I added the vfio_device handle in struct
vfio_platform_irq

Thanks ;-)

Have a nice WE

Eric
> 
> Paolo
>
diff mbox

Patch

diff --git a/include/linux/irqbypass.h b/include/linux/irqbypass.h
index 718508e..591ae3f 100644
--- a/include/linux/irqbypass.h
+++ b/include/linux/irqbypass.h
@@ -3,17 +3,37 @@ 
 
 #include <linux/list.h>
 
+struct vfio_device;
+struct irq_bypass_consumer;
+struct kvm;
+
 struct irq_bypass_producer {
 	struct list_head node;
 	void *token;
-	/* TBD */
+	unsigned int irq; /* host physical irq */
+	struct vfio_device *vdev; /* vfio device that requested irq */
+	/* is irq active at irqchip or VFIO masked? */
+	bool active;
+	void *opaque;
+	void (*stop_producer)(struct irq_bypass_producer *);
+	void (*resume_producer)(struct irq_bypass_producer *);
+	void (*add_consumer)(struct irq_bypass_producer *,
+			     struct irq_bypass_consumer *);
+	void (*del_consumer)(struct irq_bypass_producer *,
+			     struct irq_bypass_consumer *);
 };
 
 struct irq_bypass_consumer {
 	struct list_head node;
 	void *token;
-	void (*add_producer)(struct irq_bypass_producer *);
-	void (*del_producer)(struct irq_bypass_producer *);
+	unsigned int gsi;		/* the guest gsi */
+	struct kvm *kvm;
+	void (*stop_consumer)(struct irq_bypass_consumer *);
+	void (*resume_consumer)(struct irq_bypass_consumer *);
+	void (*add_producer)(struct irq_bypass_consumer *,
+			     struct irq_bypass_producer *);
+	void (*del_producer)(struct irq_bypass_consumer *,
+			     struct irq_bypass_producer *);
 };
 
 int irq_bypass_register_producer(struct irq_bypass_producer *);
diff --git a/kernel/irq/bypass.c b/kernel/irq/bypass.c
index 5d0f92b..fb31fef 100644
--- a/kernel/irq/bypass.c
+++ b/kernel/irq/bypass.c
@@ -19,6 +19,46 @@  static LIST_HEAD(producers);
 static LIST_HEAD(consumers);
 static DEFINE_MUTEX(lock);
 
+/* lock must be hold when calling connect */
+static void connect(struct irq_bypass_producer *prod,
+		    struct irq_bypass_consumer *cons)
+{
+	pr_info("++++ %s prod(%d) -> cons(%d)\n",
+		__func__, prod->irq, cons->gsi);
+	if (prod->stop_producer)
+		prod->stop_producer(prod);
+	if (cons->stop_consumer)
+		cons->stop_consumer(cons);
+	if (prod->add_consumer)
+		prod->add_consumer(prod, cons);
+	if (cons->add_producer)
+		cons->add_producer(cons, prod);
+	if (cons->resume_consumer)
+		cons->resume_consumer(cons);
+	if (prod->resume_producer)
+		prod->resume_producer(prod);
+}
+
+/* lock must be hold when calling disconnect */
+static void disconnect(struct irq_bypass_producer *prod,
+		       struct irq_bypass_consumer *cons)
+{
+	pr_info("---- %s prod(%d) -> cons(%d)\n",
+		__func__, prod->irq, cons->gsi);
+	if (prod->stop_producer)
+		prod->stop_producer(prod);
+	if (cons->stop_consumer)
+		cons->stop_consumer(cons);
+	if (cons->del_producer)
+		cons->del_producer(cons, prod);
+	if (prod->del_consumer)
+		prod->del_consumer(prod, cons);
+	if (cons->resume_consumer)
+		cons->resume_consumer(cons);
+	if (prod->resume_producer)
+		prod->resume_producer(prod);
+}
+
 int irq_bypass_register_producer(struct irq_bypass_producer *producer)
 {
 	struct irq_bypass_producer *tmp;
@@ -38,7 +78,7 @@  int irq_bypass_register_producer(struct irq_bypass_producer *producer)
 
 	list_for_each_entry(consumer, &consumers, node) {
 		if (consumer->token == producer->token) {
-			consumer->add_producer(producer);
+			connect(producer, consumer);
 			break;
 		}
 	}
@@ -56,7 +96,7 @@  void irq_bypass_unregister_producer(struct irq_bypass_producer *producer)
 
 	list_for_each_entry(consumer, &consumers, node) {
 		if (consumer->token == producer->token) {
-			consumer->del_producer(producer);
+			disconnect(producer, consumer);
 			break;
 		}
 	}
@@ -86,7 +126,7 @@  int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer)
 
 	list_for_each_entry(producer, &producers, node) {
 		if (producer->token == consumer->token) {
-			consumer->add_producer(producer);
+			connect(producer, consumer);
 			break;
 		}
 	}
@@ -104,7 +144,7 @@  void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer)
 
 	list_for_each_entry(producer, &producers, node) {
 		if (producer->token == consumer->token) {
-			consumer->del_producer(producer);
+			disconnect(producer, consumer);
 			break;
 		}
 	}