Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 294686
b: refs/heads/master
c: 925845b
h: refs/heads/master
v: v3
  • Loading branch information
Myron Stowe authored and Jesse Barnes committed Feb 14, 2012
1 parent a5b030e commit a545934
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 351fc6d1a5175d587d4f2b00ec7bff79b13ec48a
refs/heads/master: 925845bd49c6de437dfab3bf8dc654ea3ae21d74
79 changes: 79 additions & 0 deletions trunk/arch/x86/pci/i386.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,85 @@
#include <asm/io_apic.h>


/*
* This list of dynamic mappings is for temporarily maintaining
* original BIOS BAR addresses for possible reinstatement.
*/
struct pcibios_fwaddrmap {
struct list_head list;
struct pci_dev *dev;
resource_size_t fw_addr[DEVICE_COUNT_RESOURCE];
};

static LIST_HEAD(pcibios_fwaddrmappings);
static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);

/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
{
struct pcibios_fwaddrmap *map;

list_for_each_entry(map, &pcibios_fwaddrmappings, list)
if (map->dev == dev)
return map;

return NULL;
}

static void
pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
{
unsigned long flags;
struct pcibios_fwaddrmap *map;

spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
map = pcibios_fwaddrmap_lookup(dev);
if (!map) {
spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return;

map->dev = pci_dev_get(dev);
map->fw_addr[idx] = fw_addr;
INIT_LIST_HEAD(&map->list);

spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
list_add_tail(&map->list, &pcibios_fwaddrmappings);
} else
map->fw_addr[idx] = fw_addr;
spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
}

resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
{
unsigned long flags;
struct pcibios_fwaddrmap *map;
resource_size_t fw_addr = 0;

spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
map = pcibios_fwaddrmap_lookup(dev);
if (map)
fw_addr = map->fw_addr[idx];
spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);

return fw_addr;
}

static void pcibios_fw_addr_list_del(void)
{
unsigned long flags;
struct pcibios_fwaddrmap *entry, *next;

spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
list_for_each_entry_safe(entry, next, &pcibios_fwaddrmappings, list) {
list_del(&entry->list);
pci_dev_put(entry->dev);
kfree(entry);
}
spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
}

static int
skip_isa_ioresource_align(struct pci_dev *dev) {

Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void
int pci_vpd_truncate(struct pci_dev *dev, size_t size);

/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx);
void pci_bus_assign_resources(const struct pci_bus *bus);
void pci_bus_size_bridges(struct pci_bus *bus);
int pci_claim_resource(struct pci_dev *, int);
Expand Down

0 comments on commit a545934

Please sign in to comment.