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:
commit
359c660e99
|
@ -65,6 +65,16 @@ Description:
|
|||
force a rescan of all PCI buses in the system, and
|
||||
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/
|
||||
Date: September, 2011
|
||||
Contact: Neil Horman <nhorman@tuxdriver.com>
|
||||
|
|
|
@ -23,7 +23,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
|
|||
if (irq_prepare_move(irq, cpu))
|
||||
return -1;
|
||||
|
||||
get_cached_msi_msg(irq, &msg);
|
||||
__get_cached_msi_msg(idata->msi_desc, &msg);
|
||||
|
||||
addr = msg.address_lo;
|
||||
addr &= MSI_ADDR_DEST_ID_MASK;
|
||||
|
|
|
@ -175,8 +175,8 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,
|
|||
* Release XIO resources for the old MSI PCI address
|
||||
*/
|
||||
|
||||
get_cached_msi_msg(irq, &msg);
|
||||
sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
|
||||
__get_cached_msi_msg(data->msi_desc, &msg);
|
||||
sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
|
||||
pdev = sn_pdev->pdi_linux_pcidev;
|
||||
provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
||||
|
||||
|
|
|
@ -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
|
||||
* configured_private_bits and request_private_bits equal 0.
|
||||
*/
|
||||
pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
|
||||
&control);
|
||||
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
control &= ~PCI_MSI_FLAGS_QSIZE;
|
||||
control |= request_private_bits << 4;
|
||||
pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
|
||||
control);
|
||||
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
|
||||
|
||||
irq_set_msi_desc(irq, desc);
|
||||
write_msi_msg(irq, &msg);
|
||||
|
|
|
@ -136,8 +136,6 @@ struct machdep_calls {
|
|||
int (*pci_setup_phb)(struct pci_controller *host);
|
||||
|
||||
#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 nvec, int type);
|
||||
void (*teardown_msi_irqs)(struct pci_dev *dev);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#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) {
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -199,14 +199,6 @@ out_error:
|
|||
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)
|
||||
{
|
||||
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.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
|
||||
ppc_md.msi_check_device = axon_msi_check_device;
|
||||
|
||||
axon_msi_debug_setup(dn, msic);
|
||||
|
||||
|
|
|
@ -46,29 +46,21 @@
|
|||
//#define cfg_dbg(fmt...) printk(fmt)
|
||||
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
struct msi_desc *entry;
|
||||
struct msi_msg msg;
|
||||
int hwirq;
|
||||
unsigned int virq;
|
||||
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;
|
||||
|
||||
list_for_each_entry(entry, &pdev->msi_list, list) {
|
||||
|
@ -860,7 +852,6 @@ void __init pnv_pci_init(void)
|
|||
|
||||
/* Configure MSIs */
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
ppc_md.msi_check_device = pnv_msi_check_device;
|
||||
ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
|
||||
ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
|
||||
#endif
|
||||
|
|
|
@ -336,26 +336,6 @@ out:
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct pci_dn *pdn;
|
||||
int hwirq, virq, i, rc;
|
||||
int hwirq, virq, i, quota, rc;
|
||||
struct msi_desc *entry;
|
||||
struct msi_msg msg;
|
||||
int nvec = nvec_in;
|
||||
int use_32bit_msi_hack = 0;
|
||||
|
||||
pdn = pci_get_pdn(pdev);
|
||||
if (!pdn)
|
||||
return -ENODEV;
|
||||
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;
|
||||
|
||||
if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
|
||||
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) {
|
||||
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)
|
||||
nvec = m;
|
||||
}
|
||||
|
||||
pdn = pci_get_pdn(pdev);
|
||||
|
||||
/*
|
||||
* Try the new more explicit firmware interface, if that fails fall
|
||||
* back to the old interface. The old interface is known to never
|
||||
|
@ -485,7 +476,7 @@ again:
|
|||
irq_set_msi_desc(virq, entry);
|
||||
|
||||
/* Read config space back so we can restore after reset */
|
||||
read_msi_msg(virq, &msg);
|
||||
__read_msi_msg(entry, &msg);
|
||||
entry->msg = msg;
|
||||
}
|
||||
|
||||
|
@ -526,7 +517,6 @@ static int rtas_msi_init(void)
|
|||
WARN_ON(ppc_md.setup_msi_irqs);
|
||||
ppc_md.setup_msi_irqs = rtas_setup_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);
|
||||
ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;
|
||||
|
|
|
@ -109,14 +109,6 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
|
|||
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)
|
||||
{
|
||||
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 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
|
||||
* 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) {
|
||||
ppc_md.setup_msi_irqs = fsl_setup_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) {
|
||||
dev_err(&dev->dev, "Different MSI driver already installed!\n");
|
||||
err = -ENODEV;
|
||||
|
|
|
@ -63,14 +63,6 @@ static struct irq_chip mpic_pasemi_msi_chip = {
|
|||
.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)
|
||||
{
|
||||
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;
|
||||
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",
|
||||
pdev, nvec, type);
|
||||
|
||||
|
@ -169,7 +163,6 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
|
|||
WARN_ON(ppc_md.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.msi_check_device = pasemi_msi_check_device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -105,22 +105,6 @@ static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
|
|||
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)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
|
@ -146,6 +130,17 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
|||
u64 addr;
|
||||
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) {
|
||||
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
|
||||
if (hwirq < 0) {
|
||||
|
@ -202,7 +197,6 @@ int mpic_u3msi_init(struct mpic *mpic)
|
|||
WARN_ON(ppc_md.setup_msi_irqs);
|
||||
ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
|
||||
ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
|
||||
ppc_md.msi_check_device = u3msi_msi_check_device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,12 @@ static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|||
int irq, hwirq;
|
||||
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) {
|
||||
irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
|
||||
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)
|
||||
{
|
||||
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.teardown_msi_irqs = hsta_teardown_msi_irqs;
|
||||
ppc_md.msi_check_device = hsta_msi_check_device;
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
|
|
|
@ -85,8 +85,12 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|||
struct msi_desc *entry;
|
||||
struct ppc4xx_msi *msi_data = &ppc4xx_msi;
|
||||
|
||||
msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int),
|
||||
GFP_KERNEL);
|
||||
dev_dbg(&dev->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");
|
||||
|
||||
msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL);
|
||||
if (!msi_data->msi_virqs)
|
||||
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,
|
||||
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.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
|
||||
ppc_md.msi_check_device = ppc4xx_msi_check_device;
|
||||
return err;
|
||||
|
||||
error_out:
|
||||
|
|
|
@ -136,6 +136,10 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
|
|||
struct msi_msg msg;
|
||||
int virq, hwirq;
|
||||
|
||||
/* We support MSI, but not MSI-X */
|
||||
if (desc->msi_attrib.is_msix)
|
||||
return -EINVAL;
|
||||
|
||||
hwirq = armada_370_xp_alloc_msi();
|
||||
if (hwirq < 0)
|
||||
return hwirq;
|
||||
|
@ -166,15 +170,6 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
|
|||
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 = {
|
||||
.name = "armada_370_xp_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->teardown_irq = armada_370_xp_teardown_msi_irq;
|
||||
msi_chip->check_device = armada_370_xp_check_msi_device;
|
||||
msi_chip->of_node = node;
|
||||
|
||||
armada_370_xp_msi_domain =
|
||||
|
|
|
@ -343,9 +343,8 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
|
|||
struct msi_msg msg;
|
||||
struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
|
||||
|
||||
pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS,
|
||||
&msg_ctr);
|
||||
msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4;
|
||||
pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &msg_ctr);
|
||||
msgvec = (msg_ctr & PCI_MSI_FLAGS_QSIZE) >> 4;
|
||||
if (msgvec == 0)
|
||||
msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;
|
||||
if (msgvec > 5)
|
||||
|
|
|
@ -56,16 +56,6 @@ void __weak arch_teardown_msi_irq(unsigned int 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)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
|
@ -130,7 +120,7 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
|
|||
}
|
||||
|
||||
if (entry)
|
||||
write_msi_msg(irq, &entry->msg);
|
||||
__write_msi_msg(entry, &entry->msg);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
|
||||
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;
|
||||
|
||||
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.entry_nr = entries[i].entry;
|
||||
entry->msi_attrib.default_irq = dev->irq;
|
||||
entry->msi_attrib.pos = dev->msix_cap;
|
||||
entry->mask_base = base;
|
||||
|
||||
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
|
||||
* @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
|
||||
* 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;
|
||||
int ret;
|
||||
|
||||
/* MSI must be globally enabled and supported by the device */
|
||||
if (!pci_msi_enable || !dev || dev->no_msi)
|
||||
return -EINVAL;
|
||||
if (!pci_msi_enable)
|
||||
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.
|
||||
|
@ -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.
|
||||
*/
|
||||
if (nvec < 1)
|
||||
return -ERANGE;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
ret = arch_msi_check_device(dev, nvec, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 status, nr_entries;
|
||||
int nr_entries;
|
||||
int i, j;
|
||||
|
||||
if (!entries || !dev->msix_cap || dev->current_state != PCI_D0)
|
||||
if (!pci_msi_supported(dev, nvec))
|
||||
return -EINVAL;
|
||||
|
||||
status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
|
||||
if (status)
|
||||
return status;
|
||||
if (!entries)
|
||||
return -EINVAL;
|
||||
|
||||
nr_entries = pci_msix_vec_count(dev);
|
||||
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");
|
||||
return -EINVAL;
|
||||
}
|
||||
status = msix_capability_init(dev, entries, nvec);
|
||||
return status;
|
||||
return msix_capability_init(dev, entries, nvec);
|
||||
}
|
||||
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 rc;
|
||||
|
||||
if (dev->current_state != PCI_D0)
|
||||
if (!pci_msi_supported(dev, minvec))
|
||||
return -EINVAL;
|
||||
|
||||
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)
|
||||
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 {
|
||||
rc = msi_capability_init(dev, nvec);
|
||||
if (rc < 0) {
|
||||
|
|
|
@ -250,46 +250,45 @@ static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct pci_bus *subordinate = pdev->subordinate;
|
||||
|
||||
if (!pdev->subordinate)
|
||||
return 0;
|
||||
|
||||
return sprintf(buf, "%u\n",
|
||||
!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
|
||||
return sprintf(buf, "%u\n", subordinate ?
|
||||
!(subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
||||
: !pdev->no_msi);
|
||||
}
|
||||
|
||||
static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct pci_bus *subordinate = pdev->subordinate;
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Bad things may happen if the no_msi flag is changed
|
||||
* while drivers are loaded.
|
||||
*/
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Maybe devices without subordinate buses shouldn't have this
|
||||
* attribute in the first place?
|
||||
* "no_msi" and "bus_flags" only affect what happens when a driver
|
||||
* 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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
static DEVICE_ATTR_RW(msi_bus);
|
||||
|
|
|
@ -29,7 +29,6 @@ struct msi_desc {
|
|||
__u8 multi_cap : 3; /* log2 num of messages supported */
|
||||
__u8 maskbit : 1; /* mask-pending bit supported ? */
|
||||
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
|
||||
__u8 pos; /* Location of the msi capability */
|
||||
__u16 entry_nr; /* specific enabled entry */
|
||||
unsigned default_irq; /* default pre-assigned irq */
|
||||
} msi_attrib;
|
||||
|
@ -47,8 +46,6 @@ struct msi_desc {
|
|||
|
||||
/* Last set MSI message */
|
||||
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);
|
||||
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
|
||||
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 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,
|
||||
struct msi_desc *desc);
|
||||
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 */
|
||||
|
|
Loading…
Reference in New Issue