2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-18 02:04:05 +08:00

Merge branch 'pci/msi' into next

* pci/msi:
  PCI/MSI: Remove unnecessary temporary variable
  PCI/MSI: Use __write_msi_msg() instead of write_msi_msg()
  MSI/powerpc: Use __read_msi_msg() instead of read_msi_msg()
  PCI/MSI: Use __get_cached_msi_msg() instead of get_cached_msi_msg()
  PCI/MSI: Add "msi_bus" sysfs MSI/MSI-X control for endpoints
  PCI/MSI: Remove "pos" from the struct msi_desc msi_attrib
  PCI/MSI: Remove unused kobject from struct msi_desc
  PCI/MSI: Rename pci_msi_check_device() to pci_msi_supported()
  PCI/MSI: Move D0 check into pci_msi_check_device()
  PCI/MSI: Remove arch_msi_check_device()
  irqchip: armada-370-xp: Remove arch_msi_check_device()
  PCI/MSI/PPC: Remove arch_msi_check_device()

Conflicts:
	drivers/pci/host/pcie-designware.c
This commit is contained in:
Bjorn Helgaas 2014-10-01 12:31:46 -06:00
commit 359c660e99
19 changed files with 109 additions and 226 deletions

View File

@ -65,6 +65,16 @@ Description:
force a rescan of all PCI buses in the system, and force a rescan of all PCI buses in the system, and
re-discover previously removed devices. re-discover previously removed devices.
What: /sys/bus/pci/devices/.../msi_bus
Date: September 2014
Contact: Linux PCI developers <linux-pci@vger.kernel.org>
Description:
Writing a zero value to this attribute disallows MSI and
MSI-X for any future drivers of the device. If the device
is a bridge, MSI and MSI-X will be disallowed for future
drivers of all child devices under the bridge. Drivers
must be reloaded for the new setting to take effect.
What: /sys/bus/pci/devices/.../msi_irqs/ What: /sys/bus/pci/devices/.../msi_irqs/
Date: September, 2011 Date: September, 2011
Contact: Neil Horman <nhorman@tuxdriver.com> Contact: Neil Horman <nhorman@tuxdriver.com>

View File

@ -23,7 +23,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
if (irq_prepare_move(irq, cpu)) if (irq_prepare_move(irq, cpu))
return -1; return -1;
get_cached_msi_msg(irq, &msg); __get_cached_msi_msg(idata->msi_desc, &msg);
addr = msg.address_lo; addr = msg.address_lo;
addr &= MSI_ADDR_DEST_ID_MASK; addr &= MSI_ADDR_DEST_ID_MASK;

View File

@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,
* Release XIO resources for the old MSI PCI address * Release XIO resources for the old MSI PCI address
*/ */
get_cached_msi_msg(irq, &msg); __get_cached_msi_msg(data->msi_desc, &msg);
sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
pdev = sn_pdev->pdi_linux_pcidev; pdev = sn_pdev->pdi_linux_pcidev;
provider = SN_PCIDEV_BUSPROVIDER(pdev); provider = SN_PCIDEV_BUSPROVIDER(pdev);

View File

@ -73,8 +73,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
* wants. Most devices only want 1, which will give * wants. Most devices only want 1, which will give
* configured_private_bits and request_private_bits equal 0. * configured_private_bits and request_private_bits equal 0.
*/ */
pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
&control);
/* /*
* If the number of private bits has been configured then use * If the number of private bits has been configured then use
@ -176,8 +175,7 @@ msi_irq_allocated:
/* Update the number of IRQs the device has available to it */ /* Update the number of IRQs the device has available to it */
control &= ~PCI_MSI_FLAGS_QSIZE; control &= ~PCI_MSI_FLAGS_QSIZE;
control |= request_private_bits << 4; control |= request_private_bits << 4;
pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
control);
irq_set_msi_desc(irq, desc); irq_set_msi_desc(irq, desc);
write_msi_msg(irq, &msg); write_msi_msg(irq, &msg);

View File

