Do not write to those config registers that are unambiguously defined
in the various pci specifications as readonly. vendor, subvendor, device and subdevice are required to be loaded in hardware by some means that isn't the system BIOS or other system software (although some devices do have ways of accomplishing this). class and subclass are defined to be read-only in section 6.2.1 (v2.2). Apart from the status register, which we weren't touching, these are the only read-only registers I could find in the 2.2 spec. progif is also defined as being read-only in section 6.2.1. However, the PCI IDE programming document specifically states that some of the bits are read/write. Since we may have to restore registers before we have a driver attached, go ahead and restore this one byte when transitioning between D3 and D0. The PCI spec also says that writes to reserved and unimplemented registers must be completed normally. It makes no statements about writes to read-only registers, so be as conservative as possible, while covering the exception to the rule that is documented in a subpart of the standard. Requested by: socttl
This commit is contained in:
parent
87ca48b6b8
commit
7138b71d5f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=129664
@ -183,15 +183,6 @@ SYSCTL_INT(_hw_pci, OID_AUTO, do_powerstate, CTLFLAG_RW,
|
||||
"Power down devices into D3 state when no driver attaches to them.\n\
|
||||
Otherwise, leave the device in D0 state when no driver attaches.");
|
||||
|
||||
/*
|
||||
* Enable restoring all the registers, even the ones that are nominally
|
||||
* read-only. If this causes problems for you, please report them to
|
||||
* imp@freebsd.org and remove this line in your local tree. The problems
|
||||
* would be seen if the device is transitioning from D3 to D0 or has ever
|
||||
* made that transition under FreeBSD this boot.
|
||||
*/
|
||||
#define PCI_RESTORE_EXTRA
|
||||
|
||||
/* Find a device_t by bus/slot/function */
|
||||
|
||||
device_t
|
||||
@ -1845,12 +1836,6 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
|
||||
for (i = 0; i < dinfo->cfg.nummaps; i++)
|
||||
pci_write_config(dev, PCIR_MAPS + i * 4, dinfo->cfg.bar[i], 4);
|
||||
pci_write_config(dev, PCIR_BIOS, dinfo->cfg.bios, 4);
|
||||
#ifdef PCI_RESTORE_EXTRA
|
||||
pci_write_config(dev, PCIR_SUBVEND_0, dinfo->cfg.subvendor, 2);
|
||||
pci_write_config(dev, PCIR_SUBDEV_0, dinfo->cfg.subdevice, 2);
|
||||
pci_write_config(dev, PCIR_VENDOR, dinfo->cfg.vendor, 2);
|
||||
pci_write_config(dev, PCIR_DEVICE, dinfo->cfg.device, 2);
|
||||
#endif
|
||||
pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2);
|
||||
pci_write_config(dev, PCIR_INTLINE, dinfo->cfg.intline, 1);
|
||||
pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1);
|
||||
@ -1858,11 +1843,7 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
|
||||
pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1);
|
||||
pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1);
|
||||
pci_write_config(dev, PCIR_LATTIMER, dinfo->cfg.lattimer, 1);
|
||||
#ifdef PCI_RESTORE_EXTRA
|
||||
pci_write_config(dev, PCIR_CLASS, dinfo->cfg.baseclass, 1);
|
||||
pci_write_config(dev, PCIR_SUBCLASS, dinfo->cfg.subclass, 1);
|
||||
pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1);
|
||||
#endif
|
||||
pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user