[patch 2.5.40] read-only PCI BARs, try #2

From: Ivan Kokshaysky (ink@jurassic.park.msu.ru)
Date: Sun Oct 06 2002 - 09:46:15 EST


Linus,
here is a non-destructive version of the previous patch.
It's a bit more complex as we have to handle
the 'old_value == probed_value' case correctly without
extra write(0) probe.

Ivan.

--- 2.5.40/drivers/pci/probe.c Sat Sep 21 12:54:53 2002
+++ linux/drivers/pci/probe.c Sun Oct 6 01:59:31 2002
@@ -34,13 +34,20 @@ static inline unsigned int pci_calc_reso
 }
 
 /*
- * Find the extent of a PCI decode..
+ * Find the extent of a PCI decode, do sanity checks.
  */
-static u32 pci_size(u32 base, unsigned long mask)
+static u32 pci_size(u32 base, u32 maxbase, unsigned long mask)
 {
- u32 size = mask & base; /* Find the significant bits */
+ u32 size = mask & maxbase; /* Find the significant bits */
+ if (!size)
+ return 0;
         size = size & ~(size-1); /* Get the lowest of them to find the decode size */
- return size-1; /* extent = size - 1 */
+ size -= 1; /* extent = size - 1 */
+ if (base == maxbase && ((base | size) & mask) != mask)
+ return 0; /* base == maxbase can be valid only
+ if the BAR has been already
+ programmed with all 1s */
+ return size;
 }
 
 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
@@ -63,13 +70,17 @@ static void pci_read_bases(struct pci_de
                 if (l == 0xffffffff)
                         l = 0;
                 if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
+ sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
+ if (!sz)
+ continue;
                         res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
                         res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
- sz = pci_size(sz, PCI_BASE_ADDRESS_MEM_MASK);
                 } else {
+ sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
+ if (!sz)
+ continue;
                         res->start = l & PCI_BASE_ADDRESS_IO_MASK;
                         res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
- sz = pci_size(sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
                 }
                 res->end = res->start + (unsigned long) sz;
                 res->flags |= pci_calc_resource_flags(l);
@@ -99,6 +110,7 @@ static void pci_read_bases(struct pci_de
         if (rom) {
                 dev->rom_base_reg = rom;
                 res = &dev->resource[PCI_ROM_RESOURCE];
+ res->name = dev->name;
                 pci_read_config_dword(dev, rom, &l);
                 pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE);
                 pci_read_config_dword(dev, rom, &sz);
@@ -106,13 +118,14 @@ static void pci_read_bases(struct pci_de
                 if (l == 0xffffffff)
                         l = 0;
                 if (sz && sz != 0xffffffff) {
+ sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK);
+ if (!sz)
+ return;
                         res->flags = (l & PCI_ROM_ADDRESS_ENABLE) |
                           IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
                         res->start = l & PCI_ROM_ADDRESS_MASK;
- sz = pci_size(sz, PCI_ROM_ADDRESS_MASK);
                         res->end = res->start + (unsigned long) sz;
                 }
- res->name = dev->name;
         }
 }
 
-
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/



This archive was generated by hypermail 2b29 : Mon Oct 07 2002 - 22:00:54 EST