pci-v6.7-fixes-1
-----BEGIN PGP SIGNATURE----- iQJIBAABCgAyFiEEgMe7l+5h9hnxdsnuWYigwDrT+vwFAmV8vZwUHGJoZWxnYWFz QGdvb2dsZS5jb20ACgkQWYigwDrT+vwQARAApzU4pesi9dkl/Fyv11IwayNm+gra 8dTsdT6dcnTq8DKXdTRtuyMwY+H57YC/Cxl0/Y6KPnJqUmgXEiOfe1duPvy5HJB2 YQGPszDC/yrbU/s65cWwuw+wLHk3PeoR/RNfo0PBNRb+FIoE2tV6mgAw0CR2xyhV MTDMMvdJBAQoNytmkw5ZYgdr3zUPgb80VgjBa453xGxMHlnpqhRIKNw5jXBOWCpY 1TkrDAtKzziCXVx9oqLDA46AgdVo48w+vPrC3wa/8kxv4/N0BplhiUrtAdXMrsIH wR3uX3ypfdjEWf+iX3dgGbvwoSZirlZdu9BaSTZqM/WAHdync/Hit/mF6rYpOQfJ 9WpALQkx11EvYpltZOO4JahaWueGxEK73/P43Cb9Pgj5zNiMagGwVc+1iEXMC0k8 MML/MZrQQaNcJOQL+V3rXr7pcRqV8X6H5/0K/e8M53D5U3ZkcjBc2QcqOd3/4ugf 7sa9JfXOFcBJvwUt3HQNHEyj+leJDJ09kRXSx8szfRrCGVTkNtZ9DxKePHzCk+kC kU4y+5E9iIsGwdGknnO53LbilgGtutJx+JpBPz0guXb53RIGQGcHfWVPHzB9fmJk Ty4d+zsP2OmKgMDX2FdVv4xVNYDsdOGG7PQu++pm0fBmIvBixRcQyfXrLdTMvjwX 6AOhXOppox58COs= =4BWR -----END PGP SIGNATURE----- Merge tag 'pci-v6.7-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci Pull pci fixes from Bjorn Helgaas: - Limit Max_Read_Request_Size (MRRS) on some MIPS Loongson systems because they don't all support MRRS > 256, and firmware doesn't always initialize it correctly, which meant some PCIe devices didn't work (Jiaxun Yang) - Add and use pci_enable_link_state_locked() to prevent potential deadlocks in vmd and qcom drivers (Johan Hovold) - Revert recent (v6.5) acpiphp resource assignment changes that fixed issues with hot-adding devices on a root bus or with large BARs, but introduced new issues with GPU initialization and hot-adding SCSI disks in QEMU VMs and (Bjorn Helgaas) * tag 'pci-v6.7-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: Revert "PCI: acpiphp: Reassign resources on bridge if necessary" PCI/ASPM: Add pci_disable_link_state_locked() lockdep assert PCI/ASPM: Clean up __pci_disable_link_state() 'sem' parameter PCI: qcom: Clean up ASPM comment PCI: qcom: Fix potential deadlock when enabling ASPM PCI: vmd: Fix potential deadlock when enabling ASPM PCI/ASPM: Add pci_enable_link_state_locked() PCI: loongson: Limit MRRS to 256
This commit is contained in:
commit
2e3f280b24
@ -968,9 +968,12 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
|
||||
|
||||
static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
|
||||
{
|
||||
/* Downstream devices need to be in D0 state before enabling PCI PM substates */
|
||||
/*
|
||||
* Downstream devices need to be in D0 state before enabling PCI PM
|
||||
* substates.
|
||||
*/
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
|
||||
pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -80,13 +80,49 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
|
||||
DEV_LS7A_LPC, system_bus_quirk);
|
||||
|
||||
/*
|
||||
* Some Loongson PCIe ports have hardware limitations on their Maximum Read
|
||||
* Request Size. They can't handle anything larger than this. Sane
|
||||
* firmware will set proper MRRS at boot, so we only need no_inc_mrrs for
|
||||
* bridges. However, some MIPS Loongson firmware doesn't set MRRS properly,
|
||||
* so we have to enforce maximum safe MRRS, which is 256 bytes.
|
||||
*/
|
||||
#ifdef CONFIG_MIPS
|
||||
static void loongson_set_min_mrrs_quirk(struct pci_dev *pdev)
|
||||
{
|
||||
struct pci_bus *bus = pdev->bus;
|
||||
struct pci_dev *bridge;
|
||||
static const struct pci_device_id bridge_devids[] = {
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS2K_PCIE_PORT0) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT0) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT1) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT2) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT3) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT4) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT5) },
|
||||
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT6) },
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
/* look for the matching bridge */
|
||||
while (!pci_is_root_bus(bus)) {
|
||||
bridge = bus->self;
|
||||
bus = bus->parent;
|
||||
|
||||
if (pci_match_id(bridge_devids, bridge)) {
|
||||
if (pcie_get_readrq(pdev) > 256) {
|
||||
pci_info(pdev, "limiting MRRS to 256\n");
|
||||
pcie_set_readrq(pdev, 256);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, loongson_set_min_mrrs_quirk);
|
||||
#endif
|
||||
|
||||
static void loongson_mrrs_quirk(struct pci_dev *pdev)
|
||||
{
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
|
||||
|
||||
bridge->no_inc_mrrs = 1;
|
||||
|
@ -751,7 +751,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
|
||||
if (!(features & VMD_FEAT_BIOS_PM_QUIRK))
|
||||
return 0;
|
||||
|
||||
pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
|
||||
pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
|
||||
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR);
|
||||
if (!pos)
|
||||
|
@ -512,15 +512,12 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
|
||||
if (pass && dev->subordinate) {
|
||||
check_hotplug_bridge(slot, dev);
|
||||
pcibios_resource_survey_bus(dev->subordinate);
|
||||
if (pci_is_root_bus(bus))
|
||||
__pci_bus_size_bridges(dev->subordinate, &add_list);
|
||||
__pci_bus_size_bridges(dev->subordinate,
|
||||
&add_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pci_is_root_bus(bus))
|
||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||
else
|
||||
pci_assign_unassigned_bridge_resources(bus->self);
|
||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||
}
|
||||
|
||||
acpiphp_sanitize_bus(bus);
|
||||
|
@ -1041,7 +1041,7 @@ static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
|
||||
return bridge->link_state;
|
||||
}
|
||||
|
||||
static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
|
||||
static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked)
|
||||
{
|
||||
struct pcie_link_state *link = pcie_aspm_get_link(pdev);
|
||||
|
||||
@ -1060,7 +1060,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (sem)
|
||||
if (!locked)
|
||||
down_read(&pci_bus_sem);
|
||||
mutex_lock(&aspm_lock);
|
||||
if (state & PCIE_LINK_STATE_L0S)
|
||||
@ -1082,7 +1082,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
|
||||
link->clkpm_disable = 1;
|
||||
pcie_set_clkpm(link, policy_to_clkpm_state(link));
|
||||
mutex_unlock(&aspm_lock);
|
||||
if (sem)
|
||||
if (!locked)
|
||||
up_read(&pci_bus_sem);
|
||||
|
||||
return 0;
|
||||
@ -1090,7 +1090,9 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
|
||||
|
||||
int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
|
||||
{
|
||||
return __pci_disable_link_state(pdev, state, false);
|
||||
lockdep_assert_held_read(&pci_bus_sem);
|
||||
|
||||
return __pci_disable_link_state(pdev, state, true);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_link_state_locked);
|
||||
|
||||
@ -1105,21 +1107,11 @@ EXPORT_SYMBOL(pci_disable_link_state_locked);
|
||||
*/
|
||||
int pci_disable_link_state(struct pci_dev *pdev, int state)
|
||||
{
|
||||
return __pci_disable_link_state(pdev, state, true);
|
||||
return __pci_disable_link_state(pdev, state, false);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_link_state);
|
||||
|
||||
/**
|
||||
* pci_enable_link_state - Clear and set the default device link state so that
|
||||
* the link may be allowed to enter the specified states. Note that if the
|
||||
* BIOS didn't grant ASPM control to the OS, this does nothing because we can't
|
||||
* touch the LNKCTL register. Also note that this does not enable states
|
||||
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
|
||||
*
|
||||
* @pdev: PCI device
|
||||
* @state: Mask of ASPM link states to enable
|
||||
*/
|
||||
int pci_enable_link_state(struct pci_dev *pdev, int state)
|
||||
static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
|
||||
{
|
||||
struct pcie_link_state *link = pcie_aspm_get_link(pdev);
|
||||
|
||||
@ -1136,7 +1128,8 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
down_read(&pci_bus_sem);
|
||||
if (!locked)
|
||||
down_read(&pci_bus_sem);
|
||||
mutex_lock(&aspm_lock);
|
||||
link->aspm_default = 0;
|
||||
if (state & PCIE_LINK_STATE_L0S)
|
||||
@ -1157,12 +1150,48 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
|
||||
link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
|
||||
pcie_set_clkpm(link, policy_to_clkpm_state(link));
|
||||
mutex_unlock(&aspm_lock);
|
||||
up_read(&pci_bus_sem);
|
||||
if (!locked)
|
||||
up_read(&pci_bus_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_link_state - Clear and set the default device link state so that
|
||||
* the link may be allowed to enter the specified states. Note that if the
|
||||
* BIOS didn't grant ASPM control to the OS, this does nothing because we can't
|
||||
* touch the LNKCTL register. Also note that this does not enable states
|
||||
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
|
||||
*
|
||||
* @pdev: PCI device
|
||||
* @state: Mask of ASPM link states to enable
|
||||
*/
|
||||
int pci_enable_link_state(struct pci_dev *pdev, int state)
|
||||
{
|
||||
return __pci_enable_link_state(pdev, state, false);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_link_state);
|
||||
|
||||
/**
|
||||
* pci_enable_link_state_locked - Clear and set the default device link state
|
||||
* so that the link may be allowed to enter the specified states. Note that if
|
||||
* the BIOS didn't grant ASPM control to the OS, this does nothing because we
|
||||
* can't touch the LNKCTL register. Also note that this does not enable states
|
||||
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
|
||||
*
|
||||
* @pdev: PCI device
|
||||
* @state: Mask of ASPM link states to enable
|
||||
*
|
||||
* Context: Caller holds pci_bus_sem read lock.
|
||||
*/
|
||||
int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
|
||||
{
|
||||
lockdep_assert_held_read(&pci_bus_sem);
|
||||
|
||||
return __pci_enable_link_state(pdev, state, true);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_link_state_locked);
|
||||
|
||||
static int pcie_aspm_set_policy(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
|
@ -1829,6 +1829,7 @@ extern bool pcie_ports_native;
|
||||
int pci_disable_link_state(struct pci_dev *pdev, int state);
|
||||
int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
|
||||
int pci_enable_link_state(struct pci_dev *pdev, int state);
|
||||
int pci_enable_link_state_locked(struct pci_dev *pdev, int state);
|
||||
void pcie_no_aspm(void);
|
||||
bool pcie_aspm_support_enabled(void);
|
||||
bool pcie_aspm_enabled(struct pci_dev *pdev);
|
||||
@ -1839,6 +1840,8 @@ static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
|
||||
{ return 0; }
|
||||
static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
|
||||
{ return 0; }
|
||||
static inline int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
|
||||
{ return 0; }
|
||||
static inline void pcie_no_aspm(void) { }
|
||||
static inline bool pcie_aspm_support_enabled(void) { return false; }
|
||||
static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user