Skip to content

Commit

Permalink
x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
Browse files Browse the repository at this point in the history
Introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap(), which will be used
when supporting PCI root bridge hotplug.

Reviewed-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
  • Loading branch information
Jiang Liu authored and bjorn-helgaas committed Jun 22, 2012
1 parent 376f70a commit 9cf0105
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
2 changes: 2 additions & 0 deletions arch/x86/include/asm/pci_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ struct pci_mmcfg_region {

extern int __init pci_mmcfg_arch_init(void);
extern void __init pci_mmcfg_arch_free(void);
extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);

extern struct list_head pci_mmcfg_list;
Expand Down
15 changes: 15 additions & 0 deletions arch/x86/pci/mmconfig_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,18 @@ int __init pci_mmcfg_arch_init(void)
void __init pci_mmcfg_arch_free(void)
{
}

int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
{
return 0;
}

void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
{
unsigned long flags;

/* Invalidate the cached mmcfg map entry. */
raw_spin_lock_irqsave(&pci_config_lock, flags);
mmcfg_last_accessed_device = 0;
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
38 changes: 26 additions & 12 deletions arch/x86/pci/mmconfig_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static const struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};

static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg)
static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg)
{
void __iomem *addr;
u64 start, size;
Expand All @@ -114,27 +114,41 @@ int __init pci_mmcfg_arch_init(void)
{
struct pci_mmcfg_region *cfg;

list_for_each_entry(cfg, &pci_mmcfg_list, list) {
cfg->virt = mcfg_ioremap(cfg);
if (!cfg->virt) {
printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
&cfg->res);
list_for_each_entry(cfg, &pci_mmcfg_list, list)
if (pci_mmcfg_arch_map(cfg)) {
pci_mmcfg_arch_free();
return 0;
}
}

raw_pci_ext_ops = &pci_mmcfg;

return 1;
}

void __init pci_mmcfg_arch_free(void)
{
struct pci_mmcfg_region *cfg;

list_for_each_entry(cfg, &pci_mmcfg_list, list) {
if (cfg->virt) {
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
cfg->virt = NULL;
}
list_for_each_entry(cfg, &pci_mmcfg_list, list)
pci_mmcfg_arch_unmap(cfg);
}

int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
{
cfg->virt = mcfg_ioremap(cfg);
if (!cfg->virt) {
printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
&cfg->res);
return -ENOMEM;
}

return 0;
}

void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
{
if (cfg && cfg->virt) {
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
cfg->virt = NULL;
}
}

0 comments on commit 9cf0105

Please sign in to comment.