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) { } |