6797039 libpciaccess should use devinfo properties to limit the busses scanned nv_107
authorAlan Coopersmith <Alan.Coopersmith@Sun.COM>
Thu, 22 Jan 2009 16:30:08 -0800
changeset 615 2ce7b8396380
parent 614 5ef3ebaba4c3
child 616 5b9ac7999740
6797039 libpciaccess should use devinfo properties to limit the busses scanned
open-src/lib/libpciaccess/Makefile
open-src/lib/libpciaccess/bus-range.patch
--- a/open-src/lib/libpciaccess/Makefile	Thu Jan 22 16:29:55 2009 -0800
+++ b/open-src/lib/libpciaccess/Makefile	Thu Jan 22 16:30:08 2009 -0800
@@ -2,7 +2,7 @@
 #
 # libpciaccess Makefile
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use subject to license terms.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
@@ -40,6 +40,7 @@
 # Patches to apply to source after unpacking, in order
 SOURCE_PATCHES = \
 	sparc-byteswap.patch,-p1 \
+	bus-range.patch,-p1 \
 	6785726.patch \
 	6789879.patch \
 	scanpci.man.patch 
@@ -60,6 +61,9 @@
 # pkg-config files that need to have -R added
 FIX_PC_FILES=pciaccess.pc.in
 
+# Activate additional debugging code in debug builds
+MODULE_DEBUG_FLAGS=-DDEBUG
+
 include ../Makefile.inc
 
 # Update scanpci.man with program man page flags instead of library ones
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/lib/libpciaccess/bus-range.patch	Thu Jan 22 16:30:08 2009 -0800
@@ -0,0 +1,286 @@
+From 5bf4b32c2b3844c50e720be5820f2ce657ddea12 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Thu, 22 Jan 2009 16:14:22 -0800
+Subject: [PATCH] Solaris: Use bus-range properties to limit busses scanned on each node
+
+Based on code provided by [email protected]
+---
+ src/solx_devfs.c |  116 ++++++++++++++++++++++++++++++++++++++++++------------
+ 1 files changed, 90 insertions(+), 26 deletions(-)
+
+diff --git a/src/solx_devfs.c b/src/solx_devfs.c
+index e184841..99ee1ac 100644
+--- a/src/solx_devfs.c
++++ b/src/solx_devfs.c
+@@ -22,7 +22,7 @@
+  * DEALINGS IN THE SOFTWARE.
+  */
+ /*
+- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
++ * Copyright 2007, 2009 Sun Microsystems, Inc.  All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the
+@@ -68,6 +68,8 @@
+ #include "pciaccess.h"
+ #include "pciaccess_private.h"
+ 
++/* #define DEBUG */
++
+ #define	MAX_DEVICES	256
+ #define	CELL_NUMS_1275	(sizeof(pci_regspec_t) / sizeof(uint_t))
+ 
+@@ -85,12 +87,13 @@ typedef struct i_devnode {
+ 
+ typedef struct nexus {
+     int fd;
+-    int domain;
++    int first_bus;
++    int last_bus;
++    const char *path;		/* for errors/debugging; fd is all we need */
+     struct nexus *next;
+ } nexus_t;
+ 
+ static nexus_t *nexus_list = NULL;
+-static int num_domains = 0;
+ static int xsvc_fd = -1;
+ 
+ /*
+@@ -127,9 +130,6 @@ static int xsvc_fd = -1;
+ # define U45_SB_CLASS_RID	0x06040000
+ #endif
+ 
+-#define	DEBUGON	0
+-
+-
+ static int pci_device_solx_devfs_map_range(struct pci_device *dev,
+     struct pci_device_mapping *map);
+ 
+@@ -174,12 +174,12 @@ static const struct pci_system_methods solx_devfs_methods = {
+ };
+ 
+ static nexus_t *
+-find_nexus_for_domain( int domain )
++find_nexus_for_bus( int bus )
+ {
+     nexus_t *nexus;
+ 
+     for (nexus = nexus_list ; nexus != NULL ; nexus = nexus->next) {
+-	if (nexus->domain == domain) {
++	if ((bus >= nexus->first_bus) && (bus <= nexus->last_bus)) {
+ 	    return nexus;
+ 	}
+     }
+@@ -212,6 +212,7 @@ pci_system_solx_devfs_destroy( void )
+     for (nexus = nexus_list ; nexus != NULL ; nexus = next) {
+ 	next = nexus->next;
+ 	close(nexus->fd);
++	free(nexus->path);
+ 	free(nexus);
+     }
+     nexus_list = NULL;
+@@ -443,7 +444,7 @@ probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, struct pci_system *pci_sys)
+ 	    /*
+ 	     * Domain is peer bus??
+ 	     */
+-	    pci_base->domain = nexus->domain;
++	    pci_base->domain = 0;
+ 	    pci_base->bus = prg_p->bus_no;
+ 	    pci_base->dev = prg_p->dev_no;
+ 	    pci_base->func = func;
+@@ -466,12 +467,20 @@ probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, struct pci_system *pci_sys)
+ 	    pci_sys->devices[pci_sys->num_devices].header_type
+ 					= GET_CONFIG_VAL_8(PCI_CONF_HEADER);
+ 
+-#if DEBUGON
+-	    fprintf(stderr, "busno = %x, devno = %x, funcno = %x\n",
+-		    prg_p->bus_no, prg_p->dev_no, func);
++#ifdef DEBUG
++	    fprintf(stderr,
++		    "nexus = %s, busno = %x, devno = %x, funcno = %x\n",
++		    nexus->path, prg_p->bus_no, prg_p->dev_no, func);
+ #endif
+ 
+-	    pci_sys->num_devices++;
++	    if (pci_sys->num_devices < (MAX_DEVICES - 1)) {
++		pci_sys->num_devices++;
++	    } else {
++		(void) fprintf(stderr,
++			       "Maximum number of PCI devices found,"
++			       " discarding additional devices\n");
++	    }
++
+ 
+ 	    /*
+ 	     * Accommodate devices which state their
+@@ -495,17 +504,67 @@ static int
+ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
+ {
+     struct pci_system *pci_sys = (struct pci_system *) arg;
+-    char *nexus_name;
++    const char *nexus_name;
+     nexus_t *nexus;
+     int fd;
+     char nexus_path[MAXPATHLEN];
+ 
++    di_prop_t prop;
++    const char *strings;
++    int *ints;
++    int numval;
++    int pci_node = 0;
++    int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M);
++
++#ifdef DEBUG
++    nexus_name = di_devfs_minor_path(minor);
++    fprintf(stderr, "-- device name: %s\n", nexus_name);
++#endif
++
++    for (prop = di_prop_next(di_node, NULL); prop != NULL;
++	 prop = di_prop_next(di_node, prop)) {
++
++	const char *prop_name = di_prop_name(prop);
++
++#ifdef DEBUG
++	fprintf(stderr, "   property: %s\n", prop_name);
++#endif
++
++	if (strcmp(prop_name, "device_type") == 0) {
++	    numval = di_prop_strings(prop, &strings);
++	    if (numval != 1 || strncmp(strings, "pci", 3) != 0) {
++		/* not a PCI node, bail */
++		return (DI_WALK_CONTINUE);
++	    }
++	    pci_node = 1;
++	}
++	else if (strcmp(prop_name, "class-code") == 0) {
++	    /* not a root bus node, bail */
++	    return (DI_WALK_CONTINUE);
++	}
++	else if (strcmp(prop_name, "bus-range") == 0) {
++	    numval = di_prop_ints(prop, &ints);
++	    if (numval == 2) {
++		first_bus = ints[0];
++		last_bus = ints[1];
++	    }
++	}
++    }
++
++#ifdef __x86  /* sparc pci nodes don't have the device_type set */
++    if (pci_node != 1)
++	return (DI_WALK_CONTINUE);
++#endif
++
++    /* we have a PCI root bus node. */
+     nexus = calloc(1, sizeof(nexus_t));
+     if (nexus == NULL) {
+ 	(void) fprintf(stderr, "Error allocating memory for nexus: %s\n",
+ 		       strerror(errno));
+-	return DI_WALK_TERMINATE;
++	return (DI_WALK_TERMINATE);
+     }
++    nexus->first_bus = first_bus;
++    nexus->last_bus = last_bus;
+ 
+     nexus_name = di_devfs_minor_path(minor);
+     if (nexus_name == NULL) {
+@@ -517,14 +576,20 @@ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
+ 
+     snprintf(nexus_path, sizeof(nexus_path), "/devices%s", nexus_name);
+     di_devfs_path_free(nexus_name);
++    nexus->path = strdup(nexus_path);
++
++#ifdef DEBUG
++    fprintf(stderr, "nexus = %s, bus-range = %d - %d\n",
++	    nexus_path, first_bus, last_bus);
++#endif
+ 
+     if ((fd = open(nexus_path, O_RDWR)) >= 0) {
+ 	nexus->fd = fd;
+-	nexus->domain = num_domains++;
+ 	if ((do_probe(nexus, pci_sys) != 0) && (errno != ENXIO)) {
+ 	    (void) fprintf(stderr, "Error probing node %s: %s\n",
+ 			   nexus_path, strerror(errno));
+ 	    (void) close(fd);
++	    free(nexus->path);
+ 	    free(nexus);
+ 	} else {
+ 	    nexus->next = nexus_list;
+@@ -533,6 +598,7 @@ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
+     } else {
+ 	(void) fprintf(stderr, "Error opening %s: %s\n",
+ 		       nexus_path, strerror(errno));
++	free(nexus->path);
+ 	free(nexus);
+     }
+ 
+@@ -553,9 +619,9 @@ do_probe(nexus_t *nexus, struct pci_system *pci_sys)
+     pcitool_reg_t prg;
+     uint32_t bus;
+     uint8_t dev;
+-    uint32_t last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT;
++    uint32_t last_bus = nexus->last_bus;
+     uint8_t last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT;
+-    uint8_t first_bus = 0;
++    uint8_t first_bus = nexus->first_bus;
+     uint8_t first_dev = 0;
+     int rval = 0;
+ 
+@@ -593,9 +659,6 @@ do_probe(nexus_t *nexus, struct pci_system *pci_sys)
+ 	    rval = 0;
+ 	}
+     }
+-    if (pci_sys->num_devices > MAX_DEVICES) {
+-	(void) fprintf(stderr, "pci devices reach maximum number\n");
+-    }
+ 
+     return (rval);
+ }
+@@ -634,7 +697,7 @@ find_target_node(di_node_t node, void *arg)
+     len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &regbuf);
+ 
+     if (len <= 0) {
+-#if DEBUGON
++#ifdef DEBUG
+ 	fprintf(stderr, "error = %x\n", errno);
+ 	fprintf(stderr, "can not find assigned-address\n");
+ #endif
+@@ -808,7 +871,7 @@ pci_device_solx_devfs_read_rom( struct pci_device * dev, void * buffer )
+ 	.size = dev->rom_size,
+ 	.flags = 0
+     };
+-    
++
+     err = pci_device_solx_devfs_map_range(dev, &prom);
+     if (err == 0) {
+ 	(void) bcopy(prom.memory, buffer, dev->rom_size);
+@@ -831,7 +894,7 @@ pci_device_solx_devfs_read( struct pci_device * dev, void * data,
+     pcitool_reg_t cfg_prg;
+     int err = 0;
+     int i = 0;
+-    nexus_t *nexus = find_nexus_for_domain(dev->domain);
++    nexus_t *nexus = find_nexus_for_bus(dev->bus);
+ 
+     *bytes_read = 0;
+ 
+@@ -852,7 +915,8 @@ pci_device_solx_devfs_read( struct pci_device * dev, void * data,
+ 	cfg_prg.offset = offset + i;
+ 
+ 	if ((err = ioctl(nexus->fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) {
+-	    fprintf(stderr, "read bdf<%x,%x,%x,%llx> config space failure\n",
++	    fprintf(stderr, "read bdf<%s,%x,%x,%x,%llx> config space failure\n",
++		    nexus->path,
+ 		    cfg_prg.bus_no,
+ 		    cfg_prg.dev_no,
+ 		    cfg_prg.func_no,
+@@ -882,7 +946,7 @@ pci_device_solx_devfs_write( struct pci_device * dev, const void * data,
+     pcitool_reg_t cfg_prg;
+     int err = 0;
+     int cmd;
+-    nexus_t *nexus = find_nexus_for_domain(dev->domain);
++    nexus_t *nexus = find_nexus_for_bus(dev->bus);
+ 
+     if ( bytes_written != NULL ) {
+ 	*bytes_written = 0;
+-- 
+1.5.6.5
+