From 73a362a8c6e9ee521fd7f231aaca1341051c814b Mon Sep 17 00:00:00 2001 From: hcf Date: Wed, 28 Aug 2024 16:09:42 +0800 Subject: [PATCH] Dinghai driver init --- README.md | 12 +++-- kmod-dinghai.spec | 105 ++++++++++++++++++++++++++++++++++++++++++++ kmod-dinghai.tar.gz | Bin 0 -> 18138 bytes 3 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 kmod-dinghai.spec create mode 100644 kmod-dinghai.tar.gz diff --git a/README.md b/README.md index 81aa5e4..1efb86a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # kmod-dinghai #### 介绍 -dinghai kernel driver +E310/E312 是中兴生产的标卡 采用PCIE5×16接口 支持 SRIOV 虚拟化技术 支持网络功能卸载包括 checksum 卸载、vlan 卸载 及 RDMA 功能。 + +I510/I511/I512 是中兴生产的智能网卡 采用PCIE5×16接口 支持 SRIOV 虚拟化技术 支持 网络卸载加速 包括virtio-net vSwitch 等。安全加速包括IPSEC卸载 TLS 等功能。 网络功能支持 200G 吞吐量 、DPDK 100Mpps转发 安全功能支持 IPSEC 200G 吞吐量、TLS 200G 、国密SM 200G。 + +X510/X512 是中兴生产的一款DPU 采用PCIE5×16接口 支持 SRIOV 虚拟化技术 支持RDMA 卸载、安全加速、 存储加速包括virtio-blk 、NVMe 等。 #### 软件架构 软件架构说明 @@ -9,15 +13,9 @@ dinghai kernel driver #### 安装教程 -1. xxxx -2. xxxx -3. xxxx #### 使用说明 -1. xxxx -2. xxxx -3. xxxx #### 参与贡献 diff --git a/kmod-dinghai.spec b/kmod-dinghai.spec new file mode 100644 index 0000000..67901bf --- /dev/null +++ b/kmod-dinghai.spec @@ -0,0 +1,105 @@ +%global pkg dinghai +%define pkg_version 2.24.20.02 +%define release 1 + +%global debug_package %{nil} + +Name: kmod-%{pkg} +Version: %{pkg_version} +Release: %{release}%{?dist} +Summary: ZTE SmartNIC and DPU driver +License: GPLv2 +URL: https://gitee.com/anolis/kmod-dinghai +Source0: kmod-%{pkg}.tar.gz +Epoch: 1 + +# 安装依赖, 和内核版本对应 +Requires(posttrans): %{_sbindir}/depmod +Requires(postun): %{_sbindir}/depmod +Requires(posttrans): %{_sbindir}/weak-modules +Requires(postun): %{_sbindir}/weak-modules +Requires(posttrans): %{_bindir}/sort +Requires(postun): %{_bindir}/sort + +# 构建依赖, 和内核版本对应 +BuildRequires: elfutils-libelf-devel +BuildRequires: gcc +BuildRequires: kmod +BuildRequires: make +BuildRequires: system-rpm-config +BuildRequires: perl-Data-Dumper +BuildRequires: kernel +BuildRequires: kernel-headers +BuildRequires: kernel-devel + +%define kernel_version %(rpm -q kernel-devel | sed 's/kernel-devel-//') +%define kernel_source /usr/src/kernels/%{kernel_version} + +%description +RPM Package for ZXDH Driver + +%prep +%setup -q -n kmod-%{pkg} + +%build +echo "kernel_version:%{kernel_version}" +pushd crypto/zsda +%{__make} %{?_smp_mflags} -C %{kernel_source} M=$PWD modules CONFIG_ACC_ZSDA_COMMON=m CONFIG_ACC_ZSDA_PF=m CONFIG_ACC_ZSDA_VF=m +popd + +%install +mkdir -p %{buildroot}/lib/modules/%{kernel_version}/extra/drivers/dinghai/crypto/zsda/ +for ko in $(find crypto/zsda/accdevice/ -name '*.ko'); do + if [[ $ko == crypto/zsda/accdevice/* ]]; then + target_dir=%{buildroot}/lib/modules/%{kernel_version}/extra/drivers/dinghai/crypto/zsda/ + fi + %{__install} -D -t $target_dir $ko +done + +ls -l /lib/modules/%{kernel_version} + + +# Make .ko objects temporarily executable for automatic stripping +find %{buildroot}/lib/modules -type f -name \*.ko -exec chmod u+x \{\} \+ + +# Generate depmod.conf +%{__install} -d %{buildroot}/%{_sysconfdir}/depmod.d/ +for kmod in $(find %{buildroot}/lib/modules/%{kernel_version}/extra -type f -name \*.ko -printf "%%P\n" | sort) +do + echo "override $(basename $kmod .ko) * weak-updates/$(dirname $kmod)" >> %{buildroot}/%{_sysconfdir}/depmod.d/%{pkg}.conf + echo "override $(basename $kmod .ko) * extra/$(dirname $kmod)" >> %{buildroot}/%{_sysconfdir}/depmod.d/%{pkg}.conf +done + +%clean +%{__rm} -rf %{buildroot} + +%post +depmod -a > /dev/null 2>&1 + + +%preun +list_file="/var/run/rpm-%{pkg}-modules.list" +mkdir -p /var/run +for ko in $(find %{buildroot}/lib/modules/%{kernel_version}/extra/drivers/dinghai/crypto/zsda/ -name '*.ko'); do + echo "${ko#%{buildroot}}" >> $list_file +done + +%postun +depmod -a > /dev/null 2>&1 + +if [ -x "/usr/sbin/weak-modules" ]; then + modules=( $(cat /var/run/rpm-%{pkg}-modules.list) ) + printf '%s\n' "${modules[@]}" | /usr/sbin/weak-modules --no-initramfs --remove-modules +fi +rm /var/run/rpm-%{pkg}-modules.list + +%files +%defattr(644,root,root,755) +/lib/modules/%{kernel_version} +%config(noreplace) %{_sysconfdir}/depmod.d/%{pkg}.conf + +%changelog +* Wed Aug 28 2024 hcf - 1:2.24.20.02-1 +- Dinghai driver init + + diff --git a/kmod-dinghai.tar.gz b/kmod-dinghai.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6b12511680f820ce630022dc7ee5bd76750e6181 GIT binary patch literal 18138 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