高通SDX55平台 R8168 PHY驱动适配

1. SDX55 CPE应用场景

高通5G平台SDX55支持5G独立组网(SA)和非独立组网(NSA)两种网络架构,同时兼容LTE和WCDMA制式,拥有更快的传输速度,更优秀的承载能力,以及更低的网络延时,可广泛应用于网关、工业监控、远程医疗、无人机、虚拟现实和沉浸式体验(VR和AR)、智慧能源、车联网、工业互联网、智慧教育、高清视频、智慧城市、家庭娱乐等多个领域。

当SDX55被应用于工业路由器或CPE时,基本都是采取以下连接方案:客户Linux设备通过usb或pcie连接SDX55,使用AT或QMI方式进行拨号,Linux上获取公网ip进行上网,来自Linux的数据流仅可通过USB或pcie方式传输到modem侧,进一步传输到网络侧,完成数据交互。现有方案和数据流程图如下:

(1) 终端设备的数据通过网线或wifi发送到客户设备lan侧端口;
(2) lan侧端口收到数据后会通过cpu对数据进行处理和转发,转发到wan侧端口,即usb0/pcie_mhi0;
(3) usb0/pcie_mhi0将数据通过usb/pcie转发给modem;
(4) modem将数据发送给internet

但是通常CPE厂商考虑到更高的速率和更好的性能,会将控制通路和数据通路进行区分,如控制通路使用USB,而数据通路走PCIE,这就需要在主控和Modem间额外一个PCIE PHY芯片,如RTL8111H、RTL8125、AQC107等。整体框图和数据流方案如下:

(1)modem通过usb与host设备的主控进行连接,用于指令控制(也可作为host的wan口,用于数据传输);
(2)增加一个支持PCIE协议的PHY 芯片作为pcie网卡,如RTL8111、r8125等低成本2.5G phy芯片,将phy 通过pcie与modem连接,使用pcie协议进行数据传输;
(3)phy与host主控通过MDIO连接,作为host的wan口,用于与modem数据传输;
(4)主控的lan口连接RJ45接口,形成有线网口,供终端设备上网;
(5)主控的lan口连接wifi模块,形成无线网口,也可供终端上网。

针对以上场景,我们基于高通SDX55平台,调试RTL8111H PHY芯片。

2. R8168驱动调试

调试前提是基于硬件涉及连接完成,可保证pcie主线上可正确识别到PHY芯片。下面以主控MT7621、RTL8111H、SDX55为例,进行调试。

2.1 lspci

通过串口可以确认SDX55已按照硬件形态作为PCIE RC模式启动,并可以查询到模块pci总线上已识别到8111H PHY芯片:

2.2 集成r8168驱动到内核

从REALTEK官网下载R8168最新驱动源码,下载地址:https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software,将驱动源码放到SDX55基线内核如下目录:kernel\msm-4.14\drivers\net\ethernet\realtek,这个目录主要存放内核驱动中以太网相关驱动源码,realtek中原本有r8125、r8139、r8169等驱动,我们只需要将我们下载的r8168放到该目录下即可:

另外,为了将r8168驱动集成到内核中,需要在Makefile中新增r8168编译选项:

编译验证,出现无法成功加载驱动问题,且无任何异常打印。由于是直接将r8168直接编译进内核,所以无法在文件系统中找到驱动文件,进一步调试。我们有两种怀疑:1.驱动没有编译进内核;2.驱动由于某种原因加载失败。针对这两种思路,我们尝试将驱动编译成.ko模块的方式,然后通过adb导入到模块内进行手动加载:

2.3 could not insert module r8168.ko: Permission denied

手动加载r8168驱动提醒无权限,分析和编译进内核加载失败原因一致:

为了进一步验证,先手动关闭selinux权限,再加载验证:

关闭selinux权限再手动加载r8168.ko是ok的,进一步验证基本功能,首先在模块侧会枚举出以太网卡eth0,然后将eth0网卡加入网桥,并启动dhcp服务用于给host侧分配ip,通常我们可以在SDX55中增加进程用于检测以太网卡枚举,当检测到以太网卡枚举,由进程去up网卡,将网卡加入网桥并启动dhcp服务等,此处先手动完成:

通过如图的配置之后,我们再来检查host侧是否拿到ip,模块是否能通过8111h PHY和MT7621建立起通信:

MT7621的eth1(8168 PHY枚举出的网卡)已获取到ip(192.168.225.50),进行ping网关(192.168.225.1)测试也是ok的,进行反向测试,从模块ping MT7621:

