diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c2107f..62a29b9cd767 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -19,8 +19,28 @@ void lkdtm_SOFTLOCKUP(void);
 void lkdtm_HARDLOCKUP(void);
 void lkdtm_SPINLOCKUP(void);
 void lkdtm_HUNG_TASK(void);
-void lkdtm_ATOMIC_UNDERFLOW(void);
-void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_OVERFLOW_atomic_inc(void);
+void lkdtm_OVERFLOW_atomic_inc_return(void);
+void lkdtm_OVERFLOW_atomic_inc_and_test(void);
+void lkdtm_OVERFLOW_atomic_add(void);
+void lkdtm_OVERFLOW_atomic_add_return(void);
+void lkdtm_OVERFLOW_atomic_add_unless(void);
+void lkdtm_OVERFLOW_atomic_long_inc(void);
+void lkdtm_OVERFLOW_atomic_long_inc_return(void);
+void lkdtm_OVERFLOW_atomic_long_inc_and_test(void);
+void lkdtm_OVERFLOW_atomic_long_add(void);
+void lkdtm_OVERFLOW_atomic_long_add_return(void);
+void lkdtm_OVERFLOW_atomic_long_add_unless(void);
+void lkdtm_UNDERFLOW_atomic_dec(void);
+void lkdtm_UNDERFLOW_atomic_dec_return(void);
+void lkdtm_UNDERFLOW_atomic_sub(void);
+void lkdtm_UNDERFLOW_atomic_sub_return(void);
+void lkdtm_UNDERFLOW_atomic_sub_and_test(void);
+void lkdtm_UNDERFLOW_atomic_long_dec(void);
+void lkdtm_UNDERFLOW_atomic_long_dec_return(void);
+void lkdtm_UNDERFLOW_atomic_long_sub(void);
+void lkdtm_UNDERFLOW_atomic_long_sub_return(void);
+void lkdtm_UNDERFLOW_atomic_long_sub_and_test(void);
 
 /* lkdtm_heap.c */
 void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae1894b32..2473bd275a87 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -123,26 +123,54 @@ void lkdtm_HUNG_TASK(void)
 	schedule();
 }
 
