All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Levi, Ilia" <ilia.levi@intel.com>
To: "Piotr Piórkowski" <piotr.piorkowski@intel.com>
Cc: <intel-xe@lists.freedesktop.org>,
	<niranjana.vishwanathapura@intel.com>, <koby.elbaz@intel.com>,
	<yaron.avizrat@intel.com>
Subject: Re: [PATCH v5 2/5] drm/xe/irq: Separate MSI and MSI-X flows
Date: Tue, 3 Dec 2024 11:04:14 +0200	[thread overview]
Message-ID: <42cd338d-2b71-4793-90c8-eafa2a4a96e8@intel.com> (raw)
In-Reply-To: <20241202185918.bdz2oz4y3u3voklg@intel.com>

[-- Attachment #1: Type: text/plain, Size: 13409 bytes --]

On 02/12/2024 20:59, Piotr Piórkowski wrote:
> Ilia Levi <ilia.levi@intel.com> wrote on czw [2024-lis-28 14:53:42 +0200]:
>> A new flow is added for devices that support MSI-X:
>> - MSI-X vector 0 is used for GuC-to-host interrupt
>> - MSI-X vector 1 (aka default MSI-X) is used for HW engines
>>
>> The default MSI-X will be passed to the HW engines in a subsequent
>> patch.
>>
>> Signed-off-by: Ilia Levi <ilia.levi@intel.com>
>> ---
>>  drivers/gpu/drm/xe/xe_device.c       |   4 +-
>>  drivers/gpu/drm/xe/xe_device.h       |   3 +-
>>  drivers/gpu/drm/xe/xe_device_types.h |   6 +
>>  drivers/gpu/drm/xe/xe_irq.c          | 257 +++++++++++++++++++++++----
>>  drivers/gpu/drm/xe/xe_irq.h          |   3 +
>>  5 files changed, 237 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
>> index 930bb2750e2e..f1246fa8b5cc 100644
>> --- a/drivers/gpu/drm/xe/xe_device.c
>> +++ b/drivers/gpu/drm/xe/xe_device.c
>> @@ -325,7 +325,9 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
>>  	xe->info.revid = pdev->revision;
>>  	xe->info.force_execlist = xe_modparam.force_execlist;
>>  
>> -	spin_lock_init(&xe->irq.lock);
>> +	err = xe_irq_init(xe);
>> +	if (err)
>> +		goto err;
>>  
>>  	init_waitqueue_head(&xe->ufence_wq);
>>  
>> diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
>> index f1fbfe916867..fc3c2af3fb7f 100644
>> --- a/drivers/gpu/drm/xe/xe_device.h
>> +++ b/drivers/gpu/drm/xe/xe_device.h
>> @@ -157,8 +157,7 @@ static inline bool xe_device_has_sriov(struct xe_device *xe)
>>  
>>  static inline bool xe_device_has_msix(struct xe_device *xe)
>>  {
> I still think you should use the name xe_device_use_msix.
>
> We use xe_device_has_* in case, when the capability based on Platform
> version (for example xe_device_has_memirq) based on intel_device_info
> (for example xe_device_has_sriov or xe_device_has_flat_css).
>
> IMO in case you are basing it on a variable that you set yourself in init you should use
> a different name (for example with “uses” instead of “has”)
>
> My motivation is that for me xe_device_has-* is used when it is the capability of a given device
> and we base on the information that intel_device_info or infromation about the platform version
> provides us with.

As we discussed, it is akin to xe_device_has_flat_ccs - where xe->info.has_flat_ccs is set by probe_has_flat_ccs.
xe->irq.msix.nvec is set according to pci_msix_vec_count which reads MSI-X capability from the PCI.

>> -	/* TODO: change this when MSI-X support is fully integrated */
>> -	return false;
>> +	return xe->irq.msix.nvec > 0;
>>  }
>>  
>>  static inline bool xe_device_has_memirq(struct xe_device *xe)
>> diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
>> index 7ee114c17552..ed638067aa26 100644
>> --- a/drivers/gpu/drm/xe/xe_device_types.h
>> +++ b/drivers/gpu/drm/xe/xe_device_types.h
>> @@ -348,6 +348,12 @@ struct xe_device {
>>  
>>  		/** @irq.enabled: interrupts enabled on this device */
>>  		atomic_t enabled;
>> +
>> +		/** @irq.msix: irq info for platforms that support MSI-X */
>> +		struct {
>> +			/** @irq.msix.nvec: number of MSI-X interrupts */
>> +			u16 nvec;
>> +		} msix;
>>  	} irq;
>>  
>>  	/** @ttm: ttm device */
>> diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
>> index 1c509e66694d..b8a0b9bbf24c 100644
>> --- a/drivers/gpu/drm/xe/xe_irq.c
>> +++ b/drivers/gpu/drm/xe/xe_irq.c
>> @@ -10,6 +10,7 @@
>>  #include <drm/drm_managed.h>
>>  
>>  #include "display/xe_display.h"
>> +#include "regs/xe_guc_regs.h"
> I don't see why you are adding this header

GUC_INTR_GUC2HOST is defined there. It was not needed before as it was called by gt_other_irq_handler (the type of the interrupt was read from the registers).
For MSI-X those registers are no longer set - and the only type of interrupt we expect on MSI-X vector 0 is guc-to-host.

>
> Thanks,
> Piotr
>>  #include "regs/xe_irq_regs.h"
>>  #include "xe_device.h"
>>  #include "xe_drv.h"
>> @@ -29,6 +30,11 @@
>>  #define IIR(offset)				XE_REG(offset + 0x8)
>>  #define IER(offset)				XE_REG(offset + 0xc)
>>  
>> +static int xe_irq_msix_init(struct xe_device *xe);
>> +static void xe_irq_msix_free(struct xe_device *xe);
>> +static int xe_irq_msix_request_irqs(struct xe_device *xe);
>> +static void xe_irq_msix_synchronize_irq(struct xe_device *xe);
>> +
>>  static void assert_iir_is_zero(struct xe_mmio *mmio, struct xe_reg reg)
>>  {
>>  	u32 val = xe_mmio_read32(mmio, reg);
>> @@ -572,6 +578,11 @@ static void xe_irq_reset(struct xe_device *xe)
>>  	if (IS_SRIOV_VF(xe))
>>  		return vf_irq_reset(xe);
>>  
>> +	if (xe_device_uses_memirq(xe)) {
>> +		for_each_tile(tile, xe, id)
>> +			xe_memirq_reset(&tile->memirq);
>> +	}
>> +
>>  	for_each_tile(tile, xe, id) {
>>  		if (GRAPHICS_VERx100(xe) >= 1210)
>>  			dg1_irq_reset(tile);
>> @@ -614,6 +625,14 @@ static void xe_irq_postinstall(struct xe_device *xe)
>>  	if (IS_SRIOV_VF(xe))
>>  		return vf_irq_postinstall(xe);
>>  
>> +	if (xe_device_uses_memirq(xe)) {
>> +		struct xe_tile *tile;
>> +		unsigned int id;
>> +
>> +		for_each_tile(tile, xe, id)
>> +			xe_memirq_postinstall(&tile->memirq);
>> +	}
>> +
>>  	xe_display_irq_postinstall(xe, xe_root_mmio_gt(xe));
>>  
>>  	/*
>> @@ -656,60 +675,83 @@ static irq_handler_t xe_irq_handler(struct xe_device *xe)
>>  		return xelp_irq_handler;
>>  }
>>  
>> -static void irq_uninstall(void *arg)
>> +static int xe_irq_msi_request_irqs(struct xe_device *xe)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> +	irq_handler_t irq_handler;
>> +	int irq, err;
>> +
>> +	irq_handler = xe_irq_handler(xe);
>> +	if (!irq_handler) {
>> +		drm_err(&xe->drm, "No supported interrupt handler");
>> +		return -EINVAL;
>> +	}
>> +
>> +	irq = pci_irq_vector(pdev, 0);
>> +	err = request_irq(irq, irq_handler, IRQF_SHARED, DRIVER_NAME, xe);
>> +	if (err < 0) {
>> +		drm_err(&xe->drm, "Failed to request MSI IRQ %d\n", err);
>> +		return err;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void xe_irq_msi_free(struct xe_device *xe)
>>  {
>> -	struct xe_device *xe = arg;
>>  	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>>  	int irq;
>>  
>> +	irq = pci_irq_vector(pdev, 0);
>> +	free_irq(irq, xe);
>> +}
>> +
>> +static void irq_uninstall(void *arg)
>> +{
>> +	struct xe_device *xe = arg;
>> +
>>  	if (!atomic_xchg(&xe->irq.enabled, 0))
>>  		return;
>>  
>>  	xe_irq_reset(xe);
>>  
>> -	irq = pci_irq_vector(pdev, 0);
>> -	free_irq(irq, xe);
>> +	if (xe_device_has_msix(xe))
>> +		xe_irq_msix_free(xe);
>> +	else
>> +		xe_irq_msi_free(xe);
>> +}
>> +
>> +int xe_irq_init(struct xe_device *xe)
>> +{
>> +	spin_lock_init(&xe->irq.lock);
>> +
>> +	return xe_irq_msix_init(xe);
>>  }
>>  
>>  int xe_irq_install(struct xe_device *xe)
>>  {
>>  	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> -	unsigned int irq_flags = PCI_IRQ_MSIX;
>> -	irq_handler_t irq_handler;
>> -	int err, irq, nvec;
>> -
>> -	irq_handler = xe_irq_handler(xe);
>> -	if (!irq_handler) {
>> -		drm_err(&xe->drm, "No supported interrupt handler");
>> -		return -EINVAL;
>> -	}
>> +	unsigned int irq_flags = PCI_IRQ_MSI;
>> +	int nvec = 1;
>> +	int err;
>>  
>>  	xe_irq_reset(xe);
>>  
>> -	nvec = pci_msix_vec_count(pdev);
>> -	if (nvec <= 0) {
>> -		if (nvec == -EINVAL) {
>> -			/* MSIX capability is not supported in the device, using MSI */
>> -			irq_flags = PCI_IRQ_MSI;
>> -			nvec = 1;
>> -		} else {
>> -			drm_err(&xe->drm, "MSIX: Failed getting count\n");
>> -			return nvec;
>> -		}
>> +	if (xe_device_has_msix(xe)) {
>> +		nvec = xe->irq.msix.nvec;
>> +		irq_flags = PCI_IRQ_MSIX;
>>  	}
>>  
>>  	err = pci_alloc_irq_vectors(pdev, nvec, nvec, irq_flags);
>>  	if (err < 0) {
>> -		drm_err(&xe->drm, "MSI/MSIX: Failed to enable support %d\n", err);
>> +		drm_err(&xe->drm, "Failed to allocate IRQ vectors: %d\n", err);
>>  		return err;
>>  	}
>>  
>> -	irq = pci_irq_vector(pdev, 0);
>> -	err = request_irq(irq, irq_handler, IRQF_SHARED, DRIVER_NAME, xe);
>> -	if (err < 0) {
>> -		drm_err(&xe->drm, "Failed to request MSI/MSIX IRQ %d\n", err);
>> +	err = xe_device_has_msix(xe) ? xe_irq_msix_request_irqs(xe) :
>> +					xe_irq_msi_request_irqs(xe);
>> +	if (err)
>>  		return err;
>> -	}
>>  
>>  	atomic_set(&xe->irq.enabled, 1);
>>  
>> @@ -722,18 +764,28 @@ int xe_irq_install(struct xe_device *xe)
>>  	return 0;
>>  
>>  free_irq_handler:
>> -	free_irq(irq, xe);
>> +	if (xe_device_has_msix(xe))
>> +		xe_irq_msix_free(xe);
>> +	else
>> +		xe_irq_msi_free(xe);
>>  
>>  	return err;
>>  }
>>  
>> -void xe_irq_suspend(struct xe_device *xe)
>> +static void xe_irq_msi_synchronize_irq(struct xe_device *xe)
>>  {
>> -	int irq = to_pci_dev(xe->drm.dev)->irq;
>> +	synchronize_irq(to_pci_dev(xe->drm.dev)->irq);
>> +}
>>  
>> +void xe_irq_suspend(struct xe_device *xe)
>> +{
>>  	atomic_set(&xe->irq.enabled, 0); /* no new irqs */
>>  
>> -	synchronize_irq(irq); /* flush irqs */
>> +	/* flush irqs */
>> +	if (xe_device_has_msix(xe))
>> +		xe_irq_msix_synchronize_irq(xe);
>> +	else
>> +		xe_irq_msi_synchronize_irq(xe);
>>  	xe_irq_reset(xe); /* turn irqs off */
>>  }
>>  
>> @@ -754,3 +806,142 @@ void xe_irq_resume(struct xe_device *xe)
>>  	for_each_gt(gt, xe, id)
>>  		xe_irq_enable_hwe(gt);
>>  }
>> +
>> +/* MSI-X related definitions and functions below. */
>> +
>> +enum xe_irq_msix_static {
>> +	GUC2HOST_MSIX = 0,
>> +	DEFAULT_MSIX = XE_IRQ_DEFAULT_MSIX,
>> +	/* Must be last */
>> +	NUM_OF_STATIC_MSIX,
>> +};
>> +
>> +static int xe_irq_msix_init(struct xe_device *xe)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> +	int nvec = pci_msix_vec_count(pdev);
>> +
>> +	if (nvec == -EINVAL)
>> +		return 0;  /* MSI */
>> +
>> +	if (nvec < 0) {
>> +		drm_err(&xe->drm, "Failed getting MSI-X vectors count: %d\n", nvec);
>> +		return nvec;
>> +	}
>> +
>> +	xe->irq.msix.nvec = nvec;
>> +	return 0;
>> +}
>> +
>> +static irqreturn_t guc2host_irq_handler(int irq, void *arg)
>> +{
>> +	struct xe_device *xe = arg;
>> +	struct xe_tile *tile;
>> +	u8 id;
>> +
>> +	if (!atomic_read(&xe->irq.enabled))
>> +		return IRQ_NONE;
>> +
>> +	for_each_tile(tile, xe, id)
>> +		xe_guc_irq_handler(&tile->primary_gt->uc.guc,
>> +				   GUC_INTR_GUC2HOST);
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg)
>> +{
>> +	unsigned int tile_id, gt_id;
>> +	struct xe_device *xe = arg;
>> +	struct xe_memirq *memirq;
>> +	struct xe_hw_engine *hwe;
>> +	enum xe_hw_engine_id id;
>> +	struct xe_tile *tile;
>> +	struct xe_gt *gt;
>> +
>> +	if (!atomic_read(&xe->irq.enabled))
>> +		return IRQ_NONE;
>> +
>> +	for_each_tile(tile, xe, tile_id) {
>> +		memirq = &tile->memirq;
>> +		if (!memirq->bo)
>> +			continue;
>> +
>> +		for_each_gt(gt, xe, gt_id) {
>> +			if (gt->tile != tile)
>> +				continue;
>> +
>> +			for_each_hw_engine(hwe, gt, id)
>> +				xe_memirq_hwe_handler(memirq, hwe);
>> +		}
>> +	}
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static int xe_irq_msix_request_irq(struct xe_device *xe, irq_handler_t handler,
>> +				   const char *name, u16 msix)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> +	int ret, irq;
>> +
>> +	irq = pci_irq_vector(pdev, msix);
>> +	if (irq < 0)
>> +		return irq;
>> +
>> +	ret = request_irq(irq, handler, IRQF_SHARED, name, xe);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static void xe_irq_msix_free_irq(struct xe_device *xe, u16 msix)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> +	int irq;
>> +
>> +	irq = pci_irq_vector(pdev, msix);
>> +	if (irq < 0) {
>> +		drm_err(&xe->drm, "MSI-X %u can't be released, there is no matching IRQ\n", msix);
>> +		return;
>> +	}
>> +
>> +	free_irq(irq, xe);
>> +}
>> +
>> +static int xe_irq_msix_request_irqs(struct xe_device *xe)
>> +{
>> +	int err;
>> +
>> +	err = xe_irq_msix_request_irq(xe, guc2host_irq_handler,
>> +				      DRIVER_NAME "-guc2host", GUC2HOST_MSIX);
>> +	if (err) {
>> +		drm_err(&xe->drm, "Failed to request MSI-X IRQ %d: %d\n", GUC2HOST_MSIX, err);
>> +		return err;
>> +	}
>> +
>> +	err = xe_irq_msix_request_irq(xe, xe_irq_msix_default_hwe_handler,
>> +				      DRIVER_NAME "-default-msix", DEFAULT_MSIX);
>> +	if (err) {
>> +		drm_err(&xe->drm, "Failed to request MSI-X IRQ %d: %d\n", DEFAULT_MSIX, err);
>> +		xe_irq_msix_free_irq(xe, GUC2HOST_MSIX);
>> +		return err;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void xe_irq_msix_free(struct xe_device *xe)
>> +{
>> +	xe_irq_msix_free_irq(xe, GUC2HOST_MSIX);
>> +	xe_irq_msix_free_irq(xe, DEFAULT_MSIX);
>> +}
>> +
>> +static void xe_irq_msix_synchronize_irq(struct xe_device *xe)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>> +
>> +	synchronize_irq(pci_irq_vector(pdev, GUC2HOST_MSIX));
>> +	synchronize_irq(pci_irq_vector(pdev, DEFAULT_MSIX));
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_irq.h b/drivers/gpu/drm/xe/xe_irq.h
>> index 067514e13675..24ff16111b96 100644
>> --- a/drivers/gpu/drm/xe/xe_irq.h
>> +++ b/drivers/gpu/drm/xe/xe_irq.h
>> @@ -6,10 +6,13 @@
>>  #ifndef _XE_IRQ_H_
>>  #define _XE_IRQ_H_
>>  
>> +#define XE_IRQ_DEFAULT_MSIX 1
>> +
>>  struct xe_device;
>>  struct xe_tile;
>>  struct xe_gt;
>>  
>> +int xe_irq_init(struct xe_device *xe);
>>  int xe_irq_install(struct xe_device *xe);
>>  void xe_irq_suspend(struct xe_device *xe);
>>  void xe_irq_resume(struct xe_device *xe);
>> -- 
>> 2.43.2
>>

[-- Attachment #2: Type: text/html, Size: 13934 bytes --]

  reply	other threads:[~2024-12-03  9:04 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-28 12:53 [PATCH v5 0/5] MSI-X support Ilia Levi
2024-11-28 12:53 ` [PATCH v5 1/5] drm/xe: Make irq enabled flag atomic Ilia Levi
2024-12-02 18:32   ` Piotr Piórkowski
2024-12-03 11:47     ` Levi, Ilia
2024-12-05 17:24       ` Rodrigo Vivi
2024-11-28 12:53 ` [PATCH v5 2/5] drm/xe/irq: Separate MSI and MSI-X flows Ilia Levi
2024-12-02 18:59   ` Piotr Piórkowski
2024-12-03  9:04     ` Levi, Ilia [this message]
2024-12-05  8:35       ` Piotr Piórkowski
2024-11-28 12:53 ` [PATCH v5 3/5] drm/xe: Initial MSI-X support for HW engines Ilia Levi
2024-12-02 19:15   ` Piotr Piórkowski
2024-11-28 12:53 ` [PATCH v5 4/5] drm/xe/irq: Manage MSI-X interrupts allocation Ilia Levi
2024-12-05  9:07   ` Piotr Piórkowski
2024-11-28 12:53 ` [PATCH v5 5/5] drm/xe/uapi: Support requesting unique MSI-X for exec queue Ilia Levi
2024-12-05  9:00   ` Piotr Piórkowski
2024-11-28 13:01 ` ✓ CI.Patch_applied: success for MSI-X support Patchwork
2024-11-28 13:01 ` ✓ CI.checkpatch: " Patchwork
2024-11-28 13:03 ` ✓ CI.KUnit: " Patchwork
2024-11-28 13:20 ` ✓ CI.Build: " Patchwork
2024-11-28 13:23 ` ✓ CI.Hooks: " Patchwork
2024-11-28 13:24 ` ✓ CI.checksparse: " Patchwork
2024-11-28 13:42 ` ✓ Xe.CI.BAT: " Patchwork
2024-11-28 15:39 ` ✗ Xe.CI.Full: failure " Patchwork
2024-12-13  7:25 ` [PATCH v6 0/4] " Ilia Levi
2024-12-13  7:25 ` [PATCH v6 1/4] drm/xe/irq: Separate MSI and MSI-X flows Ilia Levi
2024-12-13  7:25 ` [PATCH v6 2/4] drm/xe: Initial MSI-X support for HW engines Ilia Levi
2024-12-13  7:25 ` [PATCH v6 3/4] drm/xe/irq: Manage MSI-X interrupts allocation Ilia Levi
2024-12-13  7:25 ` [PATCH v6 4/4] drm/xe/uapi: Support requesting unique MSI-X for exec queue Ilia Levi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=42cd338d-2b71-4793-90c8-eafa2a4a96e8@intel.com \
    --to=ilia.levi@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=koby.elbaz@intel.com \
    --cc=niranjana.vishwanathapura@intel.com \
    --cc=piotr.piorkowski@intel.com \
    --cc=yaron.avizrat@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.