Messages in this thread Patch in this message | | | Date | Sat, 22 Mar 2003 16:56:41 +0000 | From | Russell King <> | Subject | Re: PCI patches (3/3) |
| |
# 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/
| |