Merge master.kernel.org:/home/rmk/linux-2.6-serial
[pandora-kernel.git] / drivers / pci / probe.c
index a10ed9d..c5a58d1 100644 (file)
@@ -180,25 +180,31 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                res->flags |= pci_calc_resource_flags(l);
                if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
                    == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-                       pci_read_config_dword(dev, reg+4, &l);
+                       u32 szhi, lhi;
+                       pci_read_config_dword(dev, reg+4, &lhi);
+                       pci_write_config_dword(dev, reg+4, ~0);
+                       pci_read_config_dword(dev, reg+4, &szhi);
+                       pci_write_config_dword(dev, reg+4, lhi);
+                       szhi = pci_size(lhi, szhi, 0xffffffff);
                        next++;
 #if BITS_PER_LONG == 64
-                       res->start |= ((unsigned long) l) << 32;
+                       res->start |= ((unsigned long) lhi) << 32;
                        res->end = res->start + sz;
-                       pci_write_config_dword(dev, reg+4, ~0);
-                       pci_read_config_dword(dev, reg+4, &sz);
-                       pci_write_config_dword(dev, reg+4, l);
-                       sz = pci_size(l, sz, 0xffffffff);
-                       if (sz) {
+                       if (szhi) {
                                /* This BAR needs > 4GB?  Wow. */
-                               res->end |= (unsigned long)sz<<32;
+                               res->end |= (unsigned long)szhi<<32;
                        }
 #else
-                       if (l) {
-                               printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev));
+                       if (szhi) {
+                               printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev));
                                res->start = 0;
                                res->flags = 0;
-                               continue;
+                       } else if (lhi) {
+                               /* 64-bit wide address, treat as disabled */
+                               pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
+                               pci_write_config_dword(dev, reg+4, 0);
+                               res->start = 0;
+                               res->end = sz;
                        }
 #endif
                }
@@ -377,9 +383,9 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
 
        child = pci_alloc_child_bus(parent, dev, busnr);
        if (child) {
-               spin_lock(&pci_bus_lock);
+               down_write(&pci_bus_sem);
                list_add_tail(&child->node, &parent->children);
-               spin_unlock(&pci_bus_lock);
+               up_write(&pci_bus_sem);
        }
        return child;
 }
@@ -809,6 +815,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
        dev->vendor = l & 0xffff;
        dev->device = (l >> 16) & 0xffff;
        dev->cfg_size = pci_cfg_space_size(dev);
+       dev->error_state = pci_channel_io_normal;
 
        /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
           set this higher, assuming the system even supports it.  */
@@ -838,9 +845,9 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
         * and the bus list for fixup functions, etc.
         */
        INIT_LIST_HEAD(&dev->global_list);
-       spin_lock(&pci_bus_lock);
+       down_write(&pci_bus_sem);
        list_add_tail(&dev->bus_list, &bus->devices);
-       spin_unlock(&pci_bus_lock);
+       up_write(&pci_bus_sem);
 }
 
 struct pci_dev * __devinit
@@ -975,9 +982,10 @@ struct pci_bus * __devinit pci_create_bus(struct device *parent,
                pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
                goto err_out;
        }
-       spin_lock(&pci_bus_lock);
+
+       down_write(&pci_bus_sem);
        list_add_tail(&b->node, &pci_root_buses);
-       spin_unlock(&pci_bus_lock);
+       up_write(&pci_bus_sem);
 
        memset(dev, 0, sizeof(*dev));
        dev->parent = parent;
@@ -1017,9 +1025,9 @@ class_dev_create_file_err:
 class_dev_reg_err:
        device_unregister(dev);
 dev_reg_err:
-       spin_lock(&pci_bus_lock);
+       down_write(&pci_bus_sem);
        list_del(&b->node);
-       spin_unlock(&pci_bus_lock);
+       up_write(&pci_bus_sem);
 err_out:
        kfree(dev);
        kfree(b);