-void lkdtm_ATOMIC_UNDERFLOW(void)
-{
-	atomic_t under = ATOMIC_INIT(INT_MIN);
-
-	pr_info("attempting good atomic increment\n");
-	atomic_inc(&under);
-	atomic_dec(&under);
-
-	pr_info("attempting bad atomic underflow\n");
-	atomic_dec(&under);
-}
-
-void lkdtm_ATOMIC_OVERFLOW(void)
-{
-	atomic_t over = ATOMIC_INIT(INT_MAX);
-
-	pr_info("attempting good atomic decrement\n");
-	atomic_dec(&over);
-	atomic_inc(&over);
-
-	pr_info("attempting bad atomic overflow\n");
-	atomic_inc(&over);
-}
+/*
+ * Handle the various atomic function prototypes (potentially ignoring
+ * return values).
+ */
+#define ATOMIC_ARG_X(func, x)		func(x)
+#define ATOMIC_ARG_1_X(func, x)		func(1, x)
+#define ATOMIC_RET_ARG_X(func, x)	if (func(x)) ;
+#define ATOMIC_RET_ARG_1_X(func, x)	if (func(1, x)) ;
+#define ATOMIC_RET_ARG_X_1_0(func, x)	if (func(x, 1, 0)) ;
+
+#define ATOMIC_ANY(name, atomic_type, init_func, start, safe_func,	\
+		   test_func_proto, testfunc)				\
+void lkdtm_##name##_##testfunc(void)					\
+{									\
+	atomic_type atomic = init_func(start);				\
+									\
+	pr_info("attempting good " #testfunc "\n");			\
+	safe_func(&atomic);						\
+	test_func_proto(testfunc, &atomic);				\
+									\
+	pr_info("attempting bad " #testfunc "\n");			\
+	test_func_proto(testfunc, &atomic);				\
+}
+
+/* Declare underflow test functions for atomic_t and atomic_long_t types. */
+#define LKDTM_ATOMIC_UNDERFLOW(operation, test_func_proto)		\
+	ATOMIC_ANY(UNDERFLOW, atomic_t, ATOMIC_INIT, INT_MIN,		\
+		   atomic_inc, test_func_proto, atomic_##operation)	\
+	ATOMIC_ANY(UNDERFLOW, atomic_long_t, ATOMIC_LONG_INIT,		\
+		   LONG_MIN, atomic_long_inc, test_func_proto,		\
+		   atomic_long_##operation)
+
+/* Declare overflow test functions for atomic_t and atomic_long_t types. */
+#define LKDTM_ATOMIC_OVERFLOW(operation, test_func_proto)		\
+	ATOMIC_ANY(OVERFLOW, atomic_t, ATOMIC_INIT, INT_MAX,		\
+		   atomic_dec, test_func_proto, atomic_##operation)	\
+	ATOMIC_ANY(OVERFLOW, atomic_long_t, ATOMIC_LONG_INIT,		\
+		   LONG_MAX, atomic_long_dec, test_func_proto,		\
+		   atomic_long_##operation)
+
+LKDTM_ATOMIC_UNDERFLOW(dec,		ATOMIC_ARG_X)
+LKDTM_ATOMIC_UNDERFLOW(dec_return,	ATOMIC_RET_ARG_X)
+LKDTM_ATOMIC_UNDERFLOW(sub,		ATOMIC_ARG_1_X)
+LKDTM_ATOMIC_UNDERFLOW(sub_return,	ATOMIC_RET_ARG_1_X)
+LKDTM_ATOMIC_UNDERFLOW(sub_and_test,	ATOMIC_RET_ARG_1_X)
+LKDTM_ATOMIC_OVERFLOW(inc,		ATOMIC_ARG_X)
+LKDTM_ATOMIC_OVERFLOW(inc_return,	ATOMIC_RET_ARG_X)
+LKDTM_ATOMIC_OVERFLOW(add,		ATOMIC_ARG_1_X)
+LKDTM_ATOMIC_OVERFLOW(add_return,	ATOMIC_RET_ARG_1_X)
+LKDTM_ATOMIC_OVERFLOW(add_unless,	ATOMIC_RET_ARG_X_1_0)
+LKDTM_ATOMIC_OVERFLOW(inc_and_test,	ATOMIC_RET_ARG_X)
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8d67f6..05b097f02ce4 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -218,8 +218,28 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(WRITE_RO),
 	CRASHTYPE(WRITE_RO_AFTER_INIT),
 	CRASHTYPE(WRITE_KERN),
-	CRASHTYPE(ATOMIC_UNDERFLOW),
-	CRASHTYPE(ATOMIC_OVERFLOW),
+	CRASHTYPE(OVERFLOW_atomic_inc),
+	CRASHTYPE(OVERFLOW_atomic_inc_return),
+	CRASHTYPE(OVERFLOW_atomic_inc_and_test),
+	CRASHTYPE(OVERFLOW_atomic_add),
+	CRASHTYPE(OVERFLOW_atomic_add_return),
+	CRASHTYPE(OVERFLOW_atomic_add_unless),
+	CRASHTYPE(OVERFLOW_atomic_long_inc),
+	CRASHTYPE(OVERFLOW_atomic_long_inc_return),
+	CRASHTYPE(OVERFLOW_atomic_long_inc_and_test),
+	CRASHTYPE(OVERFLOW_atomic_long_add),
+	CRASHTYPE(OVERFLOW_atomic_long_add_return),
+	CRASHTYPE(OVERFLOW_atomic_long_add_unless),
+	CRASHTYPE(UNDERFLOW_atomic_dec),
+	CRASHTYPE(UNDERFLOW_atomic_dec_return),
+	CRASHTYPE(UNDERFLOW_atomic_sub),
+	CRASHTYPE(UNDERFLOW_atomic_sub_return),
+	CRASHTYPE(UNDERFLOW_atomic_sub_and_test),
+	CRASHTYPE(UNDERFLOW_atomic_long_dec),
+	CRASHTYPE(UNDERFLOW_atomic_long_dec_return),
+	CRASHTYPE(UNDERFLOW_atomic_long_sub),
+	CRASHTYPE(UNDERFLOW_atomic_long_sub_return),
+	CRASHTYPE(UNDERFLOW_atomic_long_sub_and_test),
 	CRASHTYPE(USERCOPY_HEAP_SIZE_TO),
 	CRASHTYPE(USERCOPY_HEAP_SIZE_FROM),
 	CRASHTYPE(USERCOPY_HEAP_FLAG_TO),
