Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/errseq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * An errseq_t is a way of recording errors in one place, and allowing any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * number of "subscribers" to tell whether it has changed since a previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * point where it was sampled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * It's implemented as an unsigned 32-bit value. The low order bits are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * designated to hold an error code (between 0 and -MAX_ERRNO). The upper bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * are used as a counter. This is done with atomics instead of locking so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * these functions can be called from any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * The general idea is for consumers to sample an errseq_t value. That value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * can later be used to tell whether any new errors have occurred since that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * sampling was done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Note that there is a risk of collisions if new errors are being recorded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * frequently, since we have so few bits to use as a counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * To mitigate this, one bit is used as a flag to tell whether the value has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * been sampled since a new value was recorded. That allows us to avoid bumping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * the counter if no one has sampled it since the last time an error was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * recorded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * A new errseq_t should always be zeroed out.  A errseq_t value of all zeroes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * is the special (but common) case where there has never been an error. An all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * zero value thus serves as the "epoch" if one wishes to know whether there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * has ever been an error set since it was first initialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /* The low bits are designated for error code (max of MAX_ERRNO) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define ERRSEQ_SHIFT		ilog2(MAX_ERRNO + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) /* This bit is used as a flag to indicate whether the value has been seen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define ERRSEQ_SEEN		(1 << ERRSEQ_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) /* The lowest bit of the counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define ERRSEQ_CTR_INC		(1 << (ERRSEQ_SHIFT + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * errseq_set - set a errseq_t for later reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * @eseq: errseq_t field that should be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * @err: error to set (must be between -1 and -MAX_ERRNO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * This function sets the error in @eseq, and increments the sequence counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * if the last sequence was sampled at some point in the past.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * Any error set will always overwrite an existing error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * Return: The previous value, primarily for debugging purposes. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * return value should not be used as a previously sampled value in later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * calls as it will not have the SEEN flag set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) errseq_t errseq_set(errseq_t *eseq, int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	errseq_t cur, old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	/* MAX_ERRNO must be able to serve as a mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	BUILD_BUG_ON_NOT_POWER_OF_2(MAX_ERRNO + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	 * Ensure the error code actually fits where we want it to go. If it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	 * doesn't then just throw a warning and don't record anything. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	 * also don't accept zero here as that would effectively clear a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	 * previous error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (WARN(unlikely(err == 0 || (unsigned int)-err > MAX_ERRNO),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 				"err = %d\n", err))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		errseq_t new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		/* Clear out error bits and set new error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		new = (old & ~(MAX_ERRNO|ERRSEQ_SEEN)) | -err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		/* Only increment if someone has looked at it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		if (old & ERRSEQ_SEEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			new += ERRSEQ_CTR_INC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		/* If there would be no change, then call it done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		if (new == old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			cur = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		/* Try to swap the new value into place */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		cur = cmpxchg(eseq, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		 * Call it success if we did the swap or someone else beat us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		 * to it for the same value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		if (likely(cur == old || cur == new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		/* Raced with an update, try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		old = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	return cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) EXPORT_SYMBOL(errseq_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * errseq_sample() - Grab current errseq_t value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @eseq: Pointer to errseq_t to be sampled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * This function allows callers to initialise their errseq_t variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * If the error has been "seen", new callers will not see an old error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * If there is an unseen error in @eseq, the caller of this function will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * see it the next time it checks for an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * Context: Any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * Return: The current errseq value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) errseq_t errseq_sample(errseq_t *eseq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	errseq_t old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	/* If nobody has seen this error yet, then we can be the first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (!(old & ERRSEQ_SEEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		old = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) EXPORT_SYMBOL(errseq_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  * errseq_check() - Has an error occurred since a particular sample point?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  * @eseq: Pointer to errseq_t value to be checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  * @since: Previously-sampled errseq_t from which to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  * Grab the value that eseq points to, and see if it has changed @since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * the given value was sampled. The @since value is not advanced, so there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * is no need to mark the value as seen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * Return: The latest error set in the errseq_t or 0 if it hasn't changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int errseq_check(errseq_t *eseq, errseq_t since)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	errseq_t cur = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (likely(cur == since))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return -(cur & MAX_ERRNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) EXPORT_SYMBOL(errseq_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * errseq_check_and_advance() - Check an errseq_t and advance to current value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * @eseq: Pointer to value being checked and reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * @since: Pointer to previously-sampled errseq_t to check against and advance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  * Grab the eseq value, and see whether it matches the value that @since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  * points to. If it does, then just return 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  * If it doesn't, then the value has changed. Set the "seen" flag, and try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  * swap it into place as the new eseq value. Then, set that value as the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  * "since" value, and return whatever the error portion is set to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * Note that no locking is provided here for concurrent updates to the "since"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  * value. The caller must provide that if necessary. Because of this, callers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  * may want to do a lockless errseq_check before taking the lock and calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  * Return: Negative errno if one has been stored, or 0 if no new error has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  * occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int errseq_check_and_advance(errseq_t *eseq, errseq_t *since)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	errseq_t old, new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * Most callers will want to use the inline wrapper to check this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * so that the common case of no error is handled without needing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * to take the lock that protects the "since" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (old != *since) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		 * Set the flag and try to swap it into place if it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		 * changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		 * We don't care about the outcome of the swap here. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		 * swap doesn't occur, then it has either been updated by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		 * writer who is altering the value in some way (updating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		 * counter or resetting the error), or another reader who is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		 * just setting the "seen" flag. Either outcome is OK, and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		 * can advance "since" and return an error based on what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		 * have.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		new = old | ERRSEQ_SEEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		if (new != old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			cmpxchg(eseq, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		*since = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		err = -(new & MAX_ERRNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) EXPORT_SYMBOL(errseq_check_and_advance);