Message ID | 20201222075121.2880892-2-vicamo.yang@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix disk probing under SATA controller behind VMD | expand |
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); >
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 --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);