Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 63a7228

Browse files
Guilherme G. Piccolimpe
authored andcommitted
powerpc/pci: Assign fixed PHB number based on device-tree properties
The domain/PHB field of PCI addresses has its value obtained from a global variable, incremented each time a new domain (represented by struct pci_controller) is added on the system. The domain addition process happens during boot or due to PHB hotplug add. As recent kernels are using predictable naming for network interfaces, the network stack is more tied to PCI naming. This can be a problem in hotplug scenarios, because PCI addresses will change if devices are removed and then re-added. This situation seems unusual, but it can happen if a user wants to replace a NIC without rebooting the machine, for example. This patch changes the way PCI domain values are generated: now, we use device-tree properties to assign fixed PHB numbers to PCI addresses when available (meaning pSeries and PowerNV cases). We also use a bitmap to allow dynamic PHB numbering when device-tree properties are not used. This bitmap keeps track of used PHB numbers and if a PHB is released (by hotplug operations for example), it allows the reuse of this PHB number, avoiding PCI address to change in case of device remove and re-add soon after. No functional changes were introduced. Signed-off-by: Guilherme G. Piccoli <[email protected]> Reviewed-by: Gavin Shan <[email protected]> Reviewed-by: Ian Munsie <[email protected]> Acked-by: Gavin Shan <[email protected]> [mpe: Drop unnecessary machine_is(pseries) test] Signed-off-by: Michael Ellerman <[email protected]>
1 parent fc022fd commit 63a7228

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

arch/powerpc/kernel/pci-common.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,18 @@
4141
#include <asm/ppc-pci.h>
4242
#include <asm/eeh.h>
4343

44+
/* hose_spinlock protects accesses to the the phb_bitmap. */
4445
static DEFINE_SPINLOCK(hose_spinlock);
4546
LIST_HEAD(hose_list);
4647

47-
/* XXX kill that some day ... */
48-
static int global_phb_number; /* Global phb counter */
48+
/* For dynamic PHB numbering on get_phb_number(): max number of PHBs. */
49+
#define MAX_PHBS 0x10000
50+
51+
/*
52+
* For dynamic PHB numbering: used/free PHBs tracking bitmap.
53+
* Accesses to this bitmap should be protected by hose_spinlock.
54+
*/
55+
static DECLARE_BITMAP(phb_bitmap, MAX_PHBS);
4956

5057
/* ISA Memory physical address */
5158
resource_size_t isa_mem_base;
@@ -64,6 +71,42 @@ struct dma_map_ops *get_pci_dma_ops(void)
6471
}
6572
EXPORT_SYMBOL(get_pci_dma_ops);
6673

74+
/*
75+
* This function should run under locking protection, specifically
76+
* hose_spinlock.
77+
*/
78+
static int get_phb_number(struct device_node *dn)
79+
{
80+
int ret, phb_id = -1;
81+
u64 prop;
82+
83+
/*
84+
* Try fixed PHB numbering first, by checking archs and reading
85+
* the respective device-tree properties. Firstly, try powernv by
86+
* reading "ibm,opal-phbid", only present in OPAL environment.
87+
*/
88+
ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
89+
if (ret)
90+
ret = of_property_read_u32_index(dn, "reg", 1, (u32 *)&prop);
91+
92+
if (!ret)
93+
phb_id = (int)(prop & (MAX_PHBS - 1));
94+
95+
/* We need to be sure to not use the same PHB number twice. */
96+
if ((phb_id >= 0) && !test_and_set_bit(phb_id, phb_bitmap))
97+
return phb_id;
98+
99+
/*
100+
* If not pseries nor powernv, or if fixed PHB numbering tried to add
101+
* the same PHB number twice, then fallback to dynamic PHB numbering.
102+
*/
103+
phb_id = find_first_zero_bit(phb_bitmap, MAX_PHBS);
104+
BUG_ON(phb_id >= MAX_PHBS);
105+
set_bit(phb_id, phb_bitmap);
106+
107+
return phb_id;
108+
}
109+
67110
struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
68111
{
69112
struct pci_controller *phb;
@@ -72,7 +115,7 @@ struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
72115
if (phb == NULL)
73116
return NULL;
74117
spin_lock(&hose_spinlock);
75-
phb->global_number = global_phb_number++;
118+
phb->global_number = get_phb_number(dev);
76119
list_add_tail(&phb->list_node, &hose_list);
77120
spin_unlock(&hose_spinlock);
78121
phb->dn = dev;
@@ -94,6 +137,11 @@ EXPORT_SYMBOL_GPL(pcibios_alloc_controller);
94137
void pcibios_free_controller(struct pci_controller *phb)
95138
{
96139
spin_lock(&hose_spinlock);
140+
141+
/* Clear bit of phb_bitmap to allow reuse of this PHB number. */
142+
if (phb->global_number < MAX_PHBS)
143+
clear_bit(phb->global_number, phb_bitmap);
144+
97145
list_del(&phb->list_node);
98146
spin_unlock(&hose_spinlock);
99147

0 commit comments

Comments
 (0)