aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2016-04-06 13:19:58 -0400
committerJiri Kosina <jkosina@suse.cz>2016-04-07 09:45:09 -0400
commit95d1c8951e5bd50bb89654a99a7012b1e75646bd (patch)
tree80f1e3f656c80f7ef27c0159418f69cce68ce731
parent6edac6fde59e231bd297ebcbc3d1bd395006cd1d (diff)
HID: simplify implement() a bit
The 'size' variable is not really needed, and we can also shift constant in the loop body when masking off existing bits. Also we do not have to use 64 bit calculations if we take an extra branch. [jkosina@suse.cz: fix a small error in changelog] Suggested-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bdb8cc89cacc..9985c0ab7c7f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1129,49 +1129,46 @@ EXPORT_SYMBOL_GPL(hid_field_extract);
1129static void __implement(u8 *report, unsigned offset, int n, u32 value) 1129static void __implement(u8 *report, unsigned offset, int n, u32 value)
1130{ 1130{
1131 unsigned int idx = offset / 8; 1131 unsigned int idx = offset / 8;
1132 unsigned int size = offset + n;
1133 unsigned int bit_shift = offset % 8; 1132 unsigned int bit_shift = offset % 8;
1134 int bits_to_set = 8 - bit_shift; 1133 int bits_to_set = 8 - bit_shift;
1135 u8 bit_mask = 0xff << bit_shift;
1136 1134
1137 while (n - bits_to_set >= 0) { 1135 while (n - bits_to_set >= 0) {
1138 report[idx] &= ~bit_mask; 1136 report[idx] &= ~(0xff << bit_shift);
1139 report[idx] |= value << bit_shift; 1137 report[idx] |= value << bit_shift;
1140 value >>= bits_to_set; 1138 value >>= bits_to_set;
1141 n -= bits_to_set; 1139 n -= bits_to_set;
1142 bits_to_set = 8; 1140 bits_to_set = 8;
1143 bit_mask = 0xff;
1144 bit_shift = 0; 1141 bit_shift = 0;
1145 idx++; 1142 idx++;
1146 } 1143 }
1147 1144
1148 /* last nibble */ 1145 /* last nibble */
1149 if (n) { 1146 if (n) {
1150 if (size % 8) 1147 u8 bit_mask = ((1U << n) - 1);
1151 bit_mask &= (1U << (size % 8)) - 1; 1148 report[idx] &= ~(bit_mask << bit_shift);
1152 report[idx] &= ~bit_mask; 1149 report[idx] |= value << bit_shift;
1153 report[idx] |= (value << bit_shift) & bit_mask;
1154 } 1150 }
1155} 1151}
1156 1152
1157static void implement(const struct hid_device *hid, u8 *report, 1153static void implement(const struct hid_device *hid, u8 *report,
1158 unsigned offset, unsigned n, u32 value) 1154 unsigned offset, unsigned n, u32 value)
1159{ 1155{
1160 u64 m; 1156 if (unlikely(n > 32)) {
1161
1162 if (n > 32) {
1163 hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", 1157 hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
1164 __func__, n, current->comm); 1158 __func__, n, current->comm);
1165 n = 32; 1159 n = 32;
1160 } else if (n < 32) {
1161 u32 m = (1U << n) - 1;
1162
1163 if (unlikely(value > m)) {
1164 hid_warn(hid,
1165 "%s() called with too large value %d (n: %d)! (%s)\n",
1166 __func__, value, n, current->comm);
1167 WARN_ON(1);
1168 value &= m;
1169 }
1166 } 1170 }
1167 1171
1168 m = (1ULL << n) - 1;
1169 if (value > m)
1170 hid_warn(hid, "%s() called with too large value %d! (%s)\n",
1171 __func__, value, current->comm);
1172 WARN_ON(value > m);
1173 value &= m;
1174
1175 __implement(report, offset, n, value); 1172 __implement(report, offset, n, value);
1176} 1173}
1177 1174