| .. | .. |
|---|
| 78 | 78 | #define for_each_irq_pin(entry, head) \ |
|---|
| 79 | 79 | list_for_each_entry(entry, &head, list) |
|---|
| 80 | 80 | |
|---|
| 81 | | -static DEFINE_RAW_SPINLOCK(ioapic_lock); |
|---|
| 81 | +static DEFINE_HARD_SPINLOCK(ioapic_lock); |
|---|
| 82 | 82 | static DEFINE_MUTEX(ioapic_mutex); |
|---|
| 83 | 83 | static unsigned int ioapic_dynirq_base; |
|---|
| 84 | 84 | static int ioapic_initialized; |
|---|
| .. | .. |
|---|
| 1634 | 1634 | return 1; |
|---|
| 1635 | 1635 | |
|---|
| 1636 | 1636 | local_save_flags(flags); |
|---|
| 1637 | | - local_irq_enable(); |
|---|
| 1637 | + local_irq_enable_full(); |
|---|
| 1638 | 1638 | |
|---|
| 1639 | 1639 | if (boot_cpu_has(X86_FEATURE_TSC)) |
|---|
| 1640 | 1640 | delay_with_tsc(); |
|---|
| .. | .. |
|---|
| 1642 | 1642 | delay_without_tsc(); |
|---|
| 1643 | 1643 | |
|---|
| 1644 | 1644 | local_irq_restore(flags); |
|---|
| 1645 | + if (raw_irqs_disabled_flags(flags)) |
|---|
| 1646 | + hard_local_irq_disable(); |
|---|
| 1645 | 1647 | |
|---|
| 1646 | 1648 | /* |
|---|
| 1647 | 1649 | * Expect a few ticks at least, to be sure some possible |
|---|
| .. | .. |
|---|
| 1722 | 1724 | return false; |
|---|
| 1723 | 1725 | } |
|---|
| 1724 | 1726 | |
|---|
| 1727 | +static inline void do_prepare_move(struct irq_data *data) |
|---|
| 1728 | +{ |
|---|
| 1729 | + if (!irqd_irq_masked(data)) |
|---|
| 1730 | + mask_ioapic_irq(data); |
|---|
| 1731 | +} |
|---|
| 1732 | + |
|---|
| 1733 | +#ifdef CONFIG_IRQ_PIPELINE |
|---|
| 1734 | + |
|---|
| 1735 | +static inline void ioapic_finish_move(struct irq_data *data, bool moveit); |
|---|
| 1736 | + |
|---|
| 1737 | +static void ioapic_deferred_irq_move(struct irq_work *work) |
|---|
| 1738 | +{ |
|---|
| 1739 | + struct irq_data *data; |
|---|
| 1740 | + struct irq_desc *desc; |
|---|
| 1741 | + unsigned long flags; |
|---|
| 1742 | + |
|---|
| 1743 | + data = container_of(work, struct irq_data, move_work); |
|---|
| 1744 | + desc = irq_data_to_desc(data); |
|---|
| 1745 | + raw_spin_lock_irqsave(&desc->lock, flags); |
|---|
| 1746 | + do_prepare_move(data); |
|---|
| 1747 | + ioapic_finish_move(data, true); |
|---|
| 1748 | + raw_spin_unlock_irqrestore(&desc->lock, flags); |
|---|
| 1749 | +} |
|---|
| 1750 | + |
|---|
| 1751 | +static inline bool __ioapic_prepare_move(struct irq_data *data) |
|---|
| 1752 | +{ |
|---|
| 1753 | + init_irq_work(&data->move_work, ioapic_deferred_irq_move); |
|---|
| 1754 | + irq_work_queue(&data->move_work); |
|---|
| 1755 | + |
|---|
| 1756 | + return false; /* Postpone ioapic_finish_move(). */ |
|---|
| 1757 | +} |
|---|
| 1758 | + |
|---|
| 1759 | +#else /* !CONFIG_IRQ_PIPELINE */ |
|---|
| 1760 | + |
|---|
| 1761 | +static inline bool __ioapic_prepare_move(struct irq_data *data) |
|---|
| 1762 | +{ |
|---|
| 1763 | + do_prepare_move(data); |
|---|
| 1764 | + |
|---|
| 1765 | + return true; |
|---|
| 1766 | +} |
|---|
| 1767 | + |
|---|
| 1768 | +#endif |
|---|
| 1769 | + |
|---|
| 1725 | 1770 | static inline bool ioapic_prepare_move(struct irq_data *data) |
|---|
| 1726 | 1771 | { |
|---|
| 1727 | 1772 | /* If we are moving the IRQ we need to mask it */ |
|---|
| 1728 | | - if (unlikely(irqd_is_setaffinity_pending(data))) { |
|---|
| 1729 | | - if (!irqd_irq_masked(data)) |
|---|
| 1730 | | - mask_ioapic_irq(data); |
|---|
| 1731 | | - return true; |
|---|
| 1732 | | - } |
|---|
| 1773 | + if (irqd_is_setaffinity_pending(data) && |
|---|
| 1774 | + !irqd_is_setaffinity_blocked(data)) |
|---|
| 1775 | + return __ioapic_prepare_move(data); |
|---|
| 1776 | + |
|---|
| 1733 | 1777 | return false; |
|---|
| 1734 | 1778 | } |
|---|
| 1735 | 1779 | |
|---|
| .. | .. |
|---|
| 1828 | 1872 | * We must acknowledge the irq before we move it or the acknowledge will |
|---|
| 1829 | 1873 | * not propagate properly. |
|---|
| 1830 | 1874 | */ |
|---|
| 1831 | | - ack_APIC_irq(); |
|---|
| 1875 | + __ack_APIC_irq(); |
|---|
| 1832 | 1876 | |
|---|
| 1833 | 1877 | /* |
|---|
| 1834 | 1878 | * Tail end of clearing remote IRR bit (either by delivering the EOI |
|---|
| .. | .. |
|---|
| 1949 | 1993 | .irq_retrigger = irq_chip_retrigger_hierarchy, |
|---|
| 1950 | 1994 | .irq_get_irqchip_state = ioapic_irq_get_chip_state, |
|---|
| 1951 | 1995 | .flags = IRQCHIP_SKIP_SET_WAKE | |
|---|
| 1952 | | - IRQCHIP_AFFINITY_PRE_STARTUP, |
|---|
| 1996 | + IRQCHIP_AFFINITY_PRE_STARTUP | |
|---|
| 1997 | + IRQCHIP_PIPELINE_SAFE, |
|---|
| 1953 | 1998 | }; |
|---|
| 1954 | 1999 | |
|---|
| 1955 | 2000 | static struct irq_chip ioapic_ir_chip __read_mostly = { |
|---|
| .. | .. |
|---|
| 1963 | 2008 | .irq_retrigger = irq_chip_retrigger_hierarchy, |
|---|
| 1964 | 2009 | .irq_get_irqchip_state = ioapic_irq_get_chip_state, |
|---|
| 1965 | 2010 | .flags = IRQCHIP_SKIP_SET_WAKE | |
|---|
| 1966 | | - IRQCHIP_AFFINITY_PRE_STARTUP, |
|---|
| 2011 | + IRQCHIP_AFFINITY_PRE_STARTUP | |
|---|
| 2012 | + IRQCHIP_PIPELINE_SAFE, |
|---|
| 1967 | 2013 | }; |
|---|
| 1968 | 2014 | |
|---|
| 1969 | 2015 | static inline void init_IO_APIC_traps(void) |
|---|
| .. | .. |
|---|
| 2010 | 2056 | |
|---|
| 2011 | 2057 | static void ack_lapic_irq(struct irq_data *data) |
|---|
| 2012 | 2058 | { |
|---|
| 2013 | | - ack_APIC_irq(); |
|---|
| 2059 | + __ack_APIC_irq(); |
|---|
| 2014 | 2060 | } |
|---|
| 2015 | 2061 | |
|---|
| 2016 | 2062 | static struct irq_chip lapic_chip __read_mostly = { |
|---|
| .. | .. |
|---|
| 2018 | 2064 | .irq_mask = mask_lapic_irq, |
|---|
| 2019 | 2065 | .irq_unmask = unmask_lapic_irq, |
|---|
| 2020 | 2066 | .irq_ack = ack_lapic_irq, |
|---|
| 2067 | + .flags = IRQCHIP_PIPELINE_SAFE, |
|---|
| 2021 | 2068 | }; |
|---|
| 2022 | 2069 | |
|---|
| 2023 | 2070 | static void lapic_register_intr(int irq) |
|---|
| .. | .. |
|---|
| 2135 | 2182 | if (!global_clock_event) |
|---|
| 2136 | 2183 | return; |
|---|
| 2137 | 2184 | |
|---|
| 2138 | | - local_irq_save(flags); |
|---|
| 2185 | + local_irq_save_full(flags); |
|---|
| 2139 | 2186 | |
|---|
| 2140 | 2187 | /* |
|---|
| 2141 | 2188 | * get/set the timer IRQ vector: |
|---|
| .. | .. |
|---|
| 2203 | 2250 | goto out; |
|---|
| 2204 | 2251 | } |
|---|
| 2205 | 2252 | panic_if_irq_remap("timer doesn't work through Interrupt-remapped IO-APIC"); |
|---|
| 2206 | | - local_irq_disable(); |
|---|
| 2253 | + local_irq_disable_full(); |
|---|
| 2207 | 2254 | clear_IO_APIC_pin(apic1, pin1); |
|---|
| 2208 | 2255 | if (!no_pin1) |
|---|
| 2209 | 2256 | apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: " |
|---|
| .. | .. |
|---|
| 2227 | 2274 | /* |
|---|
| 2228 | 2275 | * Cleanup, just in case ... |
|---|
| 2229 | 2276 | */ |
|---|
| 2230 | | - local_irq_disable(); |
|---|
| 2277 | + local_irq_disable_full(); |
|---|
| 2231 | 2278 | legacy_pic->mask(0); |
|---|
| 2232 | 2279 | clear_IO_APIC_pin(apic2, pin2); |
|---|
| 2233 | 2280 | apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); |
|---|
| .. | .. |
|---|
| 2244 | 2291 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); |
|---|
| 2245 | 2292 | goto out; |
|---|
| 2246 | 2293 | } |
|---|
| 2247 | | - local_irq_disable(); |
|---|
| 2294 | + local_irq_disable_full(); |
|---|
| 2248 | 2295 | legacy_pic->mask(0); |
|---|
| 2249 | 2296 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); |
|---|
| 2250 | 2297 | apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); |
|---|
| .. | .. |
|---|
| 2263 | 2310 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); |
|---|
| 2264 | 2311 | goto out; |
|---|
| 2265 | 2312 | } |
|---|
| 2266 | | - local_irq_disable(); |
|---|
| 2313 | + local_irq_disable_full(); |
|---|
| 2267 | 2314 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); |
|---|
| 2268 | 2315 | if (apic_is_x2apic_enabled()) |
|---|
| 2269 | 2316 | apic_printk(APIC_QUIET, KERN_INFO |
|---|
| .. | .. |
|---|
| 2272 | 2319 | panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " |
|---|
| 2273 | 2320 | "report. Then try booting with the 'noapic' option.\n"); |
|---|
| 2274 | 2321 | out: |
|---|
| 2275 | | - local_irq_restore(flags); |
|---|
| 2322 | + local_irq_restore_full(flags); |
|---|
| 2276 | 2323 | } |
|---|
| 2277 | 2324 | |
|---|
| 2278 | 2325 | /* |
|---|
| .. | .. |
|---|
| 3018 | 3065 | cfg = irqd_cfg(irq_data); |
|---|
| 3019 | 3066 | add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); |
|---|
| 3020 | 3067 | |
|---|
| 3021 | | - local_irq_save(flags); |
|---|
| 3068 | + local_irq_save_full(flags); |
|---|
| 3022 | 3069 | if (info->ioapic.entry) |
|---|
| 3023 | 3070 | mp_setup_entry(cfg, data, info->ioapic.entry); |
|---|
| 3024 | 3071 | mp_register_handler(virq, data->trigger); |
|---|
| 3025 | 3072 | if (virq < nr_legacy_irqs()) |
|---|
| 3026 | 3073 | legacy_pic->mask(virq); |
|---|
| 3027 | | - local_irq_restore(flags); |
|---|
| 3074 | + local_irq_restore_full(flags); |
|---|
| 3028 | 3075 | |
|---|
| 3029 | 3076 | apic_printk(APIC_VERBOSE, KERN_DEBUG |
|---|
| 3030 | 3077 | "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n", |
|---|