workqueue: __WORK_INITIALIZER compiler warning - linux-kernel

Just to learn, I try to compile an old device driver example on Ubuntu 14, and I get a warning.
I guess this warning is triggered because some inconsistency between the type returned from __WORK_INITIALIZER and the work_struct structure. What I don't understand is how that can happen. :)
This happens at row 19 in my file shortprint.c, at an include line that includes module.h according to the call stack shown below. So I guess that my code is irrelevant, this seems to be inside the linux include files. Am I right?
I'm running Ubuntu 14.04.
fredrik#fredrik-VirtualBox:~/Documents/lab8_3/shortprint$ make
make -C /lib/modules/3.13.0-45-generic/build M=/home/fredrik/Documents/lab8_3/shortprint modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-45-generic'
CC [M] /home/fredrik/Documents/lab8_3/shortprint/shortprint.o
In file included from include/linux/srcu.h:34:0,
from include/linux/notifier.h:15,
from include/linux/memory_hotplug.h:6,
from include/linux/mmzone.h:801,
from include/linux/gfp.h:4,
from include/linux/kmod.h:22,
from include/linux/module.h:13,
from /home/fredrik/Documents/lab8_3/shortprint/shortprint.c:19:
include/linux/workqueue.h:172:9: warning: initialization from incompatible pointer type [enabled by default]
struct work_struct n = __WORK_INITIALIZER(n, f)
FWIW I also include my makefile:
# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
EXTRA_CFLAGS += -O2 -I..
ifneq ($(KERNELRELEASE),)
# call from kernel build system
obj-m := shortprint.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
The corrected code. The function was of void short_do_work(void*) before the correction:
static void shortp_do_work(struct work_struct *work);
static DECLARE_WORK(shortp_work, shortp_do_work);

Your code is certainly relevant. The entire kernel uses these macros and somehow works, so I'd suspect the problem is in the way you call them. It would be an incompatible function pointer type passed to __WORK_INITIALIZER().
By the way, please use DECLARE_WORK() or INIT_WORK() if possible.
The function prototype for workers is
typedef void (*work_func_t)(struct work_struct *work);
Defined in include/linux/workqueue.h

Related

How should I set extra include path for linux kernel module build?

This is the Makefile that I'm using for cross-buildig a kernel module.
export CROSS_COMPILE:=aarch64-none-linux-gnu-
export ARCH:=arm64
obj-m += chr_drv_ex1.o
export KDIR:=linux-source-5.4.0
#EXTRA_CFLAGS=-I../../qemu-5.1.0/hw/misc
#ccflags-y=-I../../qemu-5.1.0/hw/misc
all: test_chr_drv map_hugetlb test_ioctl_drv
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) modules
clean:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) clean
rm -f test_chr_drv map_hugetlb test_ioctl_drv
%: %.c
$(CROSS_COMPILE)gcc $^ -o $#
Now in my chr_drv_ex1.c file, I want to include a header file placed in ../../qemu-5.1.0/hw/misc directory. What is the correct method to add this path? I saw this and tried setting EXTRA_CFLAGS and ccflags-y but none of them works(those are commented out above). Of course if I use #include "../../qemu-5.1.0/hw/misc/axpu_regs.h" in the chr_drv_ex1.c source I can compile it. But I want to use #include <axpu_regs.h>.
I changed the ccflags-y from
ccflags-y := -I../../qemu-5.1.0/hw/misc
to
ccflags-y := -I../../../qemu-5.1.0/hw/misc
So the include path should be specified as seen from the kernel make directory (where the Makefile for linux kernel is located. in this case linux-source-5.4.0 directory which is one step below from where I am now).

c11 flag is ignored in the make file [duplicate]

This question already has answers here:
Is it possible to set CFLAGS to a linux kernel module Makefile?
(2 answers)
Closed 2 years ago.
I try to compile my code with c11 mode.
Here is my make file:
obj-m := message_slot.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
CFLAGS=-g -std=c11 -Wall -pedantic
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
for some reason during compilation, the compiler still try to compile the code with c90. Does anyone understand why?
/home/eran/CLionProjects/tau_os_ex3/message_slot.c:29:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
CXXFLAGS conveys build flags for C++, but the error message indicates that you are trying to build a C source. C compiler flags go in CFLAGS.

