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.
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
......
......@@ -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);
......
......@@ -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);
......
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