Skip to content

Commit cca87d3

Browse files
Gavin Shanozbenh
authored andcommitted
powerpc/pci: Refactor pci_dn
Currently, the PCI config accessors are implemented based on device node. Unfortunately, SRIOV VFs won't have the corresponding device nodes. pci_dn will be used in replacement with device node for SRIOV VFs. So we have to use pci_dn in PCI config accessors. The patch refactors pci_dn in following aspects to make it ready to be used in PCI config accessors as we do in subsequent patch: * pci_dn is organized as a hierarchy tree. PCI device's pci_dn is put to the child list of pci_dn of its upstream bridge or PHB. VF's pci_dn will be put to the child list of pci_dn of PF's bridge. * For one particular PCI device (VF or not), its pci_dn can be found from pdev->dev.archdata.pci_data, PCI_DN(devnode), or parent's list. The fast path (fetching pci_dn through PCI device instance) is populated during early fixup time. [bhelgaas: changelog] Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
1 parent 12a89db commit cca87d3

File tree

3 files changed

+141
-6
lines changed

3 files changed

+141
-6
lines changed

arch/powerpc/include/asm/device.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
struct dma_map_ops;
1010
struct device_node;
11+
#ifdef CONFIG_PPC64
12+
struct pci_dn;
13+
#endif
1114

1215
/*
1316
* Arch extensions to struct device.
@@ -34,6 +37,9 @@ struct dev_archdata {
3437
#ifdef CONFIG_SWIOTLB
3538
dma_addr_t max_direct_dma_addr;
3639
#endif
40+
#ifdef CONFIG_PPC64
41+
struct pci_dn *pci_data;
42+
#endif
3743
#ifdef CONFIG_EEH
3844
struct eeh_dev *edev;
3945
#endif

arch/powerpc/include/asm/pci-bridge.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct pci_controller {
8989

9090
#ifdef CONFIG_PPC64
9191
unsigned long buid;
92+
struct pci_dn *pci_data;
9293
#endif /* CONFIG_PPC64 */
9394

9495
void *private_data;
@@ -154,9 +155,12 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
154155
struct iommu_table;
155156

156157
struct pci_dn {
158+
int flags;
159+
157160
int busno; /* pci bus number */
158161
int devfn; /* pci device and function number */
159162

163+
struct pci_dn *parent;
160164
struct pci_controller *phb; /* for pci devices */
161165
struct iommu_table *iommu_table; /* for phb's or bridges */
162166
struct device_node *node; /* back-pointer to the device_node */
@@ -171,14 +175,17 @@ struct pci_dn {
171175
#ifdef CONFIG_PPC_POWERNV
172176
int pe_number;
173177
#endif
178+
struct list_head child_list;
179+
struct list_head list;
174180
};
175181

176182
/* Get the pointer to a device_node's pci_dn */
177183
#define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
178184

185+
extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
186+
int devfn);
179187
extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
180-
181-
extern void * update_dn_pci_info(struct device_node *dn, void *data);
188+
extern void *update_dn_pci_info(struct device_node *dn, void *data);
182189

183190
static inline int pci_device_from_OF_node(struct device_node *np,
184191
u8 *bus, u8 *devfn)

arch/powerpc/kernel/pci_dn.c

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,108 @@
3232
#include <asm/ppc-pci.h>
3333
#include <asm/firmware.h>
3434

