Re: PCI patches (3/3)

Russell King (rmk@arm.linux.org.uk)
Sat, 22 Mar 2003 16:56:41 +0000


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1132 -> 1.1133
# drivers/pci/pci.c 1.52 -> 1.53
# arch/i386/pci/common.c 1.36 -> 1.37
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/03/22 ink@ru.rmk.(none) 1.1133
# [PCI] Fix incorrect PCI cache line size assumptions.
#
# Fix incorrect PCI cache line size assumptions on i386 and thus
# avoid potential memory corruption with Memory Write-and-Invalidate.
# --------------------------------------------
#
diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c
--- a/arch/i386/pci/common.c Sat Mar 22 16:53:43 2003
+++ b/arch/i386/pci/common.c Sat Mar 22 16:53:43 2003
@@ -120,12 +120,27 @@
return pci_scan_bus(busnum, pci_root_ops, NULL);
}

+extern u8 pci_cache_line_size;
+
static int __init pcibios_init(void)
{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+
if (!pci_root_ops) {
printk("PCI: System does not support PCI\n");
return 0;
}
+
+ /*
+ * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8
+ * and P4. It's also good for 386/486s (which actually have 16)
+ * as quite a few PCI devices do not support smaller values.
+ */
+ 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 */

pcibios_resource_survey();

diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Mar 22 16:53:43 2003
+++ b/drivers/pci/pci.c Sat Mar 22 16:53:43 2003
@@ -584,6 +584,9 @@
}

#ifndef HAVE_ARCH_PCI_MWI
+/* This can be overridden by arch code. */
+u8 pci_cache_line_size = L1_CACHE_BYTES >> 2;
+
/**
* pci_generic_prep_mwi - helper function for pci_set_mwi
* @dev: the PCI device for which MWI is enabled
@@ -597,32 +600,29 @@
static int
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, ",
- 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);
- }
- }
+ 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 */

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html

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