[Linux-kernel-mentees] [RFC PATCH v5 13/23] PCI: Initialise and Update values of pci_dev's PCIe link info

Saheed O. Bolarinwa refactormyself at gmail.com
Sat Aug 22 20:03:48 UTC 2020


The PCIe link state information defined in struct pci_dev are
initialised alongside with those of struct pcie_link_state.

The redundancy introduced is cleared out in later patches.

Signed-off-by: Saheed O. Bolarinwa <refactormyself at gmail.com>
---
 drivers/pci/pcie/aspm.c | 133 ++++++++++++++++++++++++++++++++--------
 1 file changed, 109 insertions(+), 24 deletions(-)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index d9c17093b250..e869e7faaac5 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -75,6 +75,7 @@ static int aspm_disabled, aspm_force;
 static bool aspm_support_enabled = true;
 static DEFINE_MUTEX(aspm_lock);
 static LIST_HEAD(link_list);
+static LIST_HEAD(pdev_link_list);
 
 #define POLICY_DEFAULT 0	/* BIOS default setting */
 #define POLICY_PERFORMANCE 1	/* high performance */
@@ -145,6 +146,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
 						   PCI_EXP_LNKCTL_CLKREQ_EN,
 						   val);
 	link->clkpm_enabled = !!enable;
+	link->pdev->clkpm_enabled = !!enable;
 }
 
 static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
@@ -183,6 +185,10 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
 	link->clkpm_default = enabled;
 	link->clkpm_capable = capable;
 	link->clkpm_disable = blacklist ? 1 : 0;
+	link->pdev->clkpm_enabled = enabled;
+	link->pdev->clkpm_default = enabled;
+	link->pdev->clkpm_capable = capable;
+	link->pdev->clkpm_disable = blacklist ? 1 : 0;
 }
 
 static bool pcie_retrain_link(struct pcie_link_state *link)
@@ -374,6 +380,7 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
 	u32 latency, l1_switch_latency = 0;
 	struct aspm_latency *acceptable;
 	struct pcie_link_state *link;
+	struct pci_dev *pdev;
 
 	/* Device not in D0 doesn't need latency check */
 	if ((endpoint->current_state != PCI_D0) &&
@@ -381,18 +388,24 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
 		return;
 
 	link = endpoint->bus->self->link_state;
+	pdev = endpoint->bus->self;
 	acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)];
 
 	while (link) {
 		/* Check upstream direction L0s latency */
 		if ((link->aspm_capable & ASPM_STATE_L0S_UP) &&
-		    (link->latency_up.l0s > acceptable->l0s))
+		    (link->latency_up.l0s > acceptable->l0s)) {
 			link->aspm_capable &= ~ASPM_STATE_L0S_UP;
+			pdev->aspm_capable &= ~ASPM_STATE_L0S_UP;
+		}
 
 		/* Check downstream direction L0s latency */
 		if ((link->aspm_capable & ASPM_STATE_L0S_DW) &&
-		    (link->latency_dw.l0s > acceptable->l0s))
+		    (link->latency_dw.l0s > acceptable->l0s)) {
 			link->aspm_capable &= ~ASPM_STATE_L0S_DW;
+			pdev->aspm_capable &= ~ASPM_STATE_L0S_DW;
+		}
+
 		/*
 		 * Check L1 latency.
 		 * Every switch on the path to root complex need 1
@@ -408,11 +421,15 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
 		 */
 		latency = max_t(u32, link->latency_up.l1, link->latency_dw.l1);
 		if ((link->aspm_capable & ASPM_STATE_L1) &&
-		    (latency + l1_switch_latency > acceptable->l1))
+		    (latency + l1_switch_latency > acceptable->l1)) {
 			link->aspm_capable &= ~ASPM_STATE_L1;
+			pdev->aspm_capable &= ~ASPM_STATE_L1;
+		}
+
 		l1_switch_latency += 1000;
 
 		link = link->parent;
+		pdev = pdev->parent;
 	}
 }
 
@@ -496,6 +513,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 		/* Set enabled/disable so that we will disable ASPM later */
 		link->aspm_enabled = ASPM_STATE_ALL;
 		link->aspm_disable = ASPM_STATE_ALL;
+		parent->aspm_enabled = ASPM_STATE_ALL;
+		parent->aspm_disable = ASPM_STATE_ALL;
 		return;
 	}
 
