Samuel Thibault, le Wed 06 Feb 2013 01:55:18 +0100, a écrit :
> Jeff Squyres (jsquyres), le Wed 06 Feb 2013 01:41:21 +0100, a écrit :
> > On Feb 5, 2013, at 3:50 PM, Samuel Thibault <samuel.thiba...@inria.fr> 
> > wrote:
> > 
> > > Jeff Squyres (jsquyres), le Tue 05 Feb 2013 22:52:01 +0100, a écrit :
> > >> It was just pointed out to me that libpci is licensed under the GPL (not 
> > >> the LGPL).
> > > 
> > > I'm told that we could use libpciaccess instead, which is BSD.
> > 
> > That would be great -- is it easily available?
> 
> Yes. I've made a quick port

Here is a quick version (I haven't taken the time to handle the hwloc.m4
stuff).

Samuel
Index: src/topology-libpci.c
===================================================================
--- src/topology-libpci.c       (révision 5235)
+++ src/topology-libpci.c       (copie de travail)
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2009 CNRS
  * Copyright © 2009-2012 Inria.  All rights reserved.
- * Copyright © 2009-2011 Université Bordeaux 1
+ * Copyright © 2009-2011, 2013 Université Bordeaux 1
  * See COPYING in top-level directory.
  */

@@ -14,7 +14,6 @@
 #include <private/debug.h>
 #include <private/misc.h>

-#include <pci/pci.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <string.h>
@@ -22,8 +21,92 @@
 #include <stdarg.h>
 #include <setjmp.h>

-#define CONFIG_SPACE_CACHESIZE 256
+#ifdef HWLOC_HAVE_LIBPCIACCESS
+#include <pciaccess.h>
+#undef HWLOC_HAVE_LIBPCI
+#endif

+#ifdef HWLOC_HAVE_LIBPCI
+#include <pci/pci.h>
+#endif
+
+#ifndef PCI_HEADER_TYPE
+#define PCI_HEADER_TYPE 0x0e
+#endif
+#ifndef PCI_HEADER_TYPE_BRIDGE
+#define PCI_HEADER_TYPE_BRIDGE 1
+#endif
+
+#ifndef PCI_CLASS_DEVICE
+#define PCI_CLASS_DEVICE 0x0a
+#endif
+#ifndef PCI_CLASS_BRIDGE_PCI
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#endif
+
+#ifndef PCI_REVISION_ID
+#define PCI_REVISION_ID 0x08
+#endif
+
+#ifndef PCI_SUBSYSTEM_VENDOR_ID
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#endif
+#ifndef PCI_SUBSYSTEM_ID
+#define PCI_SUBSYSTEM_ID 0x2e
+#endif
+
+#ifndef PCI_PRIMARY_BUS
+#define PCI_PRIMARY_BUS 0x18
+#endif
+#ifndef PCI_SECONDARY_BUS
+#define PCI_SECONDARY_BUS 0x19
+#endif
+#ifndef PCI_SUBORDINATE_BUS
+#define PCI_SUBORDINATE_BUS 0x1a
+#endif
+
+#ifndef PCI_EXP_LNKSTA
+#define PCI_EXP_LNKSTA 18
+#endif
+
+#ifndef PCI_EXP_LNKSTA_SPEED
+#define PCI_EXP_LNKSTA_SPEED 0x000f
+#endif
+#ifndef PCI_EXP_LNKSTA_WIDTH
+#define PCI_EXP_LNKSTA_WIDTH 0x03f0
+#endif
+
+#ifndef PCI_CAP_ID_EXP
+#define PCI_CAP_ID_EXP 0x10
+#endif
+
+#ifndef PCI_CAP_NORMAL
+#define PCI_CAP_NORMAL 1
+#endif
+
+#ifndef PCI_STATUS
+#define PCI_STATUS 0x06
+#endif
+
+#ifndef PCI_CAPABILITY_LIST
+#define PCI_CAPABILITY_LIST 0x34
+#endif
+
+#ifndef PCI_STATUS_CAP_LIST
+#define PCI_STATUS_CAP_LIST 0x10
+#endif
+
+#ifndef PCI_CAP_LIST_ID
+#define PCI_CAP_LIST_ID 0
+#endif
+
+#ifndef PCI_CAP_LIST_NEXT
+#define PCI_CAP_LIST_NEXT 1
+#endif
+
+#define CONFIG_SPACE_CACHESIZE_TRY 256
+#define CONFIG_SPACE_CACHESIZE 64
+
 static void
 hwloc_pci_traverse_print_cb(void * cbdata __hwloc_attribute_unused,
                            struct hwloc_obj *pcidev, int depth 
__hwloc_attribute_unused)
@@ -290,6 +373,7 @@
   return parent;
 }

+#ifdef HWLOC_HAVE_LIBPCI
 /* Avoid letting libpci call exit(1) when no PCI bus is available. */
 static jmp_buf err_buf;
 static void
@@ -308,15 +392,59 @@
 hwloc_pci_warning(char *msg __hwloc_attribute_unused, ...)
 {
 }
+#endif

