.. | .. |
---|
41 | 41 | |
---|
42 | 42 | #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) |
---|
43 | 43 | #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) |
---|
| 44 | +#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) |
---|
44 | 45 | |
---|
45 | 46 | #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) |
---|
46 | 47 | |
---|
.. | .. |
---|
49 | 50 | phys_addr_t phys_base; |
---|
50 | 51 | bool single_redist; |
---|
51 | 52 | }; |
---|
| 53 | + |
---|
| 54 | +static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum); |
---|
52 | 55 | |
---|
53 | 56 | static struct gic_chip_data gic_data __read_mostly; |
---|
54 | 57 | static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); |
---|
.. | .. |
---|
541 | 544 | gic_irq_set_prio(d, GICD_INT_DEF_PRI); |
---|
542 | 545 | } |
---|
543 | 546 | |
---|
| 547 | +static bool gic_arm64_erratum_2941627_needed(struct irq_data *d) |
---|
| 548 | +{ |
---|
| 549 | + enum gic_intid_range range; |
---|
| 550 | + |
---|
| 551 | + if (!static_branch_unlikely(&gic_arm64_2941627_erratum)) |
---|
| 552 | + return false; |
---|
| 553 | + |
---|
| 554 | + range = get_intid_range(d); |
---|
| 555 | + |
---|
| 556 | + /* |
---|
| 557 | + * The workaround is needed if the IRQ is an SPI and |
---|
| 558 | + * the target cpu is different from the one we are |
---|
| 559 | + * executing on. |
---|
| 560 | + */ |
---|
| 561 | + return (range == SPI_RANGE || range == ESPI_RANGE) && |
---|
| 562 | + !cpumask_test_cpu(raw_smp_processor_id(), |
---|
| 563 | + irq_data_get_effective_affinity_mask(d)); |
---|
| 564 | +} |
---|
| 565 | + |
---|
544 | 566 | static void gic_eoi_irq(struct irq_data *d) |
---|
545 | 567 | { |
---|
546 | | - gic_write_eoir(gic_irq(d)); |
---|
| 568 | + write_gicreg(gic_irq(d), ICC_EOIR1_EL1); |
---|
| 569 | + isb(); |
---|
| 570 | + |
---|
| 571 | + if (gic_arm64_erratum_2941627_needed(d)) { |
---|
| 572 | + /* |
---|
| 573 | + * Make sure the GIC stream deactivate packet |
---|
| 574 | + * issued by ICC_EOIR1_EL1 has completed before |
---|
| 575 | + * deactivating through GICD_IACTIVER. |
---|
| 576 | + */ |
---|
| 577 | + dsb(sy); |
---|
| 578 | + gic_poke_irq(d, GICD_ICACTIVER); |
---|
| 579 | + } |
---|
547 | 580 | } |
---|
548 | 581 | |
---|
549 | 582 | static void gic_eoimode1_eoi_irq(struct irq_data *d) |
---|
.. | .. |
---|
554 | 587 | */ |
---|
555 | 588 | if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d)) |
---|
556 | 589 | return; |
---|
557 | | - gic_write_dir(gic_irq(d)); |
---|
| 590 | + |
---|
| 591 | + if (!gic_arm64_erratum_2941627_needed(d)) |
---|
| 592 | + gic_write_dir(gic_irq(d)); |
---|
| 593 | + else |
---|
| 594 | + gic_poke_irq(d, GICD_ICACTIVER); |
---|
558 | 595 | } |
---|
559 | 596 | |
---|
560 | 597 | static int gic_set_type(struct irq_data *d, unsigned int type) |
---|
.. | .. |
---|
1472 | 1509 | |
---|
1473 | 1510 | /* |
---|
1474 | 1511 | * Make it clear that broken DTs are... broken. |
---|
1475 | | - * Partitionned PPIs are an unfortunate exception. |
---|
| 1512 | + * Partitioned PPIs are an unfortunate exception. |
---|
1476 | 1513 | */ |
---|
1477 | 1514 | WARN_ON(*type == IRQ_TYPE_NONE && |
---|
1478 | 1515 | fwspec->param[0] != GIC_IRQ_TYPE_PARTITION); |
---|
.. | .. |
---|
1603 | 1640 | return true; |
---|
1604 | 1641 | } |
---|
1605 | 1642 | |
---|
| 1643 | +static bool gic_enable_quirk_mtk_gicr(void *data) |
---|
| 1644 | +{ |
---|
| 1645 | + struct gic_chip_data *d = data; |
---|
| 1646 | + |
---|
| 1647 | + d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE; |
---|
| 1648 | + |
---|
| 1649 | + return true; |
---|
| 1650 | +} |
---|
| 1651 | + |
---|
1606 | 1652 | static bool gic_enable_quirk_cavium_38539(void *data) |
---|
1607 | 1653 | { |
---|
1608 | 1654 | struct gic_chip_data *d = data; |
---|
.. | .. |
---|
1632 | 1678 | return false; |
---|
1633 | 1679 | } |
---|
1634 | 1680 | |
---|
| 1681 | +static bool gic_enable_quirk_arm64_2941627(void *data) |
---|
| 1682 | +{ |
---|
| 1683 | + static_branch_enable(&gic_arm64_2941627_erratum); |
---|
| 1684 | + return true; |
---|
| 1685 | +} |
---|
| 1686 | + |
---|
1635 | 1687 | static const struct gic_quirk gic_quirks[] = { |
---|
1636 | 1688 | { |
---|
1637 | 1689 | .desc = "GICv3: Qualcomm MSM8996 broken firmware", |
---|
1638 | 1690 | .compatible = "qcom,msm8996-gic-v3", |
---|
1639 | 1691 | .init = gic_enable_quirk_msm8996, |
---|
| 1692 | + }, |
---|
| 1693 | + { |
---|
| 1694 | + .desc = "GICv3: Mediatek Chromebook GICR save problem", |
---|
| 1695 | + .property = "mediatek,broken-save-restore-fw", |
---|
| 1696 | + .init = gic_enable_quirk_mtk_gicr, |
---|
1640 | 1697 | }, |
---|
1641 | 1698 | { |
---|
1642 | 1699 | .desc = "GICv3: HIP06 erratum 161010803", |
---|
.. | .. |
---|
1664 | 1721 | .init = gic_enable_quirk_cavium_38539, |
---|
1665 | 1722 | }, |
---|
1666 | 1723 | { |
---|
| 1724 | + /* |
---|
| 1725 | + * GIC-700: 2941627 workaround - IP variant [0,1] |
---|
| 1726 | + * |
---|
| 1727 | + */ |
---|
| 1728 | + .desc = "GICv3: ARM64 erratum 2941627", |
---|
| 1729 | + .iidr = 0x0400043b, |
---|
| 1730 | + .mask = 0xff0e0fff, |
---|
| 1731 | + .init = gic_enable_quirk_arm64_2941627, |
---|
| 1732 | + }, |
---|
| 1733 | + { |
---|
| 1734 | + /* |
---|
| 1735 | + * GIC-700: 2941627 workaround - IP variant [2] |
---|
| 1736 | + */ |
---|
| 1737 | + .desc = "GICv3: ARM64 erratum 2941627", |
---|
| 1738 | + .iidr = 0x0402043b, |
---|
| 1739 | + .mask = 0xff0f0fff, |
---|
| 1740 | + .init = gic_enable_quirk_arm64_2941627, |
---|
| 1741 | + }, |
---|
| 1742 | + { |
---|
1667 | 1743 | } |
---|
1668 | 1744 | }; |
---|
1669 | 1745 | |
---|
.. | .. |
---|
1674 | 1750 | if (!gic_prio_masking_enabled()) |
---|
1675 | 1751 | return; |
---|
1676 | 1752 | |
---|
| 1753 | + if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) { |
---|
| 1754 | + pr_warn("Skipping NMI enable due to firmware issues\n"); |
---|
| 1755 | + return; |
---|
| 1756 | + } |
---|
| 1757 | + |
---|
1677 | 1758 | ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL); |
---|
1678 | 1759 | if (!ppi_nmi_refs) |
---|
1679 | 1760 | return; |
---|