Commit 4093b006 authored by Huacai Chen's avatar Huacai Chen

Merge 'pci/enumeration' into loongarch-next

LoongArch architecture changes for 6.3 depend on the pci changes
to work well, so merge them to create a base.
parents c9c3395d 6fffbc7a
...@@ -15,9 +15,14 @@ ...@@ -15,9 +15,14 @@
#include "../pci.h" #include "../pci.h"
/* Device IDs */ /* Device IDs */
#define DEV_PCIE_PORT_0 0x7a09 #define DEV_LS2K_PCIE_PORT0 0x1a05
#define DEV_PCIE_PORT_1 0x7a19 #define DEV_LS7A_PCIE_PORT0 0x7a09
#define DEV_PCIE_PORT_2 0x7a29 #define DEV_LS7A_PCIE_PORT1 0x7a19
#define DEV_LS7A_PCIE_PORT2 0x7a29
#define DEV_LS7A_PCIE_PORT3 0x7a39
#define DEV_LS7A_PCIE_PORT4 0x7a49
#define DEV_LS7A_PCIE_PORT5 0x7a59
#define DEV_LS7A_PCIE_PORT6 0x7a69
#define DEV_LS2K_APB 0x7a02 #define DEV_LS2K_APB 0x7a02
#define DEV_LS7A_GMAC 0x7a03 #define DEV_LS7A_GMAC 0x7a03
...@@ -53,11 +58,11 @@ static void bridge_class_quirk(struct pci_dev *dev) ...@@ -53,11 +58,11 @@ static void bridge_class_quirk(struct pci_dev *dev)
dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL; dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL;
} }
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_PCIE_PORT_0, bridge_class_quirk); DEV_LS7A_PCIE_PORT0, bridge_class_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_PCIE_PORT_1, bridge_class_quirk); DEV_LS7A_PCIE_PORT1, bridge_class_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_PCIE_PORT_2, bridge_class_quirk); DEV_LS7A_PCIE_PORT2, bridge_class_quirk);
static void system_bus_quirk(struct pci_dev *pdev) static void system_bus_quirk(struct pci_dev *pdev)
{ {
...@@ -75,37 +80,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, ...@@ -75,37 +80,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_LPC, system_bus_quirk); DEV_LS7A_LPC, system_bus_quirk);
static void loongson_mrrs_quirk(struct pci_dev *dev) static void loongson_mrrs_quirk(struct pci_dev *pdev)
{ {
struct pci_bus *bus = dev->bus; /*
struct pci_dev *bridge; * Some Loongson PCIe ports have h/w limitations of maximum read
static const struct pci_device_id bridge_devids[] = { * request size. They can't handle anything larger than this. So
{ PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_0) }, * force this limit on any devices attached under these ports.
{ PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_1) }, */
{ PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_2) }, struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
{ 0, },
}; bridge->no_inc_mrrs = 1;
/* look for the matching bridge */
while (!pci_is_root_bus(bus)) {
bridge = bus->self;
bus = bus->parent;
/*
* Some Loongson PCIe ports have a h/w limitation of
* 256 bytes maximum read request size. They can't handle
* anything larger than this. So force this limit on
* any devices attached under these ports.
*/
if (pci_match_id(bridge_devids, bridge)) {
if (pcie_get_readrq(dev) > 256) {
pci_info(dev, "limiting MRRS to 256\n");
pcie_set_readrq(dev, 256);
}
break;
}
}
} }
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, loongson_mrrs_quirk); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS2K_PCIE_PORT0, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT0, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT1, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT2, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT3, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT4, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT5, loongson_mrrs_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_PCIE_PORT6, loongson_mrrs_quirk);
static void loongson_pci_pin_quirk(struct pci_dev *pdev) static void loongson_pci_pin_quirk(struct pci_dev *pdev)
{ {
......
...@@ -6026,6 +6026,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) ...@@ -6026,6 +6026,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
{ {
u16 v; u16 v;
int ret; int ret;
struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
return -EINVAL; return -EINVAL;
...@@ -6044,6 +6045,15 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) ...@@ -6044,6 +6045,15 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
v = (ffs(rq) - 8) << 12; v = (ffs(rq) - 8) << 12;
if (bridge->no_inc_mrrs) {
int max_mrrs = pcie_get_readrq(dev);
if (rq > max_mrrs) {
pci_info(dev, "can't set Max_Read_Request_Size to %d; max is %d\n", rq, max_mrrs);
return -EINVAL;
}
}
ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_READRQ, v); PCI_EXP_DEVCTL_READRQ, v);
......
...@@ -501,7 +501,6 @@ static void pcie_port_device_remove(struct pci_dev *dev) ...@@ -501,7 +501,6 @@ static void pcie_port_device_remove(struct pci_dev *dev)
{ {
device_for_each_child(&dev->dev, NULL, remove_iter); device_for_each_child(&dev->dev, NULL, remove_iter);
pci_free_irq_vectors(dev); pci_free_irq_vectors(dev);
pci_disable_device(dev);
} }
/** /**
...@@ -727,6 +726,19 @@ static void pcie_portdrv_remove(struct pci_dev *dev) ...@@ -727,6 +726,19 @@ static void pcie_portdrv_remove(struct pci_dev *dev)
} }
pcie_port_device_remove(dev); pcie_port_device_remove(dev);
pci_disable_device(dev);
}
static void pcie_portdrv_shutdown(struct pci_dev *dev)
{
if (pci_bridge_d3_possible(dev)) {
pm_runtime_forbid(&dev->dev);
pm_runtime_get_noresume(&dev->dev);
pm_runtime_dont_use_autosuspend(&dev->dev);
}
pcie_port_device_remove(dev);
} }
static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
...@@ -777,7 +789,7 @@ static struct pci_driver pcie_portdriver = { ...@@ -777,7 +789,7 @@ static struct pci_driver pcie_portdriver = {
.probe = pcie_portdrv_probe, .probe = pcie_portdrv_probe,
.remove = pcie_portdrv_remove, .remove = pcie_portdrv_remove,
.shutdown = pcie_portdrv_remove, .shutdown = pcie_portdrv_shutdown,
.err_handler = &pcie_portdrv_err_handler, .err_handler = &pcie_portdrv_err_handler,
......
...@@ -1841,6 +1841,8 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -1841,6 +1841,8 @@ int pci_setup_device(struct pci_dev *dev)
pci_set_of_node(dev); pci_set_of_node(dev);
pci_set_acpi_fwnode(dev); pci_set_acpi_fwnode(dev);
if (dev->dev.fwnode && !fwnode_device_is_available(dev->dev.fwnode))
return -ENODEV;
pci_dev_assign_slot(dev); pci_dev_assign_slot(dev);
......
...@@ -572,6 +572,7 @@ struct pci_host_bridge { ...@@ -572,6 +572,7 @@ struct pci_host_bridge {
void *release_data; void *release_data;
unsigned int ignore_reset_delay:1; /* For entire hierarchy */ unsigned int ignore_reset_delay:1; /* For entire hierarchy */
unsigned int no_ext_tags:1; /* No Extended Tags */ unsigned int no_ext_tags:1; /* No Extended Tags */
unsigned int no_inc_mrrs:1; /* No Increase MRRS */
unsigned int native_aer:1; /* OS may use PCIe AER */ unsigned int native_aer:1; /* OS may use PCIe AER */
unsigned int native_pcie_hotplug:1; /* OS may use PCIe hotplug */ unsigned int native_pcie_hotplug:1; /* OS may use PCIe hotplug */
unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */ unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */
......
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