+#ifndef HWLOC_HAVE_PCI_FIND_CAP
+static unsigned
+hwloc_pci_find_cap(const unsigned char *config, size_t config_size, unsigned 
cap)
+{
+  unsigned char seen[256] = { 0 };
+  unsigned char ptr;
+
+  if (!(config[PCI_STATUS] & PCI_STATUS_CAP_LIST))
+    return 0;
+
+  for (ptr = config[PCI_CAPABILITY_LIST] & ~3;
+       ptr;
+       ptr = config[ptr + PCI_CAP_LIST_NEXT] & ~3) {
+    unsigned char id;
+
+    if (ptr >= config_size)
+      return 0;
+
+    /* Looped around! */
+    if (seen[ptr])
+      return 0;
+    seen[ptr] = 1;
+
+    id = config[ptr + PCI_CAP_LIST_ID];
+    if (id == cap)
+      return ptr;
+    if (id == 0xff)
+      break;
+
+    if (ptr + PCI_CAP_LIST_NEXT >= config_size)
+      return 0;
+  }
+  return 0;
+}
+#endif
+
 static int
 hwloc_look_libpci(struct hwloc_backend *backend)
 {
   struct hwloc_topology *topology = backend->topology;
+  struct hwloc_obj fakehostbridge; /* temporary object covering the whole PCI 
hierarchy until its complete */
+  unsigned current_hostbridge;
+#ifdef HWLOC_HAVE_LIBPCIACCESS
+  int ret;
+  struct pci_device_iterator *iter;
+  struct pci_device *pcidev;
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
   struct pci_access *pciaccess;
   struct pci_dev *pcidev;
-  struct hwloc_obj fakehostbridge; /* temporary object covering the whole PCI 
hierarchy until its complete */
-  unsigned current_hostbridge;
+#endif

   if (!(hwloc_topology_get_flags(topology) & 
(HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
     return 0;
@@ -331,6 +459,16 @@

   hwloc_debug("%s", "\nScanning PCI buses...\n");

+#ifdef HWLOC_HAVE_LIBPCIACCESS
+  ret = pci_system_init();
+  if (ret) {
+    hwloc_debug("%s", "Can not initialize libpciaccess\n");
+    return -1;
+  }
+
+  iter = pci_slot_match_iterator_create(NULL);
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
   pciaccess = pci_alloc();
   pciaccess->error = hwloc_pci_error;
   pciaccess->warning = hwloc_pci_warning;
@@ -343,20 +481,43 @@
   pci_init(pciaccess);
   pci_scan_bus(pciaccess);

-  pcidev = pciaccess->devices;
-  while (pcidev) {
-    char name[128];
+#endif
+
+#ifdef HWLOC_HAVE_LIBPCI
+  for (pcidev = pciaccess->devices;
+       pcidev;
+       pcidev = pcidev->next)
+#endif
+#ifdef HWLOC_HAVE_LIBPCIACCESS
+  for (pcidev = pci_device_next(iter);
+       pcidev;
+       pcidev = pci_device_next(iter))
+#endif
+  {
     const char *resname;
-    u8 config_space_cache[CONFIG_SPACE_CACHESIZE];
+    unsigned char config_space_cache[CONFIG_SPACE_CACHESIZE_TRY];
+    unsigned config_space_cachesize = CONFIG_SPACE_CACHESIZE_TRY;
     struct hwloc_obj *obj;
     unsigned char headertype;
     unsigned os_index;
     unsigned isbridge;
     unsigned domain;
     unsigned device_class;
+#ifdef HWLOC_HAVE_LIBPCIACCESS
+    pciaddr_t got;
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
+    char name[128];
+#endif

+#ifdef HWLOC_HAVE_LIBPCIACCESS
+    pci_device_cfg_read(pcidev, config_space_cache, 0, 
CONFIG_SPACE_CACHESIZE_TRY, &got);
+    config_space_cachesize = got;
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
     /* cache what we need of the config space */
-    pci_read_block(pcidev, 0, config_space_cache, CONFIG_SPACE_CACHESIZE);
+    pci_read_block(pcidev, 0, config_space_cache, CONFIG_SPACE_CACHESIZE_TRY);
+#endif

     /* read some fields that may not always be available */
 #ifdef HWLOC_HAVE_PCIDEV_DOMAIN
@@ -364,12 +525,17 @@
 #else
     domain = 0; /* default domain number */
 #endif
+#ifdef HWLOC_HAVE_LIBPCIACCESS
+    device_class = pcidev->device_class >> 8;
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
 #ifdef HWLOC_HAVE_PCIDEV_DEVICE_CLASS
     device_class = pcidev->device_class;
 #else
     HWLOC_BUILD_ASSERT(PCI_CLASS_DEVICE < CONFIG_SPACE_CACHESIZE);
     device_class = config_space_cache[PCI_CLASS_DEVICE] | 
(config_space_cache[PCI_CLASS_DEVICE+1] << 8);
 #endif
+#endif

     /* is this a bridge? */
     HWLOC_BUILD_ASSERT(PCI_HEADER_TYPE < CONFIG_SPACE_CACHESIZE);
@@ -396,16 +562,24 @@
     obj->attr->pcidev.subdevice_id = config_space_cache[PCI_SUBSYSTEM_ID];

     obj->attr->pcidev.linkspeed = 0; /* unknown */
+    {
 #ifdef HWLOC_HAVE_PCI_FIND_CAP
+    struct pci_cap *cap = pci_find_cap(pcidev, PCI_CAP_ID_EXP, PCI_CAP_NORMAL);
+    unsigned offset;
+    if (cap)
     {
-    struct pci_cap *cap = pci_find_cap(pcidev, PCI_CAP_ID_EXP, PCI_CAP_NORMAL);
-    if (cap) {
-      if (cap->addr + PCI_EXP_LNKSTA >= CONFIG_SPACE_CACHESIZE) {
-        fprintf(stderr, "cannot read PCI_EXP_LNKSTA cap at %d (only %d 
cached)\n", cap->addr + PCI_EXP_LNKSTA, CONFIG_SPACE_CACHESIZE);
+      offset = cap->addr;
+#else
+    unsigned offset = hwloc_pci_find_cap(config_space_cache, 
config_space_cachesize, PCI_CAP_ID_EXP);
+    if (offset > 0)
+    {
+#endif /* HWLOC_HAVE_PCI_FIND_CAP */
+      if (offset + PCI_EXP_LNKSTA + 4 >= config_space_cachesize) {
+        fprintf(stderr, "cannot read PCI_EXP_LNKSTA cap at %d (only %d 
cached)\n", offset + PCI_EXP_LNKSTA, CONFIG_SPACE_CACHESIZE);
       } else {
         unsigned linksta, speed, width;
         float lanespeed;
-        memcpy(&linksta, &config_space_cache[cap->addr + PCI_EXP_LNKSTA], 4);
+        memcpy(&linksta, &config_space_cache[offset + PCI_EXP_LNKSTA], 4);
         speed = linksta & PCI_EXP_LNKSTA_SPEED; /* PCIe generation */
         width = (linksta & PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */
        /* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding    = 
0.25GB/s data-rate per lane
@@ -417,7 +591,6 @@
       }
     }
     }
-#endif /* HWLOC_HAVE_PCI_FIND_CAP */

     if (isbridge) {
       HWLOC_BUILD_ASSERT(PCI_PRIMARY_BUS < CONFIG_SPACE_CACHESIZE);
@@ -437,6 +610,10 @@
  * of arguments, and supports the PCI_LOOKUP_NO_NUMBERS flag.
  */

+#ifdef HWLOC_HAVE_LIBPCIACCESS
+    resname = pci_device_get_vendor_name(pcidev);
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
     resname = pci_lookup_name(pciaccess, name, sizeof(name),
 #if HAVE_DECL_PCI_LOOKUP_NO_NUMBERS
                              PCI_LOOKUP_VENDOR|PCI_LOOKUP_NO_NUMBERS,
@@ -446,9 +623,14 @@
                              pcidev->vendor_id, 0, 0, 0
 #endif
                              );
+#endif
     if (resname)
       hwloc_obj_add_info(obj, "PCIVendor", resname);

+#ifdef HWLOC_HAVE_LIBPCIACCESS
+    resname = pci_device_get_device_name(pcidev);
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
     resname = pci_lookup_name(pciaccess, name, sizeof(name),
 #if HAVE_DECL_PCI_LOOKUP_NO_NUMBERS
                              PCI_LOOKUP_DEVICE|PCI_LOOKUP_NO_NUMBERS,
@@ -458,9 +640,11 @@
                              pcidev->vendor_id, pcidev->device_id, 0, 0
 #endif
                              );
+#endif
     if (resname)
       hwloc_obj_add_info(obj, "PCIDevice", resname);

+#ifdef HWLOC_HAVE_LIBPCI
     resname = pci_lookup_name(pciaccess, name, sizeof(name),
 #if HAVE_DECL_PCI_LOOKUP_NO_NUMBERS
                              
PCI_LOOKUP_VENDOR|PCI_LOOKUP_DEVICE|PCI_LOOKUP_NO_NUMBERS,
@@ -474,6 +658,7 @@
       obj->name = strdup(resname);
     else
       resname = "??";
+#endif

     hwloc_debug("  %04x:%02x:%02x.%01x %04x %04x:%04x %s\n",
                domain, pcidev->bus, pcidev->dev, pcidev->func,
@@ -481,10 +666,14 @@
                resname);

     hwloc_pci_add_object(&fakehostbridge, obj);
-    pcidev = pcidev->next;
   }

+#ifdef HWLOC_HAVE_LIBPCIACCESS
+  pci_system_cleanup();
+#endif
+#ifdef HWLOC_HAVE_LIBPCI
   pci_cleanup(pciaccess);
+#endif

   hwloc_debug("%s", "\nPCI hierarchy after basic scan:\n");
   hwloc_pci_traverse(NULL, &fakehostbridge, hwloc_pci_traverse_print_cb);

Reply via email to