Skip to content

Commit 0e759bd

Browse files
aikmpe
authored andcommitted
powerpc/powernv/npu: Move OPAL calls away from context manipulation
When introduced, the NPU context init/destroy helpers called OPAL which enabled/disabled PID (a userspace memory context ID) filtering in an NPU per a GPU; this was a requirement for P9 DD1.0. However newer chip revision added a PID wildcard support so there is no more need to call OPAL every time a new context is initialized. Also, since the PID wildcard support was added, skiboot does not clear wildcard entries in the NPU so these remain in the hardware till the system reboot. This moves LPID and wildcard programming to the PE setup code which executes once during the booting process so NPU2 context init/destroy won't need to do additional configuration. This replaces the check for FW_FEATURE_OPAL with a check for npu!=NULL as this is the way to tell if the NPU support is present and configured. This moves pnv_npu2_init() declaration as pseries should be able to use it. This keeps pnv_npu2_map_lpar() in powernv as pseries is not allowed to call that. This exports pnv_npu2_map_lpar_dev() as following patches will use it from the VFIO driver. While at it, replace redundant list_for_each_entry_safe() with a simpler list_for_each_entry(). Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent 46a1449 commit 0e759bd

File tree

4 files changed

+77
-54
lines changed

4 files changed

+77
-54
lines changed

arch/powerpc/include/asm/pci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,8 @@ extern void pcibios_scan_phb(struct pci_controller *hose);
129129

130130
extern struct pci_dev *pnv_pci_get_gpu_dev(struct pci_dev *npdev);
131131
extern struct pci_dev *pnv_pci_get_npu_dev(struct pci_dev *gpdev, int index);
132+
extern int pnv_npu2_init(struct pci_controller *hose);
133+
extern int pnv_npu2_map_lpar_dev(struct pci_dev *gpdev, unsigned int lparid,
134+
unsigned long msr);
132135

133136
#endif /* __ASM_POWERPC_PCI_H */