@@ -524,50 +543,87 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 	 */
 	if (((parent->lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10) &
 			((child->lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10) &
-			PCIE_LINK_STATE_L0S)
+			PCIE_LINK_STATE_L0S) {
 		link->aspm_support |= ASPM_STATE_L0S;
+		parent->aspm_support |= ASPM_STATE_L0S;
+	}
 
-	if (get_aspm_enable(child) & PCIE_LINK_STATE_L0S)
+	if (get_aspm_enable(child) & PCIE_LINK_STATE_L0S) {
 		link->aspm_enabled |= ASPM_STATE_L0S_UP;
-	if (get_aspm_enable(parent) & PCIE_LINK_STATE_L0S)
+		parent->aspm_enabled |= ASPM_STATE_L0S_UP;
+	}
+
+	if (get_aspm_enable(parent) & PCIE_LINK_STATE_L0S) {
 		link->aspm_enabled |= ASPM_STATE_L0S_DW;
+		parent->aspm_enabled |= ASPM_STATE_L0S_DW;
+	}
+
 	link->latency_up.l0s = calc_l0s_latency(parent);
 	link->latency_dw.l0s = calc_l0s_latency(child);
+	parent->latency_up.l0s = calc_l0s_latency(parent);
+	parent->latency_dw.l0s = calc_l0s_latency(child);
 
 	/* Setup L1 state */
 	if (((parent->lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10) &
 			((child->lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10) &
-			PCIE_LINK_STATE_L1)
+			PCIE_LINK_STATE_L1) {
 		link->aspm_support |= ASPM_STATE_L1;
-	if (get_aspm_enable(parent) & get_aspm_enable(child) & PCIE_LINK_STATE_L1)
+		parent->aspm_support |= ASPM_STATE_L1;
+	}
+
+	if (get_aspm_enable(parent) & get_aspm_enable(child) &
+			    PCIE_LINK_STATE_L1) {
 		link->aspm_enabled |= ASPM_STATE_L1;
+		parent->aspm_enabled |= ASPM_STATE_L1;
+	}
+
 	link->latency_up.l1 = calc_l1_latency(parent);
 	link->latency_dw.l1 = calc_l1_latency(child);
+	parent->latency_up.l1 = calc_l1_latency(parent);
+	parent->latency_dw.l1 = calc_l1_latency(child);
 
 	/* Setup L1 substate */
-	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_ASPM_L1_1)
+	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_ASPM_L1_1) {
 		link->aspm_support |= ASPM_STATE_L1_1;
-	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_ASPM_L1_2)
+		parent->aspm_support |= ASPM_STATE_L1_1;
+	}
+	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_ASPM_L1_2) {
 		link->aspm_support |= ASPM_STATE_L1_2;
-	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_1)
+		parent->aspm_support |= ASPM_STATE_L1_2;
+	}
+	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_1) {
 		link->aspm_support |= ASPM_STATE_L1_1_PCIPM;
-	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_2)
+		parent->aspm_support |= ASPM_STATE_L1_1_PCIPM;
+	}
+	if (parent->l1ss_cap & child->l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_2) {
 		link->aspm_support |= ASPM_STATE_L1_2_PCIPM;
+		parent->aspm_support |= ASPM_STATE_L1_2_PCIPM;
+	}
 
-	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_1)
+	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_1) {
 		link->aspm_enabled |= ASPM_STATE_L1_1;
-	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_2)
+		parent->aspm_enabled |= ASPM_STATE_L1_1;
+	}
+	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_2) {
 		link->aspm_enabled |= ASPM_STATE_L1_2;
-	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_1)
+		parent->aspm_enabled |= ASPM_STATE_L1_2;
+	}
+	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_1) {
 		link->aspm_enabled |= ASPM_STATE_L1_1_PCIPM;
-	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2)
+		parent->aspm_enabled |= ASPM_STATE_L1_1_PCIPM;
+	}
+	if (up_l1ss_ctl1 & dw_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2) {
 		link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM;
+		parent->aspm_enabled |= ASPM_STATE_L1_2_PCIPM;
+	}
 
 	/* Save default state */
 	link->aspm_default = link->aspm_enabled;
+	parent->aspm_default = parent->aspm_enabled;
 
 	/* Setup initial capable state. Will be updated later */
 	link->aspm_capable = link->aspm_support;
+	parent->aspm_capable = parent->aspm_support;
 
 	/* Get and check endpoint acceptable latencies */
 	list_for_each_entry(child, &linkbus->devices, bus_list) {
@@ -735,6 +791,7 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
 		pcie_config_aspm_dev(parent, upstream);
 
 	link->aspm_enabled = state;
+	parent->aspm_enabled = state;
 }
 
 static void pcie_config_aspm_path(struct pcie_link_state *link)
@@ -795,8 +852,10 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
 		return NULL;
 
 	INIT_LIST_HEAD(&link->sibling);