也是ok的,模块拨号,ping外网测试:

2.4 以服务方式加载r8168驱动

上面手动加载验证,整个功能是ok的,基本满足需求,但是存在手动加载驱动无权限问题;这基本可以判断出编译进内核没有加载成功的原因也是由于权限问题导致,虽然手动关闭selinux进行加载测试,r8168基本功能正常,但是通用场景下无法手动加载并主动去关闭selinux,需要解决权限问题。直接编译进内核我们无法控制加载时间和权限问题,因此我们借鉴r8125的驱动加载经验,通过启动服务来使用脚本加载驱动,这样方便我们调整驱动加载时机,控制驱动加载启动方式如是否携带参数等等。首先我们编写了如下service服务,在service中调用r8168_start_stop_le脚本去加载驱动,启动时间在系统初始化服务init_sys_mss.service之后:

poky/meta-qti-data/recipes/r8168/files/r8168.service
[Unit]
Description=R8168
SourcePath=/etc/initscripts/r8168_start_stop_le
After=init_sys_mss.service
DefaultDependencies=no[Service]
Restart=no
RemainAfterExit=yes
ExecStart=/etc/initscripts/r8168_start_stop_le start
ExecStop=/etc/initscripts/r8168_start_stop_le stop[Install]
WantedBy=multi-user.target

r8168_start_stop_le脚本中主要是加载r8168.ko驱动,另外我们还增加了加载驱动时的参数携带,用于支持以太网卡eth0的mac地址可设置,原理是手动发送AT命令去设置mac地址,这个AT下发后会在模块内部创建/data/mac.txt文件,并将下发的mac地址写入到该文件,在驱动加载脚本中可以通过读取文件,获取写入的mac地址,以参数的方式带入驱动,用于驱动设置mac地址,具体脚本见下:

