[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1539530740.939677843@decadent.org.uk>
Date: Sun, 14 Oct 2018 16:25:40 +0100
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org,
"Charles Keepax" <ckeepax@...nsource.cirrus.com>,
"Mark Brown" <broonie@...nel.org>,
"David Rhodes" <david.rhodes@...rus.com>
Subject: [PATCH 3.16 007/366] regmap: Don't use format_val in regmap_bulk_read
3.16.60-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Charles Keepax <ckeepax@...nsource.cirrus.com>
commit 9ae27a8d1f3ebff09191fb8cb1341414547293b2 upstream.
A bulk read can be implemented either through regmap_raw_read, or
by reading each register individually using regmap_read. Both
regmap_read and regmap_bulk_read should return values in native
endian. In the individual case the current implementation calls
format_val to put the data into the output array, which can cause
endian issues. The regmap_read will have already converted the data
into native endian, if the hosts endian differs from the device then
format_val will switch the endian back again.
Rather than using format_val simply use the code that is called if
there is no format_val function. This code supports all cases except
24-bit but there don't appear to be any users of regmap_bulk_read for
24-bit. Additionally, it would have to be a big endian host for the
old code to actually function correctly anyway.
Fixes: 15b8d2c41fe5 ("regmap: Fix regmap_bulk_read in BE mode")
Reported-by: David Rhodes <david.rhodes@...rus.com>
Signed-off-by: Charles Keepax <ckeepax@...nsource.cirrus.com>
Signed-off-by: Mark Brown <broonie@...nel.org>
[bwh: Backported to 3.16:
- 64-bit I/O is not supported
- Adjust context]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2240,39 +2240,30 @@ int regmap_bulk_read(struct regmap *map,
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(val + i);
} else {
+ u32 *u32 = val;
+ u16 *u16 = val;
+ u8 *u8 = val;
+
for (i = 0; i < val_count; i++) {
unsigned int ival;
+
ret = regmap_read(map, reg + (i * map->reg_stride),
&ival);
if (ret != 0)
return ret;
- if (map->format.format_val) {
- map->format.format_val(val + (i * val_bytes), ival, 0);
- } else {
- /* Devices providing read and write
- * operations can use the bulk I/O
- * functions if they define a val_bytes,
- * we assume that the values are native
- * endian.
- */
- u32 *u32 = val;
- u16 *u16 = val;
- u8 *u8 = val;
-
- switch (map->format.val_bytes) {
- case 4:
- u32[i] = ival;
- break;
- case 2:
- u16[i] = ival;
- break;
- case 1:
- u8[i] = ival;
- break;
- default:
- return -EINVAL;
- }
+ switch (map->format.val_bytes) {
+ case 4:
+ u32[i] = ival;
+ break;
+ case 2:
+ u16[i] = ival;
+ break;
+ case 1:
+ u8[i] = ival;
+ break;
+ default:
+ return -EINVAL;
}
}
}
Powered by blists - more mailing lists