Change hw.pci.do_powerstate from a boolean to a range. 0 means the

same as today: do no power management.  1 means be conservative about
what you power down (any device class that has caused problems gets
added here).  2 means be agressive about what gets powered down (any
device class that's fundamental to the system is here).  3 means power
them all down, reguardless.  The default is 1.

The effect in the default system is to add mass storage devices to the
list that we don't power down.  From all the pciconf -l lists that
I've seen for the aac and amr issue, the bad device has been a mass
storage device class.

This is an attempt at a compromise between the very small number of
systems that have extreme issues with powerdown, and the very large
number of systems that gain real benefits from powerdown (I get about
20% more battery life when I attach a minimal set of drivers on my
Sony).  Hopefully it will strike the proper balance.

MFC After: 3 days (before next beta)
This commit is contained in:
Warner Losh 2005-09-11 04:09:44 +00:00
parent d85986ec1c
commit 6c996a0055
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=149974

View file

@ -187,8 +187,14 @@ static int pci_do_powerstate = 1;
TUNABLE_INT("hw.pci.do_powerstate", &pci_do_powerstate);
SYSCTL_INT(_hw_pci, OID_AUTO, do_powerstate, CTLFLAG_RW,
&pci_do_powerstate, 1,
"Power down devices into D3 state when no driver attaches to them.\n\
Otherwise, leave the device in D0 state when no driver attaches.");
"Controls the behvior of the pci driver when it encounters\n\
devices which no driver claims. Set to 0 causes the pci to leave\n\
the device in D0. Set to 1 causes pci to conservatively devices\n\
into D3 state. These are devices which have had issues in the past.\n\
Set to 2 causes the bus driver to agressively place devices into D3 state.\n\
The only devices it excludes are devices for which no drivers generally\n\
exist in FreeBSD. Set to 3 causes the bus driver to place all unattached\n\
devices into D3 state.");
/* Find a device_t by bus/slot/function */
@ -2003,18 +2009,31 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
* power the device down on a reattach.
*/
cls = pci_get_class(dev);
if (setstate && cls != PCIC_DISPLAY && cls != PCIC_MEMORY &&
cls != PCIC_BASEPERIPH) {
/*
* PCI spec says we can only go into D3 state from D0 state.
* Transition from D[12] into D0 before going to D3 state.
*/
ps = pci_get_powerstate(dev);
if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3) {
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
}
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3) {
pci_set_powerstate(dev, PCI_POWERSTATE_D3);
}
if (!setstate)
return;
switch (pci_do_powerstate)
{
case 0: /* NO powerdown at all */
return;
case 1: /* Conservative about what to power down */
if (cls == PCIC_STORAGE)
return;
/*FALLTHROUGH*/
case 2: /* Agressive about what to power down */
if (cls == PCIC_DISPLAY || cls == PCIC_MEMORY ||
cls == PCIC_BASEPERIPH)
return;
/*FALLTHROUGH*/
case 3: /* Power down everything */
break;
}
/*
* PCI spec says we can only go into D3 state from D0 state.
* Transition from D[12] into D0 before going to D3 state.
*/
ps = pci_get_powerstate(dev);
if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3)
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3)
pci_set_powerstate(dev, PCI_POWERSTATE_D3);
}