Unverified Commit e9cf41a4 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3444 LoongArch: fix some pci problems

Merge Pull Request from: @ci-robot 
 
PR sync from: Hongchen Zhang <zhanghongchen@loongson.cn>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/XVFGUL47KTQ3SL2UQWERPLSG2QGVXX3F/ 
Baoqi Zhang (2):
  LS7A2000: Add quirk for OHCI device rev 0x02
  PCI: LS7A2000: fix GPU card error

Hongchen Zhang (1):
  PCI: fix kabi error caused by pm_suspend_target_state

Jianmin Lv (2):
  PCI: PM: fix pcie mrrs restoring
  PCI: LS7A2000: fix pm transition of devices under pcie port

Juxin Gao (1):
  PCI: irq: Add early_param pci_irq_limit to limit pci irq numbers

Tianli Xiong (4):
  PCI: Check if entry->offset already exist for mem resource
    access configuration space
  LoongArch: fix some PCIE card not scanning properly
  LoongArch: pci root bridige set acpi companion only when not
    acpi_disabled.

suijingfeng (1):
  PCI: fix X server auto probe fail when both ast and etnaviv drm
    present


-- 
2.33.0
 
https://gitee.com/openeuler/kernel/issues/I8H2OZ
https://gitee.com/openeuler/kernel/issues/I7AHL9
https://gitee.com/openeuler/kernel/issues/I6BWFP 
 
Link:https://gitee.com/openeuler/kernel/pulls/3444

 

Reviewed-by: default avatarJuxin Gao <gaojuxin@loongson.cn>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 070dcfd3 8c24766b
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -26,16 +26,17 @@ void pcibios_add_bus(struct pci_bus *bus)

int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{

	if (!acpi_disabled) {
		struct acpi_device *adev = NULL;
		struct device *bus_dev = &bridge->bus->dev;
		struct pci_config_window *cfg = bridge->bus->sysdata;

	if (!acpi_disabled)
		adev = to_acpi_device(cfg->parent);

		ACPI_COMPANION_SET(&bridge->dev, adev);
		set_dev_node(bus_dev, pa_to_nid(cfg->res.start));

	}
	return 0;
}

@@ -214,11 +215,13 @@ static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
	if (status > 0) {
		resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
			if (entry->res->flags & IORESOURCE_MEM) {
				if (!entry->offset) {
					entry->offset = ci->root->mcfg_addr & GENMASK_ULL(63, 40);
					entry->res->start |= entry->offset;
					entry->res->end   |= entry->offset;
				}
			}
		}
		return status;
	}

+144 −3
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/pci_ids.h>
#include <linux/pci-acpi.h>
#include <linux/pci-ecam.h>
#include <linux/vgaarb.h>

#include "../pci.h"

@@ -32,6 +33,7 @@
#define DEV_LS7A_CONF	0x7a10
#define DEV_LS7A_GNET	0x7a13
#define DEV_LS7A_EHCI	0x7a14
#define DEV_LS7A_OHCI	0x7a24
#define DEV_LS7A_DC2	0x7a36
#define DEV_LS7A_HDMI	0x7a37

@@ -80,6 +82,20 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_LPC, system_bus_quirk);

static void loongson_d3_quirk(struct pci_dev *pdev)
{
	pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
	pdev->no_d1d2 = 1;
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_PCIE_PORT3, loongson_d3_quirk);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_PCIE_PORT4, loongson_d3_quirk);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_PCIE_PORT5, loongson_d3_quirk);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_PCIE_PORT6, loongson_d3_quirk);

