Bug #6583: Only open /proc/bus/pci/devices once. (Bill Nottingham)
This commit is contained in:
parent
a9ed5a8790
commit
56f21bda1c
|
@ -94,6 +94,10 @@
|
||||||
* os/utils.c:
|
* os/utils.c:
|
||||||
Remove LBX. Goodbye.
|
Remove LBX. Goodbye.
|
||||||
|
|
||||||
|
* hw/xfree86/os-support/bus/linuxPci.c:
|
||||||
|
* hw/xfree86/os-support/linux/lnx_pci.c:
|
||||||
|
Bug #6583: Only parse /proc/bus/pci/devices once. (Bill Nottingham)
|
||||||
|
|
||||||
2006-05-30 Matthieu Herrb <matthieu.herrb@laas.fr>
|
2006-05-30 Matthieu Herrb <matthieu.herrb@laas.fr>
|
||||||
|
|
||||||
* hw/xfree86/os-support/bsd/Makefile.am:
|
* hw/xfree86/os-support/bsd/Makefile.am:
|
||||||
|
|
|
@ -130,16 +130,28 @@ linuxPciOpenFile(PCITAG tag, Bool write)
|
||||||
{
|
{
|
||||||
static int lbus,ldev,lfunc,fd = -1,is_write = 0;
|
static int lbus,ldev,lfunc,fd = -1,is_write = 0;
|
||||||
int bus, dev, func;
|
int bus, dev, func;
|
||||||
char file[32];
|
char file[64];
|
||||||
struct stat ignored;
|
struct stat ignored;
|
||||||
|
static int is26 = -1;
|
||||||
|
|
||||||
bus = PCI_BUS_FROM_TAG(tag);
|
bus = PCI_BUS_FROM_TAG(tag);
|
||||||
dev = PCI_DEV_FROM_TAG(tag);
|
dev = PCI_DEV_FROM_TAG(tag);
|
||||||
func = PCI_FUNC_FROM_TAG(tag);
|
func = PCI_FUNC_FROM_TAG(tag);
|
||||||
|
if (is26 == -1) {
|
||||||
|
if (stat("/sys/bus/pci",&ignored) < 0)
|
||||||
|
is26 = 0;
|
||||||
|
else
|
||||||
|
is26 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (fd == -1 || (write && (!is_write))
|
if (fd == -1 || (write && (!is_write))
|
||||||
|| bus != lbus || dev != ldev || func != lfunc) {
|
|| bus != lbus || dev != ldev || func != lfunc) {
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
if (is26)
|
||||||
|
sprintf(file,"/sys/bus/pci/devices/0000:%02x:%02x.%01x/config",
|
||||||
|
bus, dev, func);
|
||||||
|
else {
|
||||||
if (bus < 256) {
|
if (bus < 256) {
|
||||||
sprintf(file,"/proc/bus/pci/%02x",bus);
|
sprintf(file,"/proc/bus/pci/%02x",bus);
|
||||||
if (stat(file, &ignored) < 0)
|
if (stat(file, &ignored) < 0)
|
||||||
|
@ -157,6 +169,7 @@ linuxPciOpenFile(PCITAG tag, Bool write)
|
||||||
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x",
|
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x",
|
||||||
bus, dev, func);
|
bus, dev, func);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (write) {
|
if (write) {
|
||||||
fd = open(file,O_RDWR);
|
fd = open(file,O_RDWR);
|
||||||
if (fd != -1) is_write = TRUE;
|
if (fd != -1) is_write = TRUE;
|
||||||
|
|
|
@ -23,38 +23,41 @@
|
||||||
#define PCIADDR_FMT "%lx"
|
#define PCIADDR_FMT "%lx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FILE *xf86OSLinuxPCIFile = NULL;
|
struct pci_dev {
|
||||||
|
unsigned int bus;
|
||||||
|
unsigned int devfn;
|
||||||
|
PCIADDR_TYPE offset[7];
|
||||||
|
PCIADDR_TYPE size[7];
|
||||||
|
struct pci_dev *next;
|
||||||
|
};
|
||||||
|
|
||||||
Bool
|
struct pci_dev *xf86OSLinuxPCIDevs = NULL;
|
||||||
xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
|
|
||||||
{
|
static struct pci_dev *xf86OSLinuxGetPciDevs(void) {
|
||||||
char c[0x200];
|
char c[0x200];
|
||||||
char *res;
|
FILE *file = NULL;
|
||||||
unsigned int bus, devfn, dev, fn;
|
struct pci_dev *tmp, *ret = NULL;
|
||||||
unsigned PCIADDR_TYPE size[7];
|
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
signed PCIADDR_TYPE Size;
|
char *res;
|
||||||
|
|
||||||
if (index > 7)
|
file = fopen("/proc/bus/pci/devices", "r");
|
||||||
return FALSE;
|
if (!file) return NULL;
|
||||||
|
|
||||||
if (!xf86OSLinuxPCIFile && \
|
|
||||||
!(xf86OSLinuxPCIFile = fopen("/proc/bus/pci/devices","r")))
|
|
||||||
return FALSE;
|
|
||||||
do {
|
do {
|
||||||
res = fgets(c,0x1ff,xf86OSLinuxPCIFile);
|
res = fgets(c, 0x1ff, file);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
tmp = xcalloc(sizeof(struct pci_dev),1);
|
||||||
num = sscanf(res,
|
num = sscanf(res,
|
||||||
/*bus+dev vendorid deviceid irq */
|
/*bus+dev vendorid deviceid irq */
|
||||||
"%02x%02x\t%*04x%*04x\t%*x"
|
"%02x%02x\t%*04x%*04x\t%*x"
|
||||||
/* 7 PCI resource base addresses */
|
/* 7 PCI resource base addresses */
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
"\t" PCIADDR_FMT
|
||||||
/* 7 PCI resource sizes, and then optionally a driver name */
|
/* 7 PCI resource sizes, and then optionally a driver name */
|
||||||
"\t" PCIADDR_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_FMT
|
"\t" PCIADDR_FMT
|
||||||
|
@ -63,30 +66,56 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
|
||||||
"\t" PCIADDR_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_FMT
|
"\t" PCIADDR_FMT
|
||||||
"\t" PCIADDR_FMT,
|
"\t" PCIADDR_FMT,
|
||||||
&bus,&devfn,&size[0],&size[1],&size[2],&size[3],
|
&tmp->bus,&tmp->devfn,&tmp->offset[0],&tmp->offset[1],&tmp->offset[2],&tmp->offset[3],
|
||||||
&size[4],&size[5],&size[6]);
|
&tmp->offset[4],&tmp->offset[5],&tmp->offset[6], &tmp->size[0], &tmp->size[1], &tmp->size[2],
|
||||||
if (num != 9) { /* apparantly not 2.3 style */
|
&tmp->size[3], &tmp->size[4], &tmp->size[5], &tmp->size[6]);
|
||||||
fseek(xf86OSLinuxPCIFile, 0L, SEEK_SET);
|
if (num != 16) { /* apparantly not 2.3 style */
|
||||||
return FALSE;
|
xfree(tmp);
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
dev = devfn >> 3;
|
if (ret) {
|
||||||
fn = devfn & 0x7;
|
tmp->next = ret;
|
||||||
if (tag == pciTag(bus,dev,fn)) {
|
}
|
||||||
|
ret = tmp;
|
||||||
|
}
|
||||||
|
} while (res);
|
||||||
|
fclose(file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool
|
||||||
|
xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
|
||||||
|
{
|
||||||
|
unsigned int dev, fn;
|
||||||
|
signed PCIADDR_TYPE Size;
|
||||||
|
struct pci_dev *device;
|
||||||
|
|
||||||
|
if (index > 7)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!xf86OSLinuxPCIDevs) {
|
||||||
|
xf86OSLinuxPCIDevs = xf86OSLinuxGetPciDevs();
|
||||||
|
}
|
||||||
|
if (!xf86OSLinuxPCIDevs)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
|
||||||
|
dev = device->devfn >> 3;
|
||||||
|
fn = device->devfn & 0x7;
|
||||||
|
if (tag == pciTag(device->bus,dev,fn)) {
|
||||||
*bits = 0;
|
*bits = 0;
|
||||||
if (size[index] != 0) {
|
if (device->size[index] != 0) {
|
||||||
Size = size[index] - ((PCIADDR_TYPE) 1);
|
Size = device->size[index] - ((PCIADDR_TYPE) 1);
|
||||||
while (Size & ((PCIADDR_TYPE) 0x01)) {
|
while (Size & ((PCIADDR_TYPE) 0x01)) {
|
||||||
Size = Size >> ((PCIADDR_TYPE) 1);
|
Size = Size >> ((PCIADDR_TYPE) 1);
|
||||||
(*bits)++;
|
(*bits)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fseek(xf86OSLinuxPCIFile, 0L, SEEK_SET);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (res);
|
|
||||||
|
|
||||||
fseek(xf86OSLinuxPCIFile, 0L, SEEK_SET);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,59 +125,28 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
|
||||||
Bool
|
Bool
|
||||||
xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases)
|
xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases)
|
||||||
{
|
{
|
||||||
FILE *file;
|
unsigned int dev, fn;
|
||||||
char c[0x200];
|
struct pci_dev *device;
|
||||||
char *res;
|
|
||||||
unsigned int bus, devfn, dev, fn;
|
|
||||||
unsigned PCIADDR_TYPE offset[7];
|
|
||||||
unsigned int num;
|
|
||||||
|
|
||||||
if (index > 7)
|
if (index > 7)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!(file = fopen("/proc/bus/pci/devices","r")))
|
if (!xf86OSLinuxPCIDevs) {
|
||||||
return FALSE;
|
xf86OSLinuxPCIDevs = xf86OSLinuxGetPciDevs();
|
||||||
do {
|
|
||||||
res = fgets(c,0x1ff,file);
|
|
||||||
if (res) {
|
|
||||||
num = sscanf(res,
|
|
||||||
/*bus+dev vendorid deviceid irq */
|
|
||||||
"%02x%02x\t%*04x%*04x\t%*x"
|
|
||||||
/* 7 PCI resource base addresses */
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
/* 7 PCI resource sizes, and then optionally a driver name */
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT
|
|
||||||
"\t" PCIADDR_IGNORE_FMT,
|
|
||||||
&bus,&devfn,&offset[0],&offset[1],&offset[2],&offset[3],
|
|
||||||
&offset[4],&offset[5],&offset[6]);
|
|
||||||
if (num != 9) { /* apparantly not 2.3 style */
|
|
||||||
fclose(file);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
if (!xf86OSLinuxPCIDevs)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
dev = devfn >> 3;
|
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
|
||||||
fn = devfn & 0x7;
|
dev = device->devfn >> 3;
|
||||||
if (tag == pciTag(bus,dev,fn)) {
|
fn = device->devfn & 0x7;
|
||||||
|
if (tag == pciTag(device->bus,dev,fn)) {
|
||||||
/* return the offset for the index requested */
|
/* return the offset for the index requested */
|
||||||
*bases = offset[index];
|
*bases = device->offset[index];
|
||||||
fclose(file);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (res);
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,50 +154,21 @@ xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases)
|
||||||
unsigned long
|
unsigned long
|
||||||
xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base)
|
xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base)
|
||||||
{
|
{
|
||||||
FILE *file;
|
unsigned int dev, fn;
|
||||||
char c[0x200];
|
|
||||||
char *res;
|
|
||||||
unsigned int bus, devfn, dev, fn;
|
|
||||||
unsigned PCIADDR_TYPE offset[7];
|
|
||||||
unsigned PCIADDR_TYPE size[7];
|
|
||||||
unsigned int num;
|
|
||||||
unsigned int ndx;
|
unsigned int ndx;
|
||||||
|
struct pci_dev *device;
|
||||||
|
|
||||||
if (!(file = fopen("/proc/bus/pci/devices","r")))
|
if (!xf86OSLinuxPCIDevs) {
|
||||||
return 0;
|
xf86OSLinuxPCIDevs = xf86OSLinuxGetPciDevs();
|
||||||
do {
|
}
|
||||||
res = fgets(c,0x1ff,file);
|
if (!xf86OSLinuxPCIDevs) {
|
||||||
if (res) {
|
return FALSE;
|
||||||
num = sscanf(res,
|
|
||||||
/*bus+dev vendorid deviceid irq */
|
|
||||||
"%02x%02x\t%*04x%*04x\t%*x"
|
|
||||||
/* 7 PCI resource base addresses */
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
/* 7 PCI resource sizes, and then optionally a driver name */
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT
|
|
||||||
"\t" PCIADDR_FMT,
|
|
||||||
&bus,&devfn,&offset[0],&offset[1],&offset[2],&offset[3],
|
|
||||||
&offset[4],&offset[5],&offset[6], &size[0], &size[1], &size[2],
|
|
||||||
&size[3], &size[4], &size[5], &size[6]);
|
|
||||||
if (num != 16) { /* apparantly not 2.3 style */
|
|
||||||
fclose(file);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = devfn >> 3;
|
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
|
||||||
fn = devfn & 0x7;
|
dev = device->devfn >> 3;
|
||||||
if (tag == pciTag(bus,dev,fn)) {
|
fn = device->devfn & 0x7;
|
||||||
|
if (tag == pciTag(device->bus, dev, fn)) {
|
||||||
/* ok now look through all the BAR values of this device */
|
/* ok now look through all the BAR values of this device */
|
||||||
pciConfigPtr pDev = xf86GetPciConfigFromTag(tag);
|
pciConfigPtr pDev = xf86GetPciConfigFromTag(tag);
|
||||||
|
|
||||||
|
@ -221,16 +190,13 @@ xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base)
|
||||||
savePtr &= flagMask;
|
savePtr &= flagMask;
|
||||||
|
|
||||||
/* find the index of the incoming base */
|
/* find the index of the incoming base */
|
||||||
if (base >= savePtr && base < (savePtr + size[ndx])) {
|
if (base >= savePtr && base < (savePtr + device->size[ndx])) {
|
||||||
fclose(file);
|
return (device->offset[ndx] & flagMask) + (base - savePtr);
|
||||||
return (offset[ndx] & flagMask) + (base - savePtr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
} while (res);
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue