| .. | .. |
|---|
| 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); |
|---|