SOURCES (LINUX_2_6): linux-2.6-3Com_IBM-fix.patch (NEW) - fixed PC...

cieciwa cieciwa at pld-linux.org
Thu Jul 28 10:33:44 CEST 2005


Author: cieciwa                      Date: Thu Jul 28 08:33:44 2005 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- fixed PCI problem ?
-- need checkout.

---- Files affected:
SOURCES:
   linux-2.6-3Com_IBM-fix.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6-3Com_IBM-fix.patch
diff -u /dev/null SOURCES/linux-2.6-3Com_IBM-fix.patch:1.1.2.1
--- /dev/null	Thu Jul 28 10:33:44 2005
+++ SOURCES/linux-2.6-3Com_IBM-fix.patch	Thu Jul 28 10:33:39 2005
@@ -0,0 +1,157 @@
+ arch/sparc64/kernel/pci.c |    6 ++++
+ drivers/pci/pci.c         |   59 ++++++++++++++++++++++++++++++++++++++++++----
+ drivers/pci/setup-res.c   |    2 -
+ include/linux/pci.h       |    3 ++
+ 4 files changed, 65 insertions(+), 5 deletions(-)
+
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -413,6 +413,12 @@ static int pci_assign_bus_resource(const
+ 	return -EBUSY;
+ }
+ 
++void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
++{
++	/* Not implemented for sparc64... */
++	BUG();
++}
++
+ int pci_assign_resource(struct pci_dev *pdev, int resource)
+ {
+ 	struct pcidev_cookie *pcp = pdev->sysdata;
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -222,6 +222,37 @@ pci_find_parent_resource(const struct pc
+ }
+ 
+ /**
++ * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
++ * @dev: PCI device to have its BARs restored
++ *
++ * Restore the BAR values for a given device, so as to make it
++ * accessible by its driver.
++ */
++void
++pci_restore_bars(struct pci_dev *dev)
++{
++	int i, numres;
++
++	switch (dev->hdr_type) {
++	case PCI_HEADER_TYPE_NORMAL:
++		numres = 6;
++		break;
++	case PCI_HEADER_TYPE_BRIDGE:
++		numres = 2;
++		break;
++	case PCI_HEADER_TYPE_CARDBUS:
++		numres = 1;
++		break;
++	default:
++		/* Should never get here, but just in case... */
++		return;
++	}
++
++	for (i = 0; i < numres; i ++)
++		pci_update_resource(dev, &dev->resource[i], i);
++}
++
++/**
+  * pci_set_power_state - Set the power state of a PCI device
+  * @dev: PCI device to be suspended
+  * @state: PCI power state (D0, D1, D2, D3hot, D3cold) we're entering
+@@ -239,7 +270,7 @@ int (*platform_pci_set_power_state)(stru
+ int
+ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ {
+-	int pm;
++	int pm, need_restore = 0;
+ 	u16 pmcsr, pmc;
+ 
+ 	/* bound the state we're entering */
+@@ -278,14 +309,17 @@ pci_set_power_state(struct pci_dev *dev,
+ 			return -EIO;
+ 	}
+ 
++	pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
++
+ 	/* If we're in D3, force entire word to 0.
+ 	 * This doesn't affect PME_Status, disables PME_En, and
+ 	 * sets PowerState to 0.
+ 	 */
+-	if (dev->current_state >= PCI_D3hot)
++	if (dev->current_state >= PCI_D3hot) {
++		if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
++			need_restore = 1;
+ 		pmcsr = 0;
+-	else {
+-		pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
++	} else {
+ 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ 		pmcsr |= state;
+ 	}
+@@ -308,6 +342,22 @@ pci_set_power_state(struct pci_dev *dev,
+ 		platform_pci_set_power_state(dev, state);
+ 
+ 	dev->current_state = state;
++
++	/* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
++	 * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
++	 * from D3hot to D0 _may_ perform an internal reset, thereby
++	 * going to "D0 Uninitialized" rather than "D0 Initialized".
++	 * For example, at least some versions of the 3c905B and the
++	 * 3c556B exhibit this behaviour.
++	 *
++	 * At least some laptop BIOSen (e.g. the Thinkpad T21) leave
++	 * devices in a D3hot state at boot.  Consequently, we need to
++	 * restore at least the BARs so that the device will be
++	 * accessible to its driver.
++	 */
++	if (need_restore)
++		pci_restore_bars(dev);
++
+ 	return 0;
+ }
+ 
+@@ -805,6 +855,7 @@ struct pci_dev *isa_bridge;
+ EXPORT_SYMBOL(isa_bridge);
+ #endif
+ 
++EXPORT_SYMBOL_GPL(pci_restore_bars);
+ EXPORT_SYMBOL(pci_enable_device_bars);
+ EXPORT_SYMBOL(pci_enable_device);
+ EXPORT_SYMBOL(pci_disable_device);
+diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -26,7 +26,7 @@
+ #include "pci.h"
+ 
+ 
+-static void
++void
+ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
+ {
+ 	struct pci_bus_region region;
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -225,6 +225,7 @@
+ #define  PCI_PM_CAP_PME_D3cold  0x8000  /* PME# from D3 (cold) */
+ #define PCI_PM_CTRL		4	/* PM control and status register */
+ #define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
++#define  PCI_PM_CTRL_NO_SOFT_RESET	0x0004	/* No reset for D3hot->D0 */
+ #define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
+ #define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* Data select (??) */
+ #define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* Data scale (??) */
+@@ -816,7 +817,9 @@ int pci_set_mwi(struct pci_dev *dev);
+ void pci_clear_mwi(struct pci_dev *dev);
+ int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
+ int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
++void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
+ int pci_assign_resource(struct pci_dev *dev, int i);
++void pci_restore_bars(struct pci_dev *dev);
+ 
+ /* ROM control related routines */
+ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size);
================================================================



More information about the pld-cvs-commit mailing list