@ -136,8 +136,6 @@ struct machdep_calls {
int (*pci_setup_phb)(struct pci_controller *host); int (*pci_setup_phb)(struct pci_controller *host);
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
int (*msi_check_device)(struct pci_dev* dev,
int nvec, int type);
int (*setup_msi_irqs)(struct pci_dev *dev, int (*setup_msi_irqs)(struct pci_dev *dev,
int nvec, int type); int nvec, int type);
void (*teardown_msi_irqs)(struct pci_dev *dev); void (*teardown_msi_irqs)(struct pci_dev *dev);

View File

@ -13,7 +13,7 @@
#include <asm/machdep.h> #include <asm/machdep.h>
int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{ {
if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) { if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
pr_debug("msi: Platform doesn't provide MSI callbacks.\n"); pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
@ -24,16 +24,6 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
if (type == PCI_CAP_ID_MSI && nvec > 1) if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1; return 1;
if (ppc_md.msi_check_device) {
pr_debug("msi: Using platform check routine.\n");
return ppc_md.msi_check_device(dev, nvec, type);
}
return 0;
}
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
return ppc_md.setup_msi_irqs(dev, nvec, type); return ppc_md.setup_msi_irqs(dev, nvec, type);
} }

View File

@ -199,14 +199,6 @@ out_error:
return msic; return msic;
} }
static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
{
if (!find_msi_translator(dev))
return -ENODEV;
return 0;
}
static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
{ {
struct device_node *dn; struct device_node *dn;
@ -416,7 +408,6 @@ static int axon_msi_probe(struct platform_device *device)
ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
ppc_md.msi_check_device = axon_msi_check_device;
axon_msi_debug_setup(dn, msic); axon_msi_debug_setup(dn, msic);

View File

@ -46,29 +46,21 @@
//#define cfg_dbg(fmt...) printk(fmt) //#define cfg_dbg(fmt...) printk(fmt)
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
{
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
struct pnv_phb *phb = hose->private_data;
struct pci_dn *pdn = pci_get_pdn(pdev);
if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
return -ENODEV;
return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV;
}
static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{ {
struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pci_controller *hose = pci_bus_to_host(pdev->bus);
struct pnv_phb *phb = hose->private_data; struct pnv_phb *phb = hose->private_data;
struct pci_dn *pdn = pci_get_pdn(pdev);
struct msi_desc *entry; struct msi_desc *entry;
struct msi_msg msg; struct msi_msg msg;
int hwirq; int hwirq;
unsigned int virq; unsigned int virq;
int rc; int rc;
if (WARN_ON(!phb)) if (WARN_ON(!phb) || !phb->msi_bmp.bitmap)
return -ENODEV;
if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
return -ENODEV; return -ENODEV;
list_for_each_entry(entry, &pdev->msi_list, list) { list_for_each_entry(entry, &pdev->msi_list, list) {
@ -860,7 +852,6 @@ void __init pnv_pci_init(void)
/* Configure MSIs */ /* Configure MSIs */
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
ppc_md.msi_check_device = pnv_msi_check_device;
ppc_md.setup_msi_irqs = pnv_setup_msi_irqs; ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs; ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
#endif #endif

View File

@ -336,26 +336,6 @@ out:
return request; return request;
} }
static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
int quota, rc;
if (type == PCI_CAP_ID_MSIX)
rc = check_req_msix(pdev, nvec);
else
rc = check_req_msi(pdev, nvec);
if (rc)
return rc;
quota = msi_quota_for_device(pdev, nvec);
if (quota && quota < nvec)
return quota;
return 0;
}
static int check_msix_entries(struct pci_dev *pdev) static int check_msix_entries(struct pci_dev *pdev)
{ {
struct msi_desc *entry; struct msi_desc *entry;
@ -397,15 +377,24 @@ static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
{ {
struct pci_dn *pdn; struct pci_dn *pdn;
int hwirq, virq, i, rc; int hwirq, virq, i, quota, rc;
struct msi_desc *entry; struct msi_desc *entry;
struct msi_msg msg; struct msi_msg msg;
int nvec = nvec_in; int nvec = nvec_in;
int use_32bit_msi_hack = 0; int use_32bit_msi_hack = 0;
pdn = pci_get_pdn(pdev); if (type == PCI_CAP_ID_MSIX)
if (!pdn) rc = check_req_msix(pdev, nvec);
return -ENODEV; else
rc = check_req_msi(pdev, nvec);
if (rc)
return rc;
quota = msi_quota_for_device(pdev, nvec);
if (quota && quota < nvec)
return quota;
if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev)) if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
return -EINVAL; return -EINVAL;
@ -416,12 +405,14 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
*/ */
if (type == PCI_CAP_ID_MSIX) { if (type == PCI_CAP_ID_MSIX) {
int m = roundup_pow_of_two(nvec); int m = roundup_pow_of_two(nvec);
int quota = msi_quota_for_device(pdev, m); quota = msi_quota_for_device(pdev, m);
if (quota >= m) if (quota >= m)
nvec = m; nvec = m;
} }
pdn = pci_get_pdn(pdev);
/* /*
* Try the new more explicit firmware interface, if that fails fall * Try the new more explicit firmware interface, if that fails fall
* back to the old interface. The old interface is known to never * back to the old interface. The old interface is known to never
@ -485,7 +476,7 @@ again:
irq_set_msi_desc(virq, entry); irq_set_msi_desc(virq, entry);
/* Read config space back so we can restore after reset */ /* Read config space back so we can restore after reset */
read_msi_msg(virq, &msg); __read_msi_msg(entry, &msg);
entry->msg = msg; entry->msg = msg;
} }
@ -526,7 +517,6 @@ static int rtas_msi_init(void)
WARN_ON(ppc_md.setup_msi_irqs); WARN_ON(ppc_md.setup_msi_irqs);
ppc_md.setup_msi_irqs = rtas_setup_msi_irqs; ppc_md.setup_msi_irqs = rtas_setup_msi_irqs;
ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs; ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs;
ppc_md.msi_check_device = rtas_msi_check_device;
WARN_ON(ppc_md.pci_irq_fixup); WARN_ON(ppc_md.pci_irq_fixup);
ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup; ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;

View File

@ -109,14 +109,6 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
return 0; return 0;
} }
static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
return 0;
}
static void fsl_teardown_msi_irqs(struct pci_dev *pdev) static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
{ {
struct msi_desc *entry; struct msi_desc *entry;
@ -173,6 +165,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
struct msi_msg msg; struct msi_msg msg;
struct fsl_msi *msi_data; struct fsl_msi *msi_data;
if (type == PCI_CAP_ID_MSIX)
pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
/* /*
* If the PCI node has an fsl,msi property, then we need to use it * If the PCI node has an fsl,msi property, then we need to use it
* to find the specific MSI. * to find the specific MSI.
@ -527,7 +522,6 @@ static int fsl_of_msi_probe(struct platform_device *dev)
if (!ppc_md.setup_msi_irqs) { if (!ppc_md.setup_msi_irqs) {
ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
ppc_md.msi_check_device = fsl_msi_check_device;
} else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) { } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
dev_err(&dev->dev, "Different MSI driver already installed!\n"); dev_err(&dev->dev, "Different MSI driver already installed!\n");
err = -ENODEV; err = -ENODEV;

View File

@ -63,14 +63,6 @@ static struct irq_chip mpic_pasemi_msi_chip = {
.name = "PASEMI-MSI", .name = "PASEMI-MSI",
}; };
static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
pr_debug("pasemi_msi: MSI-X untested, trying anyway\n");
return 0;
}
static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev) static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
{ {
struct msi_desc *entry; struct msi_desc *entry;
@ -97,6 +89,8 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
struct msi_msg msg; struct msi_msg msg;
int hwirq; int hwirq;
if (type == PCI_CAP_ID_MSIX)
pr_debug("pasemi_msi: MSI-X untested, trying anyway\n");
pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n", pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",
pdev, nvec, type); pdev, nvec, type);
@ -169,7 +163,6 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
WARN_ON(ppc_md.setup_msi_irqs); WARN_ON(ppc_md.setup_msi_irqs);
ppc_md.setup_msi_irqs = pasemi_msi_setup_msi_irqs; ppc_md.setup_msi_irqs = pasemi_msi_setup_msi_irqs;
ppc_md.teardown_msi_irqs = pasemi_msi_teardown_msi_irqs; ppc_md.teardown_msi_irqs = pasemi_msi_teardown_msi_irqs;
ppc_md.msi_check_device = pasemi_msi_check_device;
return 0; return 0;
} }

View File

@ -105,22 +105,6 @@ static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
return 0; return 0;
} }
static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
pr_debug("u3msi: MSI-X untested, trying anyway.\n");
/* If we can't find a magic address then MSI ain't gonna work */
if (find_ht_magic_addr(pdev, 0) == 0 &&
find_u4_magic_addr(pdev, 0) == 0) {
pr_debug("u3msi: no magic address found for %s\n",
pci_name(pdev));
return -ENXIO;
}
return 0;
}
static void u3msi_teardown_msi_irqs(struct pci_dev *pdev) static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
{ {
struct msi_desc *entry; struct msi_desc *entry;
@ -146,6 +130,17 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
u64 addr; u64 addr;
int hwirq; int hwirq;
if (type == PCI_CAP_ID_MSIX)
pr_debug("u3msi: MSI-X untested, trying anyway.\n");
/* If we can't find a magic address then MSI ain't gonna work */
if (find_ht_magic_addr(pdev, 0) == 0 &&
find_u4_magic_addr(pdev, 0) == 0) {
pr_debug("u3msi: no magic address found for %s\n",
pci_name(pdev));
return -ENXIO;
}
list_for_each_entry(entry, &pdev->msi_list, list) { list_for_each_entry(entry, &pdev->msi_list, list) {
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
if (hwirq < 0) { if (hwirq < 0) {
@ -202,7 +197,6 @@ int mpic_u3msi_init(struct mpic *mpic)
WARN_ON(ppc_md.setup_msi_irqs); WARN_ON(ppc_md.setup_msi_irqs);
ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs; ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs; ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
ppc_md.msi_check_device = u3msi_msi_check_device;
return 0; return 0;
} }

View File

@ -44,6 +44,12 @@ static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
int irq, hwirq; int irq, hwirq;
u64 addr; u64 addr;
/* We don't support MSI-X */
if (type == PCI_CAP_ID_MSIX) {
pr_debug("%s: MSI-X not supported.\n", __func__);
return -EINVAL;
}
list_for_each_entry(entry, &dev->msi_list, list) { list_for_each_entry(entry, &dev->msi_list, list) {
irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1); irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
if (irq < 0) { if (irq < 0) {
@ -117,17 +123,6 @@ static void hsta_teardown_msi_irqs(struct pci_dev *dev)
} }
} }
static int hsta_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
/* We don't support MSI-X */
if (type == PCI_CAP_ID_MSIX) {
pr_debug("%s: MSI-X not supported.\n", __func__);
return -EINVAL;
}
return 0;
}
static int hsta_msi_probe(struct platform_device *pdev) static int hsta_msi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -178,7 +173,6 @@ static int hsta_msi_probe(struct platform_device *pdev)
ppc_md.setup_msi_irqs = hsta_setup_msi_irqs; ppc_md.setup_msi_irqs = hsta_setup_msi_irqs;
ppc_md.teardown_msi_irqs = hsta_teardown_msi_irqs; ppc_md.teardown_msi_irqs = hsta_teardown_msi_irqs;
ppc_md.msi_check_device = hsta_msi_check_device;
return 0; return 0;
out2: out2:

View File

@ -85,8 +85,12 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
struct msi_desc *entry; struct msi_desc *entry;
struct ppc4xx_msi *msi_data = &ppc4xx_msi; struct ppc4xx_msi *msi_data = &ppc4xx_msi;
msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), dev_dbg(&dev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
GFP_KERNEL); __func__, nvec, type);
if (type == PCI_CAP_ID_MSIX)
pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL);
if (!msi_data->msi_virqs) if (!msi_data->msi_virqs)
return -ENOMEM; return -ENOMEM;
@ -134,16 +138,6 @@ void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
} }
} }
static int ppc4xx_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
dev_dbg(&pdev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
__func__, nvec, type);
if (type == PCI_CAP_ID_MSIX)
pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
return 0;
}
static int ppc4xx_setup_pcieh_hw(struct platform_device *dev, static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
struct resource res, struct ppc4xx_msi *msi) struct resource res, struct ppc4xx_msi *msi)
{ {
@ -259,7 +253,6 @@ static int ppc4xx_msi_probe(struct platform_device *dev)
ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
ppc_md.msi_check_device = ppc4xx_msi_check_device;
return err; return err;
error_out: error_out:

View File

@ -136,6 +136,10 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
struct msi_msg msg; struct msi_msg msg;
int virq, hwirq; int virq, hwirq;
/* We support MSI, but not MSI-X */
if (desc->msi_attrib.is_msix)
return -EINVAL;
hwirq = armada_370_xp_alloc_msi(); hwirq = armada_370_xp_alloc_msi();
if (hwirq < 0) if (hwirq < 0)
return hwirq; return hwirq;
@ -166,15 +170,6 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
armada_370_xp_free_msi(hwirq); armada_370_xp_free_msi(hwirq);
} }
static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev,
int nvec, int type)
{
/* We support MSI, but not MSI-X */
if (type == PCI_CAP_ID_MSI)
return 0;
return -EINVAL;
}
static struct irq_chip armada_370_xp_msi_irq_chip = { static struct irq_chip armada_370_xp_msi_irq_chip = {
.name = "armada_370_xp_msi_irq", .name = "armada_370_xp_msi_irq",
.irq_enable = unmask_msi_irq, .irq_enable = unmask_msi_irq,
@ -213,7 +208,6 @@ static int armada_370_xp_msi_init(struct device_node *node,
msi_chip->setup_irq = armada_370_xp_setup_msi_irq; msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
msi_chip->check_device = armada_370_xp_check_msi_device;
msi_chip->of_node = node; msi_chip->of_node = node;
armada_370_xp_msi_domain = armada_370_xp_msi_domain =

View File

@ -343,8 +343,7 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
struct msi_msg msg; struct msi_msg msg;
struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata); struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS, pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &msg_ctr);
&msg_ctr);
msgvec = (msg_ctr & PCI_MSI_FLAGS_QSIZE) >> 4; msgvec = (msg_ctr & PCI_MSI_FLAGS_QSIZE) >> 4;
if (msgvec == 0) if (msgvec == 0)
msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1; msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;