35+
/*
36+
* The function is used to find the firmware data of one
37+
* specific PCI device, which is attached to the indicated
38+
* PCI bus. For VFs, their firmware data is linked to that
39+
* one of PF's bridge. For other devices, their firmware
40+
* data is linked to that of their bridge.
41+
*/
42+
static struct pci_dn *pci_bus_to_pdn(struct pci_bus *bus)
43+
{
44+
struct pci_bus *pbus;
45+
struct device_node *dn;
46+
struct pci_dn *pdn;
47+
48+
/*
49+
* We probably have virtual bus which doesn't
50+
* have associated bridge.
51+
*/
52+
pbus = bus;
53+
while (pbus) {
54+
if (pci_is_root_bus(pbus) || pbus->self)
55+
break;
56+
57+
pbus = pbus->parent;
58+
}
59+
60+
/*
61+
* Except virtual bus, all PCI buses should
62+
* have device nodes.
63+
*/
64+
dn = pci_bus_to_OF_node(pbus);
65+
pdn = dn ? PCI_DN(dn) : NULL;
66+
67+
return pdn;
68+
}
69+
70+
struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
71+
int devfn)
72+
{
73+
struct device_node *dn = NULL;
74+
struct pci_dn *parent, *pdn;
75+
struct pci_dev *pdev = NULL;
76+
77+
/* Fast path: fetch from PCI device */
78+
list_for_each_entry(pdev, &bus->devices, bus_list) {
79+
if (pdev->devfn == devfn) {
80+
if (pdev->dev.archdata.pci_data)
81+
return pdev->dev.archdata.pci_data;
82+
83+
dn = pci_device_to_OF_node(pdev);
84+
break;
85+
}
86+
}
87+
88+
/* Fast path: fetch from device node */
89+
pdn = dn ? PCI_DN(dn) : NULL;
90+
if (pdn)
91+
return pdn;
92+
93+
/* Slow path: fetch from firmware data hierarchy */
94+
parent = pci_bus_to_pdn(bus);
95+
if (!parent)
96+
return NULL;
97+
98+
list_for_each_entry(pdn, &parent->child_list, list) {
99+
if (pdn->busno == bus->number &&
100+
pdn->devfn == devfn)
101+
return pdn;
102+
}
103+
104+
return NULL;
105+
}
106+
35107
struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
36108
{
37-
struct device_node *dn = pci_device_to_OF_node(pdev);
38-
if (!dn)
109+
struct device_node *dn;
110+
struct pci_dn *parent, *pdn;
111+
112+
/* Search device directly */
113+
if (pdev->dev.archdata.pci_data)
114+
return pdev->dev.archdata.pci_data;
115+
116+
/* Check device node */
117+
dn = pci_device_to_OF_node(pdev);
118+
pdn = dn ? PCI_DN(dn) : NULL;
119+
if (pdn)
120+
return pdn;
121+
122+
/*
123+
* VFs don't have device nodes. We hook their
124+
* firmware data to PF's bridge.
125+
*/
126+
parent = pci_bus_to_pdn(pdev->bus);
127+
if (!parent)
39128
return NULL;
40-
return PCI_DN(dn);
129+
130+
list_for_each_entry(pdn, &parent->child_list, list) {
131+
if (pdn->busno == pdev->bus->number &&
132+
pdn->devfn == pdev->devfn)
133+
return pdn;
134+
}
135+
136+
return NULL;
41137
}
42138

43139
/*
@@ -49,6 +145,7 @@ void *update_dn_pci_info(struct device_node *dn, void *data)
49145
struct pci_controller *phb = data;
50146
const __be32 *type = of_get_property(dn, "ibm,pci-config-space-type", NULL);
51147
const __be32 *regs;
148+
struct device_node *parent;
52149
struct pci_dn *pdn;
53150

54151
pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL);
@@ -70,6 +167,15 @@ void *update_dn_pci_info(struct device_node *dn, void *data)
70167
}
71168

72169
pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1);
170+
171+
/* Attach to parent node */
172+
INIT_LIST_HEAD(&pdn->child_list);
173+
INIT_LIST_HEAD(&pdn->list);
174+
parent = of_get_parent(dn);
175+
pdn->parent = parent ? PCI_DN(parent) : NULL;
176+
if (pdn->parent)
177+
list_add_tail(&pdn->list, &pdn->parent->child_list);
178+
73179
return NULL;
74180
}
75181

@@ -147,8 +253,11 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
147253
/* PHB nodes themselves must not match */
148254
update_dn_pci_info(dn, phb);
149255
pdn = dn->data;
150-
if (pdn)
256+
if (pdn) {
151257
pdn->devfn = pdn->busno = -1;
258+
pdn->phb = phb;
259+
phb->pci_data = pdn;
260+
}
152261

153262
/* Update dn->phb ptrs for new phb and children devices */
154263
traverse_pci_devices(dn, update_dn_pci_info, phb);
@@ -171,3 +280,16 @@ void __init pci_devs_phb_init(void)
171280
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
172281
pci_devs_phb_init_dynamic(phb);
173282
}
283+
284+
static void pci_dev_pdn_setup(struct pci_dev *pdev)
285+
{
286+
struct pci_dn *pdn;
287+
288+
if (pdev->dev.archdata.pci_data)
289+
return;
290+
291+
/* Setup the fast path */
292+
pdn = pci_get_pdn(pdev);
293+
pdev->dev.archdata.pci_data = pdn;
294+
}
295+
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pci_dev_pdn_setup);

0 commit comments

Comments
 (0)