Ditching pci init data

Luca Lizzeri (ll@niche.it)
Sat, 19 Apr 1997 21:28:18 +0200


Hi,

In case nobody has done this yet, I have modified the pci init code to ditch
unneeded functions and data after startup. This is interesting because of the
size of the dev_info static array. After system initialization we keep around
info only on the devces present on the system.

It seems to have no adverse effects, but keep in mind that this is a first for
me ... :) Hope this gives the right ideas to whoever can implement it in a
cleaner way.

The patch is against 2.1.35.

Cheers,
Luca

--- linux/drivers/pci/pci.c.orig Sat Apr 19 11:29:55 1997
+++ linux/drivers/pci/pci.c Sat Apr 19 21:13:14 1997
@@ -13,12 +13,16 @@
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/string.h>
+#include <linux/init.h>

#include <asm/page.h>

+static void *pci_malloc(long , unsigned long*);
+
struct pci_bus pci_root;
struct pci_dev *pci_devices = 0;

+struct pci_dev_info_list *dev_info = NULL;

/*
* The bridge_id field is an offset of an item into the array
@@ -39,8 +43,9 @@
* Sorted in ascending order by vendor and device.
* Use binary search for lookup. If you add a device make sure
* it is sequential by both vendor and device id.
+ * This gets ditched after initialization.
*/
-struct pci_dev_info dev_info[] = {
+struct pci_dev_info init_dev_info[] __initdata = {
DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p"),
DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN"),
DEVICE( NCR, NCR_53C810, "53c810"),
@@ -362,19 +367,19 @@
/*
* device_info[] is sorted so we can use binary search
*/
-struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
+__initfunc(struct pci_dev_info *pci_init_lookup_dev(unsigned int vendor, unsigned int dev))
{
int min = 0,
- max = sizeof(dev_info)/sizeof(dev_info[0]) - 1;
+ max = sizeof(init_dev_info)/sizeof(init_dev_info[0]) - 1;

for ( ; ; )
{
int i = (min + max) >> 1;
long order;

- order = dev_info[i].vendor - (long) vendor;
+ order = init_dev_info[i].vendor - (long) vendor;
if (!order)
- order = dev_info[i].device - (long) dev;
+ order = init_dev_info[i].device - (long) dev;

if (order < 0)
{
@@ -392,10 +397,51 @@
continue;
}

- return & dev_info[ i ];
+ return & init_dev_info[ i ];
}
}

+/* This is the one that gets called after system initialization. */
+
+struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
+{
+ struct pci_dev_info_list *temp = dev_info;
+
+ while(temp) {
+
+ if ((temp->device_info.vendor == vendor) &&
+ (temp->device_info.device == dev))
+ return &(temp->device_info);
+
+ temp = temp->next;
+
+ }
+
+ return 0;
+}
+
+/* This is used to insert a device into the permanent device list */
+
+__initfunc(static void insert_pci_dev(struct pci_dev_info *dev, unsigned long *mem_startp))
+{
+ struct pci_dev_info_list *temp;
+
+ temp = pci_malloc(sizeof(struct pci_dev_info_list), mem_startp);
+ temp->device_info.name = pci_malloc(strlen(dev->name) + 1, mem_startp);
+
+ temp->next = dev_info;
+ temp->device_info.device = dev->device;
+ temp->device_info.vendor = dev->vendor;
+ strcpy(temp->device_info.name, dev->name);
+ temp->device_info.bridge_type = dev->bridge_type;
+
+ dev_info = temp;
+
+ return;
+
+}
+
+
const char *pci_strclass (unsigned int class)
{
switch (class >> 8) {
@@ -790,7 +836,7 @@
* pci_malloc() returns initialized memory of size SIZE. Can be
* used only while pci_init() is active.
*/
-static void *pci_malloc(long size, unsigned long *mem_startp)
+__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
{
void *mem;

@@ -804,7 +850,7 @@
}


-static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
+__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp))
{
unsigned int devfn, l, max;
unsigned char cmd, tmp, hdr_type = 0;
@@ -853,11 +899,14 @@
* a message at boot time. This is the only way to
* learn about new hardware...
*/
- info = pci_lookup_dev(dev->vendor, dev->device);
+ info = pci_init_lookup_dev(dev->vendor, dev->device);
if (!info) {
printk("Warning : Unknown PCI device (%x:%x). Please read include/linux/pci.h \n",
dev->vendor, dev->device);
} else {
+ /* Insert it into the permanent list of pci devices */
+ insert_pci_dev(info,mem_startp);
+
/* Some BIOS' are lazy. Let's do their job: */
if (info->bridge_type != 0xff) {
burst_bridge(bus->number, devfn,
@@ -979,7 +1028,7 @@
}


-unsigned long pci_init (unsigned long mem_start, unsigned long mem_end)
+__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end))
{
mem_start = pcibios_init(mem_start, mem_end);

--- linux/include/linux/pci.h.orig Sat Apr 19 13:10:03 1997
+++ linux/include/linux/pci.h Sat Apr 19 20:46:05 1997
@@ -688,8 +688,13 @@
unsigned short vendor; /* vendor id */
unsigned short device; /* device id */

- const char *name; /* device name */
+ char *name; /* device name */
unsigned char bridge_type; /* bridge type or 0xff */
+};
+
+struct pci_dev_info_list {
+ struct pci_dev_info device_info;
+ struct pci_dev_info_list *next;
};

extern struct pci_bus pci_root; /* root bus */