View File

@ -56,16 +56,6 @@ void __weak arch_teardown_msi_irq(unsigned int irq)
chip->teardown_irq(chip, irq); chip->teardown_irq(chip, irq);
} }
int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
{
struct msi_chip *chip = dev->bus->msi;
if (!chip || !chip->check_device)
return 0;
return chip->check_device(chip, dev, nvec, type);
}
int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{ {
struct msi_desc *entry; struct msi_desc *entry;
@ -130,7 +120,7 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
} }
if (entry) if (entry)
write_msi_msg(irq, &entry->msg); __write_msi_msg(entry, &entry->msg);
} }
void __weak arch_restore_msi_irqs(struct pci_dev *dev) void __weak arch_restore_msi_irqs(struct pci_dev *dev)
@ -384,17 +374,6 @@ static void free_msi_irqs(struct pci_dev *dev)
iounmap(entry->mask_base); iounmap(entry->mask_base);
} }
/*
* Its possible that we get into this path
* When populate_msi_sysfs fails, which means the entries
* were not registered with sysfs. In that case don't
* unregister them.
*/
if (entry->kobj.parent) {
kobject_del(&entry->kobj);
kobject_put(&entry->kobj);
}
list_del(&entry->list); list_del(&entry->list);
kfree(entry); kfree(entry);
} }
@ -595,7 +574,6 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
entry->msi_attrib.entry_nr = 0; entry->msi_attrib.entry_nr = 0;
entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT); entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = dev->msi_cap;
entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1; entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1;
if (control & PCI_MSI_FLAGS_64BIT) if (control & PCI_MSI_FLAGS_64BIT)
@ -699,7 +677,6 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
entry->msi_attrib.is_64 = 1; entry->msi_attrib.is_64 = 1;
entry->msi_attrib.entry_nr = entries[i].entry; entry->msi_attrib.entry_nr = entries[i].entry;
entry->msi_attrib.default_irq = dev->irq; entry->msi_attrib.default_irq = dev->irq;
entry->msi_attrib.pos = dev->msix_cap;
entry->mask_base = base; entry->mask_base = base;
list_add_tail(&entry->list, &dev->msi_list); list_add_tail(&entry->list, &dev->msi_list);
@ -806,23 +783,24 @@ out_free:
} }
/** /**
* pci_msi_check_device - check whether MSI may be enabled on a device * pci_msi_supported - check whether MSI may be enabled on a device
* @dev: pointer to the pci_dev data structure of MSI device function * @dev: pointer to the pci_dev data structure of MSI device function
* @nvec: how many MSIs have been requested ? * @nvec: how many MSIs have been requested ?
* @type: are we checking for MSI or MSI-X ?
* *
* Look at global flags, the device itself, and its parent buses * Look at global flags, the device itself, and its parent buses
* to determine if MSI/-X are supported for the device. If MSI/-X is * to determine if MSI/-X are supported for the device. If MSI/-X is
* supported return 0, else return an error code. * supported return 1, else return 0.
**/ **/
static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type) static int pci_msi_supported(struct pci_dev *dev, int nvec)
{ {
struct pci_bus *bus; struct pci_bus *bus;
int ret;
/* MSI must be globally enabled and supported by the device */ /* MSI must be globally enabled and supported by the device */
if (!pci_msi_enable || !dev || dev->no_msi) if (!pci_msi_enable)
return -EINVAL; return 0;
if (!dev || dev->no_msi || dev->current_state != PCI_D0)
return 0;
/* /*
* You can't ask to have 0 or less MSIs configured. * You can't ask to have 0 or less MSIs configured.
@ -830,7 +808,7 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
* b) the list manipulation code assumes nvec >= 1. * b) the list manipulation code assumes nvec >= 1.
*/ */
if (nvec < 1) if (nvec < 1)
return -ERANGE; return 0;
/* /*
* Any bridge which does NOT route MSI transactions from its * Any bridge which does NOT route MSI transactions from its
@ -841,13 +819,9 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
*/ */
for (bus = dev->bus; bus; bus = bus->parent) for (bus = dev->bus; bus; bus = bus->parent)
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
return -EINVAL;
ret = arch_msi_check_device(dev, nvec, type);
if (ret)
return ret;
return 0; return 0;
return 1;
} }
/** /**
@ -946,15 +920,14 @@ EXPORT_SYMBOL(pci_msix_vec_count);
**/ **/
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
{ {
int status, nr_entries; int nr_entries;
int i, j; int i, j;
if (!entries || !dev->msix_cap || dev->current_state != PCI_D0) if (!pci_msi_supported(dev, nvec))
return -EINVAL; return -EINVAL;
status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); if (!entries)
if (status) return -EINVAL;
return status;
nr_entries = pci_msix_vec_count(dev); nr_entries = pci_msix_vec_count(dev);
if (nr_entries < 0) if (nr_entries < 0)
@ -978,8 +951,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n"); dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");
return -EINVAL; return -EINVAL;
} }
status = msix_capability_init(dev, entries, nvec); return msix_capability_init(dev, entries, nvec);
return status;
} }
EXPORT_SYMBOL(pci_enable_msix); EXPORT_SYMBOL(pci_enable_msix);
@ -1062,7 +1034,7 @@ int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
int nvec; int nvec;
int rc; int rc;
if (dev->current_state != PCI_D0) if (!pci_msi_supported(dev, minvec))
return -EINVAL; return -EINVAL;
WARN_ON(!!dev->msi_enabled); WARN_ON(!!dev->msi_enabled);
@ -1085,17 +1057,6 @@ int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
else if (nvec > maxvec) else if (nvec > maxvec)
nvec = maxvec; nvec = maxvec;
do {
rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
if (rc < 0) {
return rc;
} else if (rc > 0) {
if (rc < minvec)
return -ENOSPC;
nvec = rc;
}
} while (rc);
do { do {
rc = msi_capability_init(dev, nvec); rc = msi_capability_init(dev, nvec);
if (rc < 0) { if (rc < 0) {

View File

@ -250,46 +250,45 @@ static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct pci_bus *subordinate = pdev->subordinate;
if (!pdev->subordinate) return sprintf(buf, "%u\n", subordinate ?
return 0; !(subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI)
: !pdev->no_msi);
return sprintf(buf, "%u\n",
!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
} }
static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr, static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct pci_bus *subordinate = pdev->subordinate;
unsigned long val; unsigned long val;
if (kstrtoul(buf, 0, &val) < 0) if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL; return -EINVAL;
/*
* Bad things may happen if the no_msi flag is changed
* while drivers are loaded.
*/
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
/* /*
* Maybe devices without subordinate buses shouldn't have this * "no_msi" and "bus_flags" only affect what happens when a driver
* attribute in the first place? * requests MSI or MSI-X. They don't affect any drivers that have
* already requested MSI or MSI-X.
*/ */
if (!pdev->subordinate) if (!subordinate) {
pdev->no_msi = !val;
dev_info(&pdev->dev, "MSI/MSI-X %s for future drivers\n",
val ? "allowed" : "disallowed");
return count; return count;
/* Is the flag going to change, or keep the value it already had? */
if (!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) ^
!!val) {
pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI;
dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI, bad things could happen\n",
val ? "" : " not");
} }
if (val)
subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
else
subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
dev_info(&subordinate->dev, "MSI/MSI-X %s for future drivers of devices on this bus\n",
val ? "allowed" : "disallowed");
return count; return count;
} }
static DEVICE_ATTR_RW(msi_bus); static DEVICE_ATTR_RW(msi_bus);

View File

@ -29,7 +29,6 @@ struct msi_desc {
__u8 multi_cap : 3; /* log2 num of messages supported */ __u8 multi_cap : 3; /* log2 num of messages supported */
__u8 maskbit : 1; /* mask-pending bit supported ? */ __u8 maskbit : 1; /* mask-pending bit supported ? */
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
__u8 pos; /* Location of the msi capability */
__u16 entry_nr; /* specific enabled entry */ __u16 entry_nr; /* specific enabled entry */
unsigned default_irq; /* default pre-assigned irq */ unsigned default_irq; /* default pre-assigned irq */
} msi_attrib; } msi_attrib;
@ -47,8 +46,6 @@ struct msi_desc {
/* Last set MSI message */ /* Last set MSI message */
struct msi_msg msg; struct msi_msg msg;
struct kobject kobj;
}; };
/* /*
@ -60,7 +57,6 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
void arch_teardown_msi_irq(unsigned int irq); void arch_teardown_msi_irq(unsigned int irq);
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
void arch_teardown_msi_irqs(struct pci_dev *dev); void arch_teardown_msi_irqs(struct pci_dev *dev);
int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
void arch_restore_msi_irqs(struct pci_dev *dev); void arch_restore_msi_irqs(struct pci_dev *dev);
void default_teardown_msi_irqs(struct pci_dev *dev); void default_teardown_msi_irqs(struct pci_dev *dev);
@ -77,8 +73,6 @@ struct msi_chip {
int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev, int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
struct msi_desc *desc); struct msi_desc *desc);
void (*teardown_irq)(struct msi_chip *chip, unsigned int irq); void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
int nvec, int type);
}; };
#endif /* LINUX_MSI_H */ #endif /* LINUX_MSI_H */