Module: xenomai-3 Branch: wip/drivers Commit: 2eae1185f359e6da8746333077d38e194352d805 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=2eae1185f359e6da8746333077d38e194352d805
Author: Philippe Gerum <r...@xenomai.org> Date: Fri Sep 9 18:55:43 2016 +0200 cobalt/arm: upgrade I-pipe support --- ...arm-9.patch => ipipe-core-3.18.20-arm-11.patch} | 342 +++++++++++++- ...8-arm-4.patch => ipipe-core-4.1.18-arm-8.patch} | 487 +++++++++++++++----- 2 files changed, 704 insertions(+), 125 deletions(-) diff --git a/kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-9.patch b/kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-11.patch similarity index 98% rename from kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-9.patch rename to kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-11.patch index d594401..efe7c8f 100644 --- a/kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-9.patch +++ b/kernel/cobalt/arch/arm/patches/ipipe-core-3.18.20-arm-11.patch @@ -1,5 +1,5 @@ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 89c4b5c..46ec8f8 100644 +index 89c4b5c..6b13805 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -33,8 +33,8 @@ config ARM @@ -80,6 +80,14 @@ index 89c4b5c..46ec8f8 100644 source kernel/Kconfig.preempt config HZ_FIXED +@@ -1741,6 +1760,7 @@ config ALIGNMENT_TRAP + config UACCESS_WITH_MEMCPY + bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()" + depends on MMU ++ depends on !IPIPE + default y if CPU_FEROCEON + help + Implement faster copy_to_user and clear_user methods for CPU diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index bd245d3..65f2238 100644 --- a/arch/arm/boot/compressed/decompress.c @@ -1653,7 +1661,7 @@ index bb28af7..780ca50 100644 static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) diff --git a/arch/arm/include/asm/ipipe.h b/arch/arm/include/asm/ipipe.h new file mode 100644 -index 0000000..d1c125d +index 0000000..5ec5eff --- /dev/null +++ b/arch/arm/include/asm/ipipe.h @@ -0,0 +1,272 @@ @@ -1701,7 +1709,7 @@ index 0000000..d1c125d +#include <linux/jump_label.h> +#include <linux/ipipe_trace.h> + -+#define IPIPE_CORE_RELEASE 9 ++#define IPIPE_CORE_RELEASE 11 + +struct ipipe_domain; + @@ -4301,10 +4309,10 @@ index 0000000..8024a79 +EXPORT_SYMBOL_GPL(cpu_architecture); diff --git a/arch/arm/kernel/ipipe_tsc.c b/arch/arm/kernel/ipipe_tsc.c new file mode 100644 -index 0000000..414ada5 +index 0000000..6bcabb3 --- /dev/null +++ b/arch/arm/kernel/ipipe_tsc.c -@@ -0,0 +1,203 @@ +@@ -0,0 +1,207 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -4378,6 +4386,10 @@ index 0000000..414ada5 + tsc_addr = &__ipipe_tsc_addr; +#endif + registered = ipipe_tsc_value != NULL; ++ ++ if (registered && info->freq < tsc_info.freq) ++ return; ++ + ipipe_tsc_value = (struct ipipe_tsc_value_t *)tsc_area; + vector_tsc_value = (struct ipipe_tsc_value_t *)__ipipe_tsc_area; + @@ -7090,7 +7102,7 @@ index 5211f62..c0a8610 100644 platform_device_register_simple("imx31-audmux", 0, imx25_audmux_res, ARRAY_SIZE(imx25_audmux_res)); diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c -index 7d82a5a..9bbd0f4 100644 +index 7d82a5a5..9bbd0f4 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -81,6 +81,10 @@ static const struct resource imx27_audmux_res[] __initconst = { @@ -12308,6 +12320,85 @@ index 9f06825..1087ed1 100644 irq_find_mapping(d->irq_domain, d->chip.base + bit)); } +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index a93ddbc..7c74176 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -295,10 +295,11 @@ static void mvebu_gpio_irq_ack(struct irq_data *d) + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; + u32 mask = ~(1 << (d->irq - gc->irq_base)); ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip)); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void mvebu_gpio_edge_irq_mask(struct irq_data *d) +@@ -307,12 +308,13 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d) + struct mvebu_gpio_chip *mvchip = gc->private; + struct irq_chip_type *ct = irq_data_get_chip_type(d); + u32 mask = 1 << (d->irq - gc->irq_base); ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + ct->mask_cache_priv &= ~mask; + + writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) +@@ -322,11 +324,12 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + u32 mask = 1 << (d->irq - gc->irq_base); ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + ct->mask_cache_priv |= mask; + writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void mvebu_gpio_level_irq_mask(struct irq_data *d) +@@ -336,11 +339,12 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d) + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + u32 mask = 1 << (d->irq - gc->irq_base); ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + ct->mask_cache_priv &= ~mask; + writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void mvebu_gpio_level_irq_unmask(struct irq_data *d) +@@ -350,11 +354,12 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + u32 mask = 1 << (d->irq - gc->irq_base); ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + ct->mask_cache_priv |= mask; + writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + /***************************************************************************** diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index f4e54a9..8818bc3 100644 --- a/drivers/gpio/gpio-mxc.c @@ -13212,6 +13303,86 @@ index a11aae8..ec094e1 100644 gc->chip_types[0].chip.irq_retrigger = aic5_retrigger; gc->chip_types[0].chip.irq_set_type = aic5_set_type; gc->chip_types[0].chip.irq_suspend = aic5_suspend; +diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c +index 5fb38a2..b2afa17 100644 +--- a/drivers/irqchip/irq-bcm7120-l2.c ++++ b/drivers/irqchip/irq-bcm7120-l2.c +@@ -71,27 +71,29 @@ static void bcm7120_l2_intc_suspend(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct bcm7120_l2_intc_data *b = gc->private; ++ unsigned long flags; + u32 reg; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + /* Save the current mask and the interrupt forward mask */ + b->saved_mask = __raw_readl(b->base) | b->irq_fwd_mask; + if (b->can_wake) { + reg = b->saved_mask | gc->wake_active; + __raw_writel(reg, b->base); + } +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void bcm7120_l2_intc_resume(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct bcm7120_l2_intc_data *b = gc->private; ++ unsigned long flags; + + /* Restore the saved mask */ +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + __raw_writel(b->saved_mask, b->base); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static int bcm7120_l2_intc_init_one(struct device_node *dn, +diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c +index 14691a4..31db906 100644 +--- a/drivers/irqchip/irq-brcmstb-l2.c ++++ b/drivers/irqchip/irq-brcmstb-l2.c +@@ -82,8 +82,9 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_l2_intc_data *b = gc->private; ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + /* Save the current mask */ + b->saved_mask = __raw_readl(b->base + CPU_MASK_STATUS); + +@@ -92,22 +93,23 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d) + __raw_writel(~gc->wake_active, b->base + CPU_MASK_SET); + __raw_writel(gc->wake_active, b->base + CPU_MASK_CLEAR); + } +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + static void brcmstb_l2_intc_resume(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_l2_intc_data *b = gc->private; ++ unsigned long flags; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + /* Clear unmasked non-wakeup interrupts */ + __raw_writel(~b->saved_mask & ~gc->wake_active, b->base + CPU_CLEAR); + + /* Restore the saved mask */ + __raw_writel(b->saved_mask, b->base + CPU_MASK_SET); + __raw_writel(~b->saved_mask, b->base + CPU_MASK_CLEAR); +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + } + + int __init brcmstb_l2_intc_of_init(struct device_node *np, diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 38493ff..fbc428b 100644 --- a/drivers/irqchip/irq-gic.c @@ -13645,6 +13816,40 @@ index c8d373f..1f81463 100644 } chained_irq_exit(chip, desc); +diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c +index eb9b59e..7cda6c6 100644 +--- a/drivers/irqchip/irq-sunxi-nmi.c ++++ b/drivers/irqchip/irq-sunxi-nmi.c +@@ -76,9 +76,10 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type) + u32 src_type_reg; + u32 ctrl_off = ct->regs.type; + unsigned int src_type; ++ unsigned long flags; + unsigned int i; + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + + switch (flow_type & IRQF_TRIGGER_MASK) { + case IRQ_TYPE_EDGE_FALLING: +@@ -95,7 +96,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type) + src_type = SUNXI_SRC_TYPE_LEVEL_LOW; + break; + default: +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n", + __func__, data->irq); + return -EBADR; +@@ -113,7 +114,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type) + src_type_reg |= src_type; + sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg); + +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + + return IRQ_SET_MASK_OK; + } diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 1ab4517..31d698a 100644 --- a/drivers/irqchip/irq-versatile-fpga.c @@ -13830,6 +14035,65 @@ index bbeb451..48db51f 100644 config SENSORS_APDS990X tristate "APDS990X combined als and proximity sensors" +diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c +index d6380c1..6ee894b 100644 +--- a/drivers/pinctrl/pinctrl-at91.c ++++ b/drivers/pinctrl/pinctrl-at91.c +@@ -18,6 +18,7 @@ + #include <linux/interrupt.h> + #include <linux/io.h> + #include <linux/gpio.h> ++#include <linux/ipipe.h> + #include <linux/pinctrl/machine.h> + #include <linux/pinctrl/pinconf.h> + #include <linux/pinctrl/pinctrl.h> +@@ -1615,7 +1616,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) + } + + for_each_set_bit(n, &isr, BITS_PER_LONG) { +- generic_handle_irq(irq_find_mapping( ++ ipipe_handle_demuxed_irq(irq_find_mapping( + gpio_chip->irqdomain, n)); + } + } +diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c +index 016f457..00159d1 100644 +--- a/drivers/pinctrl/pinctrl-rockchip.c ++++ b/drivers/pinctrl/pinctrl-rockchip.c +@@ -1446,6 +1446,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + u32 mask = BIT(d->hwirq); ++ unsigned long flags; + u32 polarity; + u32 level; + u32 data; +@@ -1465,7 +1466,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) + else + __irq_set_handler_locked(d->irq, handle_level_irq); + +- irq_gc_lock(gc); ++ flags = irq_gc_lock(gc); + + level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); + polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); +@@ -1506,14 +1507,14 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) + polarity &= ~mask; + break; + default: +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + return -EINVAL; + } + + writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); + writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); + +- irq_gc_unlock(gc); ++ irq_gc_unlock(gc, flags); + + return 0; + } diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c5029c1..2d68014 100644 --- a/drivers/cpuidle/Kconfig @@ -14264,6 +14528,18 @@ index abcafaa..a8440e4 100644 } ____cacheline_aligned; /* +diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h +index 662697b..6a9b6ad 100644 +--- a/include/linux/ftrace.h ++++ b/include/linux/ftrace.h +@@ -108,6 +108,7 @@ enum { + FTRACE_OPS_FL_ADDING = 1 << 9, + FTRACE_OPS_FL_REMOVING = 1 << 10, + FTRACE_OPS_FL_MODIFYING = 1 << 11, ++ FTRACE_OPS_FL_IPIPE_EXCLUSIVE = 1 << 12, + }; + + #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index cba442e..b513a46 100644 --- a/include/linux/hardirq.h @@ -20209,7 +20485,7 @@ index 0000000..143f9e6 +#endif /* CONFIG_IPIPE_HAVE_HOSTRT */ diff --git a/kernel/ipipe/tracer.c b/kernel/ipipe/tracer.c new file mode 100644 -index 0000000..da272c50 +index 0000000..8388671 --- /dev/null +++ b/kernel/ipipe/tracer.c @@ -0,0 +1,1468 @@ @@ -21547,7 +21823,7 @@ index 0000000..da272c50 + +static struct ftrace_ops ipipe_trace_ops = { + .func = ipipe_trace_function, -+ .flags = FTRACE_OPS_FL_RECURSION_SAFE, ++ .flags = FTRACE_OPS_FL_IPIPE_EXCLUSIVE, +}; + +static ssize_t __ipipe_wr_enable(struct file *file, const char __user *buffer, @@ -23108,7 +23384,7 @@ index a5da09c..6650799 100644 help This option will modify all the calls to function tracing diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index d1eff3d..2a324bc 100644 +index d1eff3d..f8b9472 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -32,6 +32,7 @@ @@ -23119,7 +23395,33 @@ index d1eff3d..2a324bc 100644 #include <trace/events/sched.h> -@@ -2298,6 +2299,9 @@ void __weak arch_ftrace_update_code(int command) +@@ -251,8 +252,17 @@ static inline void update_function_graph_func(void) { } + + static void update_ftrace_function(void) + { ++ struct ftrace_ops *ops; + ftrace_func_t func; + ++ for (ops = ftrace_ops_list; ++ ops != &ftrace_list_end; ops = ops->next) ++ if (ops->flags & FTRACE_OPS_FL_IPIPE_EXCLUSIVE) { ++ set_function_trace_op = ops; ++ func = ops->func; ++ goto set_pointers; ++ } ++ + /* + * Prepare the ftrace_ops that the arch callback will use. + * If there's only one ftrace_ops registered, the ftrace_ops_list +@@ -280,6 +290,7 @@ static void update_ftrace_function(void) + + update_function_graph_func(); + ++ set_pointers: + /* If there's no change, then do nothing more here */ + if (ftrace_trace_function == func) + return; +@@ -2298,6 +2309,9 @@ void __weak arch_ftrace_update_code(int command) static void ftrace_run_update_code(int command) { @@ -23129,7 +23431,7 @@ index d1eff3d..2a324bc 100644 int ret; ret = ftrace_arch_code_modify_prepare(); -@@ -2311,7 +2315,13 @@ static void ftrace_run_update_code(int command) +@@ -2311,7 +2325,13 @@ static void ftrace_run_update_code(int command) * is safe. The stop_machine() is the safest, but also * produces the most overhead. */ @@ -23143,7 +23445,7 @@ index d1eff3d..2a324bc 100644 ret = ftrace_arch_code_modify_post_process(); FTRACE_WARN_ON(ret); -@@ -4621,10 +4631,10 @@ static int ftrace_process_locs(struct module *mod, +@@ -4621,10 +4641,10 @@ static int ftrace_process_locs(struct module *mod, * reason to cause large interrupt latencies while we do it. */ if (!mod) @@ -23156,7 +23458,7 @@ index d1eff3d..2a324bc 100644 ret = 0; out: mutex_unlock(&ftrace_lock); -@@ -4723,9 +4733,11 @@ void __init ftrace_init(void) +@@ -4723,9 +4743,11 @@ void __init ftrace_init(void) unsigned long count, flags; int ret; @@ -23170,7 +23472,7 @@ index d1eff3d..2a324bc 100644 if (ret) goto failed; -@@ -4891,7 +4903,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, +@@ -4891,7 +4913,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, } } while_for_each_ftrace_op(op); out: @@ -23536,24 +23838,22 @@ index 0c9216c..00a9a30 100644 return err; } diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c -index 1afec32..5803111 100644 +index 1afec32..f7c1a2a 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c -@@ -12,10 +12,13 @@ notrace static unsigned int check_preemption_disabled(const char *what1, +@@ -12,6 +12,12 @@ notrace static unsigned int check_preemption_disabled(const char *what1, { int this_cpu = raw_smp_processor_id(); ++ if (hard_irqs_disabled()) ++ goto out; ++ + if (!ipipe_root_p) + goto out; + if (likely(preempt_count())) goto out; -- if (irqs_disabled()) -+ if (irqs_disabled() || hard_irqs_disabled()) - goto out; - - /* diff --git a/mm/memory.c b/mm/memory.c index 90fb265..8a1fd79 100644 --- a/mm/memory.c diff --git a/kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-4.patch b/kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-8.patch similarity index 98% rename from kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-4.patch rename to kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-8.patch index f8e3c73..cfdbcc6 100644 --- a/kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-4.patch +++ b/kernel/cobalt/arch/arm/patches/ipipe-core-4.1.18-arm-8.patch @@ -1,5 +1,5 @@ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 19f4cc6..dc88360 100644 +index 19f4cc6..6bdc70c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -36,8 +36,8 @@ config ARM @@ -60,6 +60,14 @@ index 19f4cc6..dc88360 100644 source kernel/Kconfig.preempt config HZ_FIXED +@@ -1718,6 +1731,7 @@ config ALIGNMENT_TRAP + config UACCESS_WITH_MEMCPY + bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()" + depends on MMU ++ depends on !IPIPE + default y if CPU_FEROCEON + help + Implement faster copy_to_user and clear_user methods for CPU diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index a0765e7..381ad50 100644 --- a/arch/arm/boot/compressed/decompress.c @@ -1635,10 +1643,10 @@ index bb28af7..780ca50 100644 static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) diff --git a/arch/arm/include/asm/ipipe.h b/arch/arm/include/asm/ipipe.h new file mode 100644 -index 0000000..df05570 +index 0000000..ebda70c --- /dev/null +++ b/arch/arm/include/asm/ipipe.h -@@ -0,0 +1,297 @@ +@@ -0,0 +1,298 @@ +/* -*- linux-c -*- + * arch/arm/include/asm/ipipe.h + * @@ -1685,7 +1693,7 @@ index 0000000..df05570 +#include <linux/jump_label.h> +#include <linux/ipipe_trace.h> + -+#define IPIPE_CORE_RELEASE 4 ++#define IPIPE_CORE_RELEASE 8 + +struct ipipe_domain; +struct timekeeper; @@ -1720,6 +1728,7 @@ index 0000000..df05570 + unsigned long long *tsc; /* 64 bits tsc value. */ + } dec; + } u; ++ unsigned int (*refresh_freq)(void); +}; + +struct ipipe_arch_sysinfo { @@ -4277,17 +4286,17 @@ index 0000000..ffe02fe +EXPORT_SYMBOL_GPL(cpu_architecture); diff --git a/arch/arm/kernel/ipipe_tsc.c b/arch/arm/kernel/ipipe_tsc.c new file mode 100644 -index 0000000..aa9571e +index 0000000..6f9cff8 --- /dev/null +++ b/arch/arm/kernel/ipipe_tsc.c -@@ -0,0 +1,214 @@ +@@ -0,0 +1,265 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <linux/clocksource.h> +#include <linux/ipipe_tickdev.h> -+ ++#include <linux/cpufreq.h> +#include <linux/ipipe.h> + +#include <asm/cacheflush.h> @@ -4495,6 +4504,57 @@ index 0000000..aa9571e +{ +} +#endif ++ ++#ifdef CONFIG_CPU_FREQ ++ ++static __init void update_timer_freq(void *data) ++{ ++ unsigned int hrclock_freq = *(unsigned int *)data; ++ ++ __ipipe_timer_refresh_freq(hrclock_freq); ++} ++ ++static __init int cpufreq_transition_handler(struct notifier_block *nb, ++ unsigned long state, void *data) ++{ ++ struct cpufreq_freqs *freqs = data; ++ unsigned int freq; ++ ++ if (state == CPUFREQ_POSTCHANGE && tsc_info.refresh_freq) { ++ freq = tsc_info.refresh_freq(); ++ if (freqs->cpu == 0) { ++ tsc_info.freq = freq; ++ __ipipe_tsc_register(&tsc_info); ++ __ipipe_report_clockfreq_update(freq); ++ } ++ smp_call_function_single(freqs->cpu, update_timer_freq, ++ &freq, 1); ++ } ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block __initdata cpufreq_nb = { ++ .notifier_call = cpufreq_transition_handler, ++}; ++ ++static __init int register_cpufreq_notifier(void) ++{ ++ cpufreq_register_notifier(&cpufreq_nb, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ return 0; ++} ++core_initcall(register_cpufreq_notifier); ++ ++static __init int unregister_cpufreq_notifier(void) ++{ ++ cpufreq_unregister_notifier(&cpufreq_nb, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ return 0; ++} ++late_initcall(unregister_cpufreq_notifier); ++ ++#endif /* CONFIG_CPUFREQ */ diff --git a/arch/arm/kernel/ipipe_tsc_asm.S b/arch/arm/kernel/ipipe_tsc_asm.S new file mode 100644 index 0000000..3f0999d @@ -5211,7 +5271,7 @@ index f11d825..68981b8 100644 default: diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c -index 172c6a05..6d41146 100644 +index 172c6a05..64c3c5c 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -20,14 +20,19 @@ @@ -5273,7 +5333,21 @@ index 172c6a05..6d41146 100644 static void twd_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { -@@ -232,7 +269,11 @@ static irqreturn_t twd_handler(int irq, void *dev_id) +@@ -189,6 +226,13 @@ core_initcall(twd_cpufreq_init); + + #endif + ++#ifdef CONFIG_IPIPE ++static unsigned int twd_refresh_freq(void) ++{ ++ return clk_get_rate(twd_clk); ++} ++#endif ++ + static void twd_calibrate_rate(void) + { + unsigned long count; +@@ -232,7 +276,11 @@ static irqreturn_t twd_handler(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; @@ -5285,7 +5359,7 @@ index 172c6a05..6d41146 100644 evt->event_handler(evt); return IRQ_HANDLED; } -@@ -299,6 +340,17 @@ static void twd_timer_setup(void) +@@ -299,6 +347,18 @@ static void twd_timer_setup(void) clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; @@ -5298,12 +5372,13 @@ index 172c6a05..6d41146 100644 + clk->ipipe_timer->irq = clk->irq; + clk->ipipe_timer->ack = twd_ack; + clk->ipipe_timer->min_delay_ticks = 0xf; ++ clk->ipipe_timer->refresh_freq = twd_refresh_freq; +#endif + clk->cpumask = cpumask_of(cpu); clockevents_config_and_register(clk, twd_timer_rate, -@@ -357,6 +409,10 @@ static int __init twd_local_timer_common_register(struct device_node *np) +@@ -357,6 +417,10 @@ static int __init twd_local_timer_common_register(struct device_node *np) else late_time_init = twd_timer_setup; @@ -5314,7 +5389,7 @@ index 172c6a05..6d41146 100644 return 0; out_irq: -@@ -380,6 +436,7 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt) +@@ -380,6 +444,7 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt) if (!twd_base) return -ENOMEM; @@ -5322,7 +5397,7 @@ index 172c6a05..6d41146 100644 return twd_local_timer_common_register(NULL); } -@@ -403,6 +460,7 @@ static void __init twd_local_timer_of_register(struct device_node *np) +@@ -403,6 +468,7 @@ static void __init twd_local_timer_of_register(struct device_node *np) goto out; } @@ -6569,7 +6644,7 @@ index e065fed..64c026b 100644 #include <asm/mach/map.h> diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c -index 7d82a5a..9bbd0f4 100644 +index 7d82a5a5..9bbd0f4 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -81,6 +81,10 @@ static const struct resource imx27_audmux_res[] __initconst = { @@ -8992,7 +9067,7 @@ index 9769f1e..c3a4a6f 100644 set_cr(cr_no_alignment); } diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c -index e309c8f..7053f1b 100644 +index e309c8f..48b9211 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -23,6 +23,7 @@ @@ -9003,7 +9078,7 @@ index e309c8f..7053f1b 100644 #include <linux/of.h> #include <linux/of_address.h> -@@ -47,9 +48,22 @@ struct l2c_init_data { +@@ -47,9 +48,23 @@ struct l2c_init_data { #define CACHE_LINE_SIZE 32 @@ -9018,6 +9093,7 @@ index e309c8f..7053f1b 100644 +early_param("l2x0_write_allocate", l2x0_setup_wa); +#else +#define CACHE_RANGE_ATOMIC_MAX 4096UL ++static int l2x0_wa = 1; +#endif + static void __iomem *l2x0_base; @@ -9027,7 +9103,7 @@ index e309c8f..7053f1b 100644 static u32 l2x0_way_mask; /* Bitmask of active ways */ static u32 l2x0_size; static unsigned long sync_reg_offset = L2X0_CACHE_SYNC; -@@ -292,10 +306,10 @@ static void l2c220_op_way(void __iomem *base, unsigned reg) +@@ -292,10 +307,10 @@ static void l2c220_op_way(void __iomem *base, unsigned reg) static unsigned long l2c220_op_pa_range(void __iomem *reg, unsigned long start, unsigned long end, unsigned long flags) { @@ -9040,7 +9116,7 @@ index e309c8f..7053f1b 100644 while (start < blk_end) { l2c_wait_mask(reg, 1); -@@ -498,13 +512,13 @@ static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) +@@ -498,13 +513,13 @@ static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) static void l2c310_flush_range_erratum(unsigned long start, unsigned long end) { @@ -9056,24 +9132,30 @@ index e309c8f..7053f1b 100644 l2c_set_debug(base, 0x03); while (start < blk_end) { -@@ -797,6 +811,22 @@ static int __init __l2c_init(const struct l2c_init_data *data, +@@ -797,6 +812,28 @@ static int __init __l2c_init(const struct l2c_init_data *data, if (aux_val & aux_mask) pr_alert("L2C: platform provided aux values permit register corruption.\n"); + if (IS_ENABLED(CONFIG_IPIPE)) { + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { + case L2X0_CACHE_ID_PART_L310: ++ if ((cache_id & L2X0_CACHE_ID_RTL_MASK) ++ >= L310_CACHE_ID_RTL_R3P2) { ++ l2x0_wa = 1; ++ pr_alert("L2C: I-pipe: revision >= L310-r3p2 detected, forcing WA.\n"); ++ } + case L2X0_CACHE_ID_PART_L220: + if (l2x0_wa < 0) { + l2x0_wa = 0; + pr_alert("L2C: I-pipe: l2x0_write_allocate= not specified, defaults to 0 (disabled).\n"); + } -+ aux_mask &= ~L220_AUX_CTRL_FWA_MASK; -+ aux_val &= ~L220_AUX_CTRL_FWA_MASK; -+ aux_val |= (!l2x0_wa) << L220_AUX_CTRL_FWA_SHIFT; ++ if (!l2x0_wa) { ++ aux_mask &= ~L220_AUX_CTRL_FWA_MASK; ++ aux_val &= ~L220_AUX_CTRL_FWA_MASK; ++ aux_val |= 1 << L220_AUX_CTRL_FWA_SHIFT; ++ } else ++ pr_alert("L2C: I-pipe: write-allocate enabled, induces high latencies.\n"); + } -+ if (l2x0_wa) -+ pr_alert("L2C: I-pipe: write-allocate enabled, induces high latencies.\n"); + } + old_aux = aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); @@ -10925,7 +11007,7 @@ index 0aa135d..c48e8f7 100644 clocksource_register_hz(&clocksource_counter, arch_timer_rate); cyclecounter.mult = clocksource_counter.mult; diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c -index e683377..b954fc0 100644 +index e683377..d3193ec 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -24,6 +24,7 @@ @@ -10936,16 +11018,30 @@ index e683377..b954fc0 100644 #define GT_COUNTER0 0x00 #define GT_COUNTER1 0x04 -@@ -48,6 +49,7 @@ +@@ -48,6 +49,8 @@ * the units for all operations. */ static void __iomem *gt_base; +static unsigned long gt_pbase; ++static struct clk *gt_clk; static unsigned long gt_clk_rate; static int gt_ppi; static struct clock_event_device __percpu *gt_evt; -@@ -210,6 +212,20 @@ static u64 notrace gt_sched_clock_read(void) +@@ -208,8 +211,34 @@ static u64 notrace gt_sched_clock_read(void) + } + #endif ++#ifdef CONFIG_IPIPE ++ ++static unsigned int refresh_gt_freq(void) ++{ ++ gt_clk_rate = clk_get_rate(gt_clk); ++ ++ return gt_clk_rate; ++} ++ ++#endif ++ static void __init gt_clocksource_init(void) { +#ifdef CONFIG_IPIPE @@ -10959,13 +11055,14 @@ index e683377..b954fc0 100644 + .mask = 0xffffffff, + } + }, ++ .refresh_freq = refresh_gt_freq, + }; +#endif + writel(0, gt_base + GT_CONTROL); writel(0, gt_base + GT_COUNTER0); writel(0, gt_base + GT_COUNTER1); -@@ -219,6 +235,9 @@ static void __init gt_clocksource_init(void) +@@ -219,6 +248,9 @@ static void __init gt_clocksource_init(void) #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); #endif @@ -10975,18 +11072,18 @@ index e683377..b954fc0 100644 clocksource_register_hz(>_clocksource, gt_clk_rate); } -@@ -242,8 +261,9 @@ static struct notifier_block gt_cpu_nb = { +@@ -242,8 +274,8 @@ static struct notifier_block gt_cpu_nb = { static void __init global_timer_of_register(struct device_node *np) { +- struct clk *gt_clk; +- int err = 0; + int err = 0, usable_timer = 1; + struct resource res; - struct clk *gt_clk; -- int err = 0; /* * In A9 r2p0 the comparators for each processor with the global timer -@@ -253,13 +273,15 @@ static void __init global_timer_of_register(struct device_node *np) +@@ -253,13 +285,15 @@ static void __init global_timer_of_register(struct device_node *np) if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9 && (read_cpuid_id() & 0xf0000f) < 0x200000) { pr_warn("global-timer: non support for this cpu version.\n"); @@ -11007,7 +11104,7 @@ index e683377..b954fc0 100644 } gt_base = of_iomap(np, 0); -@@ -268,6 +290,11 @@ static void __init global_timer_of_register(struct device_node *np) +@@ -268,6 +302,11 @@ static void __init global_timer_of_register(struct device_node *np) return; } @@ -11019,7 +11116,7 @@ index e683377..b954fc0 100644 gt_clk = of_clk_get(np, 0); if (!IS_ERR(gt_clk)) { err = clk_prepare_enable(gt_clk); -@@ -280,30 +307,33 @@ static void __init global_timer_of_register(struct device_node *np) +@@ -280,30 +319,33 @@ static void __init global_timer_of_register(struct device_node *np) } gt_clk_rate = clk_get_rate(gt_clk); @@ -12769,6 +12866,29 @@ index d6bcc6b..f3c04de 100644 } int __init brcmstb_l2_intc_of_init(struct device_node *np, +diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c +index c12bb93..8bb1af7 100644 +--- a/drivers/irqchip/irq-crossbar.c ++++ b/drivers/irqchip/irq-crossbar.c +@@ -15,6 +15,7 @@ + #include <linux/of_address.h> + #include <linux/of_irq.h> + #include <linux/slab.h> ++#include <linux/ipipe.h> + + #include "irqchip.h" + +@@ -74,6 +75,10 @@ static struct irq_chip crossbar_chip = { + #ifdef CONFIG_SMP + .irq_set_affinity = irq_chip_set_affinity_parent, + #endif ++#ifdef CONFIG_IPIPE ++ .irq_hold = irq_chip_hold_parent, ++ .irq_release = irq_chip_release_parent, ++#endif + }; + + static int allocate_gic_irq(struct irq_domain *domain, unsigned virq, diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c index 53bb732..5ca21a2 100644 --- a/drivers/irqchip/irq-dw-apb-ictl.c @@ -13575,7 +13695,7 @@ index dee7d5f..f4b5349 100644 return 0; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c -index 13b45f2..b00fe3a 100644 +index 13b45f2..637f923 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -16,6 +16,7 @@ @@ -13590,11 +13710,10 @@ index 13b45f2..b00fe3a 100644 #define PCS_FEAT_IRQ (1 << 1) #define PCS_FEAT_PINCONF (1 << 0) struct pcs_soc_data socdata; -- raw_spinlock_t lock; +#ifdef CONFIG_IPIPE + ipipe_spinlock_t lock; +#else /* !IPIPE */ -+ raw_spinlock_t lock + raw_spinlock_t lock; +#endif /* !IPIPE */ struct mutex mutex; unsigned width; @@ -14075,6 +14194,19 @@ index 0000000..1f6e9c3 +static inline void __ipipe_init_threadinfo(struct ipipe_threadinfo *p) { } + +#endif /* !_IPIPE_THREAD_INFO_H */ +diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h +index 0e97856..b5d7e60 100644 +--- a/include/linux/basic_mmio_gpio.h ++++ b/include/linux/basic_mmio_gpio.h +@@ -50,7 +50,7 @@ struct bgpio_chip { + * Used to lock bgpio_chip->data. Also, this is needed to keep + * shadowed and real data registers writes together. + */ +- spinlock_t lock; ++ ipipe_spinlock_t lock; + + /* Shadowed data register to clear/set bits safely. */ + unsigned long data; diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 96c280b..0baa8f1 100644 --- a/include/linux/clockchips.h @@ -14127,6 +14259,18 @@ index 901555a..1ba117c 100644 int (*read)(struct console *, char *, unsigned); struct tty_driver *(*device)(struct console *, int *); void (*unblank)(void); +diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h +index 6cd8c0e..0951ab4 100644 +--- a/include/linux/ftrace.h ++++ b/include/linux/ftrace.h +@@ -134,6 +134,7 @@ enum { + FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, + FTRACE_OPS_FL_IPMODIFY = 1 << 13, + FTRACE_OPS_FL_PID = 1 << 14, ++ FTRACE_OPS_FL_IPIPE_EXCLUSIVE = 1 << 15, + }; + + #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index f4af034..fa16b8c 100644 --- a/include/linux/hardirq.h @@ -14637,10 +14781,10 @@ index 0000000..0a9b5b6 +#endif /* !__LINUX_IPIPE_H */ diff --git a/include/linux/ipipe_base.h b/include/linux/ipipe_base.h new file mode 100644 -index 0000000..8c06eed +index 0000000..42b368a --- /dev/null +++ b/include/linux/ipipe_base.h -@@ -0,0 +1,360 @@ +@@ -0,0 +1,365 @@ +/* -*- linux-c -*- + * include/linux/ipipe_base.h + * @@ -14751,6 +14895,7 @@ index 0000000..8c06eed +#define IPIPE_KEVT_EXIT 4 +#define IPIPE_KEVT_CLEANUP 5 +#define IPIPE_KEVT_HOSTRT 6 ++#define IPIPE_KEVT_CLOCKFREQ 7 + +struct ipipe_vm_notifier { + void (*handler)(struct ipipe_vm_notifier *nfy); @@ -14879,6 +15024,9 @@ index 0000000..8c06eed +#define __ipipe_report_cleanup(mm) \ + __ipipe_notify_kevent(IPIPE_KEVT_CLEANUP, mm) + ++#define __ipipe_report_clockfreq_update(freq) \ ++ __ipipe_notify_kevent(IPIPE_KEVT_CLOCKFREQ, &(freq)) ++ +void __ipipe_notify_vm_preemption(void); + +void __ipipe_call_mayday(struct pt_regs *regs); @@ -14898,7 +15046,8 @@ index 0000000..8c06eed +#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 4) +#define IPIPE_EVENT_CLEANUP (IPIPE_FIRST_EVENT + 5) +#define IPIPE_EVENT_HOSTRT (IPIPE_FIRST_EVENT + 6) -+#define IPIPE_EVENT_SYSCALL (IPIPE_FIRST_EVENT + 7) ++#define IPIPE_EVENT_CLOCKFREQ (IPIPE_FIRST_EVENT + 7) ++#define IPIPE_EVENT_SYSCALL (IPIPE_FIRST_EVENT + 8) +#define IPIPE_LAST_EVENT IPIPE_EVENT_SYSCALL +#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1) + @@ -15749,10 +15898,10 @@ index 0000000..d00c56b +#endif /* !__LINUX_IPIPE_DOMAIN_H */ diff --git a/include/linux/ipipe_lock.h b/include/linux/ipipe_lock.h new file mode 100644 -index 0000000..f71d2f1 +index 0000000..a108278 --- /dev/null +++ b/include/linux/ipipe_lock.h -@@ -0,0 +1,260 @@ +@@ -0,0 +1,327 @@ +/* -*- linux-c -*- + * include/linux/ipipe_lock.h + * @@ -15781,22 +15930,87 @@ index 0000000..f71d2f1 + arch_spinlock_t arch_lock; +} __ipipe_spinlock_t; + ++#define ipipe_spinlock(lock) ((__ipipe_spinlock_t *)(lock)) +#define ipipe_spinlock_p(lock) \ + __builtin_types_compatible_p(typeof(lock), __ipipe_spinlock_t *) || \ + __builtin_types_compatible_p(typeof(lock), __ipipe_spinlock_t []) + ++#define std_spinlock_raw(lock) ((raw_spinlock_t *)(lock)) +#define std_spinlock_raw_p(lock) \ + __builtin_types_compatible_p(typeof(lock), raw_spinlock_t *) || \ + __builtin_types_compatible_p(typeof(lock), raw_spinlock_t []) + ++#ifdef CONFIG_PREEMPT_RT_FULL ++ ++#define PICK_SPINLOCK_IRQSAVE(lock, flags) \ ++ do { \ ++ if (ipipe_spinlock_p(lock)) \ ++ (flags) = __ipipe_spin_lock_irqsave(ipipe_spinlock(lock)); \ ++ else if (std_spinlock_raw_p(lock)) \ ++ __real_raw_spin_lock_irqsave(std_spinlock_raw(lock), flags); \ ++ else __bad_lock_type(); \ ++ } while (0) ++ ++#define PICK_SPINTRYLOCK_IRQSAVE(lock, flags) \ ++ ({ \ ++ int __ret__; \ ++ if (ipipe_spinlock_p(lock)) \ ++ __ret__ = __ipipe_spin_trylock_irqsave(ipipe_spinlock(lock), &(flags)); \ ++ else if (std_spinlock_raw_p(lock)) \ ++ __ret__ = __real_raw_spin_trylock_irqsave(std_spinlock_raw(lock), flags); \ ++ else __bad_lock_type(); \ ++ __ret__; \ ++ }) ++ ++#define PICK_SPINTRYLOCK_IRQ(lock) \ ++ ({ \ ++ int __ret__; \ ++ if (ipipe_spinlock_p(lock)) \ ++ __ret__ = __ipipe_spin_trylock_irq(ipipe_spinlock(lock)); \ ++ else if (std_spinlock_raw_p(lock)) \ ++ __ret__ = __real_raw_spin_trylock_irq(std_spinlock_raw(lock)); \ ++ else __bad_lock_type(); \ ++ __ret__; \ ++ }) ++ ++#define PICK_SPINUNLOCK_IRQRESTORE(lock, flags) \ ++ do { \ ++ if (ipipe_spinlock_p(lock)) \ ++ __ipipe_spin_unlock_irqrestore(ipipe_spinlock(lock), flags); \ ++ else if (std_spinlock_raw_p(lock)) { \ ++ __ipipe_spin_unlock_debug(flags); \ ++ __real_raw_spin_unlock_irqrestore(std_spinlock_raw(lock), flags); \ ++ } else __bad_lock_type(); \ ++ } while (0) ++ ++#define PICK_SPINOP(op, lock) \ ++ ({ \ ++ if (ipipe_spinlock_p(lock)) \ ++ arch_spin##op(&ipipe_spinlock(lock)->arch_lock); \ ++ else if (std_spinlock_raw_p(lock)) \ ++ __real_raw_spin##op(std_spinlock_raw(lock)); \ ++ else __bad_lock_type(); \ ++ (void)0; \ ++ }) ++ ++#define PICK_SPINOP_RET(op, lock, type) \ ++ ({ \ ++ type __ret__; \ ++ if (ipipe_spinlock_p(lock)) \ ++ __ret__ = arch_spin##op(&ipipe_spinlock(lock)->arch_lock); \ ++ else if (std_spinlock_raw_p(lock)) \ ++ __ret__ = __real_raw_spin##op(std_spinlock_raw(lock)); \ ++ else { __ret__ = -1; __bad_lock_type(); } \ ++ __ret__; \ ++ }) ++ ++#else /* !CONFIG_PREEMPT_RT_FULL */ ++ ++#define std_spinlock(lock) ((spinlock_t *)(lock)) +#define std_spinlock_p(lock) \ + __builtin_types_compatible_p(typeof(lock), spinlock_t *) || \ + __builtin_types_compatible_p(typeof(lock), spinlock_t []) + -+#define ipipe_spinlock(lock) ((__ipipe_spinlock_t *)(lock)) -+#define std_spinlock_raw(lock) ((raw_spinlock_t *)(lock)) -+#define std_spinlock(lock) ((spinlock_t *)(lock)) -+ +#define PICK_SPINLOCK_IRQSAVE(lock, flags) \ + do { \ + if (ipipe_spinlock_p(lock)) \ @@ -15872,6 +16086,8 @@ index 0000000..f71d2f1 + __ret__; \ + }) + ++#endif /* !CONFIG_PREEMPT_RT_FULL */ ++ +#define arch_spin_lock_init(lock) \ + do { \ + IPIPE_DEFINE_SPINLOCK(__lock__); \ @@ -16001,7 +16217,7 @@ index 0000000..f71d2f1 +#define __ipipe_spin_trylock_irq(lock) 1 +#define __ipipe_spin_trylock_irqsave(lock, x) ({ (void)(x); 1; }) +#define __ipipe_spin_unlock_irqrestore(lock, x) do { (void)(x); } while (0) -+#define __ipipe_spin_unlock_irqbegin(lock) do { } while (0) ++#define __ipipe_spin_unlock_irqbegin(lock) spin_unlock(lock) +#define __ipipe_spin_unlock_irqcomplete(x) do { (void)(x); } while (0) +#define __ipipe_spin_unlock_debug(flags) do { } while (0) + @@ -16015,10 +16231,10 @@ index 0000000..f71d2f1 +#endif /* !__LINUX_IPIPE_LOCK_H */ diff --git a/include/linux/ipipe_tickdev.h b/include/linux/ipipe_tickdev.h new file mode 100644 -index 0000000..58a4142 +index 0000000..2f065ad --- /dev/null +++ b/include/linux/ipipe_tickdev.h -@@ -0,0 +1,145 @@ +@@ -0,0 +1,148 @@ +/* -*- linux-c -*- + * include/linux/ipipe_tickdev.h + * @@ -16098,6 +16314,7 @@ index 0000000..58a4142 + struct clock_event_device *cdev); + int (*real_set_next_event)(unsigned long evt, + struct clock_event_device *cdev); ++ unsigned int (*refresh_freq)(void); +}; + +#define __ipipe_hrtimer_irq __ipipe_raw_cpu_read(ipipe_percpu.hrtimer_irq) @@ -16150,6 +16367,8 @@ index 0000000..58a4142 + +unsigned ipipe_timer_ns2ticks(struct ipipe_timer *timer, unsigned ns); + ++void __ipipe_timer_refresh_freq(unsigned int hrclock_freq); ++ +#else /* !CONFIG_IPIPE */ + +#define ipipe_host_timer_register(clkevt) do { } while (0) @@ -17704,7 +17923,7 @@ index 0000000..797a849 +} diff --git a/kernel/ipipe/core.c b/kernel/ipipe/core.c new file mode 100644 -index 0000000..3b07d65 +index 0000000..339fb95 --- /dev/null +++ b/kernel/ipipe/core.c @@ -0,0 +1,1916 @@ @@ -18532,7 +18751,7 @@ index 0000000..3b07d65 + unsigned long flags, irq = 0; + int ipos; + -+ spin_lock_irqsave(&__ipipe_lock, flags); ++ raw_spin_lock_irqsave(&__ipipe_lock, flags); + + if (__ipipe_virtual_irq_map != ~0) { + ipos = ffz(__ipipe_virtual_irq_map); @@ -18540,7 +18759,7 @@ index 0000000..3b07d65 + irq = ipos + IPIPE_VIRQ_BASE; + } + -+ spin_unlock_irqrestore(&__ipipe_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_lock, flags); + + return irq; +} @@ -18570,7 +18789,7 @@ index 0000000..3b07d65 + (irq >= IPIPE_NR_XIRQS && !ipipe_virtual_irq_p(irq))) + return -EINVAL; + -+ spin_lock_irqsave(&__ipipe_lock, flags); ++ raw_spin_lock_irqsave(&__ipipe_lock, flags); + + if (ipd->irqs[irq].handler) { + ret = -EBUSY; @@ -18588,7 +18807,7 @@ index 0000000..3b07d65 + if (irq < IPIPE_NR_ROOT_IRQS) + __ipipe_enable_irqdesc(ipd, irq); +out: -+ spin_unlock_irqrestore(&__ipipe_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_lock, flags); + + return ret; +} @@ -18603,7 +18822,7 @@ index 0000000..3b07d65 + ipipe_root_only(); +#endif /* CONFIG_IPIPE_LEGACY */ + -+ spin_lock_irqsave(&__ipipe_lock, flags); ++ raw_spin_lock_irqsave(&__ipipe_lock, flags); + + if (ipd->irqs[irq].handler == NULL) + goto out; @@ -18616,7 +18835,7 @@ index 0000000..3b07d65 + if (irq < IPIPE_NR_ROOT_IRQS) + __ipipe_disable_irqdesc(ipd, irq); +out: -+ spin_unlock_irqrestore(&__ipipe_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_lock, flags); +} +EXPORT_SYMBOL_GPL(ipipe_free_irq); + @@ -19259,7 +19478,7 @@ index 0000000..3b07d65 + * another CPU. Enter a spinning wait until he releases the + * global lock. + */ -+ spin_lock(&__ipipe_cpu_barrier); ++ raw_spin_lock(&__ipipe_cpu_barrier); + + /* Got it. Now get out. */ + @@ -19269,7 +19488,7 @@ index 0000000..3b07d65 + + cpumask_set_cpu(cpu, &__ipipe_cpu_pass_map); + -+ spin_unlock(&__ipipe_cpu_barrier); ++ raw_spin_unlock(&__ipipe_cpu_barrier); + + cpumask_clear_cpu(cpu, &__ipipe_cpu_sync_map); +} @@ -19302,7 +19521,7 @@ index 0000000..3b07d65 + } +restart: + online = *cpu_online_mask; -+ spin_lock(&__ipipe_cpu_barrier); ++ raw_spin_lock(&__ipipe_cpu_barrier); + + __ipipe_cpu_sync = syncfn; + @@ -19328,7 +19547,7 @@ index 0000000..3b07d65 + */ + __ipipe_cpu_sync = NULL; + -+ spin_unlock(&__ipipe_cpu_barrier); ++ raw_spin_unlock(&__ipipe_cpu_barrier); + /* + * Ensure all CPUs consumed the IPI to avoid + * running __ipipe_cpu_sync prematurely. This @@ -19358,7 +19577,7 @@ index 0000000..3b07d65 + +#ifdef CONFIG_SMP + if (atomic_dec_and_test(&__ipipe_critical_count)) { -+ spin_unlock(&__ipipe_cpu_barrier); ++ raw_spin_unlock(&__ipipe_cpu_barrier); + while (!cpumask_empty(&__ipipe_cpu_sync_map)) + cpu_relax(); + cpumask_clear_cpu(ipipe_processor_id(), &__ipipe_cpu_lock_map); @@ -19626,10 +19845,10 @@ index 0000000..3b07d65 +#endif diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c new file mode 100644 -index 0000000..73f748e +index 0000000..a9917f4 --- /dev/null +++ b/kernel/ipipe/timer.c -@@ -0,0 +1,497 @@ +@@ -0,0 +1,520 @@ +/* -*- linux-c -*- + * linux/kernel/ipipe/timer.c + * @@ -19756,7 +19975,7 @@ index 0000000..73f748e + if (timer->cpumask == NULL) + timer->cpumask = cpumask_of(smp_processor_id()); + -+ spin_lock_irqsave(&lock, flags); ++ raw_spin_lock_irqsave(&lock, flags); + + list_for_each_entry(t, &timers, link) { + if (t->rating <= timer->rating) { @@ -19766,7 +19985,7 @@ index 0000000..73f748e + } + list_add_tail(&timer->link, &timers); + done: -+ spin_unlock_irqrestore(&lock, flags); ++ raw_spin_unlock_irqrestore(&lock, flags); +} + +static void ipipe_timer_request_sync(void) @@ -19789,18 +20008,14 @@ index 0000000..73f748e + timer->request(timer, steal); +} + -+/* Set up a timer as per-cpu timer for ipipe */ -+static void install_pcpu_timer(unsigned cpu, unsigned hrclock_freq, -+ struct ipipe_timer *t) { -+ unsigned hrtimer_freq; ++static void config_pcpu_timer(struct ipipe_timer *t, unsigned hrclock_freq) ++{ + unsigned long long tmp; ++ unsigned hrtimer_freq; + -+ if (__ipipe_hrtimer_freq == 0) ++ if (__ipipe_hrtimer_freq != t->freq) + __ipipe_hrtimer_freq = t->freq; + -+ per_cpu(ipipe_percpu.hrtimer_irq, cpu) = t->irq; -+ per_cpu(percpu_timer, cpu) = t; -+ + hrtimer_freq = t->freq; + if (__ipipe_hrclock_freq > UINT_MAX) + hrtimer_freq /= 1000; @@ -19813,6 +20028,15 @@ index 0000000..73f748e + t->c2t_frac = tmp; +} + ++/* Set up a timer as per-cpu timer for ipipe */ ++static void install_pcpu_timer(unsigned cpu, unsigned hrclock_freq, ++ struct ipipe_timer *t) ++{ ++ per_cpu(ipipe_percpu.hrtimer_irq, cpu) = t->irq; ++ per_cpu(percpu_timer, cpu) = t; ++ config_pcpu_timer(t, hrclock_freq); ++} ++ +static void select_root_only_timer(unsigned cpu, unsigned hrclock_khz, + const struct cpumask *mask, + struct ipipe_timer *t) { @@ -19866,7 +20090,7 @@ index 0000000..73f748e + } else + hrclock_freq = __ipipe_hrclock_freq; + -+ spin_lock_irqsave(&lock, flags); ++ raw_spin_lock_irqsave(&lock, flags); + + /* First, choose timers for the CPUs handled by ipipe */ + for_each_cpu(cpu, mask) { @@ -19906,7 +20130,7 @@ index 0000000..73f748e + } + } + -+ spin_unlock_irqrestore(&lock, flags); ++ raw_spin_unlock_irqrestore(&lock, flags); + + flags = ipipe_critical_enter(ipipe_timer_request_sync); + ipipe_timer_request_sync(); @@ -19915,7 +20139,7 @@ index 0000000..73f748e + return 0; + +err_remove_all: -+ spin_unlock_irqrestore(&lock, flags); ++ raw_spin_unlock_irqrestore(&lock, flags); + + for_each_cpu(cpu, mask) { + per_cpu(ipipe_percpu.hrtimer_irq, cpu) = -1; @@ -20127,9 +20351,27 @@ index 0000000..73f748e +} + +#endif /* CONFIG_IPIPE_HAVE_HOSTRT */ ++ ++int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, ++ bool force); ++ ++void __ipipe_timer_refresh_freq(unsigned int hrclock_freq) ++{ ++ struct ipipe_timer *t = __ipipe_raw_cpu_read(percpu_timer); ++ unsigned long flags; ++ ++ if (t && t->refresh_freq) { ++ t->freq = t->refresh_freq(); ++ flags = hard_local_irq_save(); ++ config_pcpu_timer(t, hrclock_freq); ++ hard_local_irq_restore(flags); ++ clockevents_program_event(t->host_timer, ++ t->host_timer->next_event, false); ++ } ++} diff --git a/kernel/ipipe/tracer.c b/kernel/ipipe/tracer.c new file mode 100644 -index 0000000..da272c50 +index 0000000..1ae7bc2 --- /dev/null +++ b/kernel/ipipe/tracer.c @@ -0,0 +1,1468 @@ @@ -20194,7 +20436,7 @@ index 0000000..da272c50 +#define IPIPE_TFLG_CURRDOM_SHIFT 10 /* bits 10..11: current domain */ +#define IPIPE_TFLG_CURRDOM_MASK 0x0C00 +#define IPIPE_TFLG_DOMSTATE_SHIFT 12 /* bits 12..15: domain stalled? */ -+#define IPIPE_TFLG_DOMSTATE_BITS 3 ++#define IPIPE_TFLG_DOMSTATE_BITS 1 + +#define IPIPE_TFLG_DOMAIN_STALLED(point, n) \ + (point->flags & (1 << (n + IPIPE_TFLG_DOMSTATE_SHIFT))) @@ -20337,7 +20579,7 @@ index 0000000..da272c50 + if (length > per_cpu(trace_path, cpu)[per_cpu(max_path, cpu)].length) { + /* we need protection here against other cpus trying + to start a proc dump */ -+ spin_lock(&global_path_lock); ++ raw_spin_lock(&global_path_lock); + + /* active path holds new worst case */ + tp->length = length; @@ -20346,7 +20588,7 @@ index 0000000..da272c50 + /* find next unused trace path */ + active = __ipipe_get_free_trace_path(active, cpu); + -+ spin_unlock(&global_path_lock); ++ raw_spin_unlock(&global_path_lock); + + tp = &per_cpu(trace_path, cpu)[active]; + @@ -20369,7 +20611,7 @@ index 0000000..da272c50 + + /* we need protection here against other cpus trying + * to set their frozen path or to start a proc dump */ -+ spin_lock(&global_path_lock); ++ raw_spin_lock(&global_path_lock); + + per_cpu(frozen_path, cpu) = active; + @@ -20383,7 +20625,7 @@ index 0000000..da272c50 + tp->end = -1; + } + -+ spin_unlock(&global_path_lock); ++ raw_spin_unlock(&global_path_lock); + + tp = &per_cpu(trace_path, cpu)[active]; + @@ -20538,7 +20780,7 @@ index 0000000..da272c50 + int cpu; + struct ipipe_trace_path *tp; + -+ spin_lock_irqsave(&global_path_lock, flags); ++ raw_spin_lock_irqsave(&global_path_lock, flags); + + cpu = ipipe_processor_id(); + restart: @@ -21467,7 +21709,7 @@ index 0000000..da272c50 + +static struct ftrace_ops ipipe_trace_ops = { + .func = ipipe_trace_function, -+ .flags = FTRACE_OPS_FL_RECURSION_SAFE, ++ .flags = FTRACE_OPS_FL_IPIPE_EXCLUSIVE, +}; + +static ssize_t __ipipe_wr_enable(struct file *file, const char __user *buffer, @@ -22354,7 +22596,7 @@ index 2329daa..79cfe9b 100644 if (pm_wakeup_pending()) { error = -EAGAIN; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c -index 3c1aca0..90b1189 100644 +index 3c1aca0..ae6b3d5 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -62,6 +62,9 @@ int console_printk[4] = { @@ -22470,7 +22712,7 @@ index 3c1aca0..90b1189 100644 + goto start; + + do { -+ spin_unlock_irqrestore(&__ipipe_printk_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags); + start: + lmax = __ipipe_printk_fill; + while (out < lmax) { @@ -22479,13 +22721,13 @@ index 3c1aca0..90b1189 100644 + p += len; + out += len; + } -+ spin_lock_irqsave(&__ipipe_printk_lock, flags); ++ raw_spin_lock_irqsave(&__ipipe_printk_lock, flags); + } + while (__ipipe_printk_fill != lmax); + + __ipipe_printk_fill = 0; + -+ spin_unlock_irqrestore(&__ipipe_printk_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags); +} + /** @@ -22523,7 +22765,7 @@ index 3c1aca0..90b1189 100644 + goto out; + } + -+ spin_lock_irqsave(&__ipipe_printk_lock, flags); ++ raw_spin_lock_irqsave(&__ipipe_printk_lock, flags); + + oldcount = __ipipe_printk_fill; + fbytes = __LOG_BUF_LEN - oldcount; @@ -22534,7 +22776,7 @@ index 3c1aca0..90b1189 100644 + } else + r = 0; + -+ spin_unlock_irqrestore(&__ipipe_printk_lock, flags); ++ raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags); + + if (oldcount == 0) + ipipe_raise_irq(__ipipe_printk_virq); @@ -23183,7 +23425,7 @@ index 3b9a48a..edd9470 100644 help This option will modify all the calls to function tracing diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index eb11011..5fa6c0a 100644 +index eb11011..d0957bd 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -32,6 +32,7 @@ @@ -23194,7 +23436,33 @@ index eb11011..5fa6c0a 100644 #include <trace/events/sched.h> -@@ -2518,6 +2519,9 @@ void __weak arch_ftrace_update_code(int command) +@@ -262,8 +263,17 @@ static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops) + + static void update_ftrace_function(void) + { ++ struct ftrace_ops *ops; + ftrace_func_t func; + ++ for (ops = ftrace_ops_list; ++ ops != &ftrace_list_end; ops = ops->next) ++ if (ops->flags & FTRACE_OPS_FL_IPIPE_EXCLUSIVE) { ++ set_function_trace_op = ops; ++ func = ops->func; ++ goto set_pointers; ++ } ++ + /* + * Prepare the ftrace_ops that the arch callback will use. + * If there's only one ftrace_ops registered, the ftrace_ops_list +@@ -291,6 +301,7 @@ static void update_ftrace_function(void) + + update_function_graph_func(); + ++ set_pointers: + /* If there's no change, then do nothing more here */ + if (ftrace_trace_function == func) + return; +@@ -2518,6 +2529,9 @@ void __weak arch_ftrace_update_code(int command) static void ftrace_run_update_code(int command) { @@ -23204,7 +23472,7 @@ index eb11011..5fa6c0a 100644 int ret; ret = ftrace_arch_code_modify_prepare(); -@@ -2531,7 +2535,13 @@ static void ftrace_run_update_code(int command) +@@ -2531,7 +2545,13 @@ static void ftrace_run_update_code(int command) * is safe. The stop_machine() is the safest, but also * produces the most overhead. */ @@ -23218,7 +23486,7 @@ index eb11011..5fa6c0a 100644 ret = ftrace_arch_code_modify_post_process(); FTRACE_WARN_ON(ret); -@@ -4877,10 +4887,10 @@ static int ftrace_process_locs(struct module *mod, +@@ -4877,10 +4897,10 @@ static int ftrace_process_locs(struct module *mod, * reason to cause large interrupt latencies while we do it. */ if (!mod) @@ -23231,7 +23499,7 @@ index eb11011..5fa6c0a 100644 ret = 0; out: mutex_unlock(&ftrace_lock); -@@ -4979,9 +4989,11 @@ void __init ftrace_init(void) +@@ -4979,9 +4999,11 @@ void __init ftrace_init(void) unsigned long count, flags; int ret; @@ -23245,7 +23513,7 @@ index eb11011..5fa6c0a 100644 if (ret) goto failed; -@@ -5174,7 +5186,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, +@@ -5174,7 +5196,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, } } while_for_each_ftrace_op(op); out: @@ -23605,24 +23873,22 @@ index 86c8911..373a30b 100644 return err; } diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c -index 1afec32..5803111 100644 +index 1afec32..f7c1a2a 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c -@@ -12,10 +12,13 @@ notrace static unsigned int check_preemption_disabled(const char *what1, +@@ -12,6 +12,12 @@ notrace static unsigned int check_preemption_disabled(const char *what1, { int this_cpu = raw_smp_processor_id(); ++ if (hard_irqs_disabled()) ++ goto out; ++ + if (!ipipe_root_p) + goto out; + if (likely(preempt_count())) goto out; -- if (irqs_disabled()) -+ if (irqs_disabled() || hard_irqs_disabled()) - goto out; - - /* diff --git a/mm/memory.c b/mm/memory.c index 2a9e098..46ec4cd 100644 --- a/mm/memory.c @@ -23830,7 +24096,7 @@ index 2a9e098..46ec4cd 100644 static struct kmem_cache *page_ptl_cachep; diff --git a/mm/mlock.c b/mm/mlock.c -index 3d3ee6c..ed47c08 100644 +index 3d3ee6ca..ed47c08 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -756,3 +756,28 @@ void user_shm_unlock(size_t size, struct user_struct *user) @@ -23965,3 +24231,16 @@ index 2faaa29..ef00f26 100644 return nr; } +diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c +index 96c2e42..2e6e3cf 100644 +--- a/sound/soc/intel/atom/sst/sst.c ++++ b/sound/soc/intel/atom/sst/sst.c +@@ -369,7 +369,7 @@ static inline void sst_restore_shim64(struct intel_sst_drv *ctx, + */ + spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); + sst_shim_write64(shim, SST_IMRX, shim_regs->imrx), +- sst_shim_write64(shim, SST_CSR, shim_regs->csr), ++ sst_shim_write64(shim, SST_CSR, shim_regs->csr); + spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); + } + _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git