ソースを参照

Merge branch 'topic/stowe-cap-cleanup' into next

* topic/stowe-cap-cleanup:
  PCI: remove redundant capabilities checking in pci_{save, restore}_pcie_state
  PCI: add pci_pcie_cap2() check for PCIe feature capabilities >= v2
  PCI: remove redundant checking in PCI Express capability routines
  PCI: make pci_ltr_supported() static
Bjorn Helgaas 13 年 前
コミット
47fcb6da65
3 ファイル変更73 行追加49 行削除
  1. 67 48
      drivers/pci/pci.c
  2. 0 1
      include/linux/pci.h
  3. 6 0
      include/linux/pci_regs.h

+ 67 - 48
drivers/pci/pci.c

@@ -253,6 +253,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
 	return pos;
 	return pos;
 }
 }
 
 
+/**
+ * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
+ * @dev: PCI device to check
+ *
+ * Like pci_pcie_cap() but also checks that the PCIe capability version is
+ * >= 2.  Note that v1 capability structures could be sparse in that not
+ * all register fields were required.  v2 requires the entire structure to
+ * be present size wise, while still allowing for non-implemented registers
+ * to exist but they must be hardwired to 0.
+ *
+ * Due to the differences in the versions of capability structures, one
+ * must be careful not to try and access non-existant registers that may
+ * exist in early versions - v1 - of Express devices.
+ *
+ * Returns the offset of the PCIe capability structure as long as the
+ * capability version is >= 2; otherwise 0 is returned.
+ */
+static int pci_pcie_cap2(struct pci_dev *dev)
+{
+	u16 flags;
+	int pos;
+
+	pos = pci_pcie_cap(dev);
+	if (pos) {
+		pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
+		if ((flags & PCI_EXP_FLAGS_VERS) < 2)
+			pos = 0;
+	}
+
+	return pos;
+}
+
 /**
 /**
  * pci_find_ext_capability - Find an extended capability
  * pci_find_ext_capability - Find an extended capability
  * @dev: PCI device to query
  * @dev: PCI device to query
@@ -755,12 +787,6 @@ EXPORT_SYMBOL(pci_choose_state);
 		((flags & PCI_EXP_FLAGS_VERS) > 1 ||	\
 		((flags & PCI_EXP_FLAGS_VERS) > 1 ||	\
 		 (type == PCI_EXP_TYPE_ROOT_PORT ||	\
 		 (type == PCI_EXP_TYPE_ROOT_PORT ||	\
 		  type == PCI_EXP_TYPE_RC_EC))
 		  type == PCI_EXP_TYPE_RC_EC))
-#define pcie_cap_has_devctl2(type, flags)		\
-		((flags & PCI_EXP_FLAGS_VERS) > 1)
-#define pcie_cap_has_lnkctl2(type, flags)		\
-		((flags & PCI_EXP_FLAGS_VERS) > 1)
-#define pcie_cap_has_sltctl2(type, flags)		\
-		((flags & PCI_EXP_FLAGS_VERS) > 1)
 
 
 static struct pci_cap_saved_state *pci_find_saved_cap(
 static struct pci_cap_saved_state *pci_find_saved_cap(
 	struct pci_dev *pci_dev, char cap)
 	struct pci_dev *pci_dev, char cap)
@@ -803,13 +829,14 @@ static int pci_save_pcie_state(struct pci_dev *dev)
 		pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
 		pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
 	if (pcie_cap_has_rtctl(dev->pcie_type, flags))
 	if (pcie_cap_has_rtctl(dev->pcie_type, flags))
 		pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
 		pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-	if (pcie_cap_has_devctl2(dev->pcie_type, flags))
-		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
-	if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
-		pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
-	if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
-		pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
 
 
+	pos = pci_pcie_cap2(dev);
+	if (!pos)
+		return 0;
+
+	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
+	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
+	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -836,12 +863,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
 		pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
 		pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
 	if (pcie_cap_has_rtctl(dev->pcie_type, flags))
 	if (pcie_cap_has_rtctl(dev->pcie_type, flags))
 		pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
 		pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
-	if (pcie_cap_has_devctl2(dev->pcie_type, flags))
-		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
-	if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
-		pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
-	if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
-		pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
+
+	pos = pci_pcie_cap2(dev);
+	if (!pos)
+		return;
+
+	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
+	pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
+	pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
 }
 }
 
 
 
 
@@ -1916,7 +1945,7 @@ void pci_enable_ari(struct pci_dev *dev)
 {
 {
 	int pos;
 	int pos;
 	u32 cap;
 	u32 cap;
-	u16 flags, ctrl;
+	u16 ctrl;
 	struct pci_dev *bridge;
 	struct pci_dev *bridge;
 
 
 	if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
 	if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
@@ -1927,18 +1956,14 @@ void pci_enable_ari(struct pci_dev *dev)
 		return;
 		return;
 
 
 	bridge = dev->bus->self;
 	bridge = dev->bus->self;
-	if (!bridge || !pci_is_pcie(bridge))
+	if (!bridge)
 		return;
 		return;
 
 
-	pos = pci_pcie_cap(bridge);
+	/* ARI is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(bridge);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 
-	/* ARI is a PCIe v2 feature */
-	pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
-	if ((flags & PCI_EXP_FLAGS_VERS) < 2)
-		return;
-
 	pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
 	pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
 	if (!(cap & PCI_EXP_DEVCAP2_ARI))
 	if (!(cap & PCI_EXP_DEVCAP2_ARI))
 		return;
 		return;
