mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
Merge tag 'char-misc-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc/IIO/etc driver updates from Greg KH:
"Here is the big set of char, misc, iio, counter, fpga, and other small
driver subsystems for 7.3-rc1.
Overall, due to some driver removals we only added a bit more code
than removed, which was a nice change. Highlights in this merge
request are:
- Loads of IIO driver updates and additions
- binder driver updates (more on that below...)
- Removal of the SGI XP and GRU drivers as they are not used anymore
and turn out to be pretty insecure overall
- Removal of the obsolete ibmasm driver as it's not being used
anymore
- Coresight driver updates and additions
- Mei driver udpates
- Counter driver updates
- FPGA driver updates
- ICC driver updates
- lots and lots of other tiny driver updates to resolve reported
issues
All of these have been in linux-next for a while"
* tag 'char-misc-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (513 commits)
iio: chemical: atlas-sensor: use iio_trigger_poll_nested() to fix remove UAF
iio: adc: pac1921: fix wrong channel used in trigger handler read
iio: light: gp2ap002: re-enable irq if runtime suspend fails
iio: light: gp2ap002: Fix unbalanced runtime PM on repeated event writes
iio: light: apds9306: fix PM reference leak in apds9306_read_data()
iio: gyro: mpu3050: fix sign of raw angular velocity readings
iio: srf04: fix pm_runtime handling on probe error path
iio: adc: ad4080: configure backend data size
iio: adc: adi-axi-adc: add data size support for AD408X backend
iio: chemical: atlas-sensor: fix PM reference leak in buffer postenable
iio: dac: ad5446: fix OF module device table
iio: light: opt4001: Fix reversed GENMASK() arguments in fault count mask
iio: light: opt4001: Reject integration times with a non-zero seconds part
iio: light: opt4001: Fix incompatible pointer type passed to div_u64_rem()
iio: light: opt4001: Fix power down clearing bits of the wrong register
iio: light: opt4060: Fix incorrect register name in threshold read error message
iio: light: opt4060: Fix pointer type passed to div_u64_rem()
iio: light: opt4060: Reject integration times with a non-zero seconds part
iio: light: ltrf216a: fix runtime PM reference leak in error path
iio: pressure: dps310: fix NULL pointer dereference on ACPI probe
...
This commit is contained in:
+107
-8
@@ -17,6 +17,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
@@ -45,6 +46,7 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
|
||||
* @base: Radix
|
||||
* @p: Where to store result
|
||||
* @max_chars: Maximum amount of characters to convert
|
||||
* @init: Initial value of the multiply-accumulate result
|
||||
*
|
||||
* Convert non-negative integer string representation in explicitly given
|
||||
* radix to an integer. If overflow occurs, value at @p is set to ULLONG_MAX.
|
||||
@@ -56,12 +58,12 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
|
||||
*/
|
||||
noinline
|
||||
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
|
||||
size_t max_chars)
|
||||
size_t max_chars, unsigned long long init)
|
||||
{
|
||||
unsigned int rv, overflow = 0;
|
||||
unsigned long long res;
|
||||
|
||||
res = 0;
|
||||
res = init;
|
||||
for (rv = 0; rv < max_chars; rv++, s++) {
|
||||
unsigned int c = *s;
|
||||
unsigned int lc = _tolower(c);
|
||||
@@ -94,12 +96,6 @@ unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned lon
|
||||
return rv | overflow;
|
||||
}
|
||||
|
||||
noinline
|
||||
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
|
||||
{
|
||||
return _parse_integer_limit(s, base, p, INT_MAX);
|
||||
}
|
||||
|
||||
static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
|
||||
{
|
||||
unsigned long long _res;
|
||||
@@ -399,6 +395,109 @@ int kstrtobool(const char *s, bool *res)
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtobool);
|
||||
|
||||
static int _kstrtoudec64(const char *s, unsigned int scale, u64 *res)
|
||||
{
|
||||
unsigned int rv_int, rv_frac;
|
||||
u64 _res = 0;
|
||||
|
||||
rv_int = _parse_integer(s, 10, &_res);
|
||||
if (rv_int & KSTRTOX_OVERFLOW)
|
||||
return -ERANGE;
|
||||
s += rv_int;
|
||||
|
||||
if (*s == '.')
|
||||
s++; /* skip decimal point */
|
||||
|
||||
rv_frac = _parse_integer(s, 10, &_res, scale, _res);
|
||||
if (rv_frac & KSTRTOX_OVERFLOW)
|
||||
return -ERANGE;
|
||||
s += rv_frac;
|
||||
|
||||
/*
|
||||
* Check input beyond rv_int and rv_frac to cover cases like ".5" with
|
||||
* scale 0, which is considered a valid input, being parsed as 0.
|
||||
*/
|
||||
if (!rv_int && !rv_frac && !isdigit(*s))
|
||||
return -EINVAL;
|
||||
|
||||
while (isdigit(*s)) /* truncate digits */
|
||||
s++;
|
||||
|
||||
if (*s == '\n')
|
||||
s++;
|
||||
if (*s)
|
||||
return -EINVAL;
|
||||
|
||||
if (_res && ((scale - rv_frac) > 19 /* log10(2^64) = 19.26 */ ||
|
||||
check_mul_overflow(_res, int_pow(10, scale - rv_frac), &_res)))
|
||||
return -ERANGE;
|
||||
|
||||
*res = _res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kstrtoudec64() - Convert a string to an unsigned 64-bit scaled decimal value.
|
||||
* @s: The start of the string. The string must be null-terminated, and may also
|
||||
* include a single newline before its terminating null. The first character
|
||||
* may also be a plus sign, but not a minus sign.
|
||||
* @scale: The number of digits to the right of the decimal point.
|
||||
* @res: Where to write the result of the conversion on success.
|
||||
*
|
||||
* For example, a scale of 3 with input "123.45" results in 123450. Note that
|
||||
* trailing zeros in the fractional part input to match the scale are not
|
||||
* required. Also, digits beyond the specified scale are ignored.
|
||||
*
|
||||
* Return: 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
*/
|
||||
noinline
|
||||
int kstrtoudec64(const char *s, unsigned int scale, u64 *res)
|
||||
{
|
||||
if (s[0] == '+')
|
||||
s++;
|
||||
return _kstrtoudec64(s, scale, res);
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtoudec64);
|
||||
|
||||
/**
|
||||
* kstrtodec64() - Convert a string to a signed 64-bit scaled decimal value.
|
||||
* @s: The start of the string. The string must be null-terminated, and may also
|
||||
* include a single newline before its terminating null. The first character
|
||||
* may also be a plus sign or a minus sign.
|
||||
* @scale: The number of digits to the right of the decimal point.
|
||||
* @res: Where to write the result of the conversion on success.
|
||||
*
|
||||
* For example, a scale of 4 with input "-3.141592" results in -31415. Note
|
||||
* that digits beyond the specified scale are ignored. Also, trailing zeros in
|
||||
* the fractional part input to match the scale are not required.
|
||||
*
|
||||
* Return: 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
*/
|
||||
noinline
|
||||
int kstrtodec64(const char *s, unsigned int scale, s64 *res)
|
||||
{
|
||||
u64 tmp;
|
||||
int rv;
|
||||
|
||||
if (s[0] == '-') {
|
||||
rv = _kstrtoudec64(s + 1, scale, &tmp);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
if ((s64)-tmp > 0)
|
||||
return -ERANGE;
|
||||
*res = -tmp;
|
||||
} else {
|
||||
rv = kstrtoudec64(s, scale, &tmp);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
if ((s64)tmp < 0)
|
||||
return -ERANGE;
|
||||
*res = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtodec64);
|
||||
|
||||
/*
|
||||
* Since "base" would be a nonsense argument, this open-codes the
|
||||
* _from_user helper instead of using the helper macro below.
|
||||
|
||||
+15
-2
@@ -2,10 +2,23 @@
|
||||
#ifndef _LIB_KSTRTOX_H
|
||||
#define _LIB_KSTRTOX_H
|
||||
|
||||
#include <linux/args.h>
|
||||
|
||||
#define KSTRTOX_OVERFLOW (1U << 31)
|
||||
const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
|
||||
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *res,
|
||||
size_t max_chars);
|
||||
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res);
|
||||
size_t max_chars, unsigned long long init);
|
||||
|
||||
#define _parse_integer0(s, base, res, ...) \
|
||||
_parse_integer_limit(s, base, res, INT_MAX, 0)
|
||||
|
||||
#define _parse_integer1(s, base, res, max_chars, ...) \
|
||||
_parse_integer_limit(s, base, res, max_chars, 0)
|
||||
|
||||
#define _parse_integer2(s, base, res, max_chars, init, ...) \
|
||||
_parse_integer_limit(s, base, res, max_chars, init)
|
||||
|
||||
#define _parse_integer(s, base, res, ...) \
|
||||
CONCATENATE(_parse_integer, COUNT_ARGS(__VA_ARGS__))(s, base, res, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -158,6 +158,21 @@ u64 div64_u64(u64 dividend, u64 divisor)
|
||||
EXPORT_SYMBOL(div64_u64);
|
||||
#endif
|
||||
|
||||
#ifndef div64_s64_rem
|
||||
s64 div64_s64_rem(s64 dividend, s64 divisor, s64 *remainder)
|
||||
{
|
||||
s64 quot, t, rem;
|
||||
|
||||
quot = div64_u64_rem(abs(dividend), abs(divisor), (u64 *)&rem);
|
||||
t = dividend >> 63;
|
||||
*remainder = (rem ^ t) - t;
|
||||
t = (dividend ^ divisor) >> 63;
|
||||
|
||||
return (quot ^ t) - t;
|
||||
}
|
||||
EXPORT_SYMBOL(div64_s64_rem);
|
||||
#endif
|
||||
|
||||
#ifndef div64_s64
|
||||
s64 div64_s64(s64 dividend, s64 divisor)
|
||||
{
|
||||
|
||||
@@ -157,6 +157,7 @@ static void __exit test_exit(void)
|
||||
#define __div64_32 __div64_32
|
||||
#define div_s64_rem div_s64_rem
|
||||
#define div64_u64_rem div64_u64_rem
|
||||
#define div64_s64_rem div64_s64_rem
|
||||
#define div64_u64 div64_u64
|
||||
#define div64_s64 div64_s64
|
||||
#define iter_div_u64_rem iter_div_u64_rem
|
||||
|
||||
@@ -709,6 +709,182 @@ static void __init test_kstrtos8_fail(void)
|
||||
TEST_FAIL(kstrtos8, s8, "%hhd", test_s8_fail);
|
||||
}
|
||||
|
||||
static void __init test_kstrtoudec64_ok(void)
|
||||
{
|
||||
DECLARE_TEST_OK(u64, struct test_udec64);
|
||||
static DEFINE_TEST_OK(struct test_udec64, test_udec64_ok) = {
|
||||
/* basic: integer.fraction, exact digits */
|
||||
{"0.0", 1, 0},
|
||||
{"1.5", 1, 15},
|
||||
{"1.234", 3, 1234},
|
||||
{"42.0", 1, 420},
|
||||
/* zero */
|
||||
{"0.0", 1, 0},
|
||||
{"0.000", 3, 0},
|
||||
/* integer only */
|
||||
{"0", 1, 0},
|
||||
{"42", 3, 42000},
|
||||
{"123.", 2, 12300},
|
||||
{"1", 1, 10},
|
||||
/* fractional only (leading dot) */
|
||||
{".5", 1, 5},
|
||||
{".5", 0, 0},
|
||||
{".123", 3, 123},
|
||||
{".001", 3, 1},
|
||||
/* zero padding: fewer fractional digits than scale */
|
||||
{"1.2", 3, 1200},
|
||||
{"1.2", 6, 1200000},
|
||||
{"0.01", 3, 10},
|
||||
{"0.1", 9, 100000000ULL},
|
||||
{"0.01", 9, 10000000},
|
||||
/* truncation: more fractional digits than scale */
|
||||
{"1.23456", 3, 1234},
|
||||
{"3.1415926535", 6, 3141592},
|
||||
{"0.999999999", 3, 999},
|
||||
{"1.99", 1, 19},
|
||||
{"1.234", 0, 1},
|
||||
/* trailing newline */
|
||||
{"1.5\n", 1, 15},
|
||||
{"42\n", 3, 42000},
|
||||
/* plus sign */
|
||||
{"+1.5", 1, 15},
|
||||
{"+.5", 1, 5},
|
||||
/* scale progression */
|
||||
{"1.", 0, 1},
|
||||
{"1.0", 1, 10},
|
||||
{"1.00", 2, 100},
|
||||
{"1.000", 3, 1000},
|
||||
{"1.000000", 6, 1000000},
|
||||
{"1.000000000", 9, 1000000000ULL},
|
||||
/* max limit check */
|
||||
{"18446744073.709551615", 9, ULLONG_MAX},
|
||||
{"18446744073709.551615", 6, ULLONG_MAX},
|
||||
{"0.18446744073709551615", 20, ULLONG_MAX},
|
||||
/* scale > 19: representable when integer part is small */
|
||||
{"0.00000000000000000001", 20, 1},
|
||||
{"0.1", 20, 10000000000000000000ULL},
|
||||
{"0.00000000000000000000001", 23, 1},
|
||||
/* truncation with scale > 19 */
|
||||
{"0.0000000000000000000012345", 23, 123},
|
||||
/* truncation with many excess digits */
|
||||
{"0.00000000000000000000000000000000423", 34, 42},
|
||||
{"1.99999999999999999999999999999999999", 3, 1999},
|
||||
};
|
||||
TEST_OK(kstrtoudec64, u64, "%llu", test_udec64_ok);
|
||||
}
|
||||
|
||||
static void __init test_kstrtoudec64_fail(void)
|
||||
{
|
||||
static DEFINE_TEST_FAIL(test_udec64_fail) = {
|
||||
/* empty / whitespace */
|
||||
{"", 3},
|
||||
{"\n", 3},
|
||||
/* minus sign (unsigned) */
|
||||
{"-1.5", 1},
|
||||
{"-0.5", 1},
|
||||
/* only a decimal point */
|
||||
{".", 3},
|
||||
{".", 0},
|
||||
/* only a sign */
|
||||
{"+", 3},
|
||||
/* non-digit characters */
|
||||
{"abc", 3},
|
||||
{"1.2x", 3},
|
||||
/* leading/trailing space */
|
||||
{" 1.5", 1},
|
||||
{"1.5 ", 1},
|
||||
/* overflow */
|
||||
{"18446744073710.551615", 6},
|
||||
{"99999999999999999999", 1},
|
||||
/* overflow with scale > 19 */
|
||||
{"1.0", 21},
|
||||
{"0.2", 20},
|
||||
{"0.18446744073709551616", 20},
|
||||
{"1", 20},
|
||||
};
|
||||
TEST_FAIL(kstrtoudec64, u64, "%llu", test_udec64_fail);
|
||||
}
|
||||
|
||||
static void __init test_kstrtodec64_ok(void)
|
||||
{
|
||||
DECLARE_TEST_OK(s64, struct test_dec64);
|
||||
static DEFINE_TEST_OK(struct test_dec64, test_dec64_ok) = {
|
||||
/* basic positive */
|
||||
{"0.0", 1, 0},
|
||||
{"1.5", 1, 15},
|
||||
{"1.234", 3, 1234},
|
||||
/* basic negative */
|
||||
{"-1.5", 1, -15},
|
||||
{"-1.234", 3, -1234},
|
||||
{"-0.5", 1, -5},
|
||||
{"-0.001", 3, -1},
|
||||
/* zero (signed) */
|
||||
{"-0", 1, 0},
|
||||
{"-0.0", 1, 0},
|
||||
{"0.000", 3, 0},
|
||||
/* integer only */
|
||||
{"42", 3, 42000},
|
||||
{"-42", 3, -42000},
|
||||
/* fractional only */
|
||||
{".5", 1, 5},
|
||||
{"-.5", 1, -5},
|
||||
/* zero padding */
|
||||
{"1.2", 3, 1200},
|
||||
{"-1.2", 3, -1200},
|
||||
{"0.01", 3, 10},
|
||||
{"-0.01", 3, -10},
|
||||
/* truncation */
|
||||
{"1.23456", 3, 1234},
|
||||
{"-1.23456", 3, -1234},
|
||||
{"0.999999999", 3, 999},
|
||||
{"-0.999999999", 3, -999},
|
||||
/* trailing newline */
|
||||
{"1.5\n", 1, 15},
|
||||
{"-1.5\n", 1, -15},
|
||||
/* plus sign */
|
||||
{"+1.5", 1, 15},
|
||||
/* limits */
|
||||
{"9223372036.854775807", 9, LLONG_MAX},
|
||||
{"-9223372036.854775808", 9, LLONG_MIN},
|
||||
/* scale > 19 */
|
||||
{"0.0", 20, 0},
|
||||
{"-0.0", 20, 0},
|
||||
{"0.00000000000000000001", 20, 1},
|
||||
{"-0.00000000000000000001", 20, -1},
|
||||
{"0.009223372036854775807", 21, LLONG_MAX},
|
||||
{"-0.009223372036854775808", 21, LLONG_MIN},
|
||||
};
|
||||
TEST_OK(kstrtodec64, s64, "%lld", test_dec64_ok);
|
||||
}
|
||||
|
||||
static void __init test_kstrtodec64_fail(void)
|
||||
{
|
||||
static DEFINE_TEST_FAIL(test_dec64_fail) = {
|
||||
/* empty / whitespace */
|
||||
{"", 3},
|
||||
{"\n", 3},
|
||||
/* no digits after dot */
|
||||
{".", 3},
|
||||
{"-.", 3},
|
||||
/* no digits at all */
|
||||
{"+", 3},
|
||||
{"-", 3},
|
||||
/* non-digit characters */
|
||||
{"abc", 3},
|
||||
{"-1.2x", 3},
|
||||
/* signed overflow */
|
||||
{"9223372036.854775808", 9},
|
||||
{"-9223372036.854775809", 9},
|
||||
{"99999999999999999999", 1},
|
||||
/* signed overflow with scale > 19 */
|
||||
{"0.1", 20},
|
||||
{"-0.1", 20},
|
||||
{"0.09223372036854775808", 20},
|
||||
{"-0.09223372036854775809", 20},
|
||||
};
|
||||
TEST_FAIL(kstrtodec64, s64, "%lld", test_dec64_fail);
|
||||
}
|
||||
|
||||
static int __init test_kstrtox_init(void)
|
||||
{
|
||||
test_kstrtoull_ok();
|
||||
@@ -735,6 +911,12 @@ static int __init test_kstrtox_init(void)
|
||||
test_kstrtou8_fail();
|
||||
test_kstrtos8_ok();
|
||||
test_kstrtos8_fail();
|
||||
|
||||
test_kstrtoudec64_ok();
|
||||
test_kstrtoudec64_fail();
|
||||
test_kstrtodec64_ok();
|
||||
test_kstrtodec64_fail();
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
module_init(test_kstrtox_init);
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ static unsigned long long simple_strntoull(const char *startp, char **endp, unsi
|
||||
cp = _parse_integer_fixup_radix(startp, &base);
|
||||
prefix_chars = cp - startp;
|
||||
if (prefix_chars < max_chars) {
|
||||
rv = _parse_integer_limit(cp, base, &result, max_chars - prefix_chars);
|
||||
rv = _parse_integer(cp, base, &result, max_chars - prefix_chars);
|
||||
/* FIXME */
|
||||
cp += (rv & ~KSTRTOX_OVERFLOW);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user