diff options
Diffstat (limited to 'arch/powerpc/platforms/powernv')
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 128 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-powernv.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-xscom.c | 21 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 84 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 230 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.h | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/powernv.h | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 9 |
8 files changed, 303 insertions, 185 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index e1e71618b70c..253fefe3d1a0 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -44,7 +44,8 @@ static int ioda_eeh_event(struct notifier_block *nb, | |||
44 | 44 | ||
45 | /* We simply send special EEH event */ | 45 | /* We simply send special EEH event */ |
46 | if ((changed_evts & OPAL_EVENT_PCI_ERROR) && | 46 | if ((changed_evts & OPAL_EVENT_PCI_ERROR) && |
47 | (events & OPAL_EVENT_PCI_ERROR)) | 47 | (events & OPAL_EVENT_PCI_ERROR) && |
48 | eeh_enabled()) | ||
48 | eeh_send_failure_event(NULL); | 49 | eeh_send_failure_event(NULL); |
49 | 50 | ||
50 | return 0; | 51 | return 0; |
@@ -113,6 +114,7 @@ DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get, | |||
113 | ioda_eeh_inbB_dbgfs_set, "0x%llx\n"); | 114 | ioda_eeh_inbB_dbgfs_set, "0x%llx\n"); |
114 | #endif /* CONFIG_DEBUG_FS */ | 115 | #endif /* CONFIG_DEBUG_FS */ |
115 | 116 | ||
117 | |||
116 | /** | 118 | /** |
117 | * ioda_eeh_post_init - Chip dependent post initialization | 119 | * ioda_eeh_post_init - Chip dependent post initialization |
118 | * @hose: PCI controller | 120 | * @hose: PCI controller |
@@ -220,6 +222,22 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | |||
220 | return ret; | 222 | return ret; |
221 | } | 223 | } |
222 | 224 | ||
225 | static void ioda_eeh_phb_diag(struct pci_controller *hose) | ||
226 | { | ||
227 | struct pnv_phb *phb = hose->private_data; | ||
228 | long rc; | ||
229 | |||
230 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | ||
231 | PNV_PCI_DIAG_BUF_SIZE); | ||
232 | if (rc != OPAL_SUCCESS) { | ||
233 | pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", | ||
234 | __func__, hose->global_number, rc); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); | ||
239 | } | ||
240 | |||
223 | /** | 241 | /** |
224 | * ioda_eeh_get_state - Retrieve the state of PE | 242 | * ioda_eeh_get_state - Retrieve the state of PE |
225 | * @pe: EEH PE | 243 | * @pe: EEH PE |
@@ -271,6 +289,9 @@ static int ioda_eeh_get_state(struct eeh_pe *pe) | |||
271 | result |= EEH_STATE_DMA_ACTIVE; | 289 | result |= EEH_STATE_DMA_ACTIVE; |
272 | result |= EEH_STATE_MMIO_ENABLED; | 290 | result |= EEH_STATE_MMIO_ENABLED; |
273 | result |= EEH_STATE_DMA_ENABLED; | 291 | result |= EEH_STATE_DMA_ENABLED; |
292 | } else if (!(pe->state & EEH_PE_ISOLATED)) { | ||
293 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
294 | ioda_eeh_phb_diag(hose); | ||
274 | } | 295 | } |
275 | 296 | ||
276 | return result; | 297 | return result; |
@@ -314,6 +335,15 @@ static int ioda_eeh_get_state(struct eeh_pe *pe) | |||
314 | __func__, fstate, hose->global_number, pe_no); | 335 | __func__, fstate, hose->global_number, pe_no); |
315 | } | 336 | } |
316 | 337 | ||
338 | /* Dump PHB diag-data for frozen PE */ | ||
339 | if (result != EEH_STATE_NOT_SUPPORT && | ||
340 | (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) != | ||
341 | (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && | ||
342 | !(pe->state & EEH_PE_ISOLATED)) { | ||
343 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
344 | ioda_eeh_phb_diag(hose); | ||
345 | } | ||
346 | |||
317 | return result; | 347 | return result; |
318 | } | 348 | } |
319 | 349 | ||
@@ -489,8 +519,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose, | |||
489 | static int ioda_eeh_reset(struct eeh_pe *pe, int option) | 519 | static int ioda_eeh_reset(struct eeh_pe *pe, int option) |
490 | { | 520 | { |
491 | struct pci_controller *hose = pe->phb; | 521 | struct pci_controller *hose = pe->phb; |
492 | struct eeh_dev *edev; | 522 | struct pci_bus *bus; |
493 | struct pci_dev *dev; | ||
494 | int ret; | 523 | int ret; |
495 | 524 | ||
496 | /* | 525 | /* |
@@ -519,73 +548,17 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) | |||
519 | if (pe->type & EEH_PE_PHB) { | 548 | if (pe->type & EEH_PE_PHB) { |
520 | ret = ioda_eeh_phb_reset(hose, option); | 549 | ret = ioda_eeh_phb_reset(hose, option); |
521 | } else { | 550 | } else { |
522 | if (pe->type & EEH_PE_DEVICE) { | 551 | bus = eeh_pe_bus_get(pe); |
523 | /* | 552 | if (pci_is_root_bus(bus)) |
524 | * If it's device PE, we didn't refer to the parent | ||
525 | * PCI bus yet. So we have to figure it out indirectly. | ||
526 | */ | ||
527 | edev = list_first_entry(&pe->edevs, | ||
528 | struct eeh_dev, list); | ||
529 | dev = eeh_dev_to_pci_dev(edev); | ||
530 | dev = dev->bus->self; | ||
531 | } else { | ||
532 | /* | ||
533 | * If it's bus PE, the parent PCI bus is already there | ||
534 | * and just pick it up. | ||
535 | */ | ||
536 | dev = pe->bus->self; | ||
537 | } | ||
538 | |||
539 | /* | ||
540 | * Do reset based on the fact that the direct upstream bridge | ||
541 | * is root bridge (port) or not. | ||
542 | */ | ||
543 | if (dev->bus->number == 0) | ||
544 | ret = ioda_eeh_root_reset(hose, option); | 553 | ret = ioda_eeh_root_reset(hose, option); |
545 | else | 554 | else |
546 | ret = ioda_eeh_bridge_reset(hose, dev, option); | 555 | ret = ioda_eeh_bridge_reset(hose, bus->self, option); |
547 | } | 556 | } |
548 | 557 | ||
549 | return ret; | 558 | return ret; |
550 | } | 559 | } |
551 | 560 | ||
552 | /** | 561 | /** |
553 | * ioda_eeh_get_log - Retrieve error log | ||
554 | * @pe: EEH PE | ||
555 | * @severity: Severity level of the log | ||
556 | * @drv_log: buffer to store the log | ||
557 | * @len: space of the log buffer | ||
558 | * | ||
559 | * The function is used to retrieve error log from P7IOC. | ||
560 | */ | ||
561 | static int ioda_eeh_get_log(struct eeh_pe *pe, int severity, | ||
562 | char *drv_log, unsigned long len) | ||
563 | { | ||
564 | s64 ret; | ||
565 | unsigned long flags; | ||
566 | struct pci_controller *hose = pe->phb; | ||
567 | struct pnv_phb *phb = hose->private_data; | ||
568 | |||
569 | spin_lock_irqsave(&phb->lock, flags); | ||
570 | |||
571 | ret = opal_pci_get_phb_diag_data2(phb->opal_id, | ||
572 | phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE); | ||
573 | if (ret) { | ||
574 | spin_unlock_irqrestore(&phb->lock, flags); | ||
575 | pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n", | ||
576 | __func__, hose->global_number, pe->addr, ret); | ||
577 | return -EIO; | ||
578 | } | ||
579 | |||
580 | /* The PHB diag-data is always indicative */ | ||
581 | pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); | ||
582 | |||
583 | spin_unlock_irqrestore(&phb->lock, flags); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | /** | ||
589 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE | 562 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE |
590 | * @pe: EEH PE | 563 | * @pe: EEH PE |
591 | * | 564 | * |
@@ -666,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
666 | } | 639 | } |
667 | } | 640 | } |
668 | 641 | ||
669 | static void ioda_eeh_phb_diag(struct pci_controller *hose) | ||
670 | { | ||
671 | struct pnv_phb *phb = hose->private_data; | ||
672 | long rc; | ||
673 | |||
674 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | ||
675 | PNV_PCI_DIAG_BUF_SIZE); | ||
676 | if (rc != OPAL_SUCCESS) { | ||
677 | pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", | ||
678 | __func__, hose->global_number, rc); | ||
679 | return; | ||
680 | } | ||
681 | |||
682 | pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); | ||
683 | } | ||
684 | |||
685 | static int ioda_eeh_get_phb_pe(struct pci_controller *hose, | 642 | static int ioda_eeh_get_phb_pe(struct pci_controller *hose, |
686 | struct eeh_pe **pe) | 643 | struct eeh_pe **pe) |
687 | { | 644 | { |
@@ -855,6 +812,20 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
855 | } | 812 | } |
856 | 813 | ||
857 | /* | 814 | /* |
815 | * EEH core will try recover from fenced PHB or | ||
816 | * frozen PE. In the time for frozen PE, EEH core | ||
817 | * enable IO path for that before collecting logs, | ||
818 | * but it ruins the site. So we have to dump the | ||
819 | * log in advance here. | ||
820 | */ | ||
821 | if ((ret == EEH_NEXT_ERR_FROZEN_PE || | ||
822 | ret == EEH_NEXT_ERR_FENCED_PHB) && | ||
823 | !((*pe)->state & EEH_PE_ISOLATED)) { | ||
824 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | ||
825 | ioda_eeh_phb_diag(hose); | ||
826 | } | ||
827 | |||
828 | /* | ||
858 | * If we have no errors on the specific PHB or only | 829 | * If we have no errors on the specific PHB or only |
859 | * informative error there, we continue poking it. | 830 | * informative error there, we continue poking it. |
860 | * Otherwise, we need actions to be taken by upper | 831 | * Otherwise, we need actions to be taken by upper |
@@ -872,7 +843,6 @@ struct pnv_eeh_ops ioda_eeh_ops = { | |||
872 | .set_option = ioda_eeh_set_option, | 843 | .set_option = ioda_eeh_set_option, |
873 | .get_state = ioda_eeh_get_state, | 844 | .get_state = ioda_eeh_get_state, |
874 | .reset = ioda_eeh_reset, | 845 | .reset = ioda_eeh_reset, |
875 | .get_log = ioda_eeh_get_log, | ||
876 | .configure_bridge = ioda_eeh_configure_bridge, | 846 | .configure_bridge = ioda_eeh_configure_bridge, |
877 | .next_error = ioda_eeh_next_error | 847 | .next_error = ioda_eeh_next_error |
878 | }; | 848 | }; |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index a79fddc5e74e..a59788e83b8b 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -145,7 +145,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
145 | * Enable EEH explicitly so that we will do EEH check | 145 | * Enable EEH explicitly so that we will do EEH check |
146 | * while accessing I/O stuff | 146 | * while accessing I/O stuff |
147 | */ | 147 | */ |
148 | eeh_subsystem_enabled = 1; | 148 | eeh_set_enable(true); |
149 | 149 | ||
150 | /* Save memory bars */ | 150 | /* Save memory bars */ |
151 | eeh_save_bars(edev); | 151 | eeh_save_bars(edev); |
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c index 4fbf276ac99e..4cd2ea6c0dbe 100644 --- a/arch/powerpc/platforms/powernv/opal-xscom.c +++ b/arch/powerpc/platforms/powernv/opal-xscom.c | |||
@@ -71,11 +71,11 @@ static int opal_xscom_err_xlate(int64_t rc) | |||
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | static u64 opal_scom_unmangle(u64 reg) | 74 | static u64 opal_scom_unmangle(u64 addr) |
75 | { | 75 | { |
76 | /* | 76 | /* |
77 | * XSCOM indirect addresses have the top bit set. Additionally | 77 | * XSCOM indirect addresses have the top bit set. Additionally |
78 | * the reset of the top 3 nibbles is always 0. | 78 | * the rest of the top 3 nibbles is always 0. |
79 | * | 79 | * |
80 | * Because the debugfs interface uses signed offsets and shifts | 80 | * Because the debugfs interface uses signed offsets and shifts |
81 | * the address left by 3, we basically cannot use the top 4 bits | 81 | * the address left by 3, we basically cannot use the top 4 bits |
@@ -86,10 +86,13 @@ static u64 opal_scom_unmangle(u64 reg) | |||
86 | * conversion here. To leave room for further xscom address | 86 | * conversion here. To leave room for further xscom address |
87 | * expansion, we only clear out the top byte | 87 | * expansion, we only clear out the top byte |
88 | * | 88 | * |
89 | * For in-kernel use, we also support the real indirect bit, so | ||
90 | * we test for any of the top 5 bits | ||
91 | * | ||
89 | */ | 92 | */ |
90 | if (reg & (1ull << 59)) | 93 | if (addr & (0x1full << 59)) |
91 | reg = (reg & ~(0xffull << 56)) | (1ull << 63); | 94 | addr = (addr & ~(0xffull << 56)) | (1ull << 63); |
92 | return reg; | 95 | return addr; |
93 | } | 96 | } |
94 | 97 | ||
95 | static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) | 98 | static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) |
@@ -98,8 +101,8 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) | |||
98 | int64_t rc; | 101 | int64_t rc; |
99 | __be64 v; | 102 | __be64 v; |
100 | 103 | ||
101 | reg = opal_scom_unmangle(reg); | 104 | reg = opal_scom_unmangle(m->addr + reg); |
102 | rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v)); | 105 | rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v)); |
103 | *value = be64_to_cpu(v); | 106 | *value = be64_to_cpu(v); |
104 | return opal_xscom_err_xlate(rc); | 107 | return opal_xscom_err_xlate(rc); |
105 | } | 108 | } |
@@ -109,8 +112,8 @@ static int opal_scom_write(scom_map_t map, u64 reg, u64 value) | |||
109 | struct opal_scom_map *m = map; | 112 | struct opal_scom_map *m = map; |
110 | int64_t rc; | 113 | int64_t rc; |
111 | 114 | ||
112 | reg = opal_scom_unmangle(reg); | 115 | reg = opal_scom_unmangle(m->addr + reg); |
113 | rc = opal_xscom_write(m->chip, m->addr + reg, value); | 116 | rc = opal_xscom_write(m->chip, reg, value); |
114 | return opal_xscom_err_xlate(rc); | 117 | return opal_xscom_err_xlate(rc); |
115 | } | 118 | } |
116 | 119 | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7d6dcc6d5fa9..3b2b4fb3585b 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/msi.h> | 23 | #include <linux/msi.h> |
24 | #include <linux/memblock.h> | ||
24 | 25 | ||
25 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
@@ -460,9 +461,39 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev | |||
460 | return; | 461 | return; |
461 | 462 | ||
462 | pe = &phb->ioda.pe_array[pdn->pe_number]; | 463 | pe = &phb->ioda.pe_array[pdn->pe_number]; |
464 | WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops); | ||
463 | set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table); | 465 | set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table); |
464 | } | 466 | } |
465 | 467 | ||
468 | static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, | ||
469 | struct pci_dev *pdev, u64 dma_mask) | ||
470 | { | ||
471 | struct pci_dn *pdn = pci_get_pdn(pdev); | ||
472 | struct pnv_ioda_pe *pe; | ||
473 | uint64_t top; | ||
474 | bool bypass = false; | ||
475 | |||
476 | if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE)) | ||
477 | return -ENODEV;; | ||
478 | |||
479 | pe = &phb->ioda.pe_array[pdn->pe_number]; | ||
480 | if (pe->tce_bypass_enabled) { | ||
481 | top = pe->tce_bypass_base + memblock_end_of_DRAM() - 1; | ||
482 | bypass = (dma_mask >= top); | ||
483 | } | ||
484 | |||
485 | if (bypass) { | ||
486 | dev_info(&pdev->dev, "Using 64-bit DMA iommu bypass\n"); | ||
487 | set_dma_ops(&pdev->dev, &dma_direct_ops); | ||
488 | set_dma_offset(&pdev->dev, pe->tce_bypass_base); | ||
489 | } else { | ||
490 | dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n"); | ||
491 | set_dma_ops(&pdev->dev, &dma_iommu_ops); | ||
492 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); | ||
493 | } | ||
494 | return 0; | ||
495 | } | ||
496 | |||
466 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) | 497 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) |
467 | { | 498 | { |
468 | struct pci_dev *dev; | 499 | struct pci_dev *dev; |
@@ -657,6 +688,56 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
657 | __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs)); | 688 | __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs)); |
658 | } | 689 | } |
659 | 690 | ||
691 | static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable) | ||
692 | { | ||
693 | struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, | ||
694 | tce32_table); | ||
695 | uint16_t window_id = (pe->pe_number << 1 ) + 1; | ||
696 | int64_t rc; | ||
697 | |||
698 | pe_info(pe, "%sabling 64-bit DMA bypass\n", enable ? "En" : "Dis"); | ||
699 | if (enable) { | ||
700 | phys_addr_t top = memblock_end_of_DRAM(); | ||
701 | |||
702 | top = roundup_pow_of_two(top); | ||
703 | rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, | ||
704 | pe->pe_number, | ||
705 | window_id, | ||
706 | pe->tce_bypass_base, | ||
707 | top); | ||
708 | } else { | ||
709 | rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, | ||
710 | pe->pe_number, | ||
711 | window_id, | ||
712 | pe->tce_bypass_base, | ||
713 | 0); | ||
714 | |||
715 | /* | ||
716 | * We might want to reset the DMA ops of all devices on | ||
717 | * this PE. However in theory, that shouldn't be necessary | ||
718 | * as this is used for VFIO/KVM pass-through and the device | ||
719 | * hasn't yet been returned to its kernel driver | ||
720 | */ | ||
721 | } | ||
722 | if (rc) | ||
723 | pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); | ||
724 | else | ||
725 | pe->tce_bypass_enabled = enable; | ||
726 | } | ||
727 | |||
728 | static void pnv_pci_ioda2_setup_bypass_pe(struct pnv_phb *phb, | ||
729 | struct pnv_ioda_pe *pe) | ||
730 | { | ||
731 | /* TVE #1 is selected by PCI address bit 59 */ | ||
732 | pe->tce_bypass_base = 1ull << 59; | ||
733 | |||
734 | /* Install set_bypass callback for VFIO */ | ||
735 | pe->tce32_table.set_bypass = pnv_pci_ioda2_set_bypass; | ||
736 | |||
737 | /* Enable bypass by default */ | ||
738 | pnv_pci_ioda2_set_bypass(&pe->tce32_table, true); | ||
739 | } | ||
740 | |||
660 | static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | 741 | static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, |
661 | struct pnv_ioda_pe *pe) | 742 | struct pnv_ioda_pe *pe) |
662 | { | 743 | { |
@@ -727,6 +808,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
727 | else | 808 | else |
728 | pnv_ioda_setup_bus_dma(pe, pe->pbus); | 809 | pnv_ioda_setup_bus_dma(pe, pe->pbus); |
729 | 810 | ||
811 | /* Also create a bypass window */ | ||
812 | pnv_pci_ioda2_setup_bypass_pe(phb, pe); | ||
730 | return; | 813 | return; |
731 | fail: | 814 | fail: |
732 | if (pe->tce32_seg >= 0) | 815 | if (pe->tce32_seg >= 0) |
@@ -1286,6 +1369,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1286 | 1369 | ||
1287 | /* Setup TCEs */ | 1370 | /* Setup TCEs */ |
1288 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; | 1371 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; |
1372 | phb->dma_set_mask = pnv_pci_ioda_dma_set_mask; | ||
1289 | 1373 | ||
1290 | /* Setup shutdown function for kexec */ | 1374 | /* Setup shutdown function for kexec */ |
1291 | phb->shutdown = pnv_pci_ioda_shutdown; | 1375 | phb->shutdown = pnv_pci_ioda_shutdown; |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index b555ebc57ef5..8518817dcdfd 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -134,57 +134,72 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, | |||
134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n", | 134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n", |
135 | hose->global_number, common->version); | 135 | hose->global_number, common->version); |
136 | 136 | ||
137 | pr_info(" brdgCtl: %08x\n", data->brdgCtl); | 137 | if (data->brdgCtl) |
138 | 138 | pr_info(" brdgCtl: %08x\n", | |
139 | pr_info(" portStatusReg: %08x\n", data->portStatusReg); | 139 | data->brdgCtl); |
140 | pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus); | 140 | if (data->portStatusReg || data->rootCmplxStatus || |
141 | pr_info(" busAgentStatus: %08x\n", data->busAgentStatus); | 141 | data->busAgentStatus) |
142 | 142 | pr_info(" UtlSts: %08x %08x %08x\n", | |
143 | pr_info(" deviceStatus: %08x\n", data->deviceStatus); | 143 | data->portStatusReg, data->rootCmplxStatus, |
144 | pr_info(" slotStatus: %08x\n", data->slotStatus); | 144 | data->busAgentStatus); |
145 | pr_info(" linkStatus: %08x\n", data->linkStatus); | 145 | if (data->deviceStatus || data->slotStatus || |
146 | pr_info(" devCmdStatus: %08x\n", data->devCmdStatus); | 146 | data->linkStatus || data->devCmdStatus || |
147 | pr_info(" devSecStatus: %08x\n", data->devSecStatus); | 147 | data->devSecStatus) |
148 | 148 | pr_info(" RootSts: %08x %08x %08x %08x %08x\n", | |
149 | pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus); | 149 | data->deviceStatus, data->slotStatus, |
150 | pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus); | 150 | data->linkStatus, data->devCmdStatus, |
151 | pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus); | 151 | data->devSecStatus); |
152 | pr_info(" tlpHdr1: %08x\n", data->tlpHdr1); | 152 | if (data->rootErrorStatus || data->uncorrErrorStatus || |
153 | pr_info(" tlpHdr2: %08x\n", data->tlpHdr2); | 153 | data->corrErrorStatus) |
154 | pr_info(" tlpHdr3: %08x\n", data->tlpHdr3); | 154 | pr_info(" RootErrSts: %08x %08x %08x\n", |
155 | pr_info(" tlpHdr4: %08x\n", data->tlpHdr4); | 155 | data->rootErrorStatus, data->uncorrErrorStatus, |
156 | pr_info(" sourceId: %08x\n", data->sourceId); | 156 | data->corrErrorStatus); |
157 | pr_info(" errorClass: %016llx\n", data->errorClass); | 157 | if (data->tlpHdr1 || data->tlpHdr2 || |
158 | pr_info(" correlator: %016llx\n", data->correlator); | 158 | data->tlpHdr3 || data->tlpHdr4) |
159 | pr_info(" p7iocPlssr: %016llx\n", data->p7iocPlssr); | 159 | pr_info(" RootErrLog: %08x %08x %08x %08x\n", |
160 | pr_info(" p7iocCsr: %016llx\n", data->p7iocCsr); | 160 | data->tlpHdr1, data->tlpHdr2, |
161 | pr_info(" lemFir: %016llx\n", data->lemFir); | 161 | data->tlpHdr3, data->tlpHdr4); |
162 | pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask); | 162 | if (data->sourceId || data->errorClass || |
163 | pr_info(" lemWOF: %016llx\n", data->lemWOF); | 163 | data->correlator) |
164 | pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus); | 164 | pr_info(" RootErrLog1: %08x %016llx %016llx\n", |
165 | pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus); | 165 | data->sourceId, data->errorClass, |
166 | pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0); | 166 | data->correlator); |
167 | pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1); | 167 | if (data->p7iocPlssr || data->p7iocCsr) |
168 | pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus); | 168 | pr_info(" PhbSts: %016llx %016llx\n", |
169 | pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus); | 169 | data->p7iocPlssr, data->p7iocCsr); |
170 | pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0); | 170 | if (data->lemFir || data->lemErrorMask || |
171 | pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1); | 171 | data->lemWOF) |
172 | pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus); | 172 | pr_info(" Lem: %016llx %016llx %016llx\n", |
173 | pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus); | 173 | data->lemFir, data->lemErrorMask, |
174 | pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0); | 174 | data->lemWOF); |
175 | pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1); | 175 | if (data->phbErrorStatus || data->phbFirstErrorStatus || |
176 | pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus); | 176 | data->phbErrorLog0 || data->phbErrorLog1) |
177 | pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus); | 177 | pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n", |
178 | pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0); | 178 | data->phbErrorStatus, data->phbFirstErrorStatus, |
179 | pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1); | 179 | data->phbErrorLog0, data->phbErrorLog1); |
180 | if (data->mmioErrorStatus || data->mmioFirstErrorStatus || | ||
181 | data->mmioErrorLog0 || data->mmioErrorLog1) | ||
182 | pr_info(" OutErr: %016llx %016llx %016llx %016llx\n", | ||
183 | data->mmioErrorStatus, data->mmioFirstErrorStatus, | ||
184 | data->mmioErrorLog0, data->mmioErrorLog1); | ||
185 | if (data->dma0ErrorStatus || data->dma0FirstErrorStatus || | ||
186 | data->dma0ErrorLog0 || data->dma0ErrorLog1) | ||
187 | pr_info(" InAErr: %016llx %016llx %016llx %016llx\n", | ||
188 | data->dma0ErrorStatus, data->dma0FirstErrorStatus, | ||
189 | data->dma0ErrorLog0, data->dma0ErrorLog1); | ||
190 | if (data->dma1ErrorStatus || data->dma1FirstErrorStatus || | ||
191 | data->dma1ErrorLog0 || data->dma1ErrorLog1) | ||
192 | pr_info(" InBErr: %016llx %016llx %016llx %016llx\n", | ||
193 | data->dma1ErrorStatus, data->dma1FirstErrorStatus, | ||
194 | data->dma1ErrorLog0, data->dma1ErrorLog1); | ||
180 | 195 | ||
181 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { | 196 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { |
182 | if ((data->pestA[i] >> 63) == 0 && | 197 | if ((data->pestA[i] >> 63) == 0 && |
183 | (data->pestB[i] >> 63) == 0) | 198 | (data->pestB[i] >> 63) == 0) |
184 | continue; | 199 | continue; |
185 | 200 | ||
186 | pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]); | 201 | pr_info(" PE[%3d] A/B: %016llx %016llx\n", |
187 | pr_info(" PESTB: %016llx\n", data->pestB[i]); | 202 | i, data->pestA[i], data->pestB[i]); |
188 | } | 203 | } |
189 | } | 204 | } |
190 | 205 | ||
@@ -197,62 +212,77 @@ static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose, | |||
197 | data = (struct OpalIoPhb3ErrorData*)common; | 212 | data = (struct OpalIoPhb3ErrorData*)common; |
198 | pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n", | 213 | pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n", |
199 | hose->global_number, common->version); | 214 | hose->global_number, common->version); |
200 | 215 | if (data->brdgCtl) | |
201 | pr_info(" brdgCtl: %08x\n", data->brdgCtl); | 216 | pr_info(" brdgCtl: %08x\n", |
202 | 217 | data->brdgCtl); | |
203 | pr_info(" portStatusReg: %08x\n", data->portStatusReg); | 218 | if (data->portStatusReg || data->rootCmplxStatus || |
204 | pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus); | 219 | data->busAgentStatus) |
205 | pr_info(" busAgentStatus: %08x\n", data->busAgentStatus); | 220 | pr_info(" UtlSts: %08x %08x %08x\n", |
206 | 221 | data->portStatusReg, data->rootCmplxStatus, | |
207 | pr_info(" deviceStatus: %08x\n", data->deviceStatus); | 222 | data->busAgentStatus); |
208 | pr_info(" slotStatus: %08x\n", data->slotStatus); | 223 | if (data->deviceStatus || data->slotStatus || |
209 | pr_info(" linkStatus: %08x\n", data->linkStatus); | 224 | data->linkStatus || data->devCmdStatus || |
210 | pr_info(" devCmdStatus: %08x\n", data->devCmdStatus); | 225 | data->devSecStatus) |
211 | pr_info(" devSecStatus: %08x\n", data->devSecStatus); | 226 | pr_info(" RootSts: %08x %08x %08x %08x %08x\n", |
212 | 227 | data->deviceStatus, data->slotStatus, | |
213 | pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus); | 228 | data->linkStatus, data->devCmdStatus, |
214 | pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus); | 229 | data->devSecStatus); |
215 | pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus); | 230 | if (data->rootErrorStatus || data->uncorrErrorStatus || |
216 | pr_info(" tlpHdr1: %08x\n", data->tlpHdr1); | 231 | data->corrErrorStatus) |
217 | pr_info(" tlpHdr2: %08x\n", data->tlpHdr2); | 232 | pr_info(" RootErrSts: %08x %08x %08x\n", |
218 | pr_info(" tlpHdr3: %08x\n", data->tlpHdr3); | 233 | data->rootErrorStatus, data->uncorrErrorStatus, |
219 | pr_info(" tlpHdr4: %08x\n", data->tlpHdr4); | 234 | data->corrErrorStatus); |
220 | pr_info(" sourceId: %08x\n", data->sourceId); | 235 | if (data->tlpHdr1 || data->tlpHdr2 || |
221 | pr_info(" errorClass: %016llx\n", data->errorClass); | 236 | data->tlpHdr3 || data->tlpHdr4) |
222 | pr_info(" correlator: %016llx\n", data->correlator); | 237 | pr_info(" RootErrLog: %08x %08x %08x %08x\n", |
223 | 238 | data->tlpHdr1, data->tlpHdr2, | |
224 | pr_info(" nFir: %016llx\n", data->nFir); | 239 | data->tlpHdr3, data->tlpHdr4); |
225 | pr_info(" nFirMask: %016llx\n", data->nFirMask); | 240 | if (data->sourceId || data->errorClass || |
226 | pr_info(" nFirWOF: %016llx\n", data->nFirWOF); | 241 | data->correlator) |
227 | pr_info(" PhbPlssr: %016llx\n", data->phbPlssr); | 242 | pr_info(" RootErrLog1: %08x %016llx %016llx\n", |
228 | pr_info(" PhbCsr: %016llx\n", data->phbCsr); | 243 | data->sourceId, data->errorClass, |
229 | pr_info(" lemFir: %016llx\n", data->lemFir); | 244 | data->correlator); |
230 | pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask); | 245 | if (data->nFir || data->nFirMask || |
231 | pr_info(" lemWOF: %016llx\n", data->lemWOF); | 246 | data->nFirWOF) |
232 | pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus); | 247 | pr_info(" nFir: %016llx %016llx %016llx\n", |
233 | pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus); | 248 | data->nFir, data->nFirMask, |
234 | pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0); | 249 | data->nFirWOF); |
235 | pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1); | 250 | if (data->phbPlssr || data->phbCsr) |
236 | pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus); | 251 | pr_info(" PhbSts: %016llx %016llx\n", |
237 | pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus); | 252 | data->phbPlssr, data->phbCsr); |
238 | pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0); | 253 | if (data->lemFir || data->lemErrorMask || |
239 | pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1); | 254 | data->lemWOF) |
240 | pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus); | 255 | pr_info(" Lem: %016llx %016llx %016llx\n", |
241 | pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus); | 256 | data->lemFir, data->lemErrorMask, |
242 | pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0); | 257 | data->lemWOF); |
243 | pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1); | 258 | if (data->phbErrorStatus || data->phbFirstErrorStatus || |
244 | pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus); | 259 | data->phbErrorLog0 || data->phbErrorLog1) |
245 | pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus); | 260 | pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n", |
246 | pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0); | 261 | data->phbErrorStatus, data->phbFirstErrorStatus, |
247 | pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1); | 262 | data->phbErrorLog0, data->phbErrorLog1); |
263 | if (data->mmioErrorStatus || data->mmioFirstErrorStatus || | ||
264 | data->mmioErrorLog0 || data->mmioErrorLog1) | ||
265 | pr_info(" OutErr: %016llx %016llx %016llx %016llx\n", | ||
266 | data->mmioErrorStatus, data->mmioFirstErrorStatus, | ||
267 | data->mmioErrorLog0, data->mmioErrorLog1); | ||
268 | if (data->dma0ErrorStatus || data->dma0FirstErrorStatus || | ||
269 | data->dma0ErrorLog0 || data->dma0ErrorLog1) | ||
270 | pr_info(" InAErr: %016llx %016llx %016llx %016llx\n", | ||
271 | data->dma0ErrorStatus, data->dma0FirstErrorStatus, | ||
272 | data->dma0ErrorLog0, data->dma0ErrorLog1); | ||
273 | if (data->dma1ErrorStatus || data->dma1FirstErrorStatus || | ||
274 | data->dma1ErrorLog0 || data->dma1ErrorLog1) | ||
275 | pr_info(" InBErr: %016llx %016llx %016llx %016llx\n", | ||
276 | data->dma1ErrorStatus, data->dma1FirstErrorStatus, | ||
277 | data->dma1ErrorLog0, data->dma1ErrorLog1); | ||
248 | 278 | ||
249 | for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) { | 279 | for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) { |
250 | if ((data->pestA[i] >> 63) == 0 && | 280 | if ((data->pestA[i] >> 63) == 0 && |
251 | (data->pestB[i] >> 63) == 0) | 281 | (data->pestB[i] >> 63) == 0) |
252 | continue; | 282 | continue; |
253 | 283 | ||
254 | pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]); | 284 | pr_info(" PE[%3d] A/B: %016llx %016llx\n", |
255 | pr_info(" PESTB: %016llx\n", data->pestB[i]); | 285 | i, data->pestA[i], data->pestB[i]); |
256 | } | 286 | } |
257 | } | 287 | } |
258 | 288 | ||
@@ -634,6 +664,16 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) | |||
634 | pnv_pci_dma_fallback_setup(hose, pdev); | 664 | pnv_pci_dma_fallback_setup(hose, pdev); |
635 | } | 665 | } |
636 | 666 | ||
667 | int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) | ||
668 | { | ||
669 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
670 | struct pnv_phb *phb = hose->private_data; | ||
671 | |||
672 | if (phb && phb->dma_set_mask) | ||
673 | return phb->dma_set_mask(phb, pdev, dma_mask); | ||
674 | return __dma_set_mask(&pdev->dev, dma_mask); | ||
675 | } | ||
676 | |||
637 | void pnv_pci_shutdown(void) | 677 | void pnv_pci_shutdown(void) |
638 | { | 678 | { |
639 | struct pci_controller *hose; | 679 | struct pci_controller *hose; |
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 13f1942a9a5f..cde169442775 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -54,7 +54,9 @@ struct pnv_ioda_pe { | |||
54 | struct iommu_table tce32_table; | 54 | struct iommu_table tce32_table; |
55 | phys_addr_t tce_inval_reg_phys; | 55 | phys_addr_t tce_inval_reg_phys; |
56 | 56 | ||
57 | /* XXX TODO: Add support for additional 64-bit iommus */ | 57 | /* 64-bit TCE bypass region */ |
58 | bool tce_bypass_enabled; | ||
59 | uint64_t tce_bypass_base; | ||
58 | 60 | ||
59 | /* MSIs. MVE index is identical for for 32 and 64 bit MSI | 61 | /* MSIs. MVE index is identical for for 32 and 64 bit MSI |
60 | * and -1 if not supported. (It's actually identical to the | 62 | * and -1 if not supported. (It's actually identical to the |
@@ -113,6 +115,8 @@ struct pnv_phb { | |||
113 | unsigned int hwirq, unsigned int virq, | 115 | unsigned int hwirq, unsigned int virq, |
114 | unsigned int is_64, struct msi_msg *msg); | 116 | unsigned int is_64, struct msi_msg *msg); |
115 | void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); | 117 | void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); |
118 | int (*dma_set_mask)(struct pnv_phb *phb, struct pci_dev *pdev, | ||
119 | u64 dma_mask); | ||
116 | void (*fixup_phb)(struct pci_controller *hose); | 120 | void (*fixup_phb)(struct pci_controller *hose); |
117 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); | 121 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); |
118 | void (*shutdown)(struct pnv_phb *phb); | 122 | void (*shutdown)(struct pnv_phb *phb); |
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index de6819be1f95..0051e108ef0f 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h | |||
@@ -7,12 +7,20 @@ extern void pnv_smp_init(void); | |||
7 | static inline void pnv_smp_init(void) { } | 7 | static inline void pnv_smp_init(void) { } |
8 | #endif | 8 | #endif |
9 | 9 | ||
10 | struct pci_dev; | ||
11 | |||
10 | #ifdef CONFIG_PCI | 12 | #ifdef CONFIG_PCI |
11 | extern void pnv_pci_init(void); | 13 | extern void pnv_pci_init(void); |
12 | extern void pnv_pci_shutdown(void); | 14 | extern void pnv_pci_shutdown(void); |
15 | extern int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask); | ||
13 | #else | 16 | #else |
14 | static inline void pnv_pci_init(void) { } | 17 | static inline void pnv_pci_init(void) { } |
15 | static inline void pnv_pci_shutdown(void) { } | 18 | static inline void pnv_pci_shutdown(void) { } |
19 | |||
20 | static inline int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) | ||
21 | { | ||
22 | return -ENODEV; | ||
23 | } | ||
16 | #endif | 24 | #endif |
17 | 25 | ||
18 | extern void pnv_lpc_init(void); | 26 | extern void pnv_lpc_init(void); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 21166f65c97c..110f4fbd319f 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/bug.h> | 28 | #include <linux/bug.h> |
29 | #include <linux/cpuidle.h> | 29 | #include <linux/cpuidle.h> |
30 | #include <linux/pci.h> | ||
30 | 31 | ||
31 | #include <asm/machdep.h> | 32 | #include <asm/machdep.h> |
32 | #include <asm/firmware.h> | 33 | #include <asm/firmware.h> |
@@ -141,6 +142,13 @@ static void pnv_progress(char *s, unsigned short hex) | |||
141 | { | 142 | { |
142 | } | 143 | } |
143 | 144 | ||
145 | static int pnv_dma_set_mask(struct device *dev, u64 dma_mask) | ||
146 | { | ||
147 | if (dev_is_pci(dev)) | ||
148 | return pnv_pci_dma_set_mask(to_pci_dev(dev), dma_mask); | ||
149 | return __dma_set_mask(dev, dma_mask); | ||
150 | } | ||
151 | |||
144 | static void pnv_shutdown(void) | 152 | static void pnv_shutdown(void) |
145 | { | 153 | { |
146 | /* Let the PCI code clear up IODA tables */ | 154 | /* Let the PCI code clear up IODA tables */ |
@@ -238,6 +246,7 @@ define_machine(powernv) { | |||
238 | .machine_shutdown = pnv_shutdown, | 246 | .machine_shutdown = pnv_shutdown, |
239 | .power_save = powernv_idle, | 247 | .power_save = powernv_idle, |
240 | .calibrate_decr = generic_calibrate_decr, | 248 | .calibrate_decr = generic_calibrate_decr, |
249 | .dma_set_mask = pnv_dma_set_mask, | ||
241 | #ifdef CONFIG_KEXEC | 250 | #ifdef CONFIG_KEXEC |
242 | .kexec_cpu_down = pnv_kexec_cpu_down, | 251 | .kexec_cpu_down = pnv_kexec_cpu_down, |
243 | #endif | 252 | #endif |