aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2015-03-25 04:23:52 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2015-03-30 22:02:37 -0400
commita8b2f8288a3fdef8d93efef2b1ead7563004275e (patch)
tree40f3d68896c56cb4e67b48d006f367eb28cf1b34 /arch/powerpc
parentd74b9027a4dafa44d3a3c2a44ce135e50a13ec10 (diff)
powerpc/pci: Create pci_dn for VFs
pci_dn is the extension of PCI device node and is created from device node. Unfortunately, VFs are enabled dynamically by PF's driver and they don't have corresponding device nodes and pci_dn, which is required to access VFs' config spaces. The patch creates pci_dn for VFs in pcibios_sriov_enable() on their PF, and removes pci_dn for VFs in pcibios_sriov_disable() on their PF. When VF's pci_dn is created, it's put to the child list of the pci_dn of PF's upstream bridge. The pci_dn is linked to pci_dev during early fixup time to setup the fast path. [bhelgaas: add ifdef around add_one_dev_pci_info(), use dev_printk()] Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h3
-rw-r--r--arch/powerpc/kernel/pci_dn.c116
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c16
3 files changed, 135 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 2c6dc2a3d14a..ece30f589398 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -156,6 +156,7 @@ struct iommu_table;
156 156
157struct pci_dn { 157struct pci_dn {
158 int flags; 158 int flags;
159#define PCI_DN_FLAG_IOV_VF 0x01
159 160
160 int busno; /* pci bus number */ 161 int busno; /* pci bus number */
161 int devfn; /* pci device and function number */ 162 int devfn; /* pci device and function number */
@@ -188,6 +189,8 @@ struct pci_dn {
188extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, 189extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
189 int devfn); 190 int devfn);
190extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); 191extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
192extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev);
193extern void remove_dev_pci_data(struct pci_dev *pdev);
191extern void *update_dn_pci_info(struct device_node *dn, void *data); 194extern void *update_dn_pci_info(struct device_node *dn, void *data);
192 195
193static inline int pci_device_from_OF_node(struct device_node *np, 196static inline int pci_device_from_OF_node(struct device_node *np,
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 65b98367005c..e5f1d78ef7cf 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -136,6 +136,122 @@ struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
136 return NULL; 136 return NULL;
137} 137}
138 138
139#ifdef CONFIG_PCI_IOV
140static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
141 struct pci_dev *pdev,
142 int busno, int devfn)
143{
144 struct pci_dn *pdn;
145
146 /* Except PHB, we always have the parent */
147 if (!parent)
148 return NULL;
149
150 pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
151 if (!pdn) {
152 dev_warn(&pdev->dev, "%s: Out of memory!\n", __func__);
153 return NULL;
154 }
155
156 pdn->phb = parent->phb;
157 pdn->parent = parent;
158 pdn->busno = busno;
159 pdn->devfn = devfn;
160#ifdef CONFIG_PPC_POWERNV
161 pdn->pe_number = IODA_INVALID_PE;
162#endif
163 INIT_LIST_HEAD(&pdn->child_list);
164 INIT_LIST_HEAD(&pdn->list);
165 list_add_tail(&pdn->list, &parent->child_list);
166
167 /*
168 * If we already have PCI device instance, lets
169 * bind them.
170 */
171 if (pdev)
172 pdev->dev.archdata.pci_data = pdn;
173
174 return pdn;
175}
176#endif
177
178struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
179{
180#ifdef CONFIG_PCI_IOV
181 struct pci_dn *parent, *pdn;
182 int i;
183
184 /* Only support IOV for now */
185 if (!pdev->is_physfn)
186 return pci_get_pdn(pdev);
187
188 /* Check if VFs have been populated */
189 pdn = pci_get_pdn(pdev);
190 if (!pdn || (pdn->flags & PCI_DN_FLAG_IOV_VF))
191 return NULL;
192
193 pdn->flags |= PCI_DN_FLAG_IOV_VF;
194 parent = pci_bus_to_pdn(pdev->bus);
195 if (!parent)
196 return NULL;
197
198 for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
199 pdn = add_one_dev_pci_data(parent, NULL,
200 pci_iov_virtfn_bus(pdev, i),
201 pci_iov_virtfn_devfn(pdev, i));
202 if (!pdn) {
203 dev_warn(&pdev->dev, "%s: Cannot create firmware data for VF#%d\n",
204 __func__, i);
205 return NULL;
206 }
207 }
208#endif /* CONFIG_PCI_IOV */
209
210 return pci_get_pdn(pdev);
211}
212
213void remove_dev_pci_data(struct pci_dev *pdev)
214{
215#ifdef CONFIG_PCI_IOV
216 struct pci_dn *parent;
217 struct pci_dn *pdn, *tmp;
218 int i;
219
220 /* Only support IOV PF for now */
221 if (!pdev->is_physfn)
222 return;
223
224 /* Check if VFs have been populated */
225 pdn = pci_get_pdn(pdev);
226 if (!pdn || !(pdn->flags & PCI_DN_FLAG_IOV_VF))
227 return;
228
229 pdn->flags &= ~PCI_DN_FLAG_IOV_VF;
230 parent = pci_bus_to_pdn(pdev->bus);
231 if (!parent)
232 return;
233
234 /*
235 * We might introduce flag to pci_dn in future
236 * so that we can release VF's firmware data in
237 * a batch mode.
238 */
239 for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
240 list_for_each_entry_safe(pdn, tmp,
241 &parent->child_list, list) {
242 if (pdn->busno != pci_iov_virtfn_bus(pdev, i) ||
243 pdn->devfn != pci_iov_virtfn_devfn(pdev, i))
244 continue;
245
246 if (!list_empty(&pdn->list))
247 list_del(&pdn->list);
248
249 kfree(pdn);
250 }
251 }
252#endif /* CONFIG_PCI_IOV */
253}
254
139/* 255/*
140 * Traverse_func that inits the PCI fields of the device node. 256 * Traverse_func that inits the PCI fields of the device node.
141 * NOTE: this *must* be done before read/write config to the device. 257 * NOTE: this *must* be done before read/write config to the device.
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 26fe09936935..7f58f199f2c1 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -974,6 +974,22 @@ static void pnv_pci_ioda_setup_PEs(void)
974 } 974 }
975} 975}
976 976
977#ifdef CONFIG_PCI_IOV
978int pcibios_sriov_disable(struct pci_dev *pdev)
979{
980 /* Release PCI data */
981 remove_dev_pci_data(pdev);
982 return 0;
983}
984
985int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
986{
987 /* Allocate PCI data */
988 add_dev_pci_data(pdev);
989 return 0;
990}
991#endif /* CONFIG_PCI_IOV */
992
977static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) 993static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev)
978{ 994{
979 struct pci_dn *pdn = pci_get_pdn(pdev); 995 struct pci_dn *pdn = pci_get_pdn(pdev);