Skip to contentSkip to conversation

PCI: Apply _HPX link control for all supported pcie device

PATCH Superseded Yinghai Lu 2 participants 3 messages Nov 7, 2014 – Nov 11, 2014 PCI

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Yinghai Lu

author
#0 lore raw

PATCH 1/1 PCI: Apply _HPX link control for all supported pcie device

With commit 6cd33649fa83 ("PCI: Add pci_configure_device() during enumeration") and following commits, we apply _HPX for pci devices.

that is called via pci_scan_slot

			==>pci_scan_single_device
				==>pci_device_add
					==>pci_configure_device
						==>program_hpp_type2

and dev->subordinate is not allocated yet.

So that link control setup get skipped.

Acoording to ACPI spec, there is no requirement that need to be set to pcie root port or downstream port.

We could just change to pcie_cap_has_lnkctl to cover all pcie devices with link control cap.

Fixes 6cd33649fa83 ("PCI: Add pci_configure_device() during enumeration")
---
 drivers/pci/access.c |   13 -------------
 drivers/pci/pci.h    |   13 +++++++++++++
 drivers/pci/probe.c  |    2 +-
 3 files changed, 14 insertions(+), 14 deletions(-)
drivers/pci/probe.c +1 -1
Index: linux-2.6/drivers/pci/probe.c
===================================================================
@@ -1323,7 +1323,7 @@ static void program_hpp_type2(struct pci
 			~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
 	/* Initialize Link Control Register */
-	if (dev->subordinate)
+	if (pcie_cap_has_lnkctl(dev))
 		pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
 			~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
 
drivers/pci/access.c +0 -13
Index: linux-2.6/drivers/pci/access.c
===================================================================
@@ -444,19 +444,6 @@ static inline int pcie_cap_version(const
 	return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
-static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
-{
-	int type = pci_pcie_type(dev);
-
-	return type == PCI_EXP_TYPE_ENDPOINT ||
-	       type == PCI_EXP_TYPE_LEG_END ||
-	       type == PCI_EXP_TYPE_ROOT_PORT ||
-	       type == PCI_EXP_TYPE_UPSTREAM ||
-	       type == PCI_EXP_TYPE_DOWNSTREAM ||
-	       type == PCI_EXP_TYPE_PCI_BRIDGE ||
-	       type == PCI_EXP_TYPE_PCIE_BRIDGE;
-}
-
 static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
 {
 	int type = pci_pcie_type(dev);
drivers/pci/pci.h +13 -0
Index: linux-2.6/drivers/pci/pci.h
===================================================================
@@ -6,6 +6,19 @@
 
 extern const unsigned char pcie_link_speed[];
 
+static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
+{
+	int type = pci_pcie_type(dev);
+
+	return type == PCI_EXP_TYPE_ENDPOINT ||
+	       type == PCI_EXP_TYPE_LEG_END ||
+	       type == PCI_EXP_TYPE_ROOT_PORT ||
+	       type == PCI_EXP_TYPE_UPSTREAM ||
+	       type == PCI_EXP_TYPE_DOWNSTREAM ||
+	       type == PCI_EXP_TYPE_PCI_BRIDGE ||
+	       type == PCI_EXP_TYPE_PCIE_BRIDGE;
+}
+
 /* Functions internal to the PCI core code */
 
 int pci_create_sysfs_dev_files(struct pci_dev *pdev);
maintainer
#1 lore raw
Quoted 32 lines · Yinghai Lu

With commit 6cd33649fa83 ("PCI: Add pci_configure_device() during enumeration") and following commits, we apply _HPX for pci devices.

that is called via pci_scan_slot

			==>pci_scan_single_device
				==>pci_device_add
					==>pci_configure_device
						==>program_hpp_type2

and dev->subordinate is not allocated yet.

So that link control setup get skipped.

Acoording to ACPI spec, there is no requirement that need to be set to pcie root port or downstream port.

We could just change to pcie_cap_has_lnkctl to cover all pcie devices with link control cap.

Fixes 6cd33649fa83 ("PCI: Add pci_configure_device() during enumeration")
---
 drivers/pci/access.c |   13 -------------
 drivers/pci/pci.h    |   13 +++++++++++++
 drivers/pci/probe.c  |    2 +-
 3 files changed, 14 insertions(+), 14 deletions(-)

Index: linux-2.6/drivers/pci/probe.c
===================================================================

drivers/pci/probe.c static void program_hpp_type2(struct pci · line 1328

Quoted 7 lines
drivers/pci/probe.c +1 -1
@@ -1323,7 +1323,7 @@ static void program_hpp_type2(struct pci
 			~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
 	/* Initialize Link Control Register */
-	if (dev->subordinate)
+	if (pcie_cap_has_lnkctl(dev))
 		pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
 			~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);

Nice catch! It's much cleaner to do this based on pcie_cap_has_lnkctl().

Quoted 34 lines

Index: linux-2.6/drivers/pci/access.c
===================================================================

drivers/pci/access.c +0 -13
@@ -444,19 +444,6 @@ static inline int pcie_cap_version(const
 	return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
-static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
-{
-	int type = pci_pcie_type(dev);
-
-	return type == PCI_EXP_TYPE_ENDPOINT ||
-	       type == PCI_EXP_TYPE_LEG_END ||
-	       type == PCI_EXP_TYPE_ROOT_PORT ||
-	       type == PCI_EXP_TYPE_UPSTREAM ||
-	       type == PCI_EXP_TYPE_DOWNSTREAM ||
-	       type == PCI_EXP_TYPE_PCI_BRIDGE ||
-	       type == PCI_EXP_TYPE_PCIE_BRIDGE;
-}
-
 static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
 {
 	int type = pci_pcie_type(dev);

Index: linux-2.6/drivers/pci/pci.h
===================================================================

drivers/pci/pci.h +2 -0
@@ -6,6 +6,19 @@
 
 extern const unsigned char pcie_link_speed[];
 
+static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
+{

drivers/pci/pci.h line 20

Quoted 10 lines
drivers/pci/pci.h +10 -0
+	int type = pci_pcie_type(dev);
+
+	return type == PCI_EXP_TYPE_ENDPOINT ||
+	       type == PCI_EXP_TYPE_LEG_END ||
+	       type == PCI_EXP_TYPE_ROOT_PORT ||
+	       type == PCI_EXP_TYPE_UPSTREAM ||
+	       type == PCI_EXP_TYPE_DOWNSTREAM ||
+	       type == PCI_EXP_TYPE_PCI_BRIDGE ||
+	       type == PCI_EXP_TYPE_PCIE_BRIDGE;
+}

But I don't want to move pcie_cap_has_lnkctl() to pci.h and leave pcie_cap_has_sltctl() and pcie_cap_has_rtctl() in access.c. They're all related, so I think they should stay together.

What if we left them in access.c, made them non-static, non-inline, and just added prototypes to pci.h? Or I guess we could add a prototype just for pcie_cap_has_lnkctl(), since that's the only one we need so far.

Bjorn

Quoted 4 lines
drivers/pci/pci.h +1 -0
+
 /* Functions internal to the PCI core code */
 
 int pci_create_sysfs_dev_files(struct pci_dev *pdev);
author
#2 lore raw
Quoted 8 lines · Bjorn Helgaas

But I don't want to move pcie_cap_has_lnkctl() to pci.h and leave pcie_cap_has_sltctl() and pcie_cap_has_rtctl() in access.c. They're all related, so I think they should stay together.

What if we left them in access.c, made them non-static, non-inline, and just added prototypes to pci.h? Or I guess we could add a prototype just for pcie_cap_has_lnkctl(), since that's the only one we need so far.

Ok, will have another version that add only prototype for pcie_cap_has_lnkctl() to pci.h

Thanks

Yinghai