diff options
Diffstat (limited to 'arch/ppc64/kernel/pSeries_iommu.c')
| -rw-r--r-- | arch/ppc64/kernel/pSeries_iommu.c | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index 9d5e1e7fc389..f0fd7fbd6531 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c | |||
| @@ -295,7 +295,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
| 295 | struct iommu_table *tbl, | 295 | struct iommu_table *tbl, |
| 296 | unsigned int *dma_window) | 296 | unsigned int *dma_window) |
| 297 | { | 297 | { |
| 298 | tbl->it_busno = dn->bussubno; | 298 | tbl->it_busno = PCI_DN(dn)->bussubno; |
| 299 | 299 | ||
| 300 | /* TODO: Parse field size properties properly. */ | 300 | /* TODO: Parse field size properties properly. */ |
| 301 | tbl->it_size = (((unsigned long)dma_window[4] << 32) | | 301 | tbl->it_size = (((unsigned long)dma_window[4] << 32) | |
| @@ -311,6 +311,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
| 311 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 311 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) |
| 312 | { | 312 | { |
| 313 | struct device_node *dn, *pdn; | 313 | struct device_node *dn, *pdn; |
| 314 | struct pci_dn *pci; | ||
| 314 | struct iommu_table *tbl; | 315 | struct iommu_table *tbl; |
| 315 | 316 | ||
| 316 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | 317 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); |
| @@ -325,6 +326,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
| 325 | */ | 326 | */ |
| 326 | 327 | ||
| 327 | dn = pci_bus_to_OF_node(bus); | 328 | dn = pci_bus_to_OF_node(bus); |
| 329 | pci = dn->data; | ||
| 328 | 330 | ||
| 329 | if (!bus->self) { | 331 | if (!bus->self) { |
| 330 | /* Root bus */ | 332 | /* Root bus */ |
| @@ -341,18 +343,18 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
| 341 | * alltogether. This leaves 768MB for the window. | 343 | * alltogether. This leaves 768MB for the window. |
| 342 | */ | 344 | */ |
| 343 | DBG("PHB has io-hole, reserving 256MB\n"); | 345 | DBG("PHB has io-hole, reserving 256MB\n"); |
| 344 | dn->phb->dma_window_size = 3 << 28; | 346 | pci->phb->dma_window_size = 3 << 28; |
| 345 | dn->phb->dma_window_base_cur = 1 << 28; | 347 | pci->phb->dma_window_base_cur = 1 << 28; |
| 346 | } else { | 348 | } else { |
| 347 | /* 1GB window by default */ | 349 | /* 1GB window by default */ |
| 348 | dn->phb->dma_window_size = 1 << 30; | 350 | pci->phb->dma_window_size = 1 << 30; |
| 349 | dn->phb->dma_window_base_cur = 0; | 351 | pci->phb->dma_window_base_cur = 0; |
| 350 | } | 352 | } |
| 351 | 353 | ||
| 352 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 354 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); |
| 353 | 355 | ||
| 354 | iommu_table_setparms(dn->phb, dn, tbl); | 356 | iommu_table_setparms(pci->phb, dn, tbl); |
| 355 | dn->iommu_table = iommu_init_table(tbl); | 357 | pci->iommu_table = iommu_init_table(tbl); |
| 356 | } else { | 358 | } else { |
| 357 | /* Do a 128MB table at root. This is used for the IDE | 359 | /* Do a 128MB table at root. This is used for the IDE |
| 358 | * controller on some SMP-mode POWER4 machines. It | 360 | * controller on some SMP-mode POWER4 machines. It |
| @@ -363,16 +365,16 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
| 363 | * Allocate at offset 128MB to avoid having to deal | 365 | * Allocate at offset 128MB to avoid having to deal |
| 364 | * with ISA holes; 128MB table for IDE is plenty. | 366 | * with ISA holes; 128MB table for IDE is plenty. |
| 365 | */ | 367 | */ |
| 366 | dn->phb->dma_window_size = 1 << 27; | 368 | pci->phb->dma_window_size = 1 << 27; |
| 367 | dn->phb->dma_window_base_cur = 1 << 27; | 369 | pci->phb->dma_window_base_cur = 1 << 27; |
| 368 | 370 | ||
| 369 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 371 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); |
| 370 | 372 | ||
| 371 | iommu_table_setparms(dn->phb, dn, tbl); | 373 | iommu_table_setparms(pci->phb, dn, tbl); |
| 372 | dn->iommu_table = iommu_init_table(tbl); | 374 | pci->iommu_table = iommu_init_table(tbl); |
| 373 | 375 | ||
| 374 | /* All child buses have 256MB tables */ | 376 | /* All child buses have 256MB tables */ |
| 375 | dn->phb->dma_window_size = 1 << 28; | 377 | pci->phb->dma_window_size = 1 << 28; |
| 376 | } | 378 | } |
| 377 | } else { | 379 | } else { |
| 378 | pdn = pci_bus_to_OF_node(bus->parent); | 380 | pdn = pci_bus_to_OF_node(bus->parent); |
| @@ -386,12 +388,12 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
| 386 | 388 | ||
| 387 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 389 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); |
| 388 | 390 | ||
| 389 | iommu_table_setparms(dn->phb, dn, tbl); | 391 | iommu_table_setparms(pci->phb, dn, tbl); |
| 390 | 392 | ||
| 391 | dn->iommu_table = iommu_init_table(tbl); | 393 | pci->iommu_table = iommu_init_table(tbl); |
| 392 | } else { | 394 | } else { |
| 393 | /* Lower than first child or under python, use parent table */ | 395 | /* Lower than first child or under python, use parent table */ |
| 394 | dn->iommu_table = pdn->iommu_table; | 396 | pci->iommu_table = PCI_DN(pdn)->iommu_table; |
| 395 | } | 397 | } |
| 396 | } | 398 | } |
| 397 | } | 399 | } |
| @@ -401,6 +403,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
| 401 | { | 403 | { |
| 402 | struct iommu_table *tbl; | 404 | struct iommu_table *tbl; |
| 403 | struct device_node *dn, *pdn; | 405 | struct device_node *dn, *pdn; |
| 406 | struct pci_dn *ppci; | ||
| 404 | unsigned int *dma_window = NULL; | 407 | unsigned int *dma_window = NULL; |
| 405 | 408 | ||
| 406 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | 409 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); |
| @@ -419,22 +422,24 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
| 419 | return; | 422 | return; |
| 420 | } | 423 | } |
| 421 | 424 | ||
| 422 | if (!pdn->iommu_table) { | 425 | ppci = pdn->data; |
| 426 | if (!ppci->iommu_table) { | ||
| 423 | /* Bussubno hasn't been copied yet. | 427 | /* Bussubno hasn't been copied yet. |
| 424 | * Do it now because iommu_table_setparms_lpar needs it. | 428 | * Do it now because iommu_table_setparms_lpar needs it. |
| 425 | */ | 429 | */ |
| 426 | pdn->bussubno = bus->number; | 430 | |
| 431 | ppci->bussubno = bus->number; | ||
| 427 | 432 | ||
| 428 | tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), | 433 | tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), |
| 429 | GFP_KERNEL); | 434 | GFP_KERNEL); |
| 430 | 435 | ||
| 431 | iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window); | 436 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
| 432 | 437 | ||
| 433 | pdn->iommu_table = iommu_init_table(tbl); | 438 | ppci->iommu_table = iommu_init_table(tbl); |
| 434 | } | 439 | } |
| 435 | 440 | ||
| 436 | if (pdn != dn) | 441 | if (pdn != dn) |
| 437 | dn->iommu_table = pdn->iommu_table; | 442 | PCI_DN(dn)->iommu_table = ppci->iommu_table; |
| 438 | } | 443 | } |
| 439 | 444 | ||
| 440 | 445 | ||
| @@ -449,11 +454,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) | |||
| 449 | */ | 454 | */ |
| 450 | mydn = dn = pci_device_to_OF_node(dev); | 455 | mydn = dn = pci_device_to_OF_node(dev); |
| 451 | 456 | ||
| 452 | while (dn && dn->iommu_table == NULL) | 457 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) |
| 453 | dn = dn->parent; | 458 | dn = dn->parent; |
| 454 | 459 | ||
| 455 | if (dn) { | 460 | if (dn && dn->data) { |
| 456 | mydn->iommu_table = dn->iommu_table; | 461 | PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; |
| 457 | } else { | 462 | } else { |
| 458 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name); | 463 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name); |
| 459 | } | 464 | } |
| @@ -463,10 +468,11 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti | |||
| 463 | { | 468 | { |
| 464 | int err = NOTIFY_OK; | 469 | int err = NOTIFY_OK; |
| 465 | struct device_node *np = node; | 470 | struct device_node *np = node; |
| 471 | struct pci_dn *pci = np->data; | ||
| 466 | 472 | ||
| 467 | switch (action) { | 473 | switch (action) { |
| 468 | case PSERIES_RECONFIG_REMOVE: | 474 | case PSERIES_RECONFIG_REMOVE: |
| 469 | if (np->iommu_table && | 475 | if (pci->iommu_table && |
| 470 | get_property(np, "ibm,dma-window", NULL)) | 476 | get_property(np, "ibm,dma-window", NULL)) |
| 471 | iommu_free_table(np); | 477 | iommu_free_table(np); |
| 472 | break; | 478 | break; |
| @@ -486,6 +492,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 486 | struct device_node *pdn, *dn; | 492 | struct device_node *pdn, *dn; |
| 487 | struct iommu_table *tbl; | 493 | struct iommu_table *tbl; |
| 488 | int *dma_window = NULL; | 494 | int *dma_window = NULL; |
| 495 | struct pci_dn *pci; | ||
| 489 | 496 | ||
| 490 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); | 497 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); |
| 491 | 498 | ||
| @@ -497,8 +504,10 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 497 | */ | 504 | */ |
| 498 | dn = pci_device_to_OF_node(dev); | 505 | dn = pci_device_to_OF_node(dev); |
| 499 | 506 | ||
| 500 | for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) { | 507 | for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table; |
| 501 | dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); | 508 | pdn = pdn->parent) { |
| 509 | dma_window = (unsigned int *) | ||
| 510 | get_property(pdn, "ibm,dma-window", NULL); | ||
| 502 | if (dma_window) | 511 | if (dma_window) |
| 503 | break; | 512 | break; |
| 504 | } | 513 | } |
| @@ -515,20 +524,21 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 515 | DBG("Found DMA window, allocating table\n"); | 524 | DBG("Found DMA window, allocating table\n"); |
| 516 | } | 525 | } |
| 517 | 526 | ||
| 518 | if (!pdn->iommu_table) { | 527 | pci = pdn->data; |
| 528 | if (!pci->iommu_table) { | ||
| 519 | /* iommu_table_setparms_lpar needs bussubno. */ | 529 | /* iommu_table_setparms_lpar needs bussubno. */ |
| 520 | pdn->bussubno = pdn->phb->bus->number; | 530 | pci->bussubno = pci->phb->bus->number; |
| 521 | 531 | ||
| 522 | tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), | 532 | tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), |
| 523 | GFP_KERNEL); | 533 | GFP_KERNEL); |
| 524 | 534 | ||
| 525 | iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window); | 535 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
| 526 | 536 | ||
| 527 | pdn->iommu_table = iommu_init_table(tbl); | 537 | pci->iommu_table = iommu_init_table(tbl); |
| 528 | } | 538 | } |
| 529 | 539 | ||
| 530 | if (pdn != dn) | 540 | if (pdn != dn) |
| 531 | dn->iommu_table = pdn->iommu_table; | 541 | PCI_DN(dn)->iommu_table = pci->iommu_table; |
| 532 | } | 542 | } |
| 533 | 543 | ||
| 534 | static void iommu_bus_setup_null(struct pci_bus *b) { } | 544 | static void iommu_bus_setup_null(struct pci_bus *b) { } |
