Commit d31b2865a4e8a9dd02f39e56c8fadb824c5e187b

Authored by Daniel Mack
Committed by Dmitry Torokhov
1 parent 987a6c0298

Input: dynamically allocate ABS information

As all callers are now changed to only use the input_abs_*() access
helpers, switching over to dynamically allocated ABS information is
easy. This reduces size of struct input_dev from 3152 to 1640 on
64 bit architectures.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 3 changed files with 63 additions and 57 deletions Side-by-side Diff

drivers/input/evdev.c
... ... @@ -649,14 +649,8 @@
649 649 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
650 650  
651 651 t = _IOC_NR(cmd) & ABS_MAX;
  652 + abs = dev->absinfo[t];
652 653  
653   - abs.value = input_abs_get_val(dev, t);
654   - abs.minimum = input_abs_get_min(dev, t);
655   - abs.maximum = input_abs_get_max(dev, t);
656   - abs.fuzz = input_abs_get_fuzz(dev, t);
657   - abs.flat = input_abs_get_flat(dev, t);
658   - abs.resolution = input_abs_get_res(dev, t);
659   -
660 654 if (copy_to_user(p, &abs, min_t(size_t,
661 655 _IOC_SIZE(cmd),
662 656 sizeof(struct input_absinfo))))
... ... @@ -691,6 +685,9 @@
691 685 sizeof(struct input_absinfo))))
692 686 return -EFAULT;
693 687  
  688 + if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
  689 + abs.resolution = 0;
  690 +
694 691 /* We can't change number of reserved MT slots */
695 692 if (t == ABS_MT_SLOT)
696 693 return -EINVAL;
... ... @@ -701,15 +698,7 @@
701 698 * of event.
702 699 */
703 700 spin_lock_irq(&dev->event_lock);
704   -
705   - input_abs_set_val(dev, t, abs.value);
706   - input_abs_set_min(dev, t, abs.minimum);
707   - input_abs_set_max(dev, t, abs.maximum);
708   - input_abs_set_fuzz(dev, t, abs.fuzz);
709   - input_abs_set_flat(dev, t, abs.flat);
710   - input_abs_set_res(dev, t, _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
711   - 0 : abs.resolution);
712   -
  701 + dev->absinfo[t] = abs;
