[bk patch] PCI MWI updates/fixes

From: Jeff Garzik
Date: Sat Aug 30 2003 - 22:02:51 EST



Marcelo, please do a

bk pull bk://kernel.bkbits.net/jgarzik/misc-2.4

This will update the following files:

arch/i386/kernel/pci-i386.c | 11 ++++++++
arch/i386/kernel/pci-i386.h | 2 +
arch/i386/kernel/pci-pc.c | 2 +
arch/i386/kernel/pci-visws.c | 1
drivers/pci/pci.c | 55 ++++++++++++++++++++++---------------------
5 files changed, 45 insertions(+), 26 deletions(-)

through these ChangeSets:

<ink@xxxxxxxxxxxxxxxxxxxx> (03/08/30 1.1102)
[PCI] update Memory-Write-Invalidate (MWI) transaction support

Sync up PCI MWI code with 2.5:
- no changes required for drivers or architectures with HAVE_ARCH_PCI_MWI;
- do respect BIOS settings: if the cacheline size is multiple
of that we have expected, assume that this is on purpose;
- assume cacheline size of 32 bytes for all x86s except K7/K8 and P4.
Actually it's good for 386/486s as quite a few PCI devices do not support
smaller values.



diff -Nru a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c
--- a/arch/i386/kernel/pci-i386.c Sat Aug 30 22:57:53 2003
+++ b/arch/i386/kernel/pci-i386.c Sat Aug 30 22:57:53 2003
@@ -295,6 +295,17 @@
}
}

+void __init pcibios_set_cacheline_size(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+
+ pci_cache_line_size = 32 >> 2;
+ if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
+ pci_cache_line_size = 64 >> 2; /* K7 & K8 */
+ else if (c->x86 > 6)
+ pci_cache_line_size = 128 >> 2; /* P4 */
+}
+
void __init pcibios_resource_survey(void)
{
DBG("PCI: Allocating resources\n");
diff -Nru a/arch/i386/kernel/pci-i386.h b/arch/i386/kernel/pci-i386.h
--- a/arch/i386/kernel/pci-i386.h Sat Aug 30 22:57:53 2003
+++ b/arch/i386/kernel/pci-i386.h Sat Aug 30 22:57:53 2003
@@ -27,8 +27,10 @@
/* pci-i386.c */

extern unsigned int pcibios_max_latency;
+extern u8 pci_cache_line_size;

void pcibios_resource_survey(void);
+void pcibios_set_cacheline_size(void);
int pcibios_enable_resources(struct pci_dev *, int);

/* pci-pc.c */
diff -Nru a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
--- a/arch/i386/kernel/pci-pc.c Sat Aug 30 22:57:53 2003
+++ b/arch/i386/kernel/pci-pc.c Sat Aug 30 22:57:53 2003
@@ -1428,6 +1428,8 @@
return;
}

+ pcibios_set_cacheline_size();
+
printk(KERN_INFO "PCI: Probing PCI hardware\n");
#ifdef CONFIG_ACPI_PCI
if (use_acpi_pci && !acpi_pci_irq_init()) {
diff -Nru a/arch/i386/kernel/pci-visws.c b/arch/i386/kernel/pci-visws.c
--- a/arch/i386/kernel/pci-visws.c Sat Aug 30 22:57:53 2003
+++ b/arch/i386/kernel/pci-visws.c Sat Aug 30 22:57:53 2003
@@ -119,6 +119,7 @@
{
unsigned int sec_bus = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;

+ pcibios_set_cacheline_size();
printk("PCI: Probing PCI hardware on host buses 00 and %02x\n", sec_bus);
pci_scan_bus(0, &visws_pci_ops, NULL);
pci_scan_bus(sec_bus, &visws_pci_ops, NULL);
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Aug 30 22:57:53 2003
+++ b/drivers/pci/pci.c Sat Aug 30 22:57:53 2003
@@ -907,8 +907,12 @@
pcibios_set_master(dev);
}

+#ifndef HAVE_ARCH_PCI_MWI
+/* This can be overridden by arch code. */
+u8 pci_cache_line_size = L1_CACHE_BYTES >> 2;
+
/**
- * pdev_set_mwi - arch helper function for pcibios_set_mwi
+ * pci_generic_prep_mwi - helper function for pci_set_mwi
* @dev: the PCI device for which MWI is enabled
*
* Helper function for implementation the arch-specific pcibios_set_mwi
@@ -918,34 +922,33 @@
* RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
*/
int
-pdev_set_mwi(struct pci_dev *dev)
+pci_generic_prep_mwi(struct pci_dev *dev)
{
- int rc = 0;
- u8 cache_size;
+ u8 cacheline_size;
+
+ if (!pci_cache_line_size)
+ return -EINVAL; /* The system doesn't support MWI. */
+
+ /* Validate current setting: the PCI_CACHE_LINE_SIZE must be
+ equal to or multiple of the right value. */
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size);
+ if (cacheline_size >= pci_cache_line_size &&
+ (cacheline_size % pci_cache_line_size) == 0)
+ return 0;
+
+ /* Write the correct value. */
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size);
+ /* Read it back. */
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size);
+ if (cacheline_size == pci_cache_line_size)
+ return 0;

- /*
- * 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.\n",
- dev->slot_name, cache_size);
- if (cache_size > SMP_CACHE_BYTES) {
- printk("PCI: %s cache line size too large - expecting %i.\n", dev->slot_name, SMP_CACHE_BYTES);
- rc = -EINVAL;
- } else {
- printk("PCI: %s PCI cache line size corrected to %i.\n", dev->slot_name, SMP_CACHE_BYTES);
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- SMP_CACHE_BYTES >> 2);
- }
- }
+ printk(KERN_WARNING "PCI: cache line size of %d is not supported "
+ "by device %s\n", pci_cache_line_size << 2, dev->slot_name);

- return rc;
+ return -EINVAL;
}
+#endif /* !HAVE_ARCH_PCI_MWI */

/**
* pci_set_mwi - enables memory-write-invalidate PCI transaction
@@ -966,7 +969,7 @@
#ifdef HAVE_ARCH_PCI_MWI
rc = pcibios_set_mwi(dev);
#else
- rc = pdev_set_mwi(dev);
+ rc = pci_generic_prep_mwi(dev);
#endif

if (rc)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/