Loading drivers/pci/controller/pci-loongson.c +36 −35 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ #include "../pci.h" /* Device IDs */ #define DEV_PCIE_PORT_0 0x7a09 #define DEV_PCIE_PORT_1 0x7a19 #define DEV_PCIE_PORT_2 0x7a29 #define DEV_LS2K_PCIE_PORT0 0x1a05 #define DEV_LS7A_PCIE_PORT0 0x7a09 #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_LS7A_GMAC 0x7a03 Loading Loading @@ -53,11 +58,11 @@ static void bridge_class_quirk(struct pci_dev *dev) dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL; } 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, DEV_PCIE_PORT_1, bridge_class_quirk); DEV_LS7A_PCIE_PORT1, bridge_class_quirk); 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) { Loading @@ -75,37 +80,33 @@ 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_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; static const struct pci_device_id bridge_devids[] = { { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_0) }, { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_1) }, { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_2) }, { 0, }, }; /* 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. * Some Loongson PCIe ports have h/w limitations of 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; } } struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus); bridge->no_inc_mrrs = 1; } 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) { Loading drivers/pci/pci.c +10 −0 Original line number Diff line number Diff line Loading @@ -6026,6 +6026,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) { u16 v; int ret; struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus); if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) return -EINVAL; Loading @@ -6044,6 +6045,15 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) 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, PCI_EXP_DEVCTL_READRQ, v); Loading drivers/pci/pcie/portdrv.c +14 −2 Original line number Diff line number Diff line Loading @@ -501,7 +501,6 @@ static void pcie_port_device_remove(struct pci_dev *dev) { device_for_each_child(&dev->dev, NULL, remove_iter); pci_free_irq_vectors(dev); pci_disable_device(dev); } /** Loading Loading @@ -727,6 +726,19 @@ static void pcie_portdrv_remove(struct pci_dev *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, Loading Loading @@ -777,7 +789,7 @@ static struct pci_driver pcie_portdriver = { .probe = pcie_portdrv_probe, .remove = pcie_portdrv_remove, .shutdown = pcie_portdrv_remove, .shutdown = pcie_portdrv_shutdown, .err_handler = &pcie_portdrv_err_handler, Loading drivers/pci/probe.c +2 −0 Original line number Diff line number Diff line Loading @@ -1841,6 +1841,8 @@ int pci_setup_device(struct pci_dev *dev) pci_set_of_node(dev); pci_set_acpi_fwnode(dev); if (dev->dev.fwnode && !fwnode_device_is_available(dev->dev.fwnode)) return -ENODEV; pci_dev_assign_slot(dev); Loading include/linux/pci.h +1 −0 Original line number Diff line number Diff line Loading @@ -572,6 +572,7 @@ struct pci_host_bridge { void *release_data; unsigned int ignore_reset_delay:1; /* For entire hierarchy */ 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_pcie_hotplug:1; /* OS may use PCIe hotplug */ unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */ Loading Loading
drivers/pci/controller/pci-loongson.c +36 −35 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ #include "../pci.h" /* Device IDs */ #define DEV_PCIE_PORT_0 0x7a09 #define DEV_PCIE_PORT_1 0x7a19 #define DEV_PCIE_PORT_2 0x7a29 #define DEV_LS2K_PCIE_PORT0 0x1a05 #define DEV_LS7A_PCIE_PORT0 0x7a09 #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_LS7A_GMAC 0x7a03 Loading Loading @@ -53,11 +58,11 @@ static void bridge_class_quirk(struct pci_dev *dev) dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL; } 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, DEV_PCIE_PORT_1, bridge_class_quirk); DEV_LS7A_PCIE_PORT1, bridge_class_quirk); 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) { Loading @@ -75,37 +80,33 @@ 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_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; static const struct pci_device_id bridge_devids[] = { { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_0) }, { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_1) }, { PCI_VDEVICE(LOONGSON, DEV_PCIE_PORT_2) }, { 0, }, }; /* 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. * Some Loongson PCIe ports have h/w limitations of 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; } } struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus); bridge->no_inc_mrrs = 1; } 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) { Loading
drivers/pci/pci.c +10 −0 Original line number Diff line number Diff line Loading @@ -6026,6 +6026,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) { u16 v; int ret; struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus); if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) return -EINVAL; Loading @@ -6044,6 +6045,15 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) 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, PCI_EXP_DEVCTL_READRQ, v); Loading
drivers/pci/pcie/portdrv.c +14 −2 Original line number Diff line number Diff line Loading @@ -501,7 +501,6 @@ static void pcie_port_device_remove(struct pci_dev *dev) { device_for_each_child(&dev->dev, NULL, remove_iter); pci_free_irq_vectors(dev); pci_disable_device(dev); } /** Loading Loading @@ -727,6 +726,19 @@ static void pcie_portdrv_remove(struct pci_dev *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, Loading Loading @@ -777,7 +789,7 @@ static struct pci_driver pcie_portdriver = { .probe = pcie_portdrv_probe, .remove = pcie_portdrv_remove, .shutdown = pcie_portdrv_remove, .shutdown = pcie_portdrv_shutdown, .err_handler = &pcie_portdrv_err_handler, Loading
drivers/pci/probe.c +2 −0 Original line number Diff line number Diff line Loading @@ -1841,6 +1841,8 @@ int pci_setup_device(struct pci_dev *dev) pci_set_of_node(dev); pci_set_acpi_fwnode(dev); if (dev->dev.fwnode && !fwnode_device_is_available(dev->dev.fwnode)) return -ENODEV; pci_dev_assign_slot(dev); Loading
include/linux/pci.h +1 −0 Original line number Diff line number Diff line Loading @@ -572,6 +572,7 @@ struct pci_host_bridge { void *release_data; unsigned int ignore_reset_delay:1; /* For entire hierarchy */ 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_pcie_hotplug:1; /* OS may use PCIe hotplug */ unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */ Loading