问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决

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位大咖的思考法则、工作方式、逻辑体系

以上是关于问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决的主要内容,如果未能解决你的问题,请参考以下文章

一个linux内核模块移植到低版本时发生的异常

基于tiny4412的Linux内核移植 -- MMA7660驱动移植

基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)

backports移植rtlwifi驱动

如何在 Linux 内核 3.10.0 版本中启用或反向移植蓝牙 BLE 功能?

一,Linux-3.19内核移植DM9000驱动(JZ2440)