arch/powerpc/platforms/powernv/npu-dma.c

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ static void acquire_atsd_reg(struct npu_context *npu_context,
511511
continue;
512512

513513
npu = pci_bus_to_host(npdev->bus)->npu;
514+
if (!npu)
515+
continue;
516+
514517
mmio_atsd_reg[i].npu = npu;
515518
mmio_atsd_reg[i].reg = get_mmio_atsd_reg(npu);
516519
while (mmio_atsd_reg[i].reg < 0) {
@@ -675,7 +678,6 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
675678
u32 nvlink_index;
676679
struct device_node *nvlink_dn;
677680
struct mm_struct *mm = current->mm;
678-
struct pnv_phb *nphb;
679681
struct npu *npu;
680682
struct npu_context *npu_context;
681683
struct pci_controller *hose;
@@ -686,13 +688,14 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
686688
*/
687689
struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
688690

689-
if (!firmware_has_feature(FW_FEATURE_OPAL))
690-
return ERR_PTR(-ENODEV);
691-
692691
if (!npdev)
693692
/* No nvlink associated with this GPU device */
694693
return ERR_PTR(-ENODEV);
695694

695+
/* We only support DR/PR/HV in pnv_npu2_map_lpar_dev() */
696+
if (flags & ~(MSR_DR | MSR_PR | MSR_HV))
697+
return ERR_PTR(-EINVAL);
698+
696699
nvlink_dn = of_parse_phandle(npdev->dev.of_node, "ibm,nvlink", 0);
697700
if (WARN_ON(of_property_read_u32(nvlink_dn, "ibm,npu-link-index",
698701
&nvlink_index)))
@@ -707,20 +710,9 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
707710
}
708711

709712
hose = pci_bus_to_host(npdev->bus);
710-
nphb = hose->private_data;
711713
npu = hose->npu;
712-
713-
/*
714-
* Setup the NPU context table for a particular GPU. These need to be
715-
* per-GPU as we need the tables to filter ATSDs when there are no
716-
* active contexts on a particular GPU. It is safe for these to be
717-
* called concurrently with destroy as the OPAL call takes appropriate
718-
* locks and refcounts on init/destroy.
719-
*/
720-
rc = opal_npu_init_context(nphb->opal_id, mm->context.id, flags,
721-
PCI_DEVID(gpdev->bus->number, gpdev->devfn));
722-
if (rc < 0)
723-
return ERR_PTR(-ENOSPC);
714+
if (!npu)
715+
return ERR_PTR(-ENODEV);
724716

725717
/*
726718
* We store the npu pci device so we can more easily get at the
@@ -732,9 +724,6 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
732724
if (npu_context->release_cb != cb ||
733725
npu_context->priv != priv) {
734726
spin_unlock(&npu_context_lock);
735-
opal_npu_destroy_context(nphb->opal_id, mm->context.id,
736-
PCI_DEVID(gpdev->bus->number,
737-
gpdev->devfn));
738727
return ERR_PTR(-EINVAL);
739728
}
740729

@@ -760,9 +749,6 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
760749

761750
if (rc) {
762751
kfree(npu_context);
763-
opal_npu_destroy_context(nphb->opal_id, mm->context.id,
764-
PCI_DEVID(gpdev->bus->number,
765-
gpdev->devfn));
766752
return ERR_PTR(rc);
767753
}
768754

@@ -815,7 +801,6 @@ void pnv_npu2_destroy_context(struct npu_context *npu_context,
815801
struct pci_dev *gpdev)
816802
{
817803
int removed;
818-
struct pnv_phb *nphb;
819804
struct npu *npu;
820805
struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
821806
struct device_node *nvlink_dn;
@@ -825,19 +810,15 @@ void pnv_npu2_destroy_context(struct npu_context *npu_context,
825810
if (WARN_ON(!npdev))
826811
return;
827812

828-
if (!firmware_has_feature(FW_FEATURE_OPAL))
829-
return;
830-
831813
hose = pci_bus_to_host(npdev->bus);
832-
nphb = hose->private_data;
833814
npu = hose->npu;
815+
if (!npu)
816+
return;
834817
nvlink_dn = of_parse_phandle(npdev->dev.of_node, "ibm,nvlink", 0);
835818
if (WARN_ON(of_property_read_u32(nvlink_dn, "ibm,npu-link-index",
836819
&nvlink_index)))
837820
return;
838821
WRITE_ONCE(npu_context->npdev[npu->index][nvlink_index], NULL);
839-
opal_npu_destroy_context(nphb->opal_id, npu_context->mm->context.id,
840-
PCI_DEVID(gpdev->bus->number, gpdev->devfn));
841822
spin_lock(&npu_context_lock);
842823
removed = kref_put(&npu_context->kref, pnv_npu2_release_context);
843824
spin_unlock(&npu_context_lock);
@@ -869,9 +850,6 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea,
869850
/* mmap_sem should be held so the struct_mm must be present */
870851
struct mm_struct *mm = context->mm;
871852

872-
if (!firmware_has_feature(FW_FEATURE_OPAL))
873-
return -ENODEV;
874-
875853
WARN_ON(!rwsem_is_locked(&mm->mmap_sem));
876854

877855
for (i = 0; i < count; i++) {
@@ -900,15 +878,11 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea,
900878
}
901879
EXPORT_SYMBOL(pnv_npu2_handle_fault);
902880

903-
int pnv_npu2_init(struct pnv_phb *phb)
881+
int pnv_npu2_init(struct pci_controller *hose)
904882
{
905883
unsigned int i;
906884
u64 mmio_atsd;
907-
struct device_node *dn;
908-
struct pci_dev *gpdev;
909885
static int npu_index;
910-
uint64_t rc = 0;
911-
struct pci_controller *hose = phb->hose;
912886
struct npu *npu;
913887
int ret;
914888

@@ -917,18 +891,6 @@ int pnv_npu2_init(struct pnv_phb *phb)
917891
return -ENOMEM;
918892

919893
npu->nmmu_flush = of_property_read_bool(hose->dn, "ibm,nmmu-flush");
920-
for_each_child_of_node(phb->hose->dn, dn) {
921-
gpdev = pnv_pci_get_gpu_dev(get_pci_dev(dn));
922-
if (gpdev) {
923-
rc = opal_npu_map_lpar(phb->opal_id,
924-
PCI_DEVID(gpdev->bus->number, gpdev->devfn),
925-
0, 0);
926-
if (rc)
927-
dev_err(&gpdev->dev,
928-
"Error %lld mapping device to LPAR\n",
929-
rc);
930-
}
931-
}
932894

933895
for (i = 0; !of_property_read_u64_index(hose->dn, "ibm,mmio-atsd",
934896
i, &mmio_atsd); i++)
@@ -956,3 +918,52 @@ int pnv_npu2_init(struct pnv_phb *phb)
956918

957919
return ret;
958920
}
921+
922+
int pnv_npu2_map_lpar_dev(struct pci_dev *gpdev, unsigned int lparid,
923+
unsigned long msr)
924+
{
925+
int ret;
926+
struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
927+
struct pci_controller *hose;
928+
struct pnv_phb *nphb;
929+
930+
if (!npdev)
931+
return -ENODEV;
932+
933+
hose = pci_bus_to_host(npdev->bus);
934+
nphb = hose->private_data;
935+
936+
dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=%u\n",
937+
nphb->opal_id, lparid);
938+
/*
939+
* Currently we only support radix and non-zero LPCR only makes sense
940+
* for hash tables so skiboot expects the LPCR parameter to be a zero.
941+
*/
942+
ret = opal_npu_map_lpar(nphb->opal_id,
943+
PCI_DEVID(gpdev->bus->number, gpdev->devfn), lparid,
944+
0 /* LPCR bits */);
945+
if (ret) {
946+
dev_err(&gpdev->dev, "Error %d mapping device to LPAR\n", ret);
947+
return ret;
948+
}
949+
950+
dev_dbg(&gpdev->dev, "init context opalid=%llu msr=%lx\n",
951+
nphb->opal_id, msr);
952+
ret = opal_npu_init_context(nphb->opal_id, 0/*__unused*/, msr,
953+
PCI_DEVID(gpdev->bus->number, gpdev->devfn));
954+
if (ret < 0)
955+
dev_err(&gpdev->dev, "Failed to init context: %d\n", ret);
956+
else
957+
ret = 0;
958+
959+
return 0;
960+
}
961+
EXPORT_SYMBOL_GPL(pnv_npu2_map_lpar_dev);
962+
963+
void pnv_npu2_map_lpar(struct pnv_ioda_pe *gpe, unsigned long msr)
964+
{
965+
struct pci_dev *gpdev;
966+
967+
list_for_each_entry(gpdev, &gpe->pbus->devices, bus_list)
968+
pnv_npu2_map_lpar_dev(gpdev, 0, msr);
969+
}

