[openib-general] [PATCH 1/6] Add pci_find_ht_capability() for finding Hypertransport capabilities

Michael Ellerman michael at ellerman.id.au
Wed Nov 8 22:40:43 PST 2006


There are already several places in the kernel that want to search a PCI
device for a given Hypertransport capability. Although this is possible
using pci_find_capability() etc., it makes sense to encapsulate that
logic in a helper - pci_find_ht_capability().

To cater for searching exhaustively for a capability, we also provide
pci_find_next_ht_capability().

We also need to cater for the fact that the HT capability fields may be
either 3 or 5 bits wide. pci_find_ht_capability() deals with this for you,
but callers using the #defines directly must handle that themselves.

Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
---

 drivers/pci/pci.c        |   55 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h      |    2 +
 include/linux/pci_regs.h |   12 +++++++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

Index: msi/drivers/pci/pci.c
===================================================================
--- msi.orig/drivers/pci/pci.c
+++ msi/drivers/pci/pci.c
@@ -215,6 +215,61 @@ int pci_find_ext_capability(struct pci_d
 EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
 /**
+ * pci_find_next_ht_capability - query a device's Hypertransport capabilities
+ * @dev: PCI device to query
+ * @pos: Position from which to continue searching
+ * @ht_cap: Hypertransport capability code
+ *
+ * To be used in conjunction with pci_find_ht_capability() to search for
+ * all capabilities matching @ht_cap. @pos should always be a value returned
+ * from pci_find_ht_capability().
+ */
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap)
+{
+	int rc;
+	u8 cap, mask;
+
+	if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST)
+		mask = HT_3BIT_CAP_MASK;
+	else
+		mask = HT_5BIT_CAP_MASK;
+
+	while (pos) {
+		rc = pci_read_config_byte(dev, pos + 3, &cap);
+		if (rc != PCIBIOS_SUCCESSFUL)
+			return 0;
+
+		if ((cap & mask) == ht_cap)
+			return pos;
+
+		pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pci_find_next_ht_capability);
+
+/**
+ * pci_find_ht_capability - query a device's Hypertransport capabilities
+ * @dev: PCI device to query
+ * @ht_cap: Hypertransport capability code
+ *
+ * Tell if a device supports a given Hypertransport capability.
+ * Returns an address within the device's PCI configuration space
+ * or 0 in case the device does not support the request capability.
+ * The address points to the PCI capability, of type PCI_CAP_ID_HT,
+ * which has a Hypertransport capability matching @ht_cap.
+ */
+int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
+{
+	int pos;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_HT);
+	return pci_find_next_ht_capability(dev, pos, ht_cap);
+}
+EXPORT_SYMBOL_GPL(pci_find_ht_capability);
+
+/**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
  * @res: child resource record for which parent is sought
Index: msi/include/linux/pci.h
===================================================================
--- msi.orig/include/linux/pci.h
+++ msi/include/linux/pci.h
@@ -453,6 +453,8 @@ struct pci_dev *pci_find_slot (unsigned 
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability (struct pci_dev *dev, int cap);
+int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
+int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
Index: msi/include/linux/pci_regs.h
===================================================================
--- msi.orig/include/linux/pci_regs.h
+++ msi/include/linux/pci_regs.h
@@ -468,9 +468,19 @@
 #define PCI_PWR_CAP		12	/* Capability */
 #define  PCI_PWR_CAP_BUDGET(x)	((x) & 1)	/* Included in system budget */
 
-/* Hypertransport sub capability types */
+/*
+ * Hypertransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK	0xE0
 #define HT_CAPTYPE_SLAVE	0x00	/* Slave/Primary link configuration */
 #define HT_CAPTYPE_HOST		0x20	/* Host/Secondary link configuration */
+
+#define HT_5BIT_CAP_MASK	0xF8
 #define HT_CAPTYPE_IRQ		0x80	/* IRQ Configuration */
 #define HT_CAPTYPE_REMAPPING_40	0xA0	/* 40 bit address remapping */
 #define HT_CAPTYPE_REMAPPING_64 0xA2	/* 64 bit address remapping */




More information about the general mailing list