<div class="zcontentRow"><p>From 7da90caa892abc0ab27fc11e892f6616f4bc8c9a Mon Sep 17 00:00:00 2001</p><p>From: Yong Zhang <zhang.yong25@zte.com.cn></p><p>Date: Wed, 12 Jun 2024 17:35:34 +0800</p><p>Subject: [PATCH] raw/zxdh: introduce zxdh raw device driver</p><p><br></p><p>Introduce rawdev driver support for ZXDH which</p><p>can help to connect two separate hosts with each other.</p><p><br></p><p>Signed-off-by: Yong Zhang <zhang.yong25@zte.com.cn></p><p>---</p><p> MAINTAINERS                    |   5 +</p><p> doc/guides/rawdevs/index.rst   |   1 +</p><p> doc/guides/rawdevs/zxdh.rst    |  28 +</p><p> drivers/raw/meson.build        |   1 +</p><p> drivers/raw/zxdh/meson.build   |   5 +</p><p> drivers/raw/zxdh/zxdh_pci.c    | 564 ++++++++++++++++++++</p><p> drivers/raw/zxdh/zxdh_pci.h    |  40 ++</p><p> drivers/raw/zxdh/zxdh_rawdev.c | 911 +++++++++++++++++++++++++++++++++</p><p> drivers/raw/zxdh/zxdh_rawdev.h | 165 ++++++</p><p> 9 files changed, 1720 insertions(+)</p><p> create mode 100644 doc/guides/rawdevs/zxdh.rst</p><p> create mode 100644 drivers/raw/zxdh/meson.build</p><p> create mode 100644 drivers/raw/zxdh/zxdh_pci.c</p><p> create mode 100644 drivers/raw/zxdh/zxdh_pci.h</p><p> create mode 100644 drivers/raw/zxdh/zxdh_rawdev.c</p><p> create mode 100644 drivers/raw/zxdh/zxdh_rawdev.h</p><p><br></p><p>diff --git a/MAINTAINERS b/MAINTAINERS</p><p>index c9adff9846..4fcf137c10 100644</p><p>--- a/MAINTAINERS</p><p>+++ b/MAINTAINERS</p><p>@@ -1478,6 +1478,11 @@ M: Gagandeep Singh <g.singh@nxp.com></p><p> F: drivers/raw/dpaa2_cmdif/</p><p> F: doc/guides/rawdevs/dpaa2_cmdif.rst</p><p> </p><p>+ZXDH</p><p>+M: Yong Zhang <zhang.yong25@zte.com.cn></p><p>+F: drivers/raw/zxdh/</p><p>+F: doc/guides/rawdevs/zxdh.rst</p><p>+</p><p> </p><p> Packet processing</p><p> -----------------</p><p>diff --git a/doc/guides/rawdevs/index.rst b/doc/guides/rawdevs/index.rst</p><p>index f34315f051..d85a4b7148 100644</p><p>--- a/doc/guides/rawdevs/index.rst</p><p>+++ b/doc/guides/rawdevs/index.rst</p><p>@@ -16,3 +16,4 @@ application through rawdev API.</p><p>     dpaa2_cmdif</p><p>     ifpga</p><p>     ntb</p><p>+    zxdh</p><p>diff --git a/doc/guides/rawdevs/zxdh.rst b/doc/guides/rawdevs/zxdh.rst</p><p>new file mode 100644</p><p>index 0000000000..15ad85261f</p><p>--- /dev/null</p><p>+++ b/doc/guides/rawdevs/zxdh.rst</p><p>@@ -0,0 +1,28 @@</p><p>+..  SPDX-License-Identifier: BSD-3-Clause</p><p>+    Copyright 2024 ZTE Corporation</p><p>+</p><p>+ZXDH Rawdev Driver</p><p>+======================</p><p>+</p><p>+The ``zxdh`` rawdev driver is an implementation of the rawdev API,</p><p>+that provides communication between two separate hosts.</p><p>+This is achieved via using the GDMA controller of Dinghai SoC.</p><p>+</p><p>+</p><p>+Initialization</p><p>+--------------</p><p>+</p><p>+The ZXDH is exposed as a vdev device which consists of MPF devices.</p><p>+On EAL initialization, vdev device can be created from the application code by</p><p>+</p><p>+* Invoking ``rte_vdev_init("rawdev_zxdh_gdma")`` from the application</p><p>+</p><p>+* Using ``--vdev="rawdev_zxdh_gdma"`` in the EAL options, which will call</p><p>+  rte_vdev_init() internally</p><p>+</p><p>+</p><p>+Platform Requirement</p><p>+~~~~~~~~~~~~~~~~~~~~</p><p>+</p><p>+This PMD is only supported on ZTE Neo Platforms:</p><p>+- Neo X510/X512</p><p>diff --git a/drivers/raw/meson.build b/drivers/raw/meson.build</p><p>index 05cad143fe..237d1bdd80 100644</p><p>--- a/drivers/raw/meson.build</p><p>+++ b/drivers/raw/meson.build</p><p>@@ -12,5 +12,6 @@ drivers = [</p><p>         'ifpga',</p><p>         'ntb',</p><p>         'skeleton',</p><p>+        'zxdh',</p><p> ]</p><p> std_deps = ['rawdev']</p><p>diff --git a/drivers/raw/zxdh/meson.build b/drivers/raw/zxdh/meson.build</p><p>new file mode 100644</p><p>index 0000000000..6cd9521387</p><p>--- /dev/null</p><p>+++ b/drivers/raw/zxdh/meson.build</p><p>@@ -0,0 +1,5 @@</p><p>+#SPDX-License-Identifier: BSD-3-Clause</p><p>+#Copyright 2024 ZTE Corporation</p><p>+</p><p>+deps += ['rawdev', 'kvargs', 'mbuf', 'bus_vdev']</p><p>+sources = files('zxdh_rawdev.c', 'zxdh_pci.c')</p><p>diff --git a/drivers/raw/zxdh/zxdh_pci.c b/drivers/raw/zxdh/zxdh_pci.c</p><p>new file mode 100644</p><p>index 0000000000..4debddb0d2</p><p>--- /dev/null</p><p>+++ b/drivers/raw/zxdh/zxdh_pci.c</p><p>@@ -0,0 +1,564 @@</p><p>+/* SPDX-License-Identifier: BSD-3-Clause</p><p>+ * Copyright 2024 ZTE Corporation</p><p>+ */</p><p>+</p><p>+#include <stdio.h></p><p>+#include <stdlib.h></p><p>+#include <string.h></p><p>+#include <getopt.h></p><p>+#include <sys/mman.h></p><p>+#include <fcntl.h></p><p>+#include <errno.h></p><p>+#include <dirent.h></p><p>+#include <unistd.h></p><p>+</p><p>+#include "zxdh_rawdev.h"</p><p>+#include "zxdh_pci.h"</p><p>+</p><p>+#define PCI_DEVICES_DIR          "/sys/bus/pci/devices"</p><p>+</p><p>+#define BAR0_IDX                 (0)</p><p>+#define BAR2_IDX                 (2)</p><p>+</p><p>+#define IORESOURCE_MEM           (0x00000200)</p><p>+#define PCI_RESOURCE_FMT_NVAL    (3)</p><p>+#define PCI_FMT_NVAL             (4)</p><p>+#define FILE_FMT_NVAL            (2)</p><p>+</p><p>+#define STR_BUFF_LEN             (128)</p><p>+</p><p>+#define BYTES_NO_SWAP            (0)</p><p>+#define BYTES_SWAP               (1)</p><p>+</p><p>+#define PCI_CMD_OFFSET           (0x04)</p><p>+#define PCI_CMD_BYTES            (2)</p><p>+#define PCI_CMD_MSE_BIT          (1)</p><p>+#define FPGA_VER_OFFSET          (0x420)</p><p>+#define FPGA_VER_BYTES           (4)</p><p>+#define BOM_ID_OFFSET            (0x424)</p><p>+#define BOM_ID_BYTES             (1)</p><p>+#define FPGA_PR_FLAG_OFFSET      (0x425)</p><p>+#define FPGA_PR_FLAG_BYTES       (1)</p><p>+#define BOARD_ID_OFFSET          (0x426)</p><p>+#define BOARD_ID_BYTES           (2)</p><p>+#define FPGA_MAKE_TIME_OFFSET    (0x428)</p><p>+#define FPGA_MAKE_TIME_BYTES     (4)</p><p>+</p><p>+#define PARA_PR_FLAG             (0)</p><p>+#define PARA_FPGA_VER            (1)</p><p>+#define PARA_FPGA_MAKE_TIME      (2)</p><p>+#define PARA_BOARD_ID            (3)</p><p>+#define PARA_BOM_ID              (4)</p><p>+#define PARA_PCI_CMD             (5)</p><p>+</p><p>+#define PCI_READ                 (0)</p><p>+#define PCI_WRITE                (1)</p><p>+</p><p>+struct zxdh_pci_dev gdev;</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rw_pci_config(struct zxdh_pci_dev *dev, uint8_t rw, uint offset, uint count, uint8_t *buf)</p><p>+{</p><p>+<span style="white-space:pre">       </span>int fd = -1;</p><p>+<span style="white-space:pre">     </span>uint res = 0;</p><p>+<span style="white-space:pre">    </span>int ret = -1;</p><p>+<span style="white-space:pre">    </span>char filename[FILE_PATH_LEN] = {0};</p><p>+</p><p>+<span style="white-space:pre">  </span>snprintf(filename, sizeof(filename), "/proc/bus/pci/%02x/%02x.%d",</p><p>+<span style="white-space:pre">                     </span>dev->bus, dev->devid, dev->function);</p><p>+<span style="white-space:pre">   </span>fd = open(filename, O_RDWR);</p><p>+<span style="white-space:pre">     </span>if (fd < 0) {</p><p>+<span style="white-space:pre">         </span>snprintf(filename, sizeof(filename), "/proc/bus/pci/%04x:%02x/%02x.%d",</p><p>+<span style="white-space:pre">                                </span>dev->domain, dev->bus, dev->devid, dev->function);</p><p>+<span style="white-space:pre">           </span>fd = open(filename, O_RDWR);</p><p>+<span style="white-space:pre">             </span>if (fd < 0) {</p><p>+<span style="white-space:pre">                 </span>ZXDH_PMD_LOG(ERR, "Failed to open file:%s, fd:%d!", filename, fd);</p><p>+<span style="white-space:pre">                     </span>return -1;</p><p>+<span style="white-space:pre">               </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>res = lseek(fd, offset, SEEK_SET);</p><p>+<span style="white-space:pre">       </span>if (res != offset) {</p><p>+<span style="white-space:pre">             </span>close(fd);</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Failed to lseek pci, res:%d!", res);</p><p>+<span style="white-space:pre">                </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (rw == PCI_READ)</p><p>+<span style="white-space:pre">              </span>ret = read(fd, buf, count);</p><p>+<span style="white-space:pre">      </span>else</p><p>+<span style="white-space:pre">             </span>ret = write(fd, buf, count);</p><p>+</p><p>+<span style="white-space:pre"> </span>if (ret < 0) {</p><p>+<span style="white-space:pre">                </span>close(fd);</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Failed to rw pci:%d, ret:%d!", rw, ret);</p><p>+<span style="white-space:pre">            </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>close(fd);</p><p>+<span style="white-space:pre">       </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_cfg_space_read(struct zxdh_pci_dev *dev, uint8_t ParaType, uint *pParaVer)</p><p>+{</p><p>+<span style="white-space:pre">    </span>int ret = 0;</p><p>+<span style="white-space:pre">     </span>uint8_t aRegVal[sizeof(uint)] = {0};</p><p>+<span style="white-space:pre">     </span>uint8_t ucLoop = 0;</p><p>+<span style="white-space:pre">      </span>uint8_t ucSwap = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">  </span>uint dwRegOffset = 0;</p><p>+<span style="white-space:pre">    </span>uint dwRegLen = 0;</p><p>+</p><p>+<span style="white-space:pre">   </span>if ((dev == NULL) || (pParaVer == NULL)) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Param is invalid!");</p><p>+<span style="white-space:pre">                </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>switch (ParaType) {</p><p>+<span style="white-space:pre">      </span>case PARA_PR_FLAG:</p><p>+<span style="white-space:pre">               </span>dwRegOffset = FPGA_PR_FLAG_OFFSET;</p><p>+<span style="white-space:pre">               </span>dwRegLen    = FPGA_PR_FLAG_BYTES;</p><p>+<span style="white-space:pre">              </span>ucSwap      = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">              </span>break;</p><p>+<span style="white-space:pre">   </span>case PARA_FPGA_VER:</p><p>+<span style="white-space:pre">              </span>dwRegOffset = FPGA_VER_OFFSET;</p><p>+<span style="white-space:pre">           </span>dwRegLen    = FPGA_VER_BYTES;</p><p>+<span style="white-space:pre">          </span>ucSwap      = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">              </span>break;</p><p>+<span style="white-space:pre">   </span>case PARA_FPGA_MAKE_TIME:</p><p>+<span style="white-space:pre">                </span>dwRegOffset = FPGA_MAKE_TIME_OFFSET;</p><p>+<span style="white-space:pre">             </span>dwRegLen    = FPGA_MAKE_TIME_BYTES;</p><p>+<span style="white-space:pre">            </span>ucSwap      = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">              </span>break;</p><p>+<span style="white-space:pre">   </span>case PARA_BOARD_ID:</p><p>+<span style="white-space:pre">              </span>dwRegOffset = BOARD_ID_OFFSET;</p><p>+<span style="white-space:pre">           </span>dwRegLen    = BOARD_ID_BYTES;</p><p>+<span style="white-space:pre">          </span>ucSwap      = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">              </span>break;</p><p>+<span style="white-space:pre">   </span>case PARA_BOM_ID:</p><p>+<span style="white-space:pre">                </span>dwRegOffset = BOM_ID_OFFSET;</p><p>+<span style="white-space:pre">             </span>dwRegLen    = BOM_ID_BYTES;</p><p>+<span style="white-space:pre">            </span>ucSwap      = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">              </span>break;</p><p>+<span style="white-space:pre">   </span>case PARA_PCI_CMD:</p><p>+<span style="white-space:pre">               </span>dwRegOffset = PCI_CMD_OFFSET;</p><p>+<span style="white-space:pre">            </span>dwRegLen    = PCI_CMD_BYTES;</p><p>+<span style="white-space:pre">           </span>ucSwap      = BYTES_SWAP;</p><p>+<span style="white-space:pre">         </span>break;</p><p>+<span style="white-space:pre">   </span>default:</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "ParaType %u not support!", ParaType);</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (dwRegLen > sizeof(uint)) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "dwRegLen %u is invalid", dwRegLen);</p><p>+<span style="white-space:pre">         </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>*pParaVer = 0;</p><p>+<span style="white-space:pre">   </span>ret = zxdh_gdma_rw_pci_config(dev, PCI_READ, dwRegOffset, dwRegLen, aRegVal);</p><p>+<span style="white-space:pre">    </span>if (ret != 0) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "ParaType %u, zxdh_gdma_rw_pci_config failed!", ParaType);</p><p>+<span style="white-space:pre">           </span>return ret;</p><p>+<span style="white-space:pre">      </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (ucSwap == BYTES_SWAP) {</p><p>+<span style="white-space:pre">              </span>for (ucLoop = 0; ucLoop < dwRegLen; ucLoop++)</p><p>+<span style="white-space:pre">                 </span>*pParaVer = (*pParaVer << 8) | aRegVal[dwRegLen-1-ucLoop];</p><p>+<span style="white-space:pre"> </span>} else {</p><p>+<span style="white-space:pre">         </span>for (ucLoop = 0; ucLoop < dwRegLen; ucLoop++)</p><p>+<span style="white-space:pre">                 </span>*pParaVer = (*pParaVer << 8) | aRegVal[ucLoop];</p><p>+<span style="white-space:pre">    </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return ret;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_cfg_space_write(struct zxdh_pci_dev *dev, uint8_t ParaType, uint *pParaVer)</p><p>+{</p><p>+<span style="white-space:pre"> </span>int ret = 0;</p><p>+<span style="white-space:pre">     </span>uint8_t aRegVal[sizeof(uint)] = {0};</p><p>+<span style="white-space:pre">     </span>uint8_t ucLoop = 0;</p><p>+<span style="white-space:pre">      </span>uint8_t ucSwap = BYTES_NO_SWAP;</p><p>+<span style="white-space:pre">  </span>uint dwRegOffset = 0;</p><p>+<span style="white-space:pre">    </span>uint dwRegLen = 0;</p><p>+</p><p>+<span style="white-space:pre">   </span>if ((dev == NULL) || (pParaVer == NULL)) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Param is invalid");</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (ParaType != PARA_PCI_CMD) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "ParaType %u not support!", ParaType);</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>dwRegOffset = PCI_CMD_OFFSET;</p><p>+<span style="white-space:pre">    </span>dwRegLen = PCI_CMD_BYTES;</p><p>+<span style="white-space:pre">        </span>ucSwap = BYTES_SWAP;</p><p>+</p><p>+<span style="white-space:pre"> </span>if (dwRegLen > sizeof(uint)) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "dwRegLen %u is invalid", dwRegLen);</p><p>+<span style="white-space:pre">         </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (ucSwap == BYTES_SWAP) {</p><p>+<span style="white-space:pre">              </span>for (ucLoop = 0; ucLoop < dwRegLen; ucLoop++)</p><p>+<span style="white-space:pre">                 </span>aRegVal[ucLoop] = (*pParaVer >> 8*ucLoop) & 0xff;</p><p>+<span style="white-space:pre">      </span>} else {</p><p>+<span style="white-space:pre">         </span>for (ucLoop = 0; ucLoop < dwRegLen; ucLoop++)</p><p>+<span style="white-space:pre">                 </span>aRegVal[ucLoop] = (*pParaVer >> 8*(dwRegLen-1-ucLoop)) & 0xff;</p><p>+<span style="white-space:pre"> </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>ret = zxdh_gdma_rw_pci_config(dev, PCI_WRITE, dwRegOffset, dwRegLen, aRegVal);</p><p>+<span style="white-space:pre">   </span>if (ret != 0) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "ParaType %u, zxdh_gdma_rw_pci_config failed!", ParaType);</p><p>+<span style="white-space:pre">           </span>return ret;</p><p>+<span style="white-space:pre">      </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return ret;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_str_split(char *string, int stringlen, char **tokens, int maxtokens, char delim)</p><p>+{</p><p>+<span style="white-space:pre">    </span>int loop = 0;</p><p>+<span style="white-space:pre">    </span>int tok = 0;</p><p>+<span style="white-space:pre">     </span>int tokstart = 1; /* first token is right at start of string */</p><p>+</p><p>+<span style="white-space:pre">      </span>if (string == NULL || tokens == NULL) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "Param is invalid!");</p><p>+<span style="white-space:pre">                </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>for (loop = 0; loop < stringlen; loop++) {</p><p>+<span style="white-space:pre">            </span>if (string[loop] == '\0' || tok >= maxtokens)</p><p>+<span style="white-space:pre">                 </span>break;</p><p>+</p><p>+<span style="white-space:pre">               </span>if (tokstart) {</p><p>+<span style="white-space:pre">                  </span>tokstart = 0;</p><p>+<span style="white-space:pre">                    </span>tokens[tok++] = &string[loop];</p><p>+<span style="white-space:pre">               </span>}</p><p>+</p><p>+<span style="white-space:pre">            </span>if (string[loop] == delim) {</p><p>+<span style="white-space:pre">                     </span>string[loop] = '\0';</p><p>+<span style="white-space:pre">                     </span>tokstart = 1;</p><p>+<span style="white-space:pre">            </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return tok;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_devfs_parse(const char *filename, unsigned long *val)</p><p>+{</p><p>+<span style="white-space:pre">       </span>FILE *f = NULL;</p><p>+<span style="white-space:pre">  </span>char *end = NULL;</p><p>+<span style="white-space:pre">        </span>char buf[STR_BUFF_LEN] = {0};</p><p>+</p><p>+<span style="white-space:pre">        </span>f = fopen(filename, "r");</p><p>+<span style="white-space:pre">      </span>if (f == NULL) {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "Cannot open sysfs %s", filename);</p><p>+<span style="white-space:pre">           </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (fgets(buf, sizeof(buf), f) == NULL) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "Cannot read sysfs value %s", filename);</p><p>+<span style="white-space:pre">             </span>fclose(f);</p><p>+<span style="white-space:pre">               </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>*val = strtoul(buf, &end, 0);</p><p>+<span style="white-space:pre">        </span>if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Cannot parse sysfs value %s", filename);</p><p>+<span style="white-space:pre">            </span>fclose(f);</p><p>+<span style="white-space:pre">               </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>fclose(f);</p><p>+<span style="white-space:pre">       </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_resfs_parse(const char *filename, struct zxdh_pci_dev *dev)</p><p>+{</p><p>+<span style="white-space:pre">   </span>FILE *fp = NULL;</p><p>+<span style="white-space:pre"> </span>char buf[STR_BUFF_LEN] = {0};</p><p>+<span style="white-space:pre">    </span>uint8_t  loop = 0;</p><p>+<span style="white-space:pre">  </span>uint64_t phys_addr = 0;</p><p>+<span style="white-space:pre">  </span>uint64_t end_addr = 0;</p><p>+<span style="white-space:pre">   </span>uint64_t flags = 0;</p><p>+<span style="white-space:pre">      </span>int ret = 0;</p><p>+<span style="white-space:pre">     </span>union pci_resource_info {</p><p>+<span style="white-space:pre">                </span>struct {</p><p>+<span style="white-space:pre">                 </span>char *phys_addr;</p><p>+<span style="white-space:pre">                 </span>char *end_addr;</p><p>+<span style="white-space:pre">                  </span>char *flags;</p><p>+<span style="white-space:pre">             </span>};</p><p>+<span style="white-space:pre">               </span>char *ptrs[PCI_RESOURCE_FMT_NVAL];</p><p>+<span style="white-space:pre">       </span>} res_info;</p><p>+</p><p>+<span style="white-space:pre">  </span>fp = fopen(filename, "r");</p><p>+<span style="white-space:pre">     </span>if (fp == NULL) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "Failed to open file %s", filename);</p><p>+<span style="white-space:pre">         </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>for (loop = 0; loop < PCI_MAX_RESOURCE; loop++) {</p><p>+<span style="white-space:pre">             </span>if (fgets(buf, sizeof(buf), fp) == NULL) {</p><p>+<span style="white-space:pre">                       </span>ZXDH_PMD_LOG(ERR, "Failed to gets file %s", filename);</p><p>+<span style="white-space:pre">                 </span>goto err_exit;</p><p>+<span style="white-space:pre">           </span>}</p><p>+</p><p>+<span style="white-space:pre">            </span>ret = zxdh_gdma_str_split(buf, sizeof(buf), res_info.ptrs,</p><p>+<span style="white-space:pre">                                                                       </span>PCI_RESOURCE_FMT_NVAL, ' ');</p><p>+<span style="white-space:pre">             </span>if (ret != PCI_RESOURCE_FMT_NVAL) {</p><p>+<span style="white-space:pre">                      </span>ZXDH_PMD_LOG(ERR, "file %s:zxdh_gdma_str_split failed!", filename);</p><p>+<span style="white-space:pre">                    </span>goto err_exit;</p><p>+<span style="white-space:pre">           </span>}</p><p>+<span style="white-space:pre">                </span>errno = 0;</p><p>+<span style="white-space:pre">               </span>phys_addr = strtoull(res_info.phys_addr, NULL, 16);</p><p>+<span style="white-space:pre">              </span>end_addr  = strtoull(res_info.end_addr, NULL, 16);</p><p>+<span style="white-space:pre">          </span>flags     = strtoull(res_info.flags, NULL, 16);</p><p>+</p><p>+<span style="white-space:pre">               </span>if (errno != 0) {</p><p>+<span style="white-space:pre">                        </span>ZXDH_PMD_LOG(ERR, "file %s:bad resource format!", filename);</p><p>+<span style="white-space:pre">                   </span>goto err_exit;</p><p>+<span style="white-space:pre">           </span>}</p><p>+</p><p>+<span style="white-space:pre">            </span>if (flags & IORESOURCE_MEM) {</p><p>+<span style="white-space:pre">                        </span>if (loop == BAR0_IDX) {</p><p>+<span style="white-space:pre">                          </span>dev->bar_pa[BAR0_IDX] = phys_addr;</p><p>+<span style="white-space:pre">                            </span>dev->bar_len[BAR0_IDX] = end_addr - phys_addr + 1;</p><p>+<span style="white-space:pre">                    </span>}</p><p>+</p><p>+<span style="white-space:pre">                    </span>if (loop == BAR2_IDX) {</p><p>+<span style="white-space:pre">                          </span>dev->bar_pa[BAR2_IDX] = phys_addr;</p><p>+<span style="white-space:pre">                            </span>dev->bar_len[BAR2_IDX] = end_addr - phys_addr + 1;</p><p>+<span style="white-space:pre">                            </span>fclose(fp);</p><p>+<span style="white-space:pre">                              </span>return 0;</p><p>+<span style="white-space:pre">                        </span>}</p><p>+<span style="white-space:pre">                </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(ERR, "file %s: Not found IO resource memory!", filename);</p><p>+</p><p>+err_exit:</p><p>+<span style="white-space:pre">        </span>fclose(fp);</p><p>+<span style="white-space:pre">      </span>return -1;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_pci_addr_parse(const char *buf, int buf_size, struct zxdh_pci_dev *dev)</p><p>+{</p><p>+<span style="white-space:pre">      </span>char *buf_copy = NULL;</p><p>+<span style="white-space:pre">   </span>int ret = 0;</p><p>+<span style="white-space:pre">     </span>union splitaddr {</p><p>+<span style="white-space:pre">                </span>struct {</p><p>+<span style="white-space:pre">                 </span>char *domain;</p><p>+<span style="white-space:pre">                    </span>char *bus;</p><p>+<span style="white-space:pre">                       </span>char *devid;</p><p>+<span style="white-space:pre">                     </span>char *function;</p><p>+<span style="white-space:pre">          </span>};</p><p>+<span style="white-space:pre">               </span>char *str[PCI_FMT_NVAL];</p><p>+<span style="white-space:pre"> </span>} splitaddr;</p><p>+</p><p>+<span style="white-space:pre"> </span>buf_copy = strndup(buf, buf_size);</p><p>+<span style="white-space:pre">       </span>if (buf_copy == NULL) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "buf %s: strndup failed!", buf);</p><p>+<span style="white-space:pre">             </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>/* first split on ':' */</p><p>+<span style="white-space:pre"> </span>ret = zxdh_gdma_str_split(buf_copy, buf_size, splitaddr.str, PCI_FMT_NVAL, ':');</p><p>+<span style="white-space:pre"> </span>if (ret != (PCI_FMT_NVAL - 1)) {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "buf %s: zxdh_gdma_str_split failed!", buf);</p><p>+<span style="white-space:pre">         </span>goto err_exit;</p><p>+<span style="white-space:pre">   </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>/* final split is on '.' between devid and function */</p><p>+<span style="white-space:pre">   </span>splitaddr.function = strchr(splitaddr.devid, '.');</p><p>+<span style="white-space:pre">       </span>if (splitaddr.function == NULL) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "buf %s: strchr failed!", buf);</p><p>+<span style="white-space:pre">              </span>goto err_exit;</p><p>+<span style="white-space:pre">   </span>}</p><p>+<span style="white-space:pre">        </span>*splitaddr.function++ = '\0';</p><p>+</p><p>+<span style="white-space:pre">        </span>/* now convert to int values */</p><p>+<span style="white-space:pre">  </span>errno = 0;</p><p>+<span style="white-space:pre">       </span>dev->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);</p><p>+<span style="white-space:pre">  </span>dev->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);</p><p>+<span style="white-space:pre"> </span>dev->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);</p><p>+<span style="white-space:pre">     </span>dev->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);</p><p>+<span style="white-space:pre">       </span>if (errno != 0) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(ERR, "buf %s: bad format!", buf);</p><p>+<span style="white-space:pre">         </span>goto err_exit;</p><p>+<span style="white-space:pre">   </span>}</p><p>+<span style="white-space:pre">        </span>free(buf_copy);</p><p>+<span style="white-space:pre">  </span>return 0;</p><p>+</p><p>+err_exit:</p><p>+<span style="white-space:pre">       </span>free(buf_copy);</p><p>+<span style="white-space:pre">  </span>return -1;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_pci_dev_mmap(const char *filename, struct zxdh_pci_dev *dev, uint8_t bar_idx)</p><p>+{</p><p>+<span style="white-space:pre">        </span>int fd = -1;</p><p>+</p><p>+<span style="white-space:pre"> </span>if (dev->bar_va[bar_idx] == NULL) {</p><p>+<span style="white-space:pre">           </span>fd = open(filename, O_RDWR);</p><p>+<span style="white-space:pre">             </span>if (fd < 0) {</p><p>+<span style="white-space:pre">                 </span>ZXDH_PMD_LOG(ERR, "Failed to open file %s", filename);</p><p>+<span style="white-space:pre">                 </span>return -1;</p><p>+<span style="white-space:pre">               </span>}</p><p>+</p><p>+<span style="white-space:pre">            </span>dev->bar_va[bar_idx] = mmap((void *)dev->bar_pa[bar_idx],</p><p>+<span style="white-space:pre">                                                                  </span>dev->bar_len[bar_idx],</p><p>+<span style="white-space:pre">                                                                        </span>PROT_READ | PROT_WRITE,</p><p>+<span style="white-space:pre">                                                                  </span>MAP_SHARED, fd, 0);</p><p>+</p><p>+<span style="white-space:pre">          </span>if (dev->bar_va[bar_idx] == MAP_FAILED) {</p><p>+<span style="white-space:pre">                     </span>ZXDH_PMD_LOG(ERR, "Failed to mmap file %s!", filename);</p><p>+<span style="white-space:pre">                        </span>goto err_exit;</p><p>+<span style="white-space:pre">           </span>}</p><p>+<span style="white-space:pre">                </span>close(fd);</p><p>+<span style="white-space:pre">       </span>} else</p><p>+<span style="white-space:pre">           </span>ZXDH_PMD_LOG(ERR, "BarVirtAddr is not NULL!");</p><p>+</p><p>+<span style="white-space:pre">     </span>return 0;</p><p>+</p><p>+err_exit:</p><p>+<span style="white-space:pre">       </span>close(fd);</p><p>+<span style="white-space:pre">       </span>return -1;</p><p>+}</p><p>+</p><p>+void</p><p>+zxdh_gdma_pci_dev_munmap(void)</p><p>+{</p><p>+<span style="white-space:pre">       </span>if (gdev.bar_va[BAR0_IDX] != NULL) {</p><p>+<span style="white-space:pre">             </span>munmap(gdev.bar_va[BAR0_IDX], gdev.bar_len[BAR0_IDX]);</p><p>+<span style="white-space:pre">           </span>gdev.bar_va[BAR0_IDX] = NULL;</p><p>+<span style="white-space:pre">    </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (gdev.bar_va[BAR2_IDX] != NULL) {</p><p>+<span style="white-space:pre">             </span>munmap(gdev.bar_va[BAR2_IDX], gdev.bar_len[BAR2_IDX]);</p><p>+<span style="white-space:pre">           </span>gdev.bar_va[BAR2_IDX] = NULL;</p><p>+<span style="white-space:pre">    </span>}</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_pci_mse_en(struct zxdh_pci_dev *dev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>int ret = 0;</p><p>+<span style="white-space:pre">     </span>uint RegVal = 0;</p><p>+</p><p>+<span style="white-space:pre">     </span>ret = zxdh_gdma_cfg_space_read(dev, PARA_PCI_CMD, &RegVal);</p><p>+<span style="white-space:pre">  </span>if (ret != 0) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "Failed to read %04x:%02x:%02x.%01x pci config space!",</p><p>+<span style="white-space:pre">                                              </span>dev->domain, dev->bus, dev->devid, dev->function);</p><p>+<span style="white-space:pre">           </span>return ret;</p><p>+<span style="white-space:pre">      </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if ((RegVal & (1 << PCI_CMD_MSE_BIT)) == 0) {</p><p>+<span style="white-space:pre">          </span>RegVal = RegVal | (1 << PCI_CMD_MSE_BIT);</p><p>+</p><p>+<span style="white-space:pre">              </span>ret = zxdh_gdma_cfg_space_write(dev, PARA_PCI_CMD, &RegVal);</p><p>+<span style="white-space:pre">         </span>if (ret != 0) {</p><p>+<span style="white-space:pre">                  </span>ZXDH_PMD_LOG(ERR, "Failed to write %04x:%02x:%02x.%01x pci config space!",</p><p>+<span style="white-space:pre">                                                     </span>dev->domain, dev->bus,</p><p>+<span style="white-space:pre">                                                     </span>dev->devid, dev->function);</p><p>+<span style="white-space:pre">                        </span>return ret;</p><p>+<span style="white-space:pre">              </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return ret;</p><p>+}</p><p>+</p><p>+int</p><p>+zxdh_gdma_pci_scan(void)</p><p>+{</p><p>+<span style="white-space:pre">     </span>struct dirent *e = NULL;</p><p>+<span style="white-space:pre"> </span>DIR *dir = NULL;</p><p>+<span style="white-space:pre"> </span>char dirname[FILE_PATH_LEN] = {0};</p><p>+<span style="white-space:pre">       </span>char filename[FILE_PATH_LEN] = {0};</p><p>+<span style="white-space:pre">      </span>uint16_t vendor_id = 0;</p><p>+<span style="white-space:pre">  </span>uint16_t device_id = 0;</p><p>+<span style="white-space:pre">  </span>unsigned long tmp = 0;</p><p>+<span style="white-space:pre">   </span>bool found = false;</p><p>+<span style="white-space:pre">      </span>int ret = 0;</p><p>+</p><p>+<span style="white-space:pre"> </span>dir = opendir(PCI_DEVICES_DIR);</p><p>+<span style="white-space:pre">  </span>if (dir == NULL) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Failed to opendir %s", PCI_DEVICES_DIR);</p><p>+<span style="white-space:pre">            </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>while ((e = readdir(dir)) != NULL) {</p><p>+<span style="white-space:pre">             </span>if (e->d_name[0] == '.')</p><p>+<span style="white-space:pre">                      </span>continue;</p><p>+</p><p>+<span style="white-space:pre">            </span>memset(dirname, 0, FILE_PATH_LEN);</p><p>+<span style="white-space:pre">               </span>snprintf(dirname, FILE_PATH_LEN, "%s/%s", PCI_DEVICES_DIR, e->d_name);</p><p>+</p><p>+<span style="white-space:pre">          </span>snprintf(filename, sizeof(filename), "%s/vendor", dirname);</p><p>+<span style="white-space:pre">            </span>ret = zxdh_gdma_devfs_parse(filename, &tmp);</p><p>+<span style="white-space:pre">         </span>if (ret != 0)</p><p>+<span style="white-space:pre">                    </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">            </span>vendor_id = (uint16_t)tmp;</p><p>+</p><p>+<span style="white-space:pre">           </span>snprintf(filename, sizeof(filename), "%s/device", dirname);</p><p>+<span style="white-space:pre">            </span>ret = zxdh_gdma_devfs_parse(filename, &tmp);</p><p>+<span style="white-space:pre">         </span>if (ret != 0)</p><p>+<span style="white-space:pre">                    </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">            </span>device_id = (uint16_t)tmp;</p><p>+</p><p>+<span style="white-space:pre">           </span>if ((vendor_id == ZXDH_GDMA_VENDORID) && (device_id == ZXDH_GDMA_DEVICEID)) {</p><p>+<span style="white-space:pre">                    </span>found = true;</p><p>+<span style="white-space:pre">                    </span>break;</p><p>+<span style="white-space:pre">           </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (found != true) {</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(ERR, "Failed to found gdma pci dev");</p><p>+<span style="white-space:pre">             </span>ret = -1;</p><p>+<span style="white-space:pre">                </span>goto out;</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>gdev.vendor_id = vendor_id;</p><p>+<span style="white-space:pre">      </span>gdev.device_id = device_id;</p><p>+<span style="white-space:pre">      </span>memcpy(gdev.d_name, e->d_name, PCI_BUFF_LEN);</p><p>+<span style="white-space:pre"> </span>memcpy(gdev.dirname, dirname, FILE_PATH_LEN);</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(INFO, "Found gdma pci dev %s", e->d_name);</p><p>+</p><p>+<span style="white-space:pre"> </span>/* Parse pci addr */</p><p>+<span style="white-space:pre">     </span>ret = zxdh_gdma_pci_addr_parse(e->d_name, sizeof(e->d_name), &gdev);</p><p>+<span style="white-space:pre">   </span>if (ret != 0)</p><p>+<span style="white-space:pre">            </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">    </span>/* Enable MSE */</p><p>+<span style="white-space:pre"> </span>ret = zxdh_gdma_pci_mse_en(&gdev);</p><p>+<span style="white-space:pre">   </span>if (ret != 0)</p><p>+<span style="white-space:pre">            </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">    </span>/* Get bar0 phyaddr and len */</p><p>+<span style="white-space:pre">   </span>snprintf(filename, sizeof(filename), "%s/resource", dirname);</p><p>+<span style="white-space:pre">  </span>ret = zxdh_gdma_resfs_parse(filename, &gdev);</p><p>+<span style="white-space:pre">        </span>if (ret != 0)</p><p>+<span style="white-space:pre">            </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">    </span>/* Mmap bar0 virtaddr */</p><p>+<span style="white-space:pre"> </span>snprintf(filename, sizeof(filename), "%s/resource0", dirname);</p><p>+<span style="white-space:pre"> </span>ret = zxdh_gdma_pci_dev_mmap(filename, &gdev, BAR0_IDX);</p><p>+<span style="white-space:pre">     </span>if (ret != 0)</p><p>+<span style="white-space:pre">            </span>goto out;</p><p>+</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(INFO, "Found pci_scan success");</p><p>+</p><p>+out:</p><p>+<span style="white-space:pre">      </span>closedir(dir);</p><p>+<span style="white-space:pre">   </span>return ret;</p><p>+}</p><p>diff --git a/drivers/raw/zxdh/zxdh_pci.h b/drivers/raw/zxdh/zxdh_pci.h</p><p>new file mode 100644</p><p>index 0000000000..93c6c97405</p><p>--- /dev/null</p><p>+++ b/drivers/raw/zxdh/zxdh_pci.h</p><p>@@ -0,0 +1,40 @@</p><p>+/* SPDX-License-Identifier: BSD-3-Clause</p><p>+ * Copyright 2024 ZTE Corporation</p><p>+ */</p><p>+</p><p>+#ifndef __ZXDH_PCI_H__</p><p>+#define __ZXDH_PCI_H__</p><p>+</p><p>+#ifdef __cplusplus</p><p>+extern "C" {</p><p>+#endif</p><p>+</p><p>+#define FILE_PATH_LEN                       (100)</p><p>+#define PCI_BUFF_LEN                        (16)</p><p>+#define PCI_MAX_RESOURCE                    (6)</p><p>+</p><p>+struct zxdh_pci_dev {</p><p>+<span style="white-space:pre">      </span>uint16_t    vendor_id;</p><p>+<span style="white-space:pre"> </span>uint16_t    device_id;</p><p>+<span style="white-space:pre"> </span>uint16_t    domain;</p><p>+<span style="white-space:pre">    </span>uint8_t     bus;</p><p>+<span style="white-space:pre">  </span>uint8_t     devid;</p><p>+<span style="white-space:pre">        </span>uint8_t     function;</p><p>+<span style="white-space:pre">     </span>char        dirname[FILE_PATH_LEN];</p><p>+<span style="white-space:pre">  </span>char        d_name[PCI_BUFF_LEN];</p><p>+<span style="white-space:pre">    </span>void       *bar_va[PCI_MAX_RESOURCE];</p><p>+<span style="white-space:pre">        </span>uint64_t    bar_pa[PCI_MAX_RESOURCE];</p><p>+<span style="white-space:pre">  </span>uint64_t    bar_len[PCI_MAX_RESOURCE];</p><p>+};</p><p>+</p><p>+extern struct zxdh_pci_dev gdev;</p><p>+</p><p>+void zxdh_gdma_pci_dev_munmap(void);</p><p>+int zxdh_gdma_pci_scan(void);</p><p>+</p><p>+#ifdef __cplusplus</p><p>+}</p><p>+#endif</p><p>+</p><p>+#endif /* __ZXDH_PCI_H__ */</p><p>+</p><p>diff --git a/drivers/raw/zxdh/zxdh_rawdev.c b/drivers/raw/zxdh/zxdh_rawdev.c</p><p>new file mode 100644</p><p>index 0000000000..32017f8744</p><p>--- /dev/null</p><p>+++ b/drivers/raw/zxdh/zxdh_rawdev.c</p><p>@@ -0,0 +1,911 @@</p><p>+/* SPDX-License-Identifier: BSD-3-Clause</p><p>+ * Copyright 2024 ZTE Corporation</p><p>+ */</p><p>+</p><p>+#include <assert.h></p><p>+#include <stdio.h></p><p>+#include <stdbool.h></p><p>+#include <errno.h></p><p>+#include <stdint.h></p><p>+#include <inttypes.h></p><p>+#include <string.h></p><p>+#include <time.h></p><p>+#include <sys/types.h></p><p>+</p><p>+#include <rte_byteorder.h></p><p>+#include <rte_version.h></p><p>+#include <rte_errno.h></p><p>+#include <rte_common.h></p><p>+#include <rte_debug.h></p><p>+#include <rte_dev.h></p><p>+#include <rte_eal.h></p><p>+#include <rte_kvargs.h></p><p>+#include <rte_log.h></p><p>+#include <rte_malloc.h></p><p>+#include <rte_memory.h></p><p>+#include <rte_memcpy.h></p><p>+#include <rte_lcore.h></p><p>+#include <rte_cycles.h></p><p>+#include <rte_memzone.h></p><p>+#include <rte_atomic.h></p><p>+#include <rte_rawdev.h></p><p>+#include <rte_rawdev_pmd.h></p><p>+</p><p>+#if RTE_VERSION_NUM(22, 11, 0, 0) <= RTE_VERSION</p><p>+#include <bus_vdev_driver.h></p><p>+#else</p><p>+#include <rte_bus_vdev.h></p><p>+#endif</p><p>+</p><p>+#include "zxdh_rawdev.h"</p><p>+#include "zxdh_pci.h"</p><p>+</p><p>+/*</p><p>+ * User define:</p><p>+ * ep_id-bit[15:12] vfunc_num-bit[11:4] func_num-bit[3:1] vfunc_active-bit0</p><p>+ * host ep_id:5~8   zf ep_id:9</p><p>+ */</p><p>+#define ZXDH_GDMA_ZF_USER                       0x9000      /* ep4 pf0 */</p><p>+#define ZXDH_GDMA_PF_NUM_SHIFT                  1</p><p>+#define ZXDH_GDMA_VF_NUM_SHIFT                  4</p><p>+#define ZXDH_GDMA_EP_ID_SHIFT                   12</p><p>+#define ZXDH_GDMA_VF_EN                         1</p><p>+#define ZXDH_GDMA_EPID_OFFSET                   5</p><p>+</p><p>+/* Register offset */</p><p>+#define ZXDH_GDMA_BASE_OFFSET                   0x100000</p><p>+#define ZXDH_GDMA_EXT_ADDR_OFFSET               0x218</p><p>+#define ZXDH_GDMA_SAR_LOW_OFFSET                0x200</p><p>+#define ZXDH_GDMA_DAR_LOW_OFFSET                0x204</p><p>+#define ZXDH_GDMA_SAR_HIGH_OFFSET               0x234</p><p>+#define ZXDH_GDMA_DAR_HIGH_OFFSET               0x238</p><p>+#define ZXDH_GDMA_XFERSIZE_OFFSET               0x208</p><p>+#define ZXDH_GDMA_CONTROL_OFFSET                0x230</p><p>+#define ZXDH_GDMA_TC_STATUS_OFFSET              0x0</p><p>+#define ZXDH_GDMA_STATUS_CLEAN_OFFSET           0x80</p><p>+#define ZXDH_GDMA_LLI_L_OFFSET                  0x21c</p><p>+#define ZXDH_GDMA_LLI_H_OFFSET                  0x220</p><p>+#define ZXDH_GDMA_CHAN_CONTINUE_OFFSET          0x224</p><p>+#define ZXDH_GDMA_TC_CNT_OFFSET                 0x23c</p><p>+#define ZXDH_GDMA_LLI_USER_OFFSET               0x228</p><p>+</p><p>+/* Control register */</p><p>+#define ZXDH_GDMA_CHAN_ENABLE                   0x1</p><p>+#define ZXDH_GDMA_CHAN_DISABLE                  0</p><p>+#define ZXDH_GDMA_SOFT_CHAN                     0x2</p><p>+#define ZXDH_GDMA_TC_INTR_ENABLE                0x10</p><p>+#define ZXDH_GDMA_ALL_INTR_ENABLE               0x30</p><p>+#define ZXDH_GDMA_SBS_SHIFT                     6           /* src burst size */</p><p>+#define ZXDH_GDMA_SBL_SHIFT                     9           /* src burst length */</p><p>+#define ZXDH_GDMA_DBS_SHIFT                     13          /* dest burst size */</p><p>+#define ZXDH_GDMA_BURST_SIZE_MIN                0x1         /* 1 byte */</p><p>+#define ZXDH_GDMA_BURST_SIZE_MEDIUM             0x4         /* 4 word */</p><p>+#define ZXDH_GDMA_BURST_SIZE_MAX                0x6         /* 16 word */</p><p>+#define ZXDH_GDMA_DEFAULT_BURST_LEN             0xf         /* 16 beats */</p><p>+#define ZXDH_GDMA_TC_CNT_ENABLE                 (1 << 27)</p><p>+#define ZXDH_GDMA_CHAN_FORCE_CLOSE              (1 << 31)</p><p>+</p><p>+/* TC count & Error interrupt status register */</p><p>+#define ZXDH_GDMA_SRC_LLI_ERR                   (1 << 16)</p><p>+#define ZXDH_GDMA_SRC_DATA_ERR                  (1 << 17)</p><p>+#define ZXDH_GDMA_DST_ADDR_ERR                  (1 << 18)</p><p>+#define ZXDH_GDMA_ERR_STATUS                    (1 << 19)</p><p>+#define ZXDH_GDMA_ERR_INTR_ENABLE               (1 << 20)</p><p>+#define ZXDH_GDMA_TC_CNT_CLEAN                  (1)</p><p>+</p><p>+#define ZXDH_GDMA_CHAN_SHIFT                    0x80</p><p>+#define ZXDH_GDMA_LINK_END_NODE                 (1 << 30)</p><p>+#define ZXDH_GDMA_CHAN_CONTINUE                 (1)</p><p>+</p><p>+#define LOW32_MASK                              0xffffffff</p><p>+#define LOW16_MASK                              0xffff</p><p>+</p><p>+#define ZXDH_GDMA_WAIT_TIMES_MAX                100</p><p>+#define ZXDH_GDMA_TC_CNT_MAX                    0x10000</p><p>+</p><p>+#define IDX_TO_ADDR(addr, idx, t) \</p><p>+<span style="white-space:pre">      </span>((t)((uint8_t *)(addr) + (idx) * sizeof(struct zxdh_gdma_buff_desc)))</p><p>+</p><p>+static int zxdh_gdma_queue_init(struct rte_rawdev *dev, uint16_t queue_id);</p><p>+static int zxdh_gdma_queue_free(struct rte_rawdev *dev, uint16_t queue_id);</p><p>+</p><p>+char zxdh_gdma_driver_name[] = "rawdev_zxdh_gdma";</p><p>+char dev_name[] = "zxdh_gdma";</p><p>+</p><p>+static inline struct zxdh_gdma_queue *</p><p>+zxdh_gdma_get_queue(struct rte_rawdev *dev, uint16_t queue_id)</p><p>+{</p><p>+<span style="white-space:pre">     </span>struct zxdh_gdma_rawdev *gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+</p><p>+<span style="white-space:pre">   </span>if (queue_id >= ZXDH_GDMA_TOTAL_CHAN_NUM) {</p><p>+<span style="white-space:pre">           </span>ZXDH_PMD_LOG(ERR, "queue id %d is invalid", queue_id);</p><p>+<span style="white-space:pre">         </span>return NULL;</p><p>+<span style="white-space:pre">     </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return &(gdmadev->vqs[queue_id]);</p><p>+}</p><p>+</p><p>+uint</p><p>+zxdh_gdma_read_reg(struct rte_rawdev *dev, uint16_t queue_id, uint offset)</p><p>+{</p><p>+<span style="white-space:pre">     </span>struct zxdh_gdma_rawdev *gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">       </span>uint addr = 0;</p><p>+<span style="white-space:pre">   </span>uint val = 0;</p><p>+</p><p>+<span style="white-space:pre">        </span>addr = offset + queue_id * ZXDH_GDMA_CHAN_SHIFT;</p><p>+<span style="white-space:pre"> </span>val = *(uint *)(gdmadev->base_addr + addr);</p><p>+</p><p>+<span style="white-space:pre">       </span>return val;</p><p>+}</p><p>+</p><p>+void</p><p>+zxdh_gdma_write_reg(struct rte_rawdev *dev, uint16_t queue_id, uint offset, uint val)</p><p>+{</p><p>+<span style="white-space:pre">       </span>struct zxdh_gdma_rawdev *gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">       </span>uint addr = 0;</p><p>+</p><p>+<span style="white-space:pre">       </span>addr = offset + queue_id * ZXDH_GDMA_CHAN_SHIFT;</p><p>+<span style="white-space:pre"> </span>*(uint *)(gdmadev->base_addr + addr) = val;</p><p>+}</p><p>+</p><p>+int</p><p>+zxdh_gdma_debug_info_dump(struct rte_rawdev *dev, uint16_t queue_id)</p><p>+{</p><p>+<span style="white-space:pre">      </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>struct zxdh_gdma_buff_desc *bd = NULL;</p><p>+<span style="white-space:pre">   </span>struct zxdh_gdma_job *job = NULL;</p><p>+<span style="white-space:pre">        </span>uint16_t i = 0;</p><p>+</p><p>+<span style="white-space:pre">      </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if (queue == NULL)</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>ZXDH_PMD_LOG(INFO, "###dump sw_ring info###");</p><p>+<span style="white-space:pre"> </span>ZXDH_PMD_LOG(INFO, "free_cnt:%u deq_cnt:%u",</p><p>+<span style="white-space:pre">                                           </span>queue->sw_ring.free_cnt, queue->sw_ring.deq_cnt);</p><p>+<span style="white-space:pre">  </span>ZXDH_PMD_LOG(INFO, "enq_idx:%u deq_idx:%u used_idx:%u",</p><p>+<span style="white-space:pre">                                                </span>queue->sw_ring.enq_idx, queue->sw_ring.deq_idx,</p><p>+<span style="white-space:pre">                                            </span>queue->sw_ring.used_idx);</p><p>+<span style="white-space:pre">     </span>for (i = 0; i < ZXDH_GDMA_QUEUE_SIZE; i++) {</p><p>+<span style="white-space:pre">          </span>if (queue->sw_ring.job[i] != NULL) {</p><p>+<span style="white-space:pre">                  </span>job = queue->sw_ring.job[i];</p><p>+<span style="white-space:pre">                  </span>ZXDH_PMD_LOG(INFO, "idx:%d, SrcAddr:0x%"PRIx64" DstAddr:0x%"PRIx64" len:%u",</p><p>+<span style="white-space:pre">                                                               </span>i, job->src, job->dest, job->len);</p><p>+<span style="white-space:pre">              </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(INFO, "###dump ring info###");</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(INFO, "avail_idx:%u tc_cnt:%u", queue->ring.avail_idx, queue->tc_cnt);</p><p>+<span style="white-space:pre">      </span>for (i = 0; i < ZXDH_GDMA_RING_SIZE; i++) {</p><p>+<span style="white-space:pre">           </span>bd = IDX_TO_ADDR(queue->ring.desc, i, struct zxdh_gdma_buff_desc*);</p><p>+<span style="white-space:pre">           </span>ZXDH_PMD_LOG(INFO, "idx:%d Src:0x%"PRIx64" Dst:0x%"PRIx64" LLI_L:0x%x LLI_H:0x%x ctrl:0x%x user:0x%x",</p><p>+<span style="white-space:pre">                             </span>i, bd->SrcAddr_L | ((uint64_t)bd->SrcAddr_H << 32),</p><p>+<span style="white-space:pre">                          </span>bd->DstAddr_L | ((uint64_t)bd->DstAddr_H << 32),</p><p>+<span style="white-space:pre">                             </span>bd->LLI_Addr_L, bd->LLI_Addr_H, bd->Control, bd->ExtAddr);</p><p>+<span style="white-space:pre">   </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_info_get(struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                            </span>  __rte_unused rte_rawdev_obj_t dev_info,</p><p>+<span style="white-space:pre">                                           </span>  __rte_unused size_t dev_info_size)</p><p>+{</p><p>+<span style="white-space:pre">   </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_configure(const struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                             </span>   rte_rawdev_obj_t config,</p><p>+<span style="white-space:pre">                                            </span>   size_t config_size)</p><p>+{</p><p>+<span style="white-space:pre">    </span>struct zxdh_gdma_config *gdma_config = NULL;</p><p>+</p><p>+<span style="white-space:pre"> </span>if ((dev == NULL) ||</p><p>+<span style="white-space:pre">             </span>(config == NULL) ||</p><p>+<span style="white-space:pre">              </span>(config_size != sizeof(struct zxdh_gdma_config)))</p><p>+<span style="white-space:pre">                </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdma_config = (struct zxdh_gdma_config *)config;</p><p>+<span style="white-space:pre"> </span>if (gdma_config->max_vqs != ZXDH_GDMA_TOTAL_CHAN_NUM) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "gdma only support queue num %d", ZXDH_GDMA_TOTAL_CHAN_NUM);</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_start(struct rte_rawdev *dev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+</p><p>+<span style="white-space:pre">     </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>gdmadev->device_state = ZXDH_GDMA_DEV_RUNNING;</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static void</p><p>+zxdh_gdma_rawdev_stop(struct rte_rawdev *dev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+</p><p>+<span style="white-space:pre">     </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>gdmadev->device_state = ZXDH_GDMA_DEV_STOPPED;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_reset(struct rte_rawdev *dev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_close(struct rte_rawdev *dev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>uint16_t queue_id = 0;</p><p>+</p><p>+<span style="white-space:pre">       </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>for (queue_id = 0; queue_id < ZXDH_GDMA_TOTAL_CHAN_NUM; queue_id++) {</p><p>+<span style="white-space:pre">         </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">              </span>if ((queue == NULL) || (queue->enable == 0))</p><p>+<span style="white-space:pre">                  </span>continue;</p><p>+</p><p>+<span style="white-space:pre">            </span>zxdh_gdma_queue_free(dev, queue_id);</p><p>+<span style="white-space:pre">     </span>}</p><p>+<span style="white-space:pre">        </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>gdmadev->device_state = ZXDH_GDMA_DEV_STOPPED;</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_queue_setup(struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                                 </span> uint16_t queue_id,</p><p>+<span style="white-space:pre">                                                      </span> rte_rawdev_obj_t queue_conf,</p><p>+<span style="white-space:pre">                                                    </span> size_t conf_size)</p><p>+{</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>struct zxdh_gdma_queue_config *qconfig = NULL;</p><p>+<span style="white-space:pre">   </span>struct zxdh_gdma_rbp *rbp = NULL;</p><p>+<span style="white-space:pre">        </span>uint16_t i = 0;</p><p>+<span style="white-space:pre">  </span>uint8_t is_txq = 0;</p><p>+<span style="white-space:pre">      </span>uint src_user = 0;</p><p>+<span style="white-space:pre">       </span>uint dst_user = 0;</p><p>+</p><p>+<span style="white-space:pre">   </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>if ((queue_conf == NULL) || (conf_size != sizeof(struct zxdh_gdma_queue_config)))</p><p>+<span style="white-space:pre">                </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>qconfig = (struct zxdh_gdma_queue_config *)queue_conf;</p><p>+</p><p>+<span style="white-space:pre">       </span>for (i = 0; i < ZXDH_GDMA_TOTAL_CHAN_NUM; i++) {</p><p>+<span style="white-space:pre">              </span>if (gdmadev->vqs[i].enable == 0)</p><p>+<span style="white-space:pre">                      </span>break;</p><p>+<span style="white-space:pre">   </span>}</p><p>+<span style="white-space:pre">        </span>if (i >= ZXDH_GDMA_TOTAL_CHAN_NUM) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "Failed to setup queue, no avail queues");</p><p>+<span style="white-space:pre">           </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+<span style="white-space:pre">        </span>queue_id = i;</p><p>+<span style="white-space:pre">    </span>if (zxdh_gdma_queue_init(dev, queue_id) != 0) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "Failed to init queue");</p><p>+<span style="white-space:pre">             </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+<span style="white-space:pre">        </span>queue = &(gdmadev->vqs[queue_id]);</p><p>+</p><p>+<span style="white-space:pre">    </span>rbp = qconfig->rbp;</p><p>+<span style="white-space:pre">   </span>if ((rbp->srbp != 0) && (rbp->drbp == 0)) {</p><p>+<span style="white-space:pre">                </span>is_txq = 0;</p><p>+<span style="white-space:pre">              </span>dst_user = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">            </span>src_user = ((rbp->spfid << ZXDH_GDMA_PF_NUM_SHIFT) |</p><p>+<span style="white-space:pre">                    </span>((rbp->sportid + ZXDH_GDMA_EPID_OFFSET) << ZXDH_GDMA_EP_ID_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">         </span>if (rbp->svfid != 0)</p><p>+<span style="white-space:pre">                  </span>src_user |= (ZXDH_GDMA_VF_EN |</p><p>+<span style="white-space:pre">                                           </span> ((rbp->svfid - 1) << ZXDH_GDMA_VF_NUM_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(DEBUG, "rxq->qidx:%d setup src_user(ep:%d pf:%d vf:%d) success",</p><p>+<span style="white-space:pre">                                       </span>queue_id, (uint8_t)rbp->sportid, (uint8_t)rbp->spfid,</p><p>+<span style="white-space:pre">                                      </span>(uint8_t)rbp->svfid);</p><p>+<span style="white-space:pre"> </span>} else if ((rbp->srbp == 0) && (rbp->drbp != 0)) {</p><p>+<span style="white-space:pre">         </span>is_txq = 1;</p><p>+<span style="white-space:pre">              </span>src_user = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">            </span>dst_user = ((rbp->dpfid << ZXDH_GDMA_PF_NUM_SHIFT) |</p><p>+<span style="white-space:pre">                    </span>((rbp->dportid + ZXDH_GDMA_EPID_OFFSET) << ZXDH_GDMA_EP_ID_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">         </span>if (rbp->dvfid != 0)</p><p>+<span style="white-space:pre">                  </span>dst_user |= (ZXDH_GDMA_VF_EN |</p><p>+<span style="white-space:pre">                                           </span> ((rbp->dvfid - 1) << ZXDH_GDMA_VF_NUM_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(DEBUG, "txq->qidx:%d setup dst_user(ep:%d pf:%d vf:%d) success",</p><p>+<span style="white-space:pre">                                       </span>queue_id, (uint8_t)rbp->dportid, (uint8_t)rbp->dpfid,</p><p>+<span style="white-space:pre">                                      </span>(uint8_t)rbp->dvfid);</p><p>+<span style="white-space:pre"> </span>} else {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "Failed to setup queue, srbp/drbp is invalid");</p><p>+<span style="white-space:pre">              </span>return -EINVAL;</p><p>+<span style="white-space:pre">  </span>}</p><p>+<span style="white-space:pre">        </span>queue->is_txq = is_txq;</p><p>+</p><p>+<span style="white-space:pre">   </span>/* setup queue user info */</p><p>+<span style="white-space:pre">      </span>queue->user = (src_user & LOW16_MASK) | (dst_user << 16);</p><p>+</p><p>+<span style="white-space:pre">       </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_EXT_ADDR_OFFSET, queue->user);</p><p>+<span style="white-space:pre">   </span>gdmadev->used_num++;</p><p>+</p><p>+<span style="white-space:pre">      </span>return queue_id;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_queue_release(struct rte_rawdev *dev, uint16_t queue_id)</p><p>+{</p><p>+<span style="white-space:pre">        </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+</p><p>+<span style="white-space:pre">        </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if ((queue == NULL) || (queue->enable == 0))</p><p>+<span style="white-space:pre">          </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>zxdh_gdma_queue_free(dev, queue_id);</p><p>+</p><p>+<span style="white-space:pre"> </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_get_attr(struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                            </span>  __rte_unused const char *attr_name,</p><p>+<span style="white-space:pre">                                               </span>  uint64_t *attr_value)</p><p>+{</p><p>+<span style="white-space:pre">        </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_attr *gdma_attr = NULL;</p><p>+</p><p>+<span style="white-space:pre">     </span>if ((dev == NULL) || (attr_value == NULL))</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev   = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">    </span>gdma_attr = (struct zxdh_gdma_attr *)attr_value;</p><p>+<span style="white-space:pre"> </span>gdma_attr->num_hw_queues = gdmadev->used_num;</p><p>+</p><p>+<span style="white-space:pre">  </span>return 0;</p><p>+}</p><p>+</p><p>+static inline void</p><p>+zxdh_gdma_control_cal(uint *val, uint8_t tc_enable)</p><p>+{</p><p>+<span style="white-space:pre">     </span>*val = (ZXDH_GDMA_CHAN_ENABLE |</p><p>+<span style="white-space:pre">                  </span>ZXDH_GDMA_SOFT_CHAN |</p><p>+<span style="white-space:pre">                    </span>(ZXDH_GDMA_DEFAULT_BURST_LEN << ZXDH_GDMA_SBL_SHIFT) |</p><p>+<span style="white-space:pre">                     </span>(ZXDH_GDMA_BURST_SIZE_MAX << ZXDH_GDMA_SBS_SHIFT) |</p><p>+<span style="white-space:pre">                        </span>(ZXDH_GDMA_BURST_SIZE_MAX << ZXDH_GDMA_DBS_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">    </span>if (tc_enable != 0)</p><p>+<span style="white-space:pre">              </span>*val |= ZXDH_GDMA_TC_CNT_ENABLE;</p><p>+}</p><p>+</p><p>+static inline uint</p><p>+zxdh_gdma_user_get(struct zxdh_gdma_queue *queue, struct zxdh_gdma_job *job)</p><p>+{</p><p>+<span style="white-space:pre">     </span>uint src_user = 0;</p><p>+<span style="white-space:pre">       </span>uint dst_user = 0;</p><p>+</p><p>+<span style="white-space:pre">   </span>if ((job->flags & ZXDH_GDMA_JOB_DIR_MASK) == 0) {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(DEBUG, "job flags:0x%x default user:0x%x\n",</p><p>+<span style="white-space:pre">                                                      </span>job->flags, queue->user);</p><p>+<span style="white-space:pre">          </span>return queue->user;</p><p>+<span style="white-space:pre">   </span>} else if ((job->flags & ZXDH_GDMA_JOB_DIR_TX) != 0) {</p><p>+<span style="white-space:pre">            </span>src_user = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">            </span>dst_user = ((job->pf_id << ZXDH_GDMA_PF_NUM_SHIFT) |</p><p>+<span style="white-space:pre">                    </span>((job->ep_id + ZXDH_GDMA_EPID_OFFSET) << ZXDH_GDMA_EP_ID_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">           </span>if (job->vf_id != 0)</p><p>+<span style="white-space:pre">                  </span>dst_user |= (ZXDH_GDMA_VF_EN |</p><p>+<span style="white-space:pre">                                           </span> ((job->vf_id - 1) << ZXDH_GDMA_VF_NUM_SHIFT));</p><p>+<span style="white-space:pre"> </span>} else {</p><p>+<span style="white-space:pre">         </span>dst_user = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">            </span>src_user = ((job->pf_id << ZXDH_GDMA_PF_NUM_SHIFT) |</p><p>+<span style="white-space:pre">                    </span>((job->ep_id + ZXDH_GDMA_EPID_OFFSET) << ZXDH_GDMA_EP_ID_SHIFT));</p><p>+</p><p>+<span style="white-space:pre">           </span>if (job->vf_id != 0)</p><p>+<span style="white-space:pre">                  </span>src_user |= (ZXDH_GDMA_VF_EN |</p><p>+<span style="white-space:pre">                                           </span> ((job->vf_id - 1) << ZXDH_GDMA_VF_NUM_SHIFT));</p><p>+<span style="white-space:pre"> </span>}</p><p>+<span style="white-space:pre">        </span>ZXDH_PMD_LOG(DEBUG, "job flags:0x%x ep_id:%u, pf_id:%u, vf_id:%u, user:0x%x\n",</p><p>+<span style="white-space:pre">                                                </span>job->flags, job->ep_id, job->pf_id, job->vf_id,</p><p>+<span style="white-space:pre">                                              </span>(src_user & LOW16_MASK) | (dst_user << 16));</p><p>+</p><p>+<span style="white-space:pre">       </span>return (src_user & LOW16_MASK) | (dst_user << 16);</p><p>+}</p><p>+</p><p>+static inline void</p><p>+zxdh_gdma_fill_bd(struct zxdh_gdma_queue *queue, struct zxdh_gdma_job *job)</p><p>+{</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_buff_desc *bd = NULL;</p><p>+<span style="white-space:pre">   </span>uint val = 0;</p><p>+<span style="white-space:pre">    </span>uint64_t next_bd_addr = 0;</p><p>+<span style="white-space:pre">       </span>uint16_t avail_idx = 0;</p><p>+</p><p>+<span style="white-space:pre">      </span>avail_idx = queue->ring.avail_idx;</p><p>+<span style="white-space:pre">    </span>bd = &(queue->ring.desc[avail_idx]);</p><p>+<span style="white-space:pre">      </span>memset(bd, 0, sizeof(struct zxdh_gdma_buff_desc));</p><p>+</p><p>+<span style="white-space:pre">   </span>/* data bd */</p><p>+<span style="white-space:pre">    </span>if (job != NULL) {</p><p>+<span style="white-space:pre">               </span>zxdh_gdma_control_cal(&val, 1);</p><p>+<span style="white-space:pre">              </span>next_bd_addr   = IDX_TO_ADDR(queue->ring.ring_mem,</p><p>+<span style="white-space:pre">                                                  </span>(avail_idx + 1) % ZXDH_GDMA_RING_SIZE,</p><p>+<span style="white-space:pre">                                                   </span>uint64_t);</p><p>+<span style="white-space:pre">               </span>bd->SrcAddr_L  = job->src & LOW32_MASK;</p><p>+<span style="white-space:pre">           </span>bd->DstAddr_L  = job->dest & LOW32_MASK;</p><p>+<span style="white-space:pre">          </span>bd->SrcAddr_H  = (job->src >> 32) & LOW32_MASK;</p><p>+<span style="white-space:pre">             </span>bd->DstAddr_H  = (job->dest >> 32) & LOW32_MASK;</p><p>+<span style="white-space:pre">            </span>bd->Xpara      = job->len;</p><p>+<span style="white-space:pre">          </span>bd->ExtAddr    = zxdh_gdma_user_get(queue, job);</p><p>+<span style="white-space:pre">            </span>bd->LLI_Addr_L = (next_bd_addr >> 6) & LOW32_MASK;</p><p>+<span style="white-space:pre">          </span>bd->LLI_Addr_H = next_bd_addr >> 38;</p><p>+<span style="white-space:pre">            </span>bd->LLI_User   = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">         </span>bd->Control    = val;</p><p>+<span style="white-space:pre">       </span>} else {</p><p>+<span style="white-space:pre">         </span>zxdh_gdma_control_cal(&val, 0);</p><p>+<span style="white-space:pre">              </span>next_bd_addr   = IDX_TO_ADDR(queue->ring.ring_mem, avail_idx, uint64_t);</p><p>+<span style="white-space:pre">            </span>bd->ExtAddr    = queue->user;</p><p>+<span style="white-space:pre">            </span>bd->LLI_User   = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre">         </span>bd->Control    = val;</p><p>+<span style="white-space:pre">               </span>bd->LLI_Addr_L = (next_bd_addr >> 6) & LOW32_MASK;</p><p>+<span style="white-space:pre">          </span>bd->LLI_Addr_H = (next_bd_addr >> 38) | ZXDH_GDMA_LINK_END_NODE;</p><p>+<span style="white-space:pre">                </span>if (queue->flag != 0) {</p><p>+<span style="white-space:pre">                       </span>bd = IDX_TO_ADDR(queue->ring.desc,</p><p>+<span style="white-space:pre">                                    </span>queue->ring.last_avail_idx,</p><p>+<span style="white-space:pre">                                   </span>struct zxdh_gdma_buff_desc*);</p><p>+<span style="white-space:pre">                    </span>next_bd_addr = IDX_TO_ADDR(queue->ring.ring_mem,</p><p>+<span style="white-space:pre">                                      </span>(queue->ring.last_avail_idx + 1) % ZXDH_GDMA_RING_SIZE,</p><p>+<span style="white-space:pre">                                       </span>uint64_t);</p><p>+<span style="white-space:pre">                       </span>bd->LLI_Addr_L  = (next_bd_addr >> 6) & LOW32_MASK;</p><p>+<span style="white-space:pre">                    </span>bd->LLI_Addr_H  = next_bd_addr >> 38;</p><p>+<span style="white-space:pre">                      </span>rte_wmb();</p><p>+<span style="white-space:pre">                       </span>bd->LLI_Addr_H &= ~ZXDH_GDMA_LINK_END_NODE;</p><p>+<span style="white-space:pre">               </span>}</p><p>+<span style="white-space:pre">                </span>/* Record the index of empty bd for dynamic chaining */</p><p>+<span style="white-space:pre">          </span>queue->ring.last_avail_idx = avail_idx;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (++avail_idx >= ZXDH_GDMA_RING_SIZE)</p><p>+<span style="white-space:pre">               </span>avail_idx -= ZXDH_GDMA_RING_SIZE;</p><p>+</p><p>+<span style="white-space:pre">    </span>queue->ring.avail_idx = avail_idx;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_enqueue_bufs(struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                            </span>__rte_unused struct rte_rawdev_buf **buffers,</p><p>+<span style="white-space:pre">                                            </span>uint count,</p><p>+<span style="white-space:pre">                                              </span>rte_rawdev_obj_t context)</p><p>+{</p><p>+<span style="white-space:pre">   </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>struct zxdh_gdma_enqdeq *e_context = NULL;</p><p>+<span style="white-space:pre">       </span>struct zxdh_gdma_job *job = NULL;</p><p>+<span style="white-space:pre">        </span>uint16_t queue_id = 0;</p><p>+<span style="white-space:pre">   </span>uint val = 0;</p><p>+<span style="white-space:pre">    </span>uint16_t i = 0;</p><p>+<span style="white-space:pre">  </span>uint16_t free_cnt = 0;</p><p>+</p><p>+<span style="white-space:pre">       </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>if (unlikely((count < 1) || (context == NULL)))</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>if (gdmadev->device_state == ZXDH_GDMA_DEV_STOPPED) {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "gdma dev is stop");</p><p>+<span style="white-space:pre">         </span>return 0;</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>e_context = (struct zxdh_gdma_enqdeq *)context;</p><p>+<span style="white-space:pre">  </span>queue_id = e_context->vq_id;</p><p>+<span style="white-space:pre">  </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if ((queue == NULL) || (queue->enable == 0))</p><p>+<span style="white-space:pre">          </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>free_cnt = queue->sw_ring.free_cnt;</p><p>+<span style="white-space:pre">   </span>if (free_cnt == 0) {</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(ERR, "queue %u is full, enq_idx:%u deq_idx:%u used_idx:%u",</p><p>+<span style="white-space:pre">                                               </span>   queue_id, queue->sw_ring.enq_idx,</p><p>+<span style="white-space:pre">                                                </span>   queue->sw_ring.deq_idx, queue->sw_ring.used_idx);</p><p>+<span style="white-space:pre">             </span>return 0;</p><p>+<span style="white-space:pre">        </span>} else if (free_cnt < count) {</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(DEBUG, "job num %u > free_cnt, change to %u", count, free_cnt);</p><p>+<span style="white-space:pre">                </span>count = free_cnt;</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>rte_spinlock_lock(&queue->enqueue_lock);</p><p>+</p><p>+<span style="white-space:pre">      </span>/* Build bd list, the last bd is empty bd */</p><p>+<span style="white-space:pre">     </span>for (i = 0; i < count; i++) {</p><p>+<span style="white-space:pre">         </span>job = e_context->job[i];</p><p>+<span style="white-space:pre">              </span>zxdh_gdma_fill_bd(queue, job);</p><p>+<span style="white-space:pre">   </span>}</p><p>+<span style="white-space:pre">        </span>zxdh_gdma_fill_bd(queue, NULL);</p><p>+</p><p>+<span style="white-space:pre">      </span>if (unlikely(queue->flag == 0)) {</p><p>+<span style="white-space:pre">             </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_LLI_L_OFFSET,</p><p>+<span style="white-space:pre">                                                       </span>(queue->ring.ring_mem >> 6) & LOW32_MASK);</p><p>+<span style="white-space:pre">          </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_LLI_H_OFFSET,</p><p>+<span style="white-space:pre">                                                       </span> queue->ring.ring_mem >> 38);</p><p>+<span style="white-space:pre">           </span>/* Start hardware handling */</p><p>+<span style="white-space:pre">            </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_XFERSIZE_OFFSET, 0);</p><p>+<span style="white-space:pre">                </span>zxdh_gdma_control_cal(&val, 0);</p><p>+<span style="white-space:pre">              </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_CONTROL_OFFSET, val);</p><p>+<span style="white-space:pre">               </span>queue->flag = 1;</p><p>+<span style="white-space:pre">      </span>} else {</p><p>+<span style="white-space:pre">         </span>val = ZXDH_GDMA_CHAN_CONTINUE;</p><p>+<span style="white-space:pre">           </span>zxdh_gdma_write_reg(dev, queue->vq_id, ZXDH_GDMA_CHAN_CONTINUE_OFFSET, val);</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+    /* job enqueue */</p><p>+<span style="white-space:pre"> </span>for (i = 0; i < count; i++) {</p><p>+<span style="white-space:pre">         </span>queue->sw_ring.job[queue->sw_ring.enq_idx] = e_context->job[i];</p><p>+<span style="white-space:pre">         </span>if (++queue->sw_ring.enq_idx >= queue->queue_size)</p><p>+<span style="white-space:pre">                      </span>queue->sw_ring.enq_idx -= queue->queue_size;</p><p>+</p><p>+<span style="white-space:pre">           </span>free_cnt--;</p><p>+<span style="white-space:pre">      </span>}</p><p>+<span style="white-space:pre">        </span>queue->sw_ring.free_cnt = free_cnt;</p><p>+<span style="white-space:pre">   </span>queue->sw_ring.pend_cnt += count;</p><p>+<span style="white-space:pre">     </span>rte_spinlock_unlock(&queue->enqueue_lock);</p><p>+</p><p>+<span style="white-space:pre">    </span>return count;</p><p>+}</p><p>+</p><p>+static inline void</p><p>+zxdh_gdma_used_idx_update(struct zxdh_gdma_queue *queue, uint16_t cnt, uint8_t data_bd_err)</p><p>+{</p><p>+<span style="white-space:pre"> </span>uint16_t idx = 0;</p><p>+</p><p>+<span style="white-space:pre">    </span>if (queue->sw_ring.used_idx + cnt < queue->queue_size)</p><p>+<span style="white-space:pre">          </span>queue->sw_ring.used_idx += cnt;</p><p>+<span style="white-space:pre">       </span>else</p><p>+<span style="white-space:pre">             </span>queue->sw_ring.used_idx = queue->sw_ring.used_idx + cnt - queue->queue_size;</p><p>+</p><p>+<span style="white-space:pre">        </span>if (data_bd_err == 1) {</p><p>+<span style="white-space:pre">          </span>/* Update job status, the last job status is error */</p><p>+<span style="white-space:pre">            </span>if (queue->sw_ring.used_idx == 0)</p><p>+<span style="white-space:pre">                     </span>idx = queue->queue_size - 1;</p><p>+<span style="white-space:pre">          </span>else</p><p>+<span style="white-space:pre">                     </span>idx = queue->sw_ring.used_idx - 1;</p><p>+</p><p>+<span style="white-space:pre">                </span>queue->sw_ring.job[idx]->status = 1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_dequeue_bufs(struct rte_rawdev *dev,</p><p>+<span style="white-space:pre">                                                </span>__rte_unused struct rte_rawdev_buf **buffers,</p><p>+<span style="white-space:pre">                                            </span>uint count,</p><p>+<span style="white-space:pre">                                              </span>rte_rawdev_obj_t context)</p><p>+{</p><p>+<span style="white-space:pre">   </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>struct zxdh_gdma_enqdeq *e_context = NULL;</p><p>+<span style="white-space:pre">       </span>uint16_t queue_id = 0;</p><p>+<span style="white-space:pre">   </span>uint val = 0;</p><p>+<span style="white-space:pre">    </span>uint16_t tc_cnt = 0;</p><p>+<span style="white-space:pre">     </span>uint16_t diff_cnt = 0;</p><p>+<span style="white-space:pre">   </span>uint16_t i = 0;</p><p>+<span style="white-space:pre">  </span>uint16_t bd_idx = 0;</p><p>+<span style="white-space:pre">     </span>uint64_t next_bd_addr = 0;</p><p>+<span style="white-space:pre">       </span>uint8_t data_bd_err = 0;</p><p>+</p><p>+<span style="white-space:pre">     </span>if ((dev == NULL) || (context == NULL))</p><p>+<span style="white-space:pre">          </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>e_context = (struct zxdh_gdma_enqdeq *)context;</p><p>+<span style="white-space:pre">  </span>queue_id = e_context->vq_id;</p><p>+<span style="white-space:pre">  </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if ((queue == NULL) || (queue->enable == 0))</p><p>+<span style="white-space:pre">          </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>if (queue->sw_ring.pend_cnt == 0)</p><p>+<span style="white-space:pre">             </span>goto deq_job;</p><p>+</p><p>+<span style="white-space:pre">        </span>/* Get data transmit count */</p><p>+<span style="white-space:pre">    </span>val = zxdh_gdma_read_reg(dev, queue_id, ZXDH_GDMA_TC_CNT_OFFSET);</p><p>+<span style="white-space:pre">        </span>tc_cnt = val & LOW16_MASK;</p><p>+<span style="white-space:pre">   </span>if (tc_cnt >= queue->tc_cnt)</p><p>+<span style="white-space:pre">               </span>diff_cnt = tc_cnt - queue->tc_cnt;</p><p>+<span style="white-space:pre">    </span>else</p><p>+<span style="white-space:pre">             </span>diff_cnt = tc_cnt + ZXDH_GDMA_TC_CNT_MAX - queue->tc_cnt;</p><p>+</p><p>+<span style="white-space:pre"> </span>queue->tc_cnt = tc_cnt;</p><p>+</p><p>+<span style="white-space:pre">   </span>/* Data transmit error, channel stopped */</p><p>+<span style="white-space:pre">       </span>if ((val & ZXDH_GDMA_ERR_STATUS) != 0) {</p><p>+<span style="white-space:pre">             </span>next_bd_addr  = zxdh_gdma_read_reg(dev, queue_id, ZXDH_GDMA_LLI_L_OFFSET);</p><p>+<span style="white-space:pre">          </span>next_bd_addr |= ((uint64_t)zxdh_gdma_read_reg(dev, queue_id,</p><p>+<span style="white-space:pre">                                                     </span>ZXDH_GDMA_LLI_H_OFFSET) << 32);</p><p>+<span style="white-space:pre">            </span>next_bd_addr  = next_bd_addr << 6;</p><p>+<span style="white-space:pre">            </span>bd_idx = (next_bd_addr - queue->ring.ring_mem) / sizeof(struct zxdh_gdma_buff_desc);</p><p>+<span style="white-space:pre">          </span>if ((val & ZXDH_GDMA_SRC_DATA_ERR) || (val & ZXDH_GDMA_DST_ADDR_ERR)) {</p><p>+<span style="white-space:pre">                  </span>diff_cnt++;</p><p>+<span style="white-space:pre">                      </span>data_bd_err = 1;</p><p>+<span style="white-space:pre">         </span>}</p><p>+<span style="white-space:pre">                </span>ZXDH_PMD_LOG(INFO, "queue%d is err(0x%x) next_bd_idx:%u ll_addr:0x%"PRIx64" def user:0x%x",</p><p>+<span style="white-space:pre">                                  </span>queue_id, val, bd_idx, next_bd_addr, queue->user);</p><p>+<span style="white-space:pre">            </span>zxdh_gdma_debug_info_dump(dev, queue_id);</p><p>+</p><p>+<span style="white-space:pre">            </span>ZXDH_PMD_LOG(INFO, "Clean up error status");</p><p>+<span style="white-space:pre">           </span>val = ZXDH_GDMA_ERR_STATUS | ZXDH_GDMA_ERR_INTR_ENABLE;</p><p>+<span style="white-space:pre">          </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_TC_CNT_OFFSET, val);</p><p>+</p><p>+<span style="white-space:pre">            </span>ZXDH_PMD_LOG(INFO, "Restart channel");</p><p>+<span style="white-space:pre">         </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_XFERSIZE_OFFSET, 0);</p><p>+<span style="white-space:pre">                </span>zxdh_gdma_control_cal(&val, 0);</p><p>+<span style="white-space:pre">              </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_CONTROL_OFFSET, val);</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if (diff_cnt != 0) {</p><p>+<span style="white-space:pre">             </span>zxdh_gdma_used_idx_update(queue, diff_cnt, data_bd_err);</p><p>+<span style="white-space:pre">         </span>queue->sw_ring.deq_cnt += diff_cnt;</p><p>+<span style="white-space:pre">           </span>queue->sw_ring.pend_cnt -= diff_cnt;</p><p>+<span style="white-space:pre">  </span>}</p><p>+</p><p>+deq_job:</p><p>+<span style="white-space:pre">        </span>if (queue->sw_ring.deq_cnt == 0)</p><p>+<span style="white-space:pre">              </span>return 0;</p><p>+<span style="white-space:pre">        </span>else if (queue->sw_ring.deq_cnt < count)</p><p>+<span style="white-space:pre">           </span>count = queue->sw_ring.deq_cnt;</p><p>+</p><p>+<span style="white-space:pre">   </span>queue->sw_ring.deq_cnt -= count;</p><p>+</p><p>+<span style="white-space:pre">  </span>for (i = 0; i < count; i++) {</p><p>+<span style="white-space:pre">         </span>e_context->job[i] = queue->sw_ring.job[queue->sw_ring.deq_idx];</p><p>+<span style="white-space:pre">         </span>queue->sw_ring.job[queue->sw_ring.deq_idx] = NULL;</p><p>+<span style="white-space:pre">         </span>if (++queue->sw_ring.deq_idx >= queue->queue_size)</p><p>+<span style="white-space:pre">                      </span>queue->sw_ring.deq_idx -= queue->queue_size;</p><p>+<span style="white-space:pre">       </span>}</p><p>+<span style="white-space:pre">        </span>queue->sw_ring.free_cnt += count;</p><p>+</p><p>+<span style="white-space:pre"> </span>return count;</p><p>+}</p><p>+</p><p>+static const struct rte_rawdev_ops zxdh_gdma_rawdev_ops = {</p><p>+<span style="white-space:pre">    </span>.dev_info_get = zxdh_gdma_rawdev_info_get,</p><p>+<span style="white-space:pre">       </span>.dev_configure = zxdh_gdma_rawdev_configure,</p><p>+<span style="white-space:pre">     </span>.dev_start = zxdh_gdma_rawdev_start,</p><p>+<span style="white-space:pre">     </span>.dev_stop = zxdh_gdma_rawdev_stop,</p><p>+<span style="white-space:pre">       </span>.dev_close = zxdh_gdma_rawdev_close,</p><p>+<span style="white-space:pre">     </span>.dev_reset = zxdh_gdma_rawdev_reset,</p><p>+</p><p>+<span style="white-space:pre"> </span>.queue_setup = zxdh_gdma_rawdev_queue_setup,</p><p>+<span style="white-space:pre">     </span>.queue_release = zxdh_gdma_rawdev_queue_release,</p><p>+</p><p>+<span style="white-space:pre">     </span>.attr_get = zxdh_gdma_rawdev_get_attr,</p><p>+</p><p>+<span style="white-space:pre">       </span>.enqueue_bufs = zxdh_gdma_rawdev_enqueue_bufs,</p><p>+<span style="white-space:pre">   </span>.dequeue_bufs = zxdh_gdma_rawdev_dequeue_bufs,</p><p>+};</p><p>+</p><p>+static int</p><p>+zxdh_gdma_queue_init(struct rte_rawdev *dev, uint16_t queue_id)</p><p>+{</p><p>+<span style="white-space:pre">   </span>char name[RTE_RAWDEV_NAME_MAX_LEN];</p><p>+<span style="white-space:pre">      </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>const struct rte_memzone *mz = NULL;</p><p>+<span style="white-space:pre">     </span>uint size = 0;</p><p>+<span style="white-space:pre">   </span>uint val = 0;</p><p>+<span style="white-space:pre">    </span>int ret = 0;</p><p>+</p><p>+<span style="white-space:pre"> </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if (queue == NULL)</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>queue->enable = 1;</p><p>+<span style="white-space:pre">    </span>queue->vq_id  = queue_id;</p><p>+<span style="white-space:pre">        </span>queue->flag   = 0;</p><p>+<span style="white-space:pre">  </span>queue->tc_cnt = 0;</p><p>+</p><p>+<span style="white-space:pre">        </span>/* Init sw_ring */</p><p>+<span style="white-space:pre">       </span>memset(name, 0, sizeof(name));</p><p>+<span style="white-space:pre">   </span>snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "gdma_vq%d_sw_ring", queue_id);</p><p>+<span style="white-space:pre">        </span>size = queue->queue_size * sizeof(struct zxdh_gdma_job *);</p><p>+<span style="white-space:pre">    </span>queue->sw_ring.job = rte_zmalloc(name, size, 0);</p><p>+<span style="white-space:pre">      </span>if (queue->sw_ring.job == NULL) {</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(ERR, "can not allocate sw_ring %s", name);</p><p>+<span style="white-space:pre">                </span>ret = -ENOMEM;</p><p>+<span style="white-space:pre">           </span>goto free_queue;</p><p>+<span style="white-space:pre"> </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>/* Cache up to size-1 job in the ring to prevent overwriting hardware prefetching */</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.free_cnt = queue->queue_size - 1;</p><p>+<span style="white-space:pre">   </span>queue->sw_ring.deq_cnt  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.pend_cnt = 0;</p><p>+<span style="white-space:pre">  </span>queue->sw_ring.enq_idx  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.deq_idx  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.used_idx = 0;</p><p>+</p><p>+<span style="white-space:pre">      </span>/* Init ring */</p><p>+<span style="white-space:pre">  </span>memset(name, 0, sizeof(name));</p><p>+<span style="white-space:pre">   </span>snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "gdma_vq%d_ring", queue_id);</p><p>+<span style="white-space:pre">   </span>size = ZXDH_GDMA_RING_SIZE * sizeof(struct zxdh_gdma_buff_desc);</p><p>+<span style="white-space:pre"> </span>mz = rte_memzone_reserve_aligned(name, size, rte_socket_id(),</p><p>+<span style="white-space:pre">                                                    </span>RTE_MEMZONE_IOVA_CONTIG, size);</p><p>+<span style="white-space:pre">  </span>if (mz == NULL) {</p><p>+<span style="white-space:pre">                </span>if (rte_errno == EEXIST)</p><p>+<span style="white-space:pre">                 </span>mz = rte_memzone_lookup(name);</p><p>+<span style="white-space:pre">           </span>if (mz == NULL) {</p><p>+<span style="white-space:pre">                        </span>ZXDH_PMD_LOG(ERR, "can not allocate ring %s", name);</p><p>+<span style="white-space:pre">                   </span>ret = -ENOMEM;</p><p>+<span style="white-space:pre">                   </span>goto free_queue;</p><p>+<span style="white-space:pre">         </span>}</p><p>+<span style="white-space:pre">        </span>}</p><p>+<span style="white-space:pre">        </span>memset(mz->addr, 0, size);</p><p>+<span style="white-space:pre">    </span>queue->ring.ring_mz   = mz;</p><p>+<span style="white-space:pre"> </span>queue->ring.desc      = (struct zxdh_gdma_buff_desc *)(mz->addr);</p><p>+<span style="white-space:pre">   </span>queue->ring.ring_mem  = mz->iova;</p><p>+<span style="white-space:pre">     </span>queue->ring.avail_idx = 0;</p><p>+<span style="white-space:pre">    </span>ZXDH_PMD_LOG(INFO, "queue%u ring phy addr:0x%"PRIx64" virt addr:%p",</p><p>+<span style="white-space:pre">                                         </span>queue_id, mz->iova, mz->addr);</p><p>+</p><p>+<span style="white-space:pre"> </span>/* clean gdma channel */</p><p>+<span style="white-space:pre"> </span>val = ZXDH_GDMA_CHAN_FORCE_CLOSE;</p><p>+<span style="white-space:pre">        </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_CONTROL_OFFSET, val);</p><p>+</p><p>+<span style="white-space:pre">   </span>val = ZXDH_GDMA_ERR_INTR_ENABLE | ZXDH_GDMA_ERR_STATUS | ZXDH_GDMA_TC_CNT_CLEAN;</p><p>+<span style="white-space:pre"> </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_TC_CNT_OFFSET, val);</p><p>+</p><p>+<span style="white-space:pre">    </span>val = ZXDH_GDMA_ZF_USER;</p><p>+<span style="white-space:pre"> </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_LLI_USER_OFFSET, val);</p><p>+</p><p>+<span style="white-space:pre">  </span>return 0;</p><p>+</p><p>+free_queue:</p><p>+<span style="white-space:pre">     </span>zxdh_gdma_queue_free(dev, queue_id);</p><p>+<span style="white-space:pre">     </span>return ret;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_queue_free(struct rte_rawdev *dev, uint16_t queue_id)</p><p>+{</p><p>+<span style="white-space:pre">       </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>uint val = 0;</p><p>+</p><p>+<span style="white-space:pre">        </span>queue = zxdh_gdma_get_queue(dev, queue_id);</p><p>+<span style="white-space:pre">      </span>if (queue == NULL)</p><p>+<span style="white-space:pre">               </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>gdmadev->used_num--;</p><p>+</p><p>+<span style="white-space:pre">      </span>/* disable gdma channel */</p><p>+<span style="white-space:pre">       </span>val = ZXDH_GDMA_CHAN_FORCE_CLOSE;</p><p>+<span style="white-space:pre">        </span>zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_CONTROL_OFFSET, val);</p><p>+</p><p>+<span style="white-space:pre">   </span>queue->enable           = 0;</p><p>+<span style="white-space:pre">    </span>queue->is_txq           = 0;</p><p>+<span style="white-space:pre">    </span>queue->flag             = 0;</p><p>+<span style="white-space:pre">       </span>queue->user             = 0;</p><p>+<span style="white-space:pre">       </span>queue->tc_cnt           = 0;</p><p>+<span style="white-space:pre">    </span>queue->ring.avail_idx   = 0;</p><p>+<span style="white-space:pre">        </span>queue->sw_ring.free_cnt = 0;</p><p>+<span style="white-space:pre">  </span>queue->sw_ring.deq_cnt  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.pend_cnt = 0;</p><p>+<span style="white-space:pre">  </span>queue->sw_ring.enq_idx  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.deq_idx  = 0;</p><p>+<span style="white-space:pre">     </span>queue->sw_ring.used_idx = 0;</p><p>+</p><p>+<span style="white-space:pre">      </span>if (queue->sw_ring.job != NULL)</p><p>+<span style="white-space:pre">               </span>rte_free(queue->sw_ring.job);</p><p>+</p><p>+<span style="white-space:pre">     </span>if (queue->ring.ring_mz != NULL)</p><p>+<span style="white-space:pre">              </span>rte_memzone_free(queue->ring.ring_mz);</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_probe(struct rte_vdev_device *vdev)</p><p>+{</p><p>+<span style="white-space:pre">    </span>struct rte_rawdev *dev = NULL;</p><p>+<span style="white-space:pre">   </span>struct zxdh_gdma_rawdev *gdmadev = NULL;</p><p>+<span style="white-space:pre"> </span>struct zxdh_gdma_queue *queue = NULL;</p><p>+<span style="white-space:pre">    </span>uint8_t i = 0;</p><p>+</p><p>+<span style="white-space:pre">       </span>if (zxdh_gdma_pci_scan() != 0) {</p><p>+<span style="white-space:pre">         </span>ZXDH_PMD_LOG(ERR, "Failed to scan gdma pci device!");</p><p>+<span style="white-space:pre">          </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>if ((gdev.bar_pa[0]) == 0) {</p><p>+<span style="white-space:pre">             </span>ZXDH_PMD_LOG(ERR, "Empty bars 0x%"PRIx64,</p><p>+<span style="white-space:pre">                                                      </span>(uint64_t)gdev.bar_pa[0]);</p><p>+<span style="white-space:pre">               </span>zxdh_gdma_pci_dev_munmap();</p><p>+<span style="white-space:pre">              </span>return -ENODEV;</p><p>+<span style="white-space:pre">  </span>}</p><p>+<span style="white-space:pre">        </span>ZXDH_PMD_LOG(INFO, "%04x:%02x:%02x.%01x Bar0 PhyAddr: 0x%"PRIx64,</p><p>+<span style="white-space:pre">                                      </span>gdev.domain, gdev.bus, gdev.devid, gdev.function,</p><p>+<span style="white-space:pre">                                        </span>(uint64_t)gdev.bar_pa[0]);</p><p>+</p><p>+<span style="white-space:pre">   </span>dev = rte_rawdev_pmd_allocate(dev_name, sizeof(struct zxdh_gdma_rawdev), rte_socket_id());</p><p>+<span style="white-space:pre">       </span>if (dev == NULL) {</p><p>+<span style="white-space:pre">               </span>ZXDH_PMD_LOG(ERR, "Unable to allocate gdma rawdev");</p><p>+<span style="white-space:pre">           </span>zxdh_gdma_pci_dev_munmap();</p><p>+<span style="white-space:pre">              </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+<span style="white-space:pre">        </span>ZXDH_PMD_LOG(INFO, "Init %s on NUMA node %d, dev_id is %d",</p><p>+<span style="white-space:pre">                                            </span>dev_name, rte_socket_id(), dev->dev_id);</p><p>+</p><p>+<span style="white-space:pre">  </span>dev->dev_ops = &zxdh_gdma_rawdev_ops;</p><p>+<span style="white-space:pre">     </span>dev->device = &vdev->device;</p><p>+<span style="white-space:pre">   </span>dev->driver_name = zxdh_gdma_driver_name;</p><p>+<span style="white-space:pre">     </span>gdmadev = zxdh_gdma_rawdev_get_priv(dev);</p><p>+<span style="white-space:pre">        </span>gdmadev->device_state = ZXDH_GDMA_DEV_STOPPED;</p><p>+<span style="white-space:pre">        </span>gdmadev->rawdev = dev;</p><p>+<span style="white-space:pre">        </span>gdmadev->queue_num = ZXDH_GDMA_TOTAL_CHAN_NUM;</p><p>+<span style="white-space:pre">        </span>gdmadev->used_num = 0;</p><p>+<span style="white-space:pre">        </span>gdmadev->base_addr = (uintptr_t)gdev.bar_va[0] + ZXDH_GDMA_BASE_OFFSET;</p><p>+</p><p>+<span style="white-space:pre">   </span>for (i = 0; i < ZXDH_GDMA_TOTAL_CHAN_NUM; i++) {</p><p>+<span style="white-space:pre">              </span>queue = &(gdmadev->vqs[i]);</p><p>+<span style="white-space:pre">               </span>queue->enable = 0;</p><p>+<span style="white-space:pre">            </span>queue->queue_size = ZXDH_GDMA_QUEUE_SIZE;</p><p>+<span style="white-space:pre">             </span>rte_spinlock_init(&(queue->enqueue_lock));</p><p>+<span style="white-space:pre">        </span>}</p><p>+</p><p>+<span style="white-space:pre">    </span>return 0;</p><p>+}</p><p>+</p><p>+static int</p><p>+zxdh_gdma_rawdev_remove(__rte_unused struct rte_vdev_device *vdev)</p><p>+{</p><p>+<span style="white-space:pre">      </span>struct rte_rawdev *dev = NULL;</p><p>+<span style="white-space:pre">   </span>int ret = 0;</p><p>+</p><p>+<span style="white-space:pre"> </span>dev = rte_rawdev_pmd_get_named_dev(dev_name);</p><p>+<span style="white-space:pre">    </span>if (dev == NULL)</p><p>+<span style="white-space:pre">         </span>return -EINVAL;</p><p>+</p><p>+<span style="white-space:pre">      </span>/* rte_rawdev_close is called by pmd_release */</p><p>+<span style="white-space:pre">  </span>ret = rte_rawdev_pmd_release(dev);</p><p>+<span style="white-space:pre">       </span>if (ret != 0) {</p><p>+<span style="white-space:pre">          </span>ZXDH_PMD_LOG(ERR, "Device cleanup failed");</p><p>+<span style="white-space:pre">            </span>return -1;</p><p>+<span style="white-space:pre">       </span>}</p><p>+<span style="white-space:pre">        </span>ZXDH_PMD_LOG(DEBUG, "rawdev %s remove done!", dev_name);</p><p>+</p><p>+<span style="white-space:pre">   </span>return ret;</p><p>+}</p><p>+</p><p>+static struct rte_vdev_driver zxdh_gdma_pmd_drv = {</p><p>+<span style="white-space:pre">      </span>.probe = zxdh_gdma_rawdev_probe,</p><p>+<span style="white-space:pre"> </span>.remove = zxdh_gdma_rawdev_remove</p><p>+};</p><p>+</p><p>+RTE_PMD_REGISTER_VDEV(rawdev_zxdh_gdma, zxdh_gdma_pmd_drv);</p><p>+RTE_LOG_REGISTER_DEFAULT(zxdh_gdma_pmd_logtype, NOTICE);</p><p>diff --git a/drivers/raw/zxdh/zxdh_rawdev.h b/drivers/raw/zxdh/zxdh_rawdev.h</p><p>new file mode 100644</p><p>index 0000000000..8f26b4f01a</p><p>--- /dev/null</p><p>+++ b/drivers/raw/zxdh/zxdh_rawdev.h</p><p>@@ -0,0 +1,165 @@</p><p>+/* SPDX-License-Identifier: BSD-3-Clause</p><p>+ * Copyright 2024 ZTE Corporation</p><p>+ */</p><p>+</p><p>+#ifndef __ZXDH_RAWDEV_H__</p><p>+#define __ZXDH_RAWDEV_H__</p><p>+</p><p>+#ifdef __cplusplus</p><p>+extern "C" {</p><p>+#endif</p><p>+</p><p>+#include <rte_rawdev.h></p><p>+#include <rte_spinlock.h></p><p>+</p><p>+extern int zxdh_gdma_pmd_logtype;</p><p>+</p><p>+#define ZXDH_PMD_LOG(level, fmt, args...) \</p><p>+<span style="white-space:pre">   </span>rte_log(RTE_LOG_ ## level, zxdh_gdma_pmd_logtype, "%s(): " fmt "\n", __func__, ##args)</p><p>+</p><p>+#define ZXDH_GDMA_VENDORID                      0x1cf2</p><p>+#define ZXDH_GDMA_DEVICEID                      0x8044</p><p>+</p><p>+#define ZXDH_GDMA_TOTAL_CHAN_NUM                58</p><p>+#define ZXDH_GDMA_QUEUE_SIZE                    16384 /* >= 65*64*3 */</p><p>+#define ZXDH_GDMA_RING_SIZE                     32768</p><p>+</p><p>+/* States if the source addresses is physical. */</p><p>+#define ZXDH_GDMA_JOB_SRC_PHY                   (1UL)</p><p>+</p><p>+/* States if the destination addresses is physical. */</p><p>+#define ZXDH_GDMA_JOB_DEST_PHY                  (1UL << 1)</p><p>+</p><p>+/* ZF->HOST */</p><p>+#define ZXDH_GDMA_JOB_DIR_TX                    (1UL << 2)</p><p>+</p><p>+/* HOST->ZF */</p><p>+#define ZXDH_GDMA_JOB_DIR_RX                    (1UL << 3)</p><p>+</p><p>+#define ZXDH_GDMA_JOB_DIR_MASK                  (ZXDH_GDMA_JOB_DIR_TX | ZXDH_GDMA_JOB_DIR_RX)</p><p>+</p><p>+enum zxdh_gdma_device_state {</p><p>+<span style="white-space:pre">        </span>ZXDH_GDMA_DEV_RUNNING,</p><p>+<span style="white-space:pre">   </span>ZXDH_GDMA_DEV_STOPPED</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_buff_desc {</p><p>+<span style="white-space:pre">  </span>uint SrcAddr_L;</p><p>+<span style="white-space:pre">  </span>uint DstAddr_L;</p><p>+<span style="white-space:pre">  </span>uint Xpara;</p><p>+<span style="white-space:pre">      </span>uint ZY_para;</p><p>+<span style="white-space:pre">    </span>uint ZY_SrcStep;</p><p>+<span style="white-space:pre"> </span>uint ZY_DstStep;</p><p>+<span style="white-space:pre"> </span>uint ExtAddr;</p><p>+<span style="white-space:pre">    </span>uint LLI_Addr_L;</p><p>+<span style="white-space:pre"> </span>uint LLI_Addr_H;</p><p>+<span style="white-space:pre"> </span>uint ChCont;</p><p>+<span style="white-space:pre">     </span>uint LLI_User;</p><p>+<span style="white-space:pre">   </span>uint ErrAddr;</p><p>+<span style="white-space:pre">    </span>uint Control;</p><p>+<span style="white-space:pre">    </span>uint SrcAddr_H;</p><p>+<span style="white-space:pre">  </span>uint DstAddr_H;</p><p>+<span style="white-space:pre">  </span>uint Reserved;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_queue {</p><p>+<span style="white-space:pre">     </span>uint8_t   enable;</p><p>+<span style="white-space:pre">      </span>uint8_t   is_txq;</p><p>+<span style="white-space:pre">      </span>uint16_t  vq_id;</p><p>+<span style="white-space:pre">    </span>uint16_t  queue_size;</p><p>+<span style="white-space:pre">       </span>/* 0:GDMA needs to be configured through the APB interface */</p><p>+<span style="white-space:pre">    </span>uint16_t  flag;</p><p>+<span style="white-space:pre">     </span>uint      user;</p><p>+<span style="white-space:pre">   </span>uint16_t  tc_cnt;</p><p>+<span style="white-space:pre">   </span>rte_spinlock_t enqueue_lock;</p><p>+<span style="white-space:pre">     </span>struct {</p><p>+<span style="white-space:pre">         </span>uint16_t avail_idx;</p><p>+<span style="white-space:pre">              </span>uint16_t last_avail_idx;</p><p>+<span style="white-space:pre">         </span>rte_iova_t ring_mem;</p><p>+<span style="white-space:pre">             </span>const struct rte_memzone *ring_mz;</p><p>+<span style="white-space:pre">               </span>struct zxdh_gdma_buff_desc *desc;</p><p>+<span style="white-space:pre">        </span>} ring;</p><p>+<span style="white-space:pre">  </span>struct {</p><p>+<span style="white-space:pre">         </span>uint16_t  free_cnt;</p><p>+<span style="white-space:pre">         </span>uint16_t  deq_cnt;</p><p>+<span style="white-space:pre">          </span>uint16_t  pend_cnt;</p><p>+<span style="white-space:pre">         </span>uint16_t  enq_idx;</p><p>+<span style="white-space:pre">          </span>uint16_t  deq_idx;</p><p>+<span style="white-space:pre">          </span>uint16_t  used_idx;</p><p>+<span style="white-space:pre">         </span>struct zxdh_gdma_job **job;</p><p>+<span style="white-space:pre">      </span>} sw_ring;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_rawdev {</p><p>+<span style="white-space:pre">        </span>struct rte_device *device;</p><p>+<span style="white-space:pre">       </span>struct rte_rawdev *rawdev;</p><p>+<span style="white-space:pre">       </span>uintptr_t base_addr;</p><p>+<span style="white-space:pre">     </span>uint8_t queue_num; /* total queue num */</p><p>+<span style="white-space:pre"> </span>uint8_t used_num;  /* used  queue num */</p><p>+<span style="white-space:pre">       </span>enum zxdh_gdma_device_state device_state;</p><p>+<span style="white-space:pre">        </span>struct zxdh_gdma_queue vqs[ZXDH_GDMA_TOTAL_CHAN_NUM];</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_job {</p><p>+<span style="white-space:pre">        </span>uint64_t src;</p><p>+<span style="white-space:pre">    </span>uint64_t dest;</p><p>+<span style="white-space:pre">   </span>uint len;</p><p>+<span style="white-space:pre">        </span>uint flags;</p><p>+<span style="white-space:pre">      </span>uint64_t cnxt;</p><p>+<span style="white-space:pre">   </span>uint16_t status;</p><p>+<span style="white-space:pre"> </span>uint16_t vq_id;</p><p>+<span style="white-space:pre">  </span>void *usr_elem;</p><p>+<span style="white-space:pre">  </span>uint8_t ep_id;</p><p>+<span style="white-space:pre">   </span>uint8_t pf_id;</p><p>+<span style="white-space:pre">   </span>uint16_t vf_id;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_enqdeq {</p><p>+<span style="white-space:pre">   </span>uint16_t vq_id;</p><p>+<span style="white-space:pre">  </span>struct zxdh_gdma_job **job;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_config {</p><p>+<span style="white-space:pre">       </span>uint16_t max_hw_queues_per_core;</p><p>+<span style="white-space:pre"> </span>uint16_t max_vqs;</p><p>+<span style="white-space:pre">        </span>int fle_queue_pool_cnt;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_rbp {</p><p>+<span style="white-space:pre">      </span>uint use_ultrashort:1;</p><p>+<span style="white-space:pre">   </span>uint enable:1;</p><p>+<span style="white-space:pre">   </span>uint dportid:3;</p><p>+<span style="white-space:pre">  </span>uint dpfid:3;</p><p>+<span style="white-space:pre">    </span>uint dvfid:8; /*using route by port for destination */</p><p>+<span style="white-space:pre">   </span>uint drbp:1;</p><p>+<span style="white-space:pre">     </span>uint sportid:3;</p><p>+<span style="white-space:pre">  </span>uint spfid:3;</p><p>+<span style="white-space:pre">    </span>uint svfid:8;</p><p>+<span style="white-space:pre">    </span>uint srbp:1;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_queue_config {</p><p>+<span style="white-space:pre">        </span>uint lcore_id;</p><p>+<span style="white-space:pre">   </span>uint flags;</p><p>+<span style="white-space:pre">      </span>struct zxdh_gdma_rbp *rbp;</p><p>+};</p><p>+</p><p>+struct zxdh_gdma_attr {</p><p>+<span style="white-space:pre">  </span>uint16_t num_hw_queues;</p><p>+};</p><p>+</p><p>+static inline struct zxdh_gdma_rawdev *</p><p>+zxdh_gdma_rawdev_get_priv(const struct rte_rawdev *rawdev)</p><p>+{</p><p>+<span style="white-space:pre">  </span>return rawdev->dev_private;</p><p>+}</p><p>+</p><p>+uint zxdh_gdma_read_reg(struct rte_rawdev *dev, uint16_t qidx, uint offset);</p><p>+void zxdh_gdma_write_reg(struct rte_rawdev *dev, uint16_t qidx, uint offset, uint val);</p><p>+int zxdh_gdma_debug_info_dump(struct rte_rawdev *dev, uint16_t queue_id);</p><p>+</p><p>+#ifdef __cplusplus</p><p>+}</p><p>+#endif</p><p>+</p><p>+#endif /* __ZXDH_RAWDEV_H__ */</p><p>-- </p><p>2.43.0</p><p><br></p></div>