"Ronald G. Minnich" rminnich@lanl.gov writes:
On 14 Feb 2003, Eric W. Biederman wrote:
So what I am looking at:
The current pci bus scan starts with a root pci bus device. And then finds the devices on that bus, and the recursively scans the sub busses.
O.k. Getting into specifics:
From our pci.h, the current operations we have for a pci device.
struct pci_dev_operations { void (*read_resources)(struct pci_dev *dev); void (*set_resources)(struct pci_dev *dev); void (*init)(struct pci_dev *dev); unsigned int (*scan_bus)(struct pci_dev *bus, unsigned int max); };
I'm still not getting it.
For some chips, LinuxBIOS needs to call some chip-specific code for that device BEFORE the pci bus scan, or resource allocation gets done incorrectly. How can we structure the code so that the pre-pci init functions work in a reasonable way that most people can understand? The current superio stuff does this, and the information to drive it is contained in the superio file. If you have code that needs to be called before the PCI scan, you initalize the structure member to point to a function. Same for after PCI scan, same for right before hardwaremain() exits. You can look at the superio.c file for the given chip and see if this pre-pci-scan function exists and is called.
O.k. The superio code I definitely figure is a step in that direction.
This discussion must get into nitty gritty specifics if we are going to reach a consensus.
What we currently do: pci_enumerate(); pci_configure(); pci_initialize();
In pci_enumerate(), If a device is in the hard coded list it is placed into the list of pci devices even if it does not exist. This allows invisible devices on the motherboard to be configured.
In addition each device is assigned a set of operations. set_pci_ops does that work.
set_pci_ops first looks through a table of device drivers and listed by vendor and device id to see if it can find a specific driver for that device. If a driver is found it uses those device methods. Otherwise depending if it is a bridge or a normal pci device a default set of methods is assigned.
After pci_scan_bus finishes enumerating the devices on a bus. It looks at each child device to see if it has a scan_bus method. And if so it calls child->ops->scan_bus(). Which is usually just pci_scan_bus again.
In pci_configure. The device tree is walked again. And for each device it's read_resources operation is called, to find the bar's on that device. read_resources allows for the presence of non standard bars. Each bar read_resources returns can either be a fixed resource, that must be catered to. Or a resource needing to be assigned a value.
Then a second pass is made to the tree and set_resources is called on each device.
For bridges, read_resources, and set_resources are recursive.
In pci_initialize. The device tree is walked one last time, and this time the init() method of each device is called.
I like the self-contained nature of the superio.c files (I grabbed all those ideas from Plan 9). Does this seem desirable to people?
Yes. Self contained is good. The one part my newer pci code that is lacking that you did well on the superio code is a way to build the static device information. I suspect we want to allow a different structure for each different device, but basically I like the superio directive.
If so, can we expand it to the south and north bridges so as to replace the current ad-hoc mechanisms?
Look at what I have done with pci. Essentially I have already done that. Everything but making the configuration manageable.
If this mechanism is not desirable, how would it change? Would the .c files continue to be self-contained or would we start getting into more linker sets and other magic stuff (which, as you can tell, worries me as it does confuse people).
The only magic thing that I might touch with a linker is building the table of devices. But that is to make things more self contained.
I would appreciate some feedback from the other committers and developers.
Agreed. Just Eric talking is imperfect.
I just looked through the LinuxBIOS tree at every superio.c. And perhaps I missed something but I did not see a single superio file that used more than one of the three functions defined, and none of them used the pre pci function.
So all of those I can straight forwardly transformed so their init or finishup method is converted into a pci init method and called from pci_initialize().
For the hypothetical case of needing a device that is called before the rest of the pci initialization, it can be forced into the device tree ahead of everything else. And it's scan_bus method can do what special magic is required.
Similarly for the hypothetical case of needing a device that is called after everything else, a dummy device can be inserted way at the bottom and the end of the pci device tree, so that it's init method will be called last.
So it is possible in a nasty way to cope with those hypothetical situations. Buying time for a clean fix to be put into the LinuxBIOS tree.
If you have specific examples of things that need to be done I am quite willing to discuss them and how I would fit it into the new frame work.
The code flow I am confident of. The mechanism to configure it that I do not currently have that problem solved. But I suspect we can use something like the current superio configuration to statically build parts of the device tree.
Eric