+	INIT_LIST_HEAD(&pdev->sibling);
 	link->pdev = pdev;
 	link->downstream = pci_function_0(pdev->subordinate);
+	pdev->downstream = pci_function_0(pdev->subordinate);
 
 	/*
 	 * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
@@ -809,6 +868,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
 	    pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE ||
 	    !pdev->bus->parent->self) {
 		link->root = link;
+		pdev->root = pdev;
 	} else {
 		struct pcie_link_state *parent;
 
@@ -820,9 +880,12 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
 
 		link->parent = parent;
 		link->root = link->parent->root;
+		pdev->parent = pdev->bus->parent->self;
+		pdev->root = pdev->parent->root;
 	}
 
 	list_add(&link->sibling, &link_list);
+	list_add(&pdev->sibling, &pdev_link_list);
 	pdev->link_state = link;
 	return link;
 }
@@ -913,6 +976,7 @@ static void pcie_update_aspm_capable(struct pcie_link_state *root)
 		if (link->root != root)
 			continue;
 		link->aspm_capable = link->aspm_support;
+		link->pdev->aspm_capable = link->aspm_support;
 	}
 	list_for_each_entry(link, &link_list, sibling) {
 		struct pci_dev *child;
@@ -1021,6 +1085,7 @@ static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
 static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 {
 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+	struct pci_dev *bridge = link->pdev;
 
 	if (!link)
 		return -EINVAL;
@@ -1040,23 +1105,37 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 	if (sem)
 		down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	if (state & PCIE_LINK_STATE_L0S)
+	if (state & PCIE_LINK_STATE_L0S) {
 		link->aspm_disable |= ASPM_STATE_L0S;
-	if (state & PCIE_LINK_STATE_L1)
+		bridge->aspm_disable |= ASPM_STATE_L0S;
+	}
+	if (state & PCIE_LINK_STATE_L1) {
 		/* L1 PM substates require L1 */
 		link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
-	if (state & PCIE_LINK_STATE_L1_1)
+		bridge->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
+	}
+	if (state & PCIE_LINK_STATE_L1_1) {
 		link->aspm_disable |= ASPM_STATE_L1_1;
-	if (state & PCIE_LINK_STATE_L1_2)
+		bridge->aspm_disable |= ASPM_STATE_L1_1;
+	}
+	if (state & PCIE_LINK_STATE_L1_2) {
 		link->aspm_disable |= ASPM_STATE_L1_2;
-	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
+		bridge->aspm_disable |= ASPM_STATE_L1_2;
+	}
+	if (state & PCIE_LINK_STATE_L1_1_PCIPM) {
 		link->aspm_disable |= ASPM_STATE_L1_1_PCIPM;
-	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
+		bridge->aspm_disable |= ASPM_STATE_L1_1_PCIPM;
+	}
+	if (state & PCIE_LINK_STATE_L1_2_PCIPM) {
 		link->aspm_disable |= ASPM_STATE_L1_2_PCIPM;
+		bridge->aspm_disable |= ASPM_STATE_L1_2_PCIPM;
+	}
 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
 
-	if (state & PCIE_LINK_STATE_CLKPM)
+	if (state & PCIE_LINK_STATE_CLKPM) {
 		link->clkpm_disable = 1;
+		bridge->clkpm_disable = 1;
+	}
 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
 	mutex_unlock(&aspm_lock);
 	if (sem)
@@ -1162,6 +1241,7 @@ static ssize_t aspm_attr_store_common(struct device *dev,
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+	struct pci_dev *bridge = link->pdev;
 	bool state_enable;
 
 	if (strtobool(buf, &state_enable) < 0)
@@ -1172,11 +1252,15 @@ static ssize_t aspm_attr_store_common(struct device *dev,
 
 	if (state_enable) {
 		link->aspm_disable &= ~state;
+		bridge->aspm_disable &= ~state;
 		/* need to enable L1 for substates */
-		if (state & ASPM_STATE_L1SS)
+		if (state & ASPM_STATE_L1SS) {
 			link->aspm_disable &= ~ASPM_STATE_L1;
+			bridge->aspm_disable &= ~ASPM_STATE_L1;
+		}
 	} else {
 		link->aspm_disable |= state;
+		bridge->aspm_disable |= state;
 	}
 
 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
@@ -1228,6 +1312,7 @@ static ssize_t clkpm_store(struct device *dev,
 	mutex_lock(&aspm_lock);
 
 	link->clkpm_disable = !state_enable;
+	link->pdev->clkpm_disable = !state_enable;
 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
 
 	mutex_unlock(&aspm_lock);
-- 
2.18.4



More information about the Linux-kernel-mentees mailing list