diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt
index 9bd4b7f966b5..820bbf3b892a 100644
--- a/Documentation/trace/events.txt
+++ b/Documentation/trace/events.txt
@@ -669,15 +669,15 @@ triggers (you have to use '!' for each one added.)
   The examples below provide a more concrete illustration of the
   concepts and typical usage patterns discussed above.
 
-  'synthetic' event fields
+  'special' event fields
   ------------------------
 
-  There are a number of 'synthetic fields' available for use as keys
-  or values in a hist trigger.  These look like and behave as if they
-  were event fields, but aren't actually part of the event's field
-  definition or format file.  They are however available for any
+  There are a number of 'special event fields' available for use as
+  keys or values in a hist trigger.  These look like and behave as if
+  they were actual event fields, but aren't really part of the event's
+  field definition or format file.  They are however available for any
   event, and can be used anywhere an actual event field could be.
-  'Synthetic' field names are always prefixed with a '$' character to
+  'Special' field names are always prefixed with a '$' character to
   indicate that they're not normal fields (with the exception of
   'cpu', for compatibility with existing filter usage):
 
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index df6fd9df698e..15e7ff4ea178 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -530,7 +530,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
 		return false;
 	}
 
-	zram_meta_init_table_locks(zram, disksize);
+	zram_meta_init_table_locks(zram, num_pages);
 	return true;
 }
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 7e55aa9ce680..85750ec39645 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -52,6 +52,31 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
 	return container_of(data, struct tpm_tis_tcg_phy, priv);
 }
 
