.. | .. |
---|
47 | 47 | #include <linux/kthread.h> |
---|
48 | 48 | #include <linux/jiffies.h> /* time_after() */ |
---|
49 | 49 | #include <linux/slab.h> |
---|
50 | | -#include <linux/bootmem.h> |
---|
| 50 | +#include <linux/memblock.h> |
---|
51 | 51 | |
---|
52 | 52 | #include <asm/irqdomain.h> |
---|
53 | 53 | #include <asm/io.h> |
---|
.. | .. |
---|
58 | 58 | #include <asm/acpi.h> |
---|
59 | 59 | #include <asm/dma.h> |
---|
60 | 60 | #include <asm/timer.h> |
---|
| 61 | +#include <asm/time.h> |
---|
61 | 62 | #include <asm/i8259.h> |
---|
62 | 63 | #include <asm/setup.h> |
---|
63 | 64 | #include <asm/irq_remapping.h> |
---|
.. | .. |
---|
151 | 152 | static inline bool mp_is_legacy_irq(int irq) |
---|
152 | 153 | { |
---|
153 | 154 | return irq >= 0 && irq < nr_legacy_irqs(); |
---|
154 | | -} |
---|
155 | | - |
---|
156 | | -/* |
---|
157 | | - * Initialize all legacy IRQs and all pins on the first IOAPIC |
---|
158 | | - * if we have legacy interrupt controller. Kernel boot option "pirq=" |
---|
159 | | - * may rely on non-legacy pins on the first IOAPIC. |
---|
160 | | - */ |
---|
161 | | -static inline int mp_init_irq_at_boot(int ioapic, int irq) |
---|
162 | | -{ |
---|
163 | | - if (!nr_legacy_irqs()) |
---|
164 | | - return 0; |
---|
165 | | - |
---|
166 | | - return ioapic == 0 || mp_is_legacy_irq(irq); |
---|
167 | 155 | } |
---|
168 | 156 | |
---|
169 | 157 | static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic) |
---|
.. | .. |
---|
812 | 800 | return IOAPIC_POL_HIGH; |
---|
813 | 801 | case MP_IRQPOL_RESERVED: |
---|
814 | 802 | pr_warn("IOAPIC: Invalid polarity: 2, defaulting to low\n"); |
---|
| 803 | + fallthrough; |
---|
815 | 804 | case MP_IRQPOL_ACTIVE_LOW: |
---|
816 | 805 | default: /* Pointless default required due to do gcc stupidity */ |
---|
817 | 806 | return IOAPIC_POL_LOW; |
---|
.. | .. |
---|
859 | 848 | return IOAPIC_EDGE; |
---|
860 | 849 | case MP_IRQTRIG_RESERVED: |
---|
861 | 850 | pr_warn("IOAPIC: Invalid trigger mode 2 defaulting to level\n"); |
---|
| 851 | + fallthrough; |
---|
862 | 852 | case MP_IRQTRIG_LEVEL: |
---|
863 | 853 | default: /* Pointless default required due to do gcc stupidity */ |
---|
864 | 854 | return IOAPIC_LEVEL; |
---|
.. | .. |
---|
870 | 860 | { |
---|
871 | 861 | init_irq_alloc_info(info, NULL); |
---|
872 | 862 | info->type = X86_IRQ_ALLOC_TYPE_IOAPIC; |
---|
873 | | - info->ioapic_node = node; |
---|
874 | | - info->ioapic_trigger = trigger; |
---|
875 | | - info->ioapic_polarity = polarity; |
---|
876 | | - info->ioapic_valid = 1; |
---|
| 863 | + info->ioapic.node = node; |
---|
| 864 | + info->ioapic.trigger = trigger; |
---|
| 865 | + info->ioapic.polarity = polarity; |
---|
| 866 | + info->ioapic.valid = 1; |
---|
877 | 867 | } |
---|
878 | 868 | |
---|
879 | 869 | #ifndef CONFIG_ACPI |
---|
.. | .. |
---|
888 | 878 | |
---|
889 | 879 | copy_irq_alloc_info(dst, src); |
---|
890 | 880 | dst->type = X86_IRQ_ALLOC_TYPE_IOAPIC; |
---|
891 | | - dst->ioapic_id = mpc_ioapic_id(ioapic_idx); |
---|
892 | | - dst->ioapic_pin = pin; |
---|
893 | | - dst->ioapic_valid = 1; |
---|
894 | | - if (src && src->ioapic_valid) { |
---|
895 | | - dst->ioapic_node = src->ioapic_node; |
---|
896 | | - dst->ioapic_trigger = src->ioapic_trigger; |
---|
897 | | - dst->ioapic_polarity = src->ioapic_polarity; |
---|
| 881 | + dst->devid = mpc_ioapic_id(ioapic_idx); |
---|
| 882 | + dst->ioapic.pin = pin; |
---|
| 883 | + dst->ioapic.valid = 1; |
---|
| 884 | + if (src && src->ioapic.valid) { |
---|
| 885 | + dst->ioapic.node = src->ioapic.node; |
---|
| 886 | + dst->ioapic.trigger = src->ioapic.trigger; |
---|
| 887 | + dst->ioapic.polarity = src->ioapic.polarity; |
---|
898 | 888 | } else { |
---|
899 | | - dst->ioapic_node = NUMA_NO_NODE; |
---|
| 889 | + dst->ioapic.node = NUMA_NO_NODE; |
---|
900 | 890 | if (acpi_get_override_irq(gsi, &trigger, &polarity) >= 0) { |
---|
901 | | - dst->ioapic_trigger = trigger; |
---|
902 | | - dst->ioapic_polarity = polarity; |
---|
| 891 | + dst->ioapic.trigger = trigger; |
---|
| 892 | + dst->ioapic.polarity = polarity; |
---|
903 | 893 | } else { |
---|
904 | 894 | /* |
---|
905 | 895 | * PCI interrupts are always active low level |
---|
906 | 896 | * triggered. |
---|
907 | 897 | */ |
---|
908 | | - dst->ioapic_trigger = IOAPIC_LEVEL; |
---|
909 | | - dst->ioapic_polarity = IOAPIC_POL_LOW; |
---|
| 898 | + dst->ioapic.trigger = IOAPIC_LEVEL; |
---|
| 899 | + dst->ioapic.polarity = IOAPIC_POL_LOW; |
---|
910 | 900 | } |
---|
911 | 901 | } |
---|
912 | 902 | } |
---|
913 | 903 | |
---|
914 | 904 | static int ioapic_alloc_attr_node(struct irq_alloc_info *info) |
---|
915 | 905 | { |
---|
916 | | - return (info && info->ioapic_valid) ? info->ioapic_node : NUMA_NO_NODE; |
---|
| 906 | + return (info && info->ioapic.valid) ? info->ioapic.node : NUMA_NO_NODE; |
---|
917 | 907 | } |
---|
918 | 908 | |
---|
919 | 909 | static void mp_register_handler(unsigned int irq, unsigned long trigger) |
---|
.. | .. |
---|
943 | 933 | * pin with real trigger and polarity attributes. |
---|
944 | 934 | */ |
---|
945 | 935 | if (irq < nr_legacy_irqs() && data->count == 1) { |
---|
946 | | - if (info->ioapic_trigger != data->trigger) |
---|
947 | | - mp_register_handler(irq, info->ioapic_trigger); |
---|
948 | | - data->entry.trigger = data->trigger = info->ioapic_trigger; |
---|
949 | | - data->entry.polarity = data->polarity = info->ioapic_polarity; |
---|
| 936 | + if (info->ioapic.trigger != data->trigger) |
---|
| 937 | + mp_register_handler(irq, info->ioapic.trigger); |
---|
| 938 | + data->entry.trigger = data->trigger = info->ioapic.trigger; |
---|
| 939 | + data->entry.polarity = data->polarity = info->ioapic.polarity; |
---|
950 | 940 | } |
---|
951 | 941 | |
---|
952 | | - return data->trigger == info->ioapic_trigger && |
---|
953 | | - data->polarity == info->ioapic_polarity; |
---|
| 942 | + return data->trigger == info->ioapic.trigger && |
---|
| 943 | + data->polarity == info->ioapic.polarity; |
---|
954 | 944 | } |
---|
955 | 945 | |
---|
956 | 946 | static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi, |
---|
.. | .. |
---|
1012 | 1002 | if (!mp_check_pin_attr(irq, info)) |
---|
1013 | 1003 | return -EBUSY; |
---|
1014 | 1004 | if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic, |
---|
1015 | | - info->ioapic_pin)) |
---|
| 1005 | + info->ioapic.pin)) |
---|
1016 | 1006 | return -ENOMEM; |
---|
1017 | 1007 | } else { |
---|
1018 | 1008 | info->flags |= X86_IRQ_ALLOC_LEGACY; |
---|
.. | .. |
---|
1732 | 1722 | return false; |
---|
1733 | 1723 | } |
---|
1734 | 1724 | |
---|
1735 | | -static inline bool ioapic_irqd_mask(struct irq_data *data) |
---|
| 1725 | +static inline bool ioapic_prepare_move(struct irq_data *data) |
---|
1736 | 1726 | { |
---|
1737 | 1727 | /* If we are moving the IRQ we need to mask it */ |
---|
1738 | 1728 | if (unlikely(irqd_is_setaffinity_pending(data))) { |
---|
.. | .. |
---|
1743 | 1733 | return false; |
---|
1744 | 1734 | } |
---|
1745 | 1735 | |
---|
1746 | | -static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked) |
---|
| 1736 | +static inline void ioapic_finish_move(struct irq_data *data, bool moveit) |
---|
1747 | 1737 | { |
---|
1748 | | - if (unlikely(masked)) { |
---|
| 1738 | + if (unlikely(moveit)) { |
---|
1749 | 1739 | /* Only migrate the irq if the ack has been received. |
---|
1750 | 1740 | * |
---|
1751 | 1741 | * On rare occasions the broadcast level triggered ack gets |
---|
.. | .. |
---|
1780 | 1770 | } |
---|
1781 | 1771 | } |
---|
1782 | 1772 | #else |
---|
1783 | | -static inline bool ioapic_irqd_mask(struct irq_data *data) |
---|
| 1773 | +static inline bool ioapic_prepare_move(struct irq_data *data) |
---|
1784 | 1774 | { |
---|
1785 | 1775 | return false; |
---|
1786 | 1776 | } |
---|
1787 | | -static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked) |
---|
| 1777 | +static inline void ioapic_finish_move(struct irq_data *data, bool moveit) |
---|
1788 | 1778 | { |
---|
1789 | 1779 | } |
---|
1790 | 1780 | #endif |
---|
.. | .. |
---|
1793 | 1783 | { |
---|
1794 | 1784 | struct irq_cfg *cfg = irqd_cfg(irq_data); |
---|
1795 | 1785 | unsigned long v; |
---|
1796 | | - bool masked; |
---|
| 1786 | + bool moveit; |
---|
1797 | 1787 | int i; |
---|
1798 | 1788 | |
---|
1799 | 1789 | irq_complete_move(cfg); |
---|
1800 | | - masked = ioapic_irqd_mask(irq_data); |
---|
| 1790 | + moveit = ioapic_prepare_move(irq_data); |
---|
1801 | 1791 | |
---|
1802 | 1792 | /* |
---|
1803 | 1793 | * It appears there is an erratum which affects at least version 0x11 |
---|
.. | .. |
---|
1852 | 1842 | eoi_ioapic_pin(cfg->vector, irq_data->chip_data); |
---|
1853 | 1843 | } |
---|
1854 | 1844 | |
---|
1855 | | - ioapic_irqd_unmask(irq_data, masked); |
---|
| 1845 | + ioapic_finish_move(irq_data, moveit); |
---|
1856 | 1846 | } |
---|
1857 | 1847 | |
---|
1858 | 1848 | static void ioapic_ir_ack_level(struct irq_data *irq_data) |
---|
.. | .. |
---|
2114 | 2104 | struct irq_alloc_info info; |
---|
2115 | 2105 | |
---|
2116 | 2106 | ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 0, 0); |
---|
2117 | | - info.ioapic_id = mpc_ioapic_id(ioapic); |
---|
2118 | | - info.ioapic_pin = pin; |
---|
| 2107 | + info.devid = mpc_ioapic_id(ioapic); |
---|
| 2108 | + info.ioapic.pin = pin; |
---|
2119 | 2109 | mutex_lock(&ioapic_mutex); |
---|
2120 | 2110 | irq = alloc_isa_irq_from_domain(domain, 0, ioapic, pin, &info); |
---|
2121 | 2111 | mutex_unlock(&ioapic_mutex); |
---|
.. | .. |
---|
2141 | 2131 | int apic1, pin1, apic2, pin2; |
---|
2142 | 2132 | unsigned long flags; |
---|
2143 | 2133 | int no_pin1 = 0; |
---|
| 2134 | + |
---|
| 2135 | + if (!global_clock_event) |
---|
| 2136 | + return; |
---|
2144 | 2137 | |
---|
2145 | 2138 | local_irq_save(flags); |
---|
2146 | 2139 | |
---|
.. | .. |
---|
2316 | 2309 | return 0; |
---|
2317 | 2310 | |
---|
2318 | 2311 | init_irq_alloc_info(&info, NULL); |
---|
2319 | | - info.type = X86_IRQ_ALLOC_TYPE_IOAPIC; |
---|
2320 | | - info.ioapic_id = mpc_ioapic_id(ioapic); |
---|
2321 | | - parent = irq_remapping_get_ir_irq_domain(&info); |
---|
| 2312 | + info.type = X86_IRQ_ALLOC_TYPE_IOAPIC_GET_PARENT; |
---|
| 2313 | + info.devid = mpc_ioapic_id(ioapic); |
---|
| 2314 | + parent = irq_remapping_get_irq_domain(&info); |
---|
2322 | 2315 | if (!parent) |
---|
2323 | 2316 | parent = x86_vector_domain; |
---|
2324 | 2317 | else |
---|
.. | .. |
---|
2449 | 2442 | |
---|
2450 | 2443 | unsigned int arch_dynirq_lower_bound(unsigned int from) |
---|
2451 | 2444 | { |
---|
| 2445 | + unsigned int ret; |
---|
| 2446 | + |
---|
2452 | 2447 | /* |
---|
2453 | 2448 | * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use |
---|
2454 | 2449 | * gsi_top if ioapic_dynirq_base hasn't been initialized yet. |
---|
2455 | 2450 | */ |
---|
2456 | | - if (!ioapic_initialized) |
---|
2457 | | - return gsi_top; |
---|
| 2451 | + ret = ioapic_dynirq_base ? : gsi_top; |
---|
| 2452 | + |
---|
2458 | 2453 | /* |
---|
2459 | | - * For DT enabled machines ioapic_dynirq_base is irrelevant and not |
---|
2460 | | - * updated. So simply return @from if ioapic_dynirq_base == 0. |
---|
| 2454 | + * For DT enabled machines ioapic_dynirq_base is irrelevant and |
---|
| 2455 | + * always 0. gsi_top can be 0 if there is no IO/APIC registered. |
---|
| 2456 | + * 0 is an invalid interrupt number for dynamic allocations. Return |
---|
| 2457 | + * @from instead. |
---|
2461 | 2458 | */ |
---|
2462 | | - return ioapic_dynirq_base ? : from; |
---|
| 2459 | + return ret ? : from; |
---|
2463 | 2460 | } |
---|
2464 | 2461 | |
---|
2465 | 2462 | #ifdef CONFIG_X86_32 |
---|
.. | .. |
---|
2651 | 2648 | n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource); |
---|
2652 | 2649 | n *= nr_ioapics; |
---|
2653 | 2650 | |
---|
2654 | | - mem = alloc_bootmem(n); |
---|
| 2651 | + mem = memblock_alloc(n, SMP_CACHE_BYTES); |
---|
| 2652 | + if (!mem) |
---|
| 2653 | + panic("%s: Failed to allocate %lu bytes\n", __func__, n); |
---|
2655 | 2654 | res = (void *)mem; |
---|
2656 | 2655 | |
---|
2657 | 2656 | mem += sizeof(struct resource) * nr_ioapics; |
---|
.. | .. |
---|
2694 | 2693 | #ifdef CONFIG_X86_32 |
---|
2695 | 2694 | fake_ioapic_page: |
---|
2696 | 2695 | #endif |
---|
2697 | | - ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); |
---|
| 2696 | + ioapic_phys = (unsigned long)memblock_alloc(PAGE_SIZE, |
---|
| 2697 | + PAGE_SIZE); |
---|
| 2698 | + if (!ioapic_phys) |
---|
| 2699 | + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", |
---|
| 2700 | + __func__, PAGE_SIZE, PAGE_SIZE); |
---|
2698 | 2701 | ioapic_phys = __pa(ioapic_phys); |
---|
2699 | 2702 | } |
---|
2700 | 2703 | set_fixmap_nocache(idx, ioapic_phys); |
---|
.. | .. |
---|
2946 | 2949 | static void mp_irqdomain_get_attr(u32 gsi, struct mp_chip_data *data, |
---|
2947 | 2950 | struct irq_alloc_info *info) |
---|
2948 | 2951 | { |
---|
2949 | | - if (info && info->ioapic_valid) { |
---|
2950 | | - data->trigger = info->ioapic_trigger; |
---|
2951 | | - data->polarity = info->ioapic_polarity; |
---|
| 2952 | + if (info && info->ioapic.valid) { |
---|
| 2953 | + data->trigger = info->ioapic.trigger; |
---|
| 2954 | + data->polarity = info->ioapic.polarity; |
---|
2952 | 2955 | } else if (acpi_get_override_irq(gsi, &data->trigger, |
---|
2953 | 2956 | &data->polarity) < 0) { |
---|
2954 | 2957 | /* PCI interrupts are always active low level triggered. */ |
---|
.. | .. |
---|
2994 | 2997 | return -EINVAL; |
---|
2995 | 2998 | |
---|
2996 | 2999 | ioapic = mp_irqdomain_ioapic_idx(domain); |
---|
2997 | | - pin = info->ioapic_pin; |
---|
| 3000 | + pin = info->ioapic.pin; |
---|
2998 | 3001 | if (irq_find_mapping(domain, (irq_hw_number_t)pin) > 0) |
---|
2999 | 3002 | return -EEXIST; |
---|
3000 | 3003 | |
---|
.. | .. |
---|
3002 | 3005 | if (!data) |
---|
3003 | 3006 | return -ENOMEM; |
---|
3004 | 3007 | |
---|
3005 | | - info->ioapic_entry = &data->entry; |
---|
| 3008 | + info->ioapic.entry = &data->entry; |
---|
3006 | 3009 | ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); |
---|
3007 | 3010 | if (ret < 0) { |
---|
3008 | 3011 | kfree(data); |
---|
.. | .. |
---|
3010 | 3013 | } |
---|
3011 | 3014 | |
---|
3012 | 3015 | INIT_LIST_HEAD(&data->irq_2_pin); |
---|
3013 | | - irq_data->hwirq = info->ioapic_pin; |
---|
| 3016 | + irq_data->hwirq = info->ioapic.pin; |
---|
3014 | 3017 | irq_data->chip = (domain->parent == x86_vector_domain) ? |
---|
3015 | 3018 | &ioapic_chip : &ioapic_ir_chip; |
---|
3016 | 3019 | irq_data->chip_data = data; |
---|
.. | .. |
---|
3020 | 3023 | add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); |
---|
3021 | 3024 | |
---|
3022 | 3025 | local_irq_save(flags); |
---|
3023 | | - if (info->ioapic_entry) |
---|
3024 | | - mp_setup_entry(cfg, data, info->ioapic_entry); |
---|
| 3026 | + if (info->ioapic.entry) |
---|
| 3027 | + mp_setup_entry(cfg, data, info->ioapic.entry); |
---|
3025 | 3028 | mp_register_handler(virq, data->trigger); |
---|
3026 | 3029 | if (virq < nr_legacy_irqs()) |
---|
3027 | 3030 | legacy_pic->mask(virq); |
---|