Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 30 Nov 2009 18:27:17 -0500
Subject: [pci] add and export pci_clear_master
Message-id: <20091130182717.11132.75038.stgit@localhost.localdomain>
Patchwork-id: 21545
O-Subject: [RHEL5.5 PATCH 1/5] pci: add and export pci_clear_master()
Bugzilla: 448856
RH-Acked-by: David S. Miller <davem@redhat.com>
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: John Linville <linville@redhat.com>

needed for:
https://bugzilla.redhat.com/show_bug.cgi?id=448856

Add pci_clear_master() as an opposite to pci_set_master().
It disables bus mastering. The sfc driver needs it for online device reset.

Upstream status:
Present in 2.6.29:
    commit 6a479079c07211bf348ac8a79754f26bea258f26
    Author: Ben Hutchings <bhutchings@solarflare.com>
    PCI: Add pci_clear_master() as opposite of pci_set_master()

KABI:
This exports a new symbol which is the same as in upstream:
    void pci_clear_master(struct pci_dev *dev)
    EXPORT_SYMBOL(pci_clear_master);

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 01dbf5e..3ced3f8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1182,6 +1182,22 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)
 	return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name);
 }
 
+static void __pci_set_master(struct pci_dev *dev, bool enable)
+{
+	u16 old_cmd, cmd;
+
+	pci_read_config_word(dev, PCI_COMMAND, &old_cmd);
+	if (enable)
+		cmd = old_cmd | PCI_COMMAND_MASTER;
+	else
+		cmd = old_cmd & ~PCI_COMMAND_MASTER;
+	if (cmd != old_cmd) {
+		pr_debug("PCI: %s bus mastering for device %s\n",
+			enable ? "Enabling" : "Disabling", pci_name(dev));
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	dev->is_busmaster = enable;
+}
 /**
  * pci_set_master - enables bus-mastering for device dev
  * @dev: the PCI device to enable
@@ -1189,21 +1205,21 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)
  * Enables bus-mastering on the device and calls pcibios_set_master()
  * to do the needed arch specific settings.
  */
-void
-pci_set_master(struct pci_dev *dev)
+void pci_set_master(struct pci_dev *dev)
 {
-	u16 cmd;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	if (! (cmd & PCI_COMMAND_MASTER)) {
-		pr_debug("PCI: Enabling bus mastering for device %s\n", pci_name(dev));
-		cmd |= PCI_COMMAND_MASTER;
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	dev->is_busmaster = 1;
+	__pci_set_master(dev, true);
 	pcibios_set_master(dev);
 }
 
+/**
+ * pci_clear_master - disables bus-mastering for device dev
+ * @dev: the PCI device to disable
+ */
+void pci_clear_master(struct pci_dev *dev)
+{
+	__pci_set_master(dev, false);
+}
+
 #ifndef HAVE_ARCH_PCI_MWI
 /* This can be overridden by arch code. */
 u8 pci_cache_line_size = L1_CACHE_BYTES >> 2;
@@ -1807,6 +1823,7 @@ EXPORT_SYMBOL(pci_request_region);
 EXPORT_SYMBOL(pci_release_selected_regions);
 EXPORT_SYMBOL(pci_request_selected_regions);
 EXPORT_SYMBOL(pci_set_master);
+EXPORT_SYMBOL(pci_clear_master);
 EXPORT_SYMBOL(pci_set_mwi);
 EXPORT_SYMBOL(pci_try_set_mwi);
 EXPORT_SYMBOL(pci_clear_mwi);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7a7f154..452803a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -597,6 +597,7 @@ int pci_enable_device_io(struct pci_dev *dev);
 int pci_enable_device_mem(struct pci_dev *dev);
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
+void pci_clear_master(struct pci_dev *dev);
 int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
 #define HAVE_PCI_SET_MWI
 int pci_set_mwi(struct pci_dev *dev);