arch/powerpc/platforms/powernv/pci-ioda.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,26 +1266,35 @@ static void pnv_ioda_setup_npu_PEs(struct pci_bus *bus)
12661266

12671267
static void pnv_pci_ioda_setup_PEs(void)
12681268
{
1269-
struct pci_controller *hose, *tmp;
1269+
struct pci_controller *hose;
12701270
struct pnv_phb *phb;
12711271
struct pci_bus *bus;
12721272
struct pci_dev *pdev;
1273+
struct pnv_ioda_pe *pe;
12731274

1274-
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
1275+
list_for_each_entry(hose, &hose_list, list_node) {
12751276
phb = hose->private_data;
12761277
if (phb->type == PNV_PHB_NPU_NVLINK) {
12771278
/* PE#0 is needed for error reporting */
12781279
pnv_ioda_reserve_pe(phb, 0);
12791280
pnv_ioda_setup_npu_PEs(hose->bus);
12801281
if (phb->model == PNV_PHB_MODEL_NPU2)
1281-
WARN_ON_ONCE(pnv_npu2_init(phb));
1282+
WARN_ON_ONCE(pnv_npu2_init(hose));
12821283
}
12831284
if (phb->type == PNV_PHB_NPU_OCAPI) {
12841285
bus = hose->bus;
12851286
list_for_each_entry(pdev, &bus->devices, bus_list)
12861287
pnv_ioda_setup_dev_PE(pdev);
12871288
}
12881289
}
1290+
list_for_each_entry(hose, &hose_list, list_node) {
1291+
phb = hose->private_data;
1292+
if (phb->type != PNV_PHB_IODA2)
1293+
continue;
1294+
1295+
list_for_each_entry(pe, &phb->ioda.pe_list, list)
1296+
pnv_npu2_map_lpar(pe, MSR_DR | MSR_PR | MSR_HV);
1297+
}
12891298
}
12901299

12911300
#ifdef CONFIG_PCI_IOV

arch/powerpc/platforms/powernv/pci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np);
188188
extern void pnv_pci_init_ioda2_phb(struct device_node *np);
189189
extern void pnv_pci_init_npu_phb(struct device_node *np);
190190
extern void pnv_pci_init_npu2_opencapi_phb(struct device_node *np);
191+
extern void pnv_npu2_map_lpar(struct pnv_ioda_pe *gpe, unsigned long msr);
191192
extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
192193
extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
193194

@@ -218,7 +219,6 @@ extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
218219
extern long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num);
219220
extern void pnv_npu_take_ownership(struct pnv_ioda_pe *npe);
220221
extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe);
221-
extern int pnv_npu2_init(struct pnv_phb *phb);
222222

223223
/* pci-ioda-tce.c */
224224
#define POWERNV_IOMMU_DEFAULT_LEVELS 1

0 commit comments

Comments
 (0)