Got dpa_app working

This commit is contained in:
2026-05-10 22:25:46 +08:00
parent 8bc9737032
commit 9ccd41bc54
9 changed files with 571 additions and 23 deletions

View File

@@ -9,9 +9,9 @@ apk add alpine-base \
# For diagnotics # For diagnotics
apk add \ apk add \
iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq binutils \ iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq gdb binutils \
openssl conntrack-tools ethtool findmnt kmod coreutils util-linux zstd libcap-utils \ openssl conntrack-tools ethtool findmnt kmod coreutils util-linux zstd libcap-utils \
iotop sysstat iotop sysstat dtc
echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile" echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile"
# Compat layer for kubelet for now. Will look into building it myself later. If needed # Compat layer for kubelet for now. Will look into building it myself later. If needed

View File

@@ -248,7 +248,7 @@ RUN make -C "${ASK_DIR}/cmm" \
PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \ PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \
make -C "${ASK_DIR}/dpa_app" \ make -C "${ASK_DIR}/dpa_app" \
CC="aarch64-linux-musl-gcc -static" \ CC="aarch64-linux-musl-gcc -static" \
CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ CFLAGS="-DDPAA_DEBUG_ENABLE -DLS1043 -DNCSW_LINUX -D__STDC_LIMIT_MACROS \
-I/src/fmc/source \ -I/src/fmc/source \
-I${ASK_DIR}/cdx \ -I${ASK_DIR}/cdx \
-I/src/fmlib/include/fmd \ -I/src/fmlib/include/fmd \
@@ -265,8 +265,8 @@ RUN mkdir -p /out/ASK/dist && \
mkdir -p /out/ASK/bin && \ mkdir -p /out/ASK/bin && \
cp /src/fmc/source/fmc /out/ASK/bin/ && \ cp /src/fmc/source/fmc /out/ASK/bin/ && \
cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \ cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \
cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/ && \ cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/
aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app # aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app
# in-tree Linux kernel modules # in-tree Linux kernel modules
RUN mkdir -p /out/rootfs && \ RUN mkdir -p /out/rootfs && \
@@ -282,7 +282,7 @@ RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \
RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ RUN mkdir -p /out/rootfs-cfg/etc/dpa && \
cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \ cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \
cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \ cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \
cp -r /src/fmc/etc /out/rootfs-cfg/etc cp -r /src/fmc/etc/* /out/rootfs-cfg/etc
FROM scratch AS export FROM scratch AS export

View File

@@ -1,3 +1,6 @@
## ASK
The most important one is vendor's ASK. Which provides all the required resources to build the device-specific kernel
## Updating build.env ## Updating build.env
You can find the latest package versions in here You can find the latest package versions in here
* [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/) * [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/)
@@ -10,3 +13,68 @@ You can find the latest package versions in here
https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale
* We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one. * We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one.
* The actual dts being used is the `mono-gateway-dk-sdk.dts` * The actual dts being used is the `mono-gateway-dk-sdk.dts`
## Testing dpa_app
Run this on the gateway device
```bash
while true; do nc -l -p 1234 -e sh; done
```
Run this script on your dev machine
```bash
#!/bin/bash
FILES="
bin/dpa_app
rootfs-cfg/etc/dpa/cdx_cfg.xml
rootfs-cfg/etc/dpa/cdx_pcd.xml
rootfs-cfg/etc/dpa/cdx_sp.xml
rootfs-cfg/etc/dpa/cdx_cfg_ls1046_rdb.xml
rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml
rootfs-cfg/etc/fmc/config/cfgdata.xsd
rootfs-cfg/etc/fmc/config/netpcd.xsd
"
SIZE=$(
tar -C ./out/ASK -czf - $FILES | wc -c
)
(
echo 'set -eu'
echo 'rm -rf /var/dpa-test'
echo 'mkdir -p /var/dpa-test/bin'
echo 'mkdir -p /etc/dpa'
echo 'mkdir -p /etc/fmc/config'
echo 'base64 -d > /tmp/dpa-test.tar.gz <<'"'"'EOF'"'"''
tar -C ./out/ASK -czf - $FILES | pv -s "$SIZE" | base64
echo 'EOF'
echo 'tar -xzf /tmp/dpa-test.tar.gz -C /var/dpa-test'
echo 'cp /var/dpa-test/bin/dpa_app /var/dpa_app'
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_cfg.xml /etc/dpa/cdx_cfg.xml'
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_pcd.xml /etc/dpa/cdx_pcd.xml'
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_sp.xml /etc/dpa/cdx_sp.xml'
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml /etc/fmc/config/hxs_pdl_v3.xml'
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/cfgdata.xsd /etc/fmc/config/cfgdata.xsd'
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/netpcd.xsd /etc/fmc/config/netpcd.xsd'
echo 'chmod +x /var/dpa_app'
echo 'export CDX_CFG_FILE=/etc/dpa/cdx_cfg.xml'
echo 'export CDX_PCD_FILE=/etc/dpa/cdx_pcd.xml'
echo 'export CDX_SP_FILE=/etc/dpa/cdx_sp.xml'
echo 'export CDX_PDL_FILE=/etc/fmc/config/hxs_pdl_v3.xml'
echo 'echo "CDX_CFG_FILE=$CDX_CFG_FILE"'
echo 'echo "CDX_PCD_FILE=$CDX_PCD_FILE"'
echo 'echo "CDX_SP_FILE=$CDX_SP_FILE"'
echo 'echo "CDX_PDL_FILE=$CDX_PDL_FILE"'
echo 'ls -l /var/dpa_app /etc/dpa /etc/fmc/config'
echo 'echo Running /var/dpa_app'
echo '/var/dpa_app'
echo 'echo exit=$?'
) | nc 10.0.0.10 1234
```

View File

@@ -263,22 +263,23 @@
* ethernet@8 = enet6 = MAC9 (10G) * ethernet@8 = enet6 = MAC9 (10G)
*/ */
ethernet@8 { ethernet@8 {
compatible = "fsl,dpa-ethernet-init"; compatible = "fsl,dpa-ethernet";
fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; /delete-property/ fsl,bman-buffer-pools;
fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>; /delete-property/ fsl,qman-frame-queues-rx;
fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>; /delete-property/ fsl,qman-frame-queues-tx;
}; dma-coherent;
};
/* Add MAC10 - not in qoriq-dpaa-eth.dtsi */ /* Add MAC10 - not in qoriq-dpaa-eth.dtsi */
ethernet@9 { ethernet@9 {
compatible = "fsl,dpa-ethernet-init"; compatible = "fsl,dpa-ethernet";
fsl,fman-mac = <&enet7>; fsl,fman-mac = <&enet7>;
fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; /delete-property/ fsl,bman-buffer-pools;
fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>; /delete-property/ fsl,qman-frame-queues-rx;
fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>; /delete-property/ fsl,qman-frame-queues-tx;
dma-coherent; dma-coherent;
}; };
}; };
&fman0 { &fman0 {
@@ -336,12 +337,14 @@
}; };
ethernet@f0000 { ethernet@f0000 {
status = "okay";
/delete-property/ managed; /delete-property/ managed;
fixed-link = <0 1 10000 0 0>; fixed-link = <0 1 10000 0 0>;
phy-connection-type = "xgmii"; phy-connection-type = "xgmii";
}; };
ethernet@f2000 { ethernet@f2000 {
status = "okay";
/delete-property/ managed; /delete-property/ managed;
fixed-link = <0 1 10000 0 0>; fixed-link = <0 1 10000 0 0>;
phy-connection-type = "xgmii"; phy-connection-type = "xgmii";

View File

@@ -500,14 +500,14 @@
status = "okay"; status = "okay";
}; };
fm1_mac9: ethernet@f0000 { /* 10GEC1 */ fm0_mac9: ethernet@f0000 { /* 10GEC1 */
sfp = <&sfp_xfi0>; sfp = <&sfp_xfi0>;
phy-connection-type = "10gbase-r"; phy-connection-type = "10gbase-r";
managed = "in-band-status"; managed = "in-band-status";
pcs-handle-names = "xfi"; /* Match enet7 for consistency */ pcs-handle-names = "xfi"; /* Match enet7 for consistency */
}; };
fm1_mac10: ethernet@f2000 { /* 10GEC2 */ fm0_mac10: ethernet@f2000 { /* 10GEC2 */
sfp = <&sfp_xfi1>; sfp = <&sfp_xfi1>;
phy-connection-type = "10gbase-r"; phy-connection-type = "10gbase-r";
managed = "in-band-status"; managed = "in-band-status";

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: monok8s <monok8s@example.invalid> From: monok8s <monok8s@example.invalid>
Date: Sun, 10 May 2026 00:00:00 +0000 Date: Sun, 10 May 2026 00:00:00 +0000
Subject: [PATCH] dpa_app: allow XML config paths to be overridden by env Subject: [PATCH 1/4] dpa_app: allow XML config paths to be overridden by env
Keep the vendor default XML paths, but allow deployments to override them Keep the vendor default XML paths, but allow deployments to override them
without patching the binary or placing board-specific XML files directly without patching the binary or placing board-specific XML files directly

View File

@@ -0,0 +1,152 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: monok8s <monok8s@example.invalid>
Date: Sun, 10 May 2026 00:00:00 +0000
Subject: [PATCH 2/4] cdx: harden FMAN port lookup
The DPA userspace loader passes FMC-derived port metadata into the CDX
ioctl. If an Ethernet netdev has a partially initialized DPAA private
structure, find_osdev_by_fman_params() can dereference a missing mac_dev
or FM wrapper pointer while trying to match the FMC port.
Add lookup diagnostics and hard NULL guards so a mismatched board
model returns -ENODEV instead of oopsing the kernel.
---
cdx/devman.c | 85 +++++++++++++++++++++++++++++++++++++--------------
cdx/dpa_cfg.c | 18 ++++++++---
2 files changed, 76 insertions(+), 27 deletions(-)
diff -urN a/cdx/devman.c b/cdx/devman.c
--- a/cdx/devman.c 2026-05-10 00:32:28.745375897 +0000
+++ b/cdx/devman.c 2026-05-10 00:32:29.834300280 +0000
@@ -396,39 +396,74 @@
uint32_t speed)
{
struct net_device *device;
- struct dpa_priv_s *priv;
- struct mac_device *macdev;
+
+ DPA_INFO("%s::lookup fm %u port %u speed %uG\n",
+ __func__, fm_idx, port_idx, speed);
device = first_net_device(&init_net);
- while(1) {
- if (!device)
- break;
- if (device->type == ARPHRD_ETHER) {
- t_LnxWrpFmDev *p_LnxWrpFmDev;
- priv = netdev_priv(device);
- macdev = priv->mac_dev;
- if (macdev) {
- p_LnxWrpFmDev = (t_LnxWrpFmDev*)macdev->fm;
- if (speed == 10) {
- //10 gig interfaces upports only SUPPORTED_10000baseT_Full
- /*DGW board has 2 fixed-link interfaces
- 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid
- 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and
- connected to 10G link of the board.
- sgmii - considered as 1000baseT_Full and this has cell_index = 0*/
-
- if ( (!macdev->fixed_link) && (macdev->if_support != SUPPORTED_10000baseT_Full) )
- goto next_device;
- }
- if ((fm_idx == p_LnxWrpFmDev->id) &&
- (port_idx == macdev->cell_index))
- return device;
- }
+ while (device) {
+ struct dpa_priv_s *priv;
+ struct mac_device *macdev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+
+ if (device->type != ARPHRD_ETHER)
+ goto next_device;
+
+ priv = netdev_priv(device);
+ if (!priv) {
+ DPA_INFO("%s::skip %s: null private data\n",
+ __func__, device->name);
+ goto next_device;
+ }
+
+ macdev = priv->mac_dev;
+ if (!macdev) {
+ DPA_INFO("%s::skip %s: null mac_dev\n",
+ __func__, device->name);
+ goto next_device;
+ }
+
+ if (!macdev->fm) {
+ DPA_INFO("%s::skip %s: null mac_dev->fm cell_index %u max_speed %u fixed_link %u if_support 0x%x\n",
+ __func__, device->name, macdev->cell_index,
+ macdev->max_speed, macdev->fixed_link,
+ macdev->if_support);
+ goto next_device;
}
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)macdev->fm;
+ DPA_INFO("%s::candidate %s fm %u cell_index %u max_speed %u fixed_link %u if_support 0x%x\n",
+ __func__, device->name, p_LnxWrpFmDev->id,
+ macdev->cell_index, macdev->max_speed,
+ macdev->fixed_link, macdev->if_support);
+
+ if (speed == 10) {
+ //10 gig interfaces upports only SUPPORTED_10000baseT_Full
+ /*DGW board has 2 fixed-link interfaces
+ 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid
+ 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and
+ connected to 10G link of the board.
+ sgmii - considered as 1000baseT_Full and this has cell_index = 0*/
+
+ if ((!macdev->fixed_link) &&
+ (macdev->if_support != SUPPORTED_10000baseT_Full))
+ goto next_device;
+ }
+
+ if ((fm_idx == p_LnxWrpFmDev->id) &&
+ (port_idx == macdev->cell_index)) {
+ DPA_INFO("%s::matched %s for fm %u port %u speed %uG\n",
+ __func__, device->name, fm_idx, port_idx, speed);
+ return device;
+ }
+
next_device:
device = next_net_device(device);
}
- return device;
+
+ DPA_ERROR("%s::no OS device found for fm %u port %u speed %uG\n",
+ __func__, fm_idx, port_idx, speed);
+ return NULL;
}
diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
--- a/cdx/dpa_cfg.c 2026-05-10 00:32:28.757992164 +0000
+++ b/cdx/dpa_cfg.c 2026-05-10 00:32:51.954850425 +0000
@@ -301,15 +301,21 @@
struct net_device *dev;
if (port_info->type) {
+ DPA_INFO("%s::mapping user port %s fm %u index %u portid %u type %uG\n",
+ __func__, port_info->name, port_info->fm_index,
+ port_info->index, port_info->portid, port_info->type);
dev = find_osdev_by_fman_params(port_info->fm_index,
port_info->index, port_info->type);
if (!dev) {
- DPA_ERROR("%s::could not map port %s\n",
- __func__, port_info->name);
- return -EIO;
- } else {
- strcpy(port_info->name, dev->name);
+ DPA_ERROR("%s::could not map port %s fm %u index %u portid %u type %uG\n",
+ __func__, port_info->name,
+ port_info->fm_index, port_info->index,
+ port_info->portid, port_info->type);
+ return -ENODEV;
}
+ DPA_INFO("%s::mapped user port %s to netdev %s\n",
+ __func__, port_info->name, dev->name);
+ strscpy(port_info->name, dev->name, sizeof(port_info->name));
}
#ifdef DPA_CFG_DEBUG
DPA_INFO("%s::port %s, fmindex %d, port index %d, port id %d\n",

View File

@@ -0,0 +1,120 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: monok8s <monok8s@example.invalid>
Date: Sun, 10 May 2026 00:00:00 +0000
Subject: [PATCH 3/4] cdx: avoid kfree of userspace dist_info pointers
get_port_info() copies an array of cdx_port_info from userspace. At that
point each cdx_port_info.dist_info field is still a userspace pointer.
However release_cfg_info() treats any non-NULL dist_info as a kernel
allocation and kfree()s it on error paths.
If a later step fails before get_dist_info() has replaced every dist_info
with a kernel allocation, release_cfg_info() can kfree a raw userspace
pointer and oops in kfree()/virt_to_folio().
Stash the userspace dist_info pointers in a temporary array, clear the
kernel-side cdx_port_info.dist_info fields immediately after copy_from_user(),
and pass the saved userspace pointer explicitly to get_dist_info(). This
keeps release_cfg_info() safe on partial-initialization failures.
---
cdx/dpa_cfg.c | 47 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 37 insertions(+), 10 deletions(-)
diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
--- a/cdx/dpa_cfg.c 2026-05-10 00:46:34.295813594 +0000
+++ b/cdx/dpa_cfg.c 2026-05-10 00:46:35.558487337 +0000
@@ -169,11 +169,10 @@
}
//allocate and copy distribution info from uspace
-static int get_dist_info(struct cdx_port_info *port_info)
+static int get_dist_info(struct cdx_port_info *port_info, void *uspace_info)
{
uint32_t mem_size;
struct cdx_dist_info *dist_info;
- void *uspace_info;
#ifdef DPA_CFG_DEBUG
DPA_INFO("%s::port %s dist %d\n", __func__,
@@ -187,7 +186,6 @@
return -ENOMEM;
}
memset(dist_info, 0, mem_size);
- uspace_info = port_info->dist_info;
port_info->dist_info = dist_info;
if (copy_from_user(dist_info, uspace_info,
mem_size)) {
@@ -273,6 +271,7 @@
{
struct cdx_port_info *port_info;
void *uspace_info;
+ void **uspace_dist_info;
uint32_t mem_size;
uint32_t ii;
@@ -289,13 +288,40 @@
return -ENOMEM;
}
memset(port_info, 0, mem_size);
+
+ uspace_dist_info = kcalloc(finfo->max_ports, sizeof(*uspace_dist_info),
+ GFP_KERNEL);
+ if (!uspace_dist_info) {
+ DPA_ERROR("%s::memalloc for uspace_dist_info failed\n",
+ __func__);
+ kfree(port_info);
+ return -ENOMEM;
+ }
+
uspace_info = finfo->portinfo;
finfo->portinfo = port_info;
if (copy_from_user(port_info, uspace_info, mem_size)) {
DPA_ERROR("%s::Read port_info failed\n",
__func__);
+ finfo->portinfo = NULL;
+ kfree(uspace_dist_info);
+ kfree(port_info);
return -EIO;
}
+
+ /*
+ * port_info has just been copied from userspace, so each dist_info
+ * member is still a userspace pointer. release_cfg_info() kfree()s
+ * non-NULL dist_info members, therefore keeping those raw userspace
+ * pointers in the kernel copy turns any later error path into an
+ * invalid kfree(). Stash the userspace pointers separately and clear
+ * the struct fields until get_dist_info() replaces them with real
+ * kernel allocations.
+ */
+ for (ii = 0; ii < finfo->max_ports; ii++) {
+ uspace_dist_info[ii] = port_info[ii].dist_info;
+ port_info[ii].dist_info = NULL;
+ }
//put the linux name for the port
for (ii = 0; ii < finfo->max_ports; ii++) {
struct net_device *dev;
@@ -311,6 +337,7 @@
__func__, port_info->name,
port_info->fm_index, port_info->index,
port_info->portid, port_info->type);
+ kfree(uspace_dist_info);
return -ENODEV;
}
DPA_INFO("%s::mapped user port %s to netdev %s\n",
@@ -330,11 +357,14 @@
for (ii = 0; ii < finfo->max_ports; ii++) {
int retval;
//get dist info for this port
- retval = get_dist_info(port_info);
- if (retval)
+ retval = get_dist_info(port_info, uspace_dist_info[ii]);
+ if (retval) {
+ kfree(uspace_dist_info);
return retval;
+ }
port_info++;
}
+ kfree(uspace_dist_info);
return 0;
}

View File

@@ -0,0 +1,205 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: monok8s <monok8s@example.invalid>
Date: Sun, 10 May 2026 00:00:00 +0000
Subject: [PATCH 4/4] cdx: stash userspace fman nested pointers before cleanup
cdx_ioc_set_dpa_params() copies struct cdx_fman_info from userspace.
The nested portinfo and tbl_info members are userspace pointers at that
point, but release_cfg_info() treats non-NULL nested pointers as
kernel-owned allocations.
If setup fails before get_port_info() or get_cctbl_info() replaces those
members with kernel allocations, the error path can kfree a userspace
address and panic in kfree()/virt_to_folio().
Stash the userspace pointers in temporary arrays, clear the nested
members in fman_info immediately, and pass the stashed pointers into the
copy helpers explicitly. Also route early setup failures through the same
cleanup path so partial state is released consistently.
---
diff --git a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
index c678d5d..55b910d 100644
--- a/cdx/dpa_cfg.c
+++ b/cdx/dpa_cfg.c
@@ -267,10 +267,9 @@ static void *get_dist_info_by_fman_params(struct cdx_fman_info *finfo, uint32_t
#endif //CDX_RTP_RELAY
//allocate and copy port releated info from uspace
-static int get_port_info(struct cdx_fman_info *finfo)
+static int get_port_info(struct cdx_fman_info *finfo, void *uspace_info)
{
struct cdx_port_info *port_info;
- void *uspace_info;
void **uspace_dist_info;
uint32_t mem_size;
uint32_t ii;
@@ -298,7 +297,6 @@ static int get_port_info(struct cdx_fman_info *finfo)
return -ENOMEM;
}
- uspace_info = finfo->portinfo;
finfo->portinfo = port_info;
if (copy_from_user(port_info, uspace_info, mem_size)) {
DPA_ERROR("%s::Read port_info failed\n",
@@ -355,7 +353,7 @@ static int get_port_info(struct cdx_fman_info *finfo)
}
port_info = finfo->portinfo;
for (ii = 0; ii < finfo->max_ports; ii++) {
- int retval;
+ int retval = 0;
//get dist info for this port
retval = get_dist_info(port_info, uspace_dist_info[ii]);
if (retval) {
@@ -369,11 +367,10 @@ static int get_port_info(struct cdx_fman_info *finfo)
}
//allocate and copy cc table infor from uspace
-static int get_cctbl_info(struct cdx_fman_info *finfo)
+static int get_cctbl_info(struct cdx_fman_info *finfo, void *uspace_info)
{
struct table_info *tbl_info;
uint32_t mem_size;
- void *uspace_info;
//allocate table information area
mem_size = (sizeof(struct table_info) * finfo->num_tables);
@@ -384,7 +381,6 @@ static int get_cctbl_info(struct cdx_fman_info *finfo)
return -ENOMEM;
}
memset(tbl_info, 0, mem_size);
- uspace_info = finfo->tbl_info;
finfo->tbl_info = tbl_info;
//copy table related info from user space
if (copy_from_user(tbl_info, (void *)uspace_info, mem_size)) {
@@ -625,9 +621,11 @@ int cdx_ioc_set_dpa_params(unsigned long args)
{
struct cdx_ctrl_set_dpa_params params;
struct cdx_fman_info *finfo;
+ void **uspace_port_info = NULL;
+ void **uspace_tbl_info = NULL;
uint32_t ii;
uint32_t mem_size;
- int retval;
+ int retval = 0;
if (copy_from_user(&params, (void *)args,
sizeof(struct cdx_ctrl_set_dpa_params))) {
@@ -655,6 +653,35 @@ int cdx_ioc_set_dpa_params(unsigned long args)
retval = -EIO;
goto err_ret;
}
+ uspace_port_info = kcalloc(num_fmans, sizeof(*uspace_port_info),
+ GFP_KERNEL);
+ uspace_tbl_info = kcalloc(num_fmans, sizeof(*uspace_tbl_info),
+ GFP_KERNEL);
+ if (!uspace_port_info || !uspace_tbl_info) {
+ DPA_ERROR("%s::unable to allocate user pointer stash\n",
+ __func__);
+ for (ii = 0; ii < num_fmans; ii++) {
+ fman_info[ii].portinfo = NULL;
+ fman_info[ii].tbl_info = NULL;
+ }
+ retval = -ENOMEM;
+ goto err_ret;
+ }
+
+ /*
+ * fman_info is copied from userspace. Its nested portinfo and
+ * tbl_info members are userspace pointers until get_port_info() and
+ * get_cctbl_info() replace them with kernel allocations. Never leave
+ * raw userspace pointers in fman_info, because release_cfg_info() owns
+ * and frees non-NULL nested pointers on error paths.
+ */
+ for (ii = 0; ii < num_fmans; ii++) {
+ uspace_port_info[ii] = fman_info[ii].portinfo;
+ uspace_tbl_info[ii] = fman_info[ii].tbl_info;
+ fman_info[ii].portinfo = NULL;
+ fman_info[ii].tbl_info = NULL;
+ }
+
if (copy_from_user(&ipr_info, (void *)params.ipr_info,
sizeof(struct cdx_ipr_info))) {
DPA_ERROR("%s::Read iprv_info failed\n",
@@ -665,22 +688,26 @@ int cdx_ioc_set_dpa_params(unsigned long args)
//init the fman handles
finfo = fman_info;
for (ii = 0; ii < num_fmans; ii++) {
- if (cdxdrv_get_fman_handles(finfo))
- return -1;
+ if (cdxdrv_get_fman_handles(finfo)) {
+ retval = -EIO;
+ goto err_ret;
+ }
finfo++;
}
finfo = fman_info;
//init interface stats module
- if (cdxdrv_init_stats(finfo->muram_handle))
- return -1;
+ if (cdxdrv_init_stats(finfo->muram_handle)) {
+ retval = -EIO;
+ goto err_ret;
+ }
for (ii = 0; ii < num_fmans; ii++) {
//get port info
- retval = get_port_info(finfo);
+ retval = get_port_info(finfo, uspace_port_info[ii]);
if (retval)
goto err_ret;
//get cc table info
- retval = get_cctbl_info(finfo);
+ retval = get_cctbl_info(finfo, uspace_tbl_info[ii]);
if (retval)
goto err_ret;
finfo++;
@@ -727,29 +754,43 @@ int cdx_ioc_set_dpa_params(unsigned long args)
finfo++;
}
- if (cdx_create_port_fqs())
- return -1;
+ if (cdx_create_port_fqs()) {
+ retval = -EIO;
+ goto err_ret;
+ }
//create cp rate limit policier profiles
if (cdxdrv_create_missaction_policer_profiles(fman_info)) {
+ retval = -EIO;
goto err_ret;
}
#ifdef ENABLE_INGRESS_QOS
if (cdxdrv_create_ingress_qos_policer_profiles(fman_info)) {
+ retval = -EIO;
goto err_ret;
}
#endif
#ifdef ENABLE_EGRESS_QOS
- if(ceetm_init_cq_plcr())
+ if(ceetm_init_cq_plcr()) {
+ retval = -EIO;
goto err_ret;
+ }
#endif
//init the fman and its ports
for (ii = 0; ii < num_fmans; ii++) {
- if (cdxdrv_set_miss_action(ii))
+ if (cdxdrv_set_miss_action(ii)) {
+ retval = -EIO;
goto err_ret;
+ }
}
display_dpa_cfg();
+ kfree(uspace_port_info);
+ kfree(uspace_tbl_info);
return 0;
err_ret:
+ DPA_ERROR("%s::error path retval %d, releasing partial DPA cfg\n",
+ __func__, retval);
+ kfree(uspace_port_info);
+ kfree(uspace_tbl_info);
release_cfg_info();
return retval;
}
--
2.39.5