get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/73785/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 73785,
    "url": "http://patchwork.dpdk.org/api/patches/73785/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/1594419966-230753-2-git-send-email-nicolas.chautru@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1594419966-230753-2-git-send-email-nicolas.chautru@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1594419966-230753-2-git-send-email-nicolas.chautru@intel.com",
    "date": "2020-07-10T22:26:06",
    "name": "[v1] baseband/fpga_5gnr_fec: add companion PF config App",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "3afa08f36b62c4a19a2a4ceefe19cb27214f3269",
    "submitter": {
        "id": 1314,
        "url": "http://patchwork.dpdk.org/api/people/1314/?format=api",
        "name": "Chautru, Nicolas",
        "email": "nicolas.chautru@intel.com"
    },
    "delegate": {
        "id": 6690,
        "url": "http://patchwork.dpdk.org/api/users/6690/?format=api",
        "username": "akhil",
        "first_name": "akhil",
        "last_name": "goyal",
        "email": "gakhil@marvell.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1594419966-230753-2-git-send-email-nicolas.chautru@intel.com/mbox/",
    "series": [
        {
            "id": 10962,
            "url": "http://patchwork.dpdk.org/api/series/10962/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=10962",
            "date": "2020-07-10T22:26:06",
            "name": "[v1] baseband/fpga_5gnr_fec: add companion PF config App",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/10962/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/73785/comments/",
    "check": "fail",
    "checks": "http://patchwork.dpdk.org/api/patches/73785/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 92E66A052A;\n\tSat, 11 Jul 2020 00:28:11 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7C5551DA18;\n\tSat, 11 Jul 2020 00:28:04 +0200 (CEST)",
            "from mga04.intel.com (mga04.intel.com [192.55.52.120])\n by dpdk.org (Postfix) with ESMTP id 05BAD1D9B7\n for <dev@dpdk.org>; Sat, 11 Jul 2020 00:28:01 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 10 Jul 2020 15:28:00 -0700",
            "from skx-5gnr-sc12-4.sc.intel.com ([172.25.69.210])\n by orsmga002.jf.intel.com with ESMTP; 10 Jul 2020 15:27:59 -0700"
        ],
        "IronPort-SDR": [
            "\n UXnz6irJdsRuP3FRssbzQFiFhLCio4ALmIScWTnWr23y2f3CC/rDu2+S2rV1HVg5qPXgxUj6Ew\n DPEclKz/Df4Q==",
            "\n WUGTQX/olX4+WcXgQLmh7/z6SZpTnOKCJBqE50XsNcMX/XxLO1Ii+OKiSmUdLO/SLQTf7Zg87w\n Zjpcy4ERn4MQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9678\"; a=\"145806450\"",
            "E=Sophos;i=\"5.75,336,1589266800\"; d=\"scan'208\";a=\"145806450\"",
            "E=Sophos;i=\"5.75,336,1589266800\"; d=\"scan'208\";a=\"298562033\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Nicolas Chautru <nicolas.chautru@intel.com>",
        "To": "dev@dpdk.org,\n\takhil.goyal@nxp.com,\n\tthomas@monjalon.net",
        "Cc": "Nicolas Chautru <nicolas.chautru@intel.com>",
        "Date": "Fri, 10 Jul 2020 15:26:06 -0700",
        "Message-Id": "<1594419966-230753-2-git-send-email-nicolas.chautru@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1594419966-230753-1-git-send-email-nicolas.chautru@intel.com>",
        "References": "<1594419966-230753-1-git-send-email-nicolas.chautru@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v1] baseband/fpga_5gnr_fec: add companion PF\n\tconfig App",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Adding companion application to configure HW Device from the PF.\nThen the device can be accessed through BBDEV from VF (or PF).\n\nSigned-off-by: Nicolas Chautru <nicolas.chautru@intel.com>\n---\n doc/guides/bbdevs/fpga_5gnr_fec.rst                |  81 +++--\n .../baseband/fpga_5gnr_fec/pf_config_app/Makefile  |  36 ++\n .../fpga_5gnr_fec/pf_config_app/config_app.c       | 382 +++++++++++++++++++++\n .../pf_config_app/fpga_5gnr_cfg_app.c              | 351 +++++++++++++++++++\n .../pf_config_app/fpga_5gnr_cfg_app.h              | 102 ++++++\n .../pf_config_app/fpga_5gnr_cfg_parser.c           | 187 ++++++++++\n .../pf_config_app/fpga_5gnr_config.cfg             |  18 +\n 7 files changed, 1137 insertions(+), 20 deletions(-)\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/Makefile\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/config_app.c\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.c\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.h\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_parser.c\n create mode 100644 drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_config.cfg",
    "diff": "diff --git a/doc/guides/bbdevs/fpga_5gnr_fec.rst b/doc/guides/bbdevs/fpga_5gnr_fec.rst\nindex 19bba36..b9333e3 100644\n--- a/doc/guides/bbdevs/fpga_5gnr_fec.rst\n+++ b/doc/guides/bbdevs/fpga_5gnr_fec.rst\n@@ -218,33 +218,74 @@ parameters defined in ``fpga_5gnr_fec_conf`` structure:\n   time_out = flr_time_out x 16.384us. For instance, if you want to set 10ms for\n   the FLR time out then set this setting to 0x262=610.\n \n+A companion application pf_config_app is provided as a standalone application\n+described in next section. \n \n-An example configuration code calling the function ``fpga_5gnr_fec_configure()`` is shown\n-below:\n+PF Config App\n+-------------\n \n-.. code-block:: c\n+The PF Configuration Application ``pf_config_app`` provides a means to\n+configure the baseband device at the host-level. The program sets the various\n+parameters through memory-mapped IO read/writes. Then the BBDEV driver can be\n+used to run the workload.\n+\n+The parameters are parsed from a given configuration file (with .cfg extentions)\n+that is specific to particular BBDEV device, although they follow same format.\n+\n+External Dependencies\n+~~~~~~~~~~~~~~~~~~~~~\n+\n+The third party .INI parser is a pre-requisite for building the application.\n+It can be downloaded from [github]:\n+\n+.. code-block:: console\n \n-  struct fpga_5gnr_fec_conf conf;\n-  unsigned int i;\n+    git clone https://github.com/benhoyt/inih\n \n-  memset(&conf, 0, sizeof(struct fpga_5gnr_fec_conf));\n-  conf.pf_mode_en = 1;\n+Use the version release 44 tracked by tag 'r44':\n+\n+.. code-block:: console\n+\n+    git checkout r44\n+\n+The application features a makefile in the `extra/` directory which generates\n+the library, `libinih.a`. To compile the inih library, run make as:\n+\n+.. code-block:: console\n+\n+    make -f Makefile.static\n+\n+Building PF Config App\n+~~~~~~~~~~~~~~~~~~~~~~\n+\n+Before building the application, set the following environment variables with\n+the location where the INI library is located:\n+\n+.. code-block:: console\n+\n+    export INIH_PATH=<path-to-inih-lib>\n+\n+If not set, makefile will look into current folder.\n+\n+Next, build the program by typing ``make`` from the pf_Config_app subdirectory\n+to produce the binary ``pf_config_app_fpga_5gnr``.\n+\n+Usage\n+~~~~~\n+\n+The application executes as the following:\n+\n+.. code-block:: console\n \n-  for (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; ++i) {\n-      conf.vf_ul_queues_number[i] = 4;\n-      conf.vf_dl_queues_number[i] = 4;\n-  }\n-  conf.ul_bandwidth = 12;\n-  conf.dl_bandwidth = 5;\n-  conf.dl_load_balance = 64;\n-  conf.ul_load_balance = 64;\n+    ./pf_config_app_fpga_5gnr [-h] [-a] [-c CFG_FILE] [-f NUM_VFS] [-p PCI_ID]\n \n-  /* setup FPGA PF */\n-  ret = fpga_5gnr_fec_configure(info->dev_name, &conf);\n-  TEST_ASSERT_SUCCESS(ret,\n-      \"Failed to configure 4G FPGA PF for bbdev %s\",\n-      info->dev_name);\n+* ``-c CFG_FILE``: Specifies configuration file to use\n+* ``-f NUM_VFS``: Specifies number of Virtual Functions to enable through SRIOV\n+* ``-p PCI_ID``: Specifies PCI ID of device to configure\n+* ``-a``: Configures all PCI devices\n+* ``-h``: Prints help\n \n+Default configure file is provided: ``fpga_5gnr_config.cfg``.\n \n Test Application\n ----------------\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/Makefile b/drivers/baseband/fpga_5gnr_fec/pf_config_app/Makefile\nnew file mode 100644\nindex 0000000..dfd0b6d\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/Makefile\n@@ -0,0 +1,36 @@\n+\n+CC=gcc\n+CFLAGS=-O0 -g -Wall\n+ODIR=build\n+DEPS=\n+\n+ifeq ($(INIH_PATH),)\n+INCLUDE=-I.\n+LDFLAGS=-L.\n+else\n+INCLUDE=-I. -I$(INIH_PATH)\n+LDFLAGS=-L. -L$(INIH_PATH)\n+endif\n+\n+LDLIBS=-linih\n+\n+SRC = config_app.c fpga_5gnr_cfg_app.c fpga_5gnr_cfg_parser.c\n+OBJ = $(patsubst %.c,$(ODIR)/%.o,$(SRC))\n+\n+.PHONY: clean\n+\n+all: pf_config_app\n+\n+$(ODIR):\n+\tmkdir -p $(ODIR)\n+\n+$(OBJ): $(ODIR)/%.o: ./%.c | $(DEPS) $(ODIR)\n+\t@mkdir -p $(@D)\n+\t$(CC) -c -o $@ $< $(CFLAGS) $(INCLUDE)\n+\n+pf_config_app: $(OBJ)\n+\t$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LDLIBS)\n+\n+clean:\n+\trm -rf $(ODIR)\n+\trm -rf pf_config_app\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/config_app.c b/drivers/baseband/fpga_5gnr_fec/pf_config_app/config_app.c\nnew file mode 100644\nindex 0000000..61036fc\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/config_app.c\n@@ -0,0 +1,382 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <stdlib.h>\n+#include <stdint.h>\n+#include <dirent.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include <strings.h>\n+#include <unistd.h>\n+#include <stdbool.h>\n+#include <limits.h>\n+#include <linux/vfio.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <sys/mman.h>\n+#include <sys/ioctl.h>\n+#include <fcntl.h>\n+#include <errno.h>\n+\n+#include \"fpga_5gnr_cfg_app.h\"\n+\n+#define SYS_DIR \"/sys/bus/pci/devices\"\n+#define CUR_DIR \".\"\n+#define PREV_DIR \"..\"\n+\n+#define DRIVER_LINK  \"driver\"\n+#define DEVICE_FILE  \"device\"\n+#define VENDOR_FILE  \"vendor\"\n+#define BAR0_FILE    \"resource0\"\n+#define MAX_VFS_FILE \"max_vfs\"\n+\n+#define PCI_STR_SIZE 15\n+#define DEV_STR_SIZE 10\n+#define NULL_PAD     2\n+\n+/* Function Pointer for device specific configuration file */\n+typedef int (*configuration)(void *bar0addr, const char *arg_cfg_filename);\n+\n+typedef struct hw_device {\n+\tconst char *device_name;\n+\tchar *config_file;\n+\tint vendor_id;\n+\tint device_id;\n+\tchar pci_address[PCI_STR_SIZE];\n+\tbool driver_found;\n+\tconfiguration conf;\n+\tchar *num_vfs;\n+\tint config_all;\n+} hw_device;\n+\n+static int\n+enable_vfs(const char *pci_addr, char *num_vfs)\n+{\n+\tchar maxvfspath[PATH_MAX];\n+\tchar fs_num_vfs[4] = {0, 0, 0, 0};\n+\tint maxvfsfd;\n+\n+\tsnprintf(maxvfspath, sizeof(maxvfspath),\n+\t\t\t\"%s/%s/%s\", SYS_DIR, pci_addr, MAX_VFS_FILE);\n+\tmaxvfsfd = open(maxvfspath, O_RDWR | O_SYNC);\n+\n+\tif (maxvfsfd < 0) {\n+\t\tprintf(\"Unable to enable VFs. Was device bound under igb_uio?\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* read current num of VFs */\n+\tread(maxvfsfd, (void *)fs_num_vfs, 3);\n+\tstrtok(fs_num_vfs, \"\\n\");\n+\n+\tif (!strncmp(fs_num_vfs, num_vfs, 3)) {\n+\t\t/* value is same */\n+\t\tclose(maxvfsfd);\n+\t\treturn 0;\n+\t}\n+\n+\t/* update num of VFs */\n+\twrite(maxvfsfd, \"0\", 1);\n+\twrite(maxvfsfd, num_vfs, strlen(num_vfs));\n+\tclose(maxvfsfd);\n+\n+\treturn 0;\n+}\n+\n+static void *\n+get_bar0_mapping(const char *pci_addr, unsigned int bar_size)\n+{\n+\tchar bar0path[PATH_MAX];\n+\tint bar0addrfd;\n+\tvoid *map;\n+\n+\tsnprintf(bar0path, sizeof(bar0path),\n+\t\t\t\"%s/%s/%s\", SYS_DIR, pci_addr, BAR0_FILE);\n+\tbar0addrfd = open(bar0path, O_RDWR | O_SYNC);\n+\tif (bar0addrfd < 0) {\n+\t\tprintf(\"\\nFailed to open BAR %s\\n\", bar0path);\n+\t\texit(1);\n+\t}\n+\tmap = mmap(0, bar_size, PROT_READ | PROT_WRITE, MAP_SHARED,\n+\t\t\tbar0addrfd, 0);\n+\tclose(bar0addrfd);\n+\treturn map;\n+}\n+\n+static unsigned long\n+get_file_val(const char *file_path)\n+{\n+\tchar content[BUFSIZ];\n+\tFILE *f;\n+\n+\tf = fopen(file_path, \"r\");\n+\tif (f == NULL) {\n+\t\tprintf(\"\\nFailed to open %s\\n\", file_path);\n+\t\texit(1);\n+\t}\n+\tif (fgets(content, sizeof(content), f) == NULL) {\n+\t\tfclose(f);\n+\t\treturn false;\n+\t}\n+\tfclose(f);\n+\tconst unsigned long content_val = strtoul(content, NULL, 16);\n+\n+\treturn content_val;\n+}\n+\n+static bool\n+get_device_id(hw_device *device, const char *location)\n+{\n+\tunsigned long vendor_id = -1, device_id = -1;\n+\tstruct dirent *dirent;\n+\tDIR *dir;\n+\tchar pci_path[PATH_MAX];\n+\n+\tsnprintf(pci_path, sizeof(pci_path), \"%s/%s\", SYS_DIR, location);\n+\tdir = opendir(pci_path);\n+\tif (dir == NULL) {\n+\t\tprintf(\"Failed to open %s (%s)\\n\", pci_path, strerror(errno));\n+\t\treturn false;\n+\t}\n+\n+\twhile ((dirent = readdir(dir)) != NULL) {\n+\t\tchar file_path[PATH_MAX];\n+\n+\t\t/* Omit Current Directory & Previous Directory Lookup */\n+\t\tif (strncmp(dirent->d_name, CUR_DIR,\n+\t\t\t\tstrlen(dirent->d_name)) == 0 ||\n+\t\t\t\tstrncmp(dirent->d_name, PREV_DIR,\n+\t\t\t\tstrlen(dirent->d_name)) == 0)\n+\t\t\tcontinue;\n+\n+\t\t/* Set filepath as next PCI folder (xxxx:xx:xx.x) */\n+\t\tsnprintf(file_path, sizeof(file_path), \"%s/%s\",\n+\t\t\t\tpci_path, dirent->d_name);\n+\n+\t\t/* Get Device ID */\n+\t\tif (strncmp(dirent->d_name, DEVICE_FILE,\n+\t\t\t\tstrlen(dirent->d_name)) == 0 &&\n+\t\t\t\tdirent->d_type == DT_REG)\n+\t\t\tdevice_id = get_file_val(file_path);\n+\n+\t\t/* Get Vendor ID */\n+\t\tif (strncmp(dirent->d_name, VENDOR_FILE,\n+\t\t\t\tstrlen(dirent->d_name)) == 0 &&\n+\t\t\t\tdirent->d_type == DT_REG)\n+\t\t\tvendor_id = get_file_val(file_path);\n+\t}\n+\n+\tclosedir(dir);\n+\t/* Check if device is found */\n+\treturn (vendor_id == device->vendor_id &&\n+\t\t\tdevice_id == device->device_id);\n+}\n+\n+static int\n+probe_pci_bus(hw_device *device, char **found_devices)\n+{\n+\tstruct dirent *dirent;\n+\tDIR *dir;\n+\tint num_devices = 0;\n+\n+\t/* Locate PCI Devices */\n+\tdir = opendir(SYS_DIR);\n+\tif (dir == NULL)\n+\t\treturn -1;\n+\n+\t/* Iterate Through Directories */\n+\twhile ((dirent = readdir(dir)) != NULL) {\n+\n+\t\t/* Omit Current Directory and Previous Directory Lookup */\n+\t\tif (strncmp(dirent->d_name, CUR_DIR,\n+\t\t\t\tstrlen(dirent->d_name)) == 0 ||\n+\t\t\t\tstrncmp(dirent->d_name, PREV_DIR,\n+\t\t\t\t\t\tstrlen(dirent->d_name)) == 0)\n+\t\t\tcontinue;\n+\t\t/* Check if current device matches requested device */\n+\t\tif (get_device_id(device, dirent->d_name)) {\n+\t\t\tfound_devices[num_devices] =\n+\t\t\t\t\t(char *) malloc(PCI_STR_SIZE);\n+\t\t\t/* Copy PCI slot of device */\n+\t\t\tstrncpy(found_devices[num_devices], dirent->d_name,\n+\t\t\t\t\tsizeof(device->pci_address) - NULL_PAD);\n+\t\t\tnum_devices++;\n+\t\t}\n+\t}\n+\n+\treturn num_devices;\n+}\n+\n+static int\n+match_device(char *pci_address, char **found_devices, int num_devices)\n+{\n+\tint i;\n+\tfor (i = 0; i < num_devices; i++) {\n+\t\tif (!strncmp(pci_address, found_devices[i],\n+\t\t\t\tsizeof(pci_address) - NULL_PAD))\n+\t\t\treturn 0;\n+\t}\n+\n+\tprintf(\"Given PCI ID is not available\\n\");\n+\treturn -1;\n+}\n+\n+static int\n+select_device(hw_device *device, char **found_devices, int num_devices)\n+{\n+\tint i, selected;\n+\t/* If more than one device found, get user input on which to use */\n+\tif (num_devices >= 2) {\n+\t\tprintf(\"More than one device found. Please select which device you would like to use from the list:\\n\");\n+\n+\t\t/*Print PCI Slots */\n+\t\tfor (i = 0; i < num_devices; i++)\n+\t\t\tprintf(\"[%i]: %s\\n\", i+1, found_devices[i]);\n+\n+\t\tprintf(\"> \");\n+\t\tscanf(\"%d\", &selected);\n+\t\tif (selected >= 1 && selected <= num_devices) {\n+\t\t\tstrncpy(device->pci_address, found_devices[selected-1],\n+\t\t\t\t\tsizeof(device->pci_address) - NULL_PAD);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\tprintf(\"Invalid Option, please try again..\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tstrncpy(device->pci_address, found_devices[0],\n+\t\t\tsizeof(device->pci_address) - NULL_PAD);\n+\treturn 0;\n+}\n+\n+void set_device(hw_device *device)\n+{\n+\tdevice->vendor_id = FPGA_5GNR_FEC_VENDOR_ID;\n+\tdevice->device_id = FPGA_5GNR_FEC_DEVICE_ID;\n+\tdevice->conf = fpga_5gnr_configure;\n+\tif (device->config_file == NULL) {\n+\t\tdevice->config_file = getenv(\"FPGA_5GNR_CONFIG_FILE\");\n+\t\tif (device->config_file == NULL)\n+\t\t\tdevice->config_file = \"fpga_5gnr_config.cfg\";\n+\t}\n+}\n+\n+static void\n+print_helper(const char *prgname)\n+{\n+\tprintf(\"Usage: %s [-h] [-a] [-c CFG_FILE] [-f NUM_VFS] [-p PCI_ID]\\n\\n\"\n+\t\t\t\" -c CFG_FILE \\t specifies configuration file to use\\n\"\n+\t\t\t\" -f NUM_VFS \\t specifies number of Virtual Functions to enable through SRIOV\\n\"\n+\t\t\t\" -p PCI_ID \\t specifies PCI ID of device to configure\\n\"\n+\t\t\t\" -a \\t\\t configures all PCI devices matching the given DEVICE_NAME\\n\"\n+\t\t\t\" -h \\t\\t prints this helper\\n\\n\", prgname);\n+}\n+\n+static int\n+parse_args(int argc, char **argv,\n+\t\tstruct hw_device *device)\n+{\n+\tint opt;\n+\tchar *prgname = argv[0];\n+\tdevice->device_name = FPGA_5GNR_FEC_DEV_NAME;\n+\n+\twhile ((opt = getopt(argc, argv, \"c:f:p:ah\")) != -1) {\n+\t\tswitch (opt) {\n+\t\tcase 'c':\n+\t\t\tdevice->config_file = optarg;\n+\t\t\tbreak;\n+\t\tcase 'f':\n+\t\t\tdevice->num_vfs = optarg;\n+\t\t\tbreak;\n+\t\tcase 'p':\n+\t\t\tstrncpy(device->pci_address, optarg,\n+\t\t\t\t\tsizeof(device->pci_address)\n+\t\t\t\t\t- NULL_PAD);\n+\t\t\tbreak;\n+\t\tcase 'a':\n+\t\t\tdevice->config_all = 1;\n+\t\t\tbreak;\n+\t\tcase 'h':\n+\t\tdefault:\n+\t\t\tprint_helper(prgname);\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+configure_device(hw_device *device)\n+{\n+\t/* Get BAR0 Mapping for device */\n+\tvoid *bar0addr = get_bar0_mapping(device->pci_address,\n+\t\t\tFPGA_5GNR_FEC_BAR_SIZE);\n+\n+\tif (device->num_vfs != 0)\n+\t\tif (enable_vfs(device->pci_address, device->num_vfs) < 0)\n+\t\t\treturn -1;\n+\n+\t/* Call device specific configuration function */\n+\tif (device->conf(bar0addr, device->config_file) == 0) {\n+\n+\t\tif (device->num_vfs != 0)\n+\t\t\tprintf(\"Enabled %s %s VFs\\n\",\n+\t\t\t\t\tdevice->num_vfs, device->device_name);\n+\n+\t\tprintf(\"%s PF [%s] configuration complete!\\n\\n\",\n+\t\t\t\tdevice->device_name, device->pci_address\n+\t\t\t\t- NULL_PAD);\n+\t\treturn 0;\n+\t}\n+\tprintf(\"Configuration error!!\\n\");\n+\treturn -1;\n+}\n+\n+int\n+main(int argc, char *argv[])\n+{\n+\tint i, num_devices;\n+\thw_device device;\n+\tchar *found_devices[DEV_STR_SIZE];\n+\n+\tmemset(&device, 0, sizeof(device));\n+\n+\tif (parse_args(argc, argv, &device) > 0)\n+\t\treturn 0;\n+\n+\t/* Set Device Info */\n+\tset_device(&device);\n+\t/* Check if device is installed */\n+\tnum_devices = probe_pci_bus(&device, found_devices);\n+\tif (num_devices == 0) {\n+\t\tprintf(\"No devices found!!\\n\");\n+\t\treturn -1;\n+\t} else if (num_devices < 0) {\n+\t\treturn num_devices;\n+\t}\n+\n+\tif (device.pci_address[0] != 0) {\n+\t\tif (match_device(device.pci_address, found_devices,\n+\t\t\t\tnum_devices) < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\tif (device.config_all) {\n+\t\tfor (i = 0; i < num_devices; i++) {\n+\t\t\tstrncpy(device.pci_address, found_devices[i],\n+\t\t\t\t\tsizeof(device.pci_address) - NULL_PAD);\n+\t\t\tconfigure_device(&device);\n+\t\t}\n+\t} else {\n+\t\tselect_device(&device, found_devices, num_devices);\n+\t\tconfigure_device(&device);\n+\t}\n+\n+\t/* Free memory for stored PCI slots */\n+\tfor (i = 0; i < num_devices; i++)\n+\t\tfree(found_devices[i]);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.c b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.c\nnew file mode 100644\nindex 0000000..ac01722\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.c\n@@ -0,0 +1,351 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <inttypes.h>\n+#include <errno.h>\n+\n+#include \"fpga_5gnr_cfg_app.h\"\n+\n+extern int\n+fpga_5gnr_parse_conf_file(const char *file_name,\n+\t\tstruct fpga_5gnr_fec_conf *fpga_conf);\n+\n+/* Read 8-bit register of FPGA 5GNR FEC device */\n+static uint8_t\n+fpga_reg_read_8(void *mmio_base, uint32_t offset)\n+{\n+\tvoid *reg_addr = mmio_base + offset;\n+\treturn *((volatile uint8_t *)(reg_addr));\n+}\n+\n+/* Read 16-bit register of FPGA 5GNR FEC device */\n+static uint16_t\n+fpga_reg_read_16(void *mmio_base, uint32_t offset)\n+{\n+\tvoid *reg_addr = mmio_base + offset;\n+\tuint16_t ret = *((volatile uint16_t *)(reg_addr));\n+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n+\treturn __bswap_16(ret);\n+#else\n+\treturn ret;\n+#endif\n+}\n+\n+/* Read 32-bit register of FPGA 5GNR FEC device */\n+static uint32_t\n+fpga_reg_read_32(void *mmio_base, uint32_t offset)\n+{\n+\tvoid *reg_addr = mmio_base + offset;\n+\tuint32_t ret = *((volatile uint32_t *)(reg_addr));\n+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n+\treturn __bswap_32(ret);\n+#else\n+\treturn ret;\n+#endif\n+}\n+\n+static inline void\n+fpga_reg_write_16(void *mmio_base, uint32_t offset,\n+\t\tuint16_t payload) {\n+\tvoid *reg_addr = mmio_base + offset;\n+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n+\tpayload = __bswap_16(payload);\n+#endif\n+\t*((volatile uint16_t *) (reg_addr)) = payload;\n+}\n+\n+static inline void\n+fpga_reg_write_32(void *mmio_base, uint32_t offset,\n+\t\tuint32_t payload)\n+{\n+\tvoid *reg_addr = mmio_base + offset;\n+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n+\tpayload = __bswap_32(payload);\n+#endif\n+\t*((volatile uint32_t *) (reg_addr)) = payload;\n+}\n+\n+static inline void\n+set_default_fpga_conf(struct fpga_5gnr_fec_conf *def_conf)\n+{\n+\t/* Set pf mode to true */\n+\tdef_conf->pf_mode_en = true;\n+\n+\t/* Set ratio between UL and DL to 1:1 (unit of weight is 3 CBs) */\n+\tdef_conf->ul_bandwidth = 3;\n+\tdef_conf->dl_bandwidth = 3;\n+\n+\t/* Set Load Balance Factor to 64 */\n+\tdef_conf->dl_load_balance = 64;\n+\tdef_conf->ul_load_balance = 64;\n+}\n+\n+static int\n+fpga_read_config_file(const char *arg_cfg_filename,\n+\t\tstruct fpga_5gnr_fec_conf *fpga_5gnr_fec_conf)\n+{\n+\tconst char *cfg_filename;\n+\n+\tif (arg_cfg_filename == NULL) {\n+\t\tcfg_filename = getenv(FPGA_5GNR_FEC_CONFIG_FILE_ENV);\n+\t\tif (cfg_filename == NULL) {\n+\t\t\tcfg_filename = FPGA_5GNR_FEC_CONFIG_FILE_NAME;\n+\t\t\tprintf(\"'%s' was not set. %s will be used\\n\",\n+\t\t\t\t\tFPGA_5GNR_FEC_CONFIG_FILE_NAME,\n+\t\t\t\t\tcfg_filename);\n+\t\t} else\n+\t\t\tprintf(\"'%s=%s' config file will be used\\n\",\n+\t\t\t\t\tFPGA_5GNR_FEC_CONFIG_FILE_ENV,\n+\t\t\t\t\tcfg_filename);\n+\t} else\n+\t\tcfg_filename = arg_cfg_filename;\n+\n+\treturn fpga_5gnr_parse_conf_file(cfg_filename, fpga_5gnr_fec_conf);\n+}\n+\n+/* Read Static Register of FPGA 5GNR FEC device */\n+static inline void\n+print_static_reg_debug_info(void *mmio_base)\n+{\n+\tuint8_t i, q_id;\n+\tuint32_t fid;\n+\tuint32_t version_id = fpga_reg_read_32(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_VERSION_ID);\n+\tuint16_t config = fpga_reg_read_16(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_CONFIGURATION);\n+\tuint8_t qmap_done = fpga_reg_read_8(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE);\n+\tuint16_t lb_factor = fpga_reg_read_16(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_LOAD_BALANCE_FACTOR);\n+\tuint16_t ring_desc_len = fpga_reg_read_16(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_RING_DESC_LEN);\n+\tuint16_t flr_time_out = fpga_reg_read_16(mmio_base,\n+\t\t\tFPGA_5GNR_FEC_FLR_TIME_OUT);\n+\n+\tprintf(\"FEC FPGA RTL v%u.%u\\n\",\n+\t\t((uint16_t)(version_id >> 16)), ((uint16_t)version_id));\n+\tprintf(\"UL.DL Weights = %u.%u\\n\",\n+\t\t\t((uint8_t)config), ((uint8_t)(config >> 8)));\n+\tprintf(\"UL.DL Load Balance = %u.%u\\n\",\n+\t\t\t((uint8_t)lb_factor), ((uint8_t)(lb_factor >> 8)));\n+\tprintf(\"Queue-PF/VF Mapping Table = %s\\n\",\n+\t\t\t(qmap_done > 0) ? \"READY\" : \"NOT-READY\");\n+\tprintf(\"Ring Descriptor Size = %u bytes\\n\",\n+\t\t\tring_desc_len*FPGA_RING_DESC_LEN_UNIT_BYTES);\n+\tprintf(\"FLR Timeout = %f usec\\n\",\n+\t\t\t(float)flr_time_out*FPGA_FLR_TIMEOUT_UNIT);\n+\n+\tprintf(\"\\n--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+\\n\");\n+\tprintf(\"        |  PF | VF0 | VF1 | VF2 | VF3 | VF4 | VF5 | VF6 | VF7 |\\n\");\n+\tprintf(\"--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+\\n\");\n+\n+\tfor (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; q_id++) {\n+\n+\t\tprintf(\"%s-Q'%02u |\",\n+\t\t\t(q_id < FPGA_NUM_UL_QUEUES) ? \"UL\" : \"DL\", q_id);\n+\n+\t\tfid = fpga_reg_read_32(mmio_base,\n+\t\t\t\tFPGA_5GNR_FEC_QUEUE_MAP + (q_id << 2));\n+\n+\t\tfor (i = 0; i < 9; ++i) {\n+\n+\t\t\tif (!((fid >> 16) & (0x80)) && i == 0) {\n+\t\t\t\tprintf(\"  X  |\");\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tif (((((fid >> 16) & (0x7f)) + 1) == i) &&\n+\t\t\t\t\t((fid >> 16) & (0x80)))\n+\t\t\t\tprintf(\"  X  |\");\n+\t\t\telse\n+\t\t\t\tprintf(\"     |\");\n+\t\t}\n+\t\tprintf(\"\\n\");\n+\t}\n+\tprintf(\"--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+\\n\\n\");\n+}\n+\n+static int\n+fpga_write_config(void *mapaddr, struct fpga_5gnr_fec_conf *conf)\n+{\n+\n+\tuint32_t payload_32, address;\n+\tuint16_t payload_16;\n+\tuint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;\n+\n+\tuint32_t *bar0addr = mapaddr;\n+\n+\t/*\n+\t * Configure UL:DL ratio.\n+\t * [7:0]: UL weight\n+\t * [15:8]: DL weight\n+\t */\n+\tpayload_16 = (conf->dl_bandwidth << 8) | conf->ul_bandwidth;\n+\taddress = FPGA_5GNR_FEC_CONFIGURATION;\n+\tfpga_reg_write_16(bar0addr, address, payload_16);\n+\n+\t/* Clear all queues registers */\n+\tpayload_32 = FPGA_INVALID_HW_QUEUE_ID;\n+\tfor (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) {\n+\t\taddress = (q_id << 2) + FPGA_5GNR_FEC_QUEUE_MAP;\n+\t\tfpga_reg_write_32(bar0addr, address, payload_32);\n+\t}\n+\n+\t/*\n+\t * If PF mode is enabled allocate all queues for PF only.\n+\t *\n+\t * For VF mode each VF can have different number of UL and DL queues.\n+\t * Total number of queues to configure cannot exceed FPGA\n+\t * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.\n+\t * Queues mapping is done according to configuration:\n+\t *\n+\t * UL queues:\n+\t * |                Q_ID              | VF_ID |\n+\t * |                 0                |   0   |\n+\t * |                ...               |   0   |\n+\t * | conf->vf_dl_queues_number[0] - 1 |   0   |\n+\t * | conf->vf_dl_queues_number[0]     |   1   |\n+\t * |                ...               |   1   |\n+\t * | conf->vf_dl_queues_number[1] - 1 |   1   |\n+\t * |                ...               |  ...  |\n+\t * | conf->vf_dl_queues_number[7] - 1 |   7   |\n+\t *\n+\t * DL queues:\n+\t * |                Q_ID              | VF_ID |\n+\t * |                 32               |   0   |\n+\t * |                ...               |   0   |\n+\t * | conf->vf_ul_queues_number[0] - 1 |   0   |\n+\t * | conf->vf_ul_queues_number[0]     |   1   |\n+\t * |                ...               |   1   |\n+\t * | conf->vf_ul_queues_number[1] - 1 |   1   |\n+\t * |                ...               |  ...  |\n+\t * | conf->vf_ul_queues_number[7] - 1 |   7   |\n+\t *\n+\t * Example of configuration:\n+\t * conf->vf_ul_queues_number[0] = 4;  -> 4 UL queues for VF0\n+\t * conf->vf_dl_queues_number[0] = 4;  -> 4 DL queues for VF0\n+\t * conf->vf_ul_queues_number[1] = 2;  -> 2 UL queues for VF1\n+\t * conf->vf_dl_queues_number[1] = 2;  -> 2 DL queues for VF1\n+\t *\n+\t * UL:\n+\t * | Q_ID | VF_ID |\n+\t * |   0  |   0   |\n+\t * |   1  |   0   |\n+\t * |   2  |   0   |\n+\t * |   3  |   0   |\n+\t * |   4  |   1   |\n+\t * |   5  |   1   |\n+\t *\n+\t * DL:\n+\t * | Q_ID | VF_ID |\n+\t * |  32  |   0   |\n+\t * |  33  |   0   |\n+\t * |  34  |   0   |\n+\t * |  35  |   0   |\n+\t * |  36  |   1   |\n+\t * |  37  |   1   |\n+\t */\n+\tif (conf->pf_mode_en) {\n+\t\tpayload_32 = 0x1;\n+\t\tfor (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) {\n+\t\t\taddress = (q_id << 2) + FPGA_5GNR_FEC_QUEUE_MAP;\n+\t\t\tfpga_reg_write_32(bar0addr, address, payload_32);\n+\t\t}\n+\t} else {\n+\t\t/* Calculate total number of UL and DL queues to configure */\n+\t\ttotal_ul_q_id = total_dl_q_id = 0;\n+\t\tfor (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {\n+\t\t\ttotal_ul_q_id += conf->vf_ul_queues_number[vf_id];\n+\t\t\ttotal_dl_q_id += conf->vf_dl_queues_number[vf_id];\n+\t\t}\n+\t\ttotal_q_id = total_dl_q_id + total_ul_q_id;\n+\t\t/*\n+\t\t * Check if total number of queues to configure does not exceed\n+\t\t * FPGA capabilities (64 queues - 32 UL and 32 DL queues)\n+\t\t */\n+\t\tif ((total_ul_q_id > FPGA_NUM_UL_QUEUES) ||\n+\t\t\t(total_dl_q_id > FPGA_NUM_DL_QUEUES) ||\n+\t\t\t(total_q_id > FPGA_TOTAL_NUM_QUEUES)) {\n+\t\t\tprintf(\n+\t\t\t\t\t\"FPGA Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, FPGA_Q %u\",\n+\t\t\t\t\ttotal_ul_q_id, total_dl_q_id,\n+\t\t\t\t\tFPGA_TOTAL_NUM_QUEUES);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\ttotal_ul_q_id = 0;\n+\t\tfor (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {\n+\t\t\tfor (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];\n+\t\t\t\t\t++q_id, ++total_ul_q_id) {\n+\t\t\t\taddress = (total_ul_q_id << 2) +\n+\t\t\t\t\t\tFPGA_5GNR_FEC_QUEUE_MAP;\n+\t\t\t\tpayload_32 = ((0x80 + vf_id) << 16) | 0x1;\n+\t\t\t\tfpga_reg_write_32(bar0addr, address,\n+\t\t\t\t\t\tpayload_32);\n+\t\t\t}\n+\t\t}\n+\t\ttotal_dl_q_id = 0;\n+\t\tfor (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {\n+\t\t\tfor (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];\n+\t\t\t\t\t++q_id, ++total_dl_q_id) {\n+\t\t\t\taddress = ((total_dl_q_id + FPGA_NUM_UL_QUEUES)\n+\t\t\t\t\t\t<< 2) + FPGA_5GNR_FEC_QUEUE_MAP;\n+\t\t\t\tpayload_32 = ((0x80 + vf_id) << 16) | 0x1;\n+\t\t\t\tfpga_reg_write_32(bar0addr, address,\n+\t\t\t\t\t\tpayload_32);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Setting Load Balance Factor */\n+\tpayload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);\n+\taddress = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;\n+\tfpga_reg_write_16(bar0addr, address, payload_16);\n+\n+\t/* Setting length of ring descriptor entry */\n+\tpayload_16 = FPGA_RING_DESC_ENTRY_LENGTH;\n+\taddress = FPGA_5GNR_FEC_RING_DESC_LEN;\n+\tfpga_reg_write_16(bar0addr, address, payload_16);\n+\n+\t/* Setting FLR timeout value */\n+\tpayload_16 = conf->flr_time_out;\n+\taddress = FPGA_5GNR_FEC_FLR_TIME_OUT;\n+\tfpga_reg_write_16(bar0addr, address, payload_16);\n+\n+\t/* Queue PF/VF mapping table is ready */\n+\tpayload_16 = 0x1;\n+\taddress = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;\n+\tfpga_reg_write_16(bar0addr, address, payload_16);\n+\n+\tprint_static_reg_debug_info(bar0addr);\n+\tprintf(\"Mode of operation = %s-mode\\n\",\n+\t\t\tconf->pf_mode_en ? \"PF\" : \"VF\");\n+\n+\treturn 0;\n+}\n+\n+int\n+fpga_5gnr_configure(void *bar0addr, const char *cfg_filename)\n+{\n+\tstruct fpga_5gnr_fec_conf fpga_conf;\n+\tint ret;\n+\n+\tret = fpga_read_config_file(cfg_filename, &fpga_conf);\n+\tif (ret != 0) {\n+\t\tprintf(\"Error reading config file.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = fpga_write_config(bar0addr, &fpga_conf);\n+\tif (ret != 0) {\n+\t\tprintf(\"Error writing configuration for FPGA.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.h b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.h\nnew file mode 100644\nindex 0000000..f7ab8e1\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_app.h\n@@ -0,0 +1,102 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _FPGA_5GNR_CFG_APP_H_\n+#define _FPGA_5GNR_CFG_APP_H_\n+\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <inttypes.h>\n+#include <errno.h>\n+\n+/**< Number of Virtual Functions FGPA 5GNR FEC supports */\n+#define FPGA_5GNR_FEC_NUM_VFS 8\n+#define FPGA_5GNR_FEC_VENDOR_ID 0x8086\n+#define FPGA_5GNR_FEC_DEVICE_ID 0x0D8F\n+#define FPGA_5GNR_FEC_BAR_SIZE  0x1000\n+#define FPGA_5GNR_FEC_DEV_NAME  \"FPGA_5GNR_FEC\"\n+#define FPGA_5GNR_FEC_CONFIG_FILE_ENV \"FPGA_5GNR_FEC_CONFIG_FILE\"\n+#define FPGA_5GNR_FEC_CONFIG_FILE_NAME \"fpga_5gnr_fec_config.cfg\"\n+\n+/* Multiplier of 256 bits (32 bytes) */\n+#define FPGA_RING_DESC_ENTRY_LENGTH (8)\n+#define FPGA_RING_DESC_LEN_UNIT_BYTES (32)\n+/* Maximum size of queue */\n+#define FPGA_RING_MAX_SIZE (1024)\n+#define FPGA_FLR_TIMEOUT_UNIT (16.384)\n+\n+#define FPGA_NUM_UL_QUEUES (32)\n+#define FPGA_NUM_DL_QUEUES (32)\n+#define FPGA_TOTAL_NUM_QUEUES (FPGA_NUM_UL_QUEUES + FPGA_NUM_DL_QUEUES)\n+\n+#define FPGA_INVALID_HW_QUEUE_ID (0xFFFFFFFF)\n+\n+/* FPGA 5GNR FEC Register mapping on BAR0 */\n+enum {\n+\tFPGA_5GNR_FEC_VERSION_ID = 0x00000000, /* len: 4B */\n+\tFPGA_5GNR_FEC_CONFIGURATION = 0x00000004, /* len: 2B */\n+\tFPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE = 0x00000008, /* len: 1B */\n+\tFPGA_5GNR_FEC_LOAD_BALANCE_FACTOR = 0x0000000a, /* len: 2B */\n+\tFPGA_5GNR_FEC_RING_DESC_LEN = 0x0000000c, /* len: 2B */\n+\tFPGA_5GNR_FEC_FLR_TIME_OUT = 0x0000000e, /* len: 2B */\n+\tFPGA_5GNR_FEC_VFQ_FLUSH_STATUS_LW = 0x00000018, /* len: 4B */\n+\tFPGA_5GNR_FEC_VFQ_FLUSH_STATUS_HI = 0x0000001c, /* len: 4B */\n+\tFPGA_5GNR_FEC_QUEUE_MAP = 0x00000040, /* len: 256B */\n+\tFPGA_5GNR_FEC_RING_CTRL_REGS = 0x00000200, /* len: 2048B */\n+\tFPGA_5GNR_FEC_DDR4_WR_ADDR_REGS = 0x00000A00, /* len: 4B */\n+\tFPGA_5GNR_FEC_DDR4_WR_DATA_REGS = 0x00000A08, /* len: 8B */\n+\tFPGA_5GNR_FEC_DDR4_WR_DONE_REGS = 0x00000A10, /* len: 1B */\n+\tFPGA_5GNR_FEC_DDR4_RD_ADDR_REGS = 0x00000A18, /* len: 4B */\n+\tFPGA_5GNR_FEC_DDR4_RD_DONE_REGS = 0x00000A20, /* len: 1B */\n+\tFPGA_5GNR_FEC_DDR4_RD_RDY_REGS = 0x00000A28, /* len: 1B */\n+\tFPGA_5GNR_FEC_DDR4_RD_DATA_REGS = 0x00000A30, /* len: 8B */\n+\tFPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS = 0x00000A38, /* len: 1B */\n+\tFPGA_5GNR_FEC_HARQ_BUF_SIZE_RDY_REGS = 0x00000A40, /* len: 1B */\n+\tFPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS = 0x00000A48, /* len: 4B */\n+\tFPGA_5GNR_FEC_MUTEX = 0x00000A60, /* len: 4B */\n+\tFPGA_5GNR_FEC_MUTEX_RESET = 0x00000A68  /* len: 4B */\n+};\n+\n+/* FIXME Add HARQ/DDR Registers */\n+\n+/* FPGA 5GNR FEC Ring Control Registers */\n+enum {\n+\tFPGA_5GNR_FEC_RING_HEAD_ADDR = 0x00000008,\n+\tFPGA_5GNR_FEC_RING_SIZE = 0x00000010,\n+\tFPGA_5GNR_FEC_RING_MISC = 0x00000014,\n+\tFPGA_5GNR_FEC_RING_ENABLE = 0x00000015,\n+\tFPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN = 0x00000016,\n+\tFPGA_5GNR_FEC_RING_SHADOW_TAIL = 0x00000018,\n+\tFPGA_5GNR_FEC_RING_HEAD_POINT = 0x0000001C\n+};\n+\n+struct\n+fpga_5gnr_fec_conf {\n+\t/**< 1 if PF is used for dataplane, 0 for VFs */\n+\tbool pf_mode_en;\n+\t/**< Number of UL queues per VF */\n+\tuint8_t vf_ul_queues_number[FPGA_5GNR_FEC_NUM_VFS];\n+\t/**< Number of DL queues per VF */\n+\tuint8_t vf_dl_queues_number[FPGA_5GNR_FEC_NUM_VFS];\n+\t/**< UL bandwidth. Needed for schedule algorithm */\n+\tuint8_t ul_bandwidth;\n+\t/**< DL bandwidth. Needed for schedule algorithm */\n+\tuint8_t dl_bandwidth;\n+\t/**< UL Load Balance */\n+\tuint8_t ul_load_balance;\n+\t/**< DL Load Balance */\n+\tuint8_t dl_load_balance;\n+\t/**< FLR timeout value */\n+\tuint16_t flr_time_out;\n+};\n+\n+/**\n+ * Configure FPGA\n+ */\n+int fpga_5gnr_configure(void *bar0addr, const char *arg_cfg_filename);\n+\n+#endif /* _FPGA_5GNR_CFG_APP_H_ */\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_parser.c b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_parser.c\nnew file mode 100644\nindex 0000000..271b213\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_cfg_parser.c\n@@ -0,0 +1,187 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <inttypes.h>\n+#include <errno.h>\n+\n+#include <ini.h>\n+#include \"fpga_5gnr_cfg_app.h\"\n+\n+/* Names of sections used in the configuration file */\n+#define MODE \"MODE\"\n+#define UL \"UL\"\n+#define DL \"DL\"\n+#define FLR \"FLR\"\n+\n+/* Names of entries in sections used in the configuration file */\n+#define PFMODE \"pf_mode_en\"\n+#define BANDWIDTH \"bandwidth\"\n+#define LOAD_BALANCE \"load_balance\"\n+#define QUEUE_MAP \"vfqmap\"\n+#define FLR_TIME_OUT \"flr_time_out\"\n+\n+/* Default values for FPGA device configuration variables */\n+#define DEFAULT_PF_MODE_EN 1\n+#define DEFAULT_UL_BANDWIDTH 3\n+#define DEFAULT_DL_BANDWIDTH 3\n+#define DEFAULT_UL_LOAD_BALANCE 64\n+#define DEFAULT_DL_LOAD_BALANCE 64\n+#define DEFAULT_NUM_VF_QUEUE 8\n+\n+/* Possible values for MODE and LLR_SIGN */\n+#define ZERO \"0\"\n+#define ONE \"1\"\n+\n+static int\n+parse_number8(const char *str, uint8_t *value)\n+{\n+\tuint64_t val = 0;\n+\tchar *end;\n+\n+\tif (str == NULL)\n+\t\treturn -EINVAL;\n+\n+\tval = strtoul(str, &end, 0);\n+\tif (val > UINT8_MAX || str == end) {\n+\t\tprintf(\"ERROR: Invalid value %\" PRIu64 \"\\n\", val);\n+\t\treturn -ERANGE;\n+\t}\n+\n+\t*value = (uint8_t) val;\n+\treturn 1;\n+}\n+\n+static int\n+parse_number16(const char *str, uint16_t *value)\n+{\n+\tuint64_t val = 0;\n+\tchar *end;\n+\n+\tif (str == NULL)\n+\t\treturn -EINVAL;\n+\n+\tval = strtoul(str, &end, 0);\n+\tif (val > UINT16_MAX || str == end) {\n+\t\tprintf(\"ERROR: Invalid value %\" PRIu64 \"\\n\", val);\n+\t\treturn -ERANGE;\n+\t}\n+\n+\t*value = (uint16_t) val;\n+\treturn 1;\n+}\n+\n+static int\n+parse_array8(const char *str, uint8_t *array)\n+{\n+\tint i;\n+\tuint64_t val = 0;\n+\tchar *end;\n+\n+\tif (str == NULL)\n+\t\treturn -EINVAL;\n+\n+\tchar *val_ch = strtok((char *)str, \",\");\n+\tfor (i = 0; i < 8 && NULL != val_ch; i++) {\n+\n+\t\tval = strtoul(val_ch, &end, 0);\n+\t\tif (val > UINT8_MAX || val_ch == end) {\n+\t\t\tprintf(\"ERROR: Invalid value %\" PRIu64 \"\\n\", val);\n+\t\t\treturn -ERANGE;\n+\t\t}\n+\t\tarray[i] = (uint8_t) val;\n+\n+\t\tval_ch = strtok(NULL, \",\");\n+\t}\n+\treturn 1;\n+}\n+\n+static void\n+set_default_config(struct fpga_5gnr_fec_conf *fpga_conf)\n+{\n+\tint i;\n+\n+\t/* Set pf mode to true */\n+\tfpga_conf->pf_mode_en = DEFAULT_PF_MODE_EN;\n+\n+\t/* Set ratio between UL and DL to 1:1 (unit of weight is 3 CBs) */\n+\tfpga_conf->ul_bandwidth = DEFAULT_UL_BANDWIDTH;\n+\tfpga_conf->dl_bandwidth = DEFAULT_DL_BANDWIDTH;\n+\n+\t/* Set Load Balance Factor to 64 */\n+\tfpga_conf->ul_load_balance = DEFAULT_UL_LOAD_BALANCE;\n+\tfpga_conf->dl_load_balance = DEFAULT_DL_LOAD_BALANCE;\n+\n+\tfor (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; i++) {\n+\t\tfpga_conf->vf_ul_queues_number[i] = DEFAULT_NUM_VF_QUEUE / 2;\n+\t\tfpga_conf->vf_dl_queues_number[i] = DEFAULT_NUM_VF_QUEUE / 2;\n+\t}\n+}\n+\n+static int\n+fpga_handler(void *user, const char *section,\n+\t     const char *name, const char *value)\n+{\n+\tstruct fpga_5gnr_fec_conf *fpga_conf =\n+\t\t\t(struct fpga_5gnr_fec_conf *) user;\n+\tint ret = 1;\n+\n+\tif (!strcmp(section, MODE) && !strcmp(name, PFMODE)) {\n+\t\tif (!strcmp(value, ZERO))\n+\t\t\tfpga_conf->pf_mode_en = false;\n+\t\telse if (!strcmp(value, ONE))\n+\t\t\tfpga_conf->pf_mode_en = true;\n+\t\telse\n+\t\t\tret = 0;\n+\t} else if (!strcmp(section, UL) && !strcmp(name, BANDWIDTH)) {\n+\t\tret = parse_number8(value, &fpga_conf->ul_bandwidth);\n+\t} else if (!strcmp(section, DL) && !strcmp(name, BANDWIDTH)) {\n+\t\tret = parse_number8(value, &fpga_conf->dl_bandwidth);\n+\t} else if (!strcmp(section, UL) && !strcmp(name, LOAD_BALANCE)) {\n+\t\tret = parse_number8(value, &fpga_conf->ul_load_balance);\n+\t} else if (!strcmp(section, DL) && !strcmp(name, LOAD_BALANCE)) {\n+\t\tret = parse_number8(value, &fpga_conf->dl_load_balance);\n+\t} else if (!strcmp(section, UL) && !strcmp(name, QUEUE_MAP)) {\n+\t\tret = parse_array8(value, fpga_conf->vf_ul_queues_number);\n+\t} else if (!strcmp(section, DL) && !strcmp(name, QUEUE_MAP)) {\n+\t\tret = parse_array8(value, fpga_conf->vf_dl_queues_number);\n+\t} else if (!strcmp(section, FLR) && !strcmp(name, FLR_TIME_OUT)) {\n+\t\tret = parse_number16(value, &fpga_conf->flr_time_out);\n+\t} else {\n+\t\tprintf(\"ERROR: Section (%s) or name (%s) is not valid.\\n\",\n+\t\t       section, name);\n+\t\treturn 0;\n+\t}\n+\tif (ret != 1)\n+\t\tprintf(\"Error: Conversion of value (%s) failed.\\n\", value);\n+\n+\treturn ret;\n+}\n+\n+int\n+fpga_5gnr_parse_conf_file(const char *file_name,\n+\t\tstruct fpga_5gnr_fec_conf *fpga_conf)\n+{\n+\tint ret;\n+\n+\tset_default_config(fpga_conf);\n+\n+\tret = ini_parse(file_name, fpga_handler, fpga_conf);\n+\n+\tif (ret == -1) {\n+\t\tprintf(\"ERROR: Error loading configuration file %s\\n\",\n+\t\t\tfile_name);\n+\t\tset_default_config(fpga_conf);\n+\t\treturn -ENOENT;\n+\t} else if (ret == -2) {\n+\t\tprintf(\"ERROR: Memory allocation error\\n\");\n+\t\tset_default_config(fpga_conf);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_config.cfg b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_config.cfg\nnew file mode 100644\nindex 0000000..0854672\n--- /dev/null\n+++ b/drivers/baseband/fpga_5gnr_fec/pf_config_app/fpga_5gnr_config.cfg\n@@ -0,0 +1,18 @@\n+; SPDX-License-Identifier: BSD-3-Clause\n+; Copyright(c) 2020 Intel Corporation\n+\n+[MODE]\n+pf_mode_en = 1\n+\n+[UL]\n+bandwidth = 3\n+load_balance = 128\n+vfqmap = 4,4,4,4,4,4,4,4\n+\n+[DL]\n+bandwidth = 3\n+load_balance = 128\n+vfqmap = 4,4,4,4,4,4,4,4\n+\n+[FLR]\n+flr_time_out = 610\n",
    "prefixes": [
        "v1"
    ]
}