Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: intel-ish-hid: Fix -Wcast-function-type-strict in devm_ishtp_alloc_workqueue()

Clang warns (or errors with CONFIG_WERROR=y / W=e):

drivers/hid/intel-ish-hid/ipc/ipc.c:935:36: error: cast from 'void (*)(struct workqueue_struct *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict]
935 | if (devm_add_action_or_reset(dev, (void (*)(void *))destroy_workqueue,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/device/devres.h:168:34: note: expanded from macro 'devm_add_action_or_reset'
168 | __devm_add_action_or_ireset(dev, action, data, #action)
| ^~~~~~

This warning is pointing out a kernel control flow integrity (kCFI /
CONFIG_CFI=y) violation will occur due to this function cast when the
destroy_workqueue() is indirectly called via devm_action_release()
because the prototype of destroy_workqueue() does not match the
prototype of (*action)().

Use a local function with the correct prototype to wrap
destroy_workqueue() to resolve the warning and CFI violation.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202510190103.qTZvfdjj-lkp@intel.com/
Closes: https://github.com/ClangBuiltLinux/linux/issues/2139
Fixes: 0d30dae38fe0 ("HID: intel-ish-hid: Use dedicated unbound workqueues to prevent resume blocking")
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Reviewed-by: Zhang Lixu <lixu.zhang@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Nathan Chancellor and committed by
Jiri Kosina
3644f441 5677aa6a

+6 -2
+6 -2
drivers/hid/intel-ish-hid/ipc/ipc.c
··· 924 924 .dma_no_cache_snooping = _dma_no_cache_snooping 925 925 }; 926 926 927 + static void ishtp_free_workqueue(void *wq) 928 + { 929 + destroy_workqueue(wq); 930 + } 931 + 927 932 static struct workqueue_struct *devm_ishtp_alloc_workqueue(struct device *dev) 928 933 { 929 934 struct workqueue_struct *wq; ··· 937 932 if (!wq) 938 933 return NULL; 939 934 940 - if (devm_add_action_or_reset(dev, (void (*)(void *))destroy_workqueue, 941 - wq)) 935 + if (devm_add_action_or_reset(dev, ishtp_free_workqueue, wq)) 942 936 return NULL; 943 937 944 938 return wq;