1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_RATELIMIT_H
3#define _LINUX_RATELIMIT_H
4
5#include <linux/ratelimit_types.h>
6#include <linux/sched.h>
7#include <linux/spinlock.h>
8
9static inline void ratelimit_state_init(struct ratelimit_state *rs,
10					int interval, int burst)
11{
12	memset(rs, 0, sizeof(*rs));
13
14	raw_spin_lock_init(&rs->lock);
15	rs->interval	= interval;
16	rs->burst	= burst;
17}
18
19static inline void ratelimit_default_init(struct ratelimit_state *rs)
20{
21	return ratelimit_state_init(rs, DEFAULT_RATELIMIT_INTERVAL,
22					DEFAULT_RATELIMIT_BURST);
23}
24
25static inline void ratelimit_state_exit(struct ratelimit_state *rs)
26{
27	if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE))
28		return;
29
30	if (rs->missed) {
31		pr_warn("%s: %d output lines suppressed due to ratelimiting\n",
32			current->comm, rs->missed);
33		rs->missed = 0;
34	}
35}
36
37static inline void
38ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags)
39{
40	rs->flags = flags;
41}
42
43extern struct ratelimit_state printk_ratelimit_state;
44
45#ifdef CONFIG_PRINTK
46
47#define WARN_ON_RATELIMIT(condition, state)	({		\
48	bool __rtn_cond = !!(condition);			\
49	WARN_ON(__rtn_cond && __ratelimit(state));		\
50	__rtn_cond;						\
51})
52
53#define WARN_RATELIMIT(condition, format, ...)			\
54({								\
55	static DEFINE_RATELIMIT_STATE(_rs,			\
56				      DEFAULT_RATELIMIT_INTERVAL,	\
57				      DEFAULT_RATELIMIT_BURST);	\
58	int rtn = !!(condition);				\
59								\
60	if (unlikely(rtn && __ratelimit(&_rs)))			\
61		WARN(rtn, format, ##__VA_ARGS__);		\
62								\
63	rtn;							\
64})
65
66#else
67
68#define WARN_ON_RATELIMIT(condition, state)			\
69	WARN_ON(condition)
70
71#define WARN_RATELIMIT(condition, format, ...)			\
72({								\
73	int rtn = WARN(condition, format, ##__VA_ARGS__);	\
74	rtn;							\
75})
76
77#endif
78
79#endif /* _LINUX_RATELIMIT_H */
80