diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2007-12-20 23:50:09 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-01-16 22:57:05 -0500 |
commit | 885b86e4e7ccc360f8ce4d7fb10dfdfb6e3c8650 (patch) | |
tree | 306b7438cdce8479397ee1ae8c9f244a07f9d9f7 /arch/powerpc/platforms/iseries | |
parent | b6ed42a794e1ca51fb46ff2bdc562315c46dd9a8 (diff) |
[POWERPC] iSeries: eliminate pci_dn bussubno
xlate_iomm_address() really wants the ds_addr to pass to the HV, so store
that value (instead of the BAR number) when we allocate the device bars.
This is not a fast path, so we can look up the device_node property
there instead of using the bussubno field of the pci_dn.
The other user of iseries_ds_addr() was already scanning the device tree,
so looking up a property will not slow it down any more.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/iseries')
-rw-r--r-- | arch/powerpc/platforms/iseries/pci.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 931941036b91..cc562e4c2f32 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/of.h> | ||
32 | 33 | ||
33 | #include <asm/types.h> | 34 | #include <asm/types.h> |
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
@@ -70,7 +71,7 @@ static long current_iomm_table_entry; | |||
70 | * Lookup Tables. | 71 | * Lookup Tables. |
71 | */ | 72 | */ |
72 | static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; | 73 | static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; |
73 | static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES]; | 74 | static u64 ds_addr_table[IOMM_TABLE_MAX_ENTRIES]; |
74 | 75 | ||
75 | static DEFINE_SPINLOCK(iomm_table_lock); | 76 | static DEFINE_SPINLOCK(iomm_table_lock); |
76 | 77 | ||
@@ -80,8 +81,9 @@ static DEFINE_SPINLOCK(iomm_table_lock); | |||
80 | static inline u64 iseries_ds_addr(struct device_node *node) | 81 | static inline u64 iseries_ds_addr(struct device_node *node) |
81 | { | 82 | { |
82 | struct pci_dn *pdn = PCI_DN(node); | 83 | struct pci_dn *pdn = PCI_DN(node); |
84 | const u32 *sbp = of_get_property(node, "linux,subbus", NULL); | ||
83 | 85 | ||
84 | return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40) | 86 | return ((u64)pdn->busno << 48) + ((u64)(sbp ? *sbp : 0) << 40) |
85 | + ((u64)0x10 << 32); | 87 | + ((u64)0x10 << 32); |
86 | } | 88 | } |
87 | 89 | ||
@@ -333,7 +335,8 @@ static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) | |||
333 | */ | 335 | */ |
334 | while (bar_size > 0 ) { | 336 | while (bar_size > 0 ) { |
335 | iomm_table[current_iomm_table_entry] = dev->sysdata; | 337 | iomm_table[current_iomm_table_entry] = dev->sysdata; |
336 | iobar_table[current_iomm_table_entry] = bar_num; | 338 | ds_addr_table[current_iomm_table_entry] = |
339 | iseries_ds_addr(dev->sysdata) | (bar_num << 24); | ||
337 | bar_size -= IOMM_TABLE_ENTRY_SIZE; | 340 | bar_size -= IOMM_TABLE_ENTRY_SIZE; |
338 | ++current_iomm_table_entry; | 341 | ++current_iomm_table_entry; |
339 | } | 342 | } |
@@ -598,8 +601,7 @@ static inline struct device_node *xlate_iomm_address( | |||
598 | dn = iomm_table[ind]; | 601 | dn = iomm_table[ind]; |
599 | 602 | ||
600 | if (dn != NULL) { | 603 | if (dn != NULL) { |
601 | int barnum = iobar_table[ind]; | 604 | *dsaptr = ds_addr_table[ind]; |
602 | *dsaptr = iseries_ds_addr(dn) | (barnum << 24); | ||
603 | *bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE; | 605 | *bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE; |
604 | } else | 606 | } else |
605 | panic("PCI: Invalid PCI IO address detected!\n"); | 607 | panic("PCI: Invalid PCI IO address detected!\n"); |