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

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_pci_dev
  2. pnv_pci_get_gpu_dev
  3. pnv_pci_get_npu_dev
  4. get_gpu_pci_dev_and_pe
  5. pnv_npu_set_window
  6. pnv_npu_unset_window
  7. pnv_npu_take_ownership
  8. pnv_npu_release_ownership
  9. pnv_npu_peers_create_table_userspace
  10. pnv_npu_peers_set_window
  11. pnv_npu_peers_unset_window
  12. pnv_npu_peers_take_ownership
  13. pnv_npu_peers_release_ownership
  14. pnv_comp_attach_table_group
  15. pnv_try_setup_npu_table_group
  16. pnv_npu_compound_attach
  17. pnv_npu2_init
  18. pnv_npu2_map_lpar_dev
  19. pnv_npu2_map_lpar
  20. pnv_npu2_unmap_lpar_dev

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * This file implements the DMA operations for NVLink devices. The NPU
   4  * devices all point to the same iommu table as the parent PCI device.
   5  *
   6  * Copyright Alistair Popple, IBM Corporation 2015.
   7  */
   8 
   9 #include <linux/mmu_notifier.h>
  10 #include <linux/mmu_context.h>
  11 #include <linux/of.h>
  12 #include <linux/pci.h>
  13 #include <linux/memblock.h>
  14 #include <linux/sizes.h>
  15 
  16 #include <asm/debugfs.h>
  17 #include <asm/powernv.h>
  18 #include <asm/opal.h>
  19 
  20 #include "pci.h"
  21 
  22 static struct pci_dev *get_pci_dev(struct device_node *dn)
  23 {
  24         struct pci_dn *pdn = PCI_DN(dn);
  25         struct pci_dev *pdev;
  26 
  27         pdev = pci_get_domain_bus_and_slot(pci_domain_nr(pdn->phb->bus),
  28                                            pdn->busno, pdn->devfn);
  29 
  30         /*
  31          * pci_get_domain_bus_and_slot() increased the reference count of
  32          * the PCI device, but callers don't need that actually as the PE
  33          * already holds a reference to the device. Since callers aren't
  34          * aware of the reference count change, call pci_dev_put() now to
  35          * avoid leaks.
  36          */
  37         if (pdev)
  38                 pci_dev_put(pdev);
  39 
  40         return pdev;
  41 }
  42 
  43 /* Given a NPU device get the associated PCI device. */
  44 struct pci_dev *pnv_pci_get_gpu_dev(struct pci_dev *npdev)
  45 {
  46         struct device_node *dn;
  47         struct pci_dev *gpdev;
  48 
  49         if (WARN_ON(!npdev))
  50                 return NULL;
  51 
  52         if (WARN_ON(!npdev->dev.of_node))
  53                 return NULL;
  54 
  55         /* Get assoicated PCI device */
  56         dn = of_parse_phandle(npdev->dev.of_node, "ibm,gpu", 0);
  57         if (!dn)
  58                 return NULL;
  59 
  60         gpdev = get_pci_dev(dn);
  61         of_node_put(dn);
  62 
  63         return gpdev;
  64 }
  65 EXPORT_SYMBOL(pnv_pci_get_gpu_dev);
  66 
  67 /* Given the real PCI device get a linked NPU device. */
  68 struct pci_dev *pnv_pci_get_npu_dev(struct pci_dev *gpdev, int index)
  69 {
  70         struct device_node *dn;
  71         struct pci_dev *npdev;
  72 
  73         if (WARN_ON(!gpdev))
  74                 return NULL;
  75 
  76         /* Not all PCI devices have device-tree nodes */
  77         if (!gpdev->dev.of_node)
  78                 return NULL;
  79 
  80         /* Get assoicated PCI device */
  81         dn = of_parse_phandle(gpdev->dev.of_node, "ibm,npu", index);
  82         if (!dn)
  83                 return NULL;
  84 
  85         npdev = get_pci_dev(dn);
  86         of_node_put(dn);
  87 
  88         return npdev;
  89 }
  90 EXPORT_SYMBOL(pnv_pci_get_npu_dev);
  91 
  92 #ifdef CONFIG_IOMMU_API
  93 /*
  94  * Returns the PE assoicated with the PCI device of the given
  95  * NPU. Returns the linked pci device if pci_dev != NULL.
  96  */
  97 static struct pnv_ioda_pe *get_gpu_pci_dev_and_pe(struct pnv_ioda_pe *npe,
  98                                                   struct pci_dev **gpdev)
  99 {
 100         struct pnv_phb *phb;
 101         struct pci_controller *hose;
 102         struct pci_dev *pdev;
 103         struct pnv_ioda_pe *pe;
 104         struct pci_dn *pdn;
 105 
 106         pdev = pnv_pci_get_gpu_dev(npe->pdev);
 107         if (!pdev)
 108                 return NULL;
 109 
 110         pdn = pci_get_pdn(pdev);
 111         if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
 112                 return NULL;
 113 
 114         hose = pci_bus_to_host(pdev->bus);
 115         phb = hose->private_data;
 116         pe = &phb->ioda.pe_array[pdn->pe_number];
 117 
 118         if (gpdev)
 119                 *gpdev = pdev;
 120 
 121         return pe;
 122 }
 123 
 124 static long pnv_npu_unset_window(struct iommu_table_group *table_group,
 125                 int num);
 126 
 127 static long pnv_npu_set_window(struct iommu_table_group *table_group, int num,
 128                 struct iommu_table *tbl)
 129 {
 130         struct pnv_ioda_pe *npe = container_of(table_group, struct pnv_ioda_pe,
 131                         table_group);
 132         struct pnv_phb *phb = npe->phb;
 133         int64_t rc;
 134         const unsigned long size = tbl->it_indirect_levels ?
 135                 tbl->it_level_size : tbl->it_size;
 136         const __u64 start_addr = tbl->it_offset << tbl->it_page_shift;
 137         const __u64 win_size = tbl->it_size << tbl->it_page_shift;
 138         int num2 = (num == 0) ? 1 : 0;
 139 
 140         /* NPU has just one TVE so if there is another table, remove it first */
 141         if (npe->table_group.tables[num2])
 142                 pnv_npu_unset_window(&npe->table_group, num2);
 143 
 144         pe_info(npe, "Setting up window %llx..%llx pg=%lx\n",
 145                         start_addr, start_addr + win_size - 1,
 146                         IOMMU_PAGE_SIZE(tbl));
 147 
 148         rc = opal_pci_map_pe_dma_window(phb->opal_id,
 149                         npe->pe_number,
 150                         npe->pe_number,
 151                         tbl->it_indirect_levels + 1,
 152                         __pa(tbl->it_base),
 153                         size << 3,
 154                         IOMMU_PAGE_SIZE(tbl));
 155         if (rc) {
 156                 pe_err(npe, "Failed to configure TCE table, err %lld\n", rc);
 157                 return rc;
 158         }
 159         pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 160 
 161         /* Add the table to the list so its TCE cache will get invalidated */
 162         pnv_pci_link_table_and_group(phb->hose->node, num,
 163                         tbl, &npe->table_group);
 164 
 165         return 0;
 166 }
 167 
 168 static long pnv_npu_unset_window(struct iommu_table_group *table_group, int num)
 169 {
 170         struct pnv_ioda_pe *npe = container_of(table_group, struct pnv_ioda_pe,
 171                         table_group);
 172         struct pnv_phb *phb = npe->phb;
 173         int64_t rc;
 174 
 175         if (!npe->table_group.tables[num])
 176                 return 0;
 177 
 178         pe_info(npe, "Removing DMA window\n");
 179 
 180         rc = opal_pci_map_pe_dma_window(phb->opal_id, npe->pe_number,
 181                         npe->pe_number,
 182                         0/* levels */, 0/* table address */,
 183                         0/* table size */, 0/* page size */);
 184         if (rc) {
 185                 pe_err(npe, "Unmapping failed, ret = %lld\n", rc);
 186                 return rc;
 187         }
 188         pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 189 
 190         pnv_pci_unlink_table_and_group(npe->table_group.tables[num],
 191                         &npe->table_group);
 192 
 193         return 0;
 194 }
 195 
 196 /* Switch ownership from platform code to external user (e.g. VFIO) */
 197 static void pnv_npu_take_ownership(struct iommu_table_group *table_group)
 198 {
 199         struct pnv_ioda_pe *npe = container_of(table_group, struct pnv_ioda_pe,
 200                         table_group);
 201         struct pnv_phb *phb = npe->phb;
 202         int64_t rc;
 203         struct pci_dev *gpdev = NULL;
 204 
 205         /*
 206          * Note: NPU has just a single TVE in the hardware which means that
 207          * while used by the kernel, it can have either 32bit window or
 208          * DMA bypass but never both. So we deconfigure 32bit window only
 209          * if it was enabled at the moment of ownership change.
 210          */
 211         if (npe->table_group.tables[0]) {
 212                 pnv_npu_unset_window(&npe->table_group, 0);
 213                 return;
 214         }
 215 
 216         /* Disable bypass */
 217         rc = opal_pci_map_pe_dma_window_real(phb->opal_id,
 218                         npe->pe_number, npe->pe_number,
 219                         0 /* bypass base */, 0);
 220         if (rc) {
 221                 pe_err(npe, "Failed to disable bypass, err %lld\n", rc);
 222                 return;
 223         }
 224         pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false);
 225 
 226         get_gpu_pci_dev_and_pe(npe, &gpdev);
 227         if (gpdev)
 228                 pnv_npu2_unmap_lpar_dev(gpdev);
 229 }
 230 
 231 static void pnv_npu_release_ownership(struct iommu_table_group *table_group)
 232 {
 233         struct pnv_ioda_pe *npe = container_of(table_group, struct pnv_ioda_pe,
 234                         table_group);
 235         struct pci_dev *gpdev = NULL;
 236 
 237         get_gpu_pci_dev_and_pe(npe, &gpdev);
 238         if (gpdev)
 239                 pnv_npu2_map_lpar_dev(gpdev, 0, MSR_DR | MSR_PR | MSR_HV);
 240 }
 241 
 242 static struct iommu_table_group_ops pnv_pci_npu_ops = {
 243         .set_window = pnv_npu_set_window,
 244         .unset_window = pnv_npu_unset_window,
 245         .take_ownership = pnv_npu_take_ownership,
 246         .release_ownership = pnv_npu_release_ownership,
 247 };
 248 #endif /* !CONFIG_IOMMU_API */
 249 
 250 /*
 251  * NPU2 ATS
 252  */
 253 /* Maximum possible number of ATSD MMIO registers per NPU */
 254 #define NV_NMMU_ATSD_REGS 8
 255 #define NV_NPU_MAX_PE_NUM       16
 256 
 257 /*
 258  * A compound NPU IOMMU group which might consist of 1 GPU + 2xNPUs (POWER8) or
 259  * up to 3 x (GPU + 2xNPUs) (POWER9).
 260  */
 261 struct npu_comp {
 262         struct iommu_table_group table_group;
 263         int pe_num;
 264         struct pnv_ioda_pe *pe[NV_NPU_MAX_PE_NUM];
 265 };
 266 
 267 /* An NPU descriptor, valid for POWER9 only */
 268 struct npu {
 269         int index;
 270         struct npu_comp npucomp;
 271 };
 272 
 273 #ifdef CONFIG_IOMMU_API
 274 static long pnv_npu_peers_create_table_userspace(
 275                 struct iommu_table_group *table_group,
 276                 int num, __u32 page_shift, __u64 window_size, __u32 levels,
 277                 struct iommu_table **ptbl)
 278 {
 279         struct npu_comp *npucomp = container_of(table_group, struct npu_comp,
 280                         table_group);
 281 
 282         if (!npucomp->pe_num || !npucomp->pe[0] ||
 283                         !npucomp->pe[0]->table_group.ops ||
 284                         !npucomp->pe[0]->table_group.ops->create_table)
 285                 return -EFAULT;
 286 
 287         return npucomp->pe[0]->table_group.ops->create_table(
 288                         &npucomp->pe[0]->table_group, num, page_shift,
 289                         window_size, levels, ptbl);
 290 }
 291 
 292 static long pnv_npu_peers_set_window(struct iommu_table_group *table_group,
 293                 int num, struct iommu_table *tbl)
 294 {
 295         int i, j;
 296         long ret = 0;
 297         struct npu_comp *npucomp = container_of(table_group, struct npu_comp,
 298                         table_group);
 299 
 300         for (i = 0; i < npucomp->pe_num; ++i) {
 301                 struct pnv_ioda_pe *pe = npucomp->pe[i];
 302 
 303                 if (!pe->table_group.ops->set_window)
 304                         continue;
 305 
 306                 ret = pe->table_group.ops->set_window(&pe->table_group,
 307                                 num, tbl);
 308                 if (ret)
 309                         break;
 310         }
 311 
 312         if (ret) {
 313                 for (j = 0; j < i; ++j) {
 314                         struct pnv_ioda_pe *pe = npucomp->pe[j];
 315 
 316                         if (!pe->table_group.ops->unset_window)
 317                                 continue;
 318 
 319                         ret = pe->table_group.ops->unset_window(
 320                                         &pe->table_group, num);
 321                         if (ret)
 322                                 break;
 323                 }
 324         } else {
 325                 table_group->tables[num] = iommu_tce_table_get(tbl);
 326         }
 327 
 328         return ret;
 329 }
 330 
 331 static long pnv_npu_peers_unset_window(struct iommu_table_group *table_group,
 332                 int num)
 333 {
 334         int i, j;
 335         long ret = 0;
 336         struct npu_comp *npucomp = container_of(table_group, struct npu_comp,
 337                         table_group);
 338 
 339         for (i = 0; i < npucomp->pe_num; ++i) {
 340                 struct pnv_ioda_pe *pe = npucomp->pe[i];
 341 
 342                 WARN_ON(npucomp->table_group.tables[num] !=
 343                                 table_group->tables[num]);
 344                 if (!npucomp->table_group.tables[num])
 345                         continue;
 346 
 347                 if (!pe->table_group.ops->unset_window)
 348                         continue;
 349 
 350                 ret = pe->table_group.ops->unset_window(&pe->table_group, num);
 351                 if (ret)
 352                         break;
 353         }
 354 
 355         if (ret) {
 356                 for (j = 0; j < i; ++j) {
 357                         struct pnv_ioda_pe *pe = npucomp->pe[j];
 358 
 359                         if (!npucomp->table_group.tables[num])
 360                                 continue;
 361 
 362                         if (!pe->table_group.ops->set_window)
 363                                 continue;
 364 
 365                         ret = pe->table_group.ops->set_window(&pe->table_group,
 366                                         num, table_group->tables[num]);
 367                         if (ret)
 368                                 break;
 369                 }
 370         } else if (table_group->tables[num]) {
 371                 iommu_tce_table_put(table_group->tables[num]);
 372                 table_group->tables[num] = NULL;
 373         }
 374 
 375         return ret;
 376 }
 377 
 378 static void pnv_npu_peers_take_ownership(struct iommu_table_group *table_group)
 379 {
 380         int i;
 381         struct npu_comp *npucomp = container_of(table_group, struct npu_comp,
 382                         table_group);
 383 
 384         for (i = 0; i < npucomp->pe_num; ++i) {
 385                 struct pnv_ioda_pe *pe = npucomp->pe[i];
 386 
 387                 if (!pe->table_group.ops->take_ownership)
 388                         continue;
 389                 pe->table_group.ops->take_ownership(&pe->table_group);
 390         }
 391 }
 392 
 393 static void pnv_npu_peers_release_ownership(
 394                 struct iommu_table_group *table_group)
 395 {
 396         int i;
 397         struct npu_comp *npucomp = container_of(table_group, struct npu_comp,
 398                         table_group);
 399 
 400         for (i = 0; i < npucomp->pe_num; ++i) {
 401                 struct pnv_ioda_pe *pe = npucomp->pe[i];
 402 
 403                 if (!pe->table_group.ops->release_ownership)
 404                         continue;
 405                 pe->table_group.ops->release_ownership(&pe->table_group);
 406         }
 407 }
 408 
 409 static struct iommu_table_group_ops pnv_npu_peers_ops = {
 410         .get_table_size = pnv_pci_ioda2_get_table_size,
 411         .create_table = pnv_npu_peers_create_table_userspace,
 412         .set_window = pnv_npu_peers_set_window,
 413         .unset_window = pnv_npu_peers_unset_window,
 414         .take_ownership = pnv_npu_peers_take_ownership,
 415         .release_ownership = pnv_npu_peers_release_ownership,
 416 };
 417 
 418 static void pnv_comp_attach_table_group(struct npu_comp *npucomp,
 419                 struct pnv_ioda_pe *pe)
 420 {
 421         if (WARN_ON(npucomp->pe_num == NV_NPU_MAX_PE_NUM))
 422                 return;
 423 
 424         npucomp->pe[npucomp->pe_num] = pe;
 425         ++npucomp->pe_num;
 426 }
 427 
 428 struct iommu_table_group *pnv_try_setup_npu_table_group(struct pnv_ioda_pe *pe)
 429 {
 430         struct iommu_table_group *table_group;
 431         struct npu_comp *npucomp;
 432         struct pci_dev *gpdev = NULL;
 433         struct pci_controller *hose;
 434         struct pci_dev *npdev = NULL;
 435 
 436         list_for_each_entry(gpdev, &pe->pbus->devices, bus_list) {
 437                 npdev = pnv_pci_get_npu_dev(gpdev, 0);
 438                 if (npdev)
 439                         break;
 440         }
 441 
 442         if (!npdev)
 443                 /* It is not an NPU attached device, skip */
 444                 return NULL;
 445 
 446         hose = pci_bus_to_host(npdev->bus);
 447 
 448         if (hose->npu) {
 449                 table_group = &hose->npu->npucomp.table_group;
 450 
 451                 if (!table_group->group) {
 452                         table_group->ops = &pnv_npu_peers_ops;
 453                         iommu_register_group(table_group,
 454                                         hose->global_number,
 455                                         pe->pe_number);
 456                 }
 457         } else {
 458                 /* Create a group for 1 GPU and attached NPUs for POWER8 */
 459                 pe->npucomp = kzalloc(sizeof(*pe->npucomp), GFP_KERNEL);
 460                 table_group = &pe->npucomp->table_group;
 461                 table_group->ops = &pnv_npu_peers_ops;
 462                 iommu_register_group(table_group, hose->global_number,
 463                                 pe->pe_number);
 464         }
 465 
 466         /* Steal capabilities from a GPU PE */
 467         table_group->max_dynamic_windows_supported =
 468                 pe->table_group.max_dynamic_windows_supported;
 469         table_group->tce32_start = pe->table_group.tce32_start;
 470         table_group->tce32_size = pe->table_group.tce32_size;
 471         table_group->max_levels = pe->table_group.max_levels;
 472         if (!table_group->pgsizes)
 473                 table_group->pgsizes = pe->table_group.pgsizes;
 474 
 475         npucomp = container_of(table_group, struct npu_comp, table_group);
 476         pnv_comp_attach_table_group(npucomp, pe);
 477 
 478         return table_group;
 479 }
 480 
 481 struct iommu_table_group *pnv_npu_compound_attach(struct pnv_ioda_pe *pe)
 482 {
 483         struct iommu_table_group *table_group;
 484         struct npu_comp *npucomp;
 485         struct pci_dev *gpdev = NULL;
 486         struct pci_dev *npdev;
 487         struct pnv_ioda_pe *gpe = get_gpu_pci_dev_and_pe(pe, &gpdev);
 488 
 489         WARN_ON(!(pe->flags & PNV_IODA_PE_DEV));
 490         if (!gpe)
 491                 return NULL;
 492 
 493         /*
 494          * IODA2 bridges get this set up from pci_controller_ops::setup_bridge
 495          * but NPU bridges do not have this hook defined so we do it here.
 496          * We do not setup other table group parameters as they won't be used
 497          * anyway - NVLink bridges are subordinate PEs.
 498          */
 499         pe->table_group.ops = &pnv_pci_npu_ops;
 500 
 501         table_group = iommu_group_get_iommudata(
 502                         iommu_group_get(&gpdev->dev));
 503 
 504         /*
 505          * On P9 NPU PHB and PCI PHB support different page sizes,
 506          * keep only matching. We expect here that NVLink bridge PE pgsizes is
 507          * initialized by the caller.
 508          */
 509         table_group->pgsizes &= pe->table_group.pgsizes;
 510         npucomp = container_of(table_group, struct npu_comp, table_group);
 511         pnv_comp_attach_table_group(npucomp, pe);
 512 
 513         list_for_each_entry(npdev, &pe->phb->hose->bus->devices, bus_list) {
 514                 struct pci_dev *gpdevtmp = pnv_pci_get_gpu_dev(npdev);
 515 
 516                 if (gpdevtmp != gpdev)
 517                         continue;
 518 
 519                 iommu_add_device(table_group, &npdev->dev);
 520         }
 521 
 522         return table_group;
 523 }
 524 #endif /* CONFIG_IOMMU_API */
 525 
 526 int pnv_npu2_init(struct pci_controller *hose)
 527 {
 528         static int npu_index;
 529         struct npu *npu;
 530         int ret;
 531 
 532         npu = kzalloc(sizeof(*npu), GFP_KERNEL);
 533         if (!npu)
 534                 return -ENOMEM;
 535 
 536         npu_index++;
 537         if (WARN_ON(npu_index >= NV_MAX_NPUS)) {
 538                 ret = -ENOSPC;
 539                 goto fail_exit;
 540         }
 541         npu->index = npu_index;
 542         hose->npu = npu;
 543 
 544         return 0;
 545 
 546 fail_exit:
 547         kfree(npu);
 548         return ret;
 549 }
 550 
 551 int pnv_npu2_map_lpar_dev(struct pci_dev *gpdev, unsigned int lparid,
 552                 unsigned long msr)
 553 {
 554         int ret;
 555         struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
 556         struct pci_controller *hose;
 557         struct pnv_phb *nphb;
 558 
 559         if (!npdev)
 560                 return -ENODEV;
 561 
 562         hose = pci_bus_to_host(npdev->bus);
 563         nphb = hose->private_data;
 564 
 565         dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=%u\n",
 566                         nphb->opal_id, lparid);
 567         /*
 568          * Currently we only support radix and non-zero LPCR only makes sense
 569          * for hash tables so skiboot expects the LPCR parameter to be a zero.
 570          */
 571         ret = opal_npu_map_lpar(nphb->opal_id, pci_dev_id(gpdev), lparid,
 572                                 0 /* LPCR bits */);
 573         if (ret) {
 574                 dev_err(&gpdev->dev, "Error %d mapping device to LPAR\n", ret);
 575                 return ret;
 576         }
 577 
 578         dev_dbg(&gpdev->dev, "init context opalid=%llu msr=%lx\n",
 579                         nphb->opal_id, msr);
 580         ret = opal_npu_init_context(nphb->opal_id, 0/*__unused*/, msr,
 581                                     pci_dev_id(gpdev));
 582         if (ret < 0)
 583                 dev_err(&gpdev->dev, "Failed to init context: %d\n", ret);
 584         else
 585                 ret = 0;
 586 
 587         return 0;
 588 }
 589 EXPORT_SYMBOL_GPL(pnv_npu2_map_lpar_dev);
 590 
 591 void pnv_npu2_map_lpar(struct pnv_ioda_pe *gpe, unsigned long msr)
 592 {
 593         struct pci_dev *gpdev;
 594 
 595         list_for_each_entry(gpdev, &gpe->pbus->devices, bus_list)
 596                 pnv_npu2_map_lpar_dev(gpdev, 0, msr);
 597 }
 598 
 599 int pnv_npu2_unmap_lpar_dev(struct pci_dev *gpdev)
 600 {
 601         int ret;
 602         struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
 603         struct pci_controller *hose;
 604         struct pnv_phb *nphb;
 605 
 606         if (!npdev)
 607                 return -ENODEV;
 608 
 609         hose = pci_bus_to_host(npdev->bus);
 610         nphb = hose->private_data;
 611 
 612         dev_dbg(&gpdev->dev, "destroy context opalid=%llu\n",
 613                         nphb->opal_id);
 614         ret = opal_npu_destroy_context(nphb->opal_id, 0/*__unused*/,
 615                                        pci_dev_id(gpdev));
 616         if (ret < 0) {
 617                 dev_err(&gpdev->dev, "Failed to destroy context: %d\n", ret);
 618                 return ret;
 619         }
 620 
 621         /* Set LPID to 0 anyway, just to be safe */
 622         dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=0\n", nphb->opal_id);
 623         ret = opal_npu_map_lpar(nphb->opal_id, pci_dev_id(gpdev), 0 /*LPID*/,
 624                                 0 /* LPCR bits */);
 625         if (ret)
 626                 dev_err(&gpdev->dev, "Error %d mapping device to LPAR\n", ret);
 627 
 628         return ret;
 629 }
 630 EXPORT_SYMBOL_GPL(pnv_npu2_unmap_lpar_dev);

/* [<][>][^][v][top][bottom][index][help] */