static void loongson_mrrs_quirk(struct pci_dev *pdev)
{
	/*
@@ -127,6 +143,98 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON,
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON,
			DEV_LS7A_HDMI, loongson_pci_pin_quirk);

static void loongson_ohci_quirk(struct pci_dev *dev)
{
	if (dev->revision == 0x2)
		dev->resource[0].start += 0x1000;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_OHCI, loongson_ohci_quirk);

static void loongson_display_quirk(struct pci_dev *dev)
{
	u32 val;
	u64 mask, size;
	u64 max_size = 0;
	int i, num;
	struct pci_bus *bus = dev->bus;

	if (!dev->bus->number) {
		if (!(dev->vendor == PCI_VENDOR_ID_LOONGSON && dev->device == 0x7a25))
			return;
	} else {
		while (!pci_is_root_bus(bus->parent))
			bus = bus->parent;

		/* ensure slot is 7a2000 */
		if (bus->self->vendor != PCI_VENDOR_ID_LOONGSON || bus->self->device < 0x7a39)
			return;
	}
	max_size = 0;
	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
		if (dev->resource[i].flags & IORESOURCE_MEM) {
			size = dev->resource[i].end - dev->resource[i].start;
			if (size > max_size) {
				max_size = size;
				num = i;
			}
		}
	}
	mask = ~(dev->resource[num].end - dev->resource[num].start);
	val = (dev->resource[num].start >> (24 - 16)) | ((mask >> 24) & 0xffff);
	writel(val, (volatile void *)0x80000efdfb000174UL);
	writel(0x80000000, (volatile void *)0x80000efdfb000170UL);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, 0x7a25, loongson_display_quirk);
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
				PCI_BASE_CLASS_DISPLAY, 16, loongson_display_quirk);

static void pci_fixup_aspeed(struct pci_dev *pdev)
{
	struct pci_dev *bridge;
	struct pci_bus *bus;
	struct pci_dev *vdevp = NULL;
	u16 config;

	bus = pdev->bus;
	bridge = bus->self;

	/* Is VGA routed to us? */
	if (bridge && (pci_is_bridge(bridge))) {
		pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &config);

		/* Yes, this bridge is PCI bridge-to-bridge spec compliant,
		 *  just return!
		 */
		if (config & PCI_BRIDGE_CTL_VGA)
			return;

		dev_warn(&pdev->dev, "VGA bridge control is not enabled\n");
	}

	/* Just return if the system already have a default device */
	if (vga_default_device())
		return;

	/* No default vga device */
	while ((vdevp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, vdevp))) {
		if (vdevp->vendor != 0x1a03) {
			/* Have other vga devcie in the system, do nothing */
			dev_info(&pdev->dev,
				"Another boot vga device: 0x%x:0x%x\n",
				vdevp->vendor, vdevp->device);
			return;
		}
	}

	vga_set_default_device(pdev);

	dev_info(&pdev->dev,
			"Boot vga device set as 0x%x:0x%x\n",
			pdev->vendor, pdev->device);
}
DECLARE_PCI_FIXUP_CLASS_FINAL(0x1a03, 0x2000,
				PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_aspeed);

static struct loongson_pci *pci_bus_to_loongson_pci(struct pci_bus *bus)
{
	struct pci_config_window *cfg;
@@ -206,6 +314,36 @@ static void __iomem *pci_loongson_map_bus(struct pci_bus *bus,
	return NULL;
}

static int pci_loongson_config_read(struct pci_bus *bus, unsigned int devfn,
			    int where, int size, u32 *val)
{
	void __iomem *addr;

	addr = bus->ops->map_bus(bus, devfn, where);
	if (!addr) {
		*val = ~0;
		return PCIBIOS_DEVICE_NOT_FOUND;
	}

	if (size == 1)
		*val = readb(addr);
	else if (size == 2)
		*val = readw(addr);
	else
		*val = readl(addr);
	/*
	 * fix some pcie card not scanning properly when bus number is
	 * inconsistent during firmware and kernel scan phases.
	 */
	if (*val == 0x0 && where == PCI_VENDOR_ID) {
		writel(*val, addr);
		*val = readl(addr);
	}


	return PCIBIOS_SUCCESSFUL;
}

#ifdef CONFIG_OF

static int loongson_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
@@ -229,7 +367,7 @@ static int loongson_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
/* LS2K/LS7A accept 8/16/32-bit PCI config operations */
static struct pci_ops loongson_pci_ops = {
	.map_bus = pci_loongson_map_bus,
	.read	= pci_generic_config_read,
	.read	= pci_loongson_config_read,
	.write	= pci_generic_config_write,
};

@@ -272,6 +410,7 @@ static int loongson_pci_probe(struct platform_device *pdev)
	struct device_node *node = dev->of_node;
	struct pci_host_bridge *bridge;
	struct resource *regs;
	unsigned int num = 0;

