Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/powernv/npu: Do not attempt NPU2 setup on POWER8NVL NPU

We execute certain NPU2 setup code (such as mapping an LPID to a device
in NPU2) unconditionally if an Nvlink bridge is detected. However this
cannot succeed on POWER8NVL machines and errors appear in dmesg. This is
harmless as skiboot returns an error and the only place we check it is
vfio-pci but that code does not get called on P8+ either.

This adds a check if pnv_npu2_xxx helpers are called on a machine with
NPU2 which initializes pnv_phb::npu in pnv_npu2_init();
pnv_phb::npu==NULL on POWER8/NVL (Naples).

While at this, fix NULL derefencing in pnv_npu_peers_take_ownership/
pnv_npu_peers_release_ownership which occurs when GPUs on mentioned P8s
cause EEH which happens if "vfio-pci" disables devices using
the D3 power state; the vfio-pci's disable_idle_d3 module parameter
controls this and must be set on Naples. The EEH handling clears
the entire pnv_ioda_pe struct in pnv_ioda_free_pe() hence
the NULL derefencing. We cannot recover from that but at least we stop
crashing.

Tested on
- POWER9 pvr=004e1201, Ubuntu 19.04 host, Ubuntu 18.04 vm,
NVIDIA GV100 10de:1db1 driver 418.39
- POWER8 pvr=004c0100, RHEL 7.6 host, Ubuntu 16.10 vm,
NVIDIA P100 10de:15f9 driver 396.47

Fixes: 1b785611e119 ("powerpc/powernv/npu: Add release_ownership hook")
Cc: stable@vger.kernel.org # 5.0
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201122073828.15446-1-aik@ozlabs.ru

authored by

Alexey Kardashevskiy and committed by
Michael Ellerman
b1198a88 3ba150fb

+14 -2
+14 -2
arch/powerpc/platforms/powernv/npu-dma.c
··· 385 385 for (i = 0; i < npucomp->pe_num; ++i) { 386 386 struct pnv_ioda_pe *pe = npucomp->pe[i]; 387 387 388 - if (!pe->table_group.ops->take_ownership) 388 + if (!pe->table_group.ops || 389 + !pe->table_group.ops->take_ownership) 389 390 continue; 390 391 pe->table_group.ops->take_ownership(&pe->table_group); 391 392 } ··· 402 401 for (i = 0; i < npucomp->pe_num; ++i) { 403 402 struct pnv_ioda_pe *pe = npucomp->pe[i]; 404 403 405 - if (!pe->table_group.ops->release_ownership) 404 + if (!pe->table_group.ops || 405 + !pe->table_group.ops->release_ownership) 406 406 continue; 407 407 pe->table_group.ops->release_ownership(&pe->table_group); 408 408 } ··· 625 623 return -ENODEV; 626 624 627 625 hose = pci_bus_to_host(npdev->bus); 626 + if (hose->npu == NULL) { 627 + dev_info_once(&npdev->dev, "Nvlink1 does not support contexts"); 628 + return 0; 629 + } 630 + 628 631 nphb = hose->private_data; 629 632 630 633 dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=%u\n", ··· 677 670 return -ENODEV; 678 671 679 672 hose = pci_bus_to_host(npdev->bus); 673 + if (hose->npu == NULL) { 674 + dev_info_once(&npdev->dev, "Nvlink1 does not support contexts"); 675 + return 0; 676 + } 677 + 680 678 nphb = hose->private_data; 681 679 682 680 dev_dbg(&gpdev->dev, "destroy context opalid=%llu\n",