+#ifdef CONFIG_PREEMPT_RT_FULL
+/*
+ * Flushes previous write operations to chip so that a subsequent
+ * ioread*()s won't stall a cpu.
+ */
+static inline void tpm_tis_flush(void __iomem *iobase)
+{
+	ioread8(iobase + TPM_ACCESS(0));
+}
+#else
+#define tpm_tis_flush(iobase) do { } while (0)
+#endif
+
+static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
+{
+	iowrite8(b, iobase + addr);
+	tpm_tis_flush(iobase);
+}
+
+static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
+{
+	iowrite32(b, iobase + addr);
+	tpm_tis_flush(iobase);
+}
+
 static bool interrupts = true;
 module_param(interrupts, bool, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -230,7 +255,7 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 	tpm_platform_begin_xfer();
 
 	while (len--)
-		iowrite8(*value++, phy->iobase + addr);
+		tpm_tis_iowrite8(*value++, phy->iobase, addr);
 
 	tpm_platform_end_xfer();
 
@@ -269,7 +294,7 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
 
 	tpm_platform_begin_xfer();
 
-	iowrite32(value, phy->iobase + addr);
+	tpm_tis_iowrite32(value, phy->iobase, addr);
 
 	tpm_platform_end_xfer();
 
diff --git a/fs/dcache.c b/fs/dcache.c
index 1ec40bb6eb3b..6842e2220924 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2417,9 +2417,10 @@ EXPORT_SYMBOL(d_rehash);
 static inline unsigned start_dir_add(struct inode *dir)
 {
 
+	preempt_disable_rt();
 	for (;;) {
-		unsigned n = dir->i_dir_seq;
-		if (!(n & 1) && cmpxchg(&dir->i_dir_seq, n, n + 1) == n)
+		unsigned n = dir->__i_dir_seq;
+		if (!(n & 1) && cmpxchg(&dir->__i_dir_seq, n, n + 1) == n)
 			return n;
 		cpu_relax();
 	}
@@ -2427,7 +2428,8 @@ static inline unsigned start_dir_add(struct inode *dir)
 
 static inline void end_dir_add(struct inode *dir, unsigned n)
 {
-	smp_store_release(&dir->i_dir_seq, n + 2);
+	smp_store_release(&dir->__i_dir_seq, n + 2);
+	preempt_enable_rt();
 }
 
 static void d_wait_lookup(struct dentry *dentry)
@@ -2463,7 +2465,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
 
 retry:
 	rcu_read_lock();
-	seq = smp_load_acquire(&parent->d_inode->i_dir_seq) & ~1;
+	seq = smp_load_acquire(&parent->d_inode->__i_dir_seq) & ~1;
 	r_seq = read_seqbegin(&rename_lock);
 	dentry = __d_lookup_rcu(parent, name, &d_seq);
 	if (unlikely(dentry)) {
@@ -2485,7 +2487,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
 		goto retry;
 	}
 	hlist_bl_lock(b);
-	if (unlikely(parent->d_inode->i_dir_seq != seq)) {
+	if (unlikely(parent->d_inode->__i_dir_seq != seq)) {
 		hlist_bl_unlock(b);
 		rcu_read_unlock();
 		goto retry;
diff --git a/fs/inode.c b/fs/inode.c
index 6a1626e0edaf..601b666e76a9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -154,7 +154,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
 	inode->i_bdev = NULL;
 	inode->i_cdev = NULL;
 	inode->i_link = NULL;
-	inode->i_dir_seq = 0;
+	inode->__i_dir_seq = 0;
 	inode->i_rdev = 0;
 	inode->dirtied_when = 0;
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 3aabe553fc45..b5d63bf1ad8e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -90,7 +90,7 @@ static struct dentry *next_positive(struct dentry *parent,
 				    struct list_head *from,
 				    int count)
 {
-	unsigned *seq = &parent->d_inode->i_dir_seq, n;
+	unsigned *seq = &parent->d_inode->__i_dir_seq, n;
 	struct dentry *res;
 	struct list_head *p;
 	bool skipped;
@@ -123,8 +123,9 @@ static struct dentry *next_positive(struct dentry *parent,
 static void move_cursor(struct dentry *cursor, struct list_head *after)
 {
 	struct dentry *parent = cursor->d_parent;
-	unsigned n, *seq = &parent->d_inode->i_dir_seq;
+	unsigned n, *seq = &parent->d_inode->__i_dir_seq;
 	spin_lock(&parent->d_lock);
+	preempt_disable_rt();
 	for (;;) {
 		n = *seq;
 		if (!(n & 1) && cmpxchg(seq, n, n + 1) == n)
@@ -137,6 +138,7 @@ static void move_cursor(struct dentry *cursor, struct list_head *after)
 	else
 		list_add_tail(&cursor->d_child, &parent->d_subdirs);
 	smp_store_release(seq, n + 2);
+	preempt_enable_rt();
 	spin_unlock(&parent->d_lock);
 }
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d0c0ca8ea8c1..30b9561cf142 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -651,7 +651,7 @@ struct inode {
 		struct block_device	*i_bdev;
 		struct cdev		*i_cdev;
 		char			*i_link;
-		unsigned		i_dir_seq;
+		unsigned		__i_dir_seq;
 	};
 
 	__u32			i_generation;
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index e9515066250e..49bef3e96eb2 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -119,12 +119,20 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
 	struct raw_notifier_head name =				\
 		RAW_NOTIFIER_INIT(name)
 
+#ifdef CONFIG_TREE_SRCU
 #define _SRCU_NOTIFIER_HEAD(name, mod)				\
 	static DEFINE_PER_CPU(struct srcu_data,			\
 			name##_head_srcu_data);			\
 	mod struct srcu_notifier_head name =			\
 			SRCU_NOTIFIER_INIT(name, name##_head_srcu_data)
 
+#else
+#define _SRCU_NOTIFIER_HEAD(name, mod)				\
+	mod struct srcu_notifier_head name =			\
+			SRCU_NOTIFIER_INIT(name, name)
+
+#endif
+
 #define SRCU_NOTIFIER_HEAD(name)				\
 	_SRCU_NOTIFIER_HEAD(name, )
 
diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h
index cfbfc540cafc..1bdcbdd3317c 100644
--- a/include/linux/srcutiny.h
+++ b/include/linux/srcutiny.h
@@ -43,7 +43,7 @@ struct srcu_struct {
 
 void srcu_drive_gp(struct work_struct *wp);
 
-#define __SRCU_STRUCT_INIT(name)					\
+#define __SRCU_STRUCT_INIT(name, __ignored)				\
 {									\
 	.srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq),	\
 	.srcu_cb_tail = &name.srcu_cb_head,				\
@@ -56,9 +56,9 @@ void srcu_drive_gp(struct work_struct *wp);
  * Tree SRCU, which needs some per-CPU data.
  */
 #define DEFINE_SRCU(name) \
-	struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+	struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
 #define DEFINE_STATIC_SRCU(name) \
-	static struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+	static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
 
 void synchronize_srcu(struct srcu_struct *sp);
 
diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
index bc22d54adc52..a03192052066 100644
--- a/include/linux/tracepoint-defs.h
+++ b/include/linux/tracepoint-defs.h
@@ -32,7 +32,6 @@ struct tracepoint {
 	int (*regfunc)(void);
 	void (*unregfunc)(void);
 	struct tracepoint_func __rcu *funcs;
-	bool dynamic;
 };
 
 #endif
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 434c840e2d82..ad55ddecc1e9 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -585,6 +585,9 @@ config HIST_TRIGGERS
 	  event activity as an initial guide for further investigation
 	  using more advanced tools.
 
+	  Inter-event tracing of quantities such as latencies is also
+	  supported using hist triggers under this option.
+
 	  See Documentation/trace/events.txt.
 	  If in doubt, say N.
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9dbb4590b836..f78a1ad89f82 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2590,16 +2590,16 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
  *  IRQ context
  *  NMI context
  *
- * If for some reason the ring buffer starts to recurse, we
- * only allow that to happen at most 4 times (one for each
- * context). If it happens 5 times, then we consider this a
- * recusive loop and do not let it go further.
+ * If for some reason the ring buffer starts to recurse, we only allow
+ * that to happen at most 6 times (one for each context, plus possibly
+ * two levels of synthetic event generation). If it happens 7 times,
+ * then we consider this a recusive loop and do not let it go further.
  */
 
 static __always_inline int
 trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer)
 {
-	if (cpu_buffer->current_context >= 4)
+	if (cpu_buffer->current_context >= 6)
 		return 1;
 
 	cpu_buffer->current_context++;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7e69a14177cf..fced553fda6b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6333,7 +6333,7 @@ int tracing_set_time_stamp_abs(struct trace_array *tr, bool abs)
 	tracing_reset_online_cpus(&tr->trace_buffer);
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-	if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer)
+	if (tr->max_buffer.buffer)
 		ring_buffer_set_time_stamp_abs(tr->max_buffer.buffer, abs);
 	tracing_reset_online_cpus(&tr->max_buffer);
 #endif
@@ -7732,6 +7732,7 @@ static int instance_mkdir(const char *name)
 	struct trace_array *tr;
 	int ret;
 
+	mutex_lock(&event_mutex);
 	mutex_lock(&trace_types_lock);
 
 	ret = -EEXIST;
@@ -7788,6 +7789,7 @@ static int instance_mkdir(const char *name)
 	list_add(&tr->list, &ftrace_trace_arrays);
 
 	mutex_unlock(&trace_types_lock);
+	mutex_unlock(&event_mutex);
 
 	return 0;
 
@@ -7799,6 +7801,7 @@ static int instance_mkdir(const char *name)
 
  out_unlock:
 	mutex_unlock(&trace_types_lock);
+	mutex_unlock(&event_mutex);
 
 	return ret;
 
@@ -7811,6 +7814,7 @@ static int instance_rmdir(const char *name)
 	int ret;
 	int i;
 
+	mutex_lock(&event_mutex);
 	mutex_lock(&trace_types_lock);
 
 	ret = -ENODEV;
@@ -7856,6 +7860,7 @@ static int instance_rmdir(const char *name)
 
  out_unlock:
 	mutex_unlock(&trace_types_lock);
+	mutex_unlock(&event_mutex);
 
 	return ret;
 }
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 1d5095e2dfe5..08ee331b554f 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2953,24 +2953,24 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
  * creates the event hierachry in the @parent/events directory.
  *
  * Returns 0 on success.
+ *
+ * Must be called with event_mutex held.
  */
 int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr)
 {
 	int ret;
 
-	mutex_lock(&event_mutex);
+	lockdep_assert_held(&event_mutex);
 
 	ret = create_event_toplevel_files(parent, tr);
 	if (ret)
-		goto out_unlock;
+		goto out;
 
 	down_write(&trace_event_sem);
 	__trace_add_event_dirs(tr);
 	up_write(&trace_event_sem);
 
- out_unlock:
-	mutex_unlock(&event_mutex);
-
+ out:
 	return ret;
 }
 
@@ -2999,9 +2999,10 @@ early_event_add_tracer(struct dentry *parent, struct trace_array *tr)
 	return ret;
 }
 
+/* Must be called with event_mutex held */
 int event_trace_del_tracer(struct trace_array *tr)
 {
-	mutex_lock(&event_mutex);
+	lockdep_assert_held(&event_mutex);
 
 	/* Disable any event triggers and associated soft-disabled events */
 	clear_event_triggers(tr);
@@ -3022,8 +3023,6 @@ int event_trace_del_tracer(struct trace_array *tr)
 
 	tr->event_dir = NULL;
 
-	mutex_unlock(&event_mutex);
-
 	return 0;
 }
 
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index eb77eee93611..e884d5d78551 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -210,24 +210,24 @@ DEFINE_HIST_FIELD_FN(u8);
 #define HIST_KEY_SIZE_MAX	(MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE)
 
 enum hist_field_flags {
-	HIST_FIELD_FL_HITCOUNT		= 1,
-	HIST_FIELD_FL_KEY		= 2,
-	HIST_FIELD_FL_STRING		= 4,
-	HIST_FIELD_FL_HEX		= 8,
-	HIST_FIELD_FL_SYM		= 16,
-	HIST_FIELD_FL_SYM_OFFSET	= 32,
-	HIST_FIELD_FL_EXECNAME		= 64,
-	HIST_FIELD_FL_SYSCALL		= 128,
-	HIST_FIELD_FL_STACKTRACE	= 256,
-	HIST_FIELD_FL_LOG2		= 512,
-	HIST_FIELD_FL_TIMESTAMP		= 1024,
-	HIST_FIELD_FL_TIMESTAMP_USECS	= 2048,
-	HIST_FIELD_FL_VAR		= 4096,
-	HIST_FIELD_FL_VAR_ONLY		= 8192,
-	HIST_FIELD_FL_EXPR		= 16384,
-	HIST_FIELD_FL_VAR_REF		= 32768,
-	HIST_FIELD_FL_CPU		= 65536,
-	HIST_FIELD_FL_ALIAS		= 131072,
+	HIST_FIELD_FL_HITCOUNT		= 1 << 0,
+	HIST_FIELD_FL_KEY		= 1 << 1,
+	HIST_FIELD_FL_STRING		= 1 << 2,
+	HIST_FIELD_FL_HEX		= 1 << 3,
+	HIST_FIELD_FL_SYM		= 1 << 4,
+	HIST_FIELD_FL_SYM_OFFSET	= 1 << 5,
+	HIST_FIELD_FL_EXECNAME		= 1 << 6,
+	HIST_FIELD_FL_SYSCALL		= 1 << 7,
+	HIST_FIELD_FL_STACKTRACE	= 1 << 8,
+	HIST_FIELD_FL_LOG2		= 1 << 9,
+	HIST_FIELD_FL_TIMESTAMP		= 1 << 10,
+	HIST_FIELD_FL_TIMESTAMP_USECS	= 1 << 11,
+	HIST_FIELD_FL_VAR		= 1 << 12,
+	HIST_FIELD_FL_VAR_ONLY		= 1 << 13,
+	HIST_FIELD_FL_EXPR		= 1 << 14,
+	HIST_FIELD_FL_VAR_REF		= 1 << 15,
+	HIST_FIELD_FL_CPU		= 1 << 16,
+	HIST_FIELD_FL_ALIAS		= 1 << 17,
 };
 
 struct var_defs {
@@ -353,42 +353,22 @@ struct action_data {
 };
 
 
-static char *hist_err_str;
-static char *last_hist_cmd;
-
-static int hist_err_alloc(void)
-{
-	int ret = 0;
-
-	last_hist_cmd = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
-	if (!last_hist_cmd)
-		return -ENOMEM;
-
-	hist_err_str = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
-	if (!hist_err_str) {
-		kfree(last_hist_cmd);
-		ret = -ENOMEM;
-	}
-
-	return ret;
-}
+static char last_hist_cmd[MAX_FILTER_STR_VAL];
+static char hist_err_str[MAX_FILTER_STR_VAL];
 
 static void last_cmd_set(char *str)
 {
-	if (!last_hist_cmd || !str)
+	if (!str)
 		return;
 
-	if (strlen(str) > MAX_FILTER_STR_VAL - 1)
-		return;
-
-	strcpy(last_hist_cmd, str);
+	strncpy(last_hist_cmd, str, MAX_FILTER_STR_VAL - 1);
 }
 
 static void hist_err(char *str, char *var)
 {
 	int maxlen = MAX_FILTER_STR_VAL - 1;
 
-	if (!hist_err_str || !str)
+	if (!str)
 		return;
 
 	if (strlen(hist_err_str))
@@ -409,26 +389,23 @@ static void hist_err_event(char *str, char *system, char *event, char *var)
 	char err[MAX_FILTER_STR_VAL];
 
 	if (system && var)
-		sprintf(err, "%s.%s.%s", system, event, var);
+		snprintf(err, MAX_FILTER_STR_VAL, "%s.%s.%s", system, event, var);
 	else if (system)
-		sprintf(err, "%s.%s", system, event);
+		snprintf(err, MAX_FILTER_STR_VAL, "%s.%s", system, event);
 	else
-		strcpy(err, var);
+		strncpy(err, var, MAX_FILTER_STR_VAL);
 
 	hist_err(str, err);
 }
 
 static void hist_err_clear(void)
 {
-	if (!hist_err_str)
-		return;
-
 	hist_err_str[0] = '\0';
 }
 
 static bool have_hist_err(void)
 {
-	if (hist_err_str && strlen(hist_err_str))
+	if (strlen(hist_err_str))
 		return true;
 
 	return false;
@@ -508,7 +485,7 @@ static int synth_field_string_size(char *type)
 		return -EINVAL;
 
 	len = end - start;
-	if (len > 2)
+	if (len > 3)
 		return -EINVAL;
 
 	strncpy(buf, start, len);
@@ -631,12 +608,12 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter,
 		if (tr->trace_flags & TRACE_ITER_VERBOSE)
 			trace_seq_printf(s, "%s ", fmt);
 
-		sprintf(print_fmt, "%%s=%s%%s", fmt);
+		snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt);
 
 		/* parameter values */
 		if (se->fields[i]->is_string) {
 			trace_seq_printf(s, print_fmt, se->fields[i]->name,
-					 (char *)entry->fields[n_u64],
+					 (char *)(long)entry->fields[n_u64],
 					 i == se->n_fields - 1 ? "" : " ");
 			n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
 		} else {
@@ -681,7 +658,7 @@ static notrace void trace_event_raw_event_synth(void *__data,
 
 	for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
 		if (event->fields[i]->is_string) {
-			char *str_val = (char *)var_ref_vals[var_ref_idx + i];
+			char *str_val = (char *)(long)var_ref_vals[var_ref_idx + i];
 			char *str_field = (char *)&entry->fields[n_u64];
 
 			strncpy(str_field, str_val, STR_VAR_LEN_MAX);
@@ -697,8 +674,10 @@ static notrace void trace_event_raw_event_synth(void *__data,
 
 static void free_synth_event_print_fmt(struct trace_event_call *call)
 {
-	if (call)
+	if (call) {
 		kfree(call->print_fmt);
+		call->print_fmt = NULL;
+	}
 }
 
 static int __set_synth_event_print_fmt(struct synth_event *event,
@@ -827,27 +806,18 @@ static void free_synth_tracepoint(struct tracepoint *tp)
 static struct tracepoint *alloc_synth_tracepoint(char *name)
 {
 	struct tracepoint *tp;
-	int ret = 0;
 
 	tp = kzalloc(sizeof(*tp), GFP_KERNEL);
-	if (!tp) {
-		ret = -ENOMEM;
-		goto free;
-	}
+	if (!tp)
+		return ERR_PTR(-ENOMEM);
 
 	tp->name = kstrdup(name, GFP_KERNEL);
 	if (!tp->name) {
-		ret = -ENOMEM;
-		goto free;
+		kfree(tp);
+		return ERR_PTR(-ENOMEM);
 	}
 
-	tp->dynamic = true;
-
 	return tp;
- free:
-	free_synth_tracepoint(tp);
-
-	return ERR_PTR(ret);
 }
 
 typedef void (*synth_probe_func_t) (void *__data, u64 *var_ref_vals,
@@ -869,8 +839,8 @@ static inline void trace_synth(struct synth_event *event, u64 *var_ref_vals,
 		probe_func_ptr = rcu_dereference_sched((tp)->funcs);
 		if (probe_func_ptr) {
 			do {
-				probe_func = (probe_func_ptr)->func;
-				__data = (probe_func_ptr)->data;
+				probe_func = probe_func_ptr->func;
+				__data = probe_func_ptr->data;
 				probe_func(__data, var_ref_vals, var_ref_idx);
 			} while ((++probe_func_ptr)->func);
 		}
@@ -889,6 +859,7 @@ static struct synth_event *find_synth_event(const char *name)
 	return NULL;
 }
 
+/* This function releases synth_event_mutex */
 static int register_synth_event(struct synth_event *event)
 {
 	struct trace_event_call *call = &event->call;
@@ -923,6 +894,11 @@ static int register_synth_event(struct synth_event *event)
 	call->data = event;
 	call->tp = event->tp;
 
+	/*
+	 * trace_add_event_call() grabs event_mutex, but that can
+	 * deadlock with a hist trigger cmd already holding it that
+	 * can grab synth_event_mutex
+	 */
 	mutex_unlock(&synth_event_mutex);
 	ret = trace_add_event_call(call);
 	mutex_lock(&synth_event_mutex);
@@ -946,6 +922,7 @@ static int register_synth_event(struct synth_event *event)
 	goto out;
 }
 
+/* This function releases synth_event_mutex */
 static int unregister_synth_event(struct synth_event *event)
 {
 	struct trace_event_call *call = &event->call;
@@ -954,20 +931,18 @@ static int unregister_synth_event(struct synth_event *event)
 	mutex_unlock(&synth_event_mutex);
 	ret = trace_remove_event_call(call);
 	mutex_lock(&synth_event_mutex);
-	if (ret) {
-		pr_warn("Failed to remove synthetic event: %s\n",
-			trace_event_name(call));
-		free_synth_event_print_fmt(call);
-		unregister_trace_event(&call->event);
-	}
 
 	return ret;
 }
 
-static void remove_synth_event(struct synth_event *event)
+static int remove_synth_event(struct synth_event *event)
 {
-	unregister_synth_event(event);
-	list_del(&event->list);
+	int ret = unregister_synth_event(event);
+
+	if (!ret)
+		list_del(&event->list);
+
+	return ret;
 }
 
 static int add_synth_event(struct synth_event *event)
@@ -1050,6 +1025,7 @@ struct hist_var_data {
 	struct hist_trigger_data *hist_data;
 };
 
+/* This function releases synth_event_mutex */
 static int create_synth_event(int argc, char **argv)
 {
 	struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
@@ -1084,8 +1060,9 @@ static int create_synth_event(int argc, char **argv)
 				ret = -EBUSY;
 				goto out;
 			}
-			remove_synth_event(event);
-			free_synth_event(event);
+			ret = remove_synth_event(event);
+			if (!ret)
+				free_synth_event(event);
 			goto out;
 		}
 		ret = -EEXIST;
@@ -1140,6 +1117,7 @@ static int create_synth_event(int argc, char **argv)
 	goto out;
 }
 
+/* This function releases synth_event_mutex */
 static int release_all_synth_events(void)
 {
 	struct synth_event *event, *e;
@@ -1155,8 +1133,9 @@ static int release_all_synth_events(void)
 	}
 
 	list_for_each_entry_safe(event, e, &synth_event_list, list) {
-		remove_synth_event(event);
-		free_synth_event(event);
+		ret = remove_synth_event(event);
+		if (!ret)
+			free_synth_event(event);
 	}
  out:
 	mutex_unlock(&synth_event_mutex);
@@ -1260,7 +1239,7 @@ static u64 hist_field_cpu(struct hist_field *hist_field,
 			  struct ring_buffer_event *rbe,
 			  void *event)
 {
-	int cpu = raw_smp_processor_id();
+	int cpu = smp_processor_id();
 
 	return cpu;
 }
@@ -1732,17 +1711,33 @@ static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
 	int ret = 0;
 
 	if ((strncmp(str, "key=", strlen("key=")) == 0) ||
-	    (strncmp(str, "keys=", strlen("keys=")) == 0))
+	    (strncmp(str, "keys=", strlen("keys=")) == 0)) {
 		attrs->keys_str = kstrdup(str, GFP_KERNEL);
-	else if ((strncmp(str, "val=", strlen("val=")) == 0) ||
+		if (!attrs->keys_str) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	} else if ((strncmp(str, "val=", strlen("val=")) == 0) ||
 		 (strncmp(str, "vals=", strlen("vals=")) == 0) ||
-		 (strncmp(str, "values=", strlen("values=")) == 0))
+		 (strncmp(str, "values=", strlen("values=")) == 0)) {
 		attrs->vals_str = kstrdup(str, GFP_KERNEL);
-	else if (strncmp(str, "sort=", strlen("sort=")) == 0)
+		if (!attrs->vals_str) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	} else if (strncmp(str, "sort=", strlen("sort=")) == 0) {
 		attrs->sort_key_str = kstrdup(str, GFP_KERNEL);
-	else if (strncmp(str, "name=", strlen("name=")) == 0)
+		if (!attrs->sort_key_str) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	} else if (strncmp(str, "name=", strlen("name=")) == 0) {
 		attrs->name = kstrdup(str, GFP_KERNEL);
-	else if (strncmp(str, "clock=", strlen("clock=")) == 0) {
+		if (!attrs->name) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	} else if (strncmp(str, "clock=", strlen("clock=")) == 0) {
 		strsep(&str, "=");
 		if (!str) {
 			ret = -EINVAL;
@@ -1751,6 +1746,10 @@ static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
 
 		str = strstrip(str);
 		attrs->clock = kstrdup(str, GFP_KERNEL);
+		if (!attrs->clock) {
+			ret = -ENOMEM;
+			goto out;
+		}
 	} else if (strncmp(str, "size=", strlen("size=")) == 0) {
 		int map_bits = parse_map_size(str);
 
@@ -1816,8 +1815,10 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
 
 	if (!attrs->clock) {
 		attrs->clock = kstrdup("global", GFP_KERNEL);
-		if (!attrs->clock)
+		if (!attrs->clock) {
+			ret = -ENOMEM;
 			goto free;
+		}
 	}
 
 	return attrs;
@@ -1842,19 +1843,22 @@ static inline void save_comm(char *comm, struct task_struct *task)
 	memcpy(comm, task->comm, TASK_COMM_LEN);
 }
 
+static void hist_elt_data_free(struct hist_elt_data *elt_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < SYNTH_FIELDS_MAX; i++)
+		kfree(elt_data->field_var_str[i]);
+
+	kfree(elt_data->comm);
+	kfree(elt_data);
+}
+
 static void hist_trigger_elt_data_free(struct tracing_map_elt *elt)
 {
-	struct hist_trigger_data *hist_data = elt->map->private_data;
-	struct hist_elt_data *private_data = elt->private_data;
-	unsigned int i, n_str;
+	struct hist_elt_data *elt_data = elt->private_data;
 
-	n_str = hist_data->n_field_var_str + hist_data->n_max_var_str;
-
-	for (i = 0; i < n_str; i++)
-		kfree(private_data->field_var_str[i]);
-
-	kfree(private_data->comm);
-	kfree(private_data);
+	hist_elt_data_free(elt_data);
 }
 
 static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
@@ -1865,7 +1869,7 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
 	struct hist_field *key_field;
 	unsigned int i, n_str;
 
-	elt->private_data = elt_data = kzalloc(sizeof(*elt_data), GFP_KERNEL);
+	elt_data = kzalloc(sizeof(*elt_data), GFP_KERNEL);
 	if (!elt_data)
 		return -ENOMEM;
 
@@ -1876,7 +1880,6 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
 			elt_data->comm = kzalloc(size, GFP_KERNEL);
 			if (!elt_data->comm) {
 				kfree(elt_data);
-				elt->private_data = NULL;
 				return -ENOMEM;
 			}
 			break;
@@ -1890,20 +1893,22 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
 	for (i = 0; i < n_str; i++) {
 		elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);
 		if (!elt_data->field_var_str[i]) {
-			hist_trigger_elt_data_free(elt);
+			hist_elt_data_free(elt_data);
 			return -ENOMEM;
 		}
 	}
 
+	elt->private_data = elt_data;
+
 	return 0;
 }
 
 static void hist_trigger_elt_data_init(struct tracing_map_elt *elt)
 {
-	struct hist_elt_data *private_data = elt->private_data;
+	struct hist_elt_data *elt_data = elt->private_data;
 
-	if (private_data->comm)
-		save_comm(private_data->comm, current);
+	if (elt_data->comm)
+		save_comm(elt_data->comm, current);
 }
 
 static const struct tracing_map_ops hist_trigger_elt_data_ops = {
@@ -2371,7 +2376,15 @@ struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
 		s = strchr(++s, '.');
 		if (s) {
 			ref_system = strsep(&str, ".");
+			if (!str) {
+				ret = -EINVAL;
+				goto out;
+			}
 			ref_event = strsep(&str, ".");
+			if (!str) {
+				ret = -EINVAL;
+				goto out;
+			}
 			ref_var = str;
 		}
 	}
@@ -2452,8 +2465,10 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
 	}
 
 	strsep(&str, "(");
-	if (!str)
+	if (!str) {
+		ret = -EINVAL;
 		goto free;
+	}
 
 	flags |= HIST_FIELD_FL_EXPR;
 	expr = create_hist_field(hist_data, NULL, flags, var_name);
@@ -3111,8 +3126,10 @@ static int onmax_create(struct hist_trigger_data *hist_data,
 
 	for (i = 0; i < data->n_params; i++) {
 		param = kstrdup(data->params[i], GFP_KERNEL);
-		if (!param)
+		if (!param) {
+			ret = -ENOMEM;
 			goto out;
+		}
 
 		field_var = create_target_field_var(hist_data, NULL, NULL, param);
 		if (IS_ERR(field_var)) {
@@ -3144,8 +3161,10 @@ static int parse_action_params(char *params, struct action_data *data)
 			goto out;
 
 		param = strsep(&params, ",");
-		if (!param)
+		if (!param) {
+			ret = -EINVAL;
 			goto out;
+		}
 
 		param = strstrip(param);
 		if (strlen(param) < 2) {
@@ -3196,8 +3215,10 @@ static struct action_data *onmax_parse(char *str)
 	if (strncmp(onmax_fn_name, "save", strlen("save")) == 0) {
 		char *params = strsep(&str, ")");
 
-		if (!params)
+		if (!params) {
+			ret = -EINVAL;
 			goto free;
+		}
 
 		ret = parse_action_params(params, data);
 		if (ret)
@@ -3231,11 +3252,11 @@ static void onmatch_destroy(struct action_data *data)
 	for (i = 0; i < data->n_params; i++)
 		kfree(data->params[i]);
 
-	kfree(data);
-
 	if (data->onmatch.synth_event)
 		data->onmatch.synth_event->ref--;
 
+	kfree(data);
+
 	mutex_unlock(&synth_event_mutex);
 }
 
@@ -3372,13 +3393,13 @@ static int onmatch_create(struct hist_trigger_data *hist_data,
 	int ret = 0;
 
 	mutex_lock(&synth_event_mutex);
-
 	event = find_synth_event(data->onmatch.synth_event_name);
 	if (!event) {
 		hist_err("onmatch: Couldn't find synthetic event: ", data->onmatch.synth_event_name);
-		ret = -EINVAL;
-		goto out;
+		mutex_unlock(&synth_event_mutex);
+		return -EINVAL;
 	}
+	mutex_unlock(&synth_event_mutex);
 
 	var_ref_idx = hist_data->n_var_refs;
 
@@ -3386,8 +3407,10 @@ static int onmatch_create(struct hist_trigger_data *hist_data,
 		char *p;
 
 		p = param = kstrdup(data->params[i], GFP_KERNEL);
-		if (!param)
+		if (!param) {
+			ret = -ENOMEM;
 			goto out;
+		}
 
 		system = strsep(&param, ".");
 		if (!param) {
@@ -3401,6 +3424,7 @@ static int onmatch_create(struct hist_trigger_data *hist_data,
 				goto out;
 			}
 		}
+
 		if (param[0] == '$')
 			hist_field = onmatch_find_var(hist_data, data, system,
 						      event_name, param);
@@ -3449,8 +3473,6 @@ static int onmatch_create(struct hist_trigger_data *hist_data,
 	hist_data->actions[hist_data->n_actions++] = data;
 	event->ref++;
  out:
-	mutex_unlock(&synth_event_mutex);
-
 	return ret;
 }
 
@@ -4839,11 +4861,10 @@ static bool hist_trigger_match(struct event_trigger_data *data,
 			return false;
 		if (key_field->is_signed != key_field_test->is_signed)
 			return false;
-		if ((key_field->var.name && !key_field_test->var.name) ||
-		    (!key_field->var.name && key_field_test->var.name))
+		if (!!key_field->var.name != !!key_field_test->var.name)
 			return false;
-		if ((key_field->var.name && key_field_test->var.name) &&
-		     strcmp(key_field->var.name, key_field_test->var.name) != 0)
+		if (key_field->var.name &&
+		    strcmp(key_field->var.name, key_field_test->var.name) != 0)
 			return false;
 	}
 
@@ -5026,8 +5047,10 @@ static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops,
 	if (unregistered && test->ops->free)
 		test->ops->free(test->ops, test);
 
-	if (hist_data->enable_timestamps)
-		tracing_set_time_stamp_abs(file->tr, false);
+	if (hist_data->enable_timestamps) {
+		if (!hist_data->remove || unregistered)
+			tracing_set_time_stamp_abs(file->tr, false);
+	}
 }
 
 static bool hist_file_check_refs(struct trace_event_file *file)
@@ -5040,7 +5063,6 @@ static bool hist_file_check_refs(struct trace_event_file *file)
 			hist_data = test->private_data;
 			if (check_var_refs(hist_data))
 				return true;
-			break;
 		}
 	}
 
@@ -5092,7 +5114,10 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
 	if (glob[0] == '!')
 		remove = true;
 
-	/* separate the trigger from the filter (k:v [if filter]) */
+	/*
+	 * separate the trigger from the filter (k:v [if filter])
+	 * allowing for whitespace in the trigger
+	 */
 	trigger = param;
 	p = strstr(param, " if");
 	if (!p)
@@ -5396,8 +5421,6 @@ static __init int trace_events_hist_init(void)
 		goto err;
 	}
 
-	hist_err_alloc();
-
 	return err;
  err:
 	pr_warn("Could not create tracefs 'synthetic_events' entry\n");
diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c
index f8e2338dec6e..5cadb1b8b5fe 100644
--- a/kernel/trace/tracing_map.c
+++ b/kernel/trace/tracing_map.c
@@ -524,6 +524,7 @@ __tracing_map_insert(struct tracing_map *map, void *key, bool lookup_only)
 	u32 idx, key_hash, test_key;
 	int dup_try = 0;
 	struct tracing_map_entry *entry;
+	struct tracing_map_elt *val;
 
 	key_hash = jhash(key, map->key_size, 0);
 	if (key_hash == 0)
@@ -536,12 +537,13 @@ __tracing_map_insert(struct tracing_map *map, void *key, bool lookup_only)
 		test_key = entry->key;
 
 		if (test_key && test_key == key_hash) {
-			if (entry->val &&
-			    keys_match(key, entry->val->key, map->key_size)) {
+			val = READ_ONCE(entry->val);
+			if (val &&
+			    keys_match(key, val->key, map->key_size)) {
 				if (!lookup_only)
 					atomic64_inc(&map->hits);
-				return entry->val;
-			} else if (unlikely(!entry->val)) {
+				return val;
+			} else if (unlikely(!val)) {
 				/*
 				 * The key is present. But, val (pointer to elt
 				 * struct) is still NULL. which means some other
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 1c5957f23b9a..685c50ae6300 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -197,9 +197,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
 	struct tracepoint_func *old, *tp_funcs;
 	int ret;
 
-	if (tp->regfunc &&
-	    ((tp->dynamic && !(atomic_read(&tp->key.enabled) > 0)) ||
-	     !static_key_enabled(&tp->key))) {
+	if (tp->regfunc && !static_key_enabled(&tp->key)) {
 		ret = tp->regfunc();
 		if (ret < 0)
 			return ret;
@@ -221,9 +219,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
 	 * is used.
 	 */
 	rcu_assign_pointer(tp->funcs, tp_funcs);
-	if (tp->dynamic && !(atomic_read(&tp->key.enabled) > 0))
-		atomic_inc(&tp->key.enabled);
-	else if (!tp->dynamic && !static_key_enabled(&tp->key))
+	if (!static_key_enabled(&tp->key))
 		static_key_slow_inc(&tp->key);
 	release_probes(old);
 	return 0;
@@ -250,14 +246,10 @@ static int tracepoint_remove_func(struct tracepoint *tp,
 
 	if (!tp_funcs) {
 		/* Removed last function */
-		if (tp->unregfunc &&
-		    ((tp->dynamic && (atomic_read(&tp->key.enabled) > 0)) ||
-		     static_key_enabled(&tp->key)))
+		if (tp->unregfunc && static_key_enabled(&tp->key))
 			tp->unregfunc();
 
-		if (tp->dynamic && (atomic_read(&tp->key.enabled) > 0))
-			atomic_dec(&tp->key.enabled);
-		else if (!tp->dynamic && static_key_enabled(&tp->key))
+		if (static_key_enabled(&tp->key))
 			static_key_slow_dec(&tp->key);
 	}
 	rcu_assign_pointer(tp->funcs, tp_funcs);
@@ -266,7 +258,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,
 }
 
 /**
- * tracepoint_probe_register_prio -  Connect a probe to a tracepoint
+ * tracepoint_probe_register -  Connect a probe to a tracepoint
  * @tp: tracepoint
  * @probe: probe handler
  * @data: tracepoint data
diff --git a/localversion-rt b/localversion-rt
index c3054d08a112..1445cd65885c 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt2
+-rt3
