void (*call)(const struct marker *mdata, void *call_private, ...);
        struct marker_probe_closure single;
        struct marker_probe_closure *multi;
+       const char *tp_name;    /* Optional tracepoint name */
+       void *tp_cb;            /* Optional tracepoint callback */
 } __attribute__((aligned(8)));
 
 #ifdef CONFIG_MARKERS
                __attribute__((section("__markers"), aligned(8))) =     \
                { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)],   \
                0, 0, marker_probe_cb,                                  \
-               { __mark_empty_function, NULL}, NULL };                 \
+               { __mark_empty_function, NULL}, NULL, NULL, NULL };     \
                __mark_check_format(format, ## args);                   \
                if (unlikely(__mark_##name.state)) {                    \
                        (*__mark_##name.call)                           \
                }                                                       \
        } while (0)
 
+#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
+       do {                                                            \
+               void __check_tp_type(void)                              \
+               {                                                       \
+                       register_trace_##tp_name(tp_cb);                \
+               }                                                       \
+               static const char __mstrtab_##name[]                    \
+               __attribute__((section("__markers_strings")))           \
+               = #name "\0" format;                                    \
+               static struct marker __mark_##name                      \
+               __attribute__((section("__markers"), aligned(8))) =     \
+               { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)],   \
+               0, 0, marker_probe_cb,                                  \
+               { __mark_empty_function, NULL}, NULL, #tp_name, tp_cb };\
+               __mark_check_format(format, ## args);                   \
+               (*__mark_##name.call)(&__mark_##name, call_private,     \
+                                       ## args);                       \
+       } while (0)
+
 extern void marker_update_probe_range(struct marker *begin,
        struct marker *end);
 #else /* !CONFIG_MARKERS */
 #define __trace_mark(generic, name, call_private, format, args...) \
                __mark_check_format(format, ## args)
+#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
+       do {                                                            \
+               void __check_tp_type(void)                              \
+               {                                                       \
+                       register_trace_##tp_name(tp_cb);                \
+               }                                                       \
+               __mark_check_format(format, ## args);                   \
+       } while (0)
 static inline void marker_update_probe_range(struct marker *begin,
        struct marker *end)
 { }
 #define _trace_mark(name, format, args...) \
        __trace_mark(1, name, NULL, format, ## args)
 
+/**
+ * trace_mark_tp - Marker in a tracepoint callback
+ * @name: marker name, not quoted.
+ * @tp_name: tracepoint name, not quoted.
+ * @tp_cb: tracepoint callback. Should have an associated global symbol so it
+ *         is not optimized away by the compiler (should not be static).
+ * @format: format string
+ * @args...: variable argument list
+ *
+ * Places a marker in a tracepoint callback.
+ */
+#define trace_mark_tp(name, tp_name, tp_cb, format, args...)   \
+       __trace_mark_tp(name, NULL, tp_name, tp_cb, format, ## args)
+
 /**
  * MARK_NOARGS - Format string for a marker with no argument.
  */
 
 static int set_marker(struct marker_entry *entry, struct marker *elem,
                int active)
 {
-       int ret;
+       int ret = 0;
        WARN_ON(strcmp(entry->name, elem->name) != 0);
 
        if (entry->format) {
         */
        smp_wmb();
        elem->ptype = entry->ptype;
+
+       if (elem->tp_name && (active ^ elem->state)) {
+               WARN_ON(!elem->tp_cb);
+               /*
+                * It is ok to directly call the probe registration because type
+                * checking has been done in the __trace_mark_tp() macro.
+                */
+
+               if (active) {
+                       /*
+                        * try_module_get should always succeed because we hold
+                        * lock_module() to get the tp_cb address.
+                        */
+                       ret = try_module_get(__module_text_address(
+                               (unsigned long)elem->tp_cb));
+                       BUG_ON(!ret);
+                       ret = tracepoint_probe_register_noupdate(
+                               elem->tp_name,
+                               elem->tp_cb);
+               } else {
+                       ret = tracepoint_probe_unregister_noupdate(
+                               elem->tp_name,
+                               elem->tp_cb);
+                       /*
+                        * tracepoint_probe_update_all() must be called
+                        * before the module containing tp_cb is unloaded.
+                        */
+                       module_put(__module_text_address(
+                               (unsigned long)elem->tp_cb));
+               }
+       }
        elem->state = active;
 
-       return 0;
+       return ret;
 }
 
 /*
  */
 static void disable_marker(struct marker *elem)
 {
+       int ret;
+
        /* leave "call" as is. It is known statically. */
+       if (elem->tp_name && elem->state) {
+               WARN_ON(!elem->tp_cb);
+               /*
+                * It is ok to directly call the probe registration because type
+                * checking has been done in the __trace_mark_tp() macro.
+                */
+               ret = tracepoint_probe_unregister_noupdate(elem->tp_name,
+                       elem->tp_cb);
+               WARN_ON(ret);
+               /*
+                * tracepoint_probe_update_all() must be called
+                * before the module containing tp_cb is unloaded.
+                */
+               module_put(__module_text_address((unsigned long)elem->tp_cb));
+       }
        elem->state = 0;
        elem->single.func = __mark_empty_function;
        /* Update the function before setting the ptype */
        marker_update_probe_range(__start___markers, __stop___markers);
        /* Markers in modules. */
        module_update_markers();
+       tracepoint_probe_update_all();
 }
 
 /**