	if (!node)
		return -ENODEV;
@@ -296,7 +435,9 @@ static int loongson_pci_probe(struct platform_device *pdev)
	}

	if (priv->data->flags & FLAG_CFG1) {
		regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		if (priv->cfg0_base)
			num = 1;
		regs = platform_get_resource(pdev, IORESOURCE_MEM, num);
		if (!regs)
			dev_info(dev, "missing mem resource for cfg1\n");
		else {
@@ -353,7 +494,7 @@ const struct pci_ecam_ops loongson_pci_ecam_ops = {
	.init	   = loongson_pci_ecam_init,
	.pci_ops   = {
		.map_bus = pci_loongson_map_bus,
		.read	 = pci_generic_config_read,
		.read	 = pci_loongson_config_read,
		.write	 = pci_generic_config_write,
	}
};
+25 −0
Original line number Diff line number Diff line
@@ -402,12 +402,32 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,
	return ret;
}

#ifdef CONFIG_LOONGARCH
static unsigned int pci_irq_numbers = 32;

static int __init pci_irq_limit(char *str)
{
	get_option(&str, &pci_irq_numbers);

	if (pci_irq_numbers == 0)
		pci_irq_numbers = 32;
	return 0;
}

early_param("pci_irq_limit", pci_irq_limit);
#endif

int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
			   struct irq_affinity *affd)
{
	int nvec;
	int rc;

#ifdef CONFIG_LOONGARCH
	if (maxvec > 32)
		maxvec = pci_irq_numbers;
#endif

	if (!pci_msi_supported(dev, minvec) || dev->current_state != PCI_D0)
		return -EINVAL;

@@ -778,6 +798,11 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int
{
	int hwsize, rc, nvec = maxvec;

#ifdef CONFIG_LOONGARCH
	if (maxvec > 32)
		nvec = pci_irq_numbers;
#endif

	if (maxvec < minvec)
		return -ERANGE;

+18 −2
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@
#include <asm/dma.h>
#include <linux/aer.h>
#include <linux/bitfield.h>
#ifdef CONFIG_MACH_LOONGSON64
#include <linux/suspend.h>
#endif
#include "pci.h"

DEFINE_MUTEX(pci_slot_mutex);
@@ -172,6 +175,15 @@ static bool pci_bridge_d3_disable;
/* Force bridge_d3 for all PCIe ports */
static bool pci_bridge_d3_force;

#ifdef CONFIG_MACH_LOONGSON64

#ifndef CONFIG_PM_SLEEP
suspend_state_t pm_suspend_target_state;
#define pm_suspend_target_state (PM_SUSPEND_ON)
#endif

#endif

static int __init pcie_port_pm_setup(char *str)
{
	if (!strcmp(str, "off"))
@@ -6147,8 +6159,9 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
{
	u16 v;
	int ret;
#ifdef CONFIG_MACH_LOONGSON64
	struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);

#endif
	if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
		return -EINVAL;

@@ -6166,7 +6179,9 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)

	v = (ffs(rq) - 8) << 12;

	if (bridge->no_inc_mrrs) {
#ifdef CONFIG_MACH_LOONGSON64
	if (pm_suspend_target_state == PM_SUSPEND_ON &&
		bridge->no_inc_mrrs) {
		int max_mrrs = pcie_get_readrq(dev);

		if (rq > max_mrrs) {
@@ -6174,6 +6189,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
			return -EINVAL;
		}
	}
#endif

	ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
						  PCI_EXP_DEVCTL_READRQ, v);