diff mbox series

[1/1,SRU,G] PCI: vmd: Offset Client VMD MSI-X vectors

Message ID 20201222075121.2880892-2-vicamo.yang@canonical.com
State New
Headers show
Series Fix disk probing under SATA controller behind VMD | expand

Commit Message

You-Sheng Yang Dec. 22, 2020, 7:51 a.m. UTC
From: Jon Derrick <jonathan.derrick@intel.com>

BugLink: https://bugs.launchpad.net/bugs/1894778

Client VMD platforms have a software-triggered MSI-X vector 0 that will
not forward hardware-remapped MSI from the sub-device domain. This
causes an issue with VMD platforms that use AHCI behind VMD and have a
single MSI-X vector remapped to VMD vector 0. Add a VMD MSI-X vector
offset for these platforms.

Link: https://lore.kernel.org/r/20201102222223.92978-1-jonathan.derrick@intel.com
Tested-by: Jian-Hong Pan <jhp@endlessos.org>
Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
(backported from commit f6b7bb847ca821a8aaa1b6da10ee65311e6f15bf)
Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
---
 drivers/pci/controller/vmd.c | 37 +++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

Comments

Stefan Bader Jan. 14, 2021, 8:33 a.m. UTC | #1
On 22.12.20 08:51, You-Sheng Yang wrote:
> From: Jon Derrick <jonathan.derrick@intel.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1894778
> 
> Client VMD platforms have a software-triggered MSI-X vector 0 that will
> not forward hardware-remapped MSI from the sub-device domain. This
> causes an issue with VMD platforms that use AHCI behind VMD and have a
> single MSI-X vector remapped to VMD vector 0. Add a VMD MSI-X vector
> offset for these platforms.
> 
> Link: https://lore.kernel.org/r/20201102222223.92978-1-jonathan.derrick@intel.com
> Tested-by: Jian-Hong Pan <jhp@endlessos.org>
> Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> (backported from commit f6b7bb847ca821a8aaa1b6da10ee65311e6f15bf)
> Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  drivers/pci/controller/vmd.c | 37 +++++++++++++++++++++++++-----------
>  1 file changed, 26 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
> index ebec0a6e77ed..e03732959583 100644
> --- a/drivers/pci/controller/vmd.c
> +++ b/drivers/pci/controller/vmd.c
> @@ -47,6 +47,12 @@ enum vmd_features {
>  	 * bus numbering
>  	 */
>  	VMD_FEAT_HAS_BUS_RESTRICTIONS	= (1 << 1),
> +
> +	/*
> +	 * Device may use MSI-X vector 0 for software triggering and will not
> +	 * be used for MSI remapping
> +	 */
> +	VMD_FEAT_OFFSET_FIRST_VECTOR	= (1 << 3),
>  };
>  
>  /*
> @@ -98,6 +104,7 @@ struct vmd_dev {
>  	struct irq_domain	*irq_domain;
>  	struct pci_bus		*bus;
>  	u8			busn_start;
> +	u8			first_vec;
>  };
>  
>  static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
> @@ -193,11 +200,11 @@ static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info,
>   */
>  static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc)
>  {
> -	int i, best = 1;
>  	unsigned long flags;
> +	int i, best;
>  
> -	if (vmd->msix_count == 1)
> -		return &vmd->irqs[0];
> +	if (vmd->msix_count == 1 + vmd->first_vec)
> +		return &vmd->irqs[vmd->first_vec];
>  
>  	/*
>  	 * White list for fast-interrupt handlers. All others will share the
> @@ -207,11 +214,12 @@ static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *d
>  	case PCI_CLASS_STORAGE_EXPRESS:
>  		break;
>  	default:
> -		return &vmd->irqs[0];
> +		return &vmd->irqs[vmd->first_vec];
>  	}
>  
>  	raw_spin_lock_irqsave(&list_lock, flags);
> -	for (i = 1; i < vmd->msix_count; i++)
> +	best = vmd->first_vec + 1;
> +	for (i = best; i < vmd->msix_count; i++)
>  		if (vmd->irqs[i].count < vmd->irqs[best].count)
>  			best = i;
>  	vmd->irqs[best].count++;
> @@ -601,6 +609,7 @@ static irqreturn_t vmd_irq(int irq, void *data)
>  
>  static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  {
> +	unsigned long features = (unsigned long) id->driver_data;
>  	struct vmd_dev *vmd;
>  	int i, err;
>  
> @@ -625,12 +634,15 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  	    dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
>  		return -ENODEV;
>  
> +	if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
> +		vmd->first_vec = 1;
> +
>  	vmd->msix_count = pci_msix_vec_count(dev);
>  	if (vmd->msix_count < 0)
>  		return -ENODEV;
>  
> -	vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count,
> -					PCI_IRQ_MSIX);
> +	vmd->msix_count = pci_alloc_irq_vectors(dev, vmd->first_vec + 1,
> +					vmd->msix_count, PCI_IRQ_MSIX);
>  	if (vmd->msix_count < 0)
>  		return vmd->msix_count;
>  
> @@ -654,7 +666,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  
>  	spin_lock_init(&vmd->cfg_lock);
>  	pci_set_drvdata(dev, vmd);
> -	err = vmd_enable_domain(vmd, (unsigned long) id->driver_data);
> +	err = vmd_enable_domain(vmd, features);
>  	if (err)
>  		return err;
>  
> @@ -725,11 +737,14 @@ static const struct pci_device_id vmd_ids[] = {
>  		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
>  				VMD_FEAT_HAS_BUS_RESTRICTIONS,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{0,}
>  };
>  MODULE_DEVICE_TABLE(pci, vmd_ids);
>
William Breathitt Gray Jan. 25, 2021, 2:25 a.m. UTC | #2
On Tue, Dec 22, 2020 at 03:51:20PM +0800, You-Sheng Yang wrote:
> From: Jon Derrick <jonathan.derrick@intel.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1894778
> 
> Client VMD platforms have a software-triggered MSI-X vector 0 that will
> not forward hardware-remapped MSI from the sub-device domain. This
> causes an issue with VMD platforms that use AHCI behind VMD and have a
> single MSI-X vector remapped to VMD vector 0. Add a VMD MSI-X vector
> offset for these platforms.
> 
> Link: https://lore.kernel.org/r/20201102222223.92978-1-jonathan.derrick@intel.com
> Tested-by: Jian-Hong Pan <jhp@endlessos.org>
> Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> (backported from commit f6b7bb847ca821a8aaa1b6da10ee65311e6f15bf)
> Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>

Acked-by: William Breathitt Gray <william.gray@canonical.com>

> ---
>  drivers/pci/controller/vmd.c | 37 +++++++++++++++++++++++++-----------
>  1 file changed, 26 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
> index ebec0a6e77ed..e03732959583 100644
> --- a/drivers/pci/controller/vmd.c
> +++ b/drivers/pci/controller/vmd.c
> @@ -47,6 +47,12 @@ enum vmd_features {
>  	 * bus numbering
>  	 */
>  	VMD_FEAT_HAS_BUS_RESTRICTIONS	= (1 << 1),
> +
> +	/*
> +	 * Device may use MSI-X vector 0 for software triggering and will not
> +	 * be used for MSI remapping
> +	 */
> +	VMD_FEAT_OFFSET_FIRST_VECTOR	= (1 << 3),
>  };
>  
>  /*
> @@ -98,6 +104,7 @@ struct vmd_dev {
>  	struct irq_domain	*irq_domain;
>  	struct pci_bus		*bus;
>  	u8			busn_start;
> +	u8			first_vec;
>  };
>  
>  static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
> @@ -193,11 +200,11 @@ static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info,
>   */
>  static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc)
>  {
> -	int i, best = 1;
>  	unsigned long flags;
> +	int i, best;
>  
> -	if (vmd->msix_count == 1)
> -		return &vmd->irqs[0];
> +	if (vmd->msix_count == 1 + vmd->first_vec)
> +		return &vmd->irqs[vmd->first_vec];
>  
>  	/*
>  	 * White list for fast-interrupt handlers. All others will share the
> @@ -207,11 +214,12 @@ static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *d
>  	case PCI_CLASS_STORAGE_EXPRESS:
>  		break;
>  	default:
> -		return &vmd->irqs[0];
> +		return &vmd->irqs[vmd->first_vec];
>  	}
>  
>  	raw_spin_lock_irqsave(&list_lock, flags);
> -	for (i = 1; i < vmd->msix_count; i++)
> +	best = vmd->first_vec + 1;
> +	for (i = best; i < vmd->msix_count; i++)
>  		if (vmd->irqs[i].count < vmd->irqs[best].count)
>  			best = i;
>  	vmd->irqs[best].count++;
> @@ -601,6 +609,7 @@ static irqreturn_t vmd_irq(int irq, void *data)
>  
>  static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  {
> +	unsigned long features = (unsigned long) id->driver_data;
>  	struct vmd_dev *vmd;
>  	int i, err;
>  
> @@ -625,12 +634,15 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  	    dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
>  		return -ENODEV;
>  
> +	if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
> +		vmd->first_vec = 1;
> +
>  	vmd->msix_count = pci_msix_vec_count(dev);
>  	if (vmd->msix_count < 0)
>  		return -ENODEV;
>  
> -	vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count,
> -					PCI_IRQ_MSIX);
> +	vmd->msix_count = pci_alloc_irq_vectors(dev, vmd->first_vec + 1,
> +					vmd->msix_count, PCI_IRQ_MSIX);
>  	if (vmd->msix_count < 0)
>  		return vmd->msix_count;
>  
> @@ -654,7 +666,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  
>  	spin_lock_init(&vmd->cfg_lock);
>  	pci_set_drvdata(dev, vmd);
> -	err = vmd_enable_domain(vmd, (unsigned long) id->driver_data);
> +	err = vmd_enable_domain(vmd, features);
>  	if (err)
>  		return err;
>  
> @@ -725,11 +737,14 @@ static const struct pci_device_id vmd_ids[] = {
>  		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
>  				VMD_FEAT_HAS_BUS_RESTRICTIONS,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
> -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
> +		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
> +			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
>  	{0,}
>  };
>  MODULE_DEVICE_TABLE(pci, vmd_ids);
> -- 
> 2.29.2
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff mbox series

Patch

diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index ebec0a6e77ed..e03732959583 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -47,6 +47,12 @@  enum vmd_features {
 	 * bus numbering
 	 */
 	VMD_FEAT_HAS_BUS_RESTRICTIONS	= (1 << 1),
+
+	/*
+	 * Device may use MSI-X vector 0 for software triggering and will not
+	 * be used for MSI remapping
+	 */
+	VMD_FEAT_OFFSET_FIRST_VECTOR	= (1 << 3),
 };
 
 /*
@@ -98,6 +104,7 @@  struct vmd_dev {
 	struct irq_domain	*irq_domain;
 	struct pci_bus		*bus;
 	u8			busn_start;
+	u8			first_vec;
 };
 
 static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
@@ -193,11 +200,11 @@  static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info,
  */
 static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc)
 {
-	int i, best = 1;
 	unsigned long flags;
+	int i, best;
 
-	if (vmd->msix_count == 1)
-		return &vmd->irqs[0];
+	if (vmd->msix_count == 1 + vmd->first_vec)
+		return &vmd->irqs[vmd->first_vec];
 
 	/*
 	 * White list for fast-interrupt handlers. All others will share the
@@ -207,11 +214,12 @@  static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *d
 	case PCI_CLASS_STORAGE_EXPRESS:
 		break;
 	default:
-		return &vmd->irqs[0];
+		return &vmd->irqs[vmd->first_vec];
 	}
 
 	raw_spin_lock_irqsave(&list_lock, flags);
-	for (i = 1; i < vmd->msix_count; i++)
+	best = vmd->first_vec + 1;
+	for (i = best; i < vmd->msix_count; i++)
 		if (vmd->irqs[i].count < vmd->irqs[best].count)
 			best = i;
 	vmd->irqs[best].count++;
@@ -601,6 +609,7 @@  static irqreturn_t vmd_irq(int irq, void *data)
 
 static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	unsigned long features = (unsigned long) id->driver_data;
 	struct vmd_dev *vmd;
 	int i, err;
 
@@ -625,12 +634,15 @@  static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	    dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
 		return -ENODEV;
 
+	if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
+		vmd->first_vec = 1;
+
 	vmd->msix_count = pci_msix_vec_count(dev);
 	if (vmd->msix_count < 0)
 		return -ENODEV;
 
-	vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count,
-					PCI_IRQ_MSIX);
+	vmd->msix_count = pci_alloc_irq_vectors(dev, vmd->first_vec + 1,
+					vmd->msix_count, PCI_IRQ_MSIX);
 	if (vmd->msix_count < 0)
 		return vmd->msix_count;
 
@@ -654,7 +666,7 @@  static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	spin_lock_init(&vmd->cfg_lock);
 	pci_set_drvdata(dev, vmd);
-	err = vmd_enable_domain(vmd, (unsigned long) id->driver_data);
+	err = vmd_enable_domain(vmd, features);
 	if (err)
 		return err;
 
@@ -725,11 +737,14 @@  static const struct pci_device_id vmd_ids[] = {
 		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
 				VMD_FEAT_HAS_BUS_RESTRICTIONS,},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
-		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
+		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
+			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d),
-		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
+		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
+			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
-		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
+		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS |
+			       VMD_FEAT_OFFSET_FIRST_VECTOR,},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, vmd_ids);