Commit 5c6c0af0 authored by Jeff Garzik's avatar Jeff Garzik

Add new architecture PCI API function helper, pdev_set_mwi().

Add new PCI API functions pci_set_mwi(), pci_clear_mwi().
parent 4ed485a5
...@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail. ...@@ -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 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. 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 4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...@@ -202,6 +207,8 @@ pci_resource_end() Returns bus end address for a given PCI region ...@@ -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_resource_len() Returns the byte length of a PCI region
pci_set_drvdata() Set private driver data pointer for a pci_dev 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_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 7. Miscellaneous hints
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/kmod.h> /* for hotplug_path */ #include <linux/kmod.h> /* for hotplug_path */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cache.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */ #include <asm/dma.h> /* isa_dma_bridge_buggy */
...@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev) ...@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev)
pcibios_set_master(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 int
pci_set_dma_mask(struct pci_dev *dev, u64 mask) pci_set_dma_mask(struct pci_dev *dev, u64 mask)
{ {
...@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device); ...@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_find_slot);
EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_find_subsys);
EXPORT_SYMBOL(pci_set_master); 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_set_dma_mask);
EXPORT_SYMBOL(pci_dac_set_dma_mask); EXPORT_SYMBOL(pci_dac_set_dma_mask);
EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_assign_resource);
......
...@@ -564,6 +564,10 @@ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val); ...@@ -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); int pci_enable_device(struct pci_dev *dev);
void pci_disable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev);
void pci_set_master(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_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_dac_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); int pci_assign_resource(struct pci_dev *dev, int i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment