]> git.hungrycats.org Git - linux/commitdiff
Add new architecture PCI API function helper, pdev_set_mwi().
authorJeff Garzik <jgarzik@mandrakesoft.com>
Wed, 6 Mar 2002 16:23:59 +0000 (11:23 -0500)
committerJeff Garzik <jgarzik@mandrakesoft.com>
Wed, 6 Mar 2002 16:23:59 +0000 (11:23 -0500)
Add new PCI API functions pci_set_mwi(), pci_clear_mwi().

Documentation/pci.txt
drivers/pci/pci.c
include/linux/pci.h

index 5ac05854aa8976d99b34ff5d3fe03f4b74a4ffc9..496abe268ad4aa614e64065f0fae514f30e39376 100644 (file)
@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail.
 which enables the bus master bit in PCI_COMMAND register and also fixes
 the latency timer value if it's set to something bogus by the BIOS.
 
+   If you want to use the PCI Memory-Write-Invalidate transaction,
+call pci_set_mwi().  This enables bit PCI_COMMAND bit for Mem-Wr-Inval
+and also ensures that the cache line size register is set correctly.
+Make sure to check the return value of pci_set_mwi(), not all architectures
+may support Memory-Write-Invalidate.
 
 4. How to access PCI config space
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -202,6 +207,8 @@ pci_resource_end()          Returns bus end address for a given PCI region
 pci_resource_len()             Returns the byte length of a PCI region
 pci_set_drvdata()              Set private driver data pointer for a pci_dev
 pci_get_drvdata()              Return private driver data pointer for a pci_dev
+pci_set_mwi()                  Enable Memory-Write-Invalidate transactions.
+pci_clear_mwi()                        Disable Memory-Write-Invalidate transactions.
 
 
 7. Miscellaneous hints
index c41975638b82ed93a006da49323155ec15ff3d0f..fdd083a62235f7047eba64d2aed68b701e2fa963 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kmod.h>                /* for hotplug_path */
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/cache.h>
 
 #include <asm/page.h>
 #include <asm/dma.h>   /* isa_dma_bridge_buggy */
@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev)
        pcibios_set_master(dev);
 }
 
+/**
+ * pdev_set_mwi - arch helper function for pcibios_set_mwi
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Helper function for implementation the arch-specific pcibios_set_mwi
+ * function.  Originally copied from drivers/net/acenic.c.
+ * Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>.
+ *
+ * RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
+ */
+int
+pdev_set_mwi(struct pci_dev *dev)
+{
+       int rc = 0;
+       u8 cache_size;
+
+       /*
+        * Looks like this is necessary to deal with on all architectures,
+        * even this %$#%$# N440BX Intel based thing doesn't get it right.
+        * Ie. having two NICs in the machine, one will have the cache
+        * line set at boot time, the other will not.
+        */
+       pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cache_size);
+       cache_size <<= 2;
+       if (cache_size != SMP_CACHE_BYTES) {
+               printk(KERN_WARNING "PCI: %s PCI cache line size set incorrectly "
+                      "(%i bytes) by BIOS/FW, ",
+                      dev->slot_name, cache_size);
+               if (cache_size > SMP_CACHE_BYTES) {
+                       printk("expecting %i\n", SMP_CACHE_BYTES);
+                       rc = -EINVAL;
+               } else {
+                       printk("correcting to %i\n", SMP_CACHE_BYTES);
+                       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+                                             SMP_CACHE_BYTES >> 2);
+               }
+       }
+
+       return rc;
+}
+
+/**
+ * pci_set_mwi - enables memory-write-validate PCI transaction
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
+ * and then calls @pcibios_set_mwi to do the needed arch specific
+ * operations or a generic mwi-prep function.
+ *
+ * RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
+ */
+int
+pci_set_mwi(struct pci_dev *dev)
+{
+       int rc;
+       u16 cmd;
+
+#ifdef HAVE_ARCH_PCI_MWI
+       rc = pcibios_set_mwi(dev);
+#else
+       rc = pdev_set_mwi(dev);
+#endif
+
+       if (rc)
+               return rc;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       if (! (cmd & PCI_COMMAND_INVALIDATE)) {
+               DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name);
+               cmd |= PCI_COMMAND_INVALIDATE;
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       
+       return 0;
+}
+
+/**
+ * pci_clear_mwi - disables Memory-Write-Invalidate for device dev
+ * @dev: the PCI device to disable
+ *
+ * Disables PCI Memory-Write-Invalidate transaction on the device
+ */
+void
+pci_clear_mwi(struct pci_dev *dev)
+{
+       u16 cmd;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       if (cmd & PCI_COMMAND_INVALIDATE) {
+               cmd &= ~PCI_COMMAND_INVALIDATE;
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+}
+
 int
 pci_set_dma_mask(struct pci_dev *dev, u64 mask)
 {
@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_find_subsys);
 EXPORT_SYMBOL(pci_set_master);
+EXPORT_SYMBOL(pci_set_mwi);
+EXPORT_SYMBOL(pci_clear_mwi);
+EXPORT_SYMBOL(pdev_set_mwi);
 EXPORT_SYMBOL(pci_set_dma_mask);
 EXPORT_SYMBOL(pci_dac_set_dma_mask);
 EXPORT_SYMBOL(pci_assign_resource);
index 5e3af89eee898b505da688360b4f774c2318cc67..074049025ea9c4238ed4d9b47babd4fdc4fad742 100644 (file)
@@ -564,6 +564,10 @@ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
 int pci_enable_device(struct pci_dev *dev);
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
+#define HAVE_PCI_SET_MWI
+int pci_set_mwi(struct pci_dev *dev);
+void pci_clear_mwi(struct pci_dev *dev);
+int pdev_set_mwi(struct pci_dev *dev);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_assign_resource(struct pci_dev *dev, int i);