Commit f7ce6838 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'remotes/lorenzo/pci/vmd'

- Offset client VMD MSI-X vectors (Jon Derrick)

* remotes/lorenzo/pci/vmd:
  PCI: vmd: Offset Client VMD MSI-X vectors
parents b9efb854 f6b7bb84
...@@ -54,6 +54,12 @@ enum vmd_features { ...@@ -54,6 +54,12 @@ enum vmd_features {
* vendor-specific capability space * vendor-specific capability space
*/ */
VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP = (1 << 2), VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP = (1 << 2),
/*
* 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),
}; };
/* /*
...@@ -105,6 +111,7 @@ struct vmd_dev { ...@@ -105,6 +111,7 @@ struct vmd_dev {
struct irq_domain *irq_domain; struct irq_domain *irq_domain;
struct pci_bus *bus; struct pci_bus *bus;
u8 busn_start; u8 busn_start;
u8 first_vec;
}; };
static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus) static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
...@@ -200,11 +207,11 @@ static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info, ...@@ -200,11 +207,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) static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc)
{ {
int i, best = 1;
unsigned long flags; unsigned long flags;
int i, best;
if (vmd->msix_count == 1) if (vmd->msix_count == 1 + vmd->first_vec)
return &vmd->irqs[0]; return &vmd->irqs[vmd->first_vec];
/* /*
* White list for fast-interrupt handlers. All others will share the * White list for fast-interrupt handlers. All others will share the
...@@ -214,11 +221,12 @@ static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *d ...@@ -214,11 +221,12 @@ static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *d
case PCI_CLASS_STORAGE_EXPRESS: case PCI_CLASS_STORAGE_EXPRESS:
break; break;
default: default:
return &vmd->irqs[0]; return &vmd->irqs[vmd->first_vec];
} }
raw_spin_lock_irqsave(&list_lock, flags); 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) if (vmd->irqs[i].count < vmd->irqs[best].count)
best = i; best = i;
vmd->irqs[best].count++; vmd->irqs[best].count++;
...@@ -549,8 +557,8 @@ static int vmd_alloc_irqs(struct vmd_dev *vmd) ...@@ -549,8 +557,8 @@ static int vmd_alloc_irqs(struct vmd_dev *vmd)
if (vmd->msix_count < 0) if (vmd->msix_count < 0)
return -ENODEV; return -ENODEV;
vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count, vmd->msix_count = pci_alloc_irq_vectors(dev, vmd->first_vec + 1,
PCI_IRQ_MSIX); vmd->msix_count, PCI_IRQ_MSIX);
if (vmd->msix_count < 0) if (vmd->msix_count < 0)
return vmd->msix_count; return vmd->msix_count;
...@@ -718,6 +726,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) ...@@ -718,6 +726,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) 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; struct vmd_dev *vmd;
int err; int err;
...@@ -742,13 +751,16 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -742,13 +751,16 @@ 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))) dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
return -ENODEV; return -ENODEV;
if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
vmd->first_vec = 1;
err = vmd_alloc_irqs(vmd); err = vmd_alloc_irqs(vmd);
if (err) if (err)
return err; return err;
spin_lock_init(&vmd->cfg_lock); spin_lock_init(&vmd->cfg_lock);
pci_set_drvdata(dev, vmd); pci_set_drvdata(dev, vmd);
err = vmd_enable_domain(vmd, (unsigned long) id->driver_data); err = vmd_enable_domain(vmd, features);
if (err) if (err)
return err; return err;
...@@ -817,13 +829,16 @@ static const struct pci_device_id vmd_ids[] = { ...@@ -817,13 +829,16 @@ static const struct pci_device_id vmd_ids[] = {
VMD_FEAT_HAS_BUS_RESTRICTIONS,}, VMD_FEAT_HAS_BUS_RESTRICTIONS,},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f), {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS,}, VMD_FEAT_HAS_BUS_RESTRICTIONS |
VMD_FEAT_OFFSET_FIRST_VECTOR,},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d), {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d),
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS,}, VMD_FEAT_HAS_BUS_RESTRICTIONS |
VMD_FEAT_OFFSET_FIRST_VECTOR,},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS,}, VMD_FEAT_HAS_BUS_RESTRICTIONS |
VMD_FEAT_OFFSET_FIRST_VECTOR,},
{0,} {0,}
}; };
MODULE_DEVICE_TABLE(pci, vmd_ids); MODULE_DEVICE_TABLE(pci, vmd_ids);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment