Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2826

kernel-2.6.18-194.11.1.el5.src.rpm

From: Scott Moser <smoser@redhat.com>
Subject: [RHEL5.1 PATCH] Issue 126094 PCI: unable to reserve  mem region on module reload
Date: Tue, 10 Jul 2007 15:24:51 -0400 (EDT)
Bugzilla: 247701 247400
Message-Id: <Pine.LNX.4.64.0707101524030.18157@squad5-lp1.lab.boston.redhat.com>
Changelog: [PCI] unable to reserve mem region on module reload


Description:
------------
This bug pulls back some missing devres pieces from upstream that need to
accompany the recent changes made to the RHEL 5u1 kernel.  The  missing pieces
cause "region_mask" to be always zero in pcim_release() and fail to release
device resources properly.  This patch adds the missing devres bits to
drivers/pci/pci.c. 

The bug can be seen by simply loading, unloading and reloading module
pata_pdc2027x on a system with relevant hardware.  The second load results in:
  pata_pdc2027x 0000:cc:01.0: version 0.9 
  PCI: Unable to reserve mem region #6:4000@40068000000 for device 0000:cc:01.0
  pata_pdc2027x: probe of 0000:cc:01.0 failed with error 

RHEL Version Found:
-------------------
This bug was found in RHEL 5.1 Beta

Upstream Status:
----------------
This functionality is backported from upstream.

Test Status:
------------
To ensure cross platform build, this code has been built with brew --scratch on
top of 2.6.18-32.el5.  Its results are availble at [1].

Albert Lee of IBM has tested this code to verify it is working and that load,
unload, reload of the pata_pdc2027x driver works as it should.

Proposed Patch:
----------------
Please review and ACK for RHEL5.1

---
 drivers/pci/pci.c |   27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

--- linux-2.6.18.i386/drivers/pci/pci.c.orig	2007-07-03 17:17:33.000000000 +0800
+++ linux-2.6.18.i386/drivers/pci/pci.c	2007-07-09 16:27:05.000000000 +0800
@@ -772,8 +772,13 @@ void __attribute__ ((weak)) pcibios_disa
 void
 pci_disable_device(struct pci_dev *dev)
 {
+	struct pci_devres *dr;
 	u16 pci_command;
 
+	dr = find_pci_dr(dev);
+	if (dr)
+		dr->enabled = 0;
+
 	if (dev->msi_enabled)
 		disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
 			PCI_CAP_ID_MSI);
@@ -898,6 +903,8 @@ pci_get_interrupt_pin(struct pci_dev *de
  */
 void pci_release_region(struct pci_dev *pdev, int bar)
 {
+	struct pci_devres *dr;
+
 	if (pci_resource_len(pdev, bar) == 0)
 		return;
 	if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
@@ -906,6 +913,10 @@ void pci_release_region(struct pci_dev *
 	else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM)
 		release_mem_region(pci_resource_start(pdev, bar),
 				pci_resource_len(pdev, bar));
+
+	dr = find_pci_dr(pdev);
+	if (dr)
+		dr->region_mask &= ~(1 << bar);
 }
 
 /**
@@ -924,6 +935,8 @@ void pci_release_region(struct pci_dev *
  */
 int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
 {
+	struct pci_devres *dr;
+
 	if (pci_resource_len(pdev, bar) == 0)
 		return 0;
 		
@@ -937,7 +950,11 @@ int pci_request_region(struct pci_dev *p
 				        pci_resource_len(pdev, bar), res_name))
 			goto err_out;
 	}
-	
+
+	dr = find_pci_dr(pdev);
+	if (dr)
+		dr->region_mask |= 1 << bar;
+
 	return 0;
 
 err_out:
@@ -1137,7 +1154,15 @@ pci_intx(struct pci_dev *pdev, int enabl
 	}
 
 	if (new != pci_command) {
+		struct pci_devres *dr;
+
 		pci_write_config_word(pdev, PCI_COMMAND, new);
+
+		dr = find_pci_dr(pdev);
+		if (dr && !dr->restore_intx) {
+			dr->restore_intx = 1;
+			dr->orig_intx = !enable;
+		}
 	}
 }