#! /bin/sh
# r8168 Driver init.d script to load r8168 driverexport MODULE_BASE=/lib/modules/`uname -r`/extraPHY_MAC=$(cat /data/mac.txt)
echo "mac.txt -> [$PHY_MAC],mac.len -> [${#PHY_MAC}]" > /dev/kmsgif [ ${#PHY_MAC} -eq 17 ];thenPHY_MAC_VALID=1
elsePHY_MAC_VALID=0PHY_MAC="00:00:00:00:00:00"
fi
case "$1" instart)echo -n "Starting/Loading Ethernet Driver: "echo "r8168:start/load" > /dev/kmsginsmod $MODULE_BASE/r8168.ko #phy_mac=$PHY_MAC mac_phy_valid=$PHY_MAC_VALIDecho "lk-test-at-normal" > /dev/kmsgifconfig eth0 upecho "done loading ethernet driver";;stop)echo -n "Unloading Ethernet Driver "rmmod r8168echo "done unloading ethernet driver";;restart)$0 stop$0 start;;*)echo "Usage { start | stop | restart}" >&2exit 1;;
esacexit 0

驱动中新增参数适配:

char *phy_mac = "";
module_param(phy_mac, charp, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);int mac_phy_valid=0;
module_param(mac_phy_valid, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

对手动设置mac地址的场景进行适配:

static int
rtl8168_get_mac_address(struct net_device *dev)
{...if (!is_valid_ether_addr(mac_addr)) {netif_err(tp, probe, dev, "Invalid ether addr %pM\n", mac_addr);if(mac_phy_valid){char *command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[0] = (unsigned char)simple_strtoull(command_buf,NULL,16);command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[1] = (unsigned char)simple_strtoull(command_buf,NULL,16);command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[2] = (unsigned char)simple_strtoull(command_buf,NULL,16);command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[3] = (unsigned char)simple_strtoull(command_buf,NULL,16);command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[4] = (unsigned char)simple_strtoull(command_buf,NULL,16);command_buf = strsep(&phy_mac,":");if(command_buf == NULL)return -EINVAL;mac_addr[5] = (unsigned char)simple_strtoull(command_buf,NULL,16);netif_err(tp, probe, dev,"add0 is %d, add1 is %d, add2 is %d, add3 is %d, add4 is %d, add5 is %d\r\n",mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],mac_addr[4],mac_addr[5]);netif_info(tp, probe, dev, "manual set ether addr %pM\n",mac_addr);}else{eth_hw_addr_random(dev);ether_addr_copy(mac_addr, dev->dev_addr);netif_info(tp, probe, dev, "Random ether addr %pM\n",mac_addr);}tp->random_mac = 1;...
}

为了将驱动集成到SDX55,我们还需要编写编译脚本,交叉编译出可在SDX55上可用的驱动,高通平台源码编译使用的是bitbake工具,因此需要我们编写.bb脚本,用于驱动或工具的编译,在bb脚本中指定源码所在位置,另外还需将生成的ko文件、servce文件、脚本文件等拷贝安装到指定目录,便于打包进镜像:

# r8168.bb
SUMMARY = "R8168"
export R8168_OBJDIR = "${WORKDIR}/kobj"
export R8168_SRCDIR = "${WORKSPACE}/data-kernel/drivers/r8168/src"HOMEPAGE         = "http://support.cdmatech.com"
LICENSE          = "Qualcomm-Technologies-Inc.-Proprietary"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta-qti-bsp-prop/files/qcom-licenses/${LICENSE};md5=92b1d0ceea78229551577d4284669bb8"
inherit module
inherit qperf
inherit systemdFILES_${PN}     += "${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ethernet/realtek/r8168/src/*"
FILES_${PN}     += "/etc/initscripts/r8168_start_stop_le"# Files from meta-qti-data
FILESPATH =+ "${WORKSPACE}:"
SRC_URI += "file://kobj/Makefile"
SRC_URI += "file://r8168.service"
SRC_URI += "file://r8168_start_stop_le"S = "${R8168_OBJDIR}"# The inherit of module.bbclass will automatically name module packages with
# "kernel-module-" prefix as required by the oe-core build environment.RPROVIDES_${PN} += "kernel-module-r8168"
SYSTEMD_SERVICE_${PN} = "r8168.service"
INITSCRIPT_NAME = "r8168_start_stop_le"
INITSCRIPT_PARAMS = " start 37 S . stop 63 0 1 6 "do_install_append() {# Install unit files to systemd system directory and they will be# packaged and enabled by the systemd class if 'systemd' feature# is enabled in the distro.install -d ${D}${sysconfdir}/initscriptsinstall -d ${D}${systemd_system_unitdir}/install -m 0755 ${WORKDIR}/r8168_start_stop_le ${D}${sysconfdir}/initscriptsinstall -m 0644 ${WORKDIR}/r8168.service \-D ${D}${systemd_system_unitdir}/r8168.service
}# qperf class adds do_copy_kernel_module() after do_module_signing().
# Since we do not yet support module signing, explicitly add the task to
# execute between compile and package stages.
addtask copy_kernel_module after do_compile before do_package# vim: syntax=bitbake

编译生成镜像,进行验证,发现在镜像中未找到r8125.ko、service、脚本等文件,检查编译步骤,发现这些文件在poky/build目录下已经生成,因此怀疑是install时安装失败,在poky\build\tmp-glibc\work\sdxprairie-oe-linux-gnueabi\machine-image\1.0-r0\rootfs\etc\initscripts目录下查找确实缺少脚本文件,在其他对应目录下也缺少ko、service文件,对比其他bb脚本,发现缺少如下配置:
修改后文件确实在rootfs目录下存在了,但在镜像中还是没有相关文件,再次排查打包脚本,发现在脚本中并不是所有安装目录下的文件都会打包,会读取配置文件/poky/meta-qti-data/recipes-products/images/sdxprairie/sdxprairie-data-image.inc,检查该配置文件,缺少r8168,增加进一步验证:

#sdxprairie-data-image.inc
IMAGE_INSTALL += "r8168"

编译进一步验证,集成成功,并且权限问题也没有再出现,分析和加载驱动时机有关系:

经过上述修改,再次验证,驱动加载服务可正常加载驱动,识别PHY芯片,dhcp服务也可自动给MT7621侧分配ip,当SDX55拨号后,MT7621侧可ping通外网。驱动调试完成。

高通SDX55平台:R8168 PHY驱动适配相关推荐

  1. 高通SDX55平台:5G速率问题排查分析方法

    高通SDX55平台:5G速率问题排查分析方法 1. 背景 2. 测速环境配置介绍 2.1 测速工具 2.2 工具使用 2.3 网络参数介绍 2.3.1 带宽 2.3.2 信号质量 2.3.3 RB 2 ...

  2. 高通SDX55平台:adb功能异常

    展锐UDX710:LAN7800 PHY驱动调试 1. 问题描述 2. 问题分析 2.1 测试环境 2.2 初步分析 2.3 USB驱动初始化 2.3.1 USB驱动加载流程 2.3.1.1 USB_ ...

  3. android_驱动_qcom_【高通SDM660平台】(1) ---Bringup Guide

    [高通SDM660平台]Camera 驱动 Bringup Guide 一.Kernel 代码移植 1. DTS 文件配置 1.1 sdm660.dtsi 1.2 sdm660-camera.dtsi ...

  4. 【高通SDM660平台】(1) --- Camera 驱动 Bringup Guide

    [高通SDM660平台]Camera 驱动 Bringup Guide 一.Kernel 代码移植 1. DTS 文件配置 1.1 sdm660.dtsi 1.2 sdm660-camera.dtsi ...

  5. 高通5G平台(SDX55\SDX62\SDX65):ping包异常问题排查指南

    高通5G平台:ping包异常问题排查指南 1. 背景 2. Ping包数据流走向及网络架构 2.1 终端与网络架构图 2.2 终端与基站之间协议栈数据流走向图 3. Ping包问题常见分析思路 3.1 ...

  6. android_驱动_qcom_【高通SDM660平台】(4) --- Camera Init 初始化流程

    [高通SDM660平台]Camera Init 初始化流程 一.Camera 系统架构 二.Camera Init 初始化流程 2.1 CameraService 启动 2.2 CameraServi ...

  7. 高通SDX62平台 MBIM搜网、查询信号等功能异常

    高通SDX62平台 MBIM搜网.查询信号等功能异常 1. 问题描述 按照高通SDX62平台产品规格,其支持RMNET.ECM.RNDIS.PPP.MBIM等拨号:但经测试,发现MBIM拨号功能正常, ...

  8. 高通SDX12:USB3.0驱动初始化代码分析

    1. Code Overview 高通SDX12平台使用synopsys dwc3的USB3.0控制器IP.早期的初始化是分两部分进行的,一个在高通官方提供的驱动中初始化,位于kernel/msm-5 ...

  9. 高通SDX12平台:LINUX上MBIM功能异常

    高通SDX12平台 LINUX上MBIM功能异常 1. 问题描述 按照高通SDX12平台产品规格,其支持RMNET.ECM.RNDIS.PPP.MBIM等拨号:但经测试,发现Windos下MBIM功能 ...

最新文章

  1. 概率论与数理统计中的算子半群 第一讲 Banach-Steinhaus定理2 Banach-Steinhaus定理的应用
  2. Mahout推荐算法API详解
  3. 征战蓝桥 —— 2016年第七届 —— C/C++A组第5题——消除尾一
  4. InnoDB 的辅助索引叶子节点为什么不直接保存的记录地址而要存主键键值
  5. java 文件流 重写_java中关于文件流的总结
  6. 新电脑怎么分盘_电脑如何分盘及删除与合并04
  7. 关于服务器发生w32tm的ID:29,ID:47等错误
  8. Bitmap详解(中)之像素级操作
  9. mysql 存在更新不存在写入_梅姨这个人,到底存在不存在?
  10. html 样式初始化,css样式初始化
  11. 添加多浏览器支持是什么意思_周公解梦:梦见无缘无故多了一个儿子什么意思...
  12. C# asp.net页面通过URL参数传值中文乱码问题解决办法
  13. docker portainer_Docker可视化管理:Portainer中文版
  14. Python学习笔记之 循环,列表生成式,生成器,迭代器
  15. Linux基本操作---实践+理解--CentOS 7
  16. Gibberish 本地化插件学习
  17. 开机输入用户名密码时弹出被调用对象已与其客户端断开连接解决方法
  18. 模板:求图的强连通分量(SCC)
  19. 比赛报名 | 2019AIIA杯电梯调度算法大赛正式启动
  20. 软件测试自学英语语法,5个能力一流的英语自学APP,赶紧盘它,让你告别零基础...

热门文章

  1. Vue2 带纵向合并的原生表格实现切割侧栏分页
  2. js 获取字符串的UTF8编码
  3. element ui el-table单元格按需合并
  4. 基于I2C协议读取AD值(arm单片机,转换标志位RDY-可中断使用)
  5. 简:webservice服务端及客户端开发
  6. Java Swing窗体JFrame之设置窗体图标
  7. Windows Server 2016修改计算机名
  8. 作为一个平面设计师,该如何转变平面设计思维
  9. 图片怎么压缩到200K以内,这3个图片压缩方法,简单有效
  10. Python计算分位点与逆运算:根据给定的值,计算在序列中的分位水平