@@ -1951,7 +1976,7 @@ void pci_enable_ari(struct pci_dev *dev)
 }
 }
 
 
 /**
 /**
- * pci_enable_ido - enable ID-based ordering on a device
+ * pci_enable_ido - enable ID-based Ordering on a device
  * @dev: the PCI device
  * @dev: the PCI device
  * @type: which types of IDO to enable
  * @type: which types of IDO to enable
  *
  *
@@ -1964,7 +1989,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type)
 	int pos;
 	int pos;
 	u16 ctrl;
 	u16 ctrl;
 
 
-	pos = pci_pcie_cap(dev);
+	/* ID-based Ordering is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 
@@ -1987,10 +2013,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
 	int pos;
 	int pos;
 	u16 ctrl;
 	u16 ctrl;
 
 
-	if (!pci_is_pcie(dev))
-		return;
-
-	pos = pci_pcie_cap(dev);
+	/* ID-based Ordering is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 
@@ -2029,10 +2053,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
 	u16 ctrl;
 	u16 ctrl;
 	int ret;
 	int ret;
 
 
-	if (!pci_is_pcie(dev))
-		return -ENOTSUPP;
-
-	pos = pci_pcie_cap(dev);
+	/* OBFF is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
@@ -2082,10 +2104,8 @@ void pci_disable_obff(struct pci_dev *dev)
 	int pos;
 	int pos;
 	u16 ctrl;
 	u16 ctrl;
 
 
-	if (!pci_is_pcie(dev))
-		return;
-
-	pos = pci_pcie_cap(dev);
+	/* OBFF is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 
@@ -2102,15 +2122,13 @@ EXPORT_SYMBOL(pci_disable_obff);
  * RETURNS:
  * RETURNS:
  * True if @dev supports latency tolerance reporting, false otherwise.
  * True if @dev supports latency tolerance reporting, false otherwise.
  */
  */
-bool pci_ltr_supported(struct pci_dev *dev)
+static bool pci_ltr_supported(struct pci_dev *dev)
 {
 {
 	int pos;
 	int pos;
 	u32 cap;
 	u32 cap;
 
 
-	if (!pci_is_pcie(dev))
-		return false;
-
-	pos = pci_pcie_cap(dev);
+	/* LTR is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return false;
 		return false;
 
 
@@ -2118,7 +2136,6 @@ bool pci_ltr_supported(struct pci_dev *dev)
 
 
 	return cap & PCI_EXP_DEVCAP2_LTR;
 	return cap & PCI_EXP_DEVCAP2_LTR;
 }
 }
-EXPORT_SYMBOL(pci_ltr_supported);
 
 
 /**
 /**
  * pci_enable_ltr - enable latency tolerance reporting
  * pci_enable_ltr - enable latency tolerance reporting
@@ -2139,7 +2156,8 @@ int pci_enable_ltr(struct pci_dev *dev)
 	if (!pci_ltr_supported(dev))
 	if (!pci_ltr_supported(dev))
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
-	pos = pci_pcie_cap(dev);
+	/* LTR is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
@@ -2174,7 +2192,8 @@ void pci_disable_ltr(struct pci_dev *dev)
 	if (!pci_ltr_supported(dev))
 	if (!pci_ltr_supported(dev))
 		return;
 		return;
 
 
-	pos = pci_pcie_cap(dev);
+	/* LTR is a PCIe cap v2 feature */
+	pos = pci_pcie_cap2(dev);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 

+ 0 - 1
include/linux/pci.h

@@ -911,7 +911,6 @@ enum pci_obff_signal_type {
 int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
 int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
 void pci_disable_obff(struct pci_dev *dev);
 void pci_disable_obff(struct pci_dev *dev);
 
 
-bool pci_ltr_supported(struct pci_dev *dev);
 int pci_enable_ltr(struct pci_dev *dev);
 int pci_enable_ltr(struct pci_dev *dev);
 void pci_disable_ltr(struct pci_dev *dev);
 void pci_disable_ltr(struct pci_dev *dev);
 int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns);
 int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns);

+ 6 - 0
include/linux/pci_regs.h

@@ -521,6 +521,12 @@
 #define PCI_EXP_RTSTA		32	/* Root Status */
 #define PCI_EXP_RTSTA		32	/* Root Status */
 #define PCI_EXP_RTSTA_PME	0x10000 /* PME status */
 #define PCI_EXP_RTSTA_PME	0x10000 /* PME status */
 #define PCI_EXP_RTSTA_PENDING	0x20000 /* PME pending */
 #define PCI_EXP_RTSTA_PENDING	0x20000 /* PME pending */
+/*
+ * Note that the following PCI Express 'Capability Structure' registers
+ * were introduced with 'Capability Version' 0x2 (v2).  These registers
+ * do not exist on devices with Capability Version 1.  Use pci_pcie_cap2()
+ * to use these fields safely.
+ */
 #define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
 #define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
 #define  PCI_EXP_DEVCAP2_ARI	0x20	/* Alternative Routing-ID */
 #define  PCI_EXP_DEVCAP2_ARI	0x20	/* Alternative Routing-ID */
 #define  PCI_EXP_DEVCAP2_LTR	0x800	/* Latency tolerance reporting */
 #define  PCI_EXP_DEVCAP2_LTR	0x800	/* Latency tolerance reporting */