因为项目需求,要将产品的wifi型号由AC8265升级为AC9260。我们当前项目平台的内核版本为3.9.109,而AC9260要求的最低内核版本为3.14.04。于是我下载了一个3.14的长期支持版本--3.14.79,准备基于这个版本把iwlwifi模块移植到3.9内核上。
下面是移植过程中记录的一些细节:
1. 相关文件:
(1)9260的固件
iwlwifi-9260-th-b0-jf-b0-34.ucode
(2)iwlwifi数据结构涉及到的相关头文件
kernel/include/net/cfg80211.h
kernel/include/linux/ieee80211.h
kernel/include/net/mac80211.h
kernel/include/uapi/linux/nl80211.h
kernel/include/linux/skbuff.h
(3)网络子系统相关文件
kernel/net/mac80211/agg-rx.c
kernel/net/mac80211/mlme.c
kernel/net/wireless/nl80211.c
kernel/net/mac80211/rx.c
(4)iwlwifi驱动模块
kernel/drivers/net/wireless/intel/iwlwifi/*
2. 移植方法
刚开始移植的时候,想过几种方式。先试过直接升级整个网络子系统,后来发现涉及到数据结构变化太大,修改的地方太多,工作量巨大,因此放弃了这种方式。
后来想着先将头文件数据结构差别部分同步完,这样iwlwifi驱动模块就可以成功编译。这种方式虽然可行,但是仍然不是最简化的方式,因为和网络子系统相关的头文件数据结构很多,有些iwlwifi用到了,有些没有用到。
为了进一步减少移植工作量,在同步数据结构的时候进行了更有针对性的移植。比较数据结构有差异的时候,先搜索iwlwifi是否用到了这个数据结构,如果有用到,就移植过去,如果没有用到就跳过。另外,网络子系统交互流程有些变化,旧版本和新版本的处理方式其实都可以生效,只是过程有些变化。
(1)关于数据结构定义
新旧版本往往结构体成员、枚举变量成员的名称或者成员个数不一样,移植的时候需要遵循以下原则:
a. 求同存异
当旧版本和新版本表示同一个意思的成员变量名称不一样时,为了兼容现有版本的驱动和适用新版本驱动,旧版本名称应保持不变,然后新增适用于新版本的名称。这样的话,成员变量会变多,虽然有些变量在功能上可能重复了,但是兼容性更好了。
b. 以少服多
当某个变量是子系统多处共用的,而当前模块使用的名称不一致。并且该子系统全局变量值的改变又影响当前移植模块的处理结果,那么应该将移植的当前模块中所有该不一致变量名称替换为子系统所使用的变量名。
(2)关于函数接口
当新旧版本函数接口参数不一致时,可以先定义新函数接口以保持参数一致,然后在新接口里面使用旧接口的内容,这样就可以规避数据格式(参数个数、参数类型、参数格式等)不一致导致的编译不通过问题。