Detect hwmon and i2c bus drivers interfering with ACPI Operation Region resources
Subsystems (2)
cover Detect hwmon and i2c bus drivers interfering with ACPI Operation Region resources
Hi,
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.
Be aware that there is a small change in ACPICA (first patch, that's also the reason why this one would not compile on its own).
Many thanks for detailed review, testing and a lot implementation help go to Jean Delvare, without his help I would not be able to post anything right now.
Thanks for any help/advise,
Thomas
--------------
Short general description:
In ACPI, AML can define accesses to IO ports and System Memory by Operation Regions. Those are not registered as done by PNPACPI using resource templates (and _CRS/_SRS methods).
The IO ports and System Memory regions may get accessed by arbitrary AML code. When native drivers are accessing the same resources bad things can happen (e.g. a critical shutdown temperature of 3000 C every 2 months or so).
It is not really possible to register the operation regions via request_resource, as they often overlap with pnp or other resources (e.g. statically setup IO resources below 0x100).
This approach stores all Operation Region declarations (IO and System Memory only) at ACPI table parse time. It offers a similar functionality like request_region and let drivers which are known to possibly use the same IO ports and Memory which are also often used by ACPI (hwmon and i2c) check for ACPI interference.
A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.
Goal of this patch set is:
- Identify ACPI interferences in bug reports (very hard to reproduce and to identify)
- Find BIOSes for that an ACPI driver should exist for specific HW instead of a native one.
- stability in general
Quoted 10 lines · On Wed, 24 Oct 2007 16:31:59 +0200 Thomas Renninger <[email protected]> wrote:
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.
I staged the three acpi patches against Len's tree and I staged the hwmon patch against Mark's tree and I staged the I2C patch against Jean's tree.
This means that if/when the ACPI patches have gone me->Len->Linus, I can send the I2C patch to Jean and the hwmon patch to Mark and we're all good.
Quoted 13 lines · Andrew Morton
Quoted 10 lines · On Wed, 24 Oct 2007 16:31:59 +0200 Thomas Renninger <[email protected]> wrote:
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.
Quoted 5 lines
I staged the three acpi patches against Len's tree and I staged the hwmon patch against Mark's tree and I staged the I2C patch against Jean's tree.
This means that if/when the ACPI patches have gone
me->Len->Linus, I can send the I2C patch to Jean and the hwmon patch to Mark and we're all good.
Thanks for picking these patches, having them in -mm for some time is exactly what we need. Let's see how many systems are affected by the resource conflicts and how we can fix them
Signature · 1 line
Jean Delvare
Quoted 17 lines · On Thu, 25 Oct 2007 15:51:35 +0200 Jean Delvare <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 10 lines · On Wed, 24 Oct 2007 16:31:59 +0200 Thomas Renninger <[email protected]> wrote:
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.I staged the three acpi patches against Len's tree and I staged the hwmon patch against Mark's tree and I staged the I2C patch against Jean's tree.
Quoted 6 lines
Quoted 2 lines
This means that if/when the ACPI patches have gone
me->Len->Linus, I can send the I2C patch to Jean and the hwmon patch to Mark and we're all good.Thanks for picking these patches, having them in -mm for some time is exactly what we need. Let's see how many systems are affected by the resource conflicts and how we can fix them
No probs. The main thing is to ensure that we have sufficient debug support in that patch so that if a tester does report a problem, we (ie:
you ;) can resolve it on the first pass. So feel free to make it really noisy - we can always drop the debug stuff later on.
Also, please try to avoid adding anythig which would disrupt that tester from going on and testing all the other new code. ie: try to fail gracefully and fall back to the old behaviour.
Hi Andrew,
Quoted 9 lines · Andrew Morton
Quoted 3 lines · Jean Delvare
Thanks for picking these patches, having them in -mm for some time is exactly what we need. Let's see how many systems are affected by the resource conflicts and how we can fix them
No probs. The main thing is to ensure that we have sufficient debug support in that patch so that if a tester does report a problem, we (ie:
you ;) can resolve it on the first pass. So feel free to make it really noisy - we can always drop the debug stuff later on.
Well, I'm not exactly sure what we can do when people report conflicts, except telling them "don't do that". I guess each case will be different. We will have to ask reporters for their DSDT table, look at it and... do something. I'll need (much) help from the ACPI developers. At this point we are mainly trying to gather enough data to fully understand how big the problem is. Solutions will come later.
Quoted 3 lines
Also, please try to avoid adding anythig which would disrupt that tester from going on and testing all the other new code. ie: try to fail gracefully and fall back to the old behaviour.
User will simply miss their SMBus controller or their hardware monitoring device, it wont prevent them from using their systems, but that should be enough to get them to report (I hope).
Signature · 1 line
Jean Delvare
Hi Thomas:
I recently told someone in private that ACPI vs. hwmon conflicts are the biggest open problems for the hwmon subsystem. Thank you (and Jean) for doing this.
Quoted 5 lines · Thomas Renninger
Hi,
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Quoted 7 lines
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.
Andrew has already picked this series; I vote for extended time in -mm. On the hwmon side, there is almost guaranteed to be fallout from this that may take time to resolve.
Quoted 9 lines
(...)
A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.
As long as it's in -mm, you may as well default to =strict right away. This will force people to report. Open the floodgates; I hope I don't drown.
Regards,
Signature · 2 lines
Mark M. Hoffman [email protected]
Hi Mark,
Quoted 20 lines · Mark M. Hoffman
Hi Thomas:
I recently told someone in private that ACPI vs. hwmon conflicts are the biggest open problems for the hwmon subsystem. Thank you (and Jean) for doing this.
Quoted 5 lines · Thomas Renninger
Hi,
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Quoted 7 lines
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.
Quoted 3 lines
Andrew has already picked this series; I vote for extended time in -mm. On the hwmon side, there is almost guaranteed to be fallout from this that may take time to resolve.
Of course, otherwise we wouldn't have done it ;)
Quoted 10 lines
Quoted 7 lines
A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.As long as it's in -mm, you may as well default to =strict right away. This will force people to report. Open the floodgates; I hope I don't drown.
Good point. Here's a patch. Andrew, can you please apply this on top of the other patches? Thanks.
Subject: Enforce ACPI resource conflict checks
In -mm, enforce ACPI resource conflict checks, so that users will report to us.
This patch is NOT meant to go to Linus at this point.
--- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/osl.c +1 -1
@@ -1076,7 +1076,7 @@ __setup("acpi_wake_gpes_always_on", acpi#define ENFORCE_RESOURCES_LAX 1#define ENFORCE_RESOURCES_NO 0 -static unsigned int acpi_enforce_resources =ENFORCE_RESOURCES_LAX ; +static unsigned int acpi_enforce_resources =ENFORCE_RESOURCES_STRICT ;static int __init acpi_enforce_resources_setup (char *str) {
Signature · 1 line
Jean Delvare
Quoted 11 lines · Thomas Renninger
In ACPI, AML can define accesses to IO ports and System Memory by Operation Regions. Those are not registered as done by PNPACPI using resource templates (and _CRS/_SRS methods).
The IO ports and System Memory regions may get accessed by arbitrary AML code. When native drivers are accessing the same resources bad things can happen (e.g. a critical shutdown temperature of 3000 C every 2 months or so).It is not really possible to register the operation regions via
request_resource, as they often overlap with pnp or other resources (e.g. statically setup IO resources below0x100).
But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
If these opregion resources aren't reserved, but are only put in the ACPI resource_list, we will only find conflicts with drivers that use acpi_check_resource_conflict(). Any driver unmodified by your changeset could still have a conflict, and we'd never find it.
Isn't the real problem that we have a bunch of drivers that use some of the same resources, and if ACPI reserved all the right resources, all those drivers would break?
I think it would be better to:
- Make ACPI reserve resources used by opregions unless
acpi_enforce_resources == no.
- Change the drivers so if their request_region() fails, they check acpi_enforce_resources and either fail (in strict mode) or print the warning and continue (in lax mode).
Admittedly, this is harder for the drivers that use the shiny new platform device stuff.
Quoted 20 lines
This approach stores all Operation Region declarations (IO and System Memory only) at ACPI table parse time. It offers a similar functionality like
request_regionand let drivers which are known to possibly use the same IO ports and Memory which are also often used by ACPI (hwmon and i2c) check for ACPI interference.A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.Goal of this patch set is:
- Identify ACPI interferences in bug reports (very hard to reproduce and to identify)
- Find BIOSes for that an ACPI driver should exist for specific HW instead of a native one.
- stability in general
Quoted 17 lines · Bjorn Helgaas
Quoted 11 lines · Thomas Renninger
In ACPI, AML can define accesses to IO ports and System Memory by Operation Regions. Those are not registered as done by PNPACPI using resource templates (and _CRS/_SRS methods).
The IO ports and System Memory regions may get accessed by arbitrary AML code. When native drivers are accessing the same resources bad things can happen (e.g. a critical shutdown temperature of 3000 C every 2 months or so).It is not really possible to register the operation regions via
request_resource, as they often overlap with pnp or other resources (e.g. statically setup IO resources below0x100).But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
Quoted 8 lines
If these opregion resources aren't reserved, but are only put in the ACPI
resource_list, we will only find conflicts with drivers that useacpi_check_resource_conflict(). Any driver unmodified by your changeset could still have a conflict, and we'd never find it.Isn't the real problem that we have a bunch of drivers that use some of the same resources, and if ACPI reserved all the right resources, all those drivers would break?
Yes, but:
It is really impossible to register them just like that.
I only tried on one machine I implemented on, Jean tested with more machines. Even there the resources did not only interfere, but overlap. The Operation Region declarations in ACPI don't belong to a real driver, but may be used in all kind of functions.
E.g. the thermal driver can't know which operation regions it may use later, e.g. by invoking _THM which in turn invokes a couple of other functions where IO ports are addressed via operation regions. Also the BIOS developers seem to choose the regions in a very dump way sometimes.
Just some imaginary values, but I saw similar (overlapping):
- For a PNP device IO ports from 0x400-0x410 are reserved
- A operation region is declared from 0x399-0x401
My first approach was to register the regions via request_resource and failed on the first machine.
I then thought about acpi exporting it's own request/check_acpi_region and add it into request_region..., but this also did not work out. IMO this is the only way, at least for getting an overview how regions are used and where we might need an ACPI driver and have interference as a first step. There might be more steps we could take in future, maybe someone gets a better idea, but as said, there are no rules how BIOS developers make use of those regions.
Also the current request_resource interface (not the interface but the callers), need to be polished up first.
1) E.g. PNPACPI needs to dynamically allocate its resources (as we already discussed, I hope to be able to send something soon. Already works, but this will also affect PNPBIOS and ISAPNP, a lot old code and this needs careful review/testing).
2) I have no idea why e.g. i386/x86_64 kernel/setup.c code statically requests some ports below 0x100 and whether it can be ripped out or gets requested via the operation regions then in a sane way. I know they interfere on some systems with operation regions.
It's just too much to solve in one step, if it can be resolved at all.
Thomas
Quoted 32 lines
I think it would be better to:
- Make ACPI reserve resources used by opregions unless
acpi_enforce_resources == no.- Change the drivers so if their
request_region()fails, they checkacpi_enforce_resourcesand either fail (in strict mode) or print the warning and continue (in lax mode).Admittedly, this is harder for the drivers that use the shiny new platform device stuff.
Quoted 20 lines
This approach stores all Operation Region declarations (IO and System Memory only) at ACPI table parse time. It offers a similar functionality like
request_regionand let drivers which are known to possibly use the same IO ports and Memory which are also often used by ACPI (hwmon and i2c) check for ACPI interference.A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.Goal of this patch set is:
- Identify ACPI interferences in bug reports (very hard to reproduce and to identify)
- Find BIOSes for that an ACPI driver should exist for specific HW instead of a native one.
- stability in general
Quoted 11 lines · Thomas Renninger
Quoted 3 lines · Bjorn Helgaas
Isn't the real problem that we have a bunch of drivers that use some of the same resources, and if ACPI reserved all the right resources, all those drivers would break?
Yes, but:
It is really impossible to register them just like that.
I only tried on one machine I implemented on, Jean tested with more machines. Even there the resources did not only interfere, but overlap. The Operation Region declarations in ACPI don't belong to a real driver, but may be used in all kind of functions.
Can we reserve the resources when we register the opregion? Or does the opregion declaration just not tell us what resources it might use?
Quoted 3 lines
E.g. the thermal driver can't know which operation regions it may use later, e.g. by invoking
_THMwhich in turn invokes a couple of other functions where IO ports are addressed via operation regions.
I would think the opregion resources should be reserved in connection with the opregion, not with drivers that use the opregion.
Quoted 5 lines
Also the BIOS developers seem to choose the regions in a very dump way sometimes.
Just some imaginary values, but I saw similar (overlapping):
- For a PNP device IO ports from 0x400-0x410 are reserved
- A operation region is declared from 0x399-0x401
If we know the resources the opregion can use, we can at least reserve the union of those used by the opregion and by other PNP devices. A little messy to deal with overlapping areas, I agree, but it should still be possible by shrinking the region or allocating a port at a time or something.
Quoted 6 lines
Also the current
request_resourceinterface (not the interface but the callers), need to be polished up first.
1) E.g. PNPACPI needs to dynamically allocate its resources (as we already discussed, I hope to be able to send something soon. Already works, but this will also affect PNPBIOS and ISAPNP, a lot old code and this needs careful review/testing).
I have a patch for this (see below). It is risky, and I'm nervous about it. But the alternative (leaving PNP devices active but not reserving their resources, as we do today) is also risky.
If you have a similar patch in the works, I'd like to compare with mine.
Quoted 4 lines
2) I have no idea why e.g. i386/x86_64
kernel/setup.ccode statically requests some ports below0x100and whether it can be ripped out or gets requested via the operation regions then in a sane way. I know they interfere on some systems with operation regions.
You mean the stuff in request_standard_resources()? I think that's legacy from before we had PNPBIOS and ACPI. Theoretically, we should be able to remove it if we have PNPBIOS or ACPI. But I think that would be too dangerous.
It should be safe to leave it -- it's OK if we reserve a little bit too much. The problem is if we reserve too little.
Bjorn
NOT FOR APPLICATION -- NOT FOR APPLICATION -- NOT FOR APPLICATION
PNP: request ioport and iomem resources used by active devices
For platform-type devices, PNP tells us what devices are present, whether they're active, and what resources they consume. To prevent conflicts, the PNP core should request the resources used by active devices before we assign resources to any other devices.
This overlaps with request_standard_resources(), which requests resources for a built-in list of "standard PC devices" such as DMA controllers, PICs, timers, keyboard, etc. PNP tells us which devices are actually present on a specific machine.
Sometimes the built-in standard resources are larger than what PNP reports, or they combine things that PNP reports separately, which makes things look a little funny:
0000-001f : dma1 <-- built-in resource includes 2 controllers
0000-000f : 00:02 <-- PNP reports only one DMA controller
0020-0021 : pic1
002e-002f : 00:06
0040-0043 : timer0
0050-0053 : timer1
0060-006f : keyboard <-- built-in resource groups several things
0060-0060 : 00:04 <-- PNP reports 8042 controller data register
0061-0061 : 00:03 <-- PNP reports AT-style speaker
0064-0064 : 00:04 <-- PNP reports 8042 controller status register
0070-0073 : 00:06
0070-0071 : rtcThis doesn't mark the resources busy; they should be marked busy when a driver claims them. But if driver attempts to claim a region larger than what PNP reported, it will fail.
drivers/pnp/core.c +3 -0
@@ -124,6 +124,9 @@list_add_tail (&dev->protocol_list, &dev->protocol->devices);spin_unlock (&pnp_lock); +if (dev->active) +pnp_request_resources (dev); + ret =device_register (&dev->dev);if (ret)return ret;
drivers/pnp/resource.c +67 -0
73 lines not on this page · raw message
drivers/pnp/base.h +2 -0
@@ -5,6 +5,8 @@void pnp_free_option (struct pnp_option *option);int __pnp_add_device (struct pnp_dev *dev);void __pnp_remove_device (struct pnp_dev *dev); +int pnp_request_resources (struct pnp_dev *dev); +int pnp_release_resources (struct pnp_dev *dev);int pnp_check_port (struct pnp_dev * dev,int idx);int pnp_check_mem (struct pnp_dev * dev,int idx);
drivers/pnp/manager.c +9 -3
@@ -391,9 +391,11 @@if (!pnp_can_configure (dev))return -ENODEV ; + bak =pnp_alloc (sizeof (struct pnp_resource_table ));if (!bak)return -ENOMEM ; + *bak = dev->res;down (&pnp_res_mutex);
@@ -463,7 +465,7 @@* pnp_start_dev - low-level start of the PnP device * @dev: pointer to the desired device * -* assumes that resources have already been allocated +* assumes that resources have already been assigned to the device */ int pnp_start_dev (struct pnp_dev *dev) {
@@ -472,6 +474,9 @@return -EINVAL ; } +if (pnp_request_resources (dev)) +dev_err (&dev->dev,"could not allocate resources\n" ); +if (dev->protocol->set (dev, &dev->res) <0 ) {dev_err (&dev->dev,"activation failed\n" );return -EIO ;
@@ -484,8 +489,6 @@/** * pnp_stop_dev - low-level disable of the PnP device * @dev: pointer to the desired device -* -* does not free resources */ int pnp_stop_dev (struct pnp_dev *dev) {
@@ -493,11 +496,14 @@dev_dbg (&dev->dev,"disabling not supported\n" );return -EINVAL ; } +if (dev->protocol->disable (dev) <0 ) {dev_err (&dev->dev,"disable failed\n" );return -EIO ; } +pnp_release_resources (dev); +dev_info (&dev->dev,"disabled\n" );return 0 ; }
Quoted 16 lines · Bjorn Helgaas
Quoted 11 lines · Thomas Renninger
Quoted 3 lines · Bjorn Helgaas
Isn't the real problem that we have a bunch of drivers that use some of the same resources, and if ACPI reserved all the right resources, all those drivers would break?
Yes, but:
It is really impossible to register them just like that.
I only tried on one machine I implemented on, Jean tested with more machines. Even there the resources did not only interfere, but overlap. The Operation Region declarations in ACPI don't belong to a real driver, but may be used in all kind of functions.Can we reserve the resources when we register the opregion? Or does the opregion declaration just not tell us what resources it might use?
Quoted 6 lines
Quoted 3 lines
E.g. the thermal driver can't know which operation regions it may use later, e.g. by invoking
_THMwhich in turn invokes a couple of other functions where IO ports are addressed via operation regions.I would think the opregion resources should be reserved in connection with the opregion, not with drivers that use the opregion.
Yes, I tried that.
Quoted 7 lines
Quoted 6 lines
Also the BIOS developers seem to choose the regions in a very dump way sometimes.
Just some imaginary values, but I saw similar (overlapping):
- For a PNP device IO ports from 0x400-0x410 are reserved
- A operation region is declared from 0x399-0x401
Quoted 5 lines
If we know the resources the opregion can use, we can at least reserve the union of those used by the opregion and by other PNP devices. A little messy to deal with overlapping areas, I agree, but it should still be possible by shrinking the region or allocating a port at a time or something.
You mean merging them together to something like:
0x400-0x410 pnp device
0x399 ACPI Op region's name
This needs touching of kernel/resource.c and modification in a very ugly way affecting all architectures...
Or working around it outside if possible, but it's everything but nice/clean.
Maybe the list set up by this patch set should be similarly exported like /proc/ioports /proc/iomem
to where ever appropriate (maybe /sys/devices/system/acpi/opreg_io and /sys/devices/system/acpi/opreg_mem?) to get a better overview what kind of devices are served by the Op regions on different machines. Expect all kind of ugliness if you have a look at some more machines...
IMO the current approach is safe, easy and sufficient (maybe some more drivers could get added later), covering most important potential offenders, we can still add some more. It should be mainly/only small devices accessed by Op regions, setting up and accessing complex devices won't be done by Op region declared objects.
Maybe there should be a rule in ACPI spec that they must also pop up as resources in the motherboard device for future, this would address your concerns? The mixture of declaring some resources in devices and some in Op regions, some in both and even let them overlap can IMO be called a broken BIOS, but it's common. Doing a complex workaround to be somehow able to request them is wrong.
Quoted 7 lines
Quoted 6 lines
Also the current
request_resourceinterface (not the interface but the callers), need to be polished up first.
1) E.g. PNPACPI needs to dynamically allocate its resources (as we already discussed, I hope to be able to send something soon. Already works, but this will also affect PNPBIOS and ISAPNP, a lot old code and this needs careful review/testing).
Quoted 5 lines
I have a patch for this (see below). It is risky, and I'm nervous about it. But the alternative (leaving PNP devices active but not reserving their resources, as we do today) is also risky.
If you have a similar patch in the works, I'd like to compare with mine.
I think I worked on something else.
Do I get this right:
This one is to request all active resources of all ACPI devices that export resources via _CRS/_SRS?
As this is currently done for the motherboard devices only by pnp/system.c?
What I meant is that the pnp_resource_table resource table is currently statically declared to have 8 ports, but e.g. motherboard devices can have more than 20.
I attached my patch at the end (two other cleanup patches are also needed and this has just been written down to work, a lot cleanup and careful review is still necessary, but I don't find the time for it currently). The most interesting part is the beginning (pnp_port_alloc and so on, that kreallocs in e.g. 8 port portions instead of using a static array).
If you are interested I can try to fast cleanup and send you a pre-version of all patches (but not before beginning of next week).
Thomas
Quoted 205 lines
Quoted 4 lines
2) I have no idea why e.g. i386/x86_64
kernel/setup.ccode statically requests some ports below0x100and whether it can be ripped out or gets requested via the operation regions then in a sane way. I know they interfere on some systems with operation regions.You mean the stuff in
request_standard_resources()? I think that's legacy from before we had PNPBIOS and ACPI. Theoretically, we should be able to remove it if we have PNPBIOS or ACPI. But I think that would be too dangerous.It should be safe to leave it -- it's OK if we reserve a little bit too much. The problem is if we reserve too little.
Bjorn
NOT FOR APPLICATION -- NOT FOR APPLICATION -- NOT FOR APPLICATION
PNP: request ioport and iomem resources used by active devices
For platform-type devices, PNP tells us what devices are present, whether they're active, and what resources they consume. To prevent conflicts, the PNP core should request the resources used by active devices before we assign resources to any other devices.
This overlaps with
request_standard_resources(), which requests resources for a built-in list of "standard PC devices" such as DMA controllers, PICs, timers, keyboard, etc. PNP tells us which devices are actually present on a specific machine.Sometimes the built-in standard resources are larger than what PNP reports, or they combine things that PNP reports separately, which makes things look a little funny:
0000-001f : dma1 <-- built-in resource includes 2 controllers 0000-000f : 00:02 <-- PNP reports only one DMA controller 0020-0021 : pic1 002e-002f : 00:06 0040-0043 : timer0 0050-0053 : timer1 0060-006f : keyboard <-- built-in resource groups several things 0060-0060 : 00:04 <-- PNP reports 8042 controller data register 0061-0061 : 00:03 <-- PNP reports AT-style speaker 0064-0064 : 00:04 <-- PNP reports 8042 controller status register 0070-0073 : 00:06 0070-0071 : rtcThis doesn't mark the resources busy; they should be marked busy when a driver claims them. But if driver attempts to claim a region larger than what PNP reported, it will fail.
Index:
w/drivers/pnp/core.c
===================================================================drivers/pnp/core.c +3
-0@@ -124,6 +124,9 @@list_add_tail (&dev->protocol_list, &dev->protocol->devices);spin_unlock (&pnp_lock); +if (dev->active) +pnp_request_resources (dev); + ret =device_register (&dev->dev);if (ret)return ret;Index:
w/drivers/pnp/resource.c
===================================================================drivers/pnp/resource.c +67
-0@@ -459,6 +459,73 @@#endif } +int pnp_request_resources (struct pnp_dev *dev) +{ +int i, ret; +struct resource *res; + +/* +* We use insert_resource() rather than request_resource() because +* request_standard_resources() has already requested some standard +* areas that are described by PNP. +*/ +for (i =0 ; i <PNP_MAX_PORT ; i++) { +if (pnp_port_valid (dev, i)) { + res = &dev->res.port_resource[i]; + res->name = dev->dev.bus_id; + ret =insert_resource (&ioport_resource, res); +if (ret) +dev_warn (&dev->dev, +"can't allocate I/O ports at 0x%llx\n" , + (unsigned long long ) res->start); + } + } + +for (i =0 ; i <PNP_MAX_MEM ; i++) { +if (pnp_mem_valid (dev, i)) { + res = &dev->res.mem_resource[i]; + res->name = dev->dev.bus_id; + ret =insert_resource (&iomem_resource, res); +if (ret) +dev_warn (&dev->dev, +"can't allocate MMIO space at 0x%llx\n" , + (unsigned long long ) res->start); + } + } + +return 0 ; +} + +int pnp_release_resources (struct pnp_dev *dev) +{ +int i, ret; +struct resource *res; + +for (i =0 ; i <PNP_MAX_PORT ; i++) { +if (pnp_port_valid (dev, i)) { + res = &dev->res.port_resource[i]; + ret =release_resource (res); +if (ret) +dev_warn (&dev->dev, +"can't release I/O ports at 0x%llx\n" , + (unsigned long long ) res->start); + } + } + +for (i =0 ; i <PNP_MAX_MEM ; i++) { +if (pnp_mem_valid (dev, i)) { + res = &dev->res.mem_resource[i]; + ret =release_resource (res); +if (ret) +dev_warn (&dev->dev, +"can't release MMIO space at 0x%llx\n" , + (unsigned long long ) res->start); + } + } + +return 0 ; +} +/* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq (char *str) {Index:
w/drivers/pnp/base.h
===================================================================drivers/pnp/base.h +2
-0@@ -5,6 +5,8 @@void pnp_free_option (struct pnp_option *option);int __pnp_add_device (struct pnp_dev *dev);void __pnp_remove_device (struct pnp_dev *dev); +int pnp_request_resources (struct pnp_dev *dev); +int pnp_release_resources (struct pnp_dev *dev);int pnp_check_port (struct pnp_dev * dev,int idx);int pnp_check_mem (struct pnp_dev * dev,int idx);Index:
w/drivers/pnp/manager.c
===================================================================drivers/pnp/manager.c +7
-3@@ -391,9 +391,11 @@if (!pnp_can_configure (dev))return -ENODEV ; + bak =pnp_alloc (sizeof (struct pnp_resource_table ));if (!bak)return -ENOMEM ; + *bak = dev->res;down (&pnp_res_mutex);@@ -463,7 +465,7 @@* pnp_start_dev - low-level start of the PnP device * @dev: pointer to the desired device * -* assumes that resources have already been allocated +* assumes that resources have already been assigned to the device */ int pnp_start_dev (struct pnp_dev *dev) {@@ -472,6 +474,9 @@return -EINVAL ; } +if (pnp_request_resources (dev)) +dev_err (&dev->dev,"could not allocate resources\n" ); +if (dev->protocol->set (dev, &dev->res) <0 ) {dev_err (&dev->dev,"activation failed\n" );return -EIO ;@@ -484,8 +489,6 @@/** * pnp_stop_dev - low-level disable of the PnP device * @dev: pointer to the desired device -* -* does not free resources */ int pnp_stop_dev (struct pnp_dev *dev) {@@ -493,11 +496,14 @@dev_dbg (&dev->dev,"disabling not supported\n" );return -EINVAL ; } +
drivers/pnp/manager.c line 509
Quoted 10 lines
drivers/pnp/manager.c +2
-0if (dev->protocol->disable (dev) <0 ) {dev_err (&dev->dev,"disable failed\n" );return -EIO ; } +pnp_release_resources (dev); +dev_info (&dev->dev,"disabled\n" );return 0 ; }
--- drivers/pnp/core.c | 4 drivers/pnp/interface.c | 65 ++------ drivers/pnp/manager.c | 330 ++++++++++++++++++++++++++++------------- drivers/pnp/pnpacpi/rsparser.c | 214 ++++++++++++++------------ drivers/pnp/pnpbios/rsparser.c | 99 ++++++------ drivers/pnp/quirks.c | 18 +- drivers/pnp/resource.c | 25 +-- drivers/pnp/system.c | 10 - include/linux/pnp.h | 50 ++++-- 9 files changed, 492 insertions(+), 323 deletions(-)
include/linux/pnp.h +38 -12
@@ -13,10 +13,6 @@#include <linux/errno.h> #include <linux/mod_devicetable.h> -#define PNP_MAX_PORT 8 -#define PNP_MAX_MEM 4 -#define PNP_MAX_IRQ 2 -#define PNP_MAX_DMA 2#define PNP_NAME_LEN 50struct pnp_protocol ;
@@ -27,12 +23,16 @@ struct pnp_dev;*/ /* Use these instead of directly reading pnp_dev to get resource information */ +#define pnp_port (dev,bar) ((dev)->res.allocated_ports > (bar) \ + ? (&(dev)->res.port_resource[bar]) : NULL)#define pnp_port_start (dev,bar) ((dev)->res.port_resource[(bar)].start)#define pnp_port_end (dev,bar) ((dev)->res.port_resource[(bar)].end)#define pnp_port_flags (dev,bar) ((dev)->res.port_resource[(bar)].flags)#define pnp_port_valid (dev,bar) \ + (pnp_port((dev),(bar)) ? \ ((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \ - == IORESOURCE_IO) + == IORESOURCE_IO) : \ + (0))#define pnp_port_len (dev,bar) \ ((pnp_port_start((dev),(bar)) == 0 && \ pnp_port_end((dev),(bar)) == \
@@ -41,12 +41,16 @@ struct pnp_dev; (pnp_port_end((dev),(bar)) - \ pnp_port_start((dev),(bar)) + 1)) +#define pnp_mem (dev,bar) ((dev)->res.allocated_mems > (bar) \ + ? (&(dev)->res.mem_resource[bar]) : NULL)#define pnp_mem_start (dev,bar) ((dev)->res.mem_resource[(bar)].start)#define pnp_mem_end (dev,bar) ((dev)->res.mem_resource[(bar)].end)#define pnp_mem_flags (dev,bar) ((dev)->res.mem_resource[(bar)].flags)#define pnp_mem_valid (dev,bar) \ + (pnp_mem((dev),(bar)) ? \ ((pnp_mem_flags((dev),(bar)) & (IORESOURCE_MEM | IORESOURCE_UNSET)) \ - == IORESOURCE_MEM) + == IORESOURCE_MEM) : \ + (0))#define pnp_mem_len (dev,bar) \ ((pnp_mem_start((dev),(bar)) == 0 && \ pnp_mem_end((dev),(bar)) == \
@@ -55,19 +59,27 @@ struct pnp_dev; (pnp_mem_end((dev),(bar)) - \ pnp_mem_start((dev),(bar)) + 1)) +#define pnp_irq (dev,bar) ((dev)->res.allocated_irqs > (bar) \ + ? (&(dev)->res.irq_resource[bar]) : NULL)#define pnp_irq_start (dev,bar) ((dev)->res.irq_resource[(bar)].start)#define pnp_irq_end (dev,bar) ((dev)->res.irq_resource[(bar)].end)#define pnp_irq_flags (dev,bar) ((dev)->res.irq_resource[(bar)].flags)#define pnp_irq_valid (dev,bar) \ + (pnp_irq((dev),(bar)) ? \ ((pnp_irq_flags((dev),(bar)) & (IORESOURCE_IRQ | IORESOURCE_UNSET)) \ - == IORESOURCE_IRQ) + == IORESOURCE_IRQ) : \ + (0)) +#define pnp_dma (dev,bar) ((dev)->res.allocated_dmas > (bar) \ + ? ((dev)->res.dma_resource + (bar)) : NULL)#define pnp_dma_start (dev,bar) ((dev)->res.dma_resource[(bar)].start)#define pnp_dma_end (dev,bar) ((dev)->res.dma_resource[(bar)].end)#define pnp_dma_flags (dev,bar) ((dev)->res.dma_resource[(bar)].flags)#define pnp_dma_valid (dev,bar) \ + (pnp_irq((dev),(bar)) ? \ ((pnp_dma_flags((dev),(bar)) & (IORESOURCE_DMA | IORESOURCE_UNSET)) \ - == IORESOURCE_DMA) + == IORESOURCE_DMA) : \ + (0))#define PNP_PORT_FLAG_16BITADDR (1<<0)#define PNP_PORT_FLAG_FIXED (1<<1)
@@ -121,10 +133,14 @@ struct pnp_option { };struct pnp_resource_table { -struct resource port_resource[PNP_MAX_PORT ]; -struct resource mem_resource[PNP_MAX_MEM ]; -struct resource dma_resource[PNP_MAX_DMA ]; -struct resource irq_resource[PNP_MAX_IRQ ]; +struct resource *port_resource; +unsigned int allocated_ports; +struct resource *mem_resource; +unsigned int allocated_mems; +struct resource *dma_resource; +unsigned int allocated_dmas; +struct resource *irq_resource; +unsigned int allocated_irqs; };/*
@@ -400,6 +416,7 @@ int pnp_activate_dev(struct pnp_dev *devint pnp_disable_dev (struct pnp_dev *dev);void pnp_resource_change (struct resource *resource,resource_size_t start,resource_size_t size); +int pnp_assign_resource (struct pnp_resource_table *table,struct resource *res);/* protocol helpers */ int pnp_is_active (struct pnp_dev *dev);
@@ -447,6 +464,7 @@ static inline int pnp_stop_dev(struct pnstatic inline int pnp_activate_dev (struct pnp_dev *dev) {return -ENODEV ; }static inline int pnp_disable_dev (struct pnp_dev *dev) {return -ENODEV ; }static inline void pnp_resource_change (struct resource *resource,resource_size_t start,resource_size_t size) { } +static inline void int pnp_assign_resource(struct pnp_resource_table *table, struct resource *res) { }/* protocol helpers */ static inline int pnp_is_active (struct pnp_dev *dev) {return 0 ; }
@@ -463,8 +481,16 @@ static inline void pnp_unregister_driver#ifdef CONFIG_PNP_DEBUG #define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg) +void pnp_dump_ports (struct pnp_dev *dev); +void pnp_dump_mems (struct pnp_dev *dev); +void pnp_dump_irqs (struct pnp_dev *dev); +void pnp_dump_dmas (struct pnp_dev *dev);#else #define pnp_dbg(format, arg...) do {} while (0) +static inline void pnp_dump_ports (struct pnp_dev *dev) { } +static inline void pnp_dump_mems (struct pnp_dev *dev) { } +static inline void pnp_dump_irqs (struct pnp_dev *dev) { } +static inline void pnp_dump_dmas (struct pnp_dev *dev) { }#endif #endif /* __KERNEL__ */
drivers/pnp/manager.c +229 -101
428 lines not on this page · raw message
drivers/pnp/interface.c +22 -43
139 lines not on this page · raw message
drivers/pnp/quirks.c +12 -6
@@ -138,6 +138,11 @@ static void quirk_smc_enable(struct pnp_ {struct resource fir, sir, irq; +if (dev->res.allocated_ports <=1 || dev->res.allocated_irqs <=0 ) { +pnp_err ("IRQ/Ports not assigned, quirk needs fixup, try" +" smsc_nopnp boot param" ); + } +pnp_activate_dev (dev);if (quirk_smc_fir_enabled (dev))return ;
@@ -182,20 +187,21 @@ static void quirk_smc_enable(struct pnp_* Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign * these resources any more. */ - fir = dev->res.port_resource[0 ]; - sir = dev->res.port_resource[1 ]; + fir = *pnp_port (dev,0 ); + sir = *pnp_port (dev,1 ); fir.flags &= ~IORESOURCE_AUTO ; sir.flags &= ~IORESOURCE_AUTO ; - irq = dev->res.irq_resource[0 ]; + sir = *pnp_irq (dev,0 ); +/* TBD: Why do we get a compile warning here but not above? */ irq.flags &= ~IORESOURCE_AUTO ; irq.flags &= ~IORESOURCE_BITS ; irq.flags |=IORESOURCE_IRQ_LOWEDGE ;pnp_disable_dev (dev); - dev->res.port_resource[0 ] = sir; - dev->res.port_resource[1 ] = fir; - dev->res.irq_resource[0 ] = irq; + *pnp_port (dev,0 ) = sir; + *pnp_port (dev,1 ) = fir; + *pnp_irq (dev,0 ) = irq;pnp_activate_dev (dev);if (quirk_smc_fir_enabled (dev)) {
drivers/pnp/resource.c +13 -12
@@ -19,10 +19,10 @@#include <linux/pnp.h> #include "base.h" -static int pnp_reserve_irq[16] = {[0...15] = -1 }; /* reserve (don't use) some IRQ */ -static int pnp_reserve_dma[8] = {[0...7] = -1 }; /* reserve (don't use) some DMA */ -static int pnp_reserve_io[16] = {[0...15] = -1 }; /* reserve (don't use) some I/O region */ -static int pnp_reserve_mem[16] = {[0...15] = -1 }; /* reserve (don't use) some memory region */ +static int pnp_reserve_irq[16 ] = {[0 ...15 ] =-1 };/* reserve (don't use) some IRQ */ +static int pnp_reserve_dma[8 ] = {[0 ...7 ] =-1 };/* reserve (don't use) some DMA */ +static int pnp_reserve_io[16 ] = {[0 ...15 ] =-1 };/* reserve (don't use) some I/O region */ +static int pnp_reserve_mem[16 ] = {[0 ...15 ] =-1 };/* reserve (don't use) some memory region */ /* * option registration
@@ -260,6 +260,7 @@ int pnp_check_port(struct pnp_dev *dev, }/* check if the resource is reserved */ +/* TBD: Check more as we now might have more than 8 ports? */ for (tmp =0 ; tmp <8 ; tmp++) {int rport = pnp_reserve_io[tmp <<1 ];int rend = pnp_reserve_io[(tmp <<1 ) +1 ] + rport -1 ;
@@ -268,7 +269,7 @@ int pnp_check_port(struct pnp_dev *dev, }/* check for internal conflicts */ -for (tmp =0 ; tmp <PNP_MAX_PORT && tmp != idx; tmp++) { +for (tmp =0 ;pnp_port (dev, tmp) && tmp != idx; tmp++) {if (pnp_port_flags (dev, tmp) &IORESOURCE_IO ) { tport = &pnp_port_start (dev, tmp); tend = &pnp_port_end (dev, tmp);
@@ -281,7 +282,7 @@ int pnp_check_port(struct pnp_dev *dev,pnp_for_each_dev (tdev) {if (tdev == dev)continue ; -for (tmp =0 ; tmp <PNP_MAX_PORT ; tmp++) { +for (tmp =0 ;pnp_port (tdev, tmp); tmp++) {if (pnp_port_flags (tdev, tmp) &IORESOURCE_IO ) {if (cannot_compare (pnp_port_flags (tdev, tmp)))continue ;
@@ -325,7 +326,7 @@ int pnp_check_mem(struct pnp_dev *dev, i }/* check for internal conflicts */ -for (tmp =0 ; tmp <PNP_MAX_MEM && tmp != idx; tmp++) { +for (tmp =0 ;pnp_mem (dev, tmp) && tmp != idx; tmp++) {if (pnp_mem_flags (dev, tmp) &IORESOURCE_MEM ) { taddr = &pnp_mem_start (dev, tmp); tend = &pnp_mem_end (dev, tmp);
@@ -338,7 +339,7 @@ int pnp_check_mem(struct pnp_dev *dev, ipnp_for_each_dev (tdev) {if (tdev == dev)continue ; -for (tmp =0 ; tmp <PNP_MAX_MEM ; tmp++) { +for (tmp =0 ;pnp_mem (tdev, tmp); tmp++) {if (pnp_mem_flags (tdev, tmp) &IORESOURCE_MEM ) {if (cannot_compare (pnp_mem_flags (tdev, tmp)))continue ;
@@ -379,7 +380,7 @@ int pnp_check_irq(struct pnp_dev *dev, i }/* check for internal conflicts */ -for (tmp =0 ; tmp <PNP_MAX_IRQ && tmp != idx; tmp++) { +for (tmp =0 ;pnp_irq (dev, tmp) && tmp != idx; tmp++) {if (pnp_irq_flags (dev, tmp) &IORESOURCE_IRQ ) {if (pnp_irq_start (dev, tmp) == *irq)return 0 ;
@@ -410,7 +411,7 @@ int pnp_check_irq(struct pnp_dev *dev, ipnp_for_each_dev (tdev) {if (tdev == dev)continue ; -for (tmp =0 ; tmp <PNP_MAX_IRQ ; tmp++) { +for (tmp =0 ;pnp_irq (tdev, tmp); tmp++) {if (pnp_irq_flags (tdev, tmp) &IORESOURCE_IRQ ) {if (cannot_compare (pnp_irq_flags (tdev, tmp)))continue ;
@@ -445,7 +446,7 @@ int pnp_check_dma(struct pnp_dev *dev, i }/* check for internal conflicts */ -for (tmp =0 ; tmp <PNP_MAX_DMA && tmp != idx; tmp++) { +for (tmp =0 ;pnp_mem (dev, tmp) && tmp != idx; tmp++) {if (pnp_mem_flags (dev, tmp) &IORESOURCE_DMA ) {if (pnp_mem_start (dev, tmp) == *dma)return 0 ;
@@ -464,7 +465,7 @@ int pnp_check_dma(struct pnp_dev *dev, ipnp_for_each_dev (tdev) {if (tdev == dev)continue ; -for (tmp =0 ; tmp <PNP_MAX_DMA ; tmp++) { +for (tmp =0 ;pnp_mem (tdev, tmp); tmp++) {if (pnp_mem_flags (tdev, tmp) &IORESOURCE_DMA ) {if (cannot_compare (pnp_mem_flags (tdev, tmp)))continue ;
drivers/pnp/system.c +5 -5
@@ -55,7 +55,7 @@ static void reserve_resources_of_dev(con {int i; -for (i =0 ; i <PNP_MAX_PORT ; i++) { +for (i =0 ;pnp_port (dev, i); i++) {if (!pnp_port_valid (dev, i))continue ;if (pnp_port_start (dev, i) ==0 )
@@ -77,7 +77,7 @@ static void reserve_resources_of_dev(con pnp_port_end(dev, i), 1); } -for (i =0 ; i <PNP_MAX_MEM ; i++) { +for (i =0 ;pnp_mem (dev, i); i++) {if (!pnp_mem_valid (dev, i))continue ;
@@ -94,10 +94,10 @@ static int system_pnp_probe(struct pnp_d }static struct pnp_driver system_pnp_driver = { - .name ="system" , + .name ="system" , .id_table = pnp_dev_table, - .flags =PNP_DRIVER_RES_DO_NOT_CHANGE , - .probe = system_pnp_probe, + .flags =PNP_DRIVER_RES_DO_NOT_CHANGE , + .probe = system_pnp_probe, };static int __init pnp_system_init (void )
drivers/pnp/pnpacpi/rsparser.c +120 -94
309 lines not on this page · raw message
drivers/pnp/pnpbios/rsparser.c +49 -50
134 lines not on this page · raw message
drivers/pnp/core.c +4 -0
@@ -132,6 +132,10 @@ int __pnp_add_device(struct pnp_dev *dev ret =device_register (&dev->dev);if (ret ==0 )pnp_interface_attach_device (dev); +pnp_dump_ports (dev); +pnp_dump_mems (dev); +pnp_dump_irqs (dev); +pnp_dump_dmas (dev);return ret; }
Quoted 15 lines · Thomas Renninger
Quoted 8 lines · Bjorn Helgaas
Quoted 5 lines · Thomas Renninger
Also the BIOS developers seem to choose the regions in a very dump way sometimes.
Just some imaginary values, but I saw similar (overlapping):
- For a PNP device IO ports from 0x400-0x410 are reserved
- A operation region is declared from 0x399-0x401Quoted 5 lines
If we know the resources the opregion can use, we can at least reserve the union of those used by the opregion and by other PNP devices. A little messy to deal with overlapping areas, I agree, but it should still be possible by shrinking the region or allocating a port at a time or something.
Quoted 5 lines
You mean merging them together to something like:
0x400-0x410 pnp device
0x399ACPI Op region's name
This needs touching ofkernel/resource.cand modification in a very ugly way affecting all architectures...
Right, that's what I was thinking. But I haven't tried it, so I'll take your word for it that it's ugly.
Quoted 5 lines
Maybe the list set up by this patch set should be similarly exported like
/proc/ioports/proc/iomem
to where ever appropriate (maybe/sys/devices/system/acpi/opreg_ioand/sys/devices/system/acpi/opreg_mem?) to get a better overview what kind of devices are served by the Op regions on different machines.
I want to try hard to avoid making ACPI a special case in this way. The current /proc/io{ports,mem} contains reservations for everything else. I'd hate to have to look two places just because of ACPI.
Quoted 6 lines
I think I worked on something else.
Do I get this right:
This one is to request all active resources of all ACPI devices that export resources via _CRS/_SRS?
As this is currently done for the motherboard devices only bypnp/system.c?
Right. Actually my patch requests resources of all active PNP devices, not just ACPI. Glad we didn't do overlapping work here :-)
Quoted 2 lines
If you are interested I can try to fast cleanup and send you a pre-version of all patches (but not before beginning of next week).
Thanks for the preview. No hurry as far as I'm concerned.
Bjorn
Hi Bjorn,
Quoted 10 lines · Bjorn Helgaas
Quoted 5 lines · Thomas Renninger
Maybe the list set up by this patch set should be similarly exported like
/proc/ioports/proc/iomem
to where ever appropriate (maybe/sys/devices/system/acpi/opreg_ioand/sys/devices/system/acpi/opreg_mem?) to get a better overview what kind of devices are served by the Op regions on different machines.I want to try hard to avoid making ACPI a special case in this way. The current
/proc/io{ports,mem}contains reservations for everything else. I'd hate to have to look two places just because of ACPI.
I agree. I consider the patches Thomas and myself just posted as a temporary workaround (even though we can't say how long this "temporary" will last). Ideally, we should register the I/O ports declared in ACPI OpRegions - just not now as it would break too many drivers. Time we tell how "clean" we manage to go.
Signature · 1 line
Jean Delvare
Quoted 3 lines · Bjorn Helgaas
But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
Only if you're happy to lose functionality like IDE, sadly.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 6 lines · Matthew Garrett
Quoted 3 lines · Bjorn Helgaas
But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
Only if you're happy to lose functionality like IDE, sadly.
That's a simplistic answer to a complex problem. I don't think we should just ignore the whole problem, cross our fingers, and hope that firmware stays out of our way.
Bjorn
Quoted 11 lines · Bjorn Helgaas
Quoted 6 lines · Matthew Garrett
Quoted 3 lines · Bjorn Helgaas
But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
Only if you're happy to lose functionality like IDE, sadly.
That's a simplistic answer to a complex problem. I don't think we should just ignore the whole problem, cross our fingers, and hope that firmware stays out of our way.
Right now, there's not really any other way of handling it. The firmware may screw with pretty much everything, and it might even be safe for it to do so in many cases. In any case, you don't necessarily win that much by registering all the opregions, since SMI can go behind your back and write to stuff that's not declared in the DSDT anyway.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 11 lines · Bjorn Helgaas
Quoted 6 lines · Matthew Garrett
Quoted 3 lines · Bjorn Helgaas
But we really *should* reserve things used by opregions, shouldn't we? After all, the whole point of resource reservation is to prevent conflicts.
Only if you're happy to lose functionality like IDE, sadly.
That's a simplistic answer to a complex problem. I don't think we should just ignore the whole problem, cross our fingers, and hope that firmware stays out of our way.
I agree that something must be done, but the problem underlined by Matthew explains the approach Thomas and myself are pursuing at the moment. Rather than plain requesting the resources at ACPI level and see everything else break, we rely on cooperation by individual drivers (or actually families of drivers) and try to fix the problems seen with these specific drivers. This is more realistic.
Signature · 1 line
Jean Delvare
Len Brown
reviewerThis is one of the most imortant issues with ACPI in Linux, and I too thank you, Thomas and Jean, for your hard work seeking the right solution.
1, 2 and 3 of 5 applied to acpi-test.
thanks,
-Len
Quoted 64 lines · Thomas Renninger
Hi,
it seems Len's test tree and Linus tree diverged a bit, at least with this patch set things do not apply cleanly.
Therefore I post these for discussion whether and in which kernel tree they should end up before doing work for nothing.
If they are still a candidate for 2.6.24 (rather unintrusive), pls tell me whether and when I should base them against Len's test/release branch or whatever other tree.
If not, it would be great if they can be included into the -mm tree and I can rebase them against this one.Be aware that there is a small change in ACPICA (first patch, that's also the reason why this one would not compile on its own).
Many thanks for detailed review, testing and a lot implementation help go to Jean Delvare, without his help I would not be able to post anything right now.
Thanks for any help/advise,
Thomas
--------------
Short general description:In ACPI, AML can define accesses to IO ports and System Memory by Operation Regions. Those are not registered as done by PNPACPI using resource templates (and _CRS/_SRS methods).
The IO ports and System Memory regions may get accessed by arbitrary AML code. When native drivers are accessing the same resources bad things can happen (e.g. a critical shutdown temperature of 3000 C every 2 months or so).
It is not really possible to register the operation regions viarequest_resource, as they often overlap with pnp or other resources (e.g. statically setup IO resources below0x100).
This approach stores all Operation Region declarations (IO and System Memory only) at ACPI table parse time. It offers a similar functionality likerequest_regionand let drivers which are known to possibly use the same IO ports and Memory which are also often used by ACPI (hwmon and i2c) check for ACPI interference.A boot parameter acpi_enforce_resources=strict/lax/no is provided, which is default set to lax:
- strict: let conflicting drivers fail to load with an error message
- lax: let conflicting driver work normal with a warning message
- no: no functional change at all
Depending on the feedback and the kind of interferences we see, this should be set to strict at later time.Goal of this patch set is:
- Identify ACPI interferences in bug reports (very hard to reproduce and to identify)
- Find BIOSes for that an ACPI driver should exist for specific HW instead of a native one.
- stability in general-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html