23 Oct, 2019

1 commit


18 Apr, 2019

7 commits

  • The touchscreen driver, max11801, which is on 12c2 bus, won't be probed
    when using the hdcp specific DTS (this is disabling 12c2, since it
    will acquire it for DDC communications). Since this driver won't be
    probed, it will spam the dmesg with the pr_err from max11801_read_adc()
    function. This function is periodically called by the battery driver. For
    this reason, I removed the pr_err() call.
    Also, to be noticed that the function signature is u32, but in case of an
    error it will return a negative integer. In order to correctly propagate
    errors, I changed the function signature to int. This is safe, since the
    read value from i2c is on 16 bits (MSB and LSB on 8 bits).

    Also, the function calibration_voltage is calling max11801_read_adc from
    touchscreen driverm which can return negative values in case of an
    error. I case of an error, just stop reading ADC data and return 0 as
    voltage_data.

    Signed-off-by: Robert Chiras
    Signed-off-by: Vipul Kumar

    Robert Chiras
     
  • cherry-pick below patch:

    ENGR00288351 sabresd_battery: fix usb charger detect when resume back on
    mx6sl

    Fix below redundant log after first resume back on mx6slevk:
    max8903-charger max8903.12: USB Charger Connected

    It's caused by not add enough prepare for uok&dok which are connected,
    such as i.MX6SL-EVK. In this case the board only support DC charger detect,
    so we didn't need judge the uok pin for USB charger detect, although uok
    share with dok pin.

    Signed-off-by: Robin Gong
    (cherry picked from commit c5ba4940a72e8124db7ef91a67b337df4e45e3b0)
    (cherry picked from commit bcd7f8e5e19528abfc1c095049b55b3d409b27af)
    Signed-off-by: Vipul Kumar

    Robin Gong
     
  • cherry-pick below patch:

    ENGR00277663-3 power: sabresd_battery: remove check charger offset on
    mx6slevk

    No need check the charger offset on mx6slevk, since there is no adc
    converter

    Signed-off-by: Robin Gong
    (cherry picked from commit 7683c62cf2290629f09983744d5a3987a4d64669)
    (cherry picked from commit 5f29715585ae82a435aa5ba0fe6393a53c10f87d)
    Signed-off-by: Vipul Kumar

    Robin Gong
     
  • cherry-pick below patch:
    ENGR00275004-4: power: sabresd_battery: add sabresd_battery driver

    Add sabresd battery driver which based on Max8903 charger IC.

    Signed-off-by: Robin Gong
    TODO: checkpatch warnings
    Signed-off-by: Vipul Kumar

    Robin Gong
     
  • Charger interrupt can't be caught anymore after plug in DC 5V in/out
    dozens of times, that caused by VBUS_I or CHG_I pending interrupt not
    cleared in time. The root cause is VBUS_I and CHG_I will be triggered in
    very narrow window, and VBUS_I/CHG_I act as the sub-interrupt of charger
    and share the same interrupt handler. Thus if CHG_I interrupt status is
    coming while VBUS_I handler is running, CHG_I interrupt status will never
    be cleared, since interrupt has been disabled in ISR. The unclear CHG_I
    interrupt status make pf1550 never trigger next interrupt again. So clear
    all charger interrupt status in ISR to workaround instead of ack for every
    sub-interrupt.

    Signed-off-by: Robin Gong
    Signed-off-by: Vipul Kumar

    Robin Gong
     
  • That's pf1550's internal interrupt, useless for charger.

    Signed-off-by: Robin Gong
    Signed-off-by: Vipul Kumar

    Robin Gong
     
  • Add basic pf1550 charger driver.

    Signed-off-by: Robin Gong
    Signed-off-by: Vipul Kumar

    Robin Gong
     

27 Mar, 2019

1 commit


24 Mar, 2019

