问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决
Posted Evan_ZGYF丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决相关的知识,希望对你有一定的参考价值。
摘要:
将klsp移植到高版本内核中编译时,有可能会遇到一些编译报错。
原因一部分是因为新版本的内核加入了更多的代码检测,或者是打开了更多的代码检测选项,将以前的warning视为了error,
还有可能是因为内核之间的版本不兼容,有些函数已经被移除,或者是有些结构体成员发生变化...等等
这些都需要我们在移植的过程中去解决。
本文记录的是将klsp移植到4.19.90内核时,遇到的部分编译报错,及对应的解决办法。
【Makefile】
内核根目录下的Makefile内有很多的编译配置,有些时候我们可能需要关闭一部分的编译检查配置,以避免可能出现的编译报错。
报错:
drivers/klsp/drivers/base/gpio_common.c:100:56: error: macro "__TIME__" might prevent reproducible builds [-Werror=date-time]
GPIO_MSG("<%s, %d> %s\\n", __func__, __LINE__, __TIME__);
错误原因:
新版本 gcc 编译包含 __DATE__ 或者 __TIME__ 宏的源程序时,会报下面的错误:
error: macro "__DATE__" might prevent reproducible builds
error: macro "__TIME__" might prevent reproducible builds
编译驱动时遇到这个错误提示,表示当前编译环境中将关于 DATE 以及 TIME 的警告也作为错误来进行处理的。有如下几种方法可以参考:
1. 在编译驱动的相应 Makefile 中增加一行:CFLAGS += -Wno-error=date-time,然后保存重新 make;
2. 若 CFLAGS 不生效,将关键字替换为 EXTRA_FLAGS;
3. 修改 /lib/modules/'uname -r'/build/Makefile 文件,找到包含 “-Werror=date-time” 这一行注释掉,然后保存退出。之后重新 make 即可
4.修改根目录下的Makefile,将
KBUILD_CFLAGS += $(call cc-option,-Werror=date-time)
改为
KBUILD_CFLAGS += $(call cc-option,-Wno-error=date-time)
解决办法:
修改根目录下的Makefile,将
KBUILD_CFLAGS += $(call cc-option,-Werror=date-time)
改为
KBUILD_CFLAGS += $(call cc-option,-Wno-error=date-time)
【隐式声明】
[-Werror=implicit-function-declaration]
很多函数,我们都是在代码中定义了,但没添加声明就在其他代码中互相调用,这样会出现报错。
还有的原因是,新的内核里去掉了相应的函数定义,需要我们自己添加进去 / 找新的替换函数
报错:
drivers/klsp/common/klsp_timer.c:64:2:
error: implicit declaration of function ‘init_timer’ [-Werror=implicit-function-declaration]
错误原因:
在4.15内核里,init_timer被移除了。需要换用新的timer_setup接口。
解决方法:
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
/* Init timer */
init_timer(&ptimer->timer);
ptimer->timer.function = klsp_timer_process;
ptimer->timer.data = (unsigned long)ptimer;
#else
timer_setup(&ptimer->timer, klsp_timer_process, 0);
#endif
ptimer->timer.expires = jiffies + timeout;
add_timer(&ptimer->timer);
-----------------------------
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
static void klsp_timer_process(unsigned long data)
struct klsp_timer *ptimer = (struct klsp_timer *)data;
#else
static void klsp_timer_process(struct timer_list *t)
struct klsp_timer *ptimer = from_timer(ptimer,t,timer);
#endif
------------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:282:2:
错误:implicit declaration of function ‘init_timer’; did you mean ‘init_timers’?
解决办法:
vi include/linux/timer.h
添加:
#define init_timer(timer) \\
__init_timer((timer),NULL, 0)
一部分提示“implicit declaration”的报错是因为缺少头文件。添加上对应的头文件就好了。
报错:
drivers/klsp/boards/kdv/jd4000/brd_ctrl.c:113:7:
error: implicit declaration of function ‘copy_to_user’
if (copy_to_user(argp, &board_cfg, sizeof(board_cfg)))
解决办法:
vi drivers/klsp/boards/kdv/jd4000/brd_ctrl.c
以前是:#include <asm/uaccess.h>
现在需要添加:#include <linux/uaccess.h>
-------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/jd4000/brd_ctrl.c:203:3:
error: implicit declaration of function ‘msleep’ [-Werror=implicit-function-declaration]
msleep(3000);
解决办法:
drivers/klsp/boards/kdv/jd4000/brd_cfg.c
drivers/klsp/boards/kdv/jd4000/brd_ctrl.c
加上#include <linux/delay.h>
-------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/base/wd_common.c:506:7:
错误:implicit declaration of function ‘kernel_thread’; did you mean ‘kernel_read’?
原先的include/linux/sched.h里面缺少了相关的函数定义,该到了其他的函数里
需要在文件中include其他头文件
解决办法:
vi drivers/base/wd_common.c
添加:
#include <linux/sched/task.h>
#include <linux/sched/types.h>
还有一部分隐式声明报错,是因为自己写的函数,没在头文件里添加声明。
-------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1127:2:
错误:implicit declaration of function ‘mc_config_idt’; did you mean ‘mc_config_pex’?
解决办法:
vi drivers/mca/mca_v6/mca_jd4000.h
添加:int mc_config_idt(void);
------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:201:8:
错误:隐式声明函数‘brd_hi35xx_reset’
解决办法:
vi drivers/pcie_boot/hi35xx_pcie_x64_k.c
添加:extern int brd_hi35xx_reset(u8 slot, u8 chip_type, u8 port);
------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/ceu2/slot.c:100:5:
错误:implicit declaration of function ‘copy_to_user’; did you mean ‘raw_copy_to_user’?
drivers/klsp/boards/kdv/ceu2/slot.c:114:5:
错误:implicit declaration of function ‘copy_from_user’; did you mean ‘raw_copy_from_user’?
解决办法:
vi drivers/klsp/boards/kdv/ceu2/slot.c
添加:#include <linux/uaccess.h>
------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/mca/mca_v6/mca_ms.c:548:4:
错误:implicit declaration of function ‘mca_i2c_pex_reset_port8’; did you mean ‘mca_i2c_pex_port_write’?
drivers/klsp/drivers/mca/mca_v6/mca_ms.c:204:11:
错误:implicit declaration of function ‘pciehp_xmpu5_3_init’; did you mean ‘pciehp_xmpu5_init’?
解决办法:
vi drivers/klsp/drivers/mca/mca_v6/mca_ms.c
添加
extern int mca_i2c_pex_reset_port8(void);
extern int pciehp_xmpu5_3_init(int slot);
------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/jd4000/brd_cfg.c:185:3:
错误:implicit declaration of function ‘hi35xx_pcie_ep_setup’; did you mean ‘hi35xx_pcie_reinit’?
解决办法:
vi drivers/klsp/boards/kdv/jd4000/brd_cfg.c
添加:extern int hi35xx_pcie_ep_setup(u32 id, chip_35xx_info *dev_p);
------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/ceu2/pcie/pcie_hotplug.c:967:8:
错误:implicit declaration of function ‘brd_slot_type_save’; did you mean ‘brd_slot_get’?
解决办法:
vi drivers/klsp/boards/kdv/ceu2/pcie/pcie_hotplug.c
添加:extern u8 brd_slot_type_save(u8 slot, u8 type);
【缺少头文件】
不同的内核版本,有可能出现将函数/结构体定义在不同的头文件中,
这样用老的驱动编译时就会报错,需要在代码中添加相应的新的头文件。
报错:
./arch/x86/include/asm/uaccess.h:32:9: error: dereferencing pointer to incomplete type ‘struct task_struct’
current->thread.addr_limit = fs;
错误原因:
出错原因主要在current上,宏current定义在arch/.../include/asm/current.h中。
编译器不知道task_struct的具体定义,因此,无法解引用current,无法获知其成员pid、comm、flags的类型,
才报“dereferencing pointer to incomplete type”
task_struct定义在<linux/sched.h>中。
在源文件头,加上#include <linux/sched.h>,即可解决问题!
解决办法:
在./arch/x86/include/asm/uaccess.h中加上
#include <linux/sched.h>
【从不兼容的指针类型赋值】
[-Werror=incompatible-pointer-types]
这种一般都是因为语法错误,需要进行修改。
还有的需要做强制类型转换。
报错:
drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c:1841:43:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
priv->gbl = &jd6000_ceue_xmpu_layout;
priv->xbl = &jd6000_ceue_xmpu5_layout;
priv->xbl_3 = &jd6000_xmpu5_3_layout;
解决办法:
vi drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c
改为:
priv->gbl = jd6000_ceue_xmpu_layout;
priv->xbl = jd6000_ceue_xmpu5_layout;
priv->xbl_3 = jd6000_xmpu5_3_layout;
------------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1224:15:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
priv->mbl = &jd4000_layout;
解决办法:
改为:priv->mbl = jd4000_layout;
------------------------------------------------------------------------------------
报错:
./include/linux/workqueue.h:262:17:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
(_work)->func = (_func); \\
drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:275:5: 附注:in expansion of macro ‘INIT_WORK’
INIT_WORK(&pend_event_work, brd_board_type_get);
解决办法:
vi drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c
改为:
INIT_WORK(&pend_event_work, (void *)brd_board_type_get)
------------------------------------------------------------------------------------
报错:
drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:283:26:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
input_timer.function =pulse_signal_give_out;
解决办法:
vi drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c
改为
input_timer.function =(void *)pulse_signal_give_out;
------------------------------------------------------------------------------------
报错:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
drivers/klsp/drivers/watchdog/nct6106_wdt.c:422:17:
wd_obj_s.feed = wdt_feed_dog;
drivers/klsp/drivers/watchdog/nct6106_wdt.c:410:21:
wd_obj_s.wdgenable = wdt_open;
解决办法:
vi drivers/klsp/drivers/watchdog/nct6106_wdt.c
static int wdt_feed_dog(unsigned char val)
改为
static int wdt_feed_dog(int val)
------------
static int wdt_open(struct inode *inode, struct file *file)
wd_obj_s.wdgenable = wdt_open;
改为
static int wdt_open(struct inode *inode, struct file *file)
static int wdt_enable(void)
wd_obj_s.wdgenable = wdt_enable;
------------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:72:20:
错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
g_hi35xx_info[id] = dev_p;
解决办法:
int hi35xx_pcie_ep_setup(u32 id, struct chip_35xx_info *dev_p)
改为
int hi35xx_pcie_ep_setup(u32 id, chip_35xx_info *dev_p)
------------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/mca/mca_v6/mca_chan.c:84:15:
错误:传递‘atomic_read’的第 1 个参数时在不兼容的指针类型间转换
atomic_read(&chan->refcount.refcount));
报错原因:
include/linux/kref.h中的
struct kref atomic_t refcount;;
变成了:
struct kref refcount_t refcount;;
对应
typedef struct refcount_struct
atomic_t refs;
refcount_t;
解决办法:
vi drivers/mca/mca_v6/mca_chan.c
判断内核版本,当大于 KERNEL_VERSION(4,19,0)时,添加上refcount_t.refs
#if defined(CONFIG_JD6100)
refcount_read(&chan->refcount.refcount));
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)
atomic_read(&chan->refcount.refcount.refs));
#else
atomic_read(&chan->refcount.refcount));
#endif
------------------------------------------------------------------------------------
报错:
drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:520:12:
警告:传递‘memcpy’的第 1 个参数时将整数赋给指针,未作类型转换 [-Wint-conversion]
memcpy(g_hi35xx_ctrl.hpdev[devId].baseInfo[2].vmBase + HI3519_EP_INFO_OFFSET, &devId, sizeof(devId));
解决办法:
vi drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c
改为:memcpy((void *)g_hi35xx_ctrl.hpdev[devId].baseInfo[2].vmBase + HI3519_EP_INFO_OFFSET, &devId, sizeof(devId));
【函数声明不是一个原型】
[-Werror=strict-prototypes]
这个报错一般是在定义/声明的时候,没添加void,虽然函数不需要传参,但仍需要加上”void“去表示。
报错:
drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c:1668:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
extern int get_e2prom_userdata_ms_mode();
drivers/klsp/drivers/mca/mca_v6/mca_i2c_pex.c:631:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
static int i2c_pex_debug_init();
drivers/klsp/drivers/mca/mca_v6/mca_ms.c:277:5: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
int mca_wait_ms_notify_is_ready()
drivers/klsp/drivers/mca/mca_v6/mca_ms.c:345:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
extern int get_e2prom_userdata_ms_mode();
解决办法:
在函数里都加上:xxx(void)
【未定义函数】
以前我们可能在老的内核里定义了一些函数,做了一些特殊操作。
现在移植到新内核下之后,需要将那些函数也同样在新的系统下定义一次。
报错:
kernel-4.19.90-2106.3.0/drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1278:
undefined reference to `pcie_reserve_mem_start'
kernel-4.19.90-2106.3.0/drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1279:
undefined reference to `pcie_reserve_mem_size'
kernel-4.19.90-2106.3.0/drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:201:
undefined reference to `brd_hi35xx_reset'
解决办法:
grep -rn "CONFIG_KDV9000A_CEU2"
grep -rn "CONFIG_KDV9000A_CEU2E"
grep -rn "CONFIG_JD4000"
找到定制的代码,在新内核下将老的内核中的改动,移植进去
在kernel下有很多针对内核版本里的改动,需要在openEuler里也修改过去
drivers/i2c/busses/i2c-designware-platdrv.c:276:#ifdef CONFIG_JD4000
drivers/i2c/busses/i2c-i801.c:1275:#if defined(CONFIG_JD4000)
arch/x86/kernel/setup.c:917:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_JD4000) || defined (CONFIG_KDV9000A_CEU2E)
arch/x86/kernel/setup.c:918:#if defined(CONFIG_JD4000)
arch/x86/kernel/setup.c:1329:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_JD4000) || defined (CONFIG_KDV9000A_CEU2E)
mm/mmap.c:1370:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_KDV9000A_CEU2E) || defined(CONFIG_JD4000)
开发者涨薪指南
48位大咖的思考法则、工作方式、逻辑体系
以上是关于问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决的主要内容,如果未能解决你的问题,请参考以下文章
基于tiny4412的Linux内核移植 -- MMA7660驱动移植
基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)