713 702 spin_unlock_irq(&dev->event_lock);
714 703  
715 704 return 0;
drivers/input/input.c
... ... @@ -182,7 +182,7 @@
182 182 is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
183 183  
184 184 if (!is_mt_event) {
185   - pold = &dev->abs[code];
  185 + pold = &dev->absinfo[code].value;
186 186 } else if (dev->mt) {
187 187 struct input_mt_slot *mtslot = &dev->mt[dev->slot];
188 188 pold = &mtslot->abs[code - ABS_MT_FIRST];
... ... @@ -196,7 +196,7 @@
196 196  
197 197 if (pold) {
198 198 *pval = input_defuzz_abs_event(*pval, *pold,
199   - dev->absfuzz[code]);
  199 + dev->absinfo[code].fuzz);
200 200 if (*pold == *pval)
201 201 return INPUT_IGNORE_EVENT;
202 202  
... ... @@ -391,6 +391,43 @@
391 391 EXPORT_SYMBOL(input_inject_event);
392 392  
393 393 /**
  394 + * input_alloc_absinfo - allocates array of input_absinfo structs
  395 + * @dev: the input device emitting absolute events
  396 + *
  397 + * If the absinfo struct the caller asked for is already allocated, this
  398 + * functions will not do anything.
  399 + */
  400 +void input_alloc_absinfo(struct input_dev *dev)
  401 +{
  402 + if (!dev->absinfo)
  403 + dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
  404 + GFP_KERNEL);
  405 +
  406 + WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
  407 +}
  408 +EXPORT_SYMBOL(input_alloc_absinfo);
  409 +
  410 +void input_set_abs_params(struct input_dev *dev, unsigned int axis,
  411 + int min, int max, int fuzz, int flat)
  412 +{
  413 + struct input_absinfo *absinfo;
  414 +
  415 + input_alloc_absinfo(dev);
  416 + if (!dev->absinfo)
  417 + return;
  418 +
  419 + absinfo = &dev->absinfo[axis];
  420 + absinfo->minimum = min;
  421 + absinfo->maximum = max;
  422 + absinfo->fuzz = fuzz;
  423 + absinfo->flat = flat;
  424 +
  425 + dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
  426 +}
  427 +EXPORT_SYMBOL(input_set_abs_params);
  428 +
  429 +
  430 +/**
394 431 * input_grab_device - grabs device for exclusive use
395 432 * @handle: input handle that wants to own the device
396 433 *
... ... @@ -1308,6 +1345,7 @@
1308 1345  
1309 1346 input_ff_destroy(dev);
1310 1347 input_mt_destroy_slots(dev);
  1348 + kfree(dev->absinfo);
1311 1349 kfree(dev);
1312 1350  
1313 1351 module_put(THIS_MODULE);
include/linux/input.h
... ... @@ -776,6 +776,7 @@
776 776 #define REP_DELAY 0x00
777 777 #define REP_PERIOD 0x01
778 778 #define REP_MAX 0x01
  779 +#define REP_CNT (REP_MAX+1)
779 780  
780 781 /*
781 782 * Sounds
782 783  
783 784  
... ... @@ -1099,21 +1100,18 @@
1099 1100 * @repeat_key: stores key code of the last key pressed; used to implement
1100 1101 * software autorepeat
1101 1102 * @timer: timer for software autorepeat
1102   - * @abs: current values for reports from absolute axes
1103 1103 * @rep: current values for autorepeat parameters (delay, rate)
1104 1104 * @mt: pointer to array of struct input_mt_slot holding current values
1105 1105 * of tracked contacts
1106 1106 * @mtsize: number of MT slots the device uses
1107 1107 * @slot: MT slot currently being transmitted
  1108 + * @absinfo: array of &struct absinfo elements holding information
  1109 + * about absolute axes (current value, min, max, flat, fuzz,
  1110 + * resolution)
1108 1111 * @key: reflects current state of device's keys/buttons
1109 1112 * @led: reflects current state of device's LEDs
1110 1113 * @snd: reflects current state of sound effects
1111 1114 * @sw: reflects current state of device's switches
1112   - * @absmax: maximum values for events coming from absolute axes
1113   - * @absmin: minimum values for events coming from absolute axes
1114   - * @absfuzz: describes noisiness for axes
1115   - * @absflat: size of the center flat position (used by joydev)
1116   - * @absres: resolution used for events coming form absolute axes
1117 1115 * @open: this method is called when the very first user calls
1118 1116 * input_open_device(). The driver must prepare the device
1119 1117 * to start generating events (start polling thread,
1120 1118  
1121 1119  
... ... @@ -1180,24 +1178,19 @@
1180 1178 unsigned int repeat_key;
1181 1179 struct timer_list timer;
1182 1180  
1183   - int abs[ABS_CNT];
1184   - int rep[REP_MAX + 1];
  1181 + int rep[REP_CNT];
1185 1182  
1186 1183 struct input_mt_slot *mt;
1187 1184 int mtsize;
1188 1185 int slot;
1189 1186  
  1187 + struct input_absinfo *absinfo;
  1188 +
1190 1189 unsigned long key[BITS_TO_LONGS(KEY_CNT)];
1191 1190 unsigned long led[BITS_TO_LONGS(LED_CNT)];
1192 1191 unsigned long snd[BITS_TO_LONGS(SND_CNT)];
1193 1192 unsigned long sw[BITS_TO_LONGS(SW_CNT)];
1194 1193  
1195   - int absmax[ABS_CNT];
1196   - int absmin[ABS_CNT];
1197   - int absfuzz[ABS_CNT];
1198   - int absflat[ABS_CNT];
1199   - int absres[ABS_CNT];
1200   -
1201 1194 int (*open)(struct input_dev *dev);
1202 1195 void (*close)(struct input_dev *dev);
1203 1196 int (*flush)(struct input_dev *dev, struct file *file);
1204 1197  
1205 1198  
1206 1199  
1207 1200  
1208 1201  
... ... @@ -1459,45 +1452,31 @@
1459 1452 dev->hint_events_per_packet = n_events;
1460 1453 }
1461 1454  
1462   -static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
1463   -{
1464   - dev->absmin[axis] = min;
1465   - dev->absmax[axis] = max;
1466   - dev->absfuzz[axis] = fuzz;
1467   - dev->absflat[axis] = flat;
  1455 +void input_alloc_absinfo(struct input_dev *dev);
  1456 +void input_set_abs_params(struct input_dev *dev, unsigned int axis,
  1457 + int min, int max, int fuzz, int flat);
1468 1458  
1469   - dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
1470   -}
1471   -
1472 1459 #define INPUT_GENERATE_ABS_ACCESSORS(_suffix, _item) \
1473 1460 static inline int input_abs_get_##_suffix(struct input_dev *dev, \
1474 1461 unsigned int axis) \
1475 1462 { \
1476   - return dev->abs##_item[axis]; \
  1463 + return dev->absinfo ? dev->absinfo[axis]._item : 0; \
1477 1464 } \
1478 1465 \
1479 1466 static inline void input_abs_set_##_suffix(struct input_dev *dev, \
1480 1467 unsigned int axis, int val) \
1481 1468 { \
1482   - dev->abs##_item[axis] = val; \
  1469 + input_alloc_absinfo(dev); \
  1470 + if (dev->absinfo) \
  1471 + dev->absinfo[axis]._item = val; \
1483 1472 }
1484 1473  
1485   -INPUT_GENERATE_ABS_ACCESSORS(min, min)
1486   -INPUT_GENERATE_ABS_ACCESSORS(max, max)
  1474 +INPUT_GENERATE_ABS_ACCESSORS(val, value)
  1475 +INPUT_GENERATE_ABS_ACCESSORS(min, minimum)
  1476 +INPUT_GENERATE_ABS_ACCESSORS(max, maximum)
1487 1477 INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
1488 1478 INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
1489   -INPUT_GENERATE_ABS_ACCESSORS(res, res)
1490   -
1491   -static inline int input_abs_get_val(struct input_dev *dev, unsigned int axis)
1492   -{
1493   - return dev->abs[axis];
1494   -}
1495   -
1496   -static inline void input_abs_set_val(struct input_dev *dev,
1497   - unsigned int axis, int val)
1498   -{
1499   - dev->abs[axis] = val;
1500   -}
  1479 +INPUT_GENERATE_ABS_ACCESSORS(res, resolution)
1501 1480  
1502 1481 int input_get_keycode(struct input_dev *dev,
1503 1482 unsigned int scancode, unsigned int *keycode);