how to add another include path in make

i want to use iostream or stdlib.h in my linux kernel driver and i have this MakeFile
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
.PHONY: build clean
build:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c
else
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
obj-m := mydev.o
endif
when i use #include in my driver code, make returns this
mydev.c:10:20: fatal error: iostream: No such file or directory
#include <iostream>
what should i add to my makefile?
iostream is a C++ header. The Kernel is written in C

Proper makefile setup for external kernel modules

I'm writing a character driver to sit on top of a modified version of ahci in the source tree. I basically have something that looks like this:
topdir
|
|- Makfile
|
|- mod_ahci
| | - Makefile, codefiles
|
|- char_interface
| | - Makefile, codefiles
now, char_interface requires symbols from mod_ahci. I have the appropriate EXPORT_SYMBOL() macro use for the symbols I need to export. However, I'm having trouble getting the makefiles right to pick up the header file in mod_ahci from char_interface. My toplevel Makefile
ifneq ($(KERNELRELEASE),)
obj-y := mod_ahci/ char_interface/
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
endif
The makefile for char_interface (because the other builds just fine)
ifneq ($(KERNELRELEASE),)
ccflags-y += -I../mod_ahci
obj-m := char_interface.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
default:
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install
endif
clean:
-sudo rmmod ahcip
-rm -f *.ko* *.mod.* *.o modules.order Modules.symvers
I have referenced various text files in the kernel documentation. For example, I'm referring to .../Documentation/kbuild/makefiles.txt right now as well as .../Documentation/kbuild/modules.txt. Whenever I build, I'm getting /home/captaink/devel/kmodtests/char_interface/char_interface.c:2:22: error: mod_ahci.h: No such file or directory. There is a file named mod_ahci.h in the directory ../mod_ahci. What am I getting wrong with my use of ccflags-y in the makefile for the char driver?
Thanks
After some digging, I found the answer to the problem. I was misunderstanding what was happening with the makefile's that I was viewing from LDD3 and the kernel documentation (which is, apparently, exactly where O'Reilly took their examples). The build system actually changes directories into /usr/src/kernels/$(uname -r)/build (or similar) because this is why my header file wasn't being found by the compiler.
I'm not saying this is an elegant way of doing this, but here's how I fixed it. The makefile in the top directory now looks like:
ifneq ($(KERNELRELEASE),)
obj-y := mod_ahci/ char_interface/
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) TOP_DIR=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
endif
And the makefile in the subdirectory containing the char driver interface looks like:
ifneq ($(KERNELRELEASE),)
ccflags-y += -I$(TOP_DIR)/mod_ahci
obj-m := char_interface.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
default:
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install
endif
clean:
-sudo rmmod ahcip
-rm -f *.ko* *.mod.* *.o modules.order Modules.symvers
As you can tell, the makefiles have been copied extensively. The subdirectories probably don't need the "shared" makefile stuff in them because that's taken care of by the higher level makefile. Nevertheless, the modules now build and the character driver I have knows of the exported symbols I made in my modified ahci driver.
I hope this may help someone who's a neophyte, like myself, to the Linux kernel build world and Linux kernel drivers.

Is it possible to set CFLAGS to a linux kernel module Makefile?

Eg: a common device module's Makefile
obj-m:=jc.o
default:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules clean
I consider if I can set CFLAGS to the file. When I change default section to
$(MAKE) -O2 -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
But it didn't work.
Any help? Thanks a lot.
-O2 would be an option to make (or $(MAKE), as you're using it) in what you tried. Obviously, the compiler (probably gcc) needs this flag, not make.
Kbuild understands a make variable named CFLAGS_modulename.o to add specific C flags when compiling this unit. In your case, your module object will be jc.o, so you can specify:
CFLAGS_jc.o := -O2
and it should work. Add V=1 to your $(MAKE) lines to get a verbose output and you should see -O2 when jc.c is being compiled.
You can find more about compiling modules in the official documentation.
You can also use
ccflags-y := -O2
This will be applied to all of the source files compiled for your module with the Makefile. This is indirectly documented in the link provided by eepp in Section 4.2

Resources