1 commit

  • commit fd10606f93a149a9f3d37574e5385b083b4a7b32 upstream.

    The driver doesn't generate uevents on charger connect/disconnect.
    This leads to UPower not detecting when AC is on or off... and that is
    bad.

    Reported by Arthur D. on github (
    https://github.com/maemo-leste/bugtracker/issues/206 ), thanks to
    Merlijn Wajer for suggesting a fix.

    Cc: stable@kernel.org
    Signed-off-by: Pavel Machek
    Acked-by: Tony Lindgren
    Signed-off-by: Sebastian Reichel
    Signed-off-by: Greg Kroah-Hartman

    Pavel Machek
     

13 Jan, 2019

1 commit

  • commit ed54ffbe554f0902689fd6d1712bbacbacd11376 upstream.

    According to [1] and [2], the temperature values are in tenths of degree
    Celsius. Exposing the Celsius value makes the battery appear on fire:

    $ upower -i /org/freedesktop/UPower/devices/battery_olpc_battery
    ...
    temperature: 236.9 degrees C

    Tested on OLPC XO-1 and OLPC XO-1.75 laptops.

    [1] include/linux/power_supply.h
    [2] Documentation/power/power_supply_class.txt

    Fixes: fb972873a767 ("[BATTERY] One Laptop Per Child power/battery driver")
    Cc: stable@vger.kernel.org
    Signed-off-by: Lubomir Rintel
    Acked-by: Pavel Machek
    Signed-off-by: Sebastian Reichel
    Signed-off-by: Greg Kroah-Hartman

    Lubomir Rintel
     

14 Nov, 2018

1 commit

  • commit 9844fb2e351311210e6660a9a1c62d17424a6145 upstream.

    Use the new of_get_compatible_child() helper to lookup the usb sibling
    node instead of using of_find_compatible_node(), which searches the
    entire tree from a given start node and thus can return an unrelated
    (non-sibling) node.

    This also addresses a potential use-after-free (e.g. after probe
    deferral) as the tree-wide helper drops a reference to its first
    argument (i.e. the parent device node).

    While at it, also fix the related phy-node reference leak.

    Fixes: f5e4edb8c888 ("power: twl4030_charger: find associated phy by more reliable means.")
    Cc: stable # 4.2
    Cc: NeilBrown
    Cc: Felipe Balbi
    Cc: Sebastian Reichel
    Reviewed-by: Sebastian Reichel
    Signed-off-by: Johan Hovold
    Signed-off-by: Rob Herring
    Signed-off-by: Greg Kroah-Hartman

    Johan Hovold
     

24 Aug, 2018

1 commit

  • Almost all files in the kernel are either plain text or UTF-8 encoded. A
    couple however are ISO_8859-1, usually just a few characters in a C
    comments, for historic reasons.

    This converts them all to UTF-8 for consistency.

    Link: http://lkml.kernel.org/r/20180724111600.4158975-1-arnd@arndb.de
    Signed-off-by: Arnd Bergmann
    Acked-by: Simon Horman [IPVS portion]
    Acked-by: Jonathan Cameron [IIO]
    Acked-by: Michael Ellerman [powerpc]
    Acked-by: Rob Herring
    Cc: Joe Perches
    Cc: Arnd Bergmann
    Cc: Samuel Ortiz
    Cc: "David S. Miller"
    Cc: Rob Herring
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Arnd Bergmann
     

22 Aug, 2018

1 commit

  • Pull power supply and reset updates from Sebastian Reichel:

    - Improve support for TI bq20z75 in sbs-battery

    - Add Qualcomm PM8xxx reboot driver

    - Add cros-ec USBPD charger driver

    - Move ds2760 battery driver from w1 to power-supply and add DT support

    - Misc fixes

    * tag 'for-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (28 commits)
    power: supply: bq27xxx: Update comments
    power: supply: max77693_charger: fix unintentional fall-through
    power: supply: mark expected switch fall-throughs
    power: supply: lego_ev3_battery: fix Vce offset
    power: supply: lego_ev3_battery: Don't ignore iio_read_channel_processed() return value
    power: supply: ds2760_battery: add devicetree probing
    power: supply: ds2760_battery: merge ds2760 supply driver with its w1 slave companion
    w1: core: match sub-nodes of bus masters in devicetree
    dt-bindings: w1: document bindings for ds2760 battery monitor
    dt-bindings: w1: document generic onewire bindings
    power: supply: adp5061: Fix a couple off by ones
    dt-bindings: power: reset: qcom: Add resin binding
    adp5061: New driver for ADP5061 I2C battery charger
    power: generic-adc-battery: check for duplicate properties copied from iio channels
    power: generic-adc-battery: fix out-of-bounds write when copying channel properties
    power: supply: axp288_charger: Fix initial constant_charge_current value
    power: supply: ab8500: stop using getnstimeofday64()
    power: gemini-poweroff: Avoid more spurious poweroffs
    power: vexpress: fix corruption in notifier registration
    power: remove possible deadlock when unregistering power_supply
    ...

    Linus Torvalds
     

17 Aug, 2018

1 commit


24 Jul, 2018

1 commit


23 Jul, 2018

5 commits


12 Jul, 2018

2 commits


11 Jul, 2018

1 commit


07 Jul, 2018

4 commits

  • At over 4000 #includes, is the 9th most
    #included header file in the Linux kernel. It does not need
    , so drop that header and explicitly add
    to source files that need it.

    4146 #include

    After this patch, there are 225 files that use ,
    for a reduction of around 3900 times that
    does not have to be read & parsed.

    225 #include

    This patch was build-tested on 20 different arch-es.

    It also makes these drivers SubmitChecklist#1 compliant.

    Signed-off-by: Randy Dunlap
    Reported-by: kbuild test robot # drivers/media/platform/vimc/
    Reported-by: kbuild test robot # drivers/pinctrl/pinctrl-u300.c
    Signed-off-by: Greg Kroah-Hartman

    Randy Dunlap
     
  • This patch adds basic support for Analog Devices I2C programmable linear
    battery charger.

    With this driver, some parameters can be read and configured such as:
    * trickle charge current level (PRECHARGE_CURRENT)
    * trickle charge voltage threshold (VOLTAGE_MIN)
    * weak charge threshold (VOLTAGE_AVG)
    * constant current (CONSTANT_CHARGE_CURRENT)
    * constant charge voltage limit (CONSTANT_CHARGE_VOLTAGE_MAX)
    * battery full (CAPACITY_LEVEL)
    * input current limit (INPUT_CURRENT_LIMIT)
    * charger status (STATUS)
    * battery status (CAPACITY_LEVEL)
    * termination current (CHARGE_TERM_CURRENT)

    Datasheet:
    http://www.analog.com/media/en/technical-documentation/data-sheets/ADP5061.pdf

    Signed-off-by: Stefan Popa
    Signed-off-by: Sebastian Reichel

    Stefan Popa
     
  • If an iio channel defines a basic property, there are duplicate entries
    in /sys/class/power/*/uevent.

    So add a check to avoid duplicates. Since all channels may be duplicates,
    we have to modify the related error check.

    Signed-off-by: H. Nikolaus Schaller
    Cc: stable@vger.kernel.org
    Fixes: e60fea794e6e ("power: battery: Generic battery driver using IIO")
    Signed-off-by: Sebastian Reichel

    H. Nikolaus Schaller
     
  • We did have sporadic problems in the pinctrl framework during boot
    where a pin group name unexpectedly became NULL leading to a NULL
    dereference in strcmp.

    Detailled analysis of the failing cases did reveal that there were
    two devm allocated objects close to each other. The second one was
    the affected group_desc in pinmux and the first one was the
    psy_desc->properties buffer of the gab driver.

    Review of the gab code showed that the address calculation for
    one memcpy() is wrong. It does

    properties + sizeof(type) * index

    but C is defined to do the index multiplication already for
    pointer + integer additions. Hence the factor was applied twice
    and the memcpy() does write outside of the properties buffer.
    Sometimes it happened to be the pinctrl and triggered the strcmp(NULL).

    Anyways, it is overkill to use a memcpy() here instead of a simple
    assignment, which is easier to read and has less risk for wrong
    address calculations. So we change code to a simple assignment.

    If we initialize the index to the first free location, we can even
    remove the local variable 'properties'.

    This bug seems to exist right from the beginning in 3.7-rc1 in

    commit e60fea794e6e ("power: battery: Generic battery driver using IIO")

    Signed-off-by: H. Nikolaus Schaller
    Cc: stable@vger.kernel.org
    Fixes: e60fea794e6e ("power: battery: Generic battery driver using IIO")
    Signed-off-by: Sebastian Reichel

    H. Nikolaus Schaller
     

06 Jul, 2018

6 commits

  • We should look at val which contains the value read from the register,
    not ret which is always 0 on a successful read.

    Signed-off-by: Hans de Goede
    Fixes: eac53b3664f59 ("power: supply: axp288_charger: Drop platform_data dependency")
    Signed-off-by: Sebastian Reichel

    Hans de Goede
     
  • getnstimeofday64() is deprecated in favor of the ktime_get() family.

    The direct replacement would be ktime_get_real_ts64(), but we only need
    the seconds value, and it seems better to use boottime than real time
    to avoid unexpected behavior with a concurrent settimeofday().

    ktime_get_seconds() might also work, but it seems better to use
    boottime than monotonic time since I assume that the charging
    process continues during suspend.

    Signed-off-by: Arnd Bergmann
    Acked-by: Linus Walleij
    Signed-off-by: Sebastian Reichel

    Arnd Bergmann
     
  • Even after the previous fix I have experienced more spurious
    poweroffs on the gemini SoC. After this fix it finally seems
    to go away.

    Fixes: f7a388d6cd1c ("power: reset: Add a driver for the Gemini poweroff")
    Signed-off-by: Linus Walleij
    Signed-off-by: Sebastian Reichel

    Linus Walleij
     
  • Vexpress platforms provide two different restart handlers: SYS_REBOOT
    that restart the entire system, while DB_RESET only restarts the
    daughter board containing the CPU. DB_RESET is overridden by SYS_REBOOT
    if it exists.

    notifier_chain_register used in register_restart_handler by design
    relies on notifiers to be registered once only, however vexpress restart
    notifier can get registered twice. When this happen it corrupts list
    of notifiers, as result some notifiers can be not called on proper
    event, traverse on list can be cycled forever, and second unregister
    can access already freed memory.

    So far, since this was the only restart handler in the system, no issue
    was observed even if the same notifier was registered twice. However
    commit 6c5c0d48b686 ("watchdog: sp805: add restart handler") added
    support for SP805 restart handlers and since the system under test
    contains two vexpress restart and two SP805 watchdog instances, it was
    observed that during the boot traversing the restart handler list looped
    forever as there's a cycle in that list resulting in boot hang.

    This patch fixes the issues by ensuring that the notifier is installed
    only once.

    Cc: Sebastian Reichel
    Signed-off-by: Sudeep Holla
    Fixes: 46c99ac66222 ("power/reset: vexpress: Register with kernel restart handler")
    Signed-off-by: Sebastian Reichel

    Sudeep Holla
     
  • If a device gets removed right after having registered a power_supply node,
    we might enter in a deadlock between the remove call (that has a lock on
    the parent device) and the deferred register work.

    Allow the deferred register work to exit without taking the lock when
    we are in the remove state.

    Stack trace on a Ubuntu 16.04:

    [16072.109121] INFO: task kworker/u16:2:1180 blocked for more than 120 seconds.
    [16072.109127] Not tainted 4.13.0-41-generic #46~16.04.1-Ubuntu
    [16072.109129] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
    [16072.109132] kworker/u16:2 D 0 1180 2 0x80000000
    [16072.109142] Workqueue: events_power_efficient power_supply_deferred_register_work
    [16072.109144] Call Trace:
    [16072.109152] __schedule+0x3d6/0x8b0
    [16072.109155] schedule+0x36/0x80
    [16072.109158] schedule_preempt_disabled+0xe/0x10
    [16072.109161] __mutex_lock.isra.2+0x2ab/0x4e0
    [16072.109166] __mutex_lock_slowpath+0x13/0x20
    [16072.109168] ? __mutex_lock_slowpath+0x13/0x20
    [16072.109171] mutex_lock+0x2f/0x40
    [16072.109174] power_supply_deferred_register_work+0x2b/0x50
    [16072.109179] process_one_work+0x15b/0x410
    [16072.109182] worker_thread+0x4b/0x460
    [16072.109186] kthread+0x10c/0x140
    [16072.109189] ? process_one_work+0x410/0x410
    [16072.109191] ? kthread_create_on_node+0x70/0x70
    [16072.109194] ret_from_fork+0x35/0x40
    [16072.109199] INFO: task test:2257 blocked for more than 120 seconds.
    [16072.109202] Not tainted 4.13.0-41-generic #46~16.04.1-Ubuntu
    [16072.109204] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
    [16072.109206] test D 0 2257 2256 0x00000004
    [16072.109208] Call Trace:
    [16072.109211] __schedule+0x3d6/0x8b0
    [16072.109215] schedule+0x36/0x80
    [16072.109218] schedule_timeout+0x1f3/0x360
    [16072.109221] ? check_preempt_curr+0x5a/0xa0
    [16072.109224] ? ttwu_do_wakeup+0x1e/0x150
    [16072.109227] wait_for_completion+0xb4/0x140
    [16072.109230] ? wait_for_completion+0xb4/0x140
    [16072.109233] ? wake_up_q+0x70/0x70
    [16072.109236] flush_work+0x129/0x1e0
    [16072.109240] ? worker_detach_from_pool+0xb0/0xb0
    [16072.109243] __cancel_work_timer+0x10f/0x190
    [16072.109247] ? device_del+0x264/0x310
    [16072.109250] ? __wake_up+0x44/0x50
    [16072.109253] cancel_delayed_work_sync+0x13/0x20
    [16072.109257] power_supply_unregister+0x37/0xb0
    [16072.109260] devm_power_supply_release+0x11/0x20
    [16072.109263] release_nodes+0x110/0x200
    [16072.109266] devres_release_group+0x7c/0xb0
    [16072.109274] wacom_remove+0xc2/0x110 [wacom]
    [16072.109279] hid_device_remove+0x6e/0xd0 [hid]
    [16072.109284] device_release_driver_internal+0x158/0x210
    [16072.109288] device_release_driver+0x12/0x20
    [16072.109291] bus_remove_device+0xec/0x160
    [16072.109293] device_del+0x1de/0x310
    [16072.109298] hid_destroy_device+0x27/0x60 [hid]
    [16072.109303] usbhid_disconnect+0x51/0x70 [usbhid]
    [16072.109308] usb_unbind_interface+0x77/0x270
    [16072.109311] device_release_driver_internal+0x158/0x210
    [16072.109315] device_release_driver+0x12/0x20
    [16072.109318] usb_driver_release_interface+0x77/0x80
    [16072.109321] proc_ioctl+0x20f/0x250
    [16072.109325] usbdev_do_ioctl+0x57f/0x1140
    [16072.109327] ? __wake_up+0x44/0x50
    [16072.109331] usbdev_ioctl+0xe/0x20
    [16072.109336] do_vfs_ioctl+0xa4/0x600
    [16072.109339] ? vfs_write+0x15a/0x1b0
    [16072.109343] SyS_ioctl+0x79/0x90
    [16072.109347] entry_SYSCALL_64_fastpath+0x24/0xab
    [16072.109349] RIP: 0033:0x7f20da807f47
    [16072.109351] RSP: 002b:00007ffc422ae398 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
    [16072.109353] RAX: ffffffffffffffda RBX: 00000000010b8560 RCX: 00007f20da807f47
    [16072.109355] RDX: 00007ffc422ae3a0 RSI: 00000000c0105512 RDI: 0000000000000009
    [16072.109356] RBP: 0000000000000000 R08: 00007ffc422ae3e0 R09: 0000000000000010
    [16072.109357] R10: 00000000000000a6 R11: 0000000000000246 R12: 0000000000000000
    [16072.109359] R13: 00000000010b8560 R14: 00007ffc422ae2e0 R15: 0000000000000000

    Reported-and-tested-by: Richard Hughes
    Tested-by: Aaron Skomra
    Signed-off-by: Benjamin Tissoires
    Fixes: 7f1a57fdd6cb ("power_supply: Fix possible NULL pointer dereference on early uevent")
    Signed-off-by: Sebastian Reichel

    Benjamin Tissoires
     
  • Add support Qualcomm PM8xxx PON which is responsible for reboot
    mode support.

    Co-developed-by: Bjorn Andersson
    Signed-off-by: Bjorn Andersson
    Signed-off-by: Vinod Koul
    Signed-off-by: Sebastian Reichel

    Vinod Koul
     

05 Jul, 2018

1 commit


28 Jun, 2018

4 commits

  • Trivial fix to spelling mistake in dev_warn message text

    Signed-off-by: Colin Ian King
    Signed-off-by: Sebastian Reichel

    Colin Ian King
     
  • zx_reboot_probe() increments refcnt of zx296702-pcu device node by
    of_find_compatible_node() and leaves it undecremented on both
    successful and error paths.

    Found by Linux Driver Verification project (linuxtesting.org).

    Signed-off-by: Alexey Khoroshilov
    Reviewed-by: Nicholas Mc Guire
    Signed-off-by: Sebastian Reichel

    Alexey Khoroshilov
     
  • Adopt the SPDX license identifier headers to ease license compliance
    management.

    Signed-off-by: Enric Balletbo i Serra
    Signed-off-by: Sebastian Reichel

    Enric Balletbo i Serra
     
  • This driver was originally submitted for the TI BQ20Z75 battery IC
    (commit a7640bfa10c5 ("power_supply: Add driver for TI BQ20Z75 gas gauge
    IC")) and later renamed to express generic SBS support. While it's
    mostly true that this driver implemented a standard SBS command set, it
    takes liberties with the REG_MANUFACTURER_DATA register. This register
    is specified in the SBS spec, but it doesn't make any mention of what
    its actual contents are.

    We've sort of noticed this optionality previously, with commit
    17c6d3979e5b ("sbs-battery: make writes to ManufacturerAccess
    optional"), where we found that some batteries NAK writes to this
    register.

    What this really means is that so far, we've just been lucky that most
    batteries have either been compatible with the TI chip, or else at least
    haven't reported highly-unexpected values.

    For instance, one battery I have here seems to report either 0x0000 or
    0x0100 to the MANUFACTURER_ACCESS_STATUS command -- while this seems to
    match either Wake Up (bits[11:8] = 0000b) or Normal Discharge
    (bits[11:8] = 0001b) status for the TI part [1], they don't seem to
    actually correspond to real states (for instance, I never see 0101b =
    Charge, even when charging).

    On other batteries, I'm getting apparently random data in return, which
    means that occasionally, we interpret this as "battery not present" or
    "battery is not healthy".

    All in all, it seems to be a really bad idea to make assumptions about
    REG_MANUFACTURER_DATA, unless we already know what battery we're using.
    Therefore, this patch reimplements the "present" and "health" checks to
    the following on most SBS batteries:

    1. HEALTH: report "unknown" -- I couldn't find a standard SBS command
    that gives us much useful here
    2. PRESENT: just send a REG_STATUS command; if it succeeds, then the
    battery is present

    Also, we stop sending MANUFACTURER_ACCESS_SLEEP to non-TI parts. I have
    no proof that this is useful and supported.

    If someone explicitly provided a 'ti,bq20z75' compatible property, then
    we continue to use the existing TI command behaviors, and we effectively
    revert commit 17c6d3979e5b ("sbs-battery: make writes to
    ManufacturerAccess optional") to again make these commands required.

    [1] http://www.ti.com/lit/er/sluu265a/sluu265a.pdf

    Signed-off-by: Brian Norris
    Reviewed-by: Guenter Roeck
    Acked-by: Rhyland Klein
    Signed-off-by: Sebastian Reichel

    Brian Norris
     

13 Jun, 2018

1 commit

  • The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
    This patch replaces cases of:

    devm_kzalloc(handle, a * b, gfp)

    with:
    devm_kcalloc(handle, a * b, gfp)

    as well as handling cases of:

    devm_kzalloc(handle, a * b * c, gfp)

    with:

    devm_kzalloc(handle, array3_size(a, b, c), gfp)

    as it's slightly less ugly than:

    devm_kcalloc(handle, array_size(a, b), c, gfp)

    This does, however, attempt to ignore constant size factors like:

    devm_kzalloc(handle, 4 * 1024, gfp)

    though any constants defined via macros get caught up in the conversion.

    Any factors with a sizeof() of "unsigned char", "char", and "u8" were
    dropped, since they're redundant.

    Some manual whitespace fixes were needed in this patch, as Coccinelle
    really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".

    The Coccinelle script used for this was:

    // Fix redundant parens around sizeof().
    @@
    expression HANDLE;
    type TYPE;
    expression THING, E;
    @@

    (
    devm_kzalloc(HANDLE,
    - (sizeof(TYPE)) * E
    + sizeof(TYPE) * E
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (sizeof(THING)) * E
    + sizeof(THING) * E
    , ...)
    )

    // Drop single-byte sizes and redundant parens.
    @@
    expression HANDLE;
    expression COUNT;
    typedef u8;
    typedef __u8;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(u8) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(__u8) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(char) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(unsigned char) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(u8) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(__u8) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(char) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(unsigned char) * COUNT
    + COUNT
    , ...)
    )

    // 2-factor product with sizeof(type/expression) and identifier or constant.
    @@
    expression HANDLE;
    type TYPE;
    expression THING;
    identifier COUNT_ID;
    constant COUNT_CONST;
    @@

    (
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (COUNT_ID)
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * COUNT_ID
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (COUNT_CONST)
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * COUNT_CONST
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (COUNT_ID)
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * COUNT_ID
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (COUNT_CONST)
    + COUNT_CONST, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * COUNT_CONST
    + COUNT_CONST, sizeof(THING)
    , ...)
    )

    // 2-factor product, only identifiers.
    @@
    expression HANDLE;
    identifier SIZE, COUNT;
    @@

    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - SIZE * COUNT
    + COUNT, SIZE
    , ...)

    // 3-factor product with 1 sizeof(type) or sizeof(expression), with
    // redundant parens removed.
    @@
    expression HANDLE;
    expression THING;
    identifier STRIDE, COUNT;
    type TYPE;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    )

    // 3-factor product with 2 sizeof(variable), with redundant parens removed.
    @@
    expression HANDLE;
    expression THING1, THING2;
    identifier COUNT;
    type TYPE1, TYPE2;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(TYPE2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    )

    // 3-factor product, only identifiers, with redundant parens removed.
    @@
    expression HANDLE;
    identifier STRIDE, SIZE, COUNT;
    @@

    (
    devm_kzalloc(HANDLE,
    - (COUNT) * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    )

    // Any remaining multi-factor products, first at least 3-factor products,
    // when they're not all constants...
    @@
    expression HANDLE;
    expression E1, E2, E3;
    constant C1, C2, C3;
    @@

    (
    devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * (E2) * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * (E2) * (E3)
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - E1 * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    )

    // And then all remaining 2 factors products when they're not all constants,
    // keeping sizeof() as the second factor argument.
    @@
    expression HANDLE;
    expression THING, E1, E2;
    type TYPE;
    constant C1, C2, C3;
    @@

    (
    devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
    |
    devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
    |
    devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
    |
    devm_kzalloc(HANDLE, C1 * C2, ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (E2)
    + E2, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * E2
    + E2, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (E2)
    + E2, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * E2
    + E2, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - (E1) * E2
    + E1, E2
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - (E1) * (E2)
    + E1, E2
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - E1 * E2
    + E1, E2
    , ...)
    )

    Signed-off-by